-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathK8 Mumshad
1206 lines (952 loc) · 64.9 KB
/
K8 Mumshad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Purpose of K8 is to host application in form of conatainer in an automated fashion so that you can easily deploy as many instances of your application as required.
K8 cluster is set of nodes.
Cluster Architecture
========================================================================================================================================================================
Worker Node:- Are the ships which can load conatiner.
Master Node:- Manage K8 cluster.Store information regarding different nodes etc.It does this using controlled plained components.
There are many containers loaded in ship so you need to maintain information about what container loaded on which ship,at what time ?
This is stored in highly available key store known as ETCD.It db which stored infor in key-value format.
Schedular: It identifys a right node to place a conatiner based on containers resource requirement,etc.
kube-apiserver: It enables communication between various componets of cluster.Its responsible for orchestration all operation in cluster.It expose api used by external
to perform manegenet operation in cluster.
kublet is the caption of this Ship.It an agent that runs on each node in a cluster.It listen intructions from kube-api server and create or destrys conainers based
on that.
kube-proxy: communication between worker nodes are enabled by kube-proxy service.This ensure necessary rules inplace on worker node to allow conatiner running on them
to reach each other.
Root directory is registry.
ETCD (port 2379)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Its is a distributed reliable key-value store that is Simple,Secure and Fast.key-value store data inform of document.
To install ETCD
1. Download binary
2. Extract
2. Run ETCD service
ETCD in K8 stores info on.Any change made in ETCD cluster is stored in this database
1. NOdes
2. PODS
3. Configs
4. Secrets
5. Accounts
6. Roles
7. Bindings
8. Others
Kube API Server:- Primary maneger in k8.When you run kubectl command.kubecontol utility reaches API server,it then validates the request and retrives data from ETCD
cluster and respond back.
1. Authenticate user
2. Validate request
3. Retrieve Data
4. Update ETCD
5. Schedular
6. kubelet
kube controller Manager:- It cntinously monitor the state of various components in K8 cluster.It has node controller which takes status of node every 5 seconds.
It marks node as unhealthy if it doesnot recievs hearbest in 40 seconds.Next controller is replication controller whic monitors the status of replica sets nad make
sure desired number of pods availabe at any given time.
Kube Schedular:- This is reponsible for deciding which POD goes on which node.It doesnot actually place the POD on node its job of kubelet.It identifies nodes based
on CPU,Memory requirement etc
kubelet:- This like captin on ship which leads all activities.Kublet in worker node register it with the K8 cluster.When it recieves intruction to load a POD on node it
request container runtime engine maybe docker to pull image and run.Kublet then monitors the sate of POD and conatiners in it and reports to kube api server on timely
basic.kubeadm does not automatically deploy kublet unlike other components.You have to manually deploy kubelet on worker nodes.
kube proxy:- Within K8 cluster every POD can reach every other POD this can be accomplish by deploying POD networking solution to the cluster.POD network is internal
network that expands across all nodes in cluster to which all PODS connected.Through this network they are able to communicate with each other.
Suppose i have web application in POD1 and DB conatiner in POD2.Yes we can use the IP of DB to access it from web application in POD1.But that is not proper way as
IP may change.FOr this best way is to expose the DB with a service.This service also gets IP.Whenever web-app tries to reach service it forwards traffic to DB.
This service will not join the POD network as it not container.kube proxy is process that runs on each node in K8 cluster its job is to find every time a new service is
created its job is to crate a approprite rule on each node to forward traffic to backend pod (db).
POD:- COntainers are encapsulated in K8 object known as POD which then deployed on worker Node.POD is instance of application.Its smallest object you can create in K8.
When we want to scale we create new POD with same instance of application>if we need more capacity we will create one more POD.POD usually have 1 2 1 relationship with
conatiners running your application.To scale up you create new POD and to scale down we delet POD.We dont add additional container to existing POD to scale up the
application.
A POD has multiple conatiner but not of same kind.Sometime there might be senario that you need helper conatiner which might be doing some task for our web-application
like processing file uploaded by user.You want this conatiner to live alongside your application in that case you can have both conatiner part of same POD.These two
conatiner can communicate using localhost as they share same network space.
$kubectl run nginx
Above command will create a POD and deploy nginx conatiner on it.It pull image from dockerhub here.You can configure K8 to images rom dockerhub.
$kubectl get pods -----> to list pods
pod-defination.yaml ----> It has below 4 sections
apiVersion: v1 {string}
kind: Pod {string}
metadata: {dictionary}
name: myapp-pod
labels:
app: myapp
spec:
containers {list/array}
- name: nginx-conatiner {- --> indicates first item in list}
image: nginx
apiversion possible values:-
------------------------------------
kind Version
POD v1
Service v1
ReplicaSet apps/v1
Deployment apps/v1
$kubectl create -f pod-defination.yaml ----> to crate POD from YAML
===> Below example of YAML file which creates POD
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
type: fron-end
spec:
containers
- name: nginx-conatiner
image: nginx
- name: backend-conatiner
iamge: redis
Replication Controller:-
It ensures HA.It makes sure that specified number of POD running always.It also helps in sharing the load across multiple PODS i.e load balancing.
Replication Controller and replica Set have same purpose but they are not same.Replication Controller is older which is replaced by replica Set.
Example:-
re-defination.YAML
apiVersion: v1
kind: Replication Controller
metadata: ----> for replication Controller
name: myapp-rc
labels:
app: myapp
type: front-end
spec:
template:
metadata: ----> for PODs
name: myapp-pod
labels:
app: myapp
type: fron-end
spec:
containers
- name: nginx-conatiner
image: nginx
- name: backend-conatiner
iamge: redis
replicas: 3
$kubectl create -f re-defination.YAML
$kubectl get replicationcontroller
===> Above was replication Cntroller.Now we will see replicationSet
replicaset-defination.YAML
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-replicaset
labels:
app: myapp
type: front-end
spec:
template:
metadata: ----> for PODs
name: myapp-pod
labels:
app: myapp
type: fron-end
spec:
containers
- name: nginx-conatiner
image: nginx
- name: backend-conatiner
iamge: redis
replicas: 3
selector: {this is required as replicat set can also manage PODS which are not created in this defination/which are create before this replicaset}
matchLables:
type: front-end
Note:- Selector is also there in Recplication controller as we hv not specified above it will assume the POD label in the defination
===> Incase you want to update no of replicas
$kubectl scale --replicas=6 -f replicaset-defination.YAML
All Commands:-
$kubectl create -f replicaset-defination.yaml
$kubectl get replicaset
$kubectl delete replicaset myapp-replicaset
$kubectl replace -f replicaset-defination.yaml
$kubectl scale --replicas=6 -f replicaset-defination.YAML
Deployment:- This provides the capability to upgrade underlying instances seamlessly,using rolling updates,undo changes as required.We have to create deployemt YAML file.
deployment-defination.YAML
apiVersion: apps/v1
kind: Deployment -----> Only chnage from above
metadata:
name: myapp-replicaset
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: fron-end
spec:
containers
- name: nginx-conatiner
image: nginx
- name: backend-conatiner
iamge: redis
replicas: 3
selector:
matchLables:
type: front-end
$kubectl create -f deployment-defination.yaml
$kubectl get deployments
$kubectl get replicaset
$kubectl get pods
$kubectl get all ==========> to get all K8 objects
Notes:-
1. Create an NGINX Pod
kubectl run --generator=run-pod/v1 nginx --image=nginx
2. Generate POD Manifest YAML file (-o yaml). Don't create it(--dry-run)
kubectl run --generator=run-pod/v1 nginx --image=nginx --dry-run -o yaml
3. Create a deployment
kubectl create deployment --image=nginx nginx
4. Generate Deployment YAML file (-o yaml). Don't create it(--dry-run)
kubectl create deployment --image=nginx nginx --dry-run -o yaml
5. Generate Deployment YAML file (-o yaml). Don't create it(--dry-run) with 4 Replicas (--replicas=4)
kubectl create deployment --image=nginx nginx --dry-run -o yaml > nginx-deployment.yaml
NameSpaces:-
All the objects in K8 will be placed in default Namespace when cluster is setup.K8 also create a set of POD and services for its internal puspose such as those
required by networking solution,DNS service etc to isolate this and prevent anyone from acidentally deleting or modifying services K8 creates them at anothe namespace
created as cluster startup name Kube System.3rd Namespace created by K8 automatically is "kube-public" this is where resources made avilable to all users are created.
We can created our own Namespace as well for example if you want to use your cluster for both dev and production enviroment but at same time isolate resources between
them you can create a different namespace for each of them.Each namespace can have set of Policy which determins who can do what.You can also restrict the namespce
to use only allowed quntity of resources.
DNS will look like below in Namesapace
db-service.dev.svc.cluster.local
Here,
db-service = service name
dev = Namespace
svc = Service
cluster.local = domain
$kubectl get pods ====> Will list PODS only in default Namespace.
$kubectl get pods --namespace=kube-system ===> to fetch from perticular Namespace
$kubectl create -f pod-defination.yaml --namespace=dev {You can put this in YAML file also in metadata section}
===> To change the default namespace to DEV namespace permanently
$kubectl config set-context $(kubectl config current-context) --namespace=dev
$kubectl get pods
$kubectl get pods --all-namespaces ======> To see PODS in all namespaces
compute-quota.YAML
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
pods: "10"
requests.cpu: "4"
requests.memory: 5Gi
limits.cpu: "10"
limits.memory: 10Gi
Services:-
K8 services enable communication between various components within and outside of organization.K8 services helps us connect application together with other applications
or users. K8 service is an object just like POD,replicaset etc.One of its use case is to listen the POD on node and forward request on that POD to a POD running the
web application.This type of service is known as node port service bcoz service listen to a POD on node and forward request to a POD.below are types of services
1. Nodeport service {Port range 30000 to 32767}
2. CLusterIP {here service crate a virtual IP inside cluster to enable communication between different services}
3. Loadbalencer
service-defination.yaml
apiversion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
ports:
- targetport: 80
port: 80
nodeport: 3008
selector: --------> This links service to POD
app: myapp
type: front-end
$kubectl create -f service-defination.yaml
$kubectl get services
ClusterIp:-
A full stack application has different kinds of PODs hosting different part of application like front-end,back-end,redis.What is the best way to establish connectivity
between these services ? IPs could be used but problem is POD can go down anytime and IP will change.So we annot rely on IP address.K8 service can help to group POD
together and provide single interface to access the PODS in a group.Example a service created for backend POD will group all BAckend PODs together and provide a single
interface for other POD to access the service.The request are forwaded to one of the service randomly similarly create additional service for redis and allow the
backend POD to access the redis system through the service.
service-defination.yaml
apiVersion: v1
kind: Service
metadata:
name: back-end
spec:
type: ClusterIP
ports:
- targetPort: 80
port: 80
selector:
app: myapp
type: back-end
$kubectl create -f service-defination.yaml
$kubectl get services
Note:-
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
--dry-run: By default as soon as the command is run, the resource will be created. If you simply want to test your command , use the --dry-run option. This will not
create the resource, instead, tell you weather the resource can be created and if your command is right.
-o yaml: This will output the resource definition in YAML format on screen.
POD
Create an NGINX Pod
$kubectl run --generator=run-pod/v1 nginx --image=nginx
Generate POD Manifest YAML file (-o yaml). Don't create it(--dry-run)
$kubectl run --generator=run-pod/v1 nginx --image=nginx --dry-run -o yaml
Deployment
Create a deployment
$kubectl create deployment --image=nginx nginx
Generate Deployment YAML file (-o yaml). Don't create it(--dry-run)
$kubectl create deployment --image=nginx nginx --dry-run -o yaml
Generate Deployment YAML file (-o yaml). Don't create it(--dry-run) with 4 Replicas (--replicas=4)
$kubectl run --generator=deployment/v1beta1 nginx --image=nginx --dry-run --replicas=4 -o yaml
The usage --generator=deployment/v1beta1 is deprecated as of Kubernetes 1.16. The recommended way is to use the kubectl create option instead.
IMPORTANT:
kubectl create deployment does not have a --replicas option. You could first create it and then scale it using the kubectl scale command.
Save it to a file - (If you need to modify or add some other details)
kubectl run --generator=deployment/v1beta1 nginx --image=nginx --dry-run --replicas=4 -o yaml > nginx-deployment.yaml
OR
kubectl create deployment --image=nginx nginx --dry-run -o yaml > nginx-deployment.yaml
You can then update the YAML file with the replicas or any other field before creating the deployment.
Service
Create a Service named redis-service of type ClusterIP to expose pod redis on port 6379
kubectl expose pod redis --port=6379 --name redis-service --dry-run -o yaml
(This will automatically use the pod's labels as selectors)
Or
kubectl create service clusterip redis --tcp=6379:6379 --dry-run -o yaml
(This will not use the pods labels as selectors, instead it will assume selectors as app=redis. You cannot pass in selectors as an option. So it does not work very
well if your pod has a different label set. So generate the file and modify the selectors before creating the service)
Create a Service named nginx of type NodePort to expose pod nginx's port 80 on port 30080 on the nodes:
kubectl expose pod nginx --port=80 --name nginx-service --dry-run -o yaml
(This will automatically use the pod's labels as selectors, but you cannot specify the node port. You have to generate a definition file and then add the node port in
manually before creating the service with the pod.)
Or
kubectl create service nodeport nginx --tcp=80:80 --node-port=30080 --dry-run -o yaml
(This will not use the pods labels as selectors)
Both the above commands have their own challenges. While one of it cannot accept a selector the other cannot accept a node port. I would recommend going with
the `kubectl expose` command. If you need to specify a node port, generate a definition file using the same command and manually input the nodeport before creating
the service.
Section 3 : Schedulling
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Manual Schedulling:-
If you to schedule a pod manually.Pod-defination have a field called "nodeName" ,this field is not set by default.You dont tipically specify this field when you create
a POD menifest file.K8 add this file automatically.Schedullar goes through all the POD and look for POD which dont have this property set.Those are candidates for
schedulling.Then it identifies the right node for the POD by running schedulling alorithm.Once identified it schedule the POD on the node by setting nodeName property to
namenode.
So if there is no schedular to monitor PODS the PODs continue to be in Pending state so here you can manually assign PODs to node yourself.Without schedular the simpletst
way is to set nameNode filed to name of node while creating POD.POD then assigned to specified node.
Taints And Tolerations:-
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
You can restrict what PODs are placed on what Nodes.Taints And Tolerations have nothing to do with Security.Taints And Tolerations are used to set restrictions on what
PODs can be schedule on a node.When PODs are created K8 schedular tries to place these PODs on available worker Nodes,considering there are no restrictions.
Lets assume we have decicated resources on Node1 for perticular use case or application.We want only the PODs belongs to this application placed on Node1.
For this we prevent Node1 with Taint called blue.By default POds have no Toleration which means unless specified otherwise none of POds can tolerate any Taints.So in
this case node of POds can be placed on Node1 as none can tolerate taint blue.Now we have to enable certain Pods to be placed on the Node1.FOr this we must specify
which POds are tolerant to this perticular Taint.So now lets allow POd "D" to be placed on this Node,so we add toleration to Pod "D".
Taint a Node:-
$kubectl taint nodes node-name key=value:taint-effect
taint-effect can be any of below 3.This effect defines what would happen to POD if they donot tolerate Taint.
1. NoSchedule ===> Means Pods will not be schedule on Nodes
2. PreferNoSchedule ===> Means system will try to avoid place POD on Node but no Garuntee.
3. NoExecute ===> Means new PODs will not be schedule on Node and existing PODs on NOde will be evicted if they donot tolerate Taint.Like incase before Tain applied
for Node.
Example: $kubectl taint nodes node1 app=blue:NoSchedule
Add tolerations to PODS:=
$kubectl taint nodes node1 app= blue:NoSchedule
===> POD defination should be like below
pod-defination.YAML
apiVersion:
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: nginx-conatiner
image: nginx
tolerations:
- key:"app"
operator:"Equal"
value:"blue"
effect:"NoSchedule"
Note:- Taints And Tolerations doesnot tell POD to go to perticular NOde instead it tells Node to only accept PODs with certain tolerations.If your requirement is to
restrict a POD to certain NOde its achived to another concept NOde Affinity.
Note:- K* does not schedule any POD on master Node even though its capable of.Why is that ? When K8 cluster is set a Taint is set on master Node automatically that
prevents any PODS from being scheduled there.
To see this Taint
$kubectl describe node kubemaster | grep Taint
Node Selctors:-
COnsider you have node cluster with 3 nodes,One of the node is with high resources and other two are with less resources.You have different workloads running in your cluster.
Now you want that Data processing workloads that require higher horsepower to the larger node as that is the only Node which will not run out of resources incase job
demands extra resources.But in current default setp any POD can go in any Node.
For this we can set up a limitation in PODs to run only on perticular node.There are two ways to achieve this.
1. Node Selectors {we we cannot provide advanced expression like AND OR in Node Selectors}
2.
For Node selectors we have to label the nodes sung below format
$kubectl label nodes <node-name> <label-key>=<label-value>
$kubectl label nodes node-1 size=Large
===> Now in pod-defination.yaml we habe to specify the Node
pod-definition.yaml
apiVersion:
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: data-processor
image: data-processor
nodeSelector:
size: Large
$kubectl create -f pod-defination.yaml
Node Affinity:-
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Primary feature of Node Affinity is to ensure PODs are hosted on perticular Nodes.
pod-definition.yaml
apiVersion:
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: data-processor
image: data-processor
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoreDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In ===> In operator.here any value Large or Medium accepted to place PODs.Other Operators uses are "NotIn" etc
values:
- Large
- Medium
Node Affinity Types:-
1. requiredDuringSchedulingIgnoreDuringExecution
2. preferredDuringSchedulingIgnoreDuringExecution
===> DuringScheduling is the state where POD does not exist and created for the first time.What if we dont have the Nodes with mentioned labels.Its has values
"Required" and "Preffered".
===> DuringExecution is a state where POD is running and change is made in enviroment that affects node affinity such as change in label of Node.
It has only Value "Ignored" which means PODs will continue to run for any changesAnd node affinity will not impact them once they are schedulled.
Taints And Tolerations Vs Node Affinity
------------------------------------------------------------------------------------------------------------------------------------------------------------------
See vedio lecture 52
Resource Requirements and Limits
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Every POD consumes a set of resources CPU,Memory and disk space.Whenever POD is placed on node it consumes resources of that Node.
As we know K8 schedular decides which node a POD goes to.By default K8 assumes that a POD or conatiner within POD requires 0.5 CPU and 256 MB memory.You can
specify this in POD or conatiner deployment file.
pod-definition.yaml
apiVersion:
kind: Pod
metadata:
name: simple-webapp-color
Labels:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
resources:
requests:
memory: "1Gi"
cpu: 1
limts:
memory: "2Gi"
cpu: 2
===> By default the POD doesnot have any restriction to use CPU .However you can set the limit on PODs.Default limit is 1 CPU to be used from node and
512 MB for memory.If it tries to exceed limit for CPU it cluster throttle and make sure conatiner doesnot use cpu beyond its limit.But this is not the case with
memory container can use more memory than its limits.So if POD tries to consume more memory than its limit constantly POD will be terminated
===> What happens when your POD tries to extend your Limits.You will error like Insufficient CPU.
DeamonSets
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
DeamonSets are like Replicasets which helps to deploy multiple instances if PODs.But it runs one copy of PODs on each node in a cluster.Whenever a new node is added to
cluster a replica of POD is added to that node.And when node is remove POD is removed automatically.DeamonSets ensures one copy of POD is always present in all nodes
of cluster.This is hhelpful if you want to deploy monitoring agent on each node of cluster or a log viewer on each node.
deamon-set-definition.yaml
apiVersion: apps/v1
kind: DeamonSet
metadata:
name: monitoring-deamon
spec:
selector:
matchLabels:
app: monitoring-agent
template:
metadata:
labels:
app: monitoring-agent
spec:
conatiners:
- name: monitoring-agent
image: monitoring-agent
$kubectl create -f deamon-set-definition.yaml
$kubectl get deamonsets
$kubectl describe deamonsets monitoring-deamon
Static PODS
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
We saw earlier that kublet relies on kube-API server for instructions on what PODs to load on its nodes.Which is based on decision made by kube scheduller which was
stored in ETC datastore.But what if there was no kube-API server and no contoller,no ETC.What if there is no master at all.Here what kublet can do as a captian.
Well here kublet can manage a node independantly,in ship we have kublet and docker installed.The one thing that kublet know to do is create PODS we dont have API-server
to provide POD details.By now we know that to create a POD we need details of POD in POD defination file.But do you provide POD defination file to kubelet without
kube-API server ?You can configure the kubelet to read the POD defination file from a directory in a server designated to store information about POD.This direcory is
====> /etc/kubernetes/manfests
====> The kublet periodically checks this directory,reads this file and creates PODs.It will also make sure PODs are alive.If you remove file from this directory POD
is deleted Automatically.
====> Only PODs can be created this way not replicaset etc
$kubectl get pods {This will also show the static PODs}
Static PODs Deamons
-------------------------------------------------------------------------------------------------------
1. Created by kubelet 1. Creatd by kube-API server {DeamonSet COntroller}
2. Deploy COntrol Plan Components as 2. Deploy Monitoring agents,Logging agents and Nodes
Static Pods
3. Ignored by kube scheduler 3. Ignored by kube scheduler
Multiple Schedulers
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
We have seen how default schedular works in K8 cluster.It have algorithm that distributes PODs across nodes evenly as well as it takes into conditions we specify
through Taints and Toleration,Node affinity etc.What if none of this satisfies your need,say you have specific application that requires its componets to be placed on
nodes after performing some additional checks.You decide to have own schedulling alogithm to place PODs on Node,with own custom conditions and checks.
K8 allows you to write your own Schedullar and deploy as default or as an additional schedullar.K8 cluster can have multiple schedular at same time.
===> In pod-defination.yaml we have to specify this schedular under "schedularName"
Section 4 - Logging and Monitoring
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
===> You can have one Metric server in each K8 cluster.Metric server retrieves metrics from each of K8 nodes and PODs.Aggregate them and stores in memory.
Metric-server is only an in-Memory monitoring solution and doesnot store metrix on disk.As a result you cannot see historical performance data.K* runs
an agent on each node know as Kubelet which is responsible for reciving instruction from K8 master server and running PODs on Nodes.The kublet also conatins a
component know as C-advisor.C-advisor is responsible for retrieving performance metrix from PODs and exposing them through kubelet API to make matric available
through metric server.
Section 5 - Application LifeCycle Management
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Rolling Updates and Rollback in Deployments:-
RolleOut and versioning:-
When you first create a deployment it triggers a rollout.A new rollout creates a new deployment revision say revision 1.When the application is updated a new version is
rollout with revision 2.
===>To check the staus of deployment
$kubectl rollout status deployment/myapp-deployment
===>To check history of deployments
$kubectl rollout history deployment/myapp-deployment
Deployment Strategy :-
Say if you have 5 replias of web-application instance deployed.One way to upgrade this to new version is to destroy all of these and then create newer version of the
application instances.Meaning first destrop the 5 instances and then deploy the 5 new versions of the application.But this has application downtime.This is called
Recreate statergy and this is not the default deployment statergy.
===> In second type of statergy we donot destroy all instance at a time.Instead we take down the older version and bring up a newer version one by one.This way the
application never goes down and upgrade is seamless.This is Rolling update stategy.This is default deployment statergy.
Deployment COmmands
--------------------------------------------------------------------------------
Create $kubectl create -f deployment-defination.yaml
get $kubectl get deployments
Update $kubectl apply -f deployments-defination.yaml
$kubectl set image deployment/myapp-deployment nginx=nginx:1.9.1
Status $kubectl rollout status deployment/myapp-deployment
$kubectl rollout history deployment/myapp-deployment
Rollback $Kubectl rollout undo deployment/myapp-deployment
Commands and Arguments in POD defination file:-
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
===> When you run $docker run ubuntu command,it runs instance of Ubuntu image and Exits immidieatly.If you see running container using $docker ps you wont see the
container running.If you see $docker ps -a you will see the stopped conatiner in exited state.But why is so? Unlike virtual machine container are not ment to
host OS they are ment to run a specific task/process such as to host instsnce of webserver/dB etc Once the task is complete conatiner exits.COntainer only live
as long as the process inside it alive.If webservice inside conatiner stops or crashes the container exits.So who defines what process is run within the conatiner.
In dockerfile you will CMD command this defines the program that will run when the consyainer starts.
===> $docker run ubuntu [COMMAND]
$docker run ubuntu sleep 5
With above command when container starts it wait for 5 seconds before it exits.Now how do we make that change permanent?Say you want to run sleep command always
when the container starts.Here is the below way to do it
FROM Ubuntu
CMD sleep 5 or CMD["sleep","5"]
$docker build -t ubuntu-sleeper .
$docker run ubuntu-sleeper
===> Above sleep command also works with ENTRYPOINT statement
FROM Ubuntu
ENTRYPOINT["sleep"]
$docker run ubuntu-sleeper 10 {If you dont specify seconds here you will get error operand is missing}
===> But if you want to configure default time then you have to use both CMD and ENTRYPOINT.
FROM Ubuntu
ENTRYPOINT["sleep"]
CMD["5"]
$docker run ubuntu-sleeper 10 {If you dont specify seconds here it will take 5 seconds}
$docker run --name ubuntu-sleeper \ {To avoid the ENTRYPOINT}
--entrypoint sleep2.0
ubuntu-sleeper 10
===> pod-definition.yaml
apiversion: vi
kind: Pod
metadata:
name: ubuntu-sleeper-pod
spec:
conatiners:
- name: ubuntu-sleeper
image: ubuntu-sleeper
args: ["10"] {sleep time}
$kubectl create -f pod-definition.yaml
Enviroment variables in Kubernetes:-
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
$docker run -e APP_COLOR=pink simple-webapp-color
===> Way to specify enviroment variable in yaml file
pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
env:
- name: APP_COLOR
value: pink
===> The other ways to specify enviroment are
1. Plain key Value
2. ConfigMap
3. Secrets
env:
- name: APP_COLOR
valueFrom:
ConfigMapKeyRef:
OR
env:
- name: APP_COLOR
valueFrom:
secretKeyRef:
Configuring ConfigMaps in Applications:-
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
ConfigMaps are used to pass Configuration data in the form of key value pairs in K8.When POD is created inject the config map in the table so the Key value pair is
available as enviroment variable for the application hosted inside the container in POD.There are two phases involved in configuring Maps
1. Create COnfigMap
2. Inject Them in POD
===> Now there are two ways to create configMaps imerative way and declarative way where we provide configMap defination file.
Imperative way:- $kubectl create configmap
<config-name> --from-literal=<key>=<value>
$kubectl create configmap \
app-config --from-literal=APP_COLOR=blue \
--from-literal=APP_MOD=prod
Declarative way:-
config-map.yaml
apiVersion: v1
kind: CnfigMap
metadata:
name: app-config
data:
APP_COLOR: blue
APP_MODE: prod
$kubectl create -f config-map.yaml
===> To view cnfigMaps
$kubectl get configmaps
==>> ConfigMap in Pods to inject
pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
labels:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
configMapref:
name: app-config {this iss take config Map}
Configure Secrets in Applications
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Here also two ways to specify the secrets Imperative way and Declarative way
1. Imperative way
$kubectl create secret generic
<secret-name> --from-literal=<key>=<value>
$kubectl create secret generic \
app-secret --from-literal=DB_Hosts=mysl \
--from-literal=DB_user=root
2. Declarative way
secret-data.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-data
data:
DB_Host: mysql
DB_User: root
DB_Password: B#c#
$kubectl create -f secret-data.yaml
$kubectl get secrets
$kubectl describe secrets
$kubectl get secrets app-secret -o yaml
===> Pod defination for secret goes below
pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
labels:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: app-secret
InitContainers
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
In a multi-container pod, each container is expected to run a process that stays alive as long as the POD's lifecycle. For example in the multi-container pod that we
talked about earlier that has a web application and logging agent, both the containers are expected to stay alive at all times. The process running in the log agent
container is expected to stay alive as long as the web application is running. If any of them fails, the POD restarts.
But at times you may want to run a process that runs to completion in a container. For example a process that pulls a code or binary from a
repository that will be used by the main web application. That is a task that will be run only one time when the pod is first created. Or a process that waits for
an external service or database to be up before the actual application starts. That's where initContainers comes in.
An initContainer is configured in a pod like all other containers, except that it is specified inside a initContainers section, like this:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
When a POD is first created the initContainer is run, and the process in the initContainer must run to a completion before the real container hosting the application
starts.
You can configure multiple such initContainers as well, like how we did for multi-pod containers. In that case each init container is run one at a time in sequential
order.
If any of the initContainers fail to complete, Kubernetes restarts the Pod repeatedly until the Init Container succeeds
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
Self Healing Applications
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Kubernetes supports self-healing applications through ReplicaSets and Replication Controllers. The replication controller helps in ensuring that a POD is re-created
automatically when the application within the POD crashes. It helps in ensuring enough replicas of the application are running at all times.
Kubernetes provides additional support to check the health of applications running within PODs and take necessary actions through Liveness and Readiness Probes.
However these are not required for the CKA exam and as such they are not covered here. These are topics for the Certified Kubernetes Application Developers (CKAD)
exam and are covered in the CKAD course.
Section 6 : Cluster Maintanence
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
OS Upgrade
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
You have clluster with few nodes and PODs serving application what happens when one of these nodes goes down ? Pods on them wont be accessible depending upon how you
deployed those PODs your users maybe impacted.For example if you have multiple relicas of blue POD the users accessing blue application are not impacted as they are
servered through other blue POD which is online.However user acessing green POD are impacted as that only node where green POd application was running.
Here if the node comeback online then the kubelet process starts and PODs also comes online.However if the node is down for more than 5 mins, then the PODs are
terminated from that Node.K8 considers them as dead.If PODsare part of replicasets then they are created at other nodes.The time it waits for POD to come back online
is know as POD eviction timeout and is set on controller manegar on 5 mins.So whenever a node goes offile the master node wait for 5 mins before considering the node as
dead.When node come online after POD eviction timeout it comesup blank without any PODs.But as blue POD was part of replicaset it was created on another node however
the green POD was not part of replicaset its just gone.
===> So here if you have any maintanance work you can purposefully drain the Node of all workloads.So that workload moved to other node on the cluster.TEchnically they
are not moved when you drain a node the PODs are gracefullt terminated from the node they are on and recreated on another.The node is also marked as unschedullable
meaning no PODs can be schedulled on this node untill you specifically remove the restriction.Now the PODs are safe on other node you can reboot the first node.
When it come back online its still unschedullable you then need to unquarantine so that PODs can be schedull again.
$kubectl drain node-1
$kubectl uncordon node-1
$kubectl cordon node-1 {makes node unschedullable}
===> If kubernetes version is v1.11.3,then
1 - major
11 - minor {functionalities}
3 - patch {bug fixes)
Cluster Upgrade Process
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
===> Since the kube-apiserver is the primary component in the control plane and that is the component that all other components talk to none of the other components
should ever be at higher version than kube-apiserver.Controller maneger and schedullar can be at one version lower so if kube-api server is at x version then
Controller maneger and schedullar can be at x-1 and kublet,kube-proxy can be at two version lower i.e x-2.This is not the case with kube control (kubectl)
It could be at version higher than api-sever or at same level or at lower version.
kube-apiserver
X v1.10
Controlle-manager kube-schedullar kubectl
X-1 X-1
v1.9 or v1.10 v.19 or v1.10
kubelet kube-proxy
X-2 X-2
v1.8 or v1.9 or v1.10 v1.8 or v1.9 or v1.10
===> At any point k8's supports upto recent 3 minor versions so with v1.12 being the latest release k8 will support v1.12,v1.11,v1.10.So when v1.13 is release v1.10 is
unsupported.Recommended to upgrade is to update one minor version at a time.
===> Suppose you have cluster with a master Node and 3 worker Nodes.All at version v1.10.First you upgrade your master node then update worker nodes.While the master
being updated componets such as api-server,schedullar and controller maneger go down briefly.Master going down does not mean that worker and application running
in cluster are impacted all workload hosted on worker nodes continue to serve users as normal since master is down all management functions are down.You cannot
access cluster using kubecontrl or other K8 api.You cannot modify existing application.Controller Manager wont function either.Once upgrade is finished on master