6.1) Kubernetes Detailed Notes
6.1) Kubernetes Detailed Notes
Topic:What is Kubernetes:-
● Kubernetes is a platform that manages container-based applications, their networking
and storage components.
● In Kubernetes, we focus on the application workloads rather than the underlying
infrastructure.
● Kubernetes provides a declarative approach to deployments, backed by a rich set of APIs
for management operations.
● Cluster: Cluster is a collection of compute, storage and networking resources that
Kubernetes uses to run workloads.
● Node: It is a single host. Now we can put the cluster as a collection of nodes.
● Master:
○ Provides core Kubernetes Services and orchestration to application workloads
● Node:
○ run your application workloads
Kubernetes Master
Cluster:
● It is collection of hosts(nodes) that provide compute, memory, storage and networking
resources
● k8s uses these resources to run application workloads.
Master Node:
● The master node is a single host in k8s cluster.
● This can be a physical server or virtual machine
● This is the control plane of k8s. This master is responsible for assigning work (container
workloads) to be scheduled on nodes
● Kubernetes master runs on Linux node
● Master Components has i) kube-apiserver ii) etct iii) kube-scheduler iv) Controller
manager v) Cloud-controller-manager
kube-apiserver
● This component is Central to Kubernetes. All communications between all components
goes through the kube-apiserver
● This component is frontend of the Kubernetes control plane.
● This component exposes a REST API.
● We would interact with this component using kubectl by using the YAML files, which
are also referred as manifests
etcd
● etcd stores the entire configuration and the state of the cluster.
● etcd is a consistent and highly available distributed key-value store.
kube-scheduler
● It watches for new work tasks and assigns them to healthy nodes in the cluster
Controller-Manager
● It is responsible for maintaining desired states mentioned in the manifest.
● It looks like single component, but with in it has
○ Node Controller: for noticing & responding when node goes down
○ Replication Controller: for maintaining the correct number of pods for every
replication controller object.
○ Endpoints Controller: Populates the Endpoints object
Cloud-Controller-manager
● It is responsible for underlying cloud specific controllers.
● If you run the Kubernetes on a supported cloud platform such as AWS, Azure or Google,
your control plane runs the Cloud-Controller-Manager.
Node Components
Nodes:
● It is a single host in k8s cluster
● This can be physical server or virtual machine
● These are managed by k8s master and they do the work of executing workloads in k8s
(They were referred as minions)
● Node is responsible for doing the work assigned.
kubelet
Container Runtime
● This is software which is responsible for running containers.
● Some of them are Docker, containerd, cri-o, rktlet
kube-proxy
● Maintains the network rules on nodes
● This is responsible for networking on nodes.
Cluster DNS
● Every Kubernetes Cluster has an internal DNS service
● This has static IP address that is hardcoded into every Pod on the cluster i.e. all Pods
now how to find the DNS Server
● Services, Stateful Sets and Pods are registered with Cluster DNS.
● Cluster DNS is based on CoreDNS
Interesting ADD ONS
Web UI (Dashboard)
● Web based Kubernetes user interface
● Capabilities:
○ Deployment
○ View cluster resources
○ Troubleshooting
Pods:-
● A pod is a unit of work in k8s.
● Each pod contains one or more containers.
● Every pod gets a unique ip address and the containers in the pod have the same ip
address.
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
Then you can join any number of worker nodes by running the following on each as root:
● As mentioned above if we execute “kubeadm init” it will display like above we need to
execute below commands as normal users
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
● After that as mentioned in the lines go to the url. This url contain network drivers and
that drivers installation commands
{https://kubernetes.io/docs/concepts/cluster-administration/addons/}
● Generally we have network drivers like Flannel,kniter,Romana..etc in above we have
selected weave-network
● I wish to install “weave-network” so we will go to the installation they will give the
command
● For install weave-wetwork -network driver we need to execute {kubectl apply -f
"https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"}
● Then join the worker node by following command for ex
5) kubectl describe pod gol-pod {It will describe entire pod details}
6) kubectl port-forward --address 0.0.0.0 <pod-name> source port(the port where the pod is
running):destination port(port where we have to expose the pod)
NOTE:- To know the pod is running on which port etc details execute
“kubectl describe <pod-name>” . When ever we do port-forward, default it will try to map on
loopback adapter which will work when we are in local machine but whenever you are
working on remote machines especially in cloud don’t forget to put ‘0.0.0.0’
9) kubectl exec -it <pod-name> -- /bin/bash {TO get inside the docker container }
10) kubectl top nodes {to see the metrics of nodes} && kubectl top pods {to see the
metrics of pods}
11) kubectl get rs {to view the replica-set}
20) kubectl get pods --selector=”app=<name>” {to view the particular pods with selected
name/label}
24) kubectl get namespaces (or) kubectl get ns {To view all name-spaces}
25) kubectl get sts {to get statefuset}
Kubernetes Objects
● K8s object is anything which can be stored in etcd, As a key-value pair.
● k8s objects are persistent entities in the k8s system.
● These objects are used to represent the state of your cluster
● Every k8s object has
○ Specification: This is also referred as object Spec
○ Status: This is also referred as object status
● How can we describe a k8s object (Specification):
○ K8s objects can be describe in the json format using k8s rest api or in yaml format
via kubectl
○ For api version Refer Here
○ Every k8s object can be described using .yaml (specification) or json when using a
rest api and passed across to the kube-api server via kubectl or k8s REST API.
The cluster responds back with status
○ While describing object spec, we will have some required fields
■ apiVersion: Which version of k8s api are you using to create this object
■ kind: what kind of k8s object do you want to create
■ metadata: Data which is helpful in uniquely identifying the object, here we
will be have name, UID and optional namespace
■ spec: What is your desired state
K8s Workloads
name: gameoflife
spec:
containers:
- image: qualitythought.in/gameoflife:07112020
- image: qualitythought/gameoflife:07112020
name: gol
ports:
- containerPort: 8080
● Accessing your pod: {if we can observe the pod ip address and node ip address is
different also those are in two different networks. So to access that pod we need to map
the ip to port “kubectl port-forward --address 0.0.0.0 gameoflife 8080:8080”}
K8s Pods
● Pods are the atomic unit of computing that you create in k8s
● A pod represents an application/microservice running in k8s cluster.
● Pods will have containers in it.
● Each container within a pod runs its own cgroup, but they share a number of Linux
namespaces like network, mnt, UTS, IPC, etc.
● These namespaces are for pods. Not for containers.
Imperative:
● We can create objects by executing commands Refer Here
Declarative:
Resource Management:
● Resource Requests for Minimum required resources and maximum limits Refer Here
● https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
● Refer Here for resource limits in a pod.
containers:
- image: qualitythought/gameoflife:07112020
name: gol
resources:
requests:
cpu: "500m"
memory: "128Mi"
limits:
cpu: "1000m"
memory: "512Mi"
ports:
- containerPort: 8080
name: golhttpport
protocol: TCP
protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
name: gameoflife
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol
resources:
requests:
cpu: "500m"
memory: "128Mi"
limits:
cpu: "1000m"
memory: "512Mi"
ports:
- containerPort: 8080
name: golhttpport
protocol: TCP
- image: httpd
name: httpd
ports:
- containerPort: 80
name: httpport
protocol: TCP
EX:-
● now we create 4 objects 2 for replica set in dev environment and test environment. And
2 for services like dev environment and test environment.
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: gol-dev
spec:
minReadySeconds: 10
replicas: 2
selector:
matchLabels:
app: gol
env: dev
template:
metadata:
labels:
app: gol
env: dev
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol-dev
ports:
- containerPort: 8080
protocol: TCP
################################################################
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: jenkins-qa
spec:
minReadySeconds: 10
replicas: 2
selector:
matchLabels:
app: jenkins
env: qa
template:
metadata:
labels:
app: jenkins
env: qa
spec:
containers:
- image: jenkins:2.60.3
name: jenkins-qa
ports:
- containerPort: 8080
protocol: TCP
#################################################################
● In the below example in the field of ports.
---
apiVersion: v1
kind: Service
metadata:
name: gol-dev
spec:
type: NodePort
selector:
app: gol
env: dev
ports:
- targetPort: 8080
port: 8080
nodePort: 32766
##########################################################
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-test
spec:
selector:
app: jenkins
env: qa
type: NodePort
ports:
- targetPort: 8080
port: 8080
nodePort: 32765
#############################################################
Topic: Kubernetes Networking Model (KNM)
● KNM requirements are
○ all pods can communicate with all other pods without using NAT
○ all Nodes can communicate with all Pods without NAT
○ the IP that Pod sees itself is the same IP that other see it as
● Lets understand the following
○ Container to Container networking
○ Pod-to-Pod Networking
○ Pod-to-svc networking
○ Internet to SVC networking
Container to Container Networking
● Pods on different nodes, as shown in the below pic, pod1 was trying to communicate
with pod4 in node-2.
● For that it will send a packet to eth0 and request will reach to ‘container bridge’ then the
bridge will call out for destination ip. If it doesn’t get any response from its own node it
will communicate to the external network.
● Basically all nodes are connected via a network. And all the node ethernet will consist of
its container's CIDR range. So that it is easy to find out ip of nodes.
● In that pool the matched CIDR node will respond and the packet will reach the
destination node. The node-bridge will take that packet to destination pod in this case
pod4
● Pod to Service IP Address , Hear pod1 wants to communicate to service1
● As same as above concepts the packet is reached to eth0 → cb0→ here it will
communicate to ‘iptables’ entries
● Because service is an iptable entry that's why service doesn’t fail. So here this entry will
tell that svc1 means pod4
● Then the packet will reach to destination
● From external world to service, request comes to eth0 then it will check in iptables and
as we know all service entries are in iptables and then the request is forwarded to that
particular service
---
apiVersion: v1
kind: Pod
metadata:
name: gameoflife
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol
livenessProbe:
httpGet:
path: /gameoflife
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 10
failureThreshold: 3
resources:
requests:
cpu: "500m"
memory: "128Mi"
limits:
cpu: "1000m"
memory: "512Mi"
ports:
- containerPort: 8080
name: golhttpport
protocol: TCP
Topic:- Activities
Activity: 1:-
Lets create a pod with the below yaml file.
---
apiVersion: v1
kind: Pod
metadata:
name: gol-pod
spec:
containers:
- name: my-gol-cont
image: qualitythought/gameoflife:07112020
ports:
- containerPort: 8080
Activity:2:-
Topic: Namespaces
● K8s is one physical cluster with k8s master and cluster nodes & in this cluster if you
want to create multiple virtual clusters (like one for dev, staging, qa..) we can use
namespaces.
● Execute kubectl api-resources. The resource with value namespaced
○ true => will be created per namespace {It means when we create two namespaces
that will be different. }
○ false => will be same/shared across namespaces {if it is false across name-spaces
or virtual clusters you can’t have different name spaces or nodes. Nodes are same
across virtual clusters}
● Generally kubectl command will pull the values from namespace default. If you want
k8s to fetch the information from other namespaces use –namespace flag
NOTE:- If we need to k8s will pull the values from some particular name-space, Then you can
set something called as context (context is nothing but some values stored in kubectl config file
~/.kube/config)
Upgrading
● Upgrading to published versions is easier in the cloud.
○ In AKS, we can upgrade the nodepools and k8s seperately
○ In the case of eksctl
Topic: Storage in K8s
● Both containers & Pods are ephemeral (when we delete the Pods/Containers data
generated is deleted)
● Docker Volume separates storage from the life cycle of Container, So even if the
container is deleted, data will still be available.
● Since Docker containers are created in the Pod, and the problem of storage has to be
solved at Pod level in k8s as Pod provides kernel namespace to docker container.
● Pod has a container. The container in the pod stores the data and let's assume it is
crashes, Pod will try to restart the container and in this case data will be lost. The new
container will start with empty disk space allocated.
● Volume is exposed to the applications which eventually store data on any type of storage
(node/cloud).
● Lifetime of k8s volume is the same as the Pod’s lifetime. As long as Pod is alive the
containers within POD will get the same volume across restarts or new container
Creation.
● How to use K8s Volume
○ Volume is defined in Pod Spec
○ Apply the k8s pod manifest with empty volume
---
apiVersion: v1
kind: Pod
metadata:
name: pod-with-emptydir
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol-container
volumeMounts:
- mountPath: /tmp
name: tmp-volume
volumes:
- name: tmp-volume
emptyDir: {}
● Refer Here for official docs
{https://kubernetes.io/docs/concepts/storage/volumes/}
● Lets use one more example of hostPath (Type of volume) Refer Here
---
apiVersion: v1
kind: Pod
metadata:
name: pod-with-hostpath
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol-container
volumeMounts:
- mountPath: /tmp
name: tmp-volume-host
volumes:
- name: tmp-volume-host
hostPath:
path: /tmp
type: Directory
● Volumes such as emptyDir and hostPath get deleted when the pod using them is deleted
or the pod is restarted. So we need to find a solution Where the data/storage lifetime is
different than Pod’s lifetime
● To Solve this Problem, K8s has Persistent Storage in the form of Persistent Volume
(PV).
Topic: Persistent Volumes & Persistent Volume Claims
● A PV is a K8s object that represents a block of storage in the cluster. This can be
provisioned before hand by cluster admins or be dynamically provisioned.
● In Order to use PV, a Persistent Volume Claim (PVC) needs to be created. A PVC is a
request for storage by user or by Pod. This request can be of specific size or specific
access mode.
● Each PV belongs to a certain storage class. A Storage Class is a K8s Object that provides
a way for administrators to describe different types of Storage.
● Volume mode has two Values Block, FileSystem
● Access Modes:
○ ReadWriteOnce (RWO): Mounted as read-write by a single node
○ ReadOnlyMany (ROX): Mounted as read-only by many nodes
○ ReadWriteMany (RWX): Mounted as Read-write by many nodes
● persistentVolume Reclaim Policy
○ Retain (Even if u delete your persistent volume the data will still be there )
○ Recycle (when we delete your persistent volume the store will be there but the
data in the storage will be cleaned )
○ Delete (when ever we delete the persistence volume the storage/volume and data
in that volume will be deleted)
PVC in Azure
● Dynamic Provision Azure Disk Refer Here Azure Files Refer Here
● Static Provision Azure Disk Refer Here Azure Files Refer Here
● NFS in Azure Refer Here
● Azure Netapp Refer Here
● AWS Refer Here
● Refer Here for AWS Storage Classes Documentation
Activity:
● Now let's create a ‘my-sql’ container, my-sql is a database so it require some kind of
storage, so we will create a pod in that we will create a my-sql,
● Lets understand how to use mysql container in a Pod with Persistent Volume (in AWS
and Azure)
● Refer Here to mysql Dockerfile which has volume at /var/lib/mysql
In azure:
● Lets use existing storage classes in Azure to create mysql-pod Refer Here
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-azure-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: managed-premium
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: mysql-azure
spec:
containers:
- name: mysql-cont
image: mysql:8
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-volume
env:
- name: MYSQL_ROOT_PASSWORD
value: 'rootroot'
- name: MYSQL_DATABASE
value: 'openmrs'
- name: MYSQL_USER
value: qtdevops
- name: MYSQL_PASSWORD
value: qtdevops
ports:
- name: mysqlport
containerPort: 3306
protocol: TCP
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: mysql-azure-pvc
In AWS:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc-aws
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: mysql-pvc-aws
spec:
containers:
- name: mysql-cont
image: mysql:8
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-volume
env:
- name: MYSQL_ROOT_PASSWORD
value: 'rootroot'
- name: MYSQL_DATABASE
value: 'openmrs'
- name: MYSQL_USER
value: qtdevops
- name: MYSQL_PASSWORD
value: qtdevops
ports:
- name: mysqlport
containerPort: 3306
protocol: TCP
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: mysql-pvc-aws
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: gol-rs
spec:
minReadySeconds: 5
replicas: 2
template:
metadata:
labels:
app: gol
version: "07112020"
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol
ports:
- containerPort: 8080
● Now lets add selector for the labels
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replocatio-set
spec:
replicas: 2
minReadySeconds: 10
template:
metadata:
labels:
app: gol
version: "1.1"
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol
ports:
- containerPort: 8080
selector:
matchLabels:
app: gol
version: "1.1"
● apply the replica set and explore
● kubectl get rs - to view the replica-set
● kubectl describe rs replication-set - to describe the replication set
● when ever we need to scale the replicas is in two ways i) chaining the yaml file ii) using
auto scaling imperative commands
● Giving any pod ip address to access the application is not good caz any pod can be killed
any time and any pod can create at any time.
● As k8s is used and application microservices run in the cluster, the number of pods
running of nodes might grow in size and complexity.
● As shown in the below pic orange circled pods are belongs to one service for ex web
server, Black circled pods are belongs to another service for ex app server..etc.,
● K8s has added foundational concepts of Labels and annotations to organization, mark
and cross-index all of your resources to represent the groups.
● Labels are key/value pairs that can be attached to k8s objects such as pods and
ReplicaSets. Labels are used by k8s cluster to group pods/other objects
● _Annotations provide storage mechanism similar to labels which information that can be
used by tools & libraries
● Labels provide identifying metadata
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: gol-rs-label
spec:
minReadySeconds: 10
replicas: 5
selector:
matchLabels:
app: gol
template:
metadata:
labels:
app: gol
version: "07112020"
spec:
containers:
- image: qualitythought/gameoflife:07112020
name: gol
ports:
- containerPort: 8080
protocol: TCP
---
selector:
matchLabels:
app: jenkins
---
selector:
matchExpressions:
- {key: app, operator: In, values: ['jenkins', 'gol']}
---
selector:
matchExpressions:
- {key: ver, operator: NotIn, values: ['1.0', '2.0']}
Service Discovery
● We are able to run our applications in pods
● We can dynamically scale pods by using autoscale command
● How do i access my application which is running in pods
● Service-discovery helps solving the problem of finding which processes are listening at
which address for each service.
● We need to expose our services to the external world. As of now w.r.t networking we
know each pod is having its own ip address.
---
apiVersion: v1
kind: Service
metadata:
name: gol-dev
spec:
type: LoadBalancer
selector:
app: gameoflife
ports:
- targetPort: 8080
port: 80
● Follow the complete application creation in k8s Refer Here
Topic:- K8s Jobs and CronJobs
● Let's assume you want to run a Pod which runs a task and then terminates gracefully, To
solve these kind of Problems k8s has Jobs & CronJobs
● The difference b/w k8s job & CronJob is CronJobs can be scheduled to run on a
particular time frame
● Run the job as mentioned in the changeset Refer Here
---
apiVersion: batch/v1
kind: Job
metadata:
name: one-time-job
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: ubuntu-container
image: ubuntu
args:
- /bin/bash
- -c
- sleep 10m
Topic: K8s Ingress
● Ingress is an object in k8s that is used manage external access to services in
the k8s cluster. Ingress provides layer 7 load balancing, so it will be aware
of url’s
● Refer Here {https://docs.microsoft.com/en-us/azure/aks/ingress-basic}
Scenario:
● I have a application component which is running in a pod
● I have a database pod
● Application Pod is configured to scale automatically
● Now application pod needs to access db
● Approach 1:
○ Create a service for db
● Whenever you add a service an environmental variables will be added in all pods
containing svc ip and port
Approach 2:
● Use a Config Map. Config Map is a k8s object that allows us to define the
application-related data.
● Config maps are key value pairs
● You can create config maps from
○ literal value
○ file
○ directory
● Lets create a sample config map
---
apiVersion: v1
kind: Pod
metadata:
name: configmapdemo
spec:
containers:
- name: configmapdemo
image: alpine
command: ["/bin/bash", "-c", "sleep 1d"]
envFrom:
- configMapRef:
name: demovalue-map
NOTE:- In K8s we also have secret which are much like config maps but they can store secret
of size 1kb in base 64 encoded form
Topic: Helm
● Helm is a Package manager for k8s
● Helm charts represent a k8s package
● Installing helm Refer Here
● Lets execute an example using helm in AKS Refer Here
● In k8s we write yaml manifests, helm simplifies and makes manifests reusable
● Refer Here
● Journey of App from docker to k8s Refer Here