Skip to content

antony@notes:~/kubernetes$ cat "CKA-2022-考題.md"

CKA 2022 考題

2022-09-18· kubernetes ·系統工程

CKA 2022 考題

Scale

題型 1:Scale the deployment presentaion to 3 pods 題型 2:Scale the deployment loadbalabcer to 6 pods

解答

題型 1

$ kubectl scale deploy presentaion --replicas=3

題型 2

$ kubectl scale deploy loadbalabcer --replicas=6

Etcd

First, create a snapshot of the existing etcd instance running at https://127.0.0.1:2379, saving the snapshot to /var/lib/backup/etcd-snapshot.db

Creating a snapshot of the given instance is expected to complete in seconds. If the operation seems to hang, something’s likely wrong with your command. Use CTRL+C to cancel the operation and try again.

Next, restore an existing, previous snapshot located at /var/lib/backup/etcd-snapshot-previous.db.

The following TLS certificates/key are supplied for connecting to the server with etcdctl: CA certificate: /opt/KUIN0061/ca.crt Client certificate: /opt/KUIN0061/etcd-client.crt Client key: /opt/KUIN0061/etcd-client.key

解答

  • K8S DOC 查詢關鍵字 : etcd backup
  • 點選 Operating etcd clusters for Kubernetes | Kubernetes 這篇文章,
  • 進取之後點藍藍的 backup

將 etcd 備份 (考試環境,確認 master node 有無 etcdctl 命令,如沒有則在一開始的終端機做題 )

ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/opt/KUIN0061/ca.crt \
  --cert=/opt/KUIN0061/etcd-client.crt \
  --key=/opt/KUIN0061/etcd-client.key \
  snapshot save /var/lib/backup/etcd-snapshot.db

將 etcd 還原

ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/opt/KUIN0061/ca.crt \
  --cert=/opt/KUIN0061/etcd-client.crt \
  --key=/opt/KUIN0061/etcd-client.key \
  snapshot restore /var/lib/backup/etcd-snapshot-previous.db

Ingress

Create a new nginx Ingress resources as follows:

  • Name: ping
  • Namespace: ing-internal
  • Exposing service hi on path /hi using service port 5678

The avaliability of service hi can be checked using the following command,which should return hi: curl -kL <INTERNAL_IP>/hi

解答

  • K8S DOC 查詢關鍵字 : ingress
  • Ingress | Kubernetes 這篇
  • 用第一個 YANL 檔

編輯 YAML 檔

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ping                                             # change
#  annotations:                                          # remove
#    nginx.ingress.kubernetes.io/rewrite-target: /       # remove
  namespace: ing-internal                                # change
spec:
#  ingressClassName: nginx-example                       # remove
  rules:
  - http:
      paths:
      - path: /hi
        pathType: Prefix
        backend:
          service:
            name: hi
            port:
              number: 5678

產生 ingress

$ k apply -f ingress.yaml

測試

$ curl -kL <INTERNAL_IP>/hi

NetworkPolicy

Create new NetworkPolicy named allow-port-from-namespace that allows Pods in the existing namespace internal to connect to port 9000 of other Pods in the same namespace.

Ensure that the new NetworkPolicy:

  • does not allow access to Pods not listening on port 9000
  • does not allow access from Pods not in namespace internal

解答

  • K8S DOC 查詢關鍵字 : networkpolicy
  • Network Policies | Kubernetes 這篇
  • 用第一個 YANL 檔

看 Namespace 的標籤

$ k get ns internal --show-labels

編輯 YAML 檔

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-port-from-namespace
  namespace: internal
spec:
  podSelector: {}                                         # 新增 {}
#    matchLabels:
#      role: db
  policyTypes:
    - Ingress
  ingress:
    - from:
#        - ipBlock:                                       # remove
#            cidr: 172.17.0.0/16                          # remove
#            except:                                      # remove
#              - 172.17.1.0/24                            # remove
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: internal
#        - podSelector:                                   # remove
#            matchLabels:                                 # remove
#              role: frontend                             # remove
      ports:
        - protocol: TCP
          port: 9000                                      # port number 改成 9000
#  egress:                                                # remove
#    - to:                                                # remove
#        - ipBlock:                                       # remove
#            cidr: 10.0.0.0/24                            # remove
#      ports:                                             # remove
#        - protocol: TCP                                  # remove
#          port: 5978                                     # remove

產生 networkpolicy

$ k apply -f i.yaml

Kubernetes 升級

Given an existing Kubernetes cluster running version 1.24.1, upgrade all of Kubernetes control plane and node components on the master node only to version 1.24.2

