{"id":15849162,"url":"https://github.com/amazingandyyy/cka","last_synced_at":"2025-08-01T04:15:31.288Z","repository":{"id":82578373,"uuid":"268137204","full_name":"amazingandyyy/cka","owner":"amazingandyyy","description":"CKA https://www.cncf.io/certification/cka/","archived":false,"fork":false,"pushed_at":"2020-06-02T04:13:24.000Z","size":18529,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-25T11:02:39.446Z","etag":null,"topics":["cka","kubernetes"],"latest_commit_sha":null,"homepage":"https://amazingandyyy.com/cka","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amazingandyyy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-30T18:26:24.000Z","updated_at":"2020-06-02T04:13:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"9c6983a4-fd35-4a4f-be16-cc187ad942e3","html_url":"https://github.com/amazingandyyy/cka","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazingandyyy%2Fcka","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazingandyyy%2Fcka/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazingandyyy%2Fcka/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazingandyyy%2Fcka/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amazingandyyy","download_url":"https://codeload.github.com/amazingandyyy/cka/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246688989,"owners_count":20818043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cka","kubernetes"],"created_at":"2024-10-05T18:21:58.987Z","updated_at":"2025-04-01T18:22:57.145Z","avatar_url":"https://github.com/amazingandyyy.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Certified Kubernetes Administrator (CKA)\n\n## Architecture\n\n![img](https://i.imgur.com/dfSsQ5g.png)\n\n![img](https://i.imgur.com/zoGkzsq.png)\n\n- Master Node\n  - ETCD cluster: store information about the cluster\n  - Kube Controller Manager: take care of different functions, like node controller, replica controller...etc\n  - kube-apiserver: responsible for orchestrating all opeations within the cluster\n  - kube-scheduler: scheduling applications on nodes\n- Worker Node\n  - kubelet: listen to the instructions from the kube-apiserver\n  - kube-proxy: enabling communication between services within the cluster\n  - container runtime engine\n\n## Kinds\n\n| Kind | Version |\n| ---- | --- |\n| Pod | v1 |\n| Service | v1 |\n| ReplicaSet | apps/v1 |\n| DaemonSet | apps/v1 |\n| Deployment | apps/v1 |\n| ConfigMap | v1 |\n| Secret | v1 |\n| Role | rbac.authorization.k8s.io/v1 |\n| LimitRange | v1 |\n| RoleBinding | rbac.authorization.k8s.io/v1 |\n| NetworkPolicy | networking.k8s.io/v1 |\n| CertificateSigningRequest | certificates.k8s.io/v1beta1 |\n| PersistentVolume | v1 |\n| PersistentVolumeClaim | v1 |\n\n## Core\n\n### ETCD cluster\n\n- ETCD is a distributed k-v store\n- ETCD in K8\n  - every change of nodes, pods, configs, secrets, accounts, roles, binding... will change the etcd, and only when the change of etcd is finished, it's considered to be completed\n- Setups:\n  - manual\n  - kubeadm\n    - `kubectl exec etcd-master -n kube-system -- sh -c \"ETCDCTL_API=3 etcdctl get / --prefix --keys-only --limit=10 --cacert /etc/kubernetes/pki/etcd/ca.crt --cert /etc/kubernetes/pki/etcd/server.crt  --key /etc/kubernetes/pki/etcd/server.key\"`\n    - it will output a lot of registry\n      - looks like `registry/pods/name...etc`\n\n### kube-apiserver\n\n- authenticate user, validate request, retrieve data\n- the only component that update ETCD, and interact with schedule and kubelet\n- view api-server options\n  - locate in kube-apiserver-minikube pods' `/etc/systemd/system/kube-apiserver.service`\n\n### Kube controller manager\n\n- controller examples\n  - watch status, remediate situation\n- a lot of controllers\n  - node-controller: node monitor period = 5s, node monitor grace period = 40s, pod eviction timeout = 5m\n  - replication-controller: make sure the replicas is enough\n  - many other controllers, deployment-controller, namespace-controller, endpoints-controller, job-controller, replication-controller, replicaset, node-controller\n- view options\n  - locate in kube-controller-manager-master pods' `/etc/kubernetes/manifests/kube-controller-manager.yaml` or (non-kube-admin-setup) `/etc/systemd/system/kube-controller-manager.service`\n\n### Scheduler\n\n- determine which pods should go to which node\n- jobs: \n  - filter nodes\n  - rank nodes\n  - resource requirements/limits, taints/tolerations, node selectors/affinity\n- view options\n  - locate in kube-controller-manager-master pods' `/etc/kubernetes/manifests/kube-scheduler.yaml` or (non-kube-admin-setup) `/etc/systemd/system/kube-scheduler.service`\n\n### kubelet\n\n- captain of the ship, register nodes, create pods, monitor node/pods\n- kubeadm does not deploy kubelets, you have to download and manually run it as a service\n- view options\n  - located in `/etc/systemd/system/kubelets.service`\n\n### kube proxy\n\n- match sevice name and the ip\n- it's a process that runs on each node\n\n### Pods\n\n- pods is the smallest object you can create in k8, it's a single process of running the docker image\n- there are also multi-container pod, one pods has multiple containers(helper containers, and each pods can refer to each other with `localhost`)\n\n- example\n\n```yml\napiVersion: v1\nkind: Pod\nmetadata:\n  name: myapp-pod\n  labels:\n    app: myapp\n    tier: frontend\nspec:\n  containers:\n  - name: nginx-container\n    image: nginx\n```\n\n### ReplicaSet (Controller)\n\n- example\n\n```yml\napiVersion: apps/v1\nkind: ReplicaSet\nmetadata:\n  name: myapp-rc\n  labels:\n    app: myapp\n    tier: frontend\nspec:\n  template:\n    metadata:\n      name: myapp-pod\n      labels:\n        app: myapp\n        tier: frontend\n    spec:\n      containers:\n      - name: nginx-container\n        image: nginx\n  replicas: 3\n  selector:\n    matchLabels:\n      app: myapp\n      tier: frontend\n```\n\n- to scale up\n  - 1. change the yaml and `kubectl replace -f rc.yml`\n  - 2. `kubectl scale --replicas=6 -f rc.yml`\n  - 3. `kubectl scale --replicas=6 replicaset myapp-rc`\n\n### Deployment\n\n- upgrade/rollback pods, advance usage of other things\n- create deployment will create rs\n\n![img](https://i.imgur.com/dO49pGy.png)\n\n### Namespceas\n\n- namespcae can be specified in yaml's metadata or using `-n flag of kubectl\n- using namespace yaml file or use `kubectl create namespace name`\n- switch\n  - kubectl config set-context $(kubectl config current-context) --namespace=dev\n\n![img](https://i.imgur.com/bFGvOQ8.png)\n\n### Service\n\n| Service Types | Feature |\n| :---- | :--- |\n| NodePort | listen to node's port and then redirect to a pod's ip |\n| ClusterIP | pods to pods communication |\n| LoadBalancer | provision a LB on the cloud provider, then distribute traffic to pods |\n\n#### NodePort\n\n- config port, targetPort, and nodePort\n![img](https://i.imgur.com/BzxxcKP.png)\n  - then use selector to select the pods(random+affinity)\n  ![img](https://i.imgur.com/R4rDAnl.png)\n  - the service is smart enough to work with single pods in single node, multiple pods in single node, or multiple pods in multiple nodes, as long as it matches the selector conditions\n\n#### ClusterIP\n\n![img](https://i.imgur.com/XWNJxXj.png)\n\n### Scheduling\n\n- schedule scan all nodes and find one node best for the new created pod, then assign a name to the node and then add a nodeName to pod's yaml file. e.g. `spec.nodeName: node02`\n- if there is not schedule and the pods' yaml doesn't have `spec.nodeName` set, then the pod status will be Pending state, manually create a Binding yaml file then send a POST request to `http://$SERVERapi/v1/namespaces/default/pods/$PODNAME/binding/` with the yaml converted JSON as body\n\n### Label \u0026 Selector\n\n- deployment/rs's selector uses matchLabels to match pods with label\n- use selector as filter: `kubectl get pods --selector env=dev,tier=frontend`\n\n### Taints \u0026 Tolerations\n\n- taints on node, tolerations defined on pods\n- commands: `kubectl taint node node01 key=value:taint-effect\n  - taint-effect can be `NoSchedule(don't schedule new pods) | PreferNoSchedule(not guarantee) | NoExecute(will evict existing pods) `\n  - e.g. `kubectl taint node node01 app=blue:NoSchdule`\n  - the pods's tolerations then has to be\n    ```yml\n    spec.tolerations:\n      - key: app\n        operator: Equal\n        value: blue\n        effect: NoSchedule\n    ```\n  - it doesn't guarantee the certain pods will must go to certain node. (that will be achieved by affinity)\n\n### Node Selector(Affinity)\n\n- select a node\n  ```yml\n    kind: Pod\n    ...\n    spec.nodeSelector:\n      size: Large\n  ```\n- label a node\n  - `kubectl label nodes node01 size=Large`\n- select a node with affinity\n  ```yml\n    kind: Pod\n    ...\n    spec:\n      affinity:\n        nodeAffinity:\n          requiredDuringSchedulingIgnoreDuringExecution:\n            nodeSelectorTerms:\n            - matchExpressions:\n              - key: size\n                operator: In\n                values:\n                - Large\n                - Medium\n              - key: size\n                operator: NotIn\n                values:\n                - Small\n              - key: good\n                operator: Exists\n  ```\n    - requiredDuringSchedulingIgnoreDuringExecution or preferredDuringSchedulingIgnoreDuringExecution or preferredDuringSchedulingRequiredDuringExecution\n\n### Resource requirements and limits\n\n- container level of request and limits\n\n```yml\nspec.containers.resources:\n  requests:\n    memory: \"1Gi\"\n    cpu: 1\n```\n\n- default requirement: 0.5CPU and 256Mi memory if the ns has that been set: ([docs](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/))\n```yml\napiVersion: v1\nkind: LimitRange\nmetadata:\n  name: cpu-limit-range\nspec:\n  limits:\n  - default:\n      cpu: 1\n      memory: 512Mi\n    defaultRequest:\n      cpu: 0.5\n      memory: 256Mi\n    type: Container\n```\n\n### DaemonSets\n\n- Make sure the pods is running on every node, it use affinity under the hood to make sure the pods is running on every node\n\n- example\n\n  ```yaml\n  apiVersion: apps/v1\n  kind: DaemonSet\n  metadata:\n    name: fluentd-elasticsearch\n    namespace: kube-system\n  spec:\n    selector:\n      matchLabels:\n        name: fluentd-elasticsearch\n    template:\n      metadata:\n        labels:\n          name: fluentd-elasticsearch\n      spec:\n        containers:\n        - name: fluentd-elasticsearch\n          image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2\n  ```\n\n### Static PODs\n\n- only kubelet to create the pods, with yaml files to be put inside `/etc/kubernetes/manifests` folder.\n- config\n  - 1. pass `--pod-manifest-path=/etc/kubernetes/manifests` to kubelet.service\n  - 2. pass `--config=kubeconfig.yaml` then inside `kubeconfig.yaml`, it is `staticPodPath: /etc/kubernetes/manifests`\n\n![img](https://i.imgur.com/LJAZnGA.png)\n![img](https://i.imgur.com/xsoXRbY.png)\n\n\n- use `ps -aux | grep .yaml ` to find the config path, then cat that file `grep staticPodPath` to find the folder of those yaml files.\n\n### Scheduling\n\n- create extra schedulers\n\n```yaml\n...\nspec:\n containers:\n  - command:\n    - kybe-scheduler\n    - --leader-elect=false\n    - --port=\n    - --scheduler-name=my-scheduler\n    - --lock-object-name=my-scheduler\n...\n```\n  \n  - then add `spec.schedulerName`\n\n- steps to find where to add pods\n  ```sh\n  $ cd /etc/systemd/system/kubelet.service.d\n  $ cat 10-kubeadm.conf | grep kubelet\n  $ cat /var/lib/kubelet/config.yaml | grep -i path\n  # copy and config the file\n  $ netstat -natulp | grep 10253 # until finding a port that is not being used\n  # then add `spec.schedulerName` to pods' yaml\n\n  ```\n\n### Monitoring/Logging\n\n- metrics\n  - enable it: `minikube addons enable metrics-server`\n  - then can use `kubectl top pods` or `kubectl top nodes`\n- logging\n  - `kubectl logs -f pod-name container-name`\n\n## Application Lifecycle Management\n\n### Rollout and versioning\n\n- `kubectl rollout status deployment/myapp-deployment`\n- `kubectl rollout history deployment/myapp-deployment`\n- deployment strategy\n  - Recreate\n  - RollingUpdate(default)\n- what counts as upgrade\n  - 1. update yaml file\n  - 2. `kubectl set image deployment/myapp-deployment nginx=nginx:1.9.1`\n- rollback\n  - `kybectl rollout undo deployment/myapp-deployment`\n- kubectl\n  ```sh\n  kubectl create -f myapp-deployment.yml\n  kubectl get deployment\n  # ugprade\n  kubectl apply -f myapp-deployment.yml\n  kubectl set image deployment/myapp-deployment nginx=nginx:1.9.1\n  # status\n  kubectl rollout status deployment/myapp-deployment\n  kubectl rollout history deployment/myapp-deployment\n  kubectl rollout undo deployment/myapp-dep1\n  ```\n\n### Config applications\n\n- config commands/args, environment variables, secrets\n- commands/args\n  - command in k8.yaml is the ENTRYPOINT in dockerfile\n  - args in k8.yaml is the CMD in dockerfile\n- environment variables\n  ```yml\n  env\n   - name: APP_COLOR\n     value: pink\n  ---\n  env\n   - name: APP_COLOR\n     valueFrom:\n       configMapKeyRef:\n  ---\n  env\n   - name: APP_COLOR\n     value:\n        secretKeyRef:\n  ```\n\n### ConfigMap\n\n- configuration data in kubernetes\n- imperative:\n  - 1. From literal: `kubectl create configmap app-config --from-literal=APP_COLOR=blue --from-literal=APP_MODE=prod`\n  - 2. From file: `kubectl create configmap app-config --from-file=app_config.properties`\n- create:\n\n  ```yml\n  apiVersion: v1\n  kind: ConfigMap\n  metadate:\n    name: app-config\n  data:\n    APP_COLOR: blue\n    APP_MODE: prod\n  ```\n\n- inject into pod\n\n  ```yml\n  --- env\n  envFrom:\n  - configMapRef:\n      name: app-config\n  --- single env\n  env\n  - name: APP_COLOR\n    valueFrom:\n      configMapKeyRef:\n        name: app-config\n        key: APP_COLOR\n  --- volume\n  volumes:\n    - name: app-config-volume\n      configMap:\n        name: app-config\n  ```\n\n### Secret\n\n- configuration secret in kubernetes\n- imperative:\n  - 1. From literal: `kubectl create secret generic secret-name --from-literal=DB_User=root --from-literal=DB_Password=passwooord`\n  - 2. From file: `kubectl create secret generic secret-name --from-file=app_secret.properties`\n- create:\n  - do `echo -n passwooord | base64` then add them to \n  - do `echo -n cGFzc3dvb29yZA== | base64 --decode` to decode\n  - config Secret yaml\n\n    ```yml\n    apiVersion: v1\n    kind: Secret\n    metadate:\n      name: app-secret\n    data:\n      DB_User: cm9vdA==\n      DB_Password: cGFzc3dvb29yZA==\n    ```\n\n- inject into pod\n\n  ```yml\n  --- env\n  envFrom:\n    - secretRef:\n        name: secret-name\n  --- single env\n  env\n  - name: DB_Password\n    valueFrom:\n      secretKeyRef:\n        name: secret-name\n        key: DB_Password\n  --- volume\n  volumes:\n    - name: app-config-volume\n      secret:\n        secretName: app-config # (which will create files such as /opt/app-config-volumes/DB_Password and /opt/app-config-volumes/DB_Host)\n  ```\n\n### Multi-container Pods\n\n- share the same lifecycle, network, and storage, create together and destroy together\n- initContainers([docs](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/))\n\n  ```yml\n  apiVersion: v1\n  kind: Pod\n  metadata:\n    name: myapp-pod\n  spec:\n    containers:\n    - name: myapp-container\n      image: busybox:1.28\n      command: ['sh', '-c', 'echo The app is running! \u0026\u0026 sleep 3600']\n    initContainers:\n    - name: init-myservice\n      image: busybox:1.28\n      command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']\n    - name: init-mydb\n      image: busybox:1.28\n      command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']\n  ```\n\n## Cluster Maintenance\n\n- `kubectl drain node-1` // will move pods inside to other nodes and cordon the node\n- `kubectl uncordon node-1` // unstrict(uncordon) scheduling\n- `kubectl cordon node-2` // if the node is running a critical service\n\n### Cluster Upgrade Process\n\n![img](https://i.imgur.com/nB7oZOc.png)\n\n- Choises\n  - 1. few clicks on GCP\n  - 2. use kubeadm\n  - 3. manual\n- strategies\n  - upgrade master first then worker node\n  - upgrade worker node:\n    - 1. bring down all then upgrade all\n    - 2. rolling upgrading\n    - 3. add new nodes of new version, then move pods\n- upgrade one cluster process\n\n  ```sh\n  $ kubectl drain node01\n  # plan on upgrading cluster\n  $ kubeadm upgrade plan\n  # install kubeadm\n  $ apt install kubeadm=1.17.0-00\n  # upgrade kubeadm\n  $ kubeadm upgrade apply v1.17.0\n  # install kubelet\n  $ apt upgrade kubelet=1.17.0-00\n  # upgrade kubelet\n  $ kubeadm upgrade node config --kubelet-version v1.17.0\n  $ systemctl restart kubelet\n  $ kubectl uncordon node01\n  ```\n\n- Case study\n  - `kubeadm upgrade node` on node is like `kubeadm upgrade apply` on master\n  - to upgrade the master node, run\n\n    ```sh\n      kubectl drain master --ignore-daemonsets\n      apt install kubeadm=\u003cversion\u003e\n      kubeadm upgrade apply \u003cversion\u003e\n      apt install kubelet=\u003cversion\u003e\n      kubectl uncordon master\n    ```\n\n  - to upgrade the worker nodes, run\n  \n  ```sh\n    kubectl drain node01 --ignore-daemonsets\n    ssh node01\n    node01$ apt install kubeadm=\u003cversion\u003e\n    node01$ apt install kubelet=\u003cversion\u003e\n    node01$ apt-mark hold kubelet\n    master$ kubectl uncordon node01\n  ```\n\n\n- use documention [no matter what](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/)\n\n### Backup \u0026 Restore\n\n- backup configuration\n  - `kubectl get all --all-namespaces -o yaml \u003e all-deploy-backup.yaml`\n- ETCD cluster ([docs](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#backing-up-an-etcd-cluster))\n  - `etcdctl snapshot save snapshot.db`\n  - [backup](https://github.com/mmumshad/kubernetes-the-hard-way/blob/master/practice-questions-answers/cluster-maintenance/backup-etcd/etcd-backup-and-restore.md#2-backup)\n\n    ```sh\n    ETCDCTL_API=3 etcdctl \\\n      --endpoints=https://[127.0.0.1]:2379 \\ (--listen-client-urls)\n      --cacert=/etc/kubernetes/pki/etcd/ca.crt \\ (--key-file)\n      --cert=/etc/kubernetes/pki/etcd/server.crt \\ (--cert-file)\n      --key=/etc/kubernetes/pki/etcd/server.key \\ (--peer-trusted-ca-file)\n      snapshot save /tmp/snapshot-pre-boot.db\n    ```\n  - [restore](https://github.com/mmumshad/kubernetes-the-hard-way/blob/master/practice-questions-answers/cluster-maintenance/backup-etcd/etcd-backup-and-restore.md#3-restore-etcd-snapshot-to-a-new-folder) and update `/etc/kubernetes/manifests/etcd.yaml`\n\n    ```sh\n    ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt \\\n     --name=master \\\n     --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key \\\n     --data-dir /var/lib/etcd-from-backup \\\n     --initial-cluster=master=https://127.0.0.1:2380 \\\n     --initial-cluster-token etcd-cluster-1 \\\n     --initial-advertise-peer-urls=https://127.0.0.1:2380 \\\n     snapshot restore /tmp/snapshot-pre-boot.db\n    ```\n\n## Security\n\n### Basic Authentication\n\n- 1. create user list in `/tmp/users/user-details.csv`\n\n```csv\n# User File Contents\npassword123,user1,u0001\npassword123,user2,u0002\npassword123,user3,u0003\npassword123,user4,u0004\npassword123,user5,u0005\n```\n\n- 2. link with kube-apiserver in `/etc/kubernetes/manifests/kube-apiserver.yaml` with `--authorization-mode` and `--basic-auth-file` flags\n\n```yml\napiVersion: v1\nkind: Pod\nmetadata:\n  name: kube-apiserver\n  namespace: kube-system\nspec:\n  containers:\n  - command:\n    - kube-apiserver\n    - --authorization-mode=Node,RBAC\n      ...\n    - --basic-auth-file=/tmp/users/user-details.csv\n```\n\n- 3. create `kind: Role` and `kind: RoleBinding` yaml files\n\n```yml\n---\nkind: Role\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  namespace: default\n  name: pod-reader\nrules:\n- apiGroups: [\"\"] # \"\" indicates the core API group\n  resources: [\"pods\"]\n  verbs: [\"get\", \"watch\", \"list\"]\n---\n# This role binding allows \"jane\" to read pods in the \"default\" namespace.\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: read-pods\n  namespace: default\nsubjects:\n- kind: User\n  name: user1 # Name is case sensitive\n  apiGroup: rbac.authorization.k8s.io\nroleRef:\n  kind: Role #this must be Role or ClusterRole\n  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to\n  apiGroup: rbac.authorization.k8s.io\n```\n\n### TLS\n\n- get all list by get details\n- decode with `openssl x509 -in /etc/kubernetes/pki/ca.crt -text -noout`\n\n### Certificate API\n\n- create CSR\n  - 1. `openssl genrsa -out jane.key 2048`\n  - 2. `openssl req -new -key jane.key -subj \"/CN=jane\" -out jane.csr`\n  - 3. `cat jane.csr | base64 | tr -d '\\n'`\n  - 4. create CertificateSigningRequest\n\n  ```yml\n  apiVersion: certificates.k8s.io/v1beta1\n  kind: CertificateSigningRequest\n  metadata:\n    name: jane\n  spec:\n    groups:\n    - system:authenticated\n    usages:\n    - digital signature\n    - key encipherment\n    - server auth\n    request:\n      GLKHLJKYHIHFVIFH...YUGHJGJKLHK\n  ````\n\n- recreate\n\n```sh\nopenssl x509 -req -in /etc/kubernetes/pki/apiserver-etcd-client.csr -CA /etc/kubernetes/pki/etcd/ca.crt -CAkey /etc/kubernetes/pki/etcd/ca.key -CAcreateserial -out /etc/kubernetes/pki/apiserver-etcd-client.crtmaster\n```\n\n- admin can do\n  - `kubectl get csr`\n  - `kubectl certificate approve jane`\n\n\n### KubeConfig\n\n- a config file in $HOME/.kube/config\n\n```yml\napiVersion: v1\nkind: Config\ncurrent-context: aws-user@kubernetes-on-aws\nclusters:\n- name: production\n  cluster:\n    certificate-authority: /etc/kubernetes/pki/ca.crt\n    server: https://172.17.0.8:6443\n\n- name: development\n  cluster:\n    certificate-authority: /etc/kubernetes/pki/ca.crt\n    server: https://172.17.0.8:6443\n\n- name: kubernetes-on-aws\n  cluster:\n    certificate-authority: /etc/kubernetes/pki/ca.crt\n    server: https://172.17.0.8:6443\n\n- name: test-cluster-1\n  cluster:\n    certificate-authority: /etc/kubernetes/pki/ca.crt\n    server: https://172.17.0.8:6443\n\ncontexts:\n- name: test-user@development\n  context:\n    cluster: development\n    user: test-user\n\n- name: aws-user@kubernetes-on-aws\n  context:\n    cluster: kubernetes-on-aws\n    user: aws-user\n\n- name: test-user@production\n  context:\n    cluster: production\n    user: test-user\n\n- name: research\n  context:\n    cluster: test-cluster-1\n    user: dev-user\n\nusers:\n- name: test-user\n  user:\n    client-certificate: /etc/kubernetes/pki/users/test-user/test-user.crt\n    client-key: /etc/kubernetes/pki/users/test-user/test-user.key\n- name: dev-user\n  user:\n    client-certificate: /etc/kubernetes/pki/users/dev-user/developer-user.crt\n    client-key: /etc/kubernetes/pki/users/dev-user/dev-user.key\n- name: aws-user\n  user:\n    client-certificate: /etc/kubernetes/pki/users/aws-user/aws-user.crt\n    client-key: /etc/kubernetes/pki/users/aws-user/aws-user.key\n```\n\n- can config multiple accounts:\n\n![img](https://i.imgur.com/gdQGnvM.png)\n\n- kubectl\n  - to see current config: `kubectl config view`\n  - to change current config: `kubectl config use-context prod-user@production`, `kubectl config --kubeconfig=/root/my-kube-config use-context research`\n\n### API Group\n\n![img](https://i.imgur.com/yFUf5vx.png)\n\n- get all path:\n\n```sh\n$ curl https://192.168.64.6:8443 -k --key /Users/andy/.minikube/client.key --cert /Users/andy/.minikube/client.crt --cacert /Users/andy/.minikube/ca.crt\n$ kubectl proxy\n$ curl http://127.0.0.1:8001 -k --key /Users/andy/.minikube/client.key --cert /Users/andy/.minikube/client.crt --cacert /Users/andy/.minikube/ca.crt\n```\n\n### Namespaced RBAC\n\n- role base access controller, only for controlling namespaced resources\n\n```yml\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: developer\nrules:\n- apiGroups: [\"\"]\n  resources: [\"pods\"]\n  verbs: [\"list\", \"get\", \"create\", \"update\", \"delete\"]\n  # resourceNames: [\"blue\", \"orange\"]\n- apiGroups: [\"\"]\n  resources: [\"ConfigMap\"]\n  verbs: [\"create\"]\n```\n\n```yml\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: devuser-developer-binding\nsubjects:\n- kind: User\n  name: dev-user\n  apiGroup: rbac.authorization.k8s.io\nroleRef:\n  kind: Role\n  name: developer\n  apiGroup: rbac.authorization.k8s.io\n```\n\n- checking\n  - kubectl get roles\n  - kubectl get rolebindings\n  - kubectl auth can-i create deployment\n\n### Cluster RBAC\n\n- `kubectl api-resources --namespaced=true` to check what resource are bound by namespaces\n- use clusteroles and clusterrolebindings to change access control\n- yaml are the smae as role/rolebinding\n\n### Image Security\n\n- pull from private registry\n  - create docker-registry secret\n\n    ```sh\n    $ kubectl create secret docker-registry regcred \\\n    --docker-server= \\\n    --docker-username= \\\n    --docker-password= \\\n    --docker-email=\n    $ kubectl create secret docker-registry private-reg-cred \\\n    --docker-server=myprivateregistry.com:5000 \\\n    --docker-username=dock_user\\\n    --docker-password=dock_password \\\n    --docker-email=dock_user@myprivateregistry.com\n    ```\n\n  - use it in the pod file, add `spec.imagePullSecrets: - name: regcred`\n\n### Security Context\n\n- only supported at the container level\n\n  ```yml\n  spec.containers:\n    - name: ubuntu\n      image: ubuntu\n      command: [\"sleep\", \"3600\"]\n      securityContext:\n        runAsUser: 1000\n        capabilities:\n          add: [\"MAC_ADMIN\"]\n  ```\n\n### Netowrk Policy\n\n- default is that \"all allow\" for each one in the cluster\n- if NetworkPolicy is presented, it will be strict\n- use `podSelector.matchLabels` to assign the network policy to the pods\n\ne.g., api can connect with db, then ingress policy for db, egress policy for api\n\n```yml\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: db-policy\nspec:\n  podSelector:\n    matchLabels:\n      role: db\n    policyTypes:\n    - Ingress\n    ingress:\n    - from:\n      - podSelector:\n          matchLabels:\n            name: api-pod\n      ports:\n      - protocol: TCP\n        port: 3306\n```\n\n## Storage\n\n- docker storage\n  - storage driver\n  - volume driver\n- kubernetes\n  - container runtime interface (CRI)\n  - container network interface (CNI)\n  - container storage interface (CSI)\n- use volumes and volumeMount\n\n### Volume\n\n```yml\napiVersion: v1\nkind: Pod\nmetadata:\n  name: mypod\nspec:\n  containers:\n    - name: myfrontend\n      image: nginx\n      volumeMounts:\n      - mountPath: \"/var/www/html\"\n        name: mypd\n  volumes:\n    - name: mypd\n      hostPath:\n        path: /data/html\n        type: Directory\n```\n\n### Persisten Volume\n\n- persisten voluem (cluster level)\n\n```yml\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: mv-vol1\nspec:\n  accessModes:\n    - ReadWriteOnce\n  capacity:\n    storage: 1Gi\n  hostPath:\n    path: /tmp/data\n  # awsElasticBlockStore:\n  #   volumeID: \u003cvolume-id\u003e\n  #   fsType: ext4\n```\n\n- persisten volume claim, once the PV is used by the PVC, other PVC cannot use it, and will stay as pending\n- match PV and PVC by checking\n  - sufficient capacity\n  - access modes\n  - volume modes\n  - storage class\n  - selector\n\n```yml\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: mvclaim\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 500Mi\n```\n\n- add to pods ([docs](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes))\n\n```yml\napiVersion: v1\nkind: Pod\nmetadata:\n  name: mypod\nspec:\n  containers:\n    - name: myfrontend\n      image: nginx\n      volumeMounts:\n      - mountPath: \"/var/www/html\"\n        name: mypd\n  volumes:\n    - name: mypd\n      persistentVolumeClaim:\n        claimName: myclaim\n```\n\n### Network\n\n- tools:\n\n```sh\nnslookup\nip link\nip addr\nip addr add 192.168.1.10/24 dev eth0\nip route\nip route add 192.168.1.10/24 via 192.168.2.1\ncat /proc/sys/net/ipv4/ip_forward, cat /etc/hosts # 1\nping\narp\nnetstat -nplt\n```\n\n![img](https://i.imgur.com/kWlFvpK.png)\n\n#### Kubernetes Networking Model\n\n- requirements\n  - Every POD should have an IP address\n  - Every POD should be able to communicate with every other POD in the same node\n  - Every POD should be able to communicate with every other POD on other nodes without LAN\n\n- scenario\n\n![img](https://i.imgur.com/bxiqXGZ.png)\n\n- setup on the scenario\n  - 1. Create veth pair\n    - `ip link add v-net-0 type bridge` on each node\n  - 2. Attach veth pair\n    - `ip link set dev v-net-0 up` on each node to bring them up\n  - 3. Assign IP address:\n    - `ip -n \u003cnamespace\u003e addr add ...`\n    - `ip -n \u003cnamespace\u003e route add ...`\n    - `ip addr add 10.244.1.1/24 dev v-net-0`, `ip addr add 10.244.2.1/24 dev v-net-0`, and `ip addr add 10.244.3.1/24 dev v-net-0` to each node\n  - 4. Bring up interface\n    - `ip -n \u003cnamespace\u003e link set ...`\n  - `ip route add 10.244.2.2 via 192.168.1.12` and `ip route add 10.244.3.1 via 192.168.1.13`\n- config file is in `/etc/cni/net.d/*.conf`\n- weave CNI solution\n\n#### IP address management (IPAM)\n\n- pod networking\n- service networking\n  - `iptables -L -t net | grep db-service`\n\n![img](https://i.imgur.com/HzUIdkR.png)\n\n#### DNS in K8s\n\n- in one cluster, `curl http://web-service`\n- cross clusters, call service, `curl http://web-service.apps.svc.cluster.local`\n- cross clusters, call pods, `curl http://10-244-2-5.apps.pod.cluster.local`\n\n### Ingress\n\n- eliminate dulplicted LB provided by service\n- deploy\n  - Deployment: deploy `nginx-ingress-controller`å as a pod first\n  - ConfigMap: create ConfigMap\n  - NodePort: create a NodePort service for the nginx-ingress-controller pod\n  - ServiceAccount: for nginx-ingress-controller to use for Roles, ClusterRoles, and RoleBindings\n  - Ingress: create ingress roles\n\n![img](https://i.imgur.com/i9WoRo8.png)\n\n- version A:single service\n  ```yml\n  apiVersion: extensions/v1beta1\n  kind: Ingress\n  metadata:\n    name: ingress-app\n  spec:\n    backend:\n      serviceName: app-service\n      servicePort: 8080\n  ```\n\n- version B: sub-path (rule 1)\n  ```yml\n  apiVersion: extensions/v1beta1\n  kind: Ingress\n  metadata:\n    name: ingress-wear-watch\n  spec:\n    rules:\n    - http:\n      paths:\n      - path: /wear\n        backend:\n          serviceName: wear-service\n          servicePort: 8080\n      - path: /watch\n        backend:\n          serviceName: watch-service\n          servicePort: 8088\n  ```\n\n- version C: sub-domain (rule 2, 3)\n\n  ```yml\n  apiVersion: extensions/v1beta1\n  kind: Ingress\n  metadata:\n    name: ingress-wear-watch\n  spec:\n    rules:\n    - host: wear.my-online-store.com\n      http:\n        paths:\n        - backend:\n          serviceName: wear-service\n          servicePort: 8080\n    - host: watch.my-online-store.com\n      http:\n        paths:\n        - backend:\n          serviceName: watch-service\n          servicePort: 8088\n  ```\n\n  - 404 page: (rule 4)\n    - create `default-http-backend:80` for default/fallback service (404 page..etc)\n\n- rewrite target\n\n  ```yml\n  metadata:\n    name: test-ingress\n    namespace: critical-space\n    annotations:\n      nginx.ingress.kubernetes.io/rewrite-target: /\n  ...\n  ```\n  \n  - without: `http://\u003cingress-service\u003e:\u003cingress-port\u003e/wear --\u003e http://\u003cwear-service\u003e:\u003cport\u003e/wear`\n  - what we want is `http://\u003cingress-service\u003e:\u003cingress-port\u003e/wear --\u003e http://\u003cwear-service\u003e:\u003cport\u003e/` (rewrite the `/wear` with `/`)\n\n## CKAD\n\n- health status check\n  - livenessProbe\n  - readinessProbe\n- multi-container patterns\n  - sidecar\n  - adapter\n  - ambassador\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazingandyyy%2Fcka","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famazingandyyy%2Fcka","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazingandyyy%2Fcka/lists"}