Kubernetes Handbook

📦 Requirements / Setup Guide

K8S EXAMPLES GITHUB REPO:
https://github.com/kubernetes/website/tree/main/content/en/examples
K8s FILES DOWNLOADING SITE:
https://k8s.io/examples/
DOCKER:
sudo apt-get update sudo apt install docker.io -y sudo usermod -aG docker ubuntu logout
KUBECTL:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256" echo "$(cat kubectl.sha256) kubectl" | sha256sum --check sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl kubectl version --client
KIND:
# For AMD64 / x86_64 [ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-amd64 # For ARM64 [ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-arm64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind
KIND MULTI NODE CONFIG:
config.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker
kind create cluster --name k8s-playground --config kind-config.yaml

DAY-12 Resource: DaemonSet

name:
ds
example-cmd:
wget https://k8s.io/examples/controllers/daemonset.yaml
cmd:
kubectl get ds kubectl explain ds kubectl apply -f daemonset.yaml
Notes:
-> DaemonSet are similar to ReplicaSet,But here we dont menioned any No. of pods to deploy. -> Instead pods will be deployed on every node in the cluster. This is useful for running system daemons on every node. -> For example, log collection, monitoring agents, etc. -> By default, DaemonSet will deploy pods on all nodes, but we can also specify nodeSelector to deploy pods on specific nodes. -> DaemonSet will not be deleted when nodes are deleted, but pods will be deleted. -> DaemonSet by default won't deploy any pods in control-plane node. You can use the name-space "kube-system" to deploy pods in control-plane node.

DAY-12 Resource: CronJob

name:
cj
example-cmd:
wget https://k8s.io/examples/application/job/cronjob.yaml
cmd:
kubectl get cj kubectl explain cj kubectl apply -f cronjob.yaml
Notes:
-> CronJob is used to run jobs at scheduled times. -> You can't schedule a job to run at a specific time, but you can schedule a job to run at a specific interval. -> You can't schedule a cronJob to run below 1 minute interval. -> cronJob is useful for running jobs that need to run at a specific time, like backups, reports, etc. -> star representation of cronJob is as follows: * - minute (0 - 59) * - hour (0 - 23) * - day of month (1 - 31) * - month (1 - 12) * - day of week (0 - 6) (Sunday=0 or 7)

DAY-13 Concept: Mannual Scheduling & Scheduler

Concept :
scheduling
process:
We are going to see how to manually schedule a pod and how to use scheduler to schedule pods.
cmd:
try to find the schedular pod kubectl get po -n kube-system | grep scheduler try to finding the node name of the schedular pod kubectl get po -n kube-system -o wide | grep schedule login into the container docker exec -it {container_id} bash try to find the kube-scheduler process # ps -ef | grep kube-scheduler find all the control plane components # cd /etc/kubernetes/manifests # ls -lrt Alter the kube-schedular.yaml file # vi kube-scheduler.yaml Now new pods will not be scheduled by the kube-scheduler. MANNUAL SCHEDULING create a pod with nodeName kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml vi pod.yaml nodeName: {node_name}
Notes:
-> All the control-plane components are running as static pods. -> Static pods are managed by kubelet and are created while creating the cluster. -> Schedular is a control-plane component that is responsible for scheduling pods. -> We can manually schedule a pod by specifying the nodeName in the pod spec.

DAY-13 Spec: Labels & Selectors

name :
labels
selectors
process:
we are going to see how to filter resources using labels and selectors.
cmd:
try creating any resource wget https://k8s.io/examples/pods/pod-nginx.yaml find its labels cat pod-nginx.yaml kubectl apply -f pod-nginx.yaml try to filter it using its label kubectl get pods --show-labels kubectl get po --selector env=test
Notes:
-> Labels are just used as filters, you can access those resources even without labels. -> Like namespaces they won't create logical isolation between resources.

DAY-14 Spec: Taints & Tolerations, Node Selectors