You are also expected to upgrade kubelet and kubectl on the master node.

Be sure to drain the master node before upgrading it and uncordon it after the upgrade. Do not upgrade the worker nodes, etcd, the container manager, the CNI plugin, the DNS service or any other addons.

解答

  • K8S DOC 查詢關鍵字 : upgrading kubeadm
  • Upgrading kubeadm clusters | Kubernetes 這篇

對 Linux 套件 kubeadm 進行升級

# ssh 連進 control plane node
$ ssh <control plane node>

# 提權
$ sudo -i

# 更新套件清單
$ apt update

# 看當前主機可以升級 kubeadm 的那些版本
$ apt-cache madison kubeadm

# 將 kubeadm 升級至 1.22.1 版
## hold ,讓系統 update 或 upgrade 的時候,忽略 hold 的套件
## unhold ,取消忽略
$ apt-mark unhold kubeadm && \
  apt-get update && apt-get install -y kubeadm=1.24.2-00 && \
  apt-mark hold kubeadm

# 檢查下載下來的 kubeadm 版本
$ kubeadm version

kubeadm upgrade

# Drain control-plane node
$ kubectl drain <control-plane-node> --delete-emptydir-data --ignore-daemonsets --force

# Verify the upgrade plan
$ kubeadm upgrade plan

# 將 kubeadm 升級至指定版本 : 1.24.2
$ sudo kubeadm upgrade apply v1.24.2 --etcd-upgrade=false

成功後,會看到的螢幕輸出

