-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathKubernetes Basics.txt
1235 lines (883 loc) · 37 KB
/
Kubernetes Basics.txt
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
Kubernetes is an open source system for automating deployment, scaling, and management of containerized applications.
At heart it is a "container orchestration" tool
With containers we can run a variety of software components across a "cluster" of generic servers; instead of running a component on (1) server and if it dies we lose everything we can have a cluster and we can distribute the components (High Availabity)
We can also scale based on resource needs
Server Server
Pod (Container) Pod (Container)
Pod (Container) Pod (Container)
Pod (Container) Pod (Container)
Kube Master
------------
Docker // container runtime
Kubeadm // automates cluster setup
Kubelet // agent that manages processes
Kubectl // CLI tool to interact w/ the cluster
Control Plane // cluster controller
Kube Node (n)
--------------
Docker
Kubeadm
Kubelet
Kubectl
"Pods" are the smallest atomic unit (like cells) in the Kubernetes ecosystem. They consist of
one or more containers, storage resources, and have a unique IP in the cluster network
Node
Pod (10.244.0.1)
Container1
Node
Pod (10.244.0.2)
Container1
Container2
Control Node
------------------
kube-api-server
other core components
Worker Node
-----------------
kubelet
kube-proxy
Pod
Pod
KIND 3-Node Cluster Setup (DEV)
--------------------------------------------
kind create cluster --name lowk8s --wait 5m --config kind-multi-node.yaml (in ~/.kube)
kind delete cluster --name lowk8s
kubectl create deployment autodor --image=lwooden/testrun:firstry
kubectl get deployments
kubectl get pods
kubectl describe pod <POD NAME>
kubeclt describe service <deployment name>
kubectl expose deployment autodor --type=Loadbalancer --port 8080 // does not work
To test connectivity to a application I have to:
- find out what node the deployment was assigend to
- ssh to that node
- curl http://<NODE-IP>:<PORT>/ping
Kubeadm 3-Node Cluster Setup
--------------------------------------------
AWS EKS 1-Node Cluster Setup (DEV)
----------------------------------------------
eksctl create cluster --name=lowk8 --nodes=1 --node-type=m5.large --zones=us-east-1a,us-east-1b
aws eks update-kubeconfig --name <CLUSTER_NAME> // updates kube-config w/ credentials
eksctl delete cluster --region=us-east-1 --name=lowk8
// Accessing AWS Services Via Pods
IRSA - IAM Roles for Service Accounts (Available on High-Side)
- require OIDC Provider setup
- would need to be setup per cluster
eksctl utils associate-iam-oidc-provider --region=us-east-1 --cluster=lowk8 --approve
Pod Identity (Not Available on High-Side)
- does not require OIDC Provider setup
- require pod identity add-on to be running in the cluster
- require association via the aws-cli/eksctl (aws eks create-pod-identity-association --cluster-name my-cluster --role-arn arn:aws:iam::111122223333:role/my-role --namespace default --service-account my-service-account)
eksctl create addon --name eks-pod-identity-agent --cluster lowk8
eksctl create addon --name aws-ebs-csi-driver --cluster lowk8
eksctl update addon -f ebsPodIdentityConfig.yaml // with podIdentity setup
eksctl get podidentityassociation --cluster lowk8 --output json // check pod identity association
Azure AKS 1-Node Cluster Setup (DEV)
----------------------------------------------
deploy resource group, vnet, subnets, etc using pulumi
az aks create --resource-group lowsandbox-dev-rg --name lowk8-aks --node-count 1 --enable-addons monitoring --generate-ssh-keys
az aks create -n lowk8-aks -g lowsandbox-dev-rg --network-plugin azure --enable-managed-identity -a ingress-appgw --appgw-name aks-ingress-gateway --appgw-subnet-cidr "10.225.0.0/16" --node-count 1 --generate-ssh-keys
az aks get-credentials --resource-group lowsandbox-dev-rg --name lowk8-aks // updates kube-config w/ credentials
az aks delete --name lowk8-aks --resource-group lowsandbox-dev-rg
Google GKS 1-Node Cluster Setup (DEV)
----------------------------------------------
deploy vpc, subnets, etc using pulumi
gcloud services enable container // enable GKE api
gcloud container clusters create lowk8-gke --cluster-version=1.27 --num-nodes=1 --network="low-sandbox-dev-vpc" --subnetwork="dev-private" --zone=us-east1-b --addons=HttpLoadBalancing,HorizontalPodAutoscaling
gcloud container clusters create-auto CLUSTER_NAME \ # creates auto-pilot cluster
--region REGION \
--project=PROJECT_ID
gcloud container clusters get-credentials lowk8-gke --region=us-east1-b
gcloud container clusters delete lowk8-gke --region=us-east1-b
Static Pod Location (On Node)
--------------------------
/etc/kubernestes/manifest
**If you move one of these files to /tmp temporarily, the static pod/component will cease to run; after the file is restored, the pod/component will be rebuilt
CNI Config Locaiton (On Node)
--------------------------
find /etc/cni/net.d/ ## find CNI info here
Upgrading Cluster Components
----------------------------------------
After upgrading kubeadm, kubelet, and trying to execute the upgrade command, if there is no kube.conf on the server then that means it hasn't been initialized
Head over to the master node and get the join token command -> kubeadm token create --print-join-command
Go back to the node and perform the join; the ca.crt and kubelet.conf will be generated at that time
Back-up Etcd (Snapshot)
----------------------------------
Inspect the etcd pod to get cert details (Node)
k describe pod/etcd -n kube-system
Perform the snapshot (Node)
ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save <FILENAME>
Verify the snapshot (Node)
ETCDCTL_API=3 etcdctl --write-out=table snapshot status <FILENAME>
Restore Etcd From Snapshot
---------------------------------------
Stop Etcd (Node)
if service, stop it; if static-pod, move it out from /etc/kubernetes/manifest
Delete /var/lib/etcd (Node)
rm -rf /var/lib/etcd
Restore from snapshot (Node)
ETCDCTL_API=3 etcdctl --data-dir /var/lib/etcd snapshot restore <FILENAME>
Start Etcd (Node)
if service, stop it; if static-pod, move it back into /etc/kubernetes/manifest)
Verify etcd is up and running (kubectl/client)
k describe pod/etcd -n kube-system
Using Helm for Manifest File Management
--------------------------------------------------------
- Helm is a package/release manager aimed to help make deploying container based applications to Kubernetes simpler
helm create example-chart // scaffolds a new helm project
helm repo add <name> <url>
helm repo update
helm search repo vweb --versions
helm show values kiamol/vweb --version 1.0.0
helm install --set namespace=test --set image.tag=e3e3140ad30ac965c5aef04e811fb629651d9fbb graphql-api alaffia-charts/graphql-api
helm install --upgrade --set namespace=test --set image.tag=e3e3140ad30ac965c5aef04e811fb629651d9fbb graphql-api alaffia-charts/graphql-api
helm ls [--all-namespaces] // list charts that have been deployed/released
helm -n <namespace> get values <release-name> // check the values you passed to a previous deployment
helm pull <REPO> --version <string> // pulls down a chart in tar.gz format
helm uninstall graphql-api // uninstall a release
// pull down a helm chart and transform it into a ready to deploy kubernetes manifest file
helm template ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --version ${CHART_VERSION} --namespace ingress-nginx > nginx-ingress.${APP_VERSION}.yaml
helm dep up // downloads all dependent sub-charts referenced in Chart.yml into the current project
Using Helmfile to Manage Helm Charts
--------------------------------------------------------
- Helmfile is a higher level abstraction built on top of Helm. It makes managing Helm charts within your project simpler as well as offering synchornization options between your project and a cluster
helmfile sync // references helmfile.yaml in the working directory
helmfile delete
Using Werf to Perform Deployments
------------------------------------------------
// Build
- Define a werf.yaml file in the root of the project
project: samplenodeapi
configVersion: 1
---
image: samplenodeapi
dockerfile: Dockerfile
- Specify the werf.yaml image specification in the Helm chart
spec:
containers:
{{- if eq .Release.Namespace "default"}}
- name: sample-node-service
{{ else }}
- name: "sample-node-service-{{ .Release.Namespace }}"
{{- end }}
image: {{ .Values.werf.image.samplenodeapi }}
werf build --repo public.ecr.aws/mock-node-api/lowsandbox
werf build --repo public.ecr.aws/mock-node-api/lowsandbox --platform linux/amd64 || linux/arm64
// Deploy
werf converge --repo public.ecr.aws/mock-node-api/lowsandbox
// Clean-Up
Common Commands
----------------------------
// Working with Contexts
kubectl config view
kubectl config current-context
kubectl config use-context arn:aws:eks:us-east-1:548883107094:cluster/alaffia-eks-cluster-prod
kubectl config get-clusters || delete-cluster <CLUSTER_NAME>
kubectl config get-contexts || delete-context <CLUSTER_NAME>
kubectl config get-users || delete-user <CLUSTER_NAME>
kubectl config unset contexts.low-aks-cluster
kubectl config unset users.clusterUser_Low-Playground_low-aks-cluster
kubectl config unset clusters.low-aks-cluster
// Getting Help
kubectl api-resources // list all resources currently available to you
kubectl explain <resource> // list information about fields associated with the resource
// Get All
kubectl get all -n <NAMESPACE>
kubectl get all --all-namespaces
kubectl get namespaces
kubectl get [ pods | svc | sa | cm | secrets | roles | rolebinding | clusterrole | clusterrolebindings | ingress ] --all-namespaces
// Exporting Manifests from Existing Resources
kubectl get service hellworldexample-helloworld -o yaml > service.yaml
// Nodes
kubectl get nodes
kubectl get nodes --show-labels
kubectl describe nodes <NODE>
kubectl label nodes <NODE> purpose: reports-services
kubectl drain <NODE> --ignore-daemonsets // drains a node of it's running pods/containers and any daemonsets that are running on it and prevents anymore pods from being scheduled
kubectl uncordon <NODE> // makes the node available to accept pod scheduling again
// Namespaces
kubectl create namespace <namespace>
kubectl get namespaces // gets all namespaces
// Pods
kubectl get pods -n <NAMESPACE>
kubectl get pods --all-namespaces
kubectl get pods -o wide // show ip address and assinged node for each pod
kubectl get pods --all-namepsaces
kubectl get pods -A --sort-by=.metadata.name
kubectl get pod -l app=fluentbit-logging -o jsonpath='{.items[0].status.containerStatuses[*].name}' // get container names in a pod
kubectl run <NAME> --image <IMAGE> --dry-run=client -o yaml > pod.yml
// Service Accounts
kubectl get sa -n <NAMESPACE>
kubectl create sa tom -n <NAMESPACE>
// Persistent Volumes
kubectl get pv // gets list of persistent volumes
// Persistent Volume Claims
kubectl get pvc // gets list of persistent volume claims
kubectl edit pvc my-pvc --record
// Services
kubectl get svc // get list of services
kubectl get endponts <service-name> // get list of backend pods the service is currently routing to
// Ingress
kubectl get ingress [ -n <NAMESPACE> ] // displayed ingress rules that exists in the namespace
// ConfigMap
kubectl get cm [ -n <NAMESPACE> ]
kubectl get cm --all-namespaces
kkubectl describe cm <NAME>
kubectl create cm sleep-config-literal --from-literal=kiamol.section='4.1' // create a config map in your cluster
kubectl create cm graphql-env --from-env-file=./graphql.env // create a config based on the contents of another .env file
// Deployments
kubectl get deployments || deploy
kubectl create deployment my-deployment --image=nginx --dry-run -o yaml > deployment.yml // generates a sample manifest imperatively
kubectl apply -f deployment.yml
kubectl scale deployment my-deployment --replicas 5 --record // scales replicaset to 5
kubectl rollout restart deploy graphql-api // does a rolling restart on containers in deployment
// Service Accounts
kubectl get [ serviceaccount | sa ] iam-test
kubectl describe sa iam-test
// Daemon Sets
kubectl get ds
// Stateful Sets
kubectl get sts
// Roles
kubectl get roles [ -n <NAMESPACE> ]
kubectl get clusterroles
kubectl create role testrole --verbs list,create ----resource=secrets,configmap [ -n <NAMESPACE> ]
// Rolebindings
kubectl get rolebindings [ -n <NAMESPACE> ]
kubectl get clustetrolebindings [ -n <NAMESPACE> ]
kubectl create rolebinding testrolebinding --role testrole --serviceaccount <NAMESPACE>:test -n project-hamster // shorthand for creating role-bindings
kubectl auth can-i create secret --as system:serviceaccount:project-hamster:processor -n project-hamster // command to do authorization checks
// Port-Forwarding
kubectl port-forward pod/hello-kiamol 8080:80 // port forward to pod resource
kubectl port-forward deploy/hello-kiamol-2 8080:80 // port forward to deployment resource
kubectl apply -f pod.yml // send local file to the K8 API for deployment
kubectl apply -f https://github.com/pod.yaml // send remote file to the K8 API for deployment
// Remote Execution
kubectl exec -it hello-kiamol-2-7f6dd54b9b-j6zvl (pod name) -- sh // get interactive shell to your container
kubectl exec -it hello-kiamol-2-7f6dd54b9b-j6zvl --namespace test -- sh // specific namespace
kubectl exec deploy/sleep -- printenv // get container environment variables
kubectl exec deploy/graphql-api -- sh -c 'nslookup processing-api' // perform an nslookup on a clusterIP service inside a container to make sure it resolves
kubectl exec deploy/graphql-api -- ping -c 1 processing-api // perform a ping from inside a container
// Logging
kubectl logs --tail=2 hello-kiamol-2-7f6dd54b9b-j6zvl // get logs from your container
kubectl logs -l app=graphql-container --follow // trail logs as they come in w/ label app=graphql-container
// Events + Cluster Information
kubectl get events -A --sort-by=.metadata.creationTimestamp // get events from all namespaces
kubectl cluster-info dump
// Resource Monitoring
kubectl top pod // gets raw resource usage metrics for pods
kubectl top pod --sort-by cpu
kubectl top pod -l app=graphql-container
kubectl top node
// Copying Files
kubectl cp hello-kiamol-2-7f6dd54b9b-j6zvl:/tmp/low.txt /Users/low/low.txt // move a file from pod to your local computer
**NOTE**: By default Kubernetes does not PULL images if they are already in the local cache. I may need to add "imagePullPolicy: Always" in the manifest to force this to happen in the event I have a container update that has the same tag name. This will ensure I get the latest image with the latest code
aws sts get-caller-identity // get your current user
<------ DEEP DIVE -------->
Services
-------------
- provides a way to expose an application runnings as a set of Pods
- clients do need to be concerned with how many pods are running or which pod they are communicating with
Client Request --> Service --> Backend Pods
[ Service Types ]
- ClusterIP: expose applications INSIDE the cluster network (needs to be consumed by other pods)
- NodePort: expose applications OUTSIDE the cluster (needs to be consumed by external clients)
**NOTE** ports exposed using this type are opened up ALL NODES and the CONTROL PLANE
- Loadbalancer: expose applications OUTSIDE the cluster (needs to be consumed by external clients) by using the cloud platforms load balancer functionality
- ExternalName
[ DNS for Services ]
- a services FULLY QUALIFIED DOMAIN NAME can be used to reach the service from ANY NAMESPACE
- a services SHORT NAME can be used to reach the service from within the SAME NAMESPACE it was created in
service-name.namespace.svc.cluster.local -> Structure
my-service.default.svc.cluster.local -> FQDN (external namespace reference)
my-service -> SHORT NAME (internal namespace reference)
Deployments
-----------------
Volumes
-------------
- file systems within containers are ephemeral (they exist only for the lifetime of the container)
- volumes provide a way to allow data to exist outside of the lifecycle of a container
- each class of storage has a particular type
Common volume types:
- hostPath: stores data in a specific dir on the host worker node
- emptyDir: stores data in dynamically created location on the host worker node; tied to the lifespan of the pod
(2) classes of storage:
Volumes
spec:
containers:
- name: buzybox
image: buzybox
volumeMounts:
- name: my-volume
mountPath: /output
volumes:
- name: my-volume
hostPath:
path: /data
Persistent Volumes - allows you to treat storage as an abstract resource to be consumed by pods (EBS, EFS, NFS, etc)
Persistent Volume Claim - allows you to carve out storage that is provided by the associated Persistent Volume
**PVCs are scoped to a namespace**
// Concept
Storage Class -> cluster resource
PV -> cluster resource
PVC -> namespace specific resource (consumed by pods)
// Create the Storage Class
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp3
provisioner: kubernetes.io/aws-ebs # AWS
parameters:
type: gp3
fsType: ext4
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd # GKE
parameters:
type: pd-ssd
replication-type: none
// Create the persistent volume
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
storageClassName: localdisk // different types of storage services available on a particular platform
persistentVolumeReclaimPolicy: Recycle || Retain || Delete // what happens when no one is using the this storage
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /var/output
// Create the claim for the persistent volume claim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
storageClassName: localdisk
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
// Reference the claim in the Pod Spec
spec:
containers:
- name: buzybox
image: buzybox
volumeMounts:
- name: pv-storage
mountPath: /output
volumes:
- name: pv-storage
persistentVolumeClaim:
claimName: my-pvc // reference claim created above
Scheduling
---------------
- process of assigning pods to a node so kubelet can run them
- scheduler is a core k8 service running in "kube-system"
- checks against each nodes resource requests and available resources before placing a pod
// nodeSelector
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: redis
image: redis
nodeSelector:
purpose: reports-services // assigns node based on label
nodeName: worker-1 // assings nodes based on explicit node name
Taints, Tolerations, and Node Selectors
----------------------------------------------------
- a mechanism for flagging a node to say it isn’t suitable for general work
- have a key-value pair just like a label
- also have an effect, which tells the scheduler how to treat the node
- use taints to identify nodes that are different from the rest
kubectl taint nodes --all diskType=hdd:NoSchedule
spec:
containers:
- name: sleep
image: kiamol/ch03-sleep
tolerations: # Lists taints this Pod is happy with
- key: "diskType" # The key, value, and effect all need
operator: "Equal" # to match the taint on the node.
value: "hdd"
effect: "NoSchedule"
- to guarantee that Pods only run on certain nodes, use a NodeSelector
spec:
containers:
- name: sleep
image: kiamol/ch03-sleep
nodeSelector: # The Pod will run only on nodes
kubernetes.io/arch: zxSpectrum # that match this CPU type.
Affinity and Anti-Affinity
------------------------------
- provides a rich way of expressing preferences or requirements to the scheduler
- can claim an affinity to certain nodes to ensure Pods land on those nodes
- uses a node selector but with a match expression rather than a simple equality check. Match expressions support multiple clauses, so you can build much more complex requirements
affinity: # Affinity expresses a requirement
nodeAffinity: # or a preference for nodes.
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: # Match expressions work on
- key: kubernetes.io/arch # labels, and you can supply
operator: In # a list of values that
values: # should match or not match.
- amd64
- matchExpressions: # Multiple match expressions
- key: beta.kubernetes.io/arch # work as a logical OR.
operator: In
values:
- amd64
Daemon-Sets
-------------------
- automatically runs a copy of a Pod on each node
- launches Pods on new nodes that are added to cluster immediately
- respect normal scheduling rules; if node is in violation of any of the constraints, it will not schedule the pod there
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: my-daemonset
spec:
selector:
matchLabels:
app: fluentbit // all pods with this label will be managed by my-daemonset
template:
metadata:
labels:
app: fluentbit // ensure container has this label so it can be picked up by my-daemonset
spec:
containers:
- name: nginx
image: nginix:1.19.0
Static-Pods
---------------
- a pod that is managed directly by the nodes kubelet process and not the k8 API
- when a static-pod is created k8 creates a mirror-pod which is a representaiton of the static-pod
- a mirror-pod can be viewed from the k8 API but you cannot perform any actions against it
Networking (Plugins)
-----------------------------
CNI Plugins - plugins that provide network connectivity between pods according to standards set by the Kubernetes network model;
Calico is one of the most popular general purpose CNI plugins
Nodes will remain in a NOTREADY state untill a network plugin is installed
[ Network Model ]
Node
- Pod 192.168.100.2 (unique IP address in the entire cluster)
- Pod 192.168.100.3
Any pod can reach any other pod simply using the Pod's IP address (over the virtual network) regardless of what node they are running on
Network Policy
---------------------
- an object that allows you to control the flow of network comms to and from pods
- BY DEFAULT pods are considered "non-isolated" and OPEN to all traffic;
- when a network policy is applied, the pod is deemed "isolated" and ONLY traffic that is permitted by the policy is allowed
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-network-policy
namespace: np-test
spec:
podSelector:
matchLabels:
app: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector: # traffic from pods in the same namespace that have the defined label
matchLabels:
app: nginix
- podSelector: # traffic from pods with the specified label
matchLabels:
app: nginix
ports:
- protocol: TCP
port: 80
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
DNS
------
- handled by the coreDNS service located in the kube-system namespace
- queries for services within the same namepsace work using short and fully qualified names
- queries for services in a different namespace fail using short name
- queries for services in a different namespace work using fully qualified names
// Structure
pod-ip-address.namespace-name.pod.cluster.local
service-name.namespace-name.svc.cluster.local
192-168-10-100 # short name
192-168-10-100.default.pod.cluster.local # fqdn
user-db # short
user-db.default.svc.cluster.local #fqdn
Managing RBAC
---------------------
There (4) role-based access related objects are:
Role - defines permissions within a particular namespace (e.g viewing logs for a pod in the default namespace)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
RoleBinding - links users to roles
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods // name of the binding
namespace: default
subjects:
// you can specify more than one "subject"
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role || ClusterRole
name: pod-reader // role to bind to
apiGroup: rbac.authorization.k8s.io
Clusterrole - defines permissions regardless of namespace (e.g viewing logs for any pod in the cluster)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
ClusterRoleBinding - links users to clusterroles
Service Accounts
-----------------------
- service accounts are accounts used by container processes inside of Pods to authenticate and use the k8 API
- they can be bound to clusterRoles or ClusterRoleBindings to control access to the API
- scoped to a particular namespace
- this also extends to AWS where pods can use IAM roles as service accounts to access other AWS services
Managing Container Resources
-------------------------------------------
Requests - amount of resources that we think a container may use; this value is only considered during scheduling in order to determine if a node has enough resources prior to pod placement; pods can use more than what is defined here
Limits - amount of resources a pod cannot exceed, otherwise the container runtime will kill it
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
resources:
requests:
cpu: "250m" # 1/1000th of 1 CPU (e.g. 1000m = 1 CPU)
memory: "64Mi"
limits:
cpu: "500m"
memory: "128Mi"
Container Probing
----------------------
[ LivenessProde ]
- a task that is run periodically in order to determine whether your app is healthy or not
spec:
containers:
- name: busybox
image: busybox
command: ['sh', '-c', 'while true; do sleep 3600; done']
livenessProbe:
exec:
command: ["echo", "Hello World"]
initialDelaySeconds: 5 // wait 5 secs after container starts before executing
periodSeconds: 5 // run every 5 secs
[ StartupProbe ]
- a task that is run only at startup time in order to determine whether your app is healthy or not
spec:
containers:
- name: nginx
image: nginx:1.19.1
startupProbe:
httpGet:
path: /
port: 80
failureThreshold: 30 // has to fail 30 times before deemed unhealthy
periodSeconds: 10
[ ReadinessProbe ]
- a task that is run only at startup in order to determine whether your app is ready to recevie requests or not; ideal when your container is dependent on a downstream container being availble (e.g. a databse); the pod will not enter the READY state until the readinessProbe has completed successfully
spec:
containers:
- name: nginx
image: nginx:1.19.1
readinessProbe:
httpGet:
path: /
port: 80
failureThreshold: 5
periodSeconds: 5
Multi-Container Pods
---------------------------
- pods that contains more than (1) container
- best practice is to have each container run in its own pod
- containers share the same network and storage (volume in a pod)
apiVersion: v1
kind: Pod
metadata:
name: sidecar-pod
spec:
containers:
// 1st container
- name: busybox1
image: busybox
command: ['sh', '-c', 'while true; do echo log data > /output/output.log; sleep 3600; done']
volumeMounts:
- name: sharedvol
mountPath: /output # same volume; different location in the container
// 2nd container
- name: sidecar
image: busybox
command: ['sh', '-c', 'tail -f /input/output.log']
volumeMounts:
- name: sharedvol
mountPath: /input # same volume; different location in the container
// shared volumes created in the pod but accessible by all containers
volumes:
- name: sharedvol
emptyDir: {}
$kubectl logs sidecar-pod -c sidecar
log data
Init Containers
-------------------
- run once to completion during the startup process of a pod
- they run once and in the order they are defined
Troubleshooting the Cluster
------------------------------------
Check node status
kubectl get nodes
kubectl describe node <nodename>
Check status of k8 servies on a node
ssh into worker node
systemctl status kubelet
systemctl status docker
Check key system pods in kube-system namespace
kubectl get pods -n kube-system
kubectl describe pod <podname> -n kube-system
Check logs for key k8 services
journalctl -u kubelet | docker
less /var/log/kube-apiserver.log
less /var/log/kube-scheduler.log
less /var/log/kube-controller-manager.log
Troubleshooting Apps/Containers
------------------------------------------
Get Pod status
kubectl get pods
kubectl desctibe pod <podname>
Remote into a pod and run commands
kubectl exec <pod> -- sh // opens a shell inside of the container running in this pod
kubectl exec <pod> -c <container-name> -- sh // if a pod has more than one container running
Check container logs
kubectl logs <pod-name>
kubectl logs -l app=graphql-container --follow // by label
Cluster Logging
---------------------
By default kubernetes only keeps (2) instances of logs in /var/log/pods:
1. logs for the current running instance of a container/pod
2. logs for the previously restarted instance of a container/pod
They looks as follows:
0.log - previous instance
1.log - current instance
Troubleshooting Networking Inside the Cluster
-----------------------------------------------------------
Deploy a container inside of your cluster to run commands from
deploy a contianer using image nicolaka/netshoot
kubectl exec netshoot -- sh
Restart Policies
--------------------
Always - default
OnFailure - only restart on failure
Never - never restart
Add-Ons
------------
- provide additional functionality
Examples include:
- Kubernetes Metrics Server
- Calico (Networking)
Backing Up etcd
----------------------
- etcd is the backend data storage solution k8 cluster
- k8 objects, applications and configs are stored in etcd
etcdctl --endpoints $ENDPOINT snapshot save <file-name>
etcdctl snapshot restore <file-name> // creates another cluster and restores based on the snapshot