This repo covers Kubernetes with LABs: Kubectl, Pod, Deployment, Service, PV, PVC, Rollout, Multicontainer, Daemonset, Taint-Toleration, Job, Ingress, Kubeadm, Helm, etc.
PowerShell
3,855
417 commits
updated Apr 14, 2025
This repo covers Kubernetes objects' and components' details (Kubectl, Pod, Deployment, Service, ConfigMap, Volume, PV, PVC, Daemonset, Secret, Affinity, Taint-Toleration, Helm, etc.), and possible example usage scenarios (HowTo: Hands-on LAB) in a nutshell.
Keywords: Containerization, Kubernetes, Kubectl, Pod, Deployment, Service, ConfigMap, ReplicaSet, Volume, Cheatsheet.
Note: K8s objects and objects feature can be updated/changed in time. While creating this repo, the version of K8s was v1.22.3. Some sections are trying to be kept up to date. Especially Creating K8s Cluster with Kubeadm and Containerd.
Why should we use Kubernetes? "Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes services, support, and tools are widely available." (Ref: Kubernetes.io)

(Ref: Kubernetes.io)

Download:
from here=> https://kubernetes.io/docs/tasks/tools/
For learning K8s and running on a computer, Kubectl and Minikube are enough to install.
PS: Cloud providers (Azure, Google Cloud, AWS) offer managed K8s (control plane is managed by cloud provides). You can easily create your cluster (number of computer and details) and make connection with Kubectl (using CLI get-credentials of cluster on the cloud)
Goto the Scenario: LAB: K8s Creating Pod - Imperative Way

Goto the Scenario: LAB: K8s Creating Pod - Declarative Way (With File) - Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: initcontainerpod
spec:
containers:
- name: appcontainer # after initcontainer closed successfully, appcontainer starts.
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: initcontainer
image: busybox # init container starts firstly and look up myservice is up or not in every 2 seconds, if there is myservice available, initcontainer closes.
command: ['sh', '-c', "until nslookup myservice; do echo waiting for myservice; sleep 2; done"]
Goto the Scenario: LAB: K8s Multicontainer - Sidecar - Emptydir Volume - Port-Forwarding

kubectl label pods pod1 team=development #adding label team=development on pod1
kubectl get pods --show-labels
kubectl label pods pod1 team- #remove team (key:value) from pod1
kubectl label --overwrite pods pod1 team=test #overwrite/change label on pod1
kubectl label pods --all foo=bar # add label foo=bar for all pods
kubectl get pods -l "app=firstapp" --show-labels
kubectl get pods -l "app=firstapp,tier=frontend" --show-labels
kubectl get pods -l "app=firstapp,tier!=frontend" --show-labels
kubectl get pods -l "app,tier=frontend" --show-labels #equality-based selector
kubectl get pods -l "app in (firstapp)" --show-labels #set-based selector
kubectl get pods -l "app not in (firstapp)" --show-labels #set-based selector
kubectl get pods -l "app=firstapp,app=secondapp" --show-labels # comma means and => firstapp and secondapp
kubectl get pods -l "app in (firstapp,secondapp)" --show-labels # it means or => firstapp or secondapp

kubectl apply -f podnode.yaml
kubectl get pods -w #always watch
kubectl label nodes minikube hddtype=ssd #after labelling node, pod11 configuration can run, because node is labelled with hddtype:ssd

kubectl apply -f podannotation.yaml
kubectl describe pod annotationpod
kubectl annotate pods annotationpod foo=bar #imperative way
kubectl delete -f podannotation.yaml

kubectl get pods --namespaces kube-system # get all pods in the kube-system namespaces
kubectl get pods --all-namespaces # get pods from all namespaces
kubectl create namespace development # create new development namespace in imperative way
kubectl get pods -n development # get pods from the development namespace

