Showing posts with label Cloud. Show all posts
Showing posts with label Cloud. Show all posts

Sunday, August 31, 2025

Cloud CI-CD Cheat Sheet II

In the previous post, we checked out Cloud CI/CD Cheat Sheet to transition from the 1990s to modern day CI/CD. Now lets integrate GitLab with GitFlow SDLC to demonstrate the Kubernetes CI/CD pipeline benefits.

Let's check it out!

GitLab CI/CD
 •  Create .gitlab-ci.yml at the root of project
 •  this is the driver file that co-ordinates stages:
 •  Build / Lint / Deploy

gitlab-ci.yml


Variables
 •  Generic Variables used in all environments and environment specific variables to build software
 •  Rules that can be used to automate deployments to "lower" environments vs. Manual deployments
 •  YAML that builds the Docker image and push image to container registry of the developer's choice
 •  YAML that has instructions on how to deploy latest built Docker image to Kubernetes cluster

 environments.yml  deployment-rules.yml

Artefacts
 •  YAML files that contain Helm chart artefacts used like Deployment and Service YAML
 •  YAML files that contain Values to be injected including environment specific variables

 deployment.yaml  service.yaml

NOTE: Hardcoded non-sensitive variables stored in Values YAML files including all environment variables:

Whereas sensitive information is stored in Kubernetes secret resources and injected at deployment time.

GitFlow SDLC
Development
 •  GitLab source code repo has main branch for all the Prod deployments
 •  GitLab source code repo has develop branch as the integration branch
 •  develop branch for feature development and deployment to DEV / UAT
 •  GitFlow: ensure develop branch is stable: cut feature branch off develop

Deployment
 •  Submit Pull Request | Merge to develop branch | Trigger build
 •  Auto-deploy to DEV | Manual deploy to UAT [when QA ready]

Testing
 •  Feature completed on DEV / preliminary testing on UAT cut release branch off develop
 •  Deploy release branch to UAT - complete feature testing and regression testing
 •  Any bugs on UAT in release candidate then cut bugfix branch off release branch
 •  Fix bug | Submit Pull Request | Merge to release branch | Re-deploy to UAT [manually]

Release
 •  Once release candidate is stable / all bugs fixed: then submit Pull Request release branch to main
 •  This action will build pipeline but NOT deploy!! Manually deploy to Prod when stakeholders agree!!


Alignment
 •  Finally, after deploy to Prod from main submit PR from main to develop for alignment
 •  Hotfixes available similar to bugfix | Cut hotfix branch from main and submit PR deploy to Prod
 •  After hotfix merged to main and deployed to Prod submit PR from main to develop for alignment


Kubernetes Management: Rancher
Q. What is Rancher?
Open source platform that simplifies the deployment, scaling and management of your Kubernetes clusters:
 •  Kubernetes: open source orchestration platform that automates management of containerized apps
 •  Rancher: open source container platform built on top of Kubernetes to simplify cluster management
 •  Download Kubernetes cluster configuration kubeconfig files from Rancher to connect to your clusters


Kubernetes kubeconfig
 •  kubeconfig file is YAML configuration used to connect to Kubernetes clusters, users and contexts
 •  Download DEV kubeconfig file from Rancher to localhost ~/.kube/dev-config
 •  Download UAT kubeconfig file from Rancher to localhost ~/.kube/uat-config

SETUP
  # Setup the global KUBECONFIG environment variable
  export KUBECONFIG=~/.kube/config:~/.kube/dev-config:~/.kube/uat-config
  # Flatten multiple kubeconfig files into one "master" kubeconfig file
  kubectl config view --flatten > one-config.yaml
  # Rename accordingly
  mv one-config.yaml ~/.kube/config
  # Confirm cluster configuration update
  kubectl config get-contexts


Deployment Verification
Monitor cluster - What is kubectl?
 •  Command line tool run commands against Kubernetes clusters - communicate using Kubernetes API
 •  Post-deployment use kubectl commands to verify the health of cluster ensuring all pods re-spawned


TEST Deployment
Finally, test endpoint(s) via curl or in Postman:
  # Test endpoint
  kubectl port-forward service/flask-api-service 8080:80
  curl http://localhost:8080/api/v1 --header "Content-Type: application/json"
  # RESPONSE
  {"message": "Hello World (Python)!"}


CI/CD Pipeline Benefits
Four Benefits of CI/CD - successful pipeline strategy helps your team deliver higher quality Software faster!
 •  Increased speed of innovation + automation = deployments that are faster and more regular
 •  Code in Production adds immediate value instead of sat waiting in a deployment queue!
 •  Engineers become more productive instead of focus on boring / mundane manual tasks
 •  Higher code quality due to continuous automated build, test, deploy rinse + repeat cycles J

Summary
To summarize, we have now highlighted the back story transitioning from the 1990s to modern day CI/CD and outlined the integration process with GitFlow SDLC to demonstrate Kubernetes CI/CD pipeline benefits!

Thursday, July 31, 2025

Cloud CI-CD Cheat Sheet

In 2024, we checked out GitLab Cheat Sheet to streamline collaborative workflow and then leverage CI/CD pipelines. However, it is interesting to tell the back story how we got from the 1990s to modern day CI/CD.

Let's check it out!

Evolution of SoftwareDeployment: Physical Servers to Container Orchestration