[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.24.2". Enjoy!

[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.

Upgrade kubelet and kubectl

$ apt-mark unhold kubelet kubectl && \
  apt-get update && apt-get install -y kubelet=1.24.1-00 kubectl=1.24.1-00 && \
  apt-mark hold kubelet kubectl

Restart the kubelet

# Reload systemd manager configuration
$ systemctl daemon-reload

# 將 kubelet 重啟
$ systemctl restart kubelet

# 檢查 kubelet 狀態
$ systemctl status kubelet

Uncordon the node

# Bring the node back online by marking it schedulable
$ kubectl uncordon <control-plane-node>

檢查 node 狀態

$ kubectl get nodes

Reference

CPU

From the pod label name=cpu-loader,find pods running high CPU workloads and write the name of the pod consuming most CPU to the file /opt/KUTR00401/KURT00401.txt (while alreay exists).

解答

$ kubectl top pod -l "name=cpu-loader" --sort-by=cpu
$ echo "pod_name" > /opt/KUTR00401/KURT00401.txt

Sidecar

Context Without changing its existing containers, an existing Pod needs to be integrated into Kubernetes’s build-in logging architecture(e.g kubectl logs). Adding a streaming sidecar container is a good and common way to accomplish this requirement.

Task Add a busybox sidecar container to the existing Pod big-corp-app.The new sidecar container has to run the following command:

/bin/sh -c tail -n+1 -f /var/log/big-corp-app.log

Use a volume mount named logs to make the file /var/log/big-corp-app.log available to the sidecar container.

Don’t modify the existing container. Don’t modify the path of the log file, both containers must access it at /var/log/bin-corp-app.log

解答

  • K8S DOC 查詢關鍵字 : sidecar yaml
  • Logging Architecture | Kubernetes 這篇
  • admin/logging/two-files-counter-pod-streaming-sidecar.yaml 這個 yaml 檔
    • ctrl + f 搜尋 : streaming-

匯出 YAML 檔

$ k get pod big-corp-app -o yaml > sidecar.yaml

編輯 YAML 檔

apiVersion: v1
kind: Pod
metadata:
...
  - name: count-log-2                                              # add
    image: busybox:1.28                                            # add
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/big-corp-app.log']  # add and change
    volumeMounts:                                                  # add
    - name: logs                                                   # add and change
      mountPath: /var/log                                          # add
  volumes:                                                         # add
  - name: logs                                                     # add and change
    emptyDir: {}                                                   # add

重新產生 pod

$ kubectl replace -f sidecar.yaml --force

Trobleshooting - kubelet 故障

A Kubernetes worker node, named wk8s-node-0 is in state NotReady. Investigate why this is the case, and perform an appropriate steps to bring the node to a Ready stat, ensuring that any changes are made permanent.

You can ssh to the failed node using: ssh wk8s-node-0 You can assume elevated privileges on the node with the following command: sudo -i

解答

# 連到 wk8s-node-0 這台 node
$ ssh wk8s-node-0

# 提權
$ sudo -i

# 檢查 kubelet 狀態
$ systemctl status kubelet

# 將 kubelet 重啟
$ systemctl start kubelet

# 將 kubelet 設為開機自動啟動
$ systemctl enable kubelet

# 檢查 kubelet 狀態
$ systemctl status kubelet

Check Ready Node

Check to see how many nodes are ready (not including nodes tained NoSchedule) and write the number to /opt/KUSC00402/kusc00402.txt.

解答

$ kubectl get nodes | grep 'Ready'
$ kubectl describe node | grep 'NoSchedule'

Service

Reconfigure the existing deployment front-end and add a port specifiction named http exposing port 80/tcp of the existing container nginx.

Create a new service named front-end-svc exposing the container port http.

Configure the new service to also expose the individual Pods via a NodePort on the nodes on which they are scheduled.

解答

匯出 YAML 檔

$ kubectl get deploy front-end -o yaml > deploy.yaml

編輯 YAML 檔

apiVersion: apps/v1
kind: Deployment
...
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - name: http                      # add
          protocol: TCP                   # add
          containerPort: 80               # add

重新建立

$ kubectl replace -f deploy.yaml --force
  • K8S DOC 查詢關鍵字 : nodeport yaml
  • Connecting Applications with Services | Kubernetes 這篇
  • service/networking/nginx-secure-app.yaml 這個 YAML 檔

編輯 Service YAML 檔

apiVersion: v1
kind: Service
metadata:
  name: front-end-svc
#  labels:                                # remove
#    run: my-nginx                        # remove
spec:
  type: NodePort
  ports:
  - port: 80
#    targetPort: 80                       # remove
    protocol: TCP
    name: http
#  - port: 443                            # remove
#    protocol: TCP                        # remove
#    name: https                          # remove
  selector:
    run: nginx                            # 看考試時的標籤

產生 Service

$ kubectl apply -f srv.yaml

NodeSelector

Schedule a pod as follows:

  • name: nginx-kusc00401
  • Image: nginx
  • Node selector: disk=spinning

解答

產生 YAML 檔

$ kubectl run nginx-kusc00401 --image=nginx --dry-run=client -o yaml > pod.yaml

編輯 YAML 檔

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx-kusc00401
  name: nginx-kusc00401
spec:
  containers:
  - image: nginx
    name: nginx-kusc00401
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
  nodeSelector:                         # add
    disk: spinning                      # add
status: {}

產生 pod

$ kubectl apply -f pod.yaml

檢查

$ kubectl get pod -o wide

Pod Logs

Monitor the logs of pod bar and:

  • Extract log lines corresponding to error unable-to-access-website
  • Write them to /opt/KUTR00101/bar

解答

$ kubectl logs bar | grep 'unable-to-access-website' > /opt/KUTR00101/bar

Multi-container Pod

題型 1: Create a pod named kucc8 with a single app container for each of the following images runing inside(there may be between 1 and 4 images specified): nginx + memcached

題型 2: Create a pod named kucc1 with a single app container for each of the following images runing inside(there may be between 1 and 4 images specified): nginx + redis + memcached + consul

題型 1: 解答

產生 YAML 檔

$ kubectl run kucc8 --image=nginx --dry-run=client -o yaml > pod.yaml

編輯 YAML 檔

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: kucc8
  name: kucc8
spec:
  containers:
  - image: nginx
    name: kucc8
    resources: {}
  - image: memcached                    # add and change
    name: kucc8-1                       # add
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

產生 pod

$ kubectl apply -f pod.yaml

題型 2: 解答

產生 YAML 檔

$ kubectl run kucc8 --image=nginx --dry-run=client -o yaml > pod.yaml

編輯 YAML 檔

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: kucc8
  name: kucc8
spec:
  containers:
  - image: nginx
    name: kucc8
    resources: {}
  - image: redis                        # add and change
    name: kucc8-1                       # add
  - image: memcached                    # add and change
    name: kucc8-2                       # add
  - image: consul                       # add and change
    name: kucc8-3                       # add
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

產生 pod

$ kubectl apply -f pod.yaml

PVC

Create a new PersistentVolumeClaim:

  • Name: pv-volume
  • Class: csi-hostpath-sc
  • Capacity: 10Mi

Create a new Pod which mounts the PersistentVolumeClaim as a volume:

  • Name: web-server
  • Image: nginx
  • Mount Path: /usr/share/nginx/html

Configure the new Pod to have ReadWriteOnce access on the volume.

Finally,using kubectl edit or kubectl patch expand the PersistentVolumeClaim to a capacity of 70Mi and record that change.

解答

  • K8S DOC 查詢關鍵字 : pod pv
  • Configure a Pod to Use a PersistentVolume for Storage | Kubernetes 這篇
  • pods/storage/pv-claim.yaml 這篇 YAML 檔
  • pods/storage/pv-pod.yaml 這篇 YAML 檔

編輯 PVC YANL 檔

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-volume                         # change
spec:
  storageClassName: csi-hostpath-sc       # change
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi                       # change

產生 PVC

$ kubectl apply -f pvc.yaml

編輯 pod YAML

apiVersion: v1
kind: Pod
metadata:
  name: web-server                              # change
spec:
  volumes:                                      # add
    - name: task-pv-storage                     # add
      persistentVolumeClaim:                    # add
        claimName: pv-volume                    # change
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:                             # add
        - mountPath: "/usr/share/nginx/html"    # add
          name: task-pv-storage                 # add

產生 Pod

$ kubectl apply -f pod.yaml

將 PVC 的 capacity 調成 70Mi

# 用 nano 編輯
$ export KUBE_EDITOR=nano

# 修改 YAML 檔,將 capacity 設為 70Mi
kubectl get pvc pv-volume
$ k edit pvc pv-volume --record

#檢查
$ k get pvc pv-volume

RBAC

Context You have been asked to create a new ClusterRole for a deployment pipiline and bind it to a specific ServiceAccount scoped a specific namespace.

Task Create a new ClusterRole named deployment-clusterrole that only allows the creation of the following resource types:

  • Deployment
  • StatefulSet
  • DaemonSet

Create a new ServiceAccount named cicd-token in the existing namespace app-team1.

Limited to namespace app-team1, bind the new ClusterRole deployment-clusterrole to the new ServiceAccount cicd-token.

解答

建立 clusterrole

$ kubectl create clusterrole deployment-clusterrole --verb=create \
  --resource=Deployment --resource=StatefulSet --resource=DaemonSet

建立 ServiceAccount

$ kubectl create sa cicd-token -n app-team1

建立 rolebinding

$ kubectl create -n app-team1 rolebinding bind \
  --clusterrole deployment-clusterrole \
  --serviceaccount app-team1:cicd-token

檢查

$ k auth can-i create pod -n app-team1 --as system:serviceaccount:app-team1:cicd-token
no

$ k auth can-i create deploy -n app-team1 --as system:serviceaccount:app-team1:cicd-token
yes

$ k auth can-i create sts -n app-team1 --as system:serviceaccount:app-team1:cicd-token
yes

$ k auth can-i create ds -n app-team1 --as system:serviceaccount:app-team1:cicd-token
yes

PV

題型 1: Create a persistent volume with name app-config, of capacity 1Gi and access mode ReadOnlyMany, the type of volume is hostPath and its location is /svc/app-config.

題型 2: Create a persistent volume with name app-config, of capacity 2Gi and access mode ReadWriteMany, the type of volume is hostPath and its location is /srv/app-config.

題型 1: 解答

  • K8S DOC 查詢關鍵字 : pod pv
  • Configure a Pod to Use a PersistentVolume for Storage | Kubernetes 這篇
  • pods/storage/pv-volume.yaml 這篇 YAML 檔

編輯 PV YAML 檔

apiVersion: v1
kind: PersistentVolume
metadata:
  name: app-config                      # change
#  labels:                              # remove
#    type: local                        # remove
spec:
#  storageClassName: manual             # remove
  capacity:
    storage: 1Gi                        # change
  accessModes:
    - ReadOnlyMany                      # change
  hostPath:
    path: "/srv/app-config"             # change

產生 PV

$ kubectl apply -f pv.yaml

題型 2: 解答

編輯 PV YAML 檔

apiVersion: v1
kind: PersistentVolume
metadata:
  name: app-config                      # change
#  labels:                              # remove
#    type: local                        # remove
spec:
#  storageClassName: manual             # remove
  capacity:
    storage: 2Gi                        # change
  accessModes:
    - ReadWeiteMany                     # change
  hostPath:
    path: "/svc/app-config"             # change

產生 PV

$ kubectl apply -f pv.yaml

cordon & drain

Set the node named ek8s-node-1 as unavaliable and reschedule all pods running on it.

解答

$ kubectl cordon ek8s-node-1
$ kubectl drain ek8s-node-1 --delete-emptydir-data --force --ignore-daemonsets

# 檢查
$ kubectl get node