kubectl apply -f namespace.yaml
kubectl get pods -n development #get pods in the development namespace
kubectl exec -it namespacedpod -n development -- /bin/sh #run namespacepod in development namespace
kubectl config set-context --current --namespace=development #now default namespace is development
kubectl get pods #returns pods in the development namespace
kubectl config set-context --current --namespace=default #now namespace is default
kubectl delete namespaces development #delete development namespace
kubectl create deployment firstdeployment --image=nginx:latest --replicas=2
kubectl get deployments
kubectl get pods -w #on another terminal
kubectl delete pods <oneofthepodname> #we can see another terminal, new pod will be created (to keep 2 replicas)
kubectl scale deployments firstdeployment --replicas=5
kubectl delete deployments firstdeployment
Goto the Scenario: LAB: K8s Deployment - Scale Up/Down - Bash Connection - Port Forwarding

kubectl set image deployment rolldeployment nginx=httpd:alpine --record # change image of deployment
kubectl rollout history deployment rolldeployment #shows record/history revisions
kubectl rollout history deployment rolldeployment --revision=2 #select the details of the one of the revisions
kubectl rollout undo deployment rolldeployment #returns back to previous deployment revision
kubectl rollout undo deployment rolldeployment --to-revision=1 #returns back to the selected revision=1
kubectl rollout status deployment rolldeployment -w #show live status of the rollout deployment
kubectl rollout pause deployment rolldeployment #pause the rollout while updating pods
kubectl rollout resume deployment rolldeployment #resume the rollout if rollout paused
Goto the Scenario: LAB: K8s Rollout - Rollback
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Goto the Scenario: LAB: K8s Service Implementations (ClusterIp, NodePort and LoadBalancer)
Goto the Scenario: LAB: K8s Liveness Probe


Goto the Scenario: LAB: K8s Creating Pod - Declarative Way - Environment Variable
spec:
containers:
- name: sidecar
image: busybox
command: ["/bin/sh"]
args: ["-c", "sleep 3600"]
volumeMounts: # volume is mounted under "volumeMounts"
- name: cache-vol # "name" of the volume type
mountPath: /tmp/log # "mountPath" is the path in the container.
volumes:
- name: cache-vol
emptyDir: {} # "volume" type "emptydir"
Goto the Scenario: LAB: K8s Multicontainer - Sidecar - Emptydir Volume - Port-Forwarding
apiVersion: v1
kind: Pod
metadata:
name: hostpath
spec:
containers:
- name: hostpathcontainer
image: ImageName # e.g. nginx
volumeMounts:
- name: directory-vol # container connects "volume" name
mountPath: /dir1 # on the container which path this volume is mounted
- name: dircreate-vol
mountPath: /cache # on the container which path this volume is mounted
- name: file-vol
mountPath: /cache/config.json # on the container which file this volume is mounted
volumes:
- name: directory-vol # "volume" name
hostPath: # "volume" type "hostpath"
path: /tmp # "path" on the node, "/tmp" is defined volume
type: Directory # "hostpath" type "Directory", existed directory
- name: dircreate-vol
hostPath: # "volume" type "hostpath"
path: /cache # "path" on the node
type: DirectoryOrCreate # "hostpath" type "DirectoryOrCreate", if it is not existed, create directory
- name: file-vol
hostPath: # "volume" type "hostpath"
path: /cache/config.json # "path" on the node
type: FileOrCreate # "hostpath" type "FileOrCreate", if it is not existed, create file

kubectl create secret generic mysecret2 --from-literal=db_server=db.example.com --from-literal=db_username=admin --from-literal=db_password=P@ssw0rd!
kubectl create secret generic mysecret3 --from-file=db_server=server.txt --from-file=db_username=username.txt --from-file=db_password=password.txt
kubectl create secret generic mysecret4 --from-file=config.json
Goto the Scenario: LAB: K8s Secret (Declarative and Imperative Way)
Goto the Scenario: LAB: K8s Config Map
With node affinity, specific pods can enable to run on the desired node (Node selector also supports that feature, but node affinity is more flexible).
If node is labelled with key-value, we can run some of the pods on that specific node.
Terms for Node Affinity:
For a better understanding, please have a look LAB: K8s Node Affinity
Go to the Scenario: LAB: K8s Node Affinity
apiVersion: v1
kind: Pod
metadata:
name: frontendpod
labels:
app: frontend # defined labels
deployment: test
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: cachepod
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # required: if not found, not run this pod on any node
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname # run this pod with the POD which includes "app=frontend" on the same worker NODE
preferredDuringSchedulingIgnoredDuringExecution: # preferred: if not found, run this pod on any node
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: branch
operator: In
values:
- develop
topologyKey: topology.kubernetes.io/zone # run this pod with the POD which includes "branch=develop" on the any NODE in the same ZONE
podAntiAffinity: # anti-affinity: NOT run this pod with the following match ""
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: deployment
operator: In
values:
- prod
topologyKey: topology.kubernetes.io/zone # NOT run this pod with the POD which includes "deployment=prod" on the any NODE in the same ZONE
containers:
- name: cachecontainer # cache image and container name
image: redis:6-alpine