Era of Physical Servers: 1990s and Before
Back in the 1990s Software was predominantly deployed directly onto physical servers, many often housed in on-premises data centers. Each server typically dedicated to specific application [or set of applications].

Challenges: Scalability, Isolation, Resource Utilization
 • involved procuring, setting up, deploying to additional physical servers = time consuming + expensive
 • multiple apps could interfer with one another leading to system crashes or other performance issues
 • some servers underutilized while others overwhelmed which meant inefficient resource distribution

Dawn of Virtualization: 2000s
Introduction of virtualization technologies like those provided by VMware allowed Virtual Machines [VMs] to each run a physical server which meant each VM operating as though it were on own dedicated hardware.

Benefits: Resource Efficiency, Isolation, Snapshot + Cloning
 •  multiple VMs could share resources of single server leading to better resource utilization
 •  VMs provide new level of isolation btwn apps = failure of one VM did not affect other VM
 •  VM state could be saved + cloned making it easier to replicate environments for scaling

Containerization: Rise of Docker
Next significant shift was containerization with Docker at the forefront. Unlike VMs, containers share host OS running in isolated User space which is lightweight and portable and can startup / shutdown more rapidly.

Advantages: Speed, Portability, Density
 •  containers start almost instantly i.e. applications launched and scaled in only a matter of seconds
 •  container images are consistent across environments = it works on my machine issues minimized
 •  lightweight nature = many containers run on host machine = better resource utilization than VMs

Container Orchestration: Enter Kubernetes
Increased container adoption prompted the need for container orchestration technologies like Kubernetes to manage scale and monitor containerized applications especially those hosted by managed Cloud providers.

Functions: Auto-scaling, Self-healing, Load Balancing, Service Discovery
 •  orchestration systems can automatically scale apps based on denamd or sudden traffic spikes
 •  if container or node fails then the orchestrator can restart or replace it = increased reliability!
 •  incoming requests are automatically distributed across containers ensure optimal performance
 •  as containers move across nodes, services can be discovered without any manual intervention

Summary of Definitions
Docker
 •  Platform as a Service product that uses OS-level virtualization Software in packages as containers
 •  Containers are isolated from one another bundle their own software, libraries, and configurations
 •  All containers share signle OS kernel on host thus use fewer resources than Virtual Machines

Kubernetes
 •  Open-source container orchestration system automating app deployment, scaling and management
 •  Runs containerized applications in cluster host machines from containers typically built using Docker

Helm
 •  Kubernetes package manager simplifies managing and deploying applications to clusters via "Charts"
 •  Helm facilitates configuration separated out in Values files and scaled out across all environments

Summary of Technology
Docker
 •  Dockerfile
 •  Image
 •  Container
 text file that contains all commands used to assemble a Docker image template
 executable package that includes code, runtime, environment variables and config
 running instance of a Docker image isolated from other processes running on host

Kubernetes
 •  Namespace
 •  Workload
 •  Pod
 •  Node
 •  Replicaset
 •  Deployment
 •  Service
 scope cluster resources and a way to isolate Kubernetes objects
 containerized application running within the Kubernetes cluster
 smallest deployable unit as created and managed in Kubernetes
 workloads are placed in Containers on Pods to be run on Nodes
 maintains a stable set of replica pods available running any time
 provide a declarative way to update all Pods and Replicasets
 abstract way to expose an application running on a set of Pods

DEMO Hello World
 •  Execute code on localhost [IDE]
 •  Build Docker image and locally
 •  Provision local Kubernetes cluster
 TEST after deployment
 curl http://localhost:8080
 Hello World

Python Flask API application:

DEMO Docker Commands
  # Create KinD cluster
  kind create cluster --name flask-cluster
  # Create Dockerfile | Build Docker image
  docker buiild --pull -rm -f "Dockerfile" -t flask-api:latest "."
  # Execute Docker container
  docker run --rm -d -p 8080:8080/tcp flask-api:latest
  # Test endpoint
  curl http://localhost:8080

Dockerfile
KinD = Kubernetes in Docker is a tool for running local Kubernetes cluster using Docker container "nodes".

DEMO Kubernetes Commands
  # Load image into KinD cluster
  kind load docker-image flask-api:latest --name flask-cluster
  # Setup KinD cluster
  kubectl create ns test-ns
  kubectl config set-context --current --namespace=test-ns
  # Rollout Kubernetes Deployment and Service resources
  kubectl apply -f Kubernetes.yaml
  # Test endpoint
  curl http://localhost:8080

Kubernetes.yaml


LIMITATIONS
DEMO Hello World is sufficient to demonstrate the process on localhost but has many real world limitations!

Limitations
 •  Everything is on localhost - Cloud Computing typically requires Kubernetes cluster(s)
 •  Manually build Docker image from the Dockerfile
 •  Manually push Docker image to container registry
 •  Manually deploy running Docker container into Kubernetes cluster [Deployment exposed as Service]
 •  All Kubernetes resource values are hardcoded into declarative YAML file [Deployment and a Service]
 •  No facility to scale deployment across multiple environments: DEV, IQA, UAT, Prod
 •  Environment variables can be injected but is very brittle and cumbersome process
 •  No real immediate and secure way to inject secret information into deployment [secret password]

Solution
Next step is to integrate GitLab CI/CD pipeline to solve these issues and automate build deployment process!
This will be the topic of the next post.

Monday, June 2, 2025

Cloud Setup Cheat Sheet II

