3. Getting Started with Kubernetes

  • Container deployment
  • Persistent storage
  • Container health monitoring
  • Compute resource management
  • Auto-scaling
  • High availability by cluster federation

Kubernetes components

  • Masters: The Master is the heart of Kubernetes, which controls and schedules all the activities in the cluster
  • Nodes: Nodes are the workers that run our containers

Pods

kubectl explain pods

KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

   metadata     <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

   spec <Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

   status       <Object>
     Most recently observed status of the pod. This data may not be up to date.
     Populated by the system. Read-only. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

In the following example, we'll show how to create two containers in a pod, and demonstrate how they access each other.

cat << EOF > 3-2-1_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: example
spec:
  containers:
  - name: web
    image: nginx
  - name: centos
    image: centos
    command: ["/bin/sh", "-c", "while : ;do curl http://localhost:80/; sleep 10; done"]
EOF

This spec will create two containers, web and centos

kubectl create -f 3-2-1_pod.yaml
pod "example" created
kubectl get pods
NAME      READY     STATUS              RESTARTS   AGE
example   0/2       ContainerCreating   0          15s

kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
example   2/2       Running   0          46s

Get stdout for centos

kubectl logs example -c centos

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   612  100   612    0     0  95595      0 --:--:-- --:--:-- --:--:--   99k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   612  100   612    0     0   110k      0 --:--:-- --:--:-- --:--:--  119k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Get detailed information for a pod

kubectl describe pods example

Name:         example
Namespace:    default
Node:         k8s-02/159.65.150.75
Start Time:   Thu, 14 Jun 2018 04:49:57 +0000
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           10.244.211.193
Containers:
  web:
    Container ID:   docker://2fa0d040f485395a95badecb71237e02be37986d4b0bbe5c27d96648142a2d05
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Thu, 14 Jun 2018 04:50:17 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-xwdh7 (ro)
  centos:
    Container ID:  docker://5f8ca89ea330f512efe79e0d9e9557195df2037d65b1ff3dc12d856cfbfb7e77
    Image:         centos
    Image ID:      docker-pullable://centos@sha256:b67d21dfe609ddacf404589e04631d90a342921e81c40aeaf3391f6717fa5322
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/sh
      -c
      while : ;do curl http://localhost:80/; sleep 10; done
    State:          Running
      Started:      Thu, 14 Jun 2018 04:50:42 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-xwdh7 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-xwdh7:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-xwdh7
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              2m    default-scheduler  Successfully assigned example to k8s-02
  Normal  SuccessfulMountVolume  2m    kubelet, k8s-02    MountVolume.SetUp succeeded for volume "default-token-xwdh7"
  Normal  Pulling                2m    kubelet, k8s-02    pulling image "nginx"
  Normal  Pulled                 1m    kubelet, k8s-02    Successfully pulled image "nginx"
  Normal  Created                1m    kubelet, k8s-02    Created container
  Normal  Started                1m    kubelet, k8s-02    Started container
  Normal  Pulling                1m    kubelet, k8s-02    pulling image "centos"
  Normal  Pulled                 1m    kubelet, k8s-02    Successfully pulled image "centos"
  Normal  Created                1m    kubelet, k8s-02    Created container
  Normal  Started                1m    kubelet, k8s-02    Started container

ReplicaSet (RS) and ReplicationController (RC)

A pod is not self-healing. When a pod encounters failure, it won't recover on its own. ReplicaSet (RS) and ReplicationController (RC) therefore come into play. Both ReplicaSet and ReplicationController will ensure a specified number of replica pods are always up and running in the cluster. If a pod crashes for any reason, ReplicaSet and ReplicationController will request to spin up a new Pod.

After the latest Kubernetes, ReplicationController is replaced by ReplicaSet gradually. They share the same concept, just using different requirements for the pod selector. ReplicationController uses equality-based selector requirements while ReplicaSet uses set-based selector requirements. ReplicaSet usually is not created by users, but by Kubernetes Deployments objects, while ReplicationController is created by users ourselves.

In this example, we'll create two pods with the labels project, service, and version, as shown below

cat << EOF > 3-2-2_rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    project: chapter3
    service: web
    version: "0.1"
  template:
    metadata:
      name: nginx
      labels:
        project: chapter3
        service: web
        version: "0.1"
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

Get current RC status

kubectl get rc
No resources found.
kubectl create -f 3-2-2_rc.yaml
replicationcontroller "nginx" created
kubectl get rc

NAME      DESIRED   CURRENT   READY     AGE
nginx     2         2         2         14s

Get current running pods

kubectl get pods

NAME          READY     STATUS    RESTARTS   AGE
example       2/2       Running   0          8m
nginx-wfm8b   1/1       Running   0          46s
nginx-zmksz   1/1       Running   0          46s

It shows we have two pods up and running. As described previously, ReplicationController manages all the pods matching the selector. If we create a pod with the same label manually, in theory, it should match the pod selector of the RC we just created. Let's try it out

cat << EOF > 3-2-2_rc_self_created_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: our-nginx
  labels:
    project: chapter3
    service: web
    version: "0.1"
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
EOF

kubectl create -f 3-2-2_rc_self_created_pod.yaml
pod "our-nginx" created

Let's see if it's up and running

kubectl get pods

NAME          READY     STATUS        RESTARTS   AGE
example       2/2       Running       0          11m
nginx-wfm8b   1/1       Running       0          4m
nginx-zmksz   1/1       Running       0          4m
our-nginx     0/1       Terminating   0          2s

It's scheduled, and ReplicationController catches it. The amount of pods becomes three, which exceeds our desired count. The pod is eventually killed