name :
taints
toleration
nodeSelector
process:
-> we are going to see how to set taints on nodes and how to use tolerations to schedule pods on tainted nodes. -> then we are going to see how to use nodeSelector to schedule pods on specific nodes.
cmd:
set taint on node k get nodes kubectl taint node {node_name} gpu=true:NoSchedule Check kubectl describe node {node_name} | grep -i taint create a pod with toleration kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml vi pod.yaml tolerations: - key: "gpu" operator: "Equal" value: "true" effect: "NoSchedule" run the pod kubectl apply -f pod.yaml check the pod run in the execpted node kubectl get po -o wide Now untain the node kubectl taint node {node_name} gpu=true:NoSchedule- create a pod with nodeSelector kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml vi pod.yaml nodeSelector: gpu: "true" run the pod kubectl apply -f pod.yaml check the pod run in the execpted node kubectl get po -o wide
Notes:
-> Taints are used to mark NODES so that pods can be scheduled on them. -> Tolerations are used to allow PODS to be scheduled on nodes with taints.
-> Effects of taints are: 1. NoSchedule - Pods will not be scheduled on the nodes. (Effects on new pods) 2. PreferNoSchedule - Pods will be scheduled on the node, but if there are no other nodes available, they will be scheduled on the node with taint. (Effects on new pods) 3. NoExecute - Pods will be evicted from the node if they are running on it. (Effects on running & newer pods)
-> Node Selector is used to schedule pods on specific nodes. ->Differnece between taints and nodeSelector is that taints are used to mark nodes and tolerations are used to allow pods to be scheduled on them. Whereas nodeSelector is used to schedule pods on specific nodes. -> In NodeSelector, PODS choose the node based on the labels of the node. -> But in Taints and Tolerations NODES choose the pods based on the tolerations of the pods.

DAY-15 Spec > Affinity : Node Affinity, Pod Affinity, Pod Anti-Affinity

name :
Node Affinity
Pod Affinity
Pod Anti-Affinity
process:
First Create the pod with nodeAffinity. Then check the pod is not scheduled on the node. Then create the node with the label. Then check the pod is scheduled on the node.
cmd:
try creating any resource wget https://k8s.io/examples/pods/pod-nginx.yaml find its node-affinity cat pod-with-node-affinity.yaml affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - antarctica-east1 - antarctica-west1 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value kubectl apply -f pod-with-node-affinity.yaml check pod kubectl get pods create label for the node& check the pod is scheduled kubectl label node {node_name} topology.kubernetes.io/zone=antarctica-east1 kubectl get pods
Notes:
→ Node Affinity is used to schedule pods on specific nodes. Here, we use nodeSelectorTerms to control which nodes the pods are scheduled on. → Pod Affinity is used to schedule pods on nodes based on the labels of other existing pods (podAffinityTerms). This ensures that new pods are scheduled on the same node as those matching pods. → Pod Anti-Affinity is used to avoid scheduling pods on the same node as certain existing pods. Here, we use podAffinityTerms to make sure new pods are placed on different nodes. -> 2 types of node affinity: 1. requiredDuringSchedulingIgnoredDuringExecution: - This is used to schedule pods on specific nodes. If the node is not available, the pod will not be scheduled. - nodeaffinity is a hard requirement for the pod to be scheduled on the node. 2. preferredDuringSchedulingIgnoredDuringExecution: - This is used to schedule pods on specific nodes. If the node is not available, the pod will be scheduled on any node. - weight & preference is used to schedule pods on specific nodes. If the node is not available, the pod will be scheduled on any node.

DAY-16 Spec > Resources: Request & Limits