Goto the Scenario: LAB: K8s Taint-Toleration
Goto the scenario: LAB: K8s Daemonset - Creating 3 nodes on Minikube
# Creating Persistent Volume on NFS Server on the network
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysqlpv
labels:
app: mysql # labelled PV with "mysql"
spec:
capacity:
storage: 5Gi # 5Gibibyte = power of 2; 5GB= power of 10
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle # volume is not deleted, all data in the volume will be deleted.
nfs:
path: /tmp # binds the path on the NFS Server
server: 10.255.255.10 # IP of NFS Server

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysqlclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem # VolumeMode
resources:
requests:
storage: 5Gi
storageClassName: ""
selector:
matchLabels:
app: mysql # choose/select "mysql" PV that is defined above.

Goto the scenario: LAB: K8s Persistant Volume and Persistant Volume Claim
# Storage Class Creation on Azure
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standarddisk
parameters:
cachingmode: ReadOnly
kind: Managed
storageaccounttype: StandardSSD_LRS
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysqlclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
storageClassName: "standarddisk" # selects/binds to storage class (defined above)
Goto the scenario: LAB: K8s Stateful Sets - Nginx
spec:
parallelism: 2 # each step how many pods start in parallel at a time
completions: 10 # number of pods that run and complete job at the end of the time
backoffLimit: 5 # to tolerate fail number of job, after 5 times of failure, not try to continue job, fail the job
activeDeadlineSeconds: 100 # if this job is not completed in 100 seconds, fail the job

Goto the scenario: LAB: K8s Job
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
#
# https://crontab.guru/
# Examples:
# 5 * * * * : (means) For every day start at minute 5: 00:05 - Second day 00:05 ....
# */5 * * * * : (means) At every 5th minute: 00:05 - 00:10 - 00:15 ...
# 0 */2 * * * : (means) At minute 0 pass every 2d hour: 00:00 - 02:00 - 04:00 ...
# "*" means "every"
# "/" means "repetitive"
spec:
schedule: "*/1 * * * *" # At every 1st minute: 00:01 - 00:02 ...
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command: # start shell and echo
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

Go to the scenario: LAB: K8s Cron Job
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"] # "services", "endpoints", "pods", "pods/log" etc.
verbs: ["get", "watch", "list"] # "get", "list", "watch", "create", "update", "patch", "delete"

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: username@hostname.net # "name" is case sensitive, this name was defined while creating .csr file
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: DevTeam # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

(ref: Kubernetes.io)
# Simple Ingress Object Definition
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
Goto the scenario: LAB: K8s Ingress
# if working on minikube
minikube addons enable dashboard
minikube addons enable metrics-server
minikube dashboard
# if running on WSL/WSL2 to open browser
sensible-browser http://127.0.0.1:45771/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/


