במאמר הזה מפורט הליך ידני ל-Google Distributed Cloud אם נתקלתם בבעיות בחיבורי NFS עם נפח או Pod תקועים, ויצרתם את האשכול עם DataPlane v2 מופעל.
הבעיה הזו נפתרה בגרסאות הבאות:
- לגרסה משנית 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 מקיים אינטראקציה עם תוכנית eBPF של Cillium. יכול להיות שהקונטיינרים ייחסמו ב-I/O או אפילו לא יהיה אפשר להרוג אותם, כי אי אפשר לבטל את הטעינה של NFS.
יכול להיות שתיתקלו בבעיה הזו אם אתם משתמשים באחסון RWX שמתארח בשרתי NFS שפועלים בצומת Kubernetes, כולל פתרונות אחסון מוגדרים בתוכנה או היפר-קונברגנטיים כמו Ondat, Robin.io או Portworx.
בדיקת ההגדרות הקיימות של האשכול
מקבלים כמה ערכי הגדרה קיימים מהאשכול. משתמשים בערכים מהשלבים האלה כדי ליצור kube-proxy קובץ מניפסט בסעיף הבא.
קחו את
ClusterCIDRמ-cm/cilium-config: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מקבלים את
APIServerAdvertiseAddressואתAPIServerPortמ-DaemonSetanetd: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"קבלת
RegistryCredentialsSecretNameמ-DaemonSetanetd:kubectl get ds -n kube-system anetd -o yaml | grep imagePullSecrets -A 1בדוגמת הפלט הבאה אפשר לראות שצריך להשתמש ב-
private-registry-credsבתורRegistryCredentialsSecretName:imagePullSecrets: - name: private-registry-credsקחו את
Registryמ-anetdDameonSet: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מקבלים את
KubernetesVersionמתג התמונה שלkube-apiserverבמרחב השמות של האשכול של אשכול האדמין: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: השם של סוד משיכת התמונה, כמו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שימוש בסכום
kube-proxy.yamlבאמצעותkubectl:kubectl apply -f kube-proxy.yamlבודקים שה-Pods הם
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) [...]מבצעים תיקון (patch) ל-ConfigMap
cilium-configבאמצעותkubectl:kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yamlעריכת
anetdבאמצעותkubectl: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באותה תמונה שמשמשת בקונטיינרים האחרים של Cilium ב-DaemonSetanetd, כמוgcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7.שומרים את קובץ המניפסט וסוגרים אותו בעורך.
כדי להחיל את השינויים האלה, צריך להפעיל מחדש את כל הצמתים באשכול. כדי לצמצם את השיבושים, אפשר לנסות לרוקן כל צומת לפני האתחול מחדש. עם זאת, Pods שמשתמשים בנפחים מסוג RWX יכולים להיתקע במצב
Terminatingבגלל טעינות NFS פגומות שחוסמות את תהליך הניקוז.אפשר למחוק בכוח את ה-Pods החסומים ולאפשר ל-Node לנקז את הנתונים בצורה תקינה:
kubectl delete pods -–force -–grace-period=0 --namespace POD_NAMESPACE POD_NAMEמחליפים את
POD_NAMEב-Pod שמנסים למחוק ואתPOD_NAMESPACEבמרחב השמות שלו.
המאמרים הבאים
לקבלת עזרה נוספת, אפשר לפנות אל Cloud Customer Care.
אפשר גם לעיין במאמר קבלת תמיכה לקבלת מידע נוסף על מקורות מידע לתמיכה, כולל:
- דרישות לפתיחת בקשת תמיכה.
- כלים שיעזרו לכם לפתור בעיות, כמו יומנים ומדדים.
- רכיבים, גרסאות ותכונות נתמכים של Google Distributed Cloud ל-VMware (תוכנה בלבד).