name :
requests
limits
process:
1. First we will create a pod with requests and limits using the polinux/stress image. This image is used to stress test the CPU and memory. 2. Then we will increase the load on the pod over the request & limits and see the effect on the CPU and memory. 3. Then we will reduce the load on the pod and see the effect on the CPU and memory. 4. to track the CPU and memory usage we will use the metrics server.
cmd:
Create a Metric Server vim metric-server.yaml apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: k8s-app: metrics-server rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-view: "true" name: system:aggregated-metrics-reader rules: - apiGroups: - metrics.k8s.io resources: - pods - nodes verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: k8s-app: metrics-server name: system:metrics-server rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get - apiGroups: - "" resources: - pods - nodes verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: k8s-app: metrics-server name: metrics-server-auth-reader namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-reader subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: k8s-app: metrics-server name: metrics-server:system:auth-delegator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegator subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: k8s-app: metrics-server name: system:metrics-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:metrics-server subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: v1 kind: Service metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: k8s-app: metrics-server --- apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system spec: selector: matchLabels: k8s-app: metrics-server strategy: rollingUpdate: maxUnavailable: 0 template: metadata: labels: k8s-app: metrics-server spec: containers: - args: - --cert-dir=/tmp - --secure-port=10250 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --kubelet-insecure-tls - --metric-resolution=15s image: registry.k8s.io/metrics-server/metrics-server:v0.7.1 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: https scheme: HTTPS periodSeconds: 10 name: metrics-server ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /readyz port: https scheme: HTTPS initialDelaySeconds: 20 periodSeconds: 10 resources: requests: cpu: 100m memory: 200Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp name: tmp-dir nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical serviceAccountName: metrics-server volumes: - emptyDir: {} name: tmp-dir --- apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata: labels: k8s-app: metrics-server name: v1beta1.metrics.k8s.io spec: group: metrics.k8s.io groupPriorityMinimum: 100 insecureSkipTLSVerify: true service: name: metrics-server namespace: kube-system version: v1beta1 versionPriority: 100 kubectl apply -f metric-server.yaml kubectl top node kubectl create namespace mem-example Create a pod with polinux/stress image wget https://k8s.io/examples/pods/resource/memory-request-limit.yaml apiVersion: v1 kind: Pod metadata: name: memory-demo namespace: mem-example spec: containers: - name: memory-demo-ctr image: polinux/stress
resources: limits: memory: "200Mi" requests: memory: "100Mi" command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
try increasing the stress args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"] kubectl apply -f memory-request-limit.yaml - You will see the pod is in pending state. - kubectl describe pod memory-demo -n mem-example - You will see the reason is OOM Killed. OUT OF MEMORY. try reducing the stress args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] kubectl apply -f memory-request-limit.yaml - You will see the pod is in running state.
Notes:
-> Requests are used to reserve resources for the pod. If the node does not have enough resources, the pod will not be scheduled. -> Limits are used to limit the resources that the pod can use. If the pod tries to use more resources than the limit, it will be killed.

DAY-17 Resource: AutoScaling

Types of AutoScaling :
MANAGED BY USER
HPA (default) - Horizontal Pod AutoScaling VPA - Vertical Pod AutoScaling
MANAGED BY CLOUD PROVIDER
Cluster AutoScaler Node AutoScaler
process:
1. Create a deployment using php-apache image. 2. autoscale the deployment using HPA. 3. Increase the load on the deployment by sending requests to the service. 4. Check the number of pods in the deployment. 5. Check the metrics of the deployment using metrics server.
cmd:
Create metric-server follow the above day-16 to create metric-server. Create php-apache deployment with service wget https://k8s.io/examples/application/php-apache.yaml kubectl apply -f php-apache.yaml kubectl get deploy kubectl get svc kubectl get pods Create an HPA imperatively kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10 Check the HPA kubectl get hpa Now increase the request to the php server (run the below command in another terminal) kubectl run -i --tty load-generator --image=busybox /bin/sh -c "while true; do wget -q -O- http://php-apache; done" (The above command will send requests to the php server and increase the load on the server.) Check kubectl get hpa --watch kubectl get pods
Notes:
HPA -> HPA is best for applications with high availability and low latency requirements, especially when the load varies and horizontal scaling (more pods) is needed. -> where you need to quickly add/remove pods to handle increased traffic or load. -> Common use case: Stateless services, microservices, APIs. -> Helps maintain high availability and low latency under dynamic traffic. VPA -> VPA is best for applications with Adjusts CPU and memory requests/limits for containers automatically (vertical scaling). -> VPA Restarts the pod when applying new resource settings, which can introduce brief downtime. -> VPA is Best suited for: Batch jobs, long-running workloads, or applications with steady load but unpredictable resource usage.

DAY-18 Spec: Health Probes (Liveness Vs Readiness)

cmd:
Create a http-liveness probe wget https://k8s.io/examples/pods/probe/exec-liveness.yaml Create a grpc-liveness probe wget https://k8s.io/examples/pods/probe/grpc-liveness.yaml Create a http-liveness probe wget https://k8s.io/examples/pods/probe/http-liveness.yaml Create a pod-with-tcp-socket-healthcheck probe wget https://k8s.io/examples/pods/probe/pod-with-tcp-socket-healthcheck.yaml
Notes:
Health Probes -> Probes are system or process that monitor our system and take necessary actions if the system is not working as expected, run a script or command to check the health of the system. -> Monitor health of the application, Literally "Checkups". -> There are three types of health probes: 1. Liveness Probe (Ensure the application is running & restart the application when failed to respond, If not rectified throw error & kill the pod) ) 2. Readiness Probe (Ensure the application is ready to serve traffic) 3. Startup Probe (for slow legacy apps) -> Types of Health checks: 1. HTTP GET 2. TCP Socket 3. Exec 4. GRPC

