A Kubernetes Walkthrough

Here are all the notes I need to get me from zero to installation, to deployment, ingress, encryption and monitoring of a service!

Create a Cluster

You can use various k8s implementations: Minikube or Rancher (with k3s) are good starting points, but check out minikube, k8s, k3s, k0s, microk8s, etc. They each have their useful features (like minikube tunnel, minikube ip or traefik), but are generally compatible with each other.

To administer your kubernetes service, you must have an administration tool - kubectl.

Check your k8s is up and running:

$ minikube version
minikube version: v1.18.0
commit: ec61815d60f66a6e4f6353030a40b12362557caa-dirty

$ minikube start
* minikube v1.18.0 on Ubuntu 18.04 (amd64)
* Using the none driver based on existing profile

X The requested memory allocation of 2200MiB does not leave room for system overhead (total system memory: 2460MiB). You may face stability issues.
* Suggestion: Start minikube with less memory allocated: 'minikube start --memory=2200mb'

* Starting control plane node minikube in cluster minikube
* Restarting existing none bare metal machine for "minikube" ...
* OS release is Ubuntu 18.04.5 LTS
* Preparing Kubernetes v1.20.2 on Docker 19.03.13 ...
  - kubelet.resolv-conf=/run/systemd/resolve/resolv.conf
* Configuring local host environment ...
* Verifying Kubernetes components...
  - Using image gcr.io/k8s-minikube/storage-provisioner:v4
* Enabled addons: storage-provisioner, default-storageclass
* Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Check that kubectl is installed:

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.4", GitCommit:"e87da0bd6e03ec3fea7933c4b5263d151aafd07c", GitTreeState:"clean", BuildDate:"2021-02-18T16:12:00Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:20:00Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}

Get info about cluster:

$ kubectl cluster-info
Kubernetes control plane is running at https://10.0.0.6:8443
KubeDNS is running at https://10.0.0.6:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

View node info:

$ kubectl get nodes
NAME       STATUS   ROLES                  AGE   VERSION
minikube   Ready    control-plane,master   77s   v1.20.2

Deploy an App

Create a deployment with a publicly available docker image:

$ kubectl create deployment  kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
deployment.apps/kubernetes-bootcamp created

Show deployments:

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           68s

Create a proxy that will forward requests into the kubernetes private network:

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

You can then make simple requests to this proxy, like this:

$ curl http://localhost:8001/version
{
  "major": "1",
  "minor": "20",
  "gitVersion": "v1.20.2",
  "gitCommit": "faecb196815e248d3ecfb03c680a4507229c2a56",
  "gitTreeState": "clean",
  "buildDate": "2021-01-13T13:20:00Z",
  "goVersion": "go1.15.5",
  "compiler": "gc",
  "platform": "linux/amd64"

In order to pass more sophisticated messages to one of our managed applications, we need its id:

$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-57978f5f5d-c4nng   1/1     Running   0          10m

$ kubectl get pods -o go-template --template '\n'
kubernetes-bootcamp-57978f5f5d-c4nng

$ export POD_NAME=$(kubectl get pods -o go-template --template '\n')

Then we can send messages to this pod:

$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-fb5c67579-c8m9c | v=1

We can also message the proxy api directly:

$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME

This requests shows you the full pod configuration:

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "kubernetes-bootcamp-57978f5f5d-c4nng",
    "generateName": "kubernetes-bootcamp-57978f5f5d-",
    "namespace": "default",
    "uid": "8fe45ce3-0a35-4149-a6be-2117ee7cbf7f",
    "resourceVersion": "997",
    "creationTimestamp": "2022-08-24T12:26:29Z",
    "labels": {
      "app": "kubernetes-bootcamp",
      "pod-template-hash": "57978f5f5d"
    },
    "ownerReferences": [
      {
        "apiVersion": "apps/v1",
        "kind": "ReplicaSet",
        "name": "kubernetes-bootcamp-57978f5f5d",
        "uid": "b6042aad-5fec-4a22-bca5-e6c562aaf6ab",
        "controller": true,
        "blockOwnerDeletion": true
      }
    ],
    "managedFields": [
      {
        "manager": "kube-controller-manager",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2022-08-24T12:26:29Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {"f:metadata":{"f:generateName":{},"f:labels":{".":{},"f:app":{},"f:pod-template-hash":{}},"f:ownerReferences":{".":{},"k:{\"uid\":\"b6042aad-5fec-4a22-bca5-e6c562aaf6ab\"}":{".":{},"f:apiVersion":{},"f:blockOwnerDeletion":{},"f:controller":{},"f:kind":{},"f:name":{},"f:uid":{}}}},"f:spec":{"f:containers":{"k:{\"name\":\"kubernetes-bootcamp\"}":{".":{},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:enableServiceLinks":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}
      },
      {
        "manager": "kubelet",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2022-08-24T12:26:32Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {"f:status":{"f:conditions":{"k:{\"type\":\"ContainersReady\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Initialized\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Ready\"}":{".":{},"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{}}},"f:containerStatuses":{},"f:hostIP":{},"f:phase":{},"f:podIP":{},"f:podIPs":{".":{},"k:{\"ip\":\"172.18.0.6\"}":{".":{},"f:ip":{}}},"f:startTime":{}}}
      }
    ]
  },
  "spec": {
    "volumes": [
      {
        "name": "default-token-9dbv6",
        "secret": {
          "secretName": "default-token-9dbv6",
          "defaultMode": 420
        }
      }
    ],
    "containers": [
      {
        "name": "kubernetes-bootcamp",
        "image": "gcr.io/google-samples/kubernetes-bootcamp:v1",
        "resources": {

        },
        "volumeMounts": [
          {
            "name": "default-token-9dbv6",
            "readOnly": true,
            "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
          }
        ],
        "terminationMessagePath": "/dev/termination-log",
        "terminationMessagePolicy": "File",
        "imagePullPolicy": "IfNotPresent"
      }
    ],
    "restartPolicy": "Always",
    "terminationGracePeriodSeconds": 30,
    "dnsPolicy": "ClusterFirst",
    "serviceAccountName": "default",
    "serviceAccount": "default",
    "nodeName": "minikube",
    "securityContext": {

    },
    "schedulerName": "default-scheduler",
    "tolerations": [
      {
        "key": "node.kubernetes.io/not-ready",
        "operator": "Exists",
        "effect": "NoExecute",
        "tolerationSeconds": 300
      },
      {
        "key": "node.kubernetes.io/unreachable",
        "operator": "Exists",
        "effect": "NoExecute",
        "tolerationSeconds": 300
      }
    ],
    "priority": 0,
    "enableServiceLinks": true,
    "preemptionPolicy": "PreemptLowerPriority"
  },
  "status": {
    "phase": "Running",
    "conditions": [
      {
        "type": "Initialized",
        "status": "True",
        "lastProbeTime": null,
        "lastTransitionTime": "2022-08-24T12:26:29Z"
      },
      {
        "type": "Ready",
        "status": "True",
        "lastProbeTime": null,
        "lastTransitionTime": "2022-08-24T12:26:32Z"
      },
      {
        "type": "ContainersReady",
        "status": "True",
        "lastProbeTime": null,
        "lastTransitionTime": "2022-08-24T12:26:32Z"
      },
      {
        "type": "PodScheduled",
        "status": "True",
        "lastProbeTime": null,
        "lastTransitionTime": "2022-08-24T12:26:29Z"
      }
    ],
    "hostIP": "10.0.0.8",
    "podIP": "172.18.0.6",
    "podIPs": [
      {
        "ip": "172.18.0.6"
      }
    ],
    "startTime": "2022-08-24T12:26:29Z",
    "containerStatuses": [
      {
        "name": "kubernetes-bootcamp",
        "state": {
          "running": {
            "startedAt": "2022-08-24T12:26:31Z"
          }
        },
        "lastState": {

        },
        "ready": true,
        "restartCount": 0,
        "image": "jocatalin/kubernetes-bootcamp:v1",
        "imageID": "docker-pullable://jocatalin/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af",
        "containerID": "docker://f47b1cd0383064d111cc112310e3fb3680a0ec7874817cfbac7473b0a6ecb186",
        "started": true
      }
    ],
    "qosClass": "BestEffort"
  }
}

This is the reference that kubernetes checks to ensure that what is actually running is consistent with the configuration that we want to be running. Any differences are automatically rectified by the kubernetes controller.

You will usually communicate with a pod without creating this proxy, though. Instead, you will create a Service.

App Status

There are a couple of go-to ways to get information about pods, nodes, services, deployments, etc. get and describe work with most objects.

$ kubectl get nodes

$ kubectl get nodes
NAME                   STATUS   ROLES                  AGE   VERSION
lima-rancher-desktop   Ready    control-plane,master   11d   v1.24.4+k3s1

Outputting in wide format lets you see more information about objects.

$ kubectl get nodes -o wide
NAME                   STATUS   ROLES                  AGE   VERSION        INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
lima-rancher-desktop   Ready    control-plane,master   11d   v1.24.4+k3s1   192.168.1.62   <none>        Alpine Linux v3.16   5.15.57-0-virt   containerd://1.6.6

describe gives more detail, and shows recent events that might be useful to know about:

$ kubectl describe nodes
Name:               lima-rancher-desktop
Roles:              control-plane,master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=k3s
                    beta.kubernetes.io/os=linux
                    egress.k3s.io/cluster=true
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=lima-rancher-desktop
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/control-plane=true
                    node-role.kubernetes.io/master=true
                    node.kubernetes.io/instance-type=k3s
Annotations:        alpha.kubernetes.io/provided-node-ip: 192.168.1.62
                    flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"9e:dd:b2:30:cf:33"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 192.168.1.62
                    k3s.io/hostname: lima-rancher-desktop
                    k3s.io/internal-ip: 192.168.1.62
                    k3s.io/node-args:
                      ["server","--https-listen-port","6443","--flannel-iface","rd0","--disable","traefik","--container-runtime-endpoint","/run/k3s/containerd/c...
                    k3s.io/node-config-hash: G4I3ATTKUNLCZ2PTZF77CHL2LW2RZWWPWVR3A32X4RKONERQ6UCA====
                    k3s.io/node-env: {"K3S_DATA_DIR":"/var/lib/rancher/k3s/data/577968fa3d58539cc4265245941b7be688833e6bf5ad7869fa2afe02f15f1cd2"}
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Tue, 23 Aug 2022 18:07:39 +0100
Taints:             <none>
Unschedulable:      false
Lease:
  HolderIdentity:  lima-rancher-desktop
  AcquireTime:     <unset>
  RenewTime:       Sun, 04 Sep 2022 15:43:19 +0100
Conditions:
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  MemoryPressure   False   Sun, 04 Sep 2022 15:42:39 +0100   Fri, 02 Sep 2022 23:40:25 +0100   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Sun, 04 Sep 2022 15:42:39 +0100   Fri, 02 Sep 2022 23:40:25 +0100   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure      False   Sun, 04 Sep 2022 15:42:39 +0100   Fri, 02 Sep 2022 23:40:25 +0100   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready            True    Sun, 04 Sep 2022 15:42:39 +0100   Sat, 03 Sep 2022 20:04:03 +0100   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  192.168.1.62
  Hostname:    lima-rancher-desktop
Capacity:
  cpu:                2
  ephemeral-storage:  102625208Ki
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             6091188Ki
  pods:               110
Allocatable:
  cpu:                2
  ephemeral-storage:  99833802265
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             6091188Ki
  pods:               110
System Info:
  Machine ID:                 a54277578e5fd09a29516dc8b2a2a049
  System UUID:                a54277578e5fd09a29516dc8b2a2a049
  Boot ID:                    8ff701c3-731e-4676-8ffe-8322150e7807
  Kernel Version:             5.15.57-0-virt
  OS Image:                   Alpine Linux v3.16
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.6.6
  Kubelet Version:            v1.24.4+k3s1
  Kube-Proxy Version:         v1.24.4+k3s1
PodCIDR:                      10.42.0.0/24
PodCIDRs:                     10.42.0.0/24
ProviderID:                   k3s://lima-rancher-desktop
Non-terminated Pods:          (8 in total)
  Namespace                   Name                                         CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                         ------------  ----------  ---------------  -------------  ---
  kube-system                 svclb-lb-blog-98ecb8d3-ggnkv                 0 (0%)        0 (0%)      0 (0%)           0 (0%)         6d3h
  default                     blog-f496555c7-m72qc                         0 (0%)        0 (0%)      0 (0%)           0 (0%)         23h
  default                     blog-f496555c7-f7w7l                         0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d5h
  default                     blog-f496555c7-q7wjt                         0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d5h
  default                     ingress-nginx-controller-6bf7bc7f94-m78b8    100m (5%)     0 (0%)      90Mi (1%)        0 (0%)         19h
  kube-system                 metrics-server-668d979685-6fnj7              100m (5%)     0 (0%)      70Mi (1%)        0 (0%)         11d
  kube-system                 coredns-b96499967-5gtw5                      100m (5%)     0 (0%)      70Mi (1%)        170Mi (2%)     11d
  kube-system                 local-path-provisioner-7b7dc8d6f5-kls56      0 (0%)        0 (0%)      0 (0%)           0 (0%)         11d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                300m (15%)  0 (0%)
  memory             230Mi (3%)  170Mi (2%)
  ephemeral-storage  0 (0%)      0 (0%)
  hugepages-1Gi      0 (0%)      0 (0%)
  hugepages-2Mi      0 (0%)      0 (0%)
Events:              <none>

You can use kubectl to examine logs, or inspect the pod environment:

$ kubectl logs $POD_NAME
Kubernetes Bootcamp App Started At: 2022-08-24T12:55:49.787Z | Running On:  kubernetes-bootcamp-fb5c67579-c8m9c

Running On: kubernetes-bootcamp-fb5c67579-c8m9c | Total Requests: 1 | App Uptime: 493.64 seconds | Log Time: 2022-08-24T13:04:03.427Z
Running On: kubernetes-bootcamp-fb5c67579-c8m9c | Total Requests: 2 | App Uptime: 539.727 seconds | Log Time: 2022-08-24T13:04:49.514Z


$ kubectl exec $POD_NAME -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-fb5c67579-c8m9c
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root

…or even open a shell:

$ kubectl exec -ti $POD_NAME -- bash
root@kubernetes-bootcamp-fb5c67579-c8m9c:/#

You can also use top commands to get resource stats:

$ kubectl top node
NAME                   CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
lima-rancher-desktop   791m         39%    1496Mi          25%
$ kubectl top pod
NAME                        CPU(cores)   MEMORY(bytes)
blog-f496555c7-7fn7z        0m           2Mi
blog-f496555c7-fcc8z        0m           7Mi
blog-f496555c7-whnml        0m           2Mi
cm-acme-http-solver-hkpw6   0m           3Mi

Monitoring

Lens

Lens is a nice UI tool for viewing and managing k8s clusters.

$ brew install --cask lens

Prometheus

Prometheus and Grafana are a useful combination for monitoring your cluster. A seperarate note to come on these.. In the meantime, see: Control plane metrics with Prometheus - Amazon EKS

file:///Volumes/protected_data_1/Media/YouTube%20Notes/Professional/DevOps/Kubernetes/Jeff_Geerling/20210210-Kubernetes_101-_Episode_10-_Monitoring_with_Lens_Prometheus_and_Grafana-zW-E8THfvPY.mp4

Creating a Service

A service defines a collection of pods and a policy and IP address by which to access them. A default kubernetes service is instantiated when the cluster is started:

$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   25s

To access this externally, we need the expose command.

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed

$ kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP          3m49s
kubernetes-bootcamp   NodePort    10.100.188.108   <none>        8080:31601/TCP   69s

For creating an external web server, you’d want to use a LoadBalancer type of service. This is usually provided by cloud services, and is not available on minikube. However, k3s comes with traefik (although I actually prefer to make use of ingress-nginx) We can then interrogate the service to view its configuration:

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   app=kubernetes-bootcamp
Annotations:              <none>
Selector:                 app=kubernetes-bootcamp
Type:                     NodePort
IP Families:              <none>
IP:                       10.100.188.108
IPs:                      10.100.188.108
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  31601/TCP
Endpoints:                172.18.0.2:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

To parse the specific node port ID, we can use:

$ kubectl get services/kubernetes-bootcamp -o go-template=''
31601

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=31601

And to access the application via the service:

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-fb5c67579-sfbjd | v=1

Labels

A label will automatically be generated. You can see this with describe deployment

$ kubectl describe deployment
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Wed, 24 Aug 2022 16:39:19 +0000
Labels:                 app=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-fb5c67579 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  10m   deployment-controller  Scaled up replica set kubernetes-bootcamp-fb5c67579 to 1

Here you can see that the deployment label is app=kubernetes-bootcamp You can use this to view the pods and services of the deployment:

$ kubectl get pods -l app=kubernetes-bootcamp
NAME                                  READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-fb5c67579-sfbjd   1/1     Running   0          20m

$ kubectl get services -l app=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.100.188.108   <none>        8080:31601/TCP   18m

We can also add new labels to a pod with:

$ kubectl label pods $POD_NAME version=v1
pod/kubernetes-bootcamp-fb5c67579-sfbjd labeled

Deleting a service

You can use a label to delete a service:

$ kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

The pod and node will continue as before, simply no longer exposed. To shut down the application, you need to also delete the deployment.

Scaling Kubernetes

I’ve split my notes about k8s scaling solutions in two:

Deployments

Rolling Updates

Performing a rolling update is simple: Update the configuration so that a new version of the application image is specified:

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps/kubernetes-bootcamp image updated

Once the deployment application is changed, kubernetes will automatically migrate the deployment to match the specification. By default, only 1 image becomes unavailable at any 1 time.

$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out

If a deployment fails or has a problem, you can rollback to the last known good state:

$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.apps/kubernetes-bootcamp rolled back

Rollback

kubectl rollout history deployment blog
...

kubectl rollout undo deployment blog

For more sophisticated deployment, check out Argo CD (blog post coming soon).

References

Interactive Tutorial - Creating a Cluster | Kubernetes

Tagged: | kubernetes |
Cover Image: Daniil Silantev, via Unsplash