We will highlight three main Kubernetes features in this section: placement, reconciliation and application rolling updates.
From the Kubernetes docs here and here.
This section focuses on containers’ placement using Kubernetes, which addresses two main issues a) placing a container relative to other containers, whether required to be on the same node as a collection (i.e. pod) or on different nodes and b) which nodes to run the collection of containers relative to other collections. We will address each issue at a time.
Kubernetes uses the concept of Pods as a logical abstract to collect containers in the same collection, which can then be guaranteed to be deployed to the same node.
Pods
. A pod containing a simple Hello World container can be specified in YAML as follows:https://github.com/lastcoolnameleft/demos/blob/master/k8s-lab/hello-world.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec: # specification of the pod's contents
restartPolicy: Never
containers:
- name: hello
image: "ubuntu:14.04"
command: ["/bin/echo", "hello", "world"]
kubectl create -f https://raw.githubusercontent.com/lastcoolnameleft/demos/master/k8s-lab/hello-world.yaml
The results should look like this
pod "hello-world" created
kubectl get pods --show-all
The results should look like this
NAME READY STATUS RESTARTS AGE
hello-world 0/1 Completed 0 1m
kubectl delete pod hello-world
The results should look like this
pod "hello-world" deleted
https://github.com/lastcoolnameleft/demos/blob/master/k8s-lab/pod-sample.yaml
apiVersion: v1
kind: Pod
metadata:
name: redis-nginx
labels:
app: web
spec:
containers:
- name: key-value-store
image: redis
ports:
- containerPort: 6379
- name: frontend
image: nginx
ports:
- containerPort: 8000
Create the the pod:
kubectl create -f https://raw.githubusercontent.com/lastcoolnameleft/demos/master/k8s-lab/pod-sample.yaml
You can constrain a pod to only be able to run on particular nodes or to prefer to run on particular nodes. There are several ways to do this, and they all use label selectors to make the selection. Generally, such constraints are unnecessary, as the scheduler will automatically do a reasonable placement (e.g. spread your pods across nodes, not place the pod on a node with insufficient free resources, etc.) but there are some circumstances where you may want more control where a pod lands, e.g. to ensure that a pod ends up on a machine with an SSD attached to it, or to co-locate pods from two different services that communicate a lot into the same availability zone.
nodeSelector is the simplest form of constraint. nodeSelector is a field of PodSpec. It specifies a map of key-value pairs. For the pod to be eligible to run on a node, the node must have each of the indicated key-value pairs as labels (it can have additional labels as well).
Get the names of the nodes on your cluster
kubectl get nodes
then add a label to your specific node
kubectl label nodes kubernetes-foo-node-1.c.a disktype=ssd
https://github.com/lastcoolnameleft/demos/blob/master/k8s-lab/pod-sample-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx2
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
Create the pod
kubectl create -f https://raw.githubusercontent.com/lastcoolnameleft/demos/master/k8s-lab/pod-sample-2.yaml
kubectl describe pod/nginx2
From the Kubernetes docs here.
A ReplicaSet ensures that a specified number of pod replicas are running at any given time. However, a Deployment is a higher-level concept that manages ReplicaSets and provides declarative updates to pods along with a lot of other useful features. Therefore, we recommend using Deployments instead of directly using ReplicaSets, unless you require custom update orchestration or don’t require updates at all.
This actually means that you may never need to manipulate ReplicaSet objects: use a Deployment instead, and define your application in the spec section.
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
A Deployment controller provides declarative updates for Pods and ReplicaSets.
You describe a desired state in a Deployment object, and the Deployment controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.
For example, your pods get re-created on a node after disruptive maintenance such as a kernel upgrade. A simple case is to create 1 Replication Set object in order to reliably run one instance of a Pod indefinitely.
https://github.com/lastcoolnameleft/demos/blob/master/k8s-lab/nginx-deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2 # tells deployment to run 2 pods matching the template
template: # create pods using pod definition in this template
metadata:
# unlike pod-nginx.yaml, the name is not included in the meta data as a unique name is
# generated from the deployment name
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kubectl create -f https://raw.githubusercontent.com/lastcoolnameleft/demos/master/k8s-lab/nginx-deployment.yaml
The output should look like this
deployment "nginx-deployment" created
kubectl describe deployment nginx-deployment
The output should look like this
➜ hello-world kubectl describe deployment nginx-deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Fri, 18 Aug 2017 11:30:55 -0500
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=1
Selector: app=nginx
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.7.9
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-4234284026 (2/2 replicas created)
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 deployment-controller Normal ScalingReplicaSet Scaled up replica set nginx-deployment-4234284026 to 2
kubectl scale --replicas=5 deployment/nginx-deployment
From the Kubernetes docs here and here.
To update a service without an outage, kubectl
supports what is called ‘rolling update’, which updates one pod at a time, rather than taking down the entire service at the same time. A rolling update applies changes to the configuration of pods being managed by a replication controller. The changes can be passed as a new replication controller configuration file; or, if only updating the image, a new container image can be specified directly.
This example demonstrates the usage of Kubernetes to perform a rolling update for a new container image on a running group of pods.
https://github.com/lastcoolnameleft/demos/blob/master/k8s-lab/deployment-nginx-update.yaml
cat deployment-nginx-update.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8 # Update the version of nginx from 1.7.9 to 1.8
ports:
- containerPort: 80
kubectl apply -f https://raw.githubusercontent.com/lastcoolnameleft/demos/master/k8s-lab/deployment-nginx-update.yaml
The output should look like this
Created my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
kubectl get pods -l app=nginx
The output should look like this
NAME READY STATUS RESTARTS AGE DEPLOYMENT
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-k156z 1/1 Running 0 1m ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-v95yh 1/1 Running 0 35s ccba8fbd8cc8160970f63f9a2696fc46
kubectl get rs -l app=nginx
The output should look like this
NAME DESIRED CURRENT READY AGE
nginx-deployment-3285060500 2 2 2 4m
nginx-deployment-4234284026 0 0 0 4m
This is one example where the immutability of containers is a huge asset, in rolling new updates and in devops.
For more exercises and info on Kubernetes, the Kubernetes website has a wealth of information and easy to follow on its various features (http://kubernetes.io/docs/).