DAY-19 Resource: ConfigMaps & Secrets

name:
cm
cmd:
ConfigMap creation via Imperative way kubectl create cm app-cm --from-literal=key1=value1 --from-literal=key2=value2 Check kubectl describe cm app-cm Call the configmap in the spec block of pod ... .... spec: -name: my-app env: - name: FIRSTNAME value - configMapRef: name: app-cm key: key1 Exec into the pod and check the env variable kubectl apply -f pod.yaml kubectl exec -it my-app -- sh echo $FIRSTNAME kubectl describe pod my-app Call key-values from a file kubectl create cm app-cm --from-file=app.config app.config file --------------- key1=value1 key2=value2 ConfigMap creation via Declarative way wget https://k8s.io/examples/configmap/configmap-multikeys.yaml
Notes:
ConfigMaps -> If we need to use same config file & Environment Values in multiple pods, we can use configmaps. -> ConfigMaps are used to store configuration data in key-value pairs. -> Secrets are used to store sensitive data like passwords, tokens, etc.

DAY-20 Concept: TLS cert

cmd:
Genearte a Private Key openssl genrsa -out adam.key 2048 Creating a CSR req file openssl req -new -key adam.key -out adam.csr - subj "/CN=adam" Decrypt the code of .csr file cat adam.csr | base64 | tr -d '\n' (copy the output) Copy the output and paste in the request block in spec of 'csr.yaml' file csr.yaml file apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: adam spec: request: {paste the output here} signerName: kubernetes.io/kube-apiserver-client expirationSeconds: 86400 usages: - client auth Apply the csr.yaml file kubectl apply -f csr.yaml Approve the csr kubectl certificate approve adam (here we are getting approval of an internal CA instead of authoirzed CA) Create a file to get the public cert kubectl get csr adam -o yaml > issuecert.yaml Open issuecert.yaml and copy the certificate vim issuecert.yaml (copy the certificate) Decoding the encoded cert echo {copied_cert} | base64 -d (we will add this cert to kubeconfig file using which user can access the cluster)
Notes:
File Identification tip -> If you find 'cert'/'pem' extension in the file, it is a public key certificate. -> If you find 'key'/'pem' extension in the file, it is a private key certificate. Openssl -> Openssl is a toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. -> It is used to generate public key & private key certificate. CSR -> Certificate Signing Request is a request to a CA to sign a certificate. -> CSR contains the public key and is used to request a certificate from a CA. It does not generate keys

DAY-21 Concept: Authentication & Authorization

cmd:
find the kubeconfig file cd $HOME ls -ltr cd .kube ls -lrt Login into controlplane docker ps docker exec -it {container_id} bash cd /etc/kubernetes/manifests ls -lrt cat kube-apiserver.yaml ( under command block you will find the authentication & authorization methods used by kube-apiserver. --authorization-mode=Node,RBAC where Node -> Priority 1 RBAC -> Priority 2 ) To find the certs and keys used by kube-apiserver cd /etc/kubernetes/pki ls -lrt ( you will find the certs and keys used by kube-apiserver)
Notes:
-> Everytime you create a any resources, an additional values like client certificate are internally passed by kubeconfig file to authenticate the user with K8s API server. kubeconfig file -> "kubeconfig" is the file that contains the configuration for the kubelet to connect to the API server. Which takes care of authentication & authorization. -> A kubeconfig file is a YAML file that contains: - clusters info - users info - contexts info context -> A context is a combination of a cluster, a user, and a namespace. It is used to group the information about how to connect to a cluster. Types of Authorization 1. Symmetric key encryption 2. Asymmetric key encryption 3. Certificates based Types of Authorization 1. Node Authorization 2. ABAC (Attribute Based Access Control ) - restart the API server to apply changes 3. RBAC (Role Based Access Control) 4. Webhook (External Authorization)