이 문서에서는 볼륨 또는 포드가 중단된 NFS 마운트에 문제가 있고 DataPlane v2가 사용 설정된 클러스터를 만든 경우 Google Distributed Cloud에 대한 수동 절차를 자세히 설명합니다.
이 문제는 다음 버전에서 해결되었습니다.
- 마이너 버전 1.16의 경우 버전 1.16.4-gke.37 이상
- 마이너 버전 1.28의 경우 버전 1.28.200-gke.111 이상
이 문제가 해결된 버전으로 업그레이드하는 것이 좋습니다. 업그레이드할 수 없으면 다음 섹션에 설명된 절차를 따르세요.
이 문제가 해결되지 않은 버전을 사용하는 경우 해당 워크로드에서 이 문제에 취약한 스토리지 드라이버로 구동되는 ReadWriteMany
볼륨이 사용되면 다음과 같은 문제가 발생할 수 있습니다(이에 국한되지 않음).
- Robin.io
- Portworx(
sharedv4
서비스 볼륨) csi-nfs
일부 스토리지 아키텍처의 NFS 마운트는 Kubernetes Service(ClusterIP) 및 DataPlane v2를 통해 엔드포인트에 연결되면 중단될 수 있습니다. 이 동작은 Linux 커널 소켓 코드가 Cilium의 eBPF 프로그램과 상호작용하는 방식에 제한이 있기 때문입니다. 사용되지 않는 NFS 마운트를 마운트 해제할 수 없으므로 컨테이너가 I/O에서 차단되거나 컨테이너를 종료하지 못할 수 있습니다.
Ondat, Robin.io 또는 Portworx와 같은 소프트웨어 정의 또는 하이퍼컨버지드 스토리지 솔루션을 포함하여 Kubernetes 노드에서 실행되는 NFS 서버에 호스팅되는 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
매니페스트 준비
이전 섹션에서 가져온 값을 사용하여 kube-proxy
를 클러스터에 배포하는 YAML 매니페스트를 만들고 적용합니다.
원하는 편집기에서
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
: 이미지 가져오기 보안 비밀 이름입니다(예: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
포드가
Running
인지 확인합니다.kubectl get pods -n kube-system -o wide | grep kube-proxy
다음 출력 예시에서는 포드가 올바르게 실행되고 있음임을 보여줍니다.
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 볼륨을 사용하는 포드가
Terminating
상태로 중단될 수 있습니다.차단된 포드를 강제로 삭제하고 노드가 올바르게 드레이닝되도록 허용할 수 있습니다.
kubectl delete pods -–force -–grace-period=0 --namespace POD_NAMESPACE POD_NAME
POD_NAME
을 삭제하려는 포드로,POD_NAMESPACE
를 해당 네임스페이스로 바꿉니다.