kubectl get pods

NAME          READY     STATUS    RESTARTS   AGE
example       2/2       Running   0          12m
nginx-wfm8b   1/1       Running   0          4m
nginx-zmksz   1/1       Running   0          4m

ReplicationController makes sure pods are in desired state

kubectl edit rc nginx

Here we'll change replica count from 2 to 5

replicationcontroller "nginx" edited

kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
nginx     5         5         5         5m

We have five pods now. Let's check how RC works

Name:         nginx
Namespace:    default
Selector:     project=chapter3,service=web,version=0.1
Labels:       project=chapter3
              service=web
              version=0.1
Annotations:  <none>
Replicas:     5 current / 5 desired
Pods Status:  5 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  project=chapter3
           service=web
           version=0.1
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age              From                    Message
  ----    ------            ----             ----                    -------
  Normal  SuccessfulCreate  6m               replication-controller  Created pod: nginx-wfm8b
  Normal  SuccessfulCreate  6m               replication-controller  Created pod: nginx-zmksz
  Normal  SuccessfulDelete  2m (x2 over 3m)  replication-controller  Deleted pod: our-nginx
  Normal  SuccessfulCreate  45s              replication-controller  Created pod: nginx-t8h87
  Normal  SuccessfulCreate  45s              replication-controller  Created pod: nginx-85s6c
  Normal  SuccessfulCreate  45s              replication-controller  Created pod: nginx-dnzg8

Delete a rc

kubectl delete rc nginx
replicationcontroller "nginx" deleted

kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
example   2/2       Running   0          16m

Following the same steps with the preceding example should work exactly the same between RC and RS. This is just an example; however, we shouldn't create RS on our own, while it should be always managed by Kubernetes deployment object.

Deployments

Deployment is the best primitive to manage and deploy our software in Kubernetes after version 1.2. It supports gracefully deploying, rolling updating, and rolling back pods and ReplicaSets. We define our desired update of the software by deployment declaratively, and then deployment will do it for us progressively.

Using kubectl run to launch the Pods

kubectl run nginx --image=nginx:1.12.0 --replicas=2 --port=80
deployment.apps "nginx" created

kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     2         2         2            0           13s

There are two pods that are deployed by deployment

kubectl get pods

NAME                    READY     STATUS    RESTARTS   AGE
example                 2/2       Running   0          20m
nginx-8cdc99758-hprmf   1/1       Running   0          1m
nginx-8cdc99758-rd6vs   1/1       Running   0          1m

If we delete one of the pods, the replaced pod will be scheduled and launched immediately. That's because deployments creates a ReplicaSet behind the scenes, which will ensure the number of replicas is matched with our desired count.

kubectl get rs
NAME              DESIRED   CURRENT   READY     AGE
nginx-8cdc99758   2         2         2         3m

Expose port 80 to service port 80

kubectl expose deployment nginx --port=80 --target-port=80
service "nginx" exposed

kubectl get services
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP        32m
nginx                 ClusterIP   10.100.137.98   <none>        80/TCP         10s

Deployments can be created by spec as well. The previous deployments and service launched by kubectl can be converted to the following spec

cat << EOF > 3-2-3_deployments.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.12.0
        ports:
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  name: nginx
  labels:
    run: nginx
spec:
  selector:
    run: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      name: http
EOF

kubectl delete deploy nginx
kubectl delete service nginx

kubectl create -f 3-2-3_deployments.yaml
deployment.apps "nginx" created
service "nginx" created

For performing rolling update, we'll have to add rolling update strategy. There are three parameters used to control the process

  • minReadySeconds: Warm-up time. How long a newly created pod is considered to be available. By default, Kubernetes assumes the application will be available once it is successfully launched. (Default: 0)
  • maxSurge: How many pods can be surged when doing rolling update process. (Default: 25%)
  • maxUnavailable: How many pods can be unavailable when doing rolling update process. (Default: 25%)
cat << EOF > 3-2-3_deployments_rollingupdate.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.12.0
        ports:
        - containerPort: 80
  minReadySeconds: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
---
kind: Service
apiVersion: v1
metadata:
  name: nginx
  labels:
    run: nginx
spec:
  selector:
    run: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      name: http
EOF

It indicates that we allow one of the pods to be unavailable at a time and one more pod could be launched when rolling the pods. The warm-up time before proceeding to the next operation will be three seconds.

kubectl create -f 3-2-3_deployments_rollingupdate.yaml
deployment.apps "nginx" created
service "nginx" created

kubectl get rs
NAME              DESIRED   CURRENT   READY     AGE
nginx-8cdc99758   2         2         2         21s

kubectl describe rs nginx-8cdc99758
Name:           nginx-8cdc99758
Namespace:      default
Selector:       pod-template-hash=478755314,run=nginx
Labels:         pod-template-hash=478755314
                run=nginx
Annotations:    deployment.kubernetes.io/desired-replicas=2
                deployment.kubernetes.io/max-replicas=3
                deployment.kubernetes.io/revision=1
Controlled By:  Deployment/nginx
Replicas:       2 current / 2 desired
Pods Status:    2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  pod-template-hash=478755314
           run=nginx
  Containers:
   nginx:
    Image:        nginx:1.12.0
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From                   Message
  ----    ------            ----  ----                   -------
  Normal  SuccessfulCreate  37s   replicaset-controller  Created pod: nginx-8cdc99758-tcf66
  Normal  SuccessfulCreate  37s   replicaset-controller  Created pod: nginx-8cdc99758-wbxcg

results matching ""

    No results matching ""