Create a new K8s deployment/cluster on MS Azure

First create the cluster in Azure Kubernetes, with the appropriate resource group and name. We will be using the commandline tool az from the Azure Cloudshell.

george [ ~/k8s ]$ az group create --location ukwest --resource-group myaksrg
{
  "id": "/subscriptions/629a8f44-c84d-459e-bc17-64c887c78ced/resourceGroups/myaksrg",
  "location": "ukwest",
  "managedBy": null,
  "name": "myaksrg",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

Create a new cluster with 1 node and ssh key for accessing it.

az aks create \
    --resource-group myaksrg \
    --name myakscluster \
    --node-count 1 \
    --generate-ssh-keys

Run the below from the cloudshell to access the cluster:

az aks get-credentials --resource-group myaksrg --name myakscluster

Run these to apply the deployment and service files:

kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml

You can check the status of your deployment and service plus public IP address using the following commands:

kubectl get deployments
kubectl get services

To list deployments:

george [ ~/k8s ]$ kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           29s

To list services:

george [ ~/k8s ]$ kubectl get services
NAME            TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)        AGE
kubernetes      ClusterIP      10.0.0.1      <none>           443/TCP        6m14s
nginx-service   LoadBalancer   10.0.26.198   20.254.x.y   80:32288/TCP   64s

To connect to the IP address via port 80, use the browser with the EXTERNAL-IP address. You can also use telnet on the same http port.

george@dom:~/Documents/new-cv$ telnet 20.254.x.y 80
Trying 20.254.x.y...
Connected to 20.254.x.y.
Escape character is '^]'.
GET /
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

To list pods and connect to a pod:

kubectl get pods
kubectl exec --stdin --tty <pod-name> -- /bin/bash

Let’s see an example:

george [ ~/k8s ]$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-576c6b7b6-9x2w6   1/1     Running   0          5m43s
nginx-deployment-576c6b7b6-skhjs   1/1     Running   0          5m43s
nginx-deployment-576c6b7b6-xmd8h   1/1     Running   0          5m43s

To connect, use kubectl exec as per below. Exit by pressing Ctrl+D:

george [ ~/k8s ]$ kubectl exec --stdin --tty nginx-deployment-576c6b7b6-9x2w6 -- /bin/bash
root@nginx-deployment-576c6b7b6-9x2w6:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

To return snapshot logs from all containers in pods defined by label app=nginx:

george [ ~/k8s ]$ kubectl logs -l app=nginx
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
[..]
10.224.0.4 - - [10/Jan/2025:16:30:02 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0" "-"
10.224.0.4 - - [10/Jan/2025:16:30:03 +0000] "GET /favicon.ico HTTP/1.1" 404 153 "http://20.254.242.128/" "Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0" "-"
2025/01/10 16:30:03 [error] 30#30: *10 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 10.224.0.4, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "20.254.242.128", referrer: "http://20.254.242.128/"

To delete the resource group and the included kubernetes deployment:

az group delete -n myaksrg

The files used for the kubectl deployment.
/first-cluster/nginx-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx

/first-cluster/nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80