Introduction to Kubernetes

YAML in Kubernetes

Standard Template:

apiVersion: v1
kind:
metadata:
  name:
  labels:

spec:
  • apiVersion and kind are String
  • metadata is a dictionary
  • kind defines the type of the resource

Creating resource with YAML:

kubectl apply -f resource-definition.yaml

Pod

Pods are the smallest unit in Kubernetes cluster which usually contain and run a single container but there can also be multi-container pods (helper containers).

Running a Container:

➜  notes git:(master) ✗ kubectl run nginx --image nginx
pod/nginx created

Container runtime note

AI-generated

The image reference identifies an OCI-compatible container image. Kubernetes uses a CRI-compatible runtime; it does not require Docker Engine on the node.

Pod operations

Getting Pods:

➜  notes git:(master) ✗ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          7s
  • 1/1 means 1 out of 1 containers is available and ready

Describing Pods:

➜  notes git:(master) ✗ kubectl describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
Node:         docker-desktop/192.168.65.4
Start Time:   Sat, 08 Jan 2022 18:03:26 +0530
Labels:       run=nginx
Annotations:  <none>
Status:       Running
IP:           10.1.0.147
IPs:
  IP:  10.1.0.147
Containers:
  nginx:
    Container ID:   docker://66faa22bb05f77c07b51f1edf45ac207f3e4c3899390ef971223792754a8a059
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sat, 08 Jan 2022 18:03:31 +0530
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-dn6w2 (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-dn6w2:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  27s   default-scheduler  Successfully assigned default/nginx to docker-desktop
  Normal  Pulling    26s   kubelet            Pulling image "nginx"
  Normal  Pulled     22s   kubelet            Successfully pulled image "nginx" in 3.7617608s
  Normal  Created    22s   kubelet            Created container nginx
  Normal  Started    22s   kubelet            Started container nginx

Getting Pods in "wide" format:

➜  notes git:(master) ✗ kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP           NODE             NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          2m48s   10.1.0.147   docker-desktop   <none>           <none>

Creating Pod using YAML:

pod-definition.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
    type: frontend
spec:
  containers:
    - name: nginx-container
      image: nginx
  • containers is an array

Using environment variables in a Container:

...
...
spec:
  containers:
    - name: postgres
      image: postgres
      env:
        - name: POSTGRES_PASSWORD
          value: mysecretpassword
  • There are better ways to store the "sensitive" data like passwords. e.g., Secrets

Creating a Pod Description File from Command line:

kubectl run redis --image=redis123 --dry-run=client -o yaml > pod.yaml

Editing Pod on the Fly:

kubectl edit pod redis
  • This will open a pod-description file as YAML inside VIM in the terminal

ReplicationControllers and ReplicaSets

  • Maintains HA with required number of pods (within a node or cluster)
  • Provides horizontal scaling by maintaining a requested replica count. A Service or another routing layer provides load balancing.

ReplicationController (legacy) Definition

apiVersion: v1
kind: ReplicationController
metadata:
  name: myapp-rc
  labels:
    app: myapp
    type: frontend
spec:
  template:
    <POD-SPEC-WITHOUT-VERSION-AND-METADATA>
  replicas: 3  # number of required replicas
  • 3 Pods will be created (and maintained) with myapp-rc- prefix
  • ReplicationController is a legacy workload controller. Prefer a Deployment, which manages ReplicaSets and supports declarative rollouts and rollback.

ReplicaSet Definition (similar to RC)

apiVersion: apps/v1   # Difference
kind: ReplicaSet
metadata:
  name: myapp-replicaset
  labels:
    app: myapp
    type: frontend
spec:
  template:
    <POD-SPEC-WITHOUT-VERSION-AND-METADATA>
  replicas: 3
  selector:           # Difference
    matchLabels:
      type: frontend
  • 3 Pods will be created (and maintained) with myapp-replicaset- prefix
  • Additional selector.matchLabels to identify which Pods to apply changes to (or scale down to).

Scaling ReplicaSet:

# after update replicas in the definition file
kubectl replace -f replicaset-definition.yaml
kubectl scale --replicas=6 -f replicaset-definition.yaml
kubectl scale --replicas=6 replicaset myapp-replicaset
#                          ^ type     ^ name

__Deleting ReplicaSet:___

kubectl delete replicaset myapp-replicaset
  • Also deletes all underlying pods

Service

AI-generated

A Service gives a changing set of Pods a stable virtual endpoint. Its selector usually identifies the Pods, and the control plane maintains EndpointSlices for the matching backends.

Common Service types:

  • ClusterIP: cluster-internal virtual IP; the default.
  • NodePort: also exposes a port on each node.
  • LoadBalancer: asks a supported cloud or load-balancer integration for an external load balancer, normally building on NodePort or direct pod routing.
  • ExternalName: returns a DNS CNAME and does not proxy traffic.

NodePort

AI-generated

NodePort Service in single Node

NodePort Service on one nodeA request to a node IP and NodePort is routed through a Service to one of the Pods.NodePort Service on one node A request to node IP 192.168.1.2 on NodePort 30008 is routed by a Service to one of three Pods. {"provenance": "AI-generated", "sourceAssets": ["archive/original-images/book/images/nodeport.png"]} NodePort on one node Client Node 192.168.1.2 NodePort 30008 Service :80 192.168.1.2:30008 Pod10.244.0.3 Pod10.244.0.2 Pod10.244.0.4

NodePort Service in multi-node Cluster

NodePort Service across a clusterThe same NodePort is reachable on every node and may select a Pod running on any node.NodePort Service across a cluster The same NodePort 30008 is reachable on every node and routes through one Service to Pods on any node. {"provenance": "AI-generated", "sourceAssets": ["archive/original-images/book/images/nodeport1.png"]} The same NodePort is exposed on every node Client Node 192.168.1.2 NodePort 30008 Pod10.244.0.3 Node 192.168.1.3 NodePort 30008 Pod10.244.0.2 Node 192.168.1.4 NodePort 30008 Pod10.244.0.4 One virtual Service routes across the cluster Client may use :30008 on any node IP; the selected backend Pod may run elsewhere.

ClusterIP

AI-generated

ClusterIP Services between application tiersStable ClusterIP Services connect changing front-end, back-end, and Redis Pods.ClusterIP Services connecting three application tiers Front-end Pods reach back-end Pods through a back-end Service, and back-end Pods reach Redis Pods through a Redis Service. {"provenance": "AI-generated", "sourceAssets": ["archive/original-images/book/images/clusterip.png"]} Stable ClusterIP Services connect changing Pods front-end Pod10.244.0.3 Pod10.244.0.2 Pod10.244.0.4 back-end Pod10.244.0.5 Pod10.244.0.6 Pod10.244.0.7 redis Pod10.244.0.8 Pod10.244.0.9 Pod10.244.0.10 back-end Service (stable ClusterIP) redis Service (stable ClusterIP)

service-definition.yaml

apiVersion: v1
kind: Service
metadata:
  name: backend

spec:
  type: ClusterIP
  ports:
    - targetPort: 80
      port: 80

    selector:
      app: myapp
      type: backend