## 1. 一次K8S测试环境故障处理过程: ##
1. 故障描述:
51放假期间公司停电,关掉所有k8s测试机器,包括3台k8s master,5台k8s node,3台ceph机器。放假来电之后启动k8s机器和所有的ceph机器;
开机之后,发现很多k8s服务无法启动,经过判断发现是ceph的存储问题。后续解决ceph存储osd节点down状态问题。但是发现依赖cephfs文件系统的pvc还是不能挂载。因为我们这个环境有两个storageClass,一个是RBD,一个是cephfs。 RBD是刚开始搭建的,因为是kubernetes集群默认提供的RBD控制器,所以配置简单,但是不支持多个主机同时读写的策略。cephfs文件系统的StorageClass可以支持多个主机同时读写,但是不足之处在于Kubernetes默认不支持cephfs存储控制器,所以需要用到第三方的cephfs控制器,才可以创建cephfs的StorageClass。最终也解决了cephfs文件系统的故障问题,K8S所有服务顺利启动,没有造成数据丢失;
2. 故障排查过程记录:
2.1 确认ceph存储故障:
启动k8s集群之后首先发现很多服务都没有自动启动成功,包括我们的一些公共组件,比如jenkins、prometheus、业务容器等。通过以下命令排查出存储故障:
kubectl describe pods -n kube-system jenkins-55c4dcb555-fwpcp Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedMount 12m (x257 over 11h) kubelet, 10.83.32.233 Unable to mount volumes for pod "jenkins-55c4dcb555-fwpcp_kube-system(8b5cda6f-6ffe-11e9-974d-480fcf482f56)": timeout expired waiting for volumes to attach or mount for pod "kube-system"/"jenkins-55c4dcb555-fwpcp". list of unmounted volumes=[jenkins-home]. list of unattached volumes=[plugins tmp jenkins-config plugin-dir secrets-dir jenkins-home jenkins-token-vb27p]
复制
然后我登录存储的管理机器(就是安装ceph-deploy)组件的机器,执行如下命令检查存储:
[root@k8sdemo-ceph1 ~]# ceph -s cluster 119b3a1c-17ad-43c8-9378-a625b8dd19d9 health HEALTH_WARN clock skew detected on mon.k8sdemo-ceph2, mon.k8sdemo-ceph3 too many PGs per OSD (1472 > max 300) mds k8sdemo-ceph1 is laggy Monitor clock skew detected monmap e2: 3 mons at {k8sdemo-ceph1=10.83.32.224:6789/0,k8sdemo-ceph2=10.83.32.225:6789/0,k8sdemo-ceph3=10.83.32.234:6789/0} election epoch 4792, quorum 0,1,2 k8sdemo-ceph1,k8sdemo-ceph2,k8sdemo-ceph3 fsmap e1045: 1/1/1 up {0=k8sdemo-ceph1=up:active(laggy or crashed)} osdmap e311: 3 osds: 3 up, 3 in flags sortbitwise,require_jewel_osds pgmap v1226550: 1472 pgs, 5 pools, 119 GB data, 41716 objects 376 GB used, 3433 GB / 3809 GB avail 1472 active+clean client io 2457 B/s wr, 0 op/s rd, 0 op/s wr [root@k8sdemo-ceph1 ~]# #在故障的情况下,这里的osdmap 3 down,经过激活osd盘之后状态变成了up [root@k8sdemo-ceph1 ~]# ceph osd tree ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY -1 3.71986 root default -2 1.52179 host k8sdemo-ceph1 0 1.52179 osd.0 up 1.00000 1.00000 -3 1.52179 host k8sdemo-ceph2 1 1.52179 osd.1 up 1.00000 1.00000 -4 0.67628 host k8sdemo-ceph3 2 0.67628 osd.2 up 1.00000 1.00000 [root@k8sdemo-ceph1 ~]# #在故障的情况下,这里的状态都是down,激活osd之后这里的状态都是up
复制
遇到这种情况我的解决方法如下:
ceph-deploy osd activate k8sdemo-ceph1:/dev/sda4 k8sdemo-ceph2:/dev/sda4 k8sdemo-ceph3:/dev/sda4 #在安装有ceph-deploy管理机器上面执行
复制
后续经过找一下ceph存储的牛人进行确认,因为我们的ceph版本是10.2.11,这个可能是一个BUG。就是重启之后OSD节点不会自动激活,需要手动激活。我们也可以采用启动自动执行激活命令的方式来实现自动激活。解决方案如下:
vim /etc/rc.d/rc.local /usr/sbin/ceph-disk -v activate --mark-init systemd --mount /dev/sda4 chmod +x /etc/rc.d/rc.local #在每一台ceph OSD节点上面增加如上内容:
复制
2.1 确认cephfs文件系统类型的StorageClass故障:
当我解决了OSD节点故障之后,执行如下检查命令:
[root@k8sdemo-ceph1 ~]# ceph osd tree ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY -1 3.71986 root default -2 1.52179 host k8sdemo-ceph1 0 1.52179 osd.0 up 1.00000 1.00000 -3 1.52179 host k8sdemo-ceph2 1 1.52179 osd.1 up 1.00000 1.00000 -4 0.67628 host k8sdemo-ceph3 2 0.67628 osd.2 up 1.00000 1.00000 [root@k8sdemo-ceph1 ~]# ceph -s cluster 119b3a1c-17ad-43c8-9378-a625b8dd19d9 health HEALTH_WARN clock skew detected on mon.k8sdemo-ceph2, mon.k8sdemo-ceph3 too many PGs per OSD (1472 > max 300) mds k8sdemo-ceph1 is laggy Monitor clock skew detected monmap e2: 3 mons at {k8sdemo-ceph1=10.83.32.224:6789/0,k8sdemo-ceph2=10.83.32.225:6789/0,k8sdemo-ceph3=10.83.32.234:6789/0} election epoch 4792, quorum 0,1,2 k8sdemo-ceph1,k8sdemo-ceph2,k8sdemo-ceph3 fsmap e1045: 1/1/1 up {0=k8sdemo-ceph1=up:active(laggy or crashed)} osdmap e311: 3 osds: 3 up, 3 in flags sortbitwise,require_jewel_osds pgmap v1226550: 1472 pgs, 5 pools, 119 GB data, 41716 objects 376 GB used, 3433 GB / 3809 GB avail 1472 active+clean client io 2457 B/s wr, 0 op/s rd, 0 op/s wr
复制
发现我们的ceph存储OSD节点状态已经是UP了。通过查看kubernetes里面的服务,大部分服务已经正常启动了。但是发现还有一部分服务没有正常启动。通过排查这些应用都是依赖于cephfs这个sc的.
[root@master-01 gitlab]# kubectl get sc NAME PROVISIONER AGE cephfs ceph.com/cephfs 26d dynamic (default) kubernetes.io/rbd 31d
复制
我们的k8s集群有两个sc,dynamic这个名称的RBD类型的ceph存储已经好了,但是cephfs这个名称的cephfs类型的存储还没有好。后面的排查思路是:
[root@master-01 cephfs_provisioner]# kubectl describe pvc -n kube-system claim2 Name: claim2 Namespace: kube-system StorageClass: cephfs Status: Pending Volume: Labels: <none> Annotations: volume.beta.kubernetes.io/storage-class: cephfs volume.beta.kubernetes.io/storage-provisioner: ceph.com/cephfs Finalizers: [kubernetes.io/pvc-protection] Capacity: Access Modes: Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Provisioning 97s ceph.com/cephfs_cephfs-provisioner-79d97b7bdf-rq8lm_58dc76ce-6dc4-11e9-8803-6e4d7afb9686 External provisioner is provisioning volume for claim "kube-system/claim2" Normal ExternalProvisioning 1s (x9 over 97s) persistentvolume-controller waiting for a volume to be created, either by external provisioner "ceph.com/cephfs" or manually created by system administrator Mounted By: test-pod2 [root@master-01 cephfs_provisioner]# # 通过查看依赖于cephfs StorageClass的pvc,发现pv创建不成功,告警如上 [root@node-01 ~]# mount -t ceph 10.83.32.224:/ /mnt/cephfs -o name=admin,secret=AQDvBadczen5HRAAD9G3IIU4v9IUtQC6Qf0g5w== mount: special device 10.83.32.224:/ does not exist # 然后我不用k8s掉cephfs存储的接口,直接在一台虚拟机上面mount cephfs也是不成功,可以确认和k8s没有关系,就是cephfs的问题;
复制
1. 先把cephfs的第三方插件控制器的资源都重启一下:
[root@master-01 rbac]# pwd /data/cephfs_provisioner/external-storage/ceph/cephfs/deploy/rbac [root@master-01 rbac]# ll total 24 -rw-r--r--. 1 root root 288 Apr 9 18:12 clusterrolebinding.yaml -rw-r--r-- 1 root root 743 May 6 11:07 clusterrole.yaml -rw-r--r--. 1 root root 670 Apr 9 18:16 deployment.yaml -rw-r--r--. 1 root root 268 Apr 9 18:12 rolebinding.yaml -rw-r--r--. 1 root root 321 Apr 9 18:12 role.yaml -rw-r--r--. 1 root root 98 Apr 9 18:12 serviceaccount.yaml [root@master-01 rbac]# kubectl delete -f ./ [root@master-01 rbac]# kubectl create -f ./
复制
发现问题依旧,说明不是第三方存储provisioner的问题。需要找cephfs端的问题;
2. 在ceph端另建一个cephfs文件系统进行测试:
当我在ceph端另建一个cephfs文件系统的时候,还发生了一个小插曲。其实ceph官方文档中有说明不建议在ceph存储上面创建两个cephfs,容易造成数据丢失等问题;
为了测试,我还是建立一个cephfs2,操作命令如下:
ceph osd pool create fs_kube_data2 128 #创建第二个ceph数据卷 ceph osd pool create fs_kube_metadata2 128 #创建第二个ceph元数据卷 ceph fs flag set enable_multiple true # 由于ceph不建议开启两个cephfs,所以需要开启运行多个cephfs的选项 ceph fs new cephfs2 fs_kube_metadata2 fs_kube_data2 #创建第二个cephfs文件系统,如果创建了第二个cephfs文件系统,还需要设置default的cephfs才可以别k8s调用 ceph fs set_default cephfs2 #设置刚才创建的cephfs2文件系统为默认的文件系统
复制
然后我在测试k8s里面调用cephfs的接口创建pv和在虚拟机里面挂载cephfs都可以了
[root@node-01 ~]# mount -t ceph 10.83.32.224:/ /mnt/cephfs -o name=admin,secret=AQDvBadczen5HRAAD9G3IIU4v9IUtQC6Qf0g5w== 成功了 #挂载第一个cephfs文件系统异常,更改为第二个cephfs2文件系统之后再次挂载就成功了.这里的密钥是如何查出来的? cd /etc/ceph/ #登录ceph的管理机器,然后进入到/etc/ceph目录 #查看 ceph.client.admin.keyring 文件内容 total 16 -rw------- 1 root root 129 May 6 14:40 ceph.client.admin.keyring -rw-r--r-- 1 root root 286 May 6 14:40 ceph.conf -rw-r--r-- 1 root root 3394 May 6 15:17 ceph-deploy-ceph.log -rw-r--r-- 1 root root 92 Jul 10 2018 rbdmap -rw------- 1 root root 0 Apr 5 15:37 tmp9rbpHS [root@k8sdemo-ceph1 ceph]# ceph-deploy --overwrite-conf admin node-01 #将密钥文件推送到节点1,然后在节点1的机器上面/etc/ceph目录下面就会有这些密钥文件 #然后就可以通过mount -t ceph mon服务器地址:/ mount_point -o name=用户名,secret=密钥文件内容 #也可以使用ceph-fuse -m 10.83.32.234:6789 /mnt 但是一定要安装ceph-fuse软件才可以 ;
复制
通过这个步骤的验证可以确认,就是cephfs这个文件有问题,重新创建一个cephfs2的文件系统就没有问题了。但是因为我们的cephfs文件系统里面有数据,包括我们k8s的harbor存储都是运行在cephfs文件系统的sc上面。所以还是要解决cephfs这个名称的sc问题;
3. 找到解决方案彻底解决问题:
最后经过高人的指点,原来是因为我们的mds服务没有启动成功的原因。mds服务没有启动成功的原因又是因为当初的OSD盘down的原因。但是修复了OSD盘之后为啥MDS服务不会自动启动就不知道啥原因了,可能也是ceph的一个BUG吧。
ceph mds stat #此命令可以查出那台机器是mds元数据服务器,然后登录那台机器执行下面的命令 systemctl restart ceph-mds@target #重启所有服务cdph-mds,解决了问题
复制
刚才我也说过ceph官方是建议一个ceph存储只能创建一个cephfs文件系统,所以我们刚才测试创建的第二个cephfs2文件系统,也给系统造成了比较多的报错,主要如下:
# cephfs状态异常: [root@k8sdemo-ceph1 9.1_head]# ceph -s cluster 119b3a1c-17ad-43c8-9378-a625b8dd19d9 health HEALTH_ERR clock skew detected on mon.k8sdemo-ceph2 too many PGs per OSD (1984 > max 300) mds rank 0 has failed mds cluster is degraded Monitor clock skew detected monmap e2: 3 mons at {k8sdemo-ceph1=10.83.32.224:6789/0,k8sdemo-ceph2=10.83.32.225:6789/0,k8sdemo-ceph3=10.83.32.234:6789/0} election epoch 4798, quorum 0,1,2 k8sdemo-ceph1,k8sdemo-ceph2,k8sdemo-ceph3 fsmap e1056: cephfs-0/1/1 up cephfs2-1/1/1 up {[cephfs2:0]=k8sdemo-ceph1=up:active}, 1 failed osdmap e329: 3 osds: 3 up, 3 in flags sortbitwise,require_jewel_osds pgmap v1240137: 1984 pgs, 9 pools, 119 GB data, 41828 objects 376 GB used, 3432 GB / 3809 GB avail 1984 active+clean client io 1831 B/s wr, 0 op/s rd, 0 op/s wr [root@k8sdemo-ceph1 9.1_head]# [root@k8sdemo-ceph1 9.1_head]# ceph fs get cephfs Filesystem 'cephfs' (1) fs_name cephfs epoch 1049 flags 0 created 2019-04-09 15:58:55.124618 modified 2019-04-15 13:07:31.060391 tableserver 0 root 0 session_timeout 60 session_autoclose 300 max_file_size 1099511627776 last_failure 0 last_failure_osd_epoch 328 compat compat={},rocompat={},incompat={1=base v0.20,2=client writeable ranges,3=default file layouts on dirs,4=dir inode in separate object,5=mds uses versioned encoding,6=dirfrag is stored in omap,8=file layout v2} max_mds 1 in 0 up {} failed 0 damaged stopped data_pools 3 metadata_pool 4 inline_data disabled [root@k8sdemo-ceph1 9.1_head]# ceph health HEALTH_ERR clock skew detected on mon.k8sdemo-ceph2; too many PGs per OSD (1984 > max 300); mds rank 0 has failed; mds cluster is degraded; Monitor clock skew detected [root@k8sdemo-ceph1 9.1_head]# [root@k8sdemo-ceph1 9.1_head]# ceph mds stat e1061: cephfs-1/1/1 up cephfs2-0/1/1 up {[cephfs:0]=k8sdemo-ceph1=up:active}, 1 failed [root@k8sdemo-ceph1 9.1_head]# # 有多个状态输出命令包含了mds rank 0 has failed的报错,其实归根接地是因为我们创建了第二个cephfs2文件系统,删除掉这个cephfs2就没有问题了 ceph fs rm cephfs2 --yes-i-really-mean-it #删除第二个cephfs2文件系统 [root@k8sdemo-ceph1 9.1_head]# ceph -s cluster 119b3a1c-17ad-43c8-9378-a625b8dd19d9 health HEALTH_WARN clock skew detected on mon.k8sdemo-ceph2 too many PGs per OSD (1984 > max 300) Monitor clock skew detected monmap e2: 3 mons at {k8sdemo-ceph1=10.83.32.224:6789/0,k8sdemo-ceph2=10.83.32.225:6789/0,k8sdemo-ceph3=10.83.32.234:6789/0} election epoch 4798, quorum 0,1,2 k8sdemo-ceph1,k8sdemo-ceph2,k8sdemo-ceph3 fsmap e1062: 1/1/1 up {0=k8sdemo-ceph1=up:active} osdmap e331: 3 osds: 3 up, 3 in flags sortbitwise,require_jewel_osds pgmap v1242816: 1984 pgs, 9 pools, 119 GB data, 41816 objects 376 GB used, 3432 GB / 3809 GB avail 1984 active+clean client io 3723 B/s wr, 0 op/s rd, 2 op/s wr #告警解除
复制
4. 总结的一些经验和技巧:
4.1 pvc删除了,pv是好的,如何恢复pvc?
# 1.设置pv的数据回收策略是Retain,默认用helm安装的都是delete策略,pvc删除的话数据就会丢失; kubectl patch pv pvc-24cdfbe7-6b3b-11e9-b64b-5065f3457c8c -p '{"spec": {"persistentVolumeReclaimPolicy": "Retain" }}' 2. 创建一个pvc的清单文件,引用pv的名字 [root@master-01 ~]# cat pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins namespace: kube-system spec: accessModes: - ReadWriteOnce # - ReadWriteMany storageClassName: dynamic volumeName: pvc-24cdfbe7-6b3b-11e9-b64b-5065f3457c8c resources: requests: storage: 8Gi [root@master-01 ~] #注意这里的pvc名字,命名空间,sc的名字,pv的名字,容量 这些都需要对应上那个丢失pvc的pv的值 # 3. 修改pv的状态 kubectl edit pv pvc-24cdfbe7-6b3b-11e9-b64b-5065f3457c8c 将以下内容给删除掉 claimRef: apiVersion: v1 kind: PersistentVolumeClaim name: jenkins namespace: kube-system resourceVersion: "10532614" uid: 24cdfbe7-6b3b-11e9-b64b-5065f3457c8c # 再次查看pv就是属于available状态,并且没有关联的pvc名字 4. kubectl apply -f pvc.yaml #重新建立同名的pvc
复制
4.2 ceph存储端权限变更了,如何更新k8s里面的secrets
#1. 修改用户的权限 Ceph auth caps client.kube mon 'allow rwx' osd 'allow rw pool=fs_kube_data' mds 'allow rwp' # 2. 查看密钥 [root@k8sdemo-ceph1 ceph]# ceph auth get-key client.admin | base64 QVFEdkJhZGN6ZW41SFJtestUQ5RzNJSVU0djlJVXRRQzZRZjBnNXc9PQ== [root@k8sdemo-ceph1 ceph]# # 3. 更新RBD StorageClass依赖的secret的key [root@master-01 ceph]# cat ceph-secret.yaml apiVersion: v1 kind: Secret metadata: name: ceph-secret namespace: kube-system data: key: QVFEdkJhZGN6ZW41SFJtestUQ5RzNJSVU0djlJVXRRQzZRZjBnNXc9PQ== type: kubernetes.io/rbd [root@master-01 ceph]# cat ceph-user-secret.yaml apiVersion: v1 kind: Secret metadata: name: ceph-user-secret namespace: kube-system data: key: QVFDTks2ZGNjcEZoQmhtestWs4anVvbmVXZnZUeitvMytPbGZ6OFE9PQ== type: kubernetes.io/rbd # 4. 重建secret和sc kubectl replace -f ceph-secret.yaml --force kubectl replace -f ceph-user-secret.yaml --force kubectl replace -f ceph-storageclass.yaml --force # 5. 推送相关的密钥文件到k8s node节点 ceph-deploy --overwrite-conf admin node-01 scp -r ceph.client.kube.keyring root@node-01:/etc/ceph/
复制
4.3 更新helm的时候,如果已经有PVC了,如何使用原有的PVC
# 修改jenkins helm value.yaml文件, existingClaim: "jenkins" ## jenkins data Persistent Volume Storage Class ## jenkins data Persistent Volume Storage Class ## If defined, storageClassName: <storageClass> ## If set to "-", storageClassName: "", which disables dynamic provisioning ## If undefined (the default) or set to null, no storageClassName spec is ## set, choosing the default provisioner. (gp2 on AWS, standard on ## GKE, AWS & OpenStack) ## # storageClass: "dynamic" # 注释storageClass的值,开启existingClaim,将内容修改为现有的pvc jenkins
复制
4.4 在k8s里面如何使用命令扩展?
# kubectl这个命令行工具非常重要,与之相关的命令也很多,我们也记不住那么多的命令,而且也会经常写错,所以命令自动补全是非常有必要的,kubectl命令行工具本身就支持complication,只需要简单的设置下就可以了。以下是linux系统的设置命令: source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ~/.bashrc
复制
4.5 还有一些个人的经验如下:
有状态应用尽量不要放在K8S集群,比如RabbitMQ、Redis、Mysql等。因为这些应用是有状态应用,比如RabbitMQ有3个Pod,这3个Pod都需要有顺序的启动。只有按照顺序启动之后才能保持集群的状态。
共享存储对于K8S集群至关重要,如果存储出现故障,所有依赖于存储的服务都无法正常启动。特别是一些公共组件肯定会依赖于共享存储,比如 jenkins prometheus监控 EFK日志平台 RabbitMQ、Redis、Mysql GitLab等等。
Ceph存储的学习成本非常高,我们目前的能力只是能够搭建Ceph集群,一旦Ceph集群出现故障排查问题的能力远远不够;
在K8S集群里面使用的PV有一个数据回收策略,默认是DELETE,一定要将这个策略调整成Retain.可以通过打补丁的方式完成:
kubectl patch pv pvc-24cdfbe7-6b3b-11e9-b64b-5065f3457c8c -p ‘{“spec”: {“persistentVolumeReclaimPolicy”: “Retain” }}’在K8S集群关机和开机的过程中,有一个启动的优先顺序,应该按照启动顺序来启动服务器;我个人理解的顺序如下:
启动: ceph存储服务器—》K8S master节点—》K8S node节点; 关机: K8S node节点—》K8S master节点 ---》ceph存储服务器
复制自启动服务一定要检查完整,保证依赖的服务都可以开机自启动。目前我总结的开机自启动的服务包括:
k8s master节点: kube-apiserver.service kube-controller-manager.service kube-proxy.service kube-scheduler.service k8s node节点: kube-proxy.service kubelet.service docker.service ceph节点: ceph-mds@.service ceph-mon@.service ceph-osd@.service [root@k8sdemo-ceph1 ~]# cat /etc/rc.d/rc.local #!/bin/bash touch /var/lock/subsys/local ulimit -SHn 102400 echo "8192" > /sys/block/sda/queue/read_ahead_kb /usr/sbin/ceph-disk -v activate --mark-init systemd --mount /dev/sda4
复制
在做技术的过程中,一定要总结文档,只有总结了文档才可以形成知识共享和积累,对于后续的同样问题能够及时得到解决;并且再解决问题的过程中,建议多看官方文档和google搜索答案;