In the previous post, we checked out Cloud Cheat Sheet to explain cluster provisioning process for managed cloud providers such as Azure AKS. Now we will resume to provision clusters: Amazon EKS and Google GKE.
Let's check it out!

Pre-Requisites
This blog post assumes an Azure, AWS, GCP account is setup plus all the corresponding CLIs are configured!

AWS Login
Navigate to https://aws.amazon.com | Sign In | Sign in using root user email. Root user | Root user email address e.g. steven_boland@hotmail.com | Next | Enter password. Setup AWS Multi-Factor Authentication.

AWS Single Sign On
Accessing AWS clusters programmatically is recommened to setup and configure AWS SSO. Example config:
  sso_start_url = https://stevepro.awsapps.com/start
  sso_region = eu-west-1
  sso_account_id = 4xxxxxxxxxx8
  sso_role_name = AdministratorAccess
  region = eu-west-1
  output = json

eksctl
Command-line tool that abstracts complexity involved in setting up AWS EKS clusters. Here is how to install:

Linux
 curl --silent --location "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$(uname
 -s)_amd64.tar.gz" | tar xz -C /tmp
 sudo mv /tmp/eksctl /usr/local/bin

Mac OS/X
 brew tap eksctl-io/eksctl  brew install eksctl

Windows
 Launch Powershell  choco install eksctl


Master Key
Next, create master SSH key for secure, automated and controlled access to your Kubernetes infrastructure:
 cd ~/.ssh
 ssh-keygen -t rsa -b 4096 -N '' -f master_ssh_key
 eval $(ssh-agent -s)
 ssh-add master_ssh_key


Amazon EKS
Amazon provides Elastic Kubernetes Service as a fully managed Kubernetes container orchestration service. Follow all instructions below in order to provision a Kubernetes cluster and test its functionality end-to-end. Download code sample here.

Pre-Requisites
  aws sso login

Check Resources
  aws ec2 describe-instances --query 'Reservations[*].Instances[*].InstanceId' --output table
  aws ec2 describe-addresses --query 'Addresses[*].PublicIp' --output table
  aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output table
  aws ec2 describe-volumes --query 'Volumes[*].VolumeId' --output table
  aws ec2 describe-vpcs --query 'Vpcs[*].VpcId' --output table
  aws cloudformation list-stacks --query 'StackSummaries[*].StackName' --output table
  aws cloudwatch describe-alarms --query 'MetricAlarms[*].AlarmName' --output table
  aws ecr describe-repositories --query 'repositories[*].repositoryName' --output table
  aws ecs list-clusters --query 'clusterArns' --output table
  aws eks list-clusters --query 'clusters' --output table
  aws elasticbeanstalk describe-environments --query 'Environments[*].EnvironmentName' --output table
  aws elb describe-load-balancers --query 'LoadBalancerDescriptions[*].LoadBalancerName' --output table
  aws elbv2 describe-load-balancers --query 'LoadBalancers[*].LoadBalancerName' --output table
  aws iam list-roles --query 'Roles[*].RoleName' --output table
  aws iam list-users --query 'Users[*].UserName' --output table
  aws lambda list-functions --query 'Functions[*].FunctionName' --output table
  aws rds describe-db-instances --query 'DBInstances[*].DBInstanceIdentifier' --output table
  aws route53 list-hosted-zones --query 'HostedZones[*].Name' --output table
  aws s3 ls
  aws sns list-topics --query 'Topics[*].TopicArn' --output table
  aws sqs list-queues --query 'QueueUrls' --output table
  aws ssm describe-parameters --query 'Parameters[*].Name' --output table

Cluster YAML
  kind: ClusterConfig
  apiVersion: eksctl.io/v1alpha5
  
  metadata:
    name: stevepro-aws-eks
    region: eu-west-1
    version: "1.27"
    tags:
      createdBy: stevepro
  
  kubernetesNetworkConfig:
    ipFamily: IPv4
  
  iam:
    withOIDC: true
    serviceAccounts:
    - metadata:
        name: ebs-csi-controller-sa
        namespace: kube-system
      attachPolicyARNs:
      - "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy"
      roleOnly: true
      roleName: stevepro-aws-eks-AmazonEKS_EBS_CSI_DriverRole
  
  addons:
  - name: aws-ebs-csi-driver
    version: v1.38.1-eksbuild.2
    serviceAccountRoleARN: \
  	arn:aws:iam::4xxxxxxxxxx8:role/stevepro-aws-eks-AmazonEKS_EBS_CSI_DriverRole
  - name: vpc-cni
    version: v1.19.2-eksbuild.1
  - name: coredns
    version: v1.10.1-eksbuild.18
  - name: kube-proxy
    version: v1.27.16-eksbuild.14
  
  nodeGroups:
    - name: stevepro-aws-eks
      instanceType: m5.large
      desiredCapacity: 0
      minSize: 0
      maxSize: 3
      ssh:
        allow: true
        publicKeyPath: ~/.ssh/master_ssh_key.pub
      preBootstrapCommands:
        - "true"

Create Cluster
  eksctl create cluster -f ~/stevepro-awseks/cluster.yaml          \
     --kubeconfig ~/stevepro-awseks/kubeconfig                     \
     --verbose 5

Scale Nodegroup
  eksctl scale nodegroup                                           \
     --cluster=stevepro-aws-eks                                    \
     --name=stevepro-aws-eks                                       \
     --nodes=3                                                     \
     --nodes-min=0                                                 \
     --nodes-max=3                                                 \
     --verbose 5

