Although we have been able to publish our todobackend application, the mechanism that we have used to do this is not suitable for real-world production use, and is only really useful for limited local development scenarios.
One key requirement for running our application in the real-world is the ability to scale up or down the number of instances or replicas of the application container. To achieve this, Kubernetes supports a class of resources referred to as controllers, which are responsible for coordinating, orchestrating, and managing multiple replicas of a given pod. One popular type of controller is the deployment resource, which as the name suggests includes support for creating and updating new versions of your pods along with features such as rolling upgrades and support for rollbacks should a deployment fail.
The following example demonstrates updating the k8s/app/deployment.yaml file in the todobackend repository to define a deployment resource:
apiVersion: apps/v1
kind: Deployment
metadata:
name: todobackend
labels:
app: todobackend
spec:
replicas: 2
selector:
matchLabels:
app: todobackend
template:
metadata:
labels:
app: todobackend
spec:
containers:
- name: todobackend
image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 8000
livenessProbe:
httpGet:
port: 8000
command:
- uwsgi
- --http=0.0.0.0:8000
- --module=todobackend.wsgi
- --master
- --die-on-term
- --processes=4
- --threads=2
- --check-static=/public
env:
- name: DJANGO_SETTINGS_MODULE
value: todobackend.settings_release
We update the previous pod resource to now be a deployment resource, with the template property of the top-level spec property (i.e. spec.template) defining inline the pod that should be deployed. A key concept of deployments and Kubernetes in general is the use of set-based label selector matching (https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) to determine the resources or pods that the deployment applies to. In the preceding example, the deployment resource spec specifies two replicas and uses selectors.matchLabels to match the deployment to a pod that includes the label app with a value of todobackend. This is a simple yet powerful paradigm that allows you to create your own structures and relationships between resources in a flexible and loosely coupled manner. Notice that we also add the readinessProbe and livenessProbe properties to the container definition, which create a readiness probe and liveness probe, respectively. A readiness probe defines an action that should be performed by Kubernetes to determine if a container is ready, while a liveness probe is used to determine if a container is still healthy. In the preceding example, the readiness probe uses HTTP GET requests to port 8000 to determine when the deployment controller should permit connections to be forwarded to the container, while the liveness probe is used to restart the container in the event it no longer responds to the liveness probes. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ for further information on the different types of probes and how they can be used.
To create the new deployment resource, we can first remove the existing pod and then apply the k8s/app/deployment.yaml file in the todobackend repository using kubectl:
> kubectl delete pods/todobackend
pod "todobackend" deleted
> kubectl apply -f k8s/app/deployment.yaml
deployment.apps "todobackend" created
> kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
todobackend 2 2 2 2 12s
> kubectl get pods
NAME READY STATUS RESTARTS AGE
todobackend-7869d9965f-lh944 1/1 Running 0 17s
todobackend-7869d9965f-v986s 1/1 Running 0 17s
After creating the deployment, you can see that the configured number of replicas are deployed in the form of two pods, each with a unique name. The state for each pod will transition to ready as soon as the readiness probe you configured is successful.