Goto the scenario: LAB: Enable Dashboard on Real Cluster
Goto the scenario: LAB: HELM Install & Usage
Goto the scenario: LAB: Helm-Jenkins on running K8s Cluster (2 Node Multipass VM)
Goto: Helm Commands Cheatsheet
Goto: Kubernetes Commands Cheatsheet
Goto: Helm Commands Cheatsheet
Goto: LAB: K8s Kubeadm Cluster Setup
Goto: LAB: K8s Monitoring - Prometheus and Grafana
Goto: LAB: Enable Dashboard on Real K8s Cluster
249 followers · starred Sep 2023
32 followers · starred May 2022
419 followers · starred May 2026
46 followers · starred Aug 2023
This repo covers Kubernetes with LABs: Kubectl, Pod, Deployment, Service, PV, PVC, Rollout, Multicontainer, Daemonset, Taint-Toleration, Job, Ingress, Kubeadm, Helm, etc.
PowerShell
3,855
417 commits
updated Apr 14, 2025
This repo covers Kubernetes objects' and components' details (Kubectl, Pod, Deployment, Service, ConfigMap, Volume, PV, PVC, Daemonset, Secret, Affinity, Taint-Toleration, Helm, etc.), and possible example usage scenarios (HowTo: Hands-on LAB) in a nutshell.
Keywords: Containerization, Kubernetes, Kubectl, Pod, Deployment, Service, ConfigMap, ReplicaSet, Volume, Cheatsheet.
Note: K8s objects and objects feature can be updated/changed in time. While creating this repo, the version of K8s was v1.22.3. Some sections are trying to be kept up to date. Especially Creating K8s Cluster with Kubeadm and Containerd.
Why should we use Kubernetes? "Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes services, support, and tools are widely available." (Ref: Kubernetes.io)

(Ref: Kubernetes.io)

Download:
from here=> https://kubernetes.io/docs/tasks/tools/
For learning K8s and running on a computer, Kubectl and Minikube are enough to install.
PS: Cloud providers (Azure, Google Cloud, AWS) offer managed K8s (control plane is managed by cloud provides). You can easily create your cluster (number of computer and details) and make connection with Kubectl (using CLI get-credentials of cluster on the cloud)
Goto the Scenario: LAB: K8s Creating Pod - Imperative Way

Goto the Scenario: LAB: K8s Creating Pod - Declarative Way (With File) - Environment Variable
apiVersion: v1
kind: Pod
metadata:
name: initcontainerpod
spec:
containers:
- name: appcontainer # after initcontainer closed successfully, appcontainer starts.
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: initcontainer
image: busybox # init container starts firstly and look up myservice is up or not in every 2 seconds, if there is myservice available, initcontainer closes.
command: ['sh', '-c', "until nslookup myservice; do echo waiting for myservice; sleep 2; done"]
Goto the Scenario: LAB: K8s Multicontainer - Sidecar - Emptydir Volume - Port-Forwarding

kubectl label pods pod1 team=development #adding label team=development on pod1
kubectl get pods --show-labels
kubectl label pods pod1 team- #remove team (key:value) from pod1
kubectl label --overwrite pods pod1 team=test #overwrite/change label on pod1
kubectl label pods --all foo=bar # add label foo=bar for all pods
kubectl get pods -l "app=firstapp" --show-labels
kubectl get pods -l "app=firstapp,tier=frontend" --show-labels
kubectl get pods -l "app=firstapp,tier!=frontend" --show-labels
kubectl get pods -l "app,tier=frontend" --show-labels #equality-based selector
kubectl get pods -l "app in (firstapp)" --show-labels #set-based selector
kubectl get pods -l "app not in (firstapp)" --show-labels #set-based selector
kubectl get pods -l "app=firstapp,app=secondapp" --show-labels # comma means and => firstapp and secondapp
kubectl get pods -l "app in (firstapp,secondapp)" --show-labels # it means or => firstapp or secondapp

kubectl apply -f podnode.yaml
kubectl get pods -w #always watch
kubectl label nodes minikube hddtype=ssd #after labelling node, pod11 configuration can run, because node is labelled with hddtype:ssd

kubectl apply -f podannotation.yaml
kubectl describe pod annotationpod
kubectl annotate pods annotationpod foo=bar #imperative way
kubectl delete -f podannotation.yaml

kubectl get pods --namespaces kube-system # get all pods in the kube-system namespaces
kubectl get pods --all-namespaces # get pods from all namespaces
kubectl create namespace development # create new development namespace in imperative way
kubectl get pods -n development # get pods from the development namespace