Deploy Test
  kubectl create ns test-ns
  kubectl config set-context --current --namespace=test-ns
  kubectl apply -f Kubernetes.yaml
  kubectl port-forward service/flask-api-service 8080:80
  curl http://localhost:8080

Output
  Hello World (Python)!

Shell into Node
  kubectl get po -o wide
  cd ~/.ssh
  ssh -i master_ssh_key ec2-user@node-ip-address

Cleanup
  kubectl delete -f Kubernetes.yaml
  kubectl delete ns test-ns

Delete Cluster
  eksctl delete cluster                                            \
     --name=stevepro-aws-eks                                       \
     --region eu-west-1                                            \
     --force

ERRORS
Error: getting availability zones for region operation error EC2: DescribeAvailabilityZones, StatusCode: 403
Reference: Dashboard | IAM | Users | SteveProXNA | Permissions | Add Permission | AdministratorAccess:
  {
     "Version": "2012-10-17",
     "Statement": [
         {
             "Effect": "Allow",
             "Action": "*",
             "Resource": "*"
         }
     ]
  }

Error: unable to determine AMI from SSM Parameter Store: operation SSM: GetParameter, StatusCode: 400
AWS Dashboard | IAM | Users | SteveProXNA | Create new group | Permission | AdministratorAccess-Amplify
  {
     "Version": "2012-10-17",
     "Statement": [
         {
             "Effect": "Allow",
             "Action": ],
                 "ssm:GetParameter",
                 "ssm:GetParameters"
             ],
             "Resource": "arn:aws:ssm:*:*:parameter/aws/service/eks/optimized-ami/*"
         },
         {
             "Effect": "Allow",
             "Action": "ec2:DescribeImages",
             "Resource": "*"
         }
     ]
  }


Google GKE
Google provides the Google Kubernetes Engine as fully managed Kubernetes container orchestration service. Follow all instructions below in order to provision a Kubernetes cluster and test its functionality end-to-end.
Download code sample here.

Pre-Requisites
  gcloud auth login
  gcloud auth application-default login
  gcloud auth configure-docker
  gcloud config set project SteveProProject

Check Resources
  gcloud compute instances list
  gcloud compute disks list
  gcloud compute forwarding-rules list
  gcloud compute firewall-rules list
  gcloud compute addresses list
  gcloud container clusters list

Create Cluster
   gcloud container clusters create stevepro-gcp-gke               \
     --project=steveproproject                                     \
     --zone europe-west1-b                                         \
     --machine-type=e2-standard-2                                  \
     --disk-type pd-standard                                       \
     --cluster-version=1.30.10-gke.1070000                         \
     --num-nodes 3                                                 \
     --network=default                                             \
     --create-subnetwork=name=stevepro-gcp-gke-subnet,range=/28    \
     --enable-ip-alias                                             \
     --enable-intra-node-visibility                                \
     --logging=NONE                                                \
     --monitoring=NONE                                             \
     --enable-network-policy                                       \
     --labels=prefix=stevepro-gcp-gke,created-by=${USER}           \
     --no-enable-managed-prometheus                                \
     --quiet --verbosity debug

Get Credentials
  gcloud container clusters get-credentials stevepro-gcp-gke       \
     --zone=europe-west1-b                                         \
     --quiet --verbosity debug

IMPORTANT - if you do not have the following gke gcloud auth plugin then execute the following commands:
  gcloud components install gke-gcloud-auth-plugin
  gke-gcloud-auth-plugin --version

Deploy Test
  kubectl create ns test-ns
  kubectl config set-context --current --namespace=test-ns
  kubectl apply -f Kubernetes.yaml
  kubectl port-forward service/flask-api-service 8080:80
  curl http://localhost:8080

Output
  Hello World (Python)!

Shell into Node
  mkdir -p ~/GitHub/luksa
  cd ~/GitHub/luksa
  git clone https://github.com/luksa/kubectl-plugins.git
  cd kubectl-plugins
  chmod +x kubectl-ssh
  kubectl get nodes
  ./kubectl-ssh node gke-stevepro-gcp-gke-default-pool-0b4ca8ca-sjpj

Cleanup
  kubectl delete -f Kubernetes.yaml
  kubectl delete ns test-ns

Delete Cluster
  gcloud container clusters delete stevepro-gcp-gke                \
     --zone europe-west1-border                                    \
     --quiet --verbosity debug

Summary
To summarize, we have now setup and provisioned Azure AKS, Amazon EKS and Google GKE clusters with end-to-end tests. In future we could explore provisioning AWS and GCP Kubeadm clusters using Terraform!

Monday, May 5, 2025

Cloud Setup Cheat Sheet

In 2024, we checked out GitLab Cheat Sheet to streamline collaborative team workflows that leverage CI/CD pipelines. Now, we will explain cluster provisioning process for managed cloud providers: Azure, AWS + GCP.
Let's check it out!

Pre-Requisites
This blog post assumes an Azure, AWS, GCP account is setup. The following links document paid or free tier:
 Azure [Microsoft]  AZ  PAID Tier Account  FREE Tier Account
 Amazon Web Services  AWS  PAID Tier Account  FREE Tier Account
 Google Cloud Platform  GCP  PAID Tier Account  FREE Tier Account

Azure CLI
The Azure Command Line Interface is a set of commands used to create and manage Azure resources. The CLI is available across services designed to get working with Azure quickly with an emphasis on automation.

