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