Skip to content

Kubernetes basic - The hard way

This training is intended to help developers to understand Kubernetes fundamentals. We will not use advanced tools such as Helm but instead we will do every step manually with kubectl and yaml manifests.

As a use case we will work on the deployment of the Atlassian Confluence application.

You will find all the Kubernetes manifest use in this course into the manifests folder.

Create a namespace

In Kubernetes a namespace is used to isolate resources, in a multi-tenant environment it is wise to create one namespace per tenant.

Let's create a namespace for our application.

kubectl apply -f manifests/namespace.yaml

Create a pod

A pod is composed of one or multiple containers acting together to provide a service. Each container inside a pod share the same node, the same IP and the same volumes.

Deploy our application pod in the demo namespace

kubectl apply -f manifests/pod.yaml --namespace demo

Verify the pods was correctly created

kubectl get pods --namespace demo

Open a tunnel to your pod

kubectl port-forward -n demo pod/confluence 8080:8090

Open your navigator and go to http://localhost:8080

After this first step you have a single pod hosting your application which is not accessible from internet. As the pod has an IP address your can access it from the cluster only (internally accessible).

Create a service

A service is a way to abstract the underlayer pods. There are several kind of services, ClusterIP(the default one), LoadBalancer, NodePort and ExternalName. A service act as a load balancer between pods of the same nature.

Deploy our service in the demo namespace

kubectl apply -f manifests/service.yaml --namespace demo

Verify that your service route the traffic to your pod

kubectl port-forward -n demo svc/confluence-svc 8080:8090

Go to http://localhost:8080

Describe your service and verify the target endpoint

kubectl describe svc confluence-svc -n demo

Deploy another confluence pods

kubectl apply -f manifests/pod-1.yaml --namespace demo

Describe your service and verify the target endpoints

kubectl describe svc confluence-svc -n demo

Note: You will see 2 IPs addresses matching the 2 pods created

Is your service publicly accessible :

kubectl get svc confluence-svc -n demo

Note: the external IP is empty, this is because a service of type ClusterIP is not internet facing.

Make your service publicly accessible

List AWS load balancers

aws elbv2 describe-load-balancers

Change the service type to LoadBalancer and apply your changes

kubectl apply -f manifests/service.yaml --namespace demo

Get the service external IP

kubectl get svc confluence-svc -n demo

Your service is now associated with and external ip (fqdn) matching an AWS classic load balancer created by kubernetes.

Get your public url and navigate to the url

echo "http://$(kubectl get svc confluence-svc -n demo -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'):8090"

Your application is now accessible from internet through an AWS Classic Load Balancer.

Create a replicaset

*A replicaset is used to manage the number of pods. If you want to scale you modify the replicaset configuration to increase the number of replica, then you will new pods spun-up.

kubectl apply -f manifests/replicaset.yaml -n demo

A replicaset acquires all the pods with specific labels, even if it did not create those pods.

Try the command below and observe the pods in the demo namespace

kubectl apply -f manifests/pod.yaml --namespace demo

The pod is automatically shutdown by the replicaset as we specified only 1 replica.

Note: Replicaset is a good way to create a canary deployment

Create a deployment

A deployment is a Kubernetes object used to manage pods. It creates and manages a replicaset which is used to configure the number of replica and all the deployment aspects of a pod. This is the default way to deploy stateless applications.

kubectl apply -f manifests/deployment.yaml --namespace demo

Verify if it was created

kubectl get deployment --namespace demo

List the replicaset inside the namespace

kubectl get replicaset -n demo

The deployment created a replicaset. Now, there are 2 replicasets managing the same pods, thus we may see inconsistencies.

Delete the first replicaset created

kubectl delete replicaset confluence-replicaset -n demo

Create a StatefulSet

A StatefulSet is a Kubernetes object used to manage pods. It has its own control plain to manage the number of replica. It is mainly used to manage stateful applications.

Deploy your application with a StatefulSet

kubectl apply -f manifests/statefulset.yaml --namespace demo

Check the status

kubectl describe statefulset confluence --namespace demo

Check the pods

kubectl get pods --namespace demo

Note: It is interesting to see that the StatefulSet counts only the pods it creates. This is because it has its own control plain.

During the deployment we requested for persistent storage.

List the persistent volume claim

kubectl get persistentvolumeclaim --namespace demo

Look for the storage in AWS

aws ec2 describe-volumes --filter Name=tag:kubernetes.io/created-for/pvc/namespace,Values=demo --query "Volumes[*].{ID:VolumeId}

Delete the StatefulSet

kubectl delete statefulset confluence --namespace demo

aws ec2 describe-volumes --filter Name=tag:kubernetes.io/created-for/pvc/namespace,Values=demo --query "Volumes[*].{ID:VolumeId}"

The disk are still there.

Note: PersistentVolume Claims are not deleted when the Pods, or StatefulSet are deleted. This must be done manually.

Deploy again the StatefulSet

kubectl apply -f manifests/statefulset.yaml --namespace demo

The new pods should be attached to the previously created volumes

Ingress

Create the ingress

kubectl apply -f manifests/ingress.yaml

Try to access http://confluence-demo.platformdxc-mg-d0.com

Persistent volume claim

As the default pod storage type (emptyDir) is ephemeral we may need to create permanent disk with the persistent volume claim;


Last update: May 23, 2023