Linux
Install the Azure CLI on Linux | Choose an installation method e.g. apt (Ubunuty, Debian) | Launch Terminal
 curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Mac OS/X
Install Azure CLI on Mac OS/X | Install with Homebrew | Install Homebrew manager if you haven't already!
 brew update && brew install azure-cli

Windows
Install Azure CLI on Windows | Microsoft Install (MSI) | Download the Latest MSI of the Azure CLI (64-bit)
 Download and install https://aka.ms/installazurecliwindowsx64

After installing the Azure CLI on Linux, Mac OS/X, Windows confirm the current working version of the CLI:
 az version


AWS CLI
The AWS Command Line Interface is a unified tool used to manage your AWS services. Use the AWS CLI tool to download configure and control AWS services from the command line and automate them through scripts.

Linux
Install the AWS CLI on Linux | Linux tab | Command line installer - Linux x86 (64-bit) | Launch the Terminal
 curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
 unzip awscliv2.zip
 sudo ./aws/install

Mac OS/X
Install the AWS CLI on MacOS/X | macOS tab | GUI installer | Download the macOS pkg file AWSCLIV2.pkg
 Download and install https://awscli.amazonaws.com/AWSCLIV2.pkg

Windows
Install the AWS CLI on Windows | Windows tab | Download MSI | Download Windows (64-bit) AWSCLIV2.msi
 Download and install https://awscli.amazonaws.com/AWSCLIV2.msi

After installing the AWS CLI on Linux, Mac OS/X, Windows confirm the current working version of the CLI:
 aws --version


GCP CLI
The GCP Command Line Interface is used to create and manage Google Cloud resources + services directly from the command line and to perform common platform tasks faster by controlling cloud resources at scale.

Linux
Install the gcloud CLI | Linux tab | Platform Linux 64-bit (x86_64) | Launch Terminal + execute commands:
 curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz
 tar -xf google-cloud-cli-linux-x86_64.tar.gz
 cd google-cloud-sdk  ./install.sh

Mac OS/X
Install the gcloud CLI | macOS tab | Platform macOS macOS 64-bit (ARM64, Apple silicon) | Launch Terminal
 curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-darwin-arm.tar.gz
 tar -xf google-cloud-cli-darwin-arm.tar.gz
 cd google-cloud-sdk  ./install.sh

Windows
Install the gcloud CLI | Windows tab | Download the Google Cloud CLI installer GoogleCloudSDKInstaller.exe
 Download and install https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe

After installing the gcloud CLI on Linux, Mac OS/X, Windows confirm the current working version of the CLI:
 gcloud init  gcloud version


Master Key
Next, create master SSH key for secure, automated and controlled access to your Kubernetes infrastructure:
 cd ~/.ssh
 ssh-keygen -t rsa -b 4096 -N '' -f master_ssh_key
 eval $(ssh-agent -s)
 ssh-add master_ssh_key


Azure AKS
Microsoft provides Azure Kubernetes Services as fully managed Kubernetes container orchestration service. Follow all instructions below in order to provision a Kubernetes cluster and end-to-end test its functionality.
Download code sample here.

Pre-Requisites
  az login

Check Resources
  az account list --output table
  az group list --output table
  az resource list --output table
  az resource list --query "[?location=='northeurope']" --output table
  az vm list --output table
  az aks list --output table
  az container list --output table
  az storage account list --output table
  az network public-ip list --output table

Create Group
  az group create --name stevepro-azraks-rg --location northeurope --debug

Security Principal
  az ad sp create-for-rbac --name ${USER}-sp --skip-assignment

Output
  {
     "appId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
     "displayName": "stevepro-sp",
     "password": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
     "tenant": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  }

Export
  export AZ_SP_ID=<value_from_appId>
  export AZ_SP_PASSWORD=<value_from_password>

Create Cluster
  az aks create --name stevepro-azraks                 \
     --resource-group stevepro-azraks-rg               \
     --dns-name-prefix stevepro-azraks                 \
     --node-count 3                                    \
     --node-vm-size Standard_D2s_v3                    \
     --kubernetes-version 1.31                         \
     --ssh-key-value ~/.ssh/master_ssh_key.pub         \
     --service-principal ${AZ_SP_ID}                   \
     --client-secret ${AZ_SP_PASSWORD}                 \
     --load-balancer-sku standard                      \
     --network-plugin azure --debug

Get Credentials
  export KUBECONFIG=~/.kube/config
  az aks get-credentials --name stevepro-azraks        \
     --resource-group stevepro-azraks-rg --file ~/.kube/config

Deploy Test
  kubectl create ns test-ns
  kubectl config set-context --current --namespace=test-ns
  kubectl apply -f Kubernetes.yaml
  kubectl port-forward service/flask-api-service 8080:80
  curl http://localhost:8080

Output
  Hello World (Python)!

Shell into Node
  mkdir -p ~/GitHub/luksa
  cd ~/GitHub/luksa
  git clone https://github.com/luksa/kubectl-plugins.git
  cd kubectl-plugins
  chmod +x kubectl-ssh
  kubectl get nodes
  ./kubectl-ssh node aks-nodepool1-20972701-vmss000000

Cleanup
  kubectl delete -f Kubernetes.yaml
  kubectl delete ns test-ns

Delete Cluster
  az aks delete --name stevepro-azraks                 \
     --resource-group stevepro-azraks-rg

