故障排查和解决方案

创建 rabc 权限

创建一个名为 deployment-clusterrole 且仅允许创建以下资源类型的新ClusterRole:

  • Deployment
  • StatefulSet
  • DaemonSet

在现有的 namespace app-team1 中创建一个名为 cicd-token 的新ServiceAccount。
限于 namespace app-team1 中,将新的 ClusterRole deployment-clusterrole 绑定到新的 ServiceAccount cicd-token。

解决方案:

rolebinding 后面的名字 cicd-token-rolebinding 随便起的,因为题目中没有要求,如果题目中有要求,就不能随便起了。题目中写了“限于 namespace app-team1 中”,则创建 rolebinding。没有写的话,则创建 clusterrolebinding。

kubectl create clusterrole deployment-clusterrole –verb create–resource deployments,statefulsets,daemonsets
kubectl -n app-team1 create serviceaccount cicd-token
kubectl -n app-team1 create rolebinding cicd-token-rolebinding–clusterrole deployment-clusterrole –serviceaccount app-team1:cicd-token

查询 cpu 占用率最高的 pod

通过 pod label name=overloaded-cpu,找到运行时占用大量 CPU 的 pod, 并将占用 CPU 最高的 pod 名称写入文件 /opt/KUTR000401/KUTR00401.txt (已 存在)。

解决方案:
将 cpu占用最高的 pod写入指定文件即可。

kubectl top pod -l name=overloaded-cpu --sort-by cpu -A
echo 查出来的 Pod Name > /opt/KUTR000401/KUTR00401.txt

deployment 扩容副本

将 deployment webserver 扩展至 6 个 pods

kubectl scale deployment webserver --replicas=6

pod 通过 label 标签指定节点部署

按如下要求调度一个 pod:

  • 名称:nginx-kusc00401
  • Image:nginx
  • Node selector:disk=ssd

参考文档open in new window
解决方案:

kubectl get nodes --show-labels | grep disk |grep ssd
# 一般是已经存在的,如果不存在 label,需要任选一个节点手动新建 label
kubectl label nodes node01 disk=ssd
vim label-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-kusc00401
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disk: ssd
kubectl apply -f label-pod.yaml

创建 pv

创建名为 app-data 的 persistent volume,容量为 1Gi,访问模式为 ReadWriteMany。
volume 类型为 hostPath,位于 /srv/app-data
参考文档open in new window
解决方案:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: app-data
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  hostPath:
   path: /srv/app-data
kubectl apply -f pv.yaml

查询 pod 日志

监控 pod foobar 的日志并:
提取与错误 unable-to-access-website 相对应的日志行
将这些日志行写入 /opt/KUTR00101/foobar
解决方案:

kubectl logs foobar | grep unable-to-access-website > /opt/KUTR00101/foobar

排查集群故障节点

名为 wk8s-node-0 的 Kubernetes worker node 处于 NotReady 状态。
调查发生这种情况的原因,并采取相应的措施将 node 恢复为 Ready 状态,确保所做的任何更改永久生效。
解决方案:

ssh wk8s-node-0
sudo -i
systemctl status kubelet
systemctl start kubelet
systemctl enable kubelet
exit #退出 root
exit #退出 wk8s-node-0回到 wk8s-node-1
# 本质原因就是 wk8s-node-0的 kubelet 被停止运行了,重启 kubelet并设置开机自启动即可。

查看集群可用节点

检查有多少 nodes 已准备就绪(不包括被打上 Taint:NoSchedule 的节点),并将数量写入 /opt/KUSC00402/kusc00402.txt
解决方案:

kubectl describe nodes | grep -i Taints
echo 没有 NoSchedule标记的节点数 > /opt/KUSC00402/kusc00402.txt

创建包含多个容器的 pod

按如下要求调度一个 Pod:

  • 名称:kucc4
  • app containers: 2
  • container 名称/images:
    • nginx
    • memcached

参考文档open in new window
解决方案:

vim con-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kucc4
spec:
  containers:
  - name: nginx
    image: nginx
  - name: memcached
    image: memcached
kubcctl apply -f con-pod.yaml

集群节点维护

将名为 ek8s-node-0 的 node 设置为不可用,并重新调度该 node 上所有运行的 pods。
解决方案:

kubectl cordon ek8s-node-0
kubectl drain ek8s-node-0 --ignore-daemonsets
# 但如果执行后有报错则需要加上--delete-emptydir-data --force会强制将pod 移除,一般用不到。
# kubectl drain node02 --ignore-daemonsets --delete-emptydir-data --force

NetworkPolicy 网络策略

在现有的 namespace my-app 中创建一个名为 allow-port-from-namespace 的新 NetworkPolicy。
确保新的 NetworkPolicy 允许 namespace corp-net 中的 Pods 连接到namespace echo 中的 Pods 的 9000 端口。
进一步确保新的 NetworkPolicy:

  • 不允许对没有在监听 端口 9000 的 Pods 的访问
  • 不允许非来自 namespace echo 中的 Pods 的访问

参考文档open in new window
解决方案:

vim networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-port-from-namespace
  namespace: echo #被访问者
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              project: corp-net #访问者
      ports:
        - protocol: TCP
          port: 9000
kubectl apply -f networkpolicy.yaml

Deployment 暴露端口/创建 Service

请重新配置现有的 deployment front-end 以及添加名为 http 的端口规范来公开现有容器 nginx 的端口 80/tcp。
创建一个名为 front-end-svc 的新 service,以公开容器端口 http。
配置此 service,以通过各个 Pod 所在的节点上的 NodePort 来公开他们。
参考文档open in new window
解决方案:

#edit deployment 然后添加端口信息,注意添加位置
kubectl edit deployment front-end
ports:
  - containerPort: 80
    name: http-web-svc
kubectl expose deployment front-end --type=NodePort --port=80 --
target-port=80 --name=front-end-svc

暴露服务后检查一下 service 的 selector 标签是否正确,这个要与deployment 的 selector 标签一致的。

kubectl get svc front-end-svc -o wide
kubectl get deployment front-end -o wide

如果你 kubectl expose 暴露服务后发现 service 的 selector 标签是空的,kubectl edit svc front-end-svc在 ports 这一小段下面添加 selector标签

selector:
app: front-end

创建 Ingress

如下创建一个新的 nginx Ingress 资源:

  • 名称: ping
  • Namespace: ing-internal

使用服务端口 5678 在路径 /hello 上公开服务 hello
可以使用以下命令检查服务 hello 的可用性,该命令应返回 hello:

curl -kL <INTERNAL_IP>/hello  

参考文档open in new window
解决方案:
ingressclass、ingress 写在同一个 yaml文件中, ingressclass不需要更改内容。

vim ingress.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  labels:
    app.kubernetes.io/component: controller
  name: nginx-example
  annotations:
    ingressclass.kubernetes.io/is-default-class: true
spec:
  controller: k8s.io/ingress-nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ping
  namespace: ing-internal #注意新增 namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx-example
  rules:
    - http:
      paths:
        - path: /hello
          pathType: Prefix
          backend:
            service:
              name: hello
              port:
                number: 5678
kubectl apply -f ingress.yaml

检查

kubectl get ingress -n ing-internal
curl http://ingress-IP/hello

创建 pvc 及挂载 pvc 的 pod

创建一个新的 PersistentVolumeClaim:

  • 名称: pv-volume
  • Class: csi-hostpath-sc
  • 容量: 10Mi

创建一个新的 Pod,来将 PersistentVolumeClaim 作为 volume 进行挂载:

  • 名称:web-server
  • Image:nginx
  • 挂载路径:/usr/share/nginx/html

参考文档open in new window

解决方案:
创建 pvc.yaml

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

创建 pvc-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: web-server
spec:
  volumes:
    - name: task-pv-storage #与下面对应 task-pv-storage可不更改
      persistentVolumeClaim:
        claimName: pv-volume #对应 pvc.yaml的 name
  containers:
    - name: nginx #容器名题目无要求可随意更改
      image: nginx
      volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: task-pv-storage #与上面对应 task-pv-storage可不更改
kubectl apply -f pvc.yaml
kubectl apply -f pvc-pod.yaml

sidecar 边车容器

将一个现有的 Pod 集成到 Kubernetes 的内置日志记录体系结构中(例如kubectl logs)。添加 streaming sidecar 容器是实现此要求的一种好方法。

使用 busybox Image 来将名为 sidecar 的 sidecar 容器添加到现有的 Podbig-crop-app 中。
新的 sidecar 容器必须运行以下命令:
/bin/sh -c tail -n+1 -f /var/log/big-crop-app.log
使用挂载在/var/log 的 Volume,使日志文件 big-crop-app.log 可用于sidecar 容器。
除了添加所需要的 volume mount 以外,请勿更改现有容器的规格。
参考文档open in new window
解决方案:
sidercar

kubectl get pod big-factor-app -o yaml >> varlog.yam
cp varlog.yaml varlog-bak.yaml
vim varlog.yaml

sidercar
sidercar

kubectl delete pod big-factor-app
kubectl apply -f varlog.yaml

检查

kubectl logs 11-factor-app sidecar
kubectl exec 11-factor-app -c sidecar -- tail -f /var/log/big-factor-app.log
kubectl exec 11-factor-app -c count -- tail -f /var/log/big-factor-app.log

升级集群

现有的 Kubernetes 集群正在运行版本 1.28.1。仅将 master 节点上的所有Kubernetes 控制平面和节点组件升级到版本 1.28.2。
确保在升级之前 drain master 节点,并在升级后 uncordon ssh mk8s-master-0 节点。
可以使用以下命令,通过 ssh 连接到 master 节点:
ssh mk8s-master-0
可以使用以下命令,在该 master 节点上获取更高权限:
sudo -i
另外,在主节点上升级 kubelet 和 kubectl。
请不要升级工作节点,etcd,container 管理器,CNI 插件, DNS 服务或任何其他插件。

升级顺序:调度节点--kubeadm--plan--集群--kubelet—kubectl

解决方案:

kubectl get nodes
kubectl cordon ssh mk8s-master-0
kubectl drain ssh mk8s-master-0 --ignore-daemonsets
ssh ssh mk8s-master-0
sudo -i
apt-get update
apt-cache show kubeadm|grep 1.28.2
apt-get install kubeadm=1.28.2-00
kubeadm version
kubeadm upgrade plan
kubeadm upgrade apply v1.28.2 --etcd-upgrade=false
apt-get install kubelet=1.28.2-00
kubelet --version
apt-get install kubectl=1.28.2-00
kubectl version
exit
exit
kubectl get nodes

备份还原 etcd

首先,为运行在 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

解决方案:

#加载环境
export ETCDCTL_API=3
#备份
etcdctl --endpoints=https://11.0.1.111: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
#检查,会出现一个 db详情表
etcdctl snapshot status /var/lib/backup/etcd-snapshot.db -wtable
#还原,需要用 sudo
sudo etcdctl –endpoints=https://11.0.1.111: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
Last Updated:
Contributors: jobcher