Create Deployments
In the last sections, we mainly worked with Pods, which are the smallest deployable units in Kubernetes. However, in real-world scenarios, you will often want to run multiple instances of your application for high availability and scalability. This is where Deployments come into play.
If you were using Pods directly, you would have to manage the lifecycle of each Pod manually, which can be cumbersome and error-prone. Deployments automate this process and provide a declarative way to manage your application. So let's first create a Deployment for our Learning Tracker application. This can be achieved in a similar way as we created the Pod earlier, but this time we will use the kubectl create deployment command.
kubectl create deployment learning-tracker --image=ghcr.io/tsclabs-eu/learning-tracker:v1.0.5 -n learning-tracker --dry-run=client -o yaml > learning-tracker-deployment.yaml
This command will create a Deployment named learning-tracker in the learning-tracker Namespace using the image ghcr.io/tsclabs-eu/learning-tracker:v1.0.5. The --dry-run=client flag tells kubectl to only simulate the creation of the Deployment and not actually create it, while the -o yaml flag tells it to output the manifest in YAML format. The output is then redirected to a file named learning-tracker-deployment.yaml in your current directory.
Now, let's delete the Pod we created earlier and apply the manifest we just created to create the Deployment. You can do this by running the following commands:
kubectl delete pod learning-tracker -n learning-tracker
kubectl apply -f learning-tracker-deployment.yaml
You can verify that the Deployment was created by running:
kubectl get deployments -n learning-tracker
kubectl get pods -n learning-tracker
You should see the newly created Deployment in the list of Deployments in the learning-tracker Namespace, and the Pod created by the Deployment should be running. The output should look similar to this:
NAME READY UP-TO-DATE AVAILABLE AGE
learning-tracker 1/1 1 1 5s
NAME READY STATUS RESTARTS AGE
learning-tracker-7f5b6c8d4c-abcde 1/1 Running 0 5s
Notice the random suffix in the Pod name. Deployments generate unique Pod names to manage them independently. The Deployment will automatically manage the Pods and ensure that the desired number of replicas is running.
If you already inspected the manifest, you might have noticed that the environment variable LOG_OUTPUT is missing in the Deployment manifest. This is because we didn't add it to the Deployment manifest when we created it. Let's take a look at the learning-tracker-deployment.yaml file and add the environment variable to the container specification.
After adding the environment variable, the whole manifest should look like this:
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: learning-tracker
name: learning-tracker
namespace: learning-tracker
spec:
replicas: 1
selector:
matchLabels:
app: learning-tracker
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: learning-tracker
spec:
containers:
- image: ghcr.io/tsclabs-eu/learning-tracker:v1.0.5
name: learning-tracker
env:
- name: LOG_OUTPUT
value: "console"
resources: {}
status: {}
Some things in this manifest might look very familiar to you, such as the apiVersion, kind, and metadata sections. The spec section contains the specification of the Deployment, including the number of replicas, the selector, and the template for the Pods that will be created by the Deployment. The template section contains the Pod specification, which is similar to the Pod manifest we created earlier.
Now, we can simply apply the manifest again to update the Deployment and add the environment variable:
kubectl apply -f learning-tracker-deployment.yaml
By applying the manifest, Kubernetes will update the Deployment and create new Pods with the updated specification. You can verify that the Pods were updated by running:
kubectl get pods -n learning-tracker
You will see that the Pods are being recreated with the new specification, and the LOG_OUTPUT environment variable is now set to console.
Try to inspect the Deployment and Pods using kubectl describe commands, take a look at the logs and try to port-forward to the workload again. You should see that the application is still running and accessible via port forwarding.
Create a Database Deployment
Now that we have a Deployment for our Learning Tracker application, we will create a Deployment for our MariaDB database. This will allow us to scale our application and use a separate database instead of SQLite.
To create a Deployment for the MariaDB database, we will use the kubectl create deployment command again. This time, we will use the official MariaDB image from Docker Hub. Run the following command in your terminal:
kubectl create deployment mariadb --image=mariadb:12.0 -n learning-tracker --dry-run=client -o yaml > mariadb-deployment.yaml
Furthermore, we will add some environment variables to the Deployment manifest to configure the database. The environment variables will include the database name, user, and password. Open the mariadb-deployment.yaml file in your text editor or IDE and add the following section under the containers section:
[...]
containers:
- name: mariadb
env:
- name: MARIADB_RANDOM_ROOT_PASSWORD
value: "yes"
- name: MARIADB_DATABASE
value: "learning.db"
- name: MARIADB_USER
value: "app"
- name: MARIADB_PASSWORD
value: "my_password"
[...]
The password in the manifest is hardcoded and should not be used in production. In real-world scenarios, there are better ways to manage sensitive information, but for this lab, we will keep it simple.
Now, we can apply the manifest to create the Deployment for the MariaDB database:
kubectl apply -f mariadb-deployment.yaml
You can verify that the Deployment was created by running:
kubectl get deployments -n learning-tracker
kubectl get pods -n learning-tracker
You should see the newly created Deployment in the list of Deployments in the learning-tracker Namespace, and the Pod created by the Deployment should be running.
Now that we have a Deployment for the MariaDB database, we need to connect our Learning Tracker application to the database. In Kubernetes, IP addresses of Pods are very volatile and will change with every restart. Pod names are also not guaranteed to be stable, so we will need a new object to connect our application to the database. This is where Services come into play.