Delete Group
  az group delete --name stevepro-azraks-rg --yes --no-wait
  az group delete --name NetworkWatcherRG --yes --no-wait

Summary
To summarize, we have setup CLIs for Azure, Amazon and Google and provisioned an Azure AKS Kubernetes cluster with end-to-end testing. Next, we will resume to provision clusters for Amazon EKS and Google GKE. This will be the topic of the next post.

Tuesday, November 15, 2022

Golang Cheat Sheet II

In the previous post, we checked out Go as a statically typed and compiled programming language designed at Google. Go is gaining popularity due to its ability to deliver highly scalable concurrent computing software.

Development teams prefer Golang to harness the power of large servers and sophisticated cloud platorms. Go can be used in mobile, web and simple game development and can also invoke C code directly via Cgo.

Let's check it out!

Example
In the previous post, we created a simple Hello World example by setting up the development environment, create a Go module with the code and issue go build and run commands to execute the Hello World program

Modules
A module in Go is a collection of Go packages stored in a file tree with a go.mod file at its root The go.mod file defines the module's path, which is also the import path used for the root directory, and its dependency requirements which are other modules needed for a successful build.

A module is defined by a UTF-8 encoded text file named go.mod in its root directory. Here are some usages:
 go get  Updates module dependencies in the go.mod file
 go install  Builds and installs the packages named by paths
 go list -m  Lists all the modules instead of all the packages
 go mod download  Downloads named modules into the module cache
 go mod init  Initializes + writes new go.mod file in the current directory
 go mod tidy  Ensures the go.mod file matches source code in the module

Packages
Go programs are built by linking together packages. A package is constructed from one or more source files that declare constants, types, variables and functions belonging to the package to which are accessible in all files of the sams package. Those elements may be exported and used in other package(s).

Functional Programming
Functional programming is the paradigm that treats computation as the evaluation of functions and avoids state and mutable data as opposed to imperative programming which empathizes change of state. Without shared data, concurrency becomes easier because this means no locks, race conditions, no dead locks etc.

Concurrency
Concurrency is the "composition of independently executing computations". Concurrency: dealing with lots of things at once but parallelism: about doing lots of things at once. Concurrency is all about structure whereas parallelism is about execution. Consequently, Golang provides first-class language support for concurrency.

Challenges in concurrent programming include co-ordinating tasks + shared memory. Thus, Go concurrency implementation centers around goroutines: functions that execute simultaneously in Go program with other (goroutine) functions and are lightweight threads managed by the Go runtime. Here are some more terms:

 Concurrency  Ability to have multiple things that can be worked on not necessarily at the same time
 Parallelism  Ability to work on multiple concurrent tasks typically all worked on at the same time
 Process  Part of the Operating System resposible for executing an application
 Thread  Unit within the process which executes the code inside an application
 Goroutines  Special function type that can run while other goroutines are running
 WaitGroups  Allows a supervising goroutine to wait on several other go routines
 Mutexes  Allow us to share memory between go routines and our application
 Channels  Another mechanism available to us to coordinate the work between multiple goroutines

Concurrency in Go is also based on Communicating Sequential Processes. CSP is a form to describe patterns of interaction in concurrent systems. CSP involvement in concurrency based on messaging passing channels. Channels in Go allow goroutines to communincate with each other safely + co-ordinate work between them.

Demos
 Introduction  Goroutine ID
 Goroutines  Sequential code, Creating goroutines
 Sync Package  Using WaitGroups, Mutexes, Read/Write Mutexes
 Channels  Unbuffered channels, Buffered channels, Channel types
 Working with closed channels, Using select statements

IMPORTANT
If you are new to goroutines then you may like to log go ID() similar to logging thread ID in multithreading:
go mod init goidtesting
go get "github.com/nikandfor/goid"
go mod tidy
main.go
package main
import (
	"fmt"
	"os"
	"time"
	"github.com/nikandfor/goid"
)
func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		_, _ = fmt.Fprintln(os.Stdout, goid.ID(), s)
	}
}
func main() {
	go say("world")
	say("hello")
}
Data Race
A data race occurs when two goroutines access the same variable concurrently and are very hard to debug:
 go run -race mysrc.go // to run the source file
 go build -race mycmd // to build the command
 go install -race mypkg // to install the package
 go test -race mypkg // to test the package

Unit Testing
Unit testing in Golang uses the testing package however more sophisticated Test Driven Design TDD / BDD can be accomplished using the Ginkgo testng framework complemented by the Gomega matching library.

However, unit testing concurrent code in Go is more challenging esp. anonymous goroutines as they are not executed immediately. Instead the calling thread keeps execution priority until it pauses. Only then will the code inside the goroutine get execution. Therefore, a solution could be insert an empty function which acts as a hook for testing purposes; push a value into a channel which blocks until received + TEST code passes.

Cloud Computing
Cloud computing systems are highly scalable that require access to resources which must be shared. Thus, Golang has the capability to develop highly scalable, highly performant, reliable and concurrent applications.

Consequently, Go is often preferred to build tools for distributed systems and containerized applications such as Docker and Kubernetes because of Go's fast compilation, low-level system calls and concurrency features.

Cgo
Cgo lets Go packages call C code. Cgo outputs Go and C files that can be combined into a single Go package.

