Replication and Deployment
$ kubectl scale --replicas=3 -f helloworld-replica.yml
replicationcontroller "helloworld-controller" scaled
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-controller-2v2x1 1/1 Running 0 13m
helloworld-controller-hgn9s 1/1 Running 0 3m
helloworld-controller-r2vkh 1/1 Running 0 5s
- Each node contain Docker engine (can be also another container engine)
- Each pod contain one or more Docker containers
-
iptables
is like a firewall - The pod is built based on the YAML spec kind
Pod
- Containers are built based on the the
containers
section
Replication Controller
Scaling
- If your application is stateless, you can horizontally scale it
- Stateless = your application doesn't have a state, it doesn't write any local files / keeps local sessions
- All traditional databases (MySQL, Postgres) are stateful, they have database files that can't split over multiple instances
- Most web applications can be made stateless:
- Session management needs to be done outside the container
- Any files that need to be saved can't be save locally on the container
- For more information about best practices, have a look at 12factor.net
- We can use volumes to still run stateful apps
- Those stateful apps can't horizontally scale, but you can run them in a single container and vertically scale (allocate more CPU / memory / disk)
- Scaling in Kubernetes can be done using the Replication Controller
- The replication controller will ensure a specified number of pod replicas will run at all time
- A pod created with the replica controller will automatically be replaced if they fail, get deleted, or are terminated
- Using the replication controller is also recommended if you just want to make sure 1 pod is always running, even after reboots
- You can then run a replication controller with just 1 replica
- This makes sure that the pod is always running
Our First App
To replicate our example app 2 times:
- Set
kind: ReplicationController
- Add
template
apiVersion: v1
kind: ReplicationController
metadata:
name: helloworld-controller
spec:
replicas: 2
selector:
app: helloworld
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: k8s-demo
image: wardviaene/k8s-demo
ports:
- name: nodejs-port
containerPort: 3000
Create pods
$ kubectl create -f helloworld-replica.yml
replicationcontroller "helloworld-controller" created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-controller-2v2x1 1/1 Running 0 9s
helloworld-controller-8bdf3 1/1 Running 0 9s
If one pod is failed, replication controller will automatically restore.
$ kubectl delete pod helloworld-controller-8bdf3
pod "helloworld-controller-8bdf3" deleted
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-controller-2v2x1 1/1 Running 0 10m
helloworld-controller-8bdf3 1/1 Terminating 0 10m
helloworld-controller-hgn9s 0/1 ContainerCreating 0 3s
You can also specify number of replicas.
$ kubectl scale --replicas=3 -f helloworld-replica.yml
replicationcontroller "helloworld-controller" scaled
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-controller-2v2x1 1/1 Running 0 13m
helloworld-controller-hgn9s 1/1 Running 0 3m
helloworld-controller-r2vkh 1/1 Running 0 5s
You can see status of the Replication Controller using kubectl get rc
$ kubectl get rc
NAME DESIRED CURRENT READY AGE
helloworld-controller 3 3 3 14m
Finally, delete the app.
$ kubectl delete rc/helloworld-controller
replicationcontroller "helloworld-controller" delete
Deployments
Replication Set
- Replica Set is the next-generation Replication Controller
- It supports a new selector that can do selection based on filtering according a set of values
- e.g. "environment" either "dev" or "qa"
- not only based on equality, like the Replication Controller
- e.g. "environment" == "dev"
- This Replica Set, rather than the Replication Controller, is used by the Deployment object
Deployment Object
- A deployment declaration in Kubernetes allows you to do app deployments and updates
- When using the deployment object, you define the state of your application
- Kubernetes will then make sure the clusters matches your desired state
- Just using the replication controller or replication set might be cumbersome to deploy apps
- The Deployment Object is easier to use and gives you more possibilities
- With a deployment object, you can:
- Create a deployment (e.g. deploying an app)
- Update a deployment (e.g. deploying a new version)
- Do rolling updates (zero downtime deployments)
- Roll back to a previous version
- Pause / resume a deployment (e.g. to roll-out to only a certain percentage)
Example Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: helloworld-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: k8s-demo
image: wardviaene/k8s-demo
ports:
- name: nodejs-port
containerPort: 3000
Useful Commands
Command | Description |
kubectl get deployments |
Get information on current deployments |
kubectl get rs |
Get information about the replica sets |
kubectl get pods --show-labels |
Get pods, and also show labels attached to those pods |
kubectl rollout status deployment/helloworld-deployment |
Get deployment status |
kubectl set image deployment/helloworld-deployment k8s-demo=k8s-demo:2 |
Run k8s-demo with the image label version 2 |
kubectl rollout status deployment/helloworld-deployment |
Get the status of the rollout |
kubectl rollout history deployment/helloworld-deployment |
Get the rollout history |
kubectl rollout undo deployment/helloworld-deployment |
Rollback to previous version |
kubectl rollout undo deployment/helloworld-deployment --to-revision=n |
Rollback to any version |
Demo
Deploy Version 1
$ kubectl create -f helloworld-deploy.yml
deployment "helloworld-deployment" created
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
helloworld-deployment 3 3 3 3 2m
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
helloworld-deployment-4153696333 3 3 3 2m
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
helloworld-deployment-4153696333-17vqp 1/1 Running 0 3m app=helloworld,pod-template-hash=4153696333
helloworld-deployment-4153696333-ltxvt 1/1 Running 0 3m app=helloworld,pod-template-hash=4153696333
helloworld-deployment-4153696333-zbtn7 1/1 Running 0 3m app=helloworld,pod-template-hash=4153696333
$ kubectl rollout status deployment/helloworld-deployment
deployment "helloworld-deployment" successfully rolled out
Expose and Test Version 1
$ kubectl expose deployment helloworld-deployment --type=NodePort
service "helloworld-deployment" exposed
$ kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld-deployment 10.0.214.139 <nodes> 3000:31616/TCP 37s
kubernetes 10.0.0.1 <none> 443/TCP 9d
$ kubectl describe service helloworld-deployment
Name: helloworld-deployment
Namespace: default
Labels: app=helloworld
Annotations: <none>
Selector: app=helloworld
Type: NodePort
IP: 10.0.214.139
Port: <unset> 3000/TCP
NodePort: <unset> 31616/TCP
Endpoints: 10.244.1.11:3000,10.244.1.12:3000,10.244.1.13:3000
Session Affinity: None
Events: <none>
$ curl http://10.0.214.139:3000
Hello World!
Upgrade to Version 2
$ kubectl set image deployment/helloworld-deployment k8s-demo=wardviaene/k8s-demo:2
deployment "helloworld-deployment" image updated
$ kubectl rollout status deployment/helloworld-deployment
deployment "helloworld-deployment" successfully rolled out
$ curl http://10.0.214.139:3000
Hello World v2!
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-deployment-4153696333-zbtn7 0/1 Terminating 0 15m
helloworld-deployment-521624165-3jftr 1/1 Running 0 36s
helloworld-deployment-521624165-469mg 1/1 Running 0 46s
helloworld-deployment-521624165-pt5f7 1/1 Running 0 46s
$ kubectl rollout history deployment/helloworld-deployment
deployments "helloworld-deployment"
REVISION CHANGE-CAUSE
1 <none>
2 <none>
Rollback to Version 1
$ kubectl rollout undo deployment/helloworld-deployment
deployment "helloworld-deployment" rolled back
$ kubectl rollout status deployment/helloworld-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "helloworld-deployment" successfully rolled out
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-deployment-4153696333-d0jv7 1/1 Running 0 10s
helloworld-deployment-4153696333-w5dhs 1/1 Running 0 15s
helloworld-deployment-4153696333-x62bk 1/1 Running 0 15s
helloworld-deployment-521624165-3jftr 1/1 Terminating 0 1m
helloworld-deployment-521624165-469mg 1/1 Terminating 0 1m
helloworld-deployment-521624165-pt5f7 1/1 Terminating 0 1m
$ kubectl rollout history deployment/helloworld-deployment
deployments "helloworld-deployment"
REVISION CHANGE-CAUSE
2 <none>
3 <none>