本文档详细介绍了 Google Distributed Cloud 的手动过程;如果您遇到具有卡住卷或 Pod 的 NFS 装载问题,并且您在创建集群时启用了 DataPlane v2,则会出现以下情况。如果您的工作负载使用的 ReadWriteMany
卷由存储驱动程序提供支持,并且容易受到此问题的影响,则您可能会遇到问题,例如(但不限于):
- Robin.io
- Portworx(
sharedv4
服务卷) csi-nfs
使用 Kubernetes Service (ClusterIP) 和 DataPlane v2 连接到端点时,某些存储架构上的 NFS 装载可能会卡住。这种行为是由于 Linux 内核套接字代码与 Cillium 的 eBPF 程序交互方式存在一些限制。容器可能会在 I/O 时被阻塞,甚至无法终止,因为无法卸载不再的 NFS 装载。
如果您使用托管在 Kubernetes 节点上的 NFS 服务器(包括软件定义或超融合存储解决方案,如 Ondat、Robin.io 或 Portworx)上托管的 RWX
存储,则可能会遇到此问题。
查看现有集群配置
从集群中获取一些现有的配置值。在下一部分中,您将使用这些步骤中的值创建 kube-proxy
清单。
从
cm/cilium-config
获取ClusterCIDR
:kubectl get cm -n kube-system cilium-config -o yaml | grep native-routing-cidr
以下示例输出显示您将使用
192.168.0.0/16
作为ClusterCIDR
:ipv4-native-routing-cidr: 192.168.0.0/16 native-routing-cidr: 192.168.0.0/16
从
anetd
DaemonSet 获取APIServerAdvertiseAddress
和APIServerPort
:kubectl get ds -n kube-system anetd -o yaml | grep KUBERNETES -A 1
以下示例输出显示您将使用
21.1.4.119
作为APIServerAdvertiseAddress
,使用443
作为APIServerPort
:- name: KUBERNETES_SERVICE_HOST value: 21.1.4.119 - name: KUBERNETES_SERVICE_PORT value: "443"
从
anetd
DaemonSet 获取RegistryCredentialsSecretName
:kubectl get ds -n kube-system anetd -o yaml | grep imagePullSecrets -A 1
以下示例输出显示您可以使用
private-registry-creds
作为RegistryCredentialsSecretName
:imagePullSecrets: - name: private-registry-creds
从
anetd
DameonSet 获取Registry
:kubectl get ds -n kube-system anetd -o yaml | grep image
以下示例输出显示您可以使用
gcr.io/gke-on-prem-release
作为Registry
:image: gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
从管理员集群的集群命名空间中
kube-apiserver
的映像标记中获取KubernetesVersion
:KUBECONFIG=ADMIN_KUBECONFIG kubectl get sts -n CLUSTER_NAME kube-apiserver -o yaml | grep image
将
ADMIN_KUBECONFIG
替换为您的管理员集群的 kubeconfig 文件,并将CLUSTER_NAME
替换为您的用户集群的名称。以下示例输出显示您将使用
v1.26.2-gke.1001
作为KubernetesVersion
:image: gcr.io/gke-on-prem-release/kube-apiserver-amd64:v1.26.2-gke.1001 imagePullPolicy: IfNotPresent
准备 kube-proxy
清单
使用在上一部分中获得的值创建并应用 YAML 清单,以将 kube-proxy
部署到您的集群。
在您选择的编辑器中创建一个名为
kube-proxy.yaml
的清单:nano kube-proxy.yaml
复制并粘贴以下 YAML 定义:
apiVersion: apps/v1 kind: DaemonSet metadata: labels: k8s-app: kube-proxy name: kube-proxy namespace: kube-system spec: selector: matchLabels: k8s-app: kube-proxy template: metadata: annotations: scheduler.alpha.kubernetes.io/critical-pod: "" labels: k8s-app: kube-proxy spec: containers: - command: - kube-proxy - --v=2 - --profiling=false - --iptables-min-sync-period=10s - --iptables-sync-period=1m - --oom-score-adj=-998 - --ipvs-sync-period=1m - --ipvs-min-sync-period=10s - --cluster-cidr=ClusterCIDR env: - name: KUBERNETES_SERVICE_HOST value:APIServerAdvertiseAddress - name: KUBERNETES_SERVICE_PORT value: "APIServerPort" image: Registry/kube-proxy-amd64:KubernetesVersion imagePullPolicy: IfNotPresent name: kube-proxy resources: requests: cpu: 100m memory: 15Mi securityContext: privileged: true volumeMounts: - mountPath: /run/xtables.lock name: xtables-lock - mountPath: /lib/modules name: lib-modules imagePullSecrets: - name: RegistryCredentialsSecretName nodeSelector: kubernetes.io/os: linux hostNetwork: true priorityClassName: system-node-critical serviceAccount: kube-proxy serviceAccountName: kube-proxy tolerations: - effect: NoExecute operator: Exists - effect: NoSchedule operator: Exists volumes: - hostPath: path: /run/xtables.lock type: FileOrCreate name: xtables-lock - hostPath: path: /lib/modules type: DirectoryOrCreate name: lib-modules --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: system:kube-proxy roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:node-proxier subjects: - kind: ServiceAccount name: kube-proxy namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: kube-proxy namespace: kube-system
在此 YAML 清单中,设置以下值:
APIServerAdvertiseAddress
:KUBERNETES_SERVICE_HOST
的值,例如21.1.4.119
。APIServerPort
:KUBERNETES_SERVICE_PORT
的值,例如443
。Registry
:Cilium 映像的前缀,例如gcr.io/gke-on-prem-release
。RegistryCredentialsSecretName
:映像拉取 Secret 名称,例如private-registry-creds
。
在编辑器中保存并关闭清单文件。
准备 anetd
补丁
为 anetd
创建并准备更新:
在您所选的编辑器中创建一个名为
cilium-config-patch.yaml
的清单:nano cilium-config-patch.yaml
复制并粘贴以下 YAML 定义:
data: kube-proxy-replacement: "disabled" kube-proxy-replacement-healthz-bind-address: "" retry-kube-proxy-healthz-binding: "false" enable-host-reachable-services: "false"
在编辑器中保存并关闭清单文件。
部署 kube-proxy
并重新配置 anetd
将配置更改应用于集群。请先创建现有配置的备份,然后再应用更改。
备份您当前的
anetd
和cilium-config
配置:kubectl get ds -n kube-system anetd > anetd-original.yaml kubectl get cm -n kube-system cilium-config > cilium-config-original.yaml
使用
kubectl
应用kube-proxy.yaml
:kubectl apply -f kube-proxy.yaml
检查 Pod 是否处于
Running
状态:kubectl get pods -n kube-system -o wide | grep kube-proxy
以下示例精简输出表明 Pod 正确运行:
kube-proxy-f8mp9 1/1 Running 1 (4m ago) [...] kube-proxy-kndhv 1/1 Running 1 (5m ago) [...] kube-proxy-sjnwl 1/1 Running 1 (4m ago) [...]
使用
kubectl
修补cilium-config
ConfigMap:kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yaml
使用
kubectl
修改anetd
:kubectl edit ds -n kube-system anetd
在打开的编辑器中,修改
anetd
的规范。在initContainers
下插入以下内容作为第一项:- name: check-kube-proxy-rules image: Image imagePullPolicy: IfNotPresent command: - sh - -ec - | if [ "$KUBE_PROXY_REPLACEMENT" != "strict" ]; then kube_proxy_forward() { iptables -L KUBE-FORWARD; } until kube_proxy_forward; do sleep 2; done fi; env: - name: KUBE_PROXY_REPLACEMENT valueFrom: configMapKeyRef: key: kube-proxy-replacement name: cilium-config optional: true securityContext: privileged: true
将
Image
替换为anetd
DaemonSet 中其他 Cilium 容器中使用的同一映像,例如gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
。在编辑器中保存并关闭清单文件。
如需应用这些更改,请重新启动集群中的所有节点。为了最大限度地减少中断,您可以在重新启动之前尝试排空每个节点。但是,由于阻止排空进程的 NFS 装载损坏,导致使用 RWX 卷的 Pod 可能会卡在
Terminating
状态。您可以强制删除已屏蔽的 Pod,并允许节点正确排空:
kubectl delete pods -–force -–grace-period=0 --namespace POD_NAMESPACE POD_NAME
将
POD_NAME
替换为您尝试删除的 Pod,将POD_NAMESPACE
替换为其命名空间。