kubectl apply -f namespace.yaml
kubectl get pods -n development #get pods in the development namespace
kubectl exec -it namespacedpod -n development -- /bin/sh #run namespacepod in development namespace
kubectl config set-context --current --namespace=development #now default namespace is development
kubectl get pods #returns pods in the development namespace
kubectl config set-context --current --namespace=default #now namespace is default
kubectl delete namespaces development #delete development namespace
kubectl create deployment firstdeployment --image=nginx:latest --replicas=2
kubectl get deployments
kubectl get pods -w #on another terminal
kubectl delete pods <oneofthepodname> #we can see another terminal, new pod will be created (to keep 2 replicas)
kubectl scale deployments firstdeployment --replicas=5
kubectl delete deployments firstdeployment
Goto the Scenario: LAB: K8s Deployment - Scale Up/Down - Bash Connection - Port Forwarding

kubectl set image deployment rolldeployment nginx=httpd:alpine --record # change image of deployment
kubectl rollout history deployment rolldeployment #shows record/history revisions
kubectl rollout history deployment rolldeployment --revision=2 #select the details of the one of the revisions
kubectl rollout undo deployment rolldeployment #returns back to previous deployment revision
kubectl rollout undo deployment rolldeployment --to-revision=1 #returns back to the selected revision=1
kubectl rollout status deployment rolldeployment -w #show live status of the rollout deployment
kubectl rollout pause deployment rolldeployment #pause the rollout while updating pods
kubectl rollout resume deployment rolldeployment #resume the rollout if rollout paused
Goto the Scenario: LAB: K8s Rollout - Rollback
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Goto the Scenario: LAB: K8s Service Implementations (ClusterIp, NodePort and LoadBalancer)
Goto the Scenario: LAB: K8s Liveness Probe


Goto the Scenario: LAB: K8s Creating Pod - Declarative Way - Environment Variable
spec:
containers:
- name: sidecar
image: busybox
command: ["/bin/sh"]
args: ["-c", "sleep 3600"]
volumeMounts: # volume is mounted under "volumeMounts"
- name: cache-vol # "name" of the volume type
mountPath: /tmp/log # "mountPath" is the path in the container.
volumes:
- name: cache-vol
emptyDir: {} # "volume" type "emptydir"
Goto the Scenario: LAB: K8s Multicontainer - Sidecar - Emptydir Volume - Port-Forwarding
apiVersion: v1
kind: Pod
metadata:
name: hostpath
spec:
containers:
- name: hostpathcontainer
image: ImageName # e.g. nginx
volumeMounts:
- name: directory-vol # container connects "volume" name
mountPath: /dir1 # on the container which path this volume is mounted
- name: dircreate-vol
mountPath: /cache # on the container which path this volume is mounted
- name: file-vol
mountPath: /cache/config.json # on the container which file this volume is mounted
volumes:
- name: directory-vol # "volume" name
hostPath: # "volume" type "hostpath"
path: /tmp # "path" on the node, "/tmp" is defined volume
type: Directory # "hostpath" type "Directory", existed directory
- name: dircreate-vol
hostPath: # "volume" type "hostpath"
path: /cache # "path" on the node
type: DirectoryOrCreate # "hostpath" type "DirectoryOrCreate", if it is not existed, create directory
- name: file-vol
hostPath: # "volume" type "hostpath"
path: /cache/config.json # "path" on the node
type: FileOrCreate # "hostpath" type "FileOrCreate", if it is not existed, create file

kubectl create secret generic mysecret2 --from-literal=db_server=db.example.com --from-literal=db_username=admin --from-literal=db_password=P@ssw0rd!
kubectl create secret generic mysecret3 --from-file=db_server=server.txt --from-file=db_username=username.txt --from-file=db_password=password.txt
kubectl create secret generic mysecret4 --from-file=config.json
Goto the Scenario: LAB: K8s Secret (Declarative and Imperative Way)
Goto the Scenario: LAB: K8s Config Map
With node affinity, specific pods can enable to run on the desired node (Node selector also supports that feature, but node affinity is more flexible).
If node is labelled with key-value, we can run some of the pods on that specific node.
Terms for Node Affinity:
For a better understanding, please have a look LAB: K8s Node Affinity
Go to the Scenario: LAB: K8s Node Affinity
apiVersion: v1
kind: Pod
metadata:
name: frontendpod
labels:
app: frontend # defined labels
deployment: test
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: cachepod
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # required: if not found, not run this pod on any node
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname # run this pod with the POD which includes "app=frontend" on the same worker NODE
preferredDuringSchedulingIgnoredDuringExecution: # preferred: if not found, run this pod on any node
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: branch
operator: In
values:
- develop
topologyKey: topology.kubernetes.io/zone # run this pod with the POD which includes "branch=develop" on the any NODE in the same ZONE
podAntiAffinity: # anti-affinity: NOT run this pod with the following match ""
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: deployment
operator: In
values:
- prod
topologyKey: topology.kubernetes.io/zone # NOT run this pod with the POD which includes "deployment=prod" on the any NODE in the same ZONE
containers:
- name: cachecontainer # cache image and container name
image: redis:6-alpine


