k3s 中 selflink 问题排查解决
# 问题描述
在部署 statefulset 类型的工作负载时,动态创建 PV/PVC 是一种比较常用的配置方式,动态创建 PV/PVC 的方法基本如下:
- 1、创建自己的 StorageClass 备用。
- 2、创建 statefulset ,在 yaml 文件的
volumeClaimTemplates
块,添加 StorageClass 的名字。
说回今天遇到的问题,在部署 VictoriaMetric 时,想使用阿里云的 nfs 做为外部存储,以进一步提高可用性。先使用 mysql 的 demo 案例(yaml 示例见这里 k8s-yaml-hub (opens new window)),来测试下 statefulset 的在使用 nfs 时的分部情况。
一直启动不动来,查看 pvc 和 pods 信息如下:
- 1、PVC 一直处于 pending 状态;
- 2、mysql pods 显示:
0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.
# 原因分析
从上边的现象来看,是 PVC 没有创建成功,动态 PVC 中,是 provisioner 中来负责创建,查看其日志,看到如下错误信息:
I0214 10:22:35.436913 1 controller.go:1068] scheduleOperation[provision-mysql-sts/mysql-pvc-mysql-0[ac333031-e705-48d9-8180-4d2d583bb559]]
E0214 10:22:35.444757 1 controller.go:766] Unexpected error getting claim reference to claim "mysql-sts/mysql-pvc-mysql-0": selfLink was empty, can't make reference
2
Google 之后,很多人遇到了同样的问题,主要原因是,官方在 k8s 1.20 中基于对性能和统一apiserver
调用方式的初衷,移除了对 SelfLink 的支持,而 nfs-provisioner 需要 SelfLink 该项功能。具体计划和原因可查看这个issue (opens new window) 和 KEP (opens new window)。
K3S 为兼容 K8S 应该也继承了该项修改,按 K8S 的方式修改测试了下,完美解决。
# 解决方案
解决问题主要有下边两种方式:
1、修改 apiserver 的配置文件,重新启用 SelfLink 功能。针对 K8S,可添加如下配置:
# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- kube-apiserver
...
- --feature-gates=RemoveSelfLink=false # 增加
2
3
4
5
6
7
8
K3S 中没有 apiserver 的配置文件,可通过 systemd 的启动文件添加该参数,如下:
# /etc/systemd/system/k3s.service
ExecStart=/usr/local/bin/k3s \
server \
...
'--kube-apiserver-arg' \ # 新增
'feature-gates=RemoveSelfLink=false' \ # 新增
2
3
4
5
6
7
若为新安装,可如下启用:
$ curl -sfL https://get.k3s.io | sh -s - --kube-apiserver-arg "feature-gates=RemoveSelfLink=false"
2、使用新的不基于 SelfLink 功能的 provisioner 镜像,重新创建 provisioner 容器。
若你能科学上网,可使用这个镜像:
gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0
国内可使用这个镜像:
registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0
记录备查,希望对你有帮助。