במאמר הזה מוסבר איך להשתמש ב-NodeLocal DNSCache כדי להפחית את זמן האחזור של חיפוש DNS ולשפר את הביצועים של האפליקציה באשכול Google Kubernetes Engine (GKE).
NodeLocal DNSCache הוא תוסף ל-GKE שמשפר את הביצועים של DNS על ידי הפעלת מטמון DNS ישירות בכל צומת של אשכול כ-DaemonSet. כש-Pods שולחים בקשת DNS, הבקשה עוברת קודם למטמון המקומי באותו צומת. טיפול בבקשות באופן מקומי מצמצם באופן משמעותי את הזמן הממוצע לחיפוש DNS ומפחית את העומס על ספק ה-DNS המרכזי של האשכול, כמו kube-dns או Cloud DNS for GKE. הסבר מפורט על ארכיטקטורת DNS והיתרונות של NodeLocal DNSCache זמין במאמר מידע על איתור שירותים.
באשכולות GKE Autopilot, NodeLocal DNSCache מופעל כברירת מחדל, ואי אפשר להשבית אותו. באשכולות GKE Standard שפועלת בהם גרסה 1.34.1-gke.3720000 ואילך, NodeLocal DNSCache מופעל כברירת מחדל, אבל אפשר להשבית אותו.
המסמך הזה מיועד למשתמשי GKE, כולל מפתחים, אדמינים וארכיטקטים. מידע נוסף על תפקידים נפוצים ומשימות לדוגמה ב- Google Cloudזמין במאמר תפקידים נפוצים של משתמשי GKE ומשימות.
במסמך הזה אנחנו יוצאים מנקודת הנחה שאתם מכירים את הנושאים הבאים:
ארכיטקטורה
NodeLocal DNSCache הוא תוסף ל-GKE שאפשר להפעיל בנוסף ל-kube-dns.
GKE מטמיע את NodeLocal DNSCache כ-DaemonSet שמפעיל מטמון DNS בכל צומת באשכול.
כש-Pod שולח בקשת DNS, הבקשה מועברת למטמון ה-DNS שפועל באותו צומת כמו ה-Pod. אם אי אפשר ליצור רזולוציית DNS מהבקשה במטמון, המטמון מעביר את הבקשה לאחד מהמקומות הבאים, בהתאם ליעד של השאילתה ולספק ה-DNS שהוגדר:
- kube-dns: כל השאילתות לגבי דומיין ה-DNS של האשכול (
cluster.local) מועברות אלkube-dns. ה-Pods של node-local-dns משתמשים ב-kube-dns-upstreamService כדי לגשת ל-Pods שלkube-dns. - דומיינים מותאמים אישית או שרתי שמות במעלה הזרם: השאילתות מועברות ישירות מ-Pods של NodeLocal DNSCache.
- Cloud DNS: כל השאילתות האחרות מועברות לשרת המטא-נתונים המקומי שפועל באותו צומת שממנו הגיעה השאילתה. שרת המטא-נתונים המקומי ניגש ל-Cloud DNS.
כשמפעילים את NodeLocal DNSCache באשכול קיים, מערכת GKE יוצרת מחדש את כל הצמתים באשכול שמריצים GKE בגרסה 1.15 ואילך, בהתאם לתהליך שדרוג הצמתים.
אחרי ש-GKE יוצר מחדש את הצמתים, הוא מוסיף להם באופן אוטומטי את התווית addon.gke.io/node-local-dns-ds-ready=true. אסור להוסיף את התווית הזו לצמתי האשכול באופן ידני.
היתרונות של NodeLocal DNSCache
היתרונות של NodeLocal DNSCache:
- קיצור הזמן הממוצע של חיפוש DNS
- חיבורים מ-Pods למטמון המקומי שלהם לא יוצרים רשומות בטבלת conntrack. ההתנהגות הזו מונעת ניתוקים ודחיות של חיבורים שנגרמים בגלל מיצוי של טבלת מעקב החיבורים ותנאי מירוץ.
- אפשר להשתמש ב-NodeLocal DNSCache עם Cloud DNS for GKE.
- שאילתות DNS לכתובות URL חיצוניות (כתובות URL שלא מפנות למשאבי אשכול) מועברות ישירות לשרת המטא-נתונים המקומי ועוקפות את
kube-dns. - מטמון ה-DNS המקומי בוחר באופן אוטומטי דומיינים מסוג stub ושרתי שמות במעלה הזרם שצוינו בקטע הוספה של פותרים מותאמים אישית לדומיינים מסוג stub.
דרישות ומגבלות
- NodeLocal DNSCache צורך משאבי מחשוב בכל צומת של האשכול.
- NodeLocal DNSCache לא נתמך במאגרי צמתים של Windows Server.
- כדי להשתמש ב-NodeLocal DNSCache, צריך GKE בגרסה 1.15 ואילך.
- הגישה של NodeLocal DNSCache אל
kube-dnsPods מתבצעת באמצעות TCP. - NodeLocal DNSCache ניגש אל
upstreamServersואלstubDomainsבאמצעות TCP ו-UDP בגרסאות GKE 1.18 ואילך. צריך להיות אפשר להגיע לשרת ה-DNS באמצעות TCP ו-UDP. - רשומות DNS נשמרות במטמון לתקופות הבאות:
- הזמן לחיות (TTL) של הרשומה, או 30 שניות אם ה-TTL גדול מ-30 שניות.
- 5 שניות אם תגובת ה-DNS היא
NXDOMAIN.
- רכיבי ה-Pod של NodeLocal DNSCache מאזינים ביציאות 53, 9253, 9353 ו-8080 בצמתים.
אם מריצים עוד
hostNetworkPod או מגדיריםhostPortsעם הפורטים האלה, NodeLocal DNSCache נכשל ומתרחשות שגיאות DNS. תת-חבילות של NodeLocal DNSCache לא משתמשות במצבhostNetworkכשהן משתמשות ב-GKE Dataplane V2 ולא משתמשות ב-Cloud DNS for GKE. - מטמון ה-DNS המקומי פועל רק במאגרי צמתים שמריצים GKE מגרסה 1.15 ואילך. אם מפעילים את NodeLocal DNSCache באשכול עם צמתים שמריצים גרסאות קודמות, הפודים בצמתים האלה משתמשים ב-
kube-dns.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק ה-API של Google Kubernetes Engine. הפעלת Google Kubernetes Engine API
- אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
- מוודאים שיש לכם אשכול קיים של Autopilot או Standard. אם אתם צריכים כזה, צריך ליצור אשכול Autopilot. באשכולות Autopilot, NodeLocal DNSCache מופעל כברירת מחדל ואי אפשר לבטל את ההגדרה שלו.
הפעלת NodeLocal DNSCache
בגרסאות 1.34.1-gke.3720000 ואילך, NodeLocal DNSCache מופעל כברירת מחדל באשכולות Standard. אם האשכול שלכם הוא בגרסה מוקדמת יותר מ-1.34.1-gke.3720000, אתם יכולים להשתמש ב-CLI של Google Cloud כדי להפעיל את NodeLocal DNSCache באשכולות חדשים או קיימים. אפשר גם להשתמש במסוףGoogle Cloud כדי להפעיל את NodeLocal DNSCache רק באשכולות חדשים.
gcloud
כדי להפעיל את NodeLocal DNSCache באשכול קיים, משתמשים בדגל --update-addons עם הארגומנט NodeLocalDNS=ENABLED:
gcloud container clusters update CLUSTER_NAME \
--location=COMPUTE_LOCATION \
--update-addons=NodeLocalDNS=ENABLED
מחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_NAME: השם של האשכול. -
COMPUTE_LOCATION: המיקום של Compute Engine עבור האשכול.
המסוף
כדי להפעיל את NodeLocal DNSCache באשכול חדש, מבצעים את השלבים הבאים:
נכנסים לדף Google Kubernetes Engine במסוף Google Cloud .
לוחצים על השם של האשכול שרוצים לשנות.
בקטע רישות, בשדה ספק DNS, לוחצים על edit עריכת ספק DNS.
מסמנים את תיבת הסימון Enable NodeLocal DNSCache (הפעלת NodeLocal DNSCache).
לוחצים על שמירת השינויים.
השינוי הזה מחייב ליצור מחדש את הצמתים, מה שעלול לשבש את עומסי העבודה הפעילים. פרטים על השינוי הספציפי הזה מופיעים בשורה המתאימה בטבלה שינויים ידניים שיוצרים מחדש את הצמתים באמצעות אסטרטגיית שדרוג צמתים, בהתאם למדיניות התחזוקה. מידע נוסף על עדכוני צמתים זמין במאמר תכנון שיבושים בעדכון צמתים.
מוודאים ש-NodeLocal DNSCache מופעל
כדי לוודא ש-NodeLocal DNSCache פועל, אפשר להציג את רשימת ה-Pods:node-local-dns
kubectl get pods -n kube-system -o wide | grep node-local-dns
הפלט אמור להיראות כך:
node-local-dns-869mt 1/1 Running 0 6m24s 10.128.0.35 gke-test-pool-69efb6b8-5d7m <none> <none>
node-local-dns-htx4w 1/1 Running 0 6m24s 10.128.0.36 gke-test-pool-69efb6b8-wssk <none> <none>
node-local-dns-v5njk 1/1 Running 0 6m24s 10.128.0.33 gke-test-pool-69efb6b8-bhz3 <none> <none>
בפלט מוצג node-local-dns Pod לכל צומת שמופעלת בו גרסה 1.15 של GKE ואילך.
השבתה של NodeLocal DNSCache
באשכולות GKE Autopilot, NodeLocal DNSCache מופעל כברירת מחדל ואי אפשר להשבית אותו.
השבתה של NodeLocal DNSCache באשכול חדש
אפשר להשבית את NodeLocal DNSCache כשיוצרים אשכול GKE Standard חדש בגרסה 1.34.1-gke.3720000 ואילך, על ידי הפעלת הפקודה הבאה:
gcloud container clusters create CLUSTER_NAME \
--location=COMPUTE_LOCATION \
--addons=NodeLocalDNS=DISABLED
מחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_NAME: השם של האשכול החדש. -
COMPUTE_LOCATION: המיקום של Compute Engine עבור האשכול.
השבתה של NodeLocal DNSCache באשכול קיים
כדי להשבית את NodeLocal DNSCache באשכול GKE קיים, מריצים את הפקודה הבאה:
gcloud container clusters update CLUSTER_NAME \
--location=COMPUTE_LOCATION \
--update-addons=NodeLocalDNS=DISABLED
מחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_NAME: השם של האשכול שרוצים להשבית. -
COMPUTE_LOCATION: המיקום של Compute Engine עבור האשכול.
השינוי הזה מחייב ליצור מחדש את הצמתים, מה שעלול לשבש את עומסי העבודה הפעילים. פרטים על השינוי הספציפי הזה מופיעים בשורה המתאימה בטבלה שינויים ידניים שיוצרים מחדש את הצמתים באמצעות אסטרטגיית שדרוג צמתים, בהתאם למדיניות התחזוקה. מידע נוסף על עדכוני צמתים זמין במאמר תכנון שיבושים בעדכון צמתים.
פתרון בעיות ב-NodeLocal DNSCache
מידע כללי על אבחון בעיות DNS ב-Kubernetes זמין במאמר בנושא ניפוי באגים של רזולוציית DNS.
ההפעלה של NodeLocal DNSCache לא מתבצעת באופן מיידי
כשמפעילים את NodeLocal DNSCache באשכול קיים, יכול להיות ש-GKE לא יעדכן את הצמתים באופן מיידי אם באשכול מוגדר חלון זמן לתחזוקה או החרגה. מידע נוסף זמין במאמר הערות לגבי יצירה מחדש של צמתים וחלונות תחזוקה.
אם לא רוצים לחכות, אפשר להחיל את השינויים על הצמתים באופן ידני על ידי הפעלת הפקודה gcloud container clusters upgrade והעברת הדגל --cluster-version עם אותה גרסת GKE שמאגר הצמתים כבר פועל בה. כדי להשתמש בפתרון העקיף הזה, צריך להשתמש ב-Google Cloud CLI.
NodeLocal DNSCache עם Cloud DNS
אם משתמשים ב-NodeLocal DNSCache עם Cloud DNS, האשכול משתמש בכתובת ה-IP של שרת השמות 169.254.20.10, כמו שמוצג בתרשים הבא:
כתוצאה מכך, כתובת ה-IP של שירות kube-dns עשויה להיות שונה מכתובת ה-IP של שרת השמות שבה נעשה שימוש ב-Pods. ההבדל הזה בכתובות ה-IP צפוי, כי כתובת ה-IP של שרת השמות 169.254.20.10 נדרשת כדי ש-Cloud DNS יפעל בצורה תקינה.
כדי לבדוק את כתובות ה-IP, מריצים את הפקודות הבאות:
הצגת כתובת ה-IP של שירות
kube-dns:kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"הפלט הוא כתובת ה-IP של
kube-dns, למשל10.0.0.10פותחים סשן של מעטפת ב-Pod:
kubectl exec -it POD_NAME -- /bin/bashבסשן של Pod shell, קוראים את התוכן של הקובץ
/etc/resolv.conf:cat /etc/resolv.confהפלט הוא
169.254.20.10
מדיניות רשת עם NodeLocal DNSCache
אם אתם משתמשים במדיניות רשת עם NodeLocal DNSCache ואתם לא משתמשים ב-Cloud DNS או ב-GKE Dataplane V2, אתם צריכים להגדיר כללים שיאפשרו לעומסי העבודה ול-Pods שלכם לשלוח שאילתות DNS.node-local-dns
משתמשים בכלל ipBlock במניפסט כדי לאפשר תקשורת בין ה-Pods לבין kube-dns.
במניפסט הבא מתוארת מדיניות רשת שמשתמשת בכלל ipBlock:
spec:
egress:
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
to:
- ipBlock:
cidr: KUBE_DNS_SVC_CLUSTER_IP/32
podSelector: {}
policyTypes:
- Egress
מחליפים את KUBE_DNS_SVC_CLUSTER_IP בכתובת ה-IP של שירות kube-dns. כדי לקבל את כתובת ה-IP של שירות kube-dns, משתמשים בפקודה הבאה:
kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"
בעיות מוכרות
בקטע הזה מפורטות בעיות מוכרות ב-NodeLocal DNSCache.
תם הזמן הקצוב ל-DNS ב-dnsPolicy ClusterFirstWithHostNet כשמשתמשים ב-NodeLocal DNSCache וב-GKE Dataplane V2
באשכולות שמשתמשים ב-GKE Dataplane V2 וב-NodeLocal DNSCache, Pods עם השדה hostNetwork שמוגדר לערך true והשדה dnsPolicy שמוגדר לערך ClusterFirstWithHostNet לא יכולים לגשת ל-backends של DNS באשכול. יומני DNS עשויים להכיל רשומות שדומות לרשומות הבאות:
dnslookup: write to 'a.b.c.d': Operation not permitted
;; connection timed out; no servers could be reached
הפלט מציין שבקשות ה-DNS לא מגיעות לשרתי הקצה העורפי.
פתרון עקיף הוא להגדיר את השדות dnsPolicy ו-dnsConfig עבור hostNetwork Pods:
spec:
dnsPolicy: "None"
dnsConfig:
nameservers:
- KUBE_DNS_UPSTREAM
searches:
- NAMESPACE.svc.cluster.local
- svc.cluster.local
- cluster.local
- c.PROJECT_ID.internal
- google.internal
options:
- name: ndots
value: "5"
מחליפים את מה שכתוב בשדות הבאים:
-
NAMESPACE: מרחב השמות של ה-podhostNetwork. -
PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
KUBE_DNS_UPSTREAM:ClusterIPשל שירותkube-dnsבמעלה הזרם. אפשר לקבל את הערך הזה באמצעות הפקודה הבאה:kubectl get svc -n kube-system kube-dns-upstream -o jsonpath="{.spec.clusterIP}"
בקשות ה-DNS מה-Pod יכולות עכשיו להגיע אל kube-dns ולעקוף את NodeLocal DNSCache.
שגיאות שקשורות לחלון הזמן הקצוב לתפוגה של NodeLocal DNSCache
באשכולות שבהם מופעל NodeLocal DNSCache, יכול להיות שהיומנים יכילו רשומות דומות לאלה:
[ERROR] plugin/errors: 2 <hostname> A: read tcp <node IP: port>-><kubedns IP>:53: i/o timeout
הפלט כולל את כתובת ה-IP של שירות kube-dns-upstream Cluster IP. בדוגמה הזו, התגובה לבקשת DNS לא התקבלה מ-
kube-dns תוך שתי שניות. יכולות להיות כמה סיבות לבעיה הזו:
- בעיה בקישוריות הרשת.
- עלייה משמעותית בשאילתות DNS מעומס העבודה או מהגדלת הקיבולת של מאגר הצמתים.
כתוצאה מכך, לא ניתן לטפל בכל הבקשות בזמן באמצעות ה-kube-dns Pods הקיימים. הפתרון הוא להגדיל את מספר העותקים של kube-dns על ידי הגדלת הקיבולת של kube-dns.
הגדלת היקף הפעילות kube-dns
כדי להבטיח שייווצרו יותר תרמילי kube-dns בזמן שהצמתים של האשכול מתרחבים, אפשר להשתמש בערך נמוך יותר בשדה nodesPerReplica. מומלץ מאוד להגדיר ערך max מפורש כדי לוודא שהמכונה הווירטואלית (VM) של מישור הבקרה של GKE לא תהיה עמוסה מדי בגלל מספר גדול של פודים kube-dns שעוקבים אחרי Kubernetes API.
אפשר להגדיר בשדה max את מספר הצמתים באשכול. אם באשכול יש יותר מ-500 צמתים, צריך להגדיר את השדה max לערך 500.
במערכות סטנדרטיות, אפשר לשנות את מספר העותקים המשוכפלים של kube-dns על ידי עריכת kube-dns-autoscaler ConfigMap. ההגדרה הזו לא נתמכת באשכולות של Autopilot.
kubectl edit configmap kube-dns-autoscaler --namespace=kube-system
הפלט אמור להיראות כך:
linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'
מספר העותקים המשוכפלים של kube-dns מחושב באמצעות הנוסחה הבאה:
replicas = max(ceil(cores * 1/coresPerReplica), ceil(nodes *
1/nodesPerReplica))
אם מגדירים את השדות min ו-max ב-ConfigMap, העותקים מוגבלים לערכים האלה. כדי להגדיל את מספר המכונות, משנים את הערך של השדה nodesPerReplica לערך קטן יותר וכוללים ערך בשדה max:
linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'
התצורה יוצרת Pod אחד kube-dns לכל שמונה צמתים באשכול. ב-cluster עם 24 צמתים יש 3 עותקים משוכפלים, וב-cluster עם 40 צמתים יש 5 עותקים משוכפלים. אם גודל האשכול גדל מעבר ל-120 צמתים, מספר העותקים המשוכפלים של kube-dns לא גדל מעבר ל-15, שהוא הערך של max.
כדי להבטיח רמת זמינות בסיסית של DNS באשכול, צריך להגדיר מספר מינימלי של עותקים משוכפלים עבור kube-dns.
הפלט של kube-dns-autoscaler ConfigMap עם שדה min מוגדר ייראה כך:
linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'
המאמרים הבאים
- סקירה כללית על האופן שבו GKE מספק DNS מנוהל
- במאמר DNS for Services and Pods (מערכת DNS לשירותים ול-Pods) מופיעה סקירה כללית של השימוש ב-DNS באשכולות Kubernetes.
- איך משתמשים ב-Cloud DNS ל-GKE