Goto the Scenario: LAB: K8s Taint-Toleration
Goto the scenario: LAB: K8s Daemonset - Creating 3 nodes on Minikube
# Creating Persistent Volume on NFS Server on the network
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysqlpv
labels:
app: mysql # labelled PV with "mysql"
spec:
capacity:
storage: 5Gi # 5Gibibyte = power of 2; 5GB= power of 10
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle # volume is not deleted, all data in the volume will be deleted.
nfs:
path: /tmp # binds the path on the NFS Server
server: 10.255.255.10 # IP of NFS Server

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysqlclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem # VolumeMode
resources:
requests:
storage: 5Gi
storageClassName: ""
selector:
matchLabels:
app: mysql # choose/select "mysql" PV that is defined above.

Goto the scenario: LAB: K8s Persistant Volume and Persistant Volume Claim
# Storage Class Creation on Azure
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standarddisk
parameters:
cachingmode: ReadOnly
kind: Managed
storageaccounttype: StandardSSD_LRS
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysqlclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
storageClassName: "standarddisk" # selects/binds to storage class (defined above)
Goto the scenario: LAB: K8s Stateful Sets - Nginx
spec:
parallelism: 2 # each step how many pods start in parallel at a time
completions: 10 # number of pods that run and complete job at the end of the time
backoffLimit: 5 # to tolerate fail number of job, after 5 times of failure, not try to continue job, fail the job
activeDeadlineSeconds: 100 # if this job is not completed in 100 seconds, fail the job

Goto the scenario: LAB: K8s Job
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
#
# https://crontab.guru/
# Examples:
# 5 * * * * : (means) For every day start at minute 5: 00:05 - Second day 00:05 ....
# */5 * * * * : (means) At every 5th minute: 00:05 - 00:10 - 00:15 ...
# 0 */2 * * * : (means) At minute 0 pass every 2d hour: 00:00 - 02:00 - 04:00 ...
# "*" means "every"
# "/" means "repetitive"
spec:
schedule: "*/1 * * * *" # At every 1st minute: 00:01 - 00:02 ...
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command: # start shell and echo
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

Go to the scenario: LAB: K8s Cron Job
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"] # "services", "endpoints", "pods", "pods/log" etc.
verbs: ["get", "watch", "list"] # "get", "list", "watch", "create", "update", "patch", "delete"

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: username@hostname.net # "name" is case sensitive, this name was defined while creating .csr file
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: DevTeam # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

(ref: Kubernetes.io)
# Simple Ingress Object Definition
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
Goto the scenario: LAB: K8s Ingress
# if working on minikube
minikube addons enable dashboard
minikube addons enable metrics-server
minikube dashboard
# if running on WSL/WSL2 to open browser
sensible-browser http://127.0.0.1:45771/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/


Goto the scenario: LAB: Enable Dashboard on Real Cluster
Goto the scenario: LAB: HELM Install & Usage
Goto the scenario: LAB: Helm-Jenkins on running K8s Cluster (2 Node Multipass VM)
Goto: Helm Commands Cheatsheet
Goto: Kubernetes Commands Cheatsheet
Goto: Helm Commands Cheatsheet
Goto: LAB: K8s Kubeadm Cluster Setup
Goto: LAB: K8s Monitoring - Prometheus and Grafana
Goto: LAB: Enable Dashboard on Real K8s Cluster
249 followers · starred Sep 2023
32 followers · starred May 2022
419 followers · starred May 2026
46 followers · starred Aug 2023