Kubernetes Voyage: Advanced Ship Steering
We will learn
- pods vs container
- Deployments
- Services
- Auto-healing concept
- config maps & secrets
- persistent volume
Let’s get started.
Pods vs Containers⌗
Pods | Container |
---|---|
Unit of conainers | Single container by containerization tool. |
Contains one or more Conainers | Only single container |
Crashed free | Can be crashed if some error occurs |
Can be Scheduled | Can’t be scheduled |
Configuration file⌗
To create pods we have to use a configuration file in YAML
, which is also called manifest
in k8s
We need manifest file for almost everything in kubernetes.
-
Kind:
To create maifest file for a paritcular service we have to define a
kind
keyword.kind
defines what type of manifest file is, like for Pods, Service or Deployment, etc.Example:
apiVersion: v1 kind: Pod metadata: # Extra data. # object name: nginx # Any name can be used. spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
-
Namespace:
logical entity allow you to isolate your resources, like pods, volumne, deploymnets, etc. You can create multiple namaspcae for different resources, it is a type of group.
Default name space is already present, and everything is created under it until you specify any other namespace in manifest.
kubectl create namespace nginx
kubectl get namespace
Example:
apiVersion: v1 kind: Pod metadata: # Extra data. # object name: nginx # Any name can be used. namespace: nginx spec: containers: - name: nginx image: nginx:latest ports: # If you don't specify then also it will assume. - containerPort: 80
-
To apply the manifest file to your cluster command:
kubectl apply -f pod.yml
This will send request to api server, then it will to scheduler (resposnisble fo managing pods) and then it send back to api server and then configuration will be stored.
-
To fetch the pods information from master we can use the below command:
kubectl get pods -n nginx
-n
: namespace, by default it only looks for resources in to default namespace.
Deployment⌗
Deployment is a desired state.
It is also written in manifest file and kind
will be set to Deployment
. It is used to create replicaset of templates,
It is a configuration of pods. It is a desired(required) state of your pods. You can also provide some data in pods while deployment using this manifest.
Example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels: # select all nginx labels
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
replicas
: Number of pods clone / replicationslabels
: Configuration is for, name of the replica.
Actions:
-
Apply the deployment:
kubectl apply -f deployment.yml
-
Get the nodes with more wider output.
kubectl get nodes -n nginx -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME ip-172-31-55-54 Ready <none> 4d23h v1.20.0 172.31.55.54 <none> Ubuntu 22.04.3 LTS 6.2.0-1011-aws docker://24.0.5 ip-172-31-57-166 Ready control-plane,master 5d v1.20.0 172.31.57.166 <none> Ubuntu 22.04.3 LTS 6.2.0-1011-aws docker://24.0.5
-
Get your deployment status.
kubectl get deployment -n nginx
NAME READY UP-TO-DATE AVAILABLE AGE │ nginx-deployment 3/3 3 3 23m
-
Get detail information about your deployment.
kubectl describe deployment
-
Apply Rolling update to deployment like scaling: # No need to edit the file.
kubectl scale deployment nginx-deployment --replicas=2 -n nginx
deployment.apps/nginx-deployment scaled
-
You can even Rollback if you made any mistake.
kubectl rollout undo deployment/nginx-deployment
Services⌗
It is method used to allow outside world to access application instance running in pods deployment, some sort of proxy.
In our example, nginx is running but not accessible because we haven’t applied any service yet.
Example:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80 # containers port
targetPort: 9376 # service's port to map with.
Services are of 3 types:⌗
-
NodePort:
It act as a node machine, this maps the deployment’s port to serivce’s port.
We have to provide 3 ports:
port
: Port of application running in pods, (80 incase of nginx).targetPort
: Service port, to map pods port with Service port. (incoming)nodePort
: Outgoing port, which is actual accessible port. ( ranges [30000 - 32627])
Example:
This service file will provide the access to users for our application which is nginx in this case.
apiVersion: v1 kind: Service metadata: name: my-service namespace: webserverss spec: selector: app: nginx type: NodePort ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 30004
-
Cluster IP:
It Exposes the Service on a cluster-internal IP, Making the Service only reachable from within the cluster not outside, And this is used by default.
-
Load balancer:
It Exposes the Service externally using an external load balancer. Kubernetes does not offer a load balancing component; you have provide one, or you can integrate your cluster with a cloud provider like AWS.
We, will use NodePort which will allow us to access out nginx outside the cluster.
-
Apply the service
kubectl apply -f serivce.yml
-
List your Services.
kubectl get services -n webserverss
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE │ my-service NodePort 10.104.86.172 <none> 80:30004/TCP 15s
Auto healing.⌗
Now, our pods are running and our application is also accessible by the user. But, what if we delete one of the pod or container?
Well, let’s do it.
-
First get list of your pods.
kubectl get pods -n webserverss # replace with your namespace
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 1 17m nginx-deployment-66b6c48dd5-2299p 1/1 Running 1 16m nginx-deployment-66b6c48dd5-vtqq8 1/1 Running 1 16m
-
And now delete one pod.
kubectl delete pod nginx-deployment-66b6c48dd5-2299p -n webserverss
Now, we have deleted one pod, let’s check the status of pods.
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 1 17m nginx-deployment-66b6c48dd5-tlq9v 1/1 Running 0 8s nginx-deployment-66b6c48dd5-vtqq8 1/1 Running 1 16m
You saw that right? The
Age
of second pod is8s
.Yes, that 2nd pod got created after we deleted one, And this is what we call Auto Healing.
-
Anyway, If you want to delete you particular depolyment or manfiest configuration use this syntax:
kubectl delete -f pod.yml # your manifest.yml file
Secrets & config map⌗
In k8s, we can’t pass environment variables through kubectl at runtime. Therefore we use secret & config map file.
-
Config map:
It is a Special kind of manifest file, if you deployment needs particular variable then you can declare that in this manifest file. All variables are passed to all pods. In manifest set kind to
kind: ConfigMap
to create a config map. It pass data as plain texts. -
Secrets:
It is a type of config which contains credentials (passwords), advantage is you can pass encoded password and it will be decrypted in pods. In manifest set kind to
kind: secrets
to create secrets.
Example:
-
Setup servers
-
Create deployment manifest.
apiVersion: apps/v1 kind: Deployment metadata: name: mysql-deplyment namespace: mysql labels: app: mysql spec: replicas: 1 selector: matchLabels: app: mysql selector: matchLabels: app: nginx-2 template: metadata: labels: app: nginx-2 spec: containers: - name: mysql image: mysql ports: - containerPort: 3306 env: - name: MYSQL_DATABASE valueFrom: configMapKeyRef: name: mysql-config key: MYSQL_DATABASE name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_PASSWORD
-
You can rectify errors using dry run, it doesn’t apply the changes only show what will be happen if applied:
kubectl apply -f deployment.yml --dry-run
-
Create defined namespace:
kuebctl create namespace mysql
-
Create configMaps manifest file
apiVersion: v1 kind: ConfigMap metadata: name: mysql-config namespace: mysql labels: app: mysql data: MYSQL_DATABASE: "cooldb"
-
Apply config map.
kubectl apply -f configMap.yml
-
Check your config map.
kubectl get configmap -n mysql
-
Now create secrests manifest.
But, before that encrypt your pass using below command.
echo -n 'secret' | base64 # you can pass -d to decrypt
copy output and pass in data field in secrets.yml
apiVersion: v1 kind: Secret metadata: name: mysql-secret namespace: mysql labels: app: mysql type: Opaque data: MYSQL_PASSWORD: dkoafusfmsdjk # base64 password.
-
Apply secrets manifest to deployment.
kubectl apply -f secret.yml
-
Now, check if secret is added successfully.
kubectl get secret -n mysql
-
After that, finally apply your deployment.
kubectl apply -f deployment.yml
NAME READY UP-TO-DATE AVAILABLE AGE │ mysql-deplyment 1/1 1 1 40m
After your deployment, you can cross verify by logging in mysql. Run commands in worker node. Make sure you are putting correct container id.
docker ps | grep mysql docker exec -it ef175a2293f2 /bin/mysql -u root -p
-
You can delete your deployment if you want.
kubectl delete -f deployment.yml
PVC & PV, Storage classes⌗
-
PV (Persistent Volume)
It creates application’s stateful location is in your disk where data is stored as snapshot.
apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv-volume namespace: mysql labels: app: mysql spec: storageClassName: manual capacity: storage: 2Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data"
Make sure hostPath.path directory exists in worker node.
Now apply your peristentVolume manifest
kubectl apply -f persistenVolume.yml
Check if persistentVolume is created.
kubectl get pv -n mysql
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE mysql-pv-volume 2Gi RWO Retain Available manual 16s
-
PVC (Persistent Volume Claim):
After creating the volume you have to claim it to use, until now we have just created not used. You can claim how much you want from volume for your deployment.
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim namespace: mysql spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 2Gi
Then, apply it
kubectl apply -f persistentVolumeClaim.yml
After that check if was successfull.
kubectl get pvc -n mysql
Now, to use volumes add these into containers object in deployment.yml.
volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pv-claim
So, that’s it.