自动补全
echo "source <(kubectl completion bash)" >> ~/.profile
echo "alias k=kubectl" >> ~/.profile
echo "complete -F __start_kubectl k" >> ~/.profile
source ~/.profile
vim 设置为粘贴模式, 防止缩进问题
echo "set paste" >> ~/.vimrc
1、权限控制 RBAC
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Context
为部署流水线创建一个新的 ClusterRole 并将其绑定到范围为特定的 namespace 的特定 ServiceAccount。
Task
创建一个名为 deployment-clusterrole 且仅允许创建以下资源类型的新 ClusterRole:
Deployment
StatefulSet
DaemonSet
在现有的 namespace app-team1 中创建一个名为 cicd-token 的新 ServiceAccount。
限于 namespace app-team1 中,将新的 ClusterRole deployment-clusterrole 绑定到新的 ServiceAccount cicd-token。
考点:
RBAC 授权模型的理解。
参考链接:
没必要参考网址,使用-h 帮助更方便。
kubectl create clusterrole -h
kubectl create rolebinding -h
https://kubernetes.io/docs/reference/access-authn-authz/rbac/#command-line-utilities
解答:
更换 context
$ kubectl config use-context k8s
创建 ClusterRole
$ kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployment,daemonset,statefulset
创建 ServiceAccount
$ kubectl create sa cicd-token -n app-team1
创建 rolebinding
rolebinding 后面的名字 cicd-token-rolebinding 随便起的,因为题目中没有要求,如果题目中有要求,就不能随便起了。
kubectl -n app-team1 create rolebinding cicd-token-rolebinding --clusterrole=deployment-clusterrole --serviceaccount=app-team1:cicd-token
检查
$ kubectl -n app-team1 describe rolebinding cicd-token-rolebinding
$ kubectl auth can-i create deployment --as system:serviceaccount:app-team1:cicd-token
no
$ kubectl auth can-i create deployment -n app-team1 --as system:serviceaccount:app-team1:cicd-token
yes
2、查看 pod 的 CPU
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
通过 pod label name=cpu-loader,找到运行时占用大量 CPU 的 pod,
并将占用 CPU 最高的 pod 名称写入文件 /opt/KUTR000401/KUTR00401.txt(已存在)。
考点:
kubectl top –l 命令的使用
参考链接:
https://kubernetes.io/docs/reference/kubectl/cheatsheet/#interacting-with-running-pods
解答:
更换 context
$ kubectl config use-context k8s
# 查看 pod 名称 -A 是所有 namespace
$ kubectl top pod -l name=cpu-loader --sort-by=cpu -A
# 将 cpu 占用最多的 pod 的 name 写入/opt/test1.txt 文件
$ echo "查出来的 Pod Name" > /opt/KUTR000401/KUTR00401.txt
检查
$ cat /opt/KUTR000401/KUTR00401.txt
3、配置网络策略 NetworkPolicy
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context hk8s
Task
在现有的 namespace my-app 中创建一个名为 allow-port-from-namespace 的新 NetworkPolicy。
确保新的 NetworkPolicy 允许 namespace echo 中的 Pods 连接到 namespace my-app 中的 Pods 的 9000 端口。
进一步确保新的 NetworkPolicy:
不允许对没有在监听 端口 9000 的 Pods 的访问 不允许非来自 namespace echo 中的 Pods 的访问
双重否定就是肯定,所以最后两句话的意思就是:
仅允许端口为 9000 的 pod 方法。
仅允许 echo 命名空间中的 pod 访问。
考点:
NetworkPolicy 的创建
参考链接:
依次点击 Concepts → Services, Load Balancing, and Networking → Network Policies(看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/concepts/services-networking/network-policies/
解答:
更换 context
$ kubectl config use-context hk8s
查看 namespace echo 的标签
# 查看所有 ns 的标签 label
$ kubectl get ns --show-labels
# 如果访问者的 namespace 没有标签 label,则需要手动打一个。如果有一个独特的标签 label,则也可以直接使用。
$ kubectl label ns echo project=echo
创建 networkpolicy
vim networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: my-app #被访问者的命名空间
spec:
podSelector: #这两行必须要写,或者也可以写成一行为 podSelector: {}
matchLabels: {} # 注意 matchLabels:与{}之间有一个空格
policyTypes:
- Ingress #策略影响入栈流量
ingress:
- from: #允许流量的来源
- namespaceSelector:
matchLabels:
project: echo #访问者的命名空间的标签 label
#- podSelector: {} #注意,这个不写。如果 ingress 里也写了- podSelector: {},则会导致 my-app 中的 pod 可以访问 my-app 中 pod 的 9000 了,这样不 满足题目要求不允许非来自 namespace echo 中的 Pods 的访问。
ports:
- protocol: TCP
port: 9000 #被访问者公开的端口
创建
$ kubectl apply -f networkpolicy.yaml
检查
$ kubectl describe networkpolicy -n my-app
4、暴露服务 service
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
请重新配置现有的 deployment front-end 以及添加名为 http 的端口规范来公开现有容器 nginx 的端口 80/tcp。
创建一个名为 front-end-svc 的新 service,以公开容器端口 http。
配置此 service,以通过各个 Pod 所在的节点上的 NodePort 来公开他们。
考点:
将现有的 deploy 暴露成 nodeport 的 service。
参考链接:
依次点击 Concepts → Workloads → Workload Resources → Deployments(看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/
解答:
更换 context
$ kubectl config use-context k8s
修改 deployment
$ kubectl edit deployment front-end
......
spec:
containers:
- image: vicuu/nginx:hello
imagePullPolicy: IfNotPresent
name: nginx #找到此位置。下文会简单说明一下 yaml 文件的格式,不懂 yaml 格式的,往下看。
ports: #添加这 4 行
- name: http
containerPort: 80
protocol: TCP
......
暴露端口
$ kubectl expose deployment front-end --type=NodePort --port=80 --target-port=80 --name=front-end-svc
检查
$ kubectl get svc front-end-svc -o wide
5、创建 Ingress
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
如下创建一个新的 nginx Ingress 资源:
名称: ping
Namespace: ing-internal
使用服务端口 5678 在路径 /hello 上公开服务 hello
可以使用以下命令检查服务 hello 的可用性,该命令应返回 hello:
curl -kL <INTERNAL_IP>/hello
考点:
Ingress 的创建
参考链接:
依次点击 Concepts → Services, Load Balancing, and Networking → Ingress (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/
解答:
更换 context
$ kubectl config use-context k8s
创建 ingressclass
$ vim ingressclass.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
name: nginx
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
$ kubectl apply -f ingressclass.yaml
创建 ingress
$ vim ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ping
namespace: ing-internal
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello
port:
number: 5678
$ kubectl apply -f ingress.yaml
检查
$ kubectl apply -f ingress.yaml
也可以 curl 一下 ingress 地址
6、扩容 deployment 副本数量
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
将 deployment presentation 扩展至 4 个 pods
考点:
deployment 扩缩容
参考链接:
没必要参考网址,使用-h 帮助更方便。
kubectl scale deployment -h
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/#scaling-a-deployment https://kubernetes.io/zh-cn/docs/tasks/run-application/scale-stateful-set/
解答:
更换 context
$ kubectl config use-context k8s
修改replicaset
$ kubectl scale deployment presentation --replicas=4
检查
$ kubectl get deployment presentation -oyaml
7、调度 pod 到指定节点
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
按如下要求调度一个 pod:
名称:nginx-kusc00401
Image:nginx
Node selector:disk=ssd
考点:
nodeSelect 属性的使用
参考链接:
依次点击 Tasks → Configure Pods and Containers → Assign Pods to Nodes (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes/
解答:
更换 context
$ kubectl config use-context k8s
创建 pod yaml
# 获取一个 pod 模版
$ kubectl run nginx-kusc00401 --image=nginx --dry-run -oyaml > 7.pod.yaml
$ cat 7.pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-kusc00401
spec:
nodeSelector: # 新增, 其余内容不需要
disk: ssd
containers:
- image: nginx
name: nginx-kusc00401
创建 pod
$ kubectl create -f 7.pod.yaml
pod/nginx-kusc00401 created
检查
$ kubectl get po -owide
8、查看可用节点数量
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
检查有多少 nodes 已准备就绪(不包括被打上 Taint:NoSchedule 的节点), 并将数量写入 /opt/KUSC00402/kusc00402.txt
考点:
检查节点角色标签,状态属性,污点属性的使用
参考链接:
没必要参考网址,使用-h 帮助更方便。
kubectl -h
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/
解答:
更换 context
$ kubectl config use-context k8s
检查就绪 node
$ k describe no | grep -i taint
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Taints: node-role.kubernetes.io/control-plane:NoSchedule
Taints: <none>
# 考试根据实际环境, 这里有 2 个节点被打上 NoSchedule
$ echo 1 > /opt/KUSC00402/kusc00402.txt
检查
$ cat /opt/KUSC00402/kusc00402.txt
9、创建多容器的 pod
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
按如下要求调度一个 Pod:
名称:kucc8
app containers: 2 container 名称/images:
⚫ nginx
⚫ consul
考点:
pod 概念
参考链接:
依次点击 Concepts → Workloads → Pods (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/
解答:
更换 context
$ kubectl config use-context k8s
创建 pod yaml
没指定 namespace 就是 default 不用填
# 获取一个 pod 模版
$ kubectl run kucc8 --image=nginx --dry-run=client -oyaml > 9.pod.yaml
$ cat 9.pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: kucc8
spec:
containers:
- image: nginx
name: nginx
- image: cousul
name: consul
创建 pod
$ kubectl create -f 9.pod.yaml
检查
$ kubectl get pod
10、创建 PV
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context hk8s
Task
创建名为 app-config 的 persistent volume,容量为 1Gi,访问模式为 ReadWriteMany。 volume 类型为 hostPath,位于 /srv/app-config
考点:
hostPath 类型的 pv
参考链接:
依次点击 Tasks → Configure Pods and Containers → Configure a Pod to Use a PersistentVolume for Storage (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
解答:
更换 context
$ kubectl config use-context hk8s
创建 pv yaml
# 复制官网模版, 修改
$ cat 10.pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-config # 名
labels:
type: local
spec:
# storageClassName: manual 题目没指定
capacity:
storage: 1Gi # 容量
accessModes:
- ReadWriteMany # 读写权限
hostPath:
path: "/srv/app-config" # 题目有指定
创建 pv
$ kubectl create -f 10.pv.yaml
检查
$ kubectl describe pv app-config
11、创建 PVC
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context ok8s
Task
创建一个新的 PersistentVolumeClaim:
名称: pv-volume
Class: csi-hostpath-sc
容量: 10Mi
创建一个新的 Pod,来将 PersistentVolumeClaim 作为 volume 进行挂载:
名称:web-server
Image:nginx:1.16
挂载路径:/usr/share/nginx/html
配置新的 Pod,以对 volume 具有 ReadWriteOnce 权限。
最后,使用 kubectl edit 或 kubectl patch 将 PersistentVolumeClaim 的容量扩展为 70Mi,并记录此更改。
考点:
pvc 的创建 class 属性的使用,–record 记录变更
参考链接:
依次点击 Tasks → Configure Pods and Containers → Configure a Pod to Use a PersistentVolume for Storage (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
解答:
更换 context
$ kubectl config use-context ok8s
创建 pvc
# 复制官网模版, 按题目修改响应字段
$ cat 11.pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-volume
spec:
storageClassName: csi-hostpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
$ kubectl create -f 11.pvc.yaml
创建 pod
# 获取 pod 模版
$ kubectl run web-server --image=nginx:1.16 --dry-run=client -oyaml > 11.pod.yaml
$ cat 11.pod.yaml # 挂载 pvc
apiVersion: v1
kind: Pod
metadata:
labels:
run: web-server
name: web-server
spec:
volumes:
- name: 11-pvc
persistentVolumeClaim:
claimName: pv-volume
containers:
- image: nginx:1.16
name: web-server
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: 11-pvc
$ kubectl create -f 11.pod.yaml
修改 pvc 并记录
$ kubectl edit pvc pv-volume --record
12、查看 pod 日志
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
监控 pod foo 的日志并:
提取与错误 RLIMIT_NOFILE 相对应的日志行 将这些日志行写入 /opt/KUTR00101/foo
考点:
kubectl logs 命令
参考链接:
没必要参考网址,使用-h 帮助更方便。
kubectl -h
https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/#examine-pod-logs
解答:
$ kubectl logs foo | grep RLIMIT_NOFILE > /opt/KUTR00101/foo
检查
$ cat /opt/KUTR00101/foo
13、使用 sidecar 代理容器日志
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Context
将一个现有的 Pod 集成到 Kubernetes 的内置日志记录体系结构中(例如 kubectl logs)。 添加 streaming sidecar 容器是实现此要求的一种好方法。
Task
使用 busybox Image 来将名为 sidecar 的 sidecar 容器添加到现有的 Pod 11-factor-app 中。 新的 sidecar 容器必须运行以下命令:
/bin/sh -c tail -n+1 -f /var/log/11-factor-app.log
使用挂载在/var/log 的 Volume,使日志文件 11-factor-app.log 可用于 sidecar 容器。 除了添加所需要的 volume mount 以外,请勿更改现有容器的规格。
考题翻译成白话,就是:
添加一个名为 sidecar 的边车容器(使用 busybox 镜像),加到已有的 pod 11-factor-app 中。 确保 sidecar 容器能够输出 /var/log/11-factor-app.log 的信息。
使用 volume 挂载 /var/log 目录,确保 sidecar 能访问 11-factor-app.log 文件
考点:
pod 两个容器共享存储卷
参考链接:
(需要复制网页内容)
依次点击 Concepts → Cluster Administration → Logging Architecture (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/logging/
解答:
更换 context
$ kubectl config use-context k8s
获取 pod yaml
$ kubectl get pod 11-factor-app -o yaml > varlog.yaml
# 备份 yaml 文件,防止改错了,回退。
$ cp varlog.yaml varlog-bak.yaml
修改 yaml
spec:
。。。。。。
volumeMounts: #在原配置文件,灰色的这段后面添加
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-4l6w8
readOnly: true
- name: varlog #新加内容
mountPath: /var/log #新加内容
- name: sidecar #新加内容,注意 name 别写错了
image: busybox #新加内容
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/11-factor-app.log'] #新加内容,注意 文件名 别写错了。另外是用逗号分隔的,而题目里是空格。
volumeMounts: #新加内容
- name: varlog #新加内容
mountPath: /var/log #新加内容
dnsPolicy: ClusterFirst
enableServiceLinks: true
。。。。。。
volumes: #在原配置文件,灰色的这段后面添加。
- name: kube-api-access-kcjc2
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef: apiVersion: v1
fieldPath: metadata.namespace
path: namespace
- name: varlog #新加内容,注意找好位置。
emptyDir: {} #新加内容
创建 pod
$ kubectl delete -f varlog.yaml
$ kubectl createe -f varlog.yaml
检查
$ kubectl exec 11-factor-app -c sidecar -- tail -f /var/log/11-factor-app.log
$ kubectl exec 11-factor-app -c count -- tail -f /var/log/11-factor-app.log
14、升级集群
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context mk8s
Task
现有的 Kubernetes 集群正在运行版本 1.28.0。仅将 master 节点上的所有 Kubernetes 控制平面和节点组件升级到版本 1.28.1。
确保在升级之前 drain master 节点,并在升级后 uncordon master 节点。
可以使用以下命令,通过 ssh 连接到 master 节点:
ssh master01
可以使用以下命令,在该 master 节点上获取更高权限:
sudo -i
另外,在主节点上升级 kubelet 和 kubectl。
请不要升级工作节点,etcd,container 管理器,CNI 插件, DNS 服务或任何其他插件。
考点:
如何离线主机,并升级控制面板和升级节点
参考链接:
没必要参考网址,建议多练习,背过命令就行。
记不清的,可以使用 kubectl -h 来帮助。
如果非要参考,可以按照下面方法。
依次点击 Tasks → Administer a Cluster → Administration with kubeadm → Upgrading kubeadm clusters (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
解答:
更换 context
$ kubectl config use-context mk8s
ssh 到 master01
$ ssh master01
$ sudo -i
排空节点
$ kubectl cordon master
$ kubectl drain master
升级 kubeadm
$ apt update
$ apt-cache madison kubeadm | grep 1.28.1
# apt 升级 kubeadm
$ apt-get install kubeadm=1.28.1-00 -y
# kubeadm 升级集群, 注意不要升级 etcd, 忘记怎么写, 可以 -h
$ kubeadm upgrade apply 1.28.1 --etcd-upgrade=false
升级 kubectl, kubelet
$ apt-get install kubectl=1.28.1-00 kubelet=1.28.1-00 -y
检查
$ kubeadm version
$ kubectl version
$ kubelet --version
# 记得使节点可重新调度
$ kubectl uncordon master01
$ exit # 退到 node01
15、备份还原 etcd
题目:
设置配置环境
此项目无需更改配置环境。但是,在执行此项目之前,请确保您已返回初始节点。
[candidate@master01] $ exit #注意,这个之前是在 master01 上,所以要 exit 退到 node01,如果已经是 node01 了,就不要再 exit 了。
Task
首先,为运行在 https://127.0.0.1:2379 上的现有 etcd 实例创建快照并将快照保存到 /var/lib/backup/etcd-snapshot.db
为给定实例创建快照预计能在几秒钟内完成。 如果该操作似乎挂起,则命令可能有问题。用 CTRL + C 来取消操作,然后重试。 然后还原位于/data/backup/etcd-snapshot-previous.db 的现有先前快照。
提供了以下 TLS 证书和密钥,以通过 etcdctl 连接到服务器。
CA 证书: /opt/KUIN00601/ca.crt
客户端证书: /opt/KUIN00601/etcd-client.crt
客户端密钥: /opt/KUIN00601/etcd-client.key
考点:
etcd 的备份和还原命令
参考链接:
没必要参考网址,建议多练习,背过命令就行。
记不清的,可以使用 etcdctl -h 来帮助,更方便。
如果非要参考,可以按照下面方法。
依次点击 Tasks → Administer a Cluster → Operating etcd clusters for Kubernetes (看不懂英文的,可右上角翻译成中文)
https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd/
解答:
注意:
- 记得设置 ETCDCTL_API=3
- 如果文件没权限, 就 sudo -i
备份快照
$ sudo ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/opt/KUIN00601/ca.crt --cert=/opt/KUIN00601/etcd-client.crt --key=/opt/KUIN00601/etcd-client.key snapshot save /var/lib/backup/etcd-snapshot.db
恢复快照
$ sudo ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/opt/KUIN00601/ca.crt --cert=/opt/KUIN00601/etcd-client.crt --key=/opt/KUIN00601/etcd-client.key snapshot restore /data/backup/etcd-snapshot-previous.db
检查
# 没必要
$ etcdctl snapshot status /var/lib/backup/etcd-snapshot.db -wtable
16、排查集群中故障节点
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context wk8s
Task
名为 node02 的 Kubernetes worker node 处于 NotReady 状态。
调查发生这种情况的原因,并采取相应的措施将 node 恢复为 Ready 状态,确保所做的任何更改永久生效。
可以使用以下命令,通过 ssh 连接到 node02 节点:
ssh node02
可以使用以下命令,在该节点上获取更高权限:
sudo -i
参考链接:
没必要参考网址,记住先 restart 再 enable 就行。
https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/kubelet-integration/
解答:
更换 context
$ kubectl config use-context wk8s
ssh 到 node02 查看 kubelet
$ ssh node02
$ sudo -i # root
# 查看 kubelet 状态
$ systemctl status kubelet
$ systemctl restart kubelet && systemctl enable kubelet
检查
$ systemctl status kubelet
# 考试时记得从 node2 退回到 node1
$ exit
$ exit
17、节点维护
题目:
设置配置环境:
[candidate@node-1] $ kubectl config use-context ek8s
Task
将名为 node02 的 node 设置为不可用,并重新调度该 node 上所有运行的 pods。
考点:
cordon 和 drain 命令的使用
参考链接:
没必要参考网址,使用-h 帮助更方便。
kubectl -h
https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/safely-drain-node/
解答:
更换 context
$ kubectl config use-context ek8s
排空节点
$ kubectl cordon node02
$ kubectl drain node02