Hello World
 hello.go  hello.h  hello.c
 package main
 import "fmt"

 // #include "hello.h"
 import "C"

 func main() {
 	fmt.Println("begin")
 	C.hello()
 	fmt.Println("-end-")
 }
 #ifndef _HELLO_H_
 #define _HELLO_H_

 #include <stdio.h>

 void hello();

 #endif//_HELLO_H_
 #include "hello.h"

 void hello()
 {
     fprintf(stderr, "%s\n", "Hello Cgo!");
 }
According to this thread, it is possible to debug Go to C from Visual Studio Code on Linux. Assuming you can F5 run the project then set breakpoints either side the Go code calling into and out of the C function to step.


Mod Security
In the previous post, we coded an example in Go from scratch as full end-to-end Web API demo on our local host, in Docker and on Kubernetes. Extend this example as Web Application Firewall using Mod Sec and Cgo.

Install Mod Security on local host
 git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
 cd ModSecurity
 git submodule init
 git submodule update
 ./build.sh
 ./configure
 make
 sudo make install
Follow all instructions from the example i.e. download OWASP rules, build main, server and waf code. Here, it is critical for Go to C interface to set include + linker flags correctly avoiding runtime PATH for shared libs!

waf.go
 package waf
 // #cgo CFLAGS: -I/usr/local/modsecurity/include
 // #cgo LDFLAGS: -L/usr/local/modsecurity/lib/ -Wl,-rpath -Wl,/usr/local/modsecurity/lib/ -lmodsecurity
 // #include "waf.h"
 import "C"

Asm
Finally, if you would like to reproduce Go example that calls ASM assembly code then replicate goid source:
 main.go  goid_amd64.s
 package main
 import (
 	"fmt"
 	"goidtesting/goid"
 	"os"
 	"time"
 )
 func say(s string) {
 	for i := 0; i < 5; i++ {
 		time.Sleep(100 * time.Millisecond)
 		_, _ = fmt.Fprintln(os.Stdout, goid.ID(), s)
 	}
 }
 func main() {
 	go say("world")
 	say("hello")
 }
 #include "textflag.h"

 TEXT ·ID(SB), NOSPLIT, $0-8
 	MOVQ	(TLS), AX     // AX = getg()
 	MOVQ	0x98(AX), AX   // AX = AX.goid
 	MOVQ	AX, ret+0(FP) // ret = AX
 	RET

Summary
To summarize, Go is now popular due to its ability to deliver highly scalable concurrent computing software. Plus, Cgo also allows Go programs to interoperate with C libraries, distributed cloud computing, and eBPF.

Therefore, writing low level C code to target 8-bit Sega Master System hardware and 16-bit Sega Mega Drive has proved to be very valuable experience for Cgo applications which could assist in Go + Cloud Computing!

Thursday, September 15, 2022

Golang Cheat Sheet

Golang is a statically typed and compiled programming language designed at Google. Go plays a major role in Enterprises by developing highly scalable concurrent cloud computing systems like Docker + Kubernetes.

Let's check it out!

Installation
Download and install Go as per instructions for your target operating system. Afterwards verify go version.

Windows
Download and open the Go MSI file. Follow all prompts and ensure Go added to PATH environment variable.

Mac OS/X
Download and open the Go PKG file. Follow all prompts and ensure Go added to PATH environment variable.

Linux
Download and extract the Go archive. Launch Terminal and ensure Go added to PATH environment variable.
 sudo rm -rf /usr/local/go
 sudo tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz
 export PATH=$PATH:/usr/local/go/bin/
 go version
Alternatively, include export PATH="$PATH:/usr/local/go/bin/" to your ~/.bashrc file for future use.

IMPORTANT
If Go does not install or update then you may have to remove snap package using sudo snap remove go. Also, verify Go environment variables by entering go env at the Terminal prompt for all operating systems.

Uninstall
Follow this guide on how to uninstall Go. While there seems to be many options, the following should work:
 sudo apt-get remove golang-go
 sudo apt-get remove --auto-remove golang-go

IDEs
Now we'd like to build Golang software so let's setup 2x main Integrated Development Environments IDEs:

VS Code
Visual Studio Code is a popular lightweight IDE available cross platform on Windows, Mac OS/X and Linux. Install VS Code and install the following plugins: Go, Go Doc, Go Outliner, Go Autotest + Go Test Explorer.
 Go  Rich Go language support for Visual Studio Code
 Go Doc  Show Go's documentation symbols and packages
 Go Outliner  Go code outline explorer and navigation package
 Go Autotest  Adds autotest functionality to vscode's Go mode
 Go Test Explorer  Go Test Explorer for unit and integration testing

Launch VS Code. Press Ctrl + Shift + P. Filter on "Go: Install". Choose "Go: Install/Update Tools". Select all. Ok. Also, if prompted "The "gopls" command is not available." bottom right then click Install to go get gopls.

Miscellaneous
Launch Terminal. Drag tab headings to prefer following order: Terminal, Problems, Output, Debug Console.

Mappings
If you are transitioning from Windows to Linux you may like to update keyboard mappings for example Back to Alt + LeftArrow. File | Preferences | Keyboard Shortcuts. Filter "Go Back". Click pencil. Hit Alt + LeftArrow.

Repeat process for Terminal: Copy Selection: File | Preferences | Keyboard Shortcuts. Hit Ctrl + C and Enter. Repeat process for Terminal: Paste into Active Terminal: File | Preferences | Keyboard Shortcuts. Hit Ctrl + V.

Navigation
If you are transitioning from Visual Studio on Windows to VS Code then the Solution Explorer with folders being represented as folder icons not arrows may be more familiar. Therefore, install vscode-icons plugin. Also, as code bases become larger it can be handier to install the Bookmarks plugin for easier navigation.

Shortcuts
 Ctrl + ,  Open Settings similar to Preferences  F5  Debug | Start w/ Debugging
 Ctrl + P  Search files to open e.g. main.go  Ctrl + F5  Debug | Run w/o Debugger
 Ctrl + R  Select to open from previous files  F9  Debug | Toggle Breakpoint
 Ctrl + Shift + O  Outline file structure for opened file  F10  Debug | Step Over
 F12  Navigate | Go to Definition  F11  Debug | Step Into
 Alt + Left  Navigate | Going Backward  Shift + F11  Debug | Step Out

Zoom In
Finally, you may like to Ctrl + "+" to zoom in on the Explorer and Terminal then reduce the Font Size to 12.


GoLand
GoLand is a cross-platform Go Integrated Development Environment IDE on Windows, Mac OS/X and Linux. Install GoLand and setup the following configurations as commercial alternative with better IDE Intellisense.

Configurations
Launch GoLand. In the "Welcome to GoLand" popup choose Customize | Color theme | IntelliJ Light. Next, choose All settings... Expand Go tab at the top | GOROOT | Add SDK... Local | Navigate to where Go was installed previously e.g. /usr/local/go. Finally update GOPATH. Click "+" select ~/go. OK | Apply | OK.


IMPORTANT
Verify GOROOT path is correct from Terminal via go env | grep GOROOT. Repeat for go env | grep GOPATH. Also, in Go tab | Go Modules ensure "Enable Go modules integration" is checked as may not be by default.


Mappings
Align GoLand Keymap to VS Code Keymap for consistent keyboard shortcuts and developer IDE experience. In the "Welcome to GoLand" popup choose Plugins | VSCode Keymap | Install. Navigate back to Customize. Under Keymap change the default value to VSCode. Now all VS Code shortcuts above will work in GoLand.

Additionally to Ctrl + Shift + O, outline file structure for opened file, GoLand has these handy shortcuts also:
 Ctrl + Numpad -  Collapse struct types for easier overall type visibility in IDE
 Ctrl + Numpad +  Expand struct types to navigate type properties + methods

NOTE
If Ctrl + Shift + O launches Symbols then remove duplicate: Choose Settings | Keymap | filter as "symbol". Double click Navigate | Go to Symbol | Edit | Remove Ctrl+Shift+O | Apply | OK. Repeat this as necessary.

Settings
Finally, from Customize | All settings... here are some more general GoLand IDE settings that can be useful:
 Editor | General | Code Folding | Fold by default | General  UNCHEKED
 Editor | Font  JetBrains Mono | Size: 14.0 | Line: 1.2
 Editor | Color Scheme Font  Scheme: Classic Light
 Editor | Inspections | Proofreading | Typo  UNCHEKED

Example
Create the obligatory Hello World program in both VS Code and GoLand IDE to complete the configration:

main.go
package main
import "fmt"

func main() {
	fmt.Println("Hello World!")
}

VS Code
Create "HelloVSCode" folder at ~/go/src. Launch VS Code. Open folder [Ctrl+K, Ctrl+O] HelloVSCode folder. New File | main.go. Enter + save Hello World source code from package main above. Launch new Terminal:
go mod init HelloVSCode
go mod tidy

go build .
go run .
Set breakpoint in main.go. Run menu and choose either Start Debugging or Run without Debugging option.


GoLand
Launch GoLand. New Project | Enter Location and GOROOT as above i.e. Go 1.18.3 /usr/local/go. Create.

 Location  ~/go/src/HelloGoLand
 GOROOT  Go 1.18.3 /usr/local/go
 Enable vendoring support automatically  CHECKED

In main.go right click triangle next to func main() | Modify Run configuration... Ensure there are no errors. If there are errors then ensure if Run kind is Package the package name matches in go.mod. Otherwise choose File | main.go. Once confirmed no errors then right click triangle and choose the Run or Debug configuration.

Cache
If GoLand complains "cannot resolve symbol" then choose File | Invalidate Caches... | Invalidate and Restart.

Configurations
Track active item in solution explorer similar to Visual Studio: Click cog to right of Project and Always Select Opened File. Hit shift key twice for quick search. Remember Rename files and folder is in the Refactor menu!

Layout
It may be good idea to position Problems tab next to code window so you can see issues as you enter code. In GoLand, click cog on Problems | Move to | Right Top. In VS Code right click Problems | Move Panel Right.

Navigation
As code bases become larger use the Bookmarks feature for easier navigation. Right click the code gutter + Add Bookmark. View menu | Tool Windows | Bookmarks. This can also be used to edit/remove Breakpoints.

Source Control
In GoLand, by default the Staging area may be disabled. Therefore, you wouldn't see any Unversioned files To disable changelists choose File menu | Settings | Version Control | Git | Enable staging area | UNCHECK.

In GoLand, top right under Project is the Control tab. Right click any file and choose Rollback to revert any changes. In VS Code the Source Control tab is third tab. Choose Discard Changes as corresponding action.


Summary
To summarize, we have a simple setup for Golang programming on Windows, Mac OS/X and Linux. There is much to explore e.g. Cloud Computing and developing highly scalable concurrent applications using Golang!
This will be topic of the next post.