Primitives for Robust Deployments
Introduction
This tutorial will guide you through the fundamental Kubernetes primitives that are crucial for deploying and managing robust, self-healing applications. We’ll cover Pods, ReplicaSets, Deployments, and Services, demonstrating how they work together to ensure your application’s availability and scalability.
Prerequisites:
- A working Kubernetes cluster (e.g., Minikube, Kind, or a cloud provider cluster)
kubectlinstalled and configured to connect to your cluster- Basic understanding of containerization concepts (e.g., Docker)
Task 1: Understanding Pods
Pods are the smallest deployable units in Kubernetes. They represent a single instance of a running process in your cluster. A pod can contain one or more containers that share network and storage resources.
-
Create a Pod definition file named
pod-definition.yaml:NODE_TYPE // yamlapiVersion: v1 kind: Pod metadata: name: my-first-pod labels: app: my-app spec: containers: - name: my-container image: nginx:latest ports: - containerPort: 80This YAML file defines a Pod namedmy-first-podrunning a single container based on thenginx:latestimage. The container exposes port 80. -
Deploy the Pod using
kubectl:NODE_TYPE // bashkubectl apply -f pod-definition.yamlNODE_TYPE // outputpod/my-first-pod created -
Verify the Pod is running:
NODE_TYPE // bashkubectl get podsNODE_TYPE // outputNAME READY STATUS RESTARTS AGE my-first-pod 1/1 Running 0 10s -
Access the nginx default page:
First, expose the pod using
kubectl port-forward:NODE_TYPE // bashkubectl port-forward pod/my-first-pod 8080:80Then, open a web browser and navigate to
http://localhost:8080. You should see the default nginx welcome page.kubectl port-forwardshould only be used for local debugging or quick access. For production deployments, use Services (explained later). Interrupt thekubectl port-forwardby pressingCtrl+Cafter verifying the nginx page.
Task 2: Introducing ReplicaSets
ReplicaSets ensure that a specified number of Pod replicas are running at any given time. If a Pod fails, the ReplicaSet automatically creates a new one to maintain the desired replica count.
-
Create a ReplicaSet definition file named
replicaset-definition.yaml:NODE_TYPE // yamlapiVersion: apps/v1 kind: ReplicaSet metadata: name: my-replicaset spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: nginx:latest ports: - containerPort: 80This YAML defines a ReplicaSet namedmy-replicasetthat manages 3 replicas of a Pod with the labelapp: my-app. Theselectorfield ensures that the ReplicaSet only manages Pods with this label. -
Deploy the ReplicaSet:
NODE_TYPE // bashkubectl apply -f replicaset-definition.yamlNODE_TYPE // outputreplicaset.apps/my-replicaset created -
Verify the ReplicaSet and its Pods:
NODE_TYPE // bashkubectl get replicasets kubectl get pods -l app=my-appNODE_TYPE // outputNAME DESIRED CURRENT READY AGE my-replicaset 3 3 3 20s NAME READY STATUS RESTARTS AGE my-replicaset-4lm9n 1/1 Running 0 20s my-replicaset-klbrx 1/1 Running 0 20s my-replicaset-q7n2z 1/1 Running 0 20sYou should see that the ReplicaSet has created and is managing three Pods.
-
Simulate a Pod failure:
NODE_TYPE // bashkubectl delete pod my-replicaset-4lm9nNODE_TYPE // outputpod "my-replicaset-4lm9n" deleted -
Observe the ReplicaSet recreate the Pod:
NODE_TYPE // bashkubectl get pods -l app=my-app --watchNODE_TYPE // outputNAME READY STATUS RESTARTS AGE my-replicaset-klbrx 1/1 Running 0 5m30s my-replicaset-q7n2z 1/1 Running 0 5m30s my-replicaset-zxb5w 1/1 Running 0 4sThe
--watchflag allows you to see the changes in real-time. You’ll notice that the deleted Pod is replaced by a new one, demonstrating the self-healing capability of ReplicaSets. PressCtrl+Cto stop watching.
Task 3: Introducing Deployments
Deployments provide declarative updates for Pods and ReplicaSets. They manage the rollout and rollback of changes to your application, ensuring minimal downtime and easy version management. Deployments use ReplicaSets under the hood to manage the underlying Pods.
-
Create a Deployment definition file named
deployment-definition.yaml:NODE_TYPE // yamlapiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: nginx:1.23 # Specify the nginx version ports: - containerPort: 80This YAML defines a Deployment namedmy-deploymentthat manages 3 replicas of a Pod with the labelapp: my-app. Theimageis set tonginx:1.23. -
Deploy the Deployment:
NODE_TYPE // bashkubectl apply -f deployment-definition.yamlNODE_TYPE // outputdeployment.apps/my-deployment created -
Verify the Deployment and its Pods:
NODE_TYPE // bashkubectl get deployments kubectl get pods -l app=my-appNODE_TYPE // outputNAME READY UP-TO-DATE AVAILABLE AGE my-deployment 3/3 3 3 25s NAME READY STATUS RESTARTS AGE my-deployment-7d66f98b76-6686z 1/1 Running 0 25s my-deployment-7d66f98b76-8f8mv 1/1 Running 0 25s my-deployment-7d66f98b76-97r5l 1/1 Running 0 25sYou should see the Deployment is managing three Pods. Note that the Pod names are prefixed with the Deployment name and a generated hash.
-
Update the Deployment (e.g., change the nginx version):
NODE_TYPE // bashkubectl set image deployment/my-deployment my-container=nginx:1.24NODE_TYPE // outputdeployment.apps/my-deployment image updated -
Monitor the rollout:
NODE_TYPE // bashkubectl rollout status deployment/my-deploymentNODE_TYPE // outputdeployment.apps/my-deployment successfully rolled outThis command shows the progress of the update. Kubernetes performs a rolling update, gradually replacing the old Pods with new ones.
-
Verify the updated Pods:
NODE_TYPE // bashkubectl get pods -l app=my-appThe output should show that the Pods are running the new
nginx:1.24image.
Task 4: Exposing Applications with Services
Services provide a stable IP address and DNS name for accessing your application. They abstract away the underlying Pods, allowing you to scale and update your application without affecting clients.
-
Create a Service definition file named
service-definition.yaml:NODE_TYPE // yamlapiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancerThis YAML defines a Service namedmy-servicethat selects Pods with the labelapp: my-app. It exposes port 80 on the Service and forwards traffic to port 80 on the selected Pods. Thetype: LoadBalancerwill provision a cloud load balancer (if supported by your Kubernetes environment). If you’re using Minikube or Kind, you’ll need to useNodePorttype instead. -
Deploy the Service:
NODE_TYPE // bashkubectl apply -f service-definition.yamlNODE_TYPE // outputservice/my-service created -
Verify the Service:
NODE_TYPE // bashkubectl get service my-serviceNODE_TYPE // outputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-service LoadBalancer 10.100.5.123 <pending> 80:30000/TCP 15sThe
EXTERNAL-IPwill be provisioned by your cloud provider (if using a cloud provider). If you are using Minikube, runminikube service my-serviceto get the URL of the service. -
Access the application through the Service:
Once the
EXTERNAL-IPis available (or you have the Minikube URL), you can access your application through the Service. Open a web browser and navigate to the provided IP address or URL. You should see the default nginx welcome page.If you’re using Minikube, you can access the service by runningminikube service my-service --url. This will output the URL you can use to access your application.
Conclusion
In this tutorial, you learned about the core Kubernetes primitives: Pods, ReplicaSets, Deployments, and Services. You saw how they work together to create a robust, self-healing application deployment. You created Pods, used ReplicaSets to ensure high availability, leveraged Deployments for rolling updates, and exposed your application with Services. Mastering these primitives is essential for building and managing applications in Kubernetes.