גישה לא אחידה לזיכרון (NUMA) מאפשרת לתמוך בעומסי עבודה עם ביצועים גבוהים וזמן אחזור קצר באשכולות ובמכונות וירטואליות (VM). כדי לוודא שעומסי העבודה מתוזמנים ישירות בצומתי NUMA, צריך לכוונן את ההגדרות של Kubernetes בצומתי האשכול ולהגדיר מכונות וירטואליות עם זיקה ל-NUMA.
במכונה וירטואלית שתומכת ב-NUMA, כל התקשורת נשארת מקומית לצומת ה-NUMA. הארכיטקטורה הזו מונעת העברות נתונים מרחוק שעלולות לפגוע בביצועים.
הגדרת צמתים לשימוש ב-NUMA
בקטעים הבאים מוסבר איך להגדיר את הרכיבים הקריטיים של Kubernetes כדי לכוונן את הצומת ולוודא שהוא יכול לתזמן קונטיינרים שמותאמים ל-NUMA. צומתי ה-NUMA האלה מותאמים לאופטימיזציה של ביצועי המעבד והזיכרון. פועלים לפי ההוראות לכל צומת שרוצים להריץ בו מכונות וירטואליות שתומכות ב-NUMA.
עדכון ההגדרות של kubelet
כחלק מהגדרת הצומת לתמיכה ב-NUMA node affinity, צריך לבצע את השינויים הבאים בהגדרת ה-kubelet:
- הפעלת מנהל המעבד (CPU) באמצעות מדיניות
static - הפעלת מנהל הזיכרון באמצעות מדיניות
Static - הפעלת מנהל הטופולוגיה עם טופולוגיה של
restricted
כדי להגדיר את kubelet בצומת העובד:
מאתרים את הקובץ
kubeletבצומת העובד ופותחים אותו לעריכה:edit /etc/default/kubeletאם הקובץ
kubeletלא מופיע, יוצרים אותו באמצעות הפקודה הבאה:echo "KUBELET_EXTRA_ARGS=\"\"" >> /etc/default/kubeletהפקודה הזו יוצרת את הקובץ
kubeletעם קטעKUBELET_EXTRA_ARGS=""ריק.כדי להפעיל את מנהל המעבד (CPU) עם מדיניות
static, מוסיפים את הדגל--cpu-manager-policy=staticלקטעKUBELET_EXTRA_ARGS=""בקובץ:KUBELET_EXTRA_ARGS="--cpu-manager-policy=static"
כדי להפעיל את מנהל הזיכרון באמצעות מדיניות
Static, מוסיפים את הדגל--memory-manager-policy=StaticלקטעKUBELET_EXTRA_ARGS=""בקובץ:KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static"
כדי להפעיל את Topology Manager עם מדיניות
restricted, מוסיפים את הדגל--topology-manager-policy=restrictedלקטעKUBELET_EXTRA_ARGS=""בקובץ:KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static --topology-manager-policy=restricted"
בודקים את כמות הזיכרון הנוכחית ששמורה ל-Google Distributed Cloud:
cat /var/lib/kubelet/kubeadm-flags.envהפלט אמור להיראות כך:
KUBELET_KUBEADM_ARGS="--anonymous-auth=false --authentication-token-webhook=true --authorization-mode=Webhook --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --feature-gates=SeccompDefault=true --kube-reserved=cpu=100m,memory=3470Mi --max-pods=110 --node-ip=192.168.1.190 --node-labels=baremetal.cluster.gke.io/k8s-ip=192.168.1.190,baremetal.cluster.gke.io/namespace=cluster-user001,baremetal.cluster.gke.io/node-pool=node-pool-1,cloud.google.com/gke-nodepool=node-pool-1 --pod-infra-container-image=gcr.io/anthos-baremetal-release/pause-amd64:3.1-gke.5 --provider-id=baremetal://192.168.1.190 --read-only-port=10255 --rotate-server-certificates=true --seccomp-default=true"
ההגדרה
--kube-reserved=cpu=100m,memory=3470Miמציינת ש-Google Distributed Cloud שמר 3,470 mebibytes של זיכרון בצומת.מגדירים את הדגל
--reserved-memoryבקטעKUBELET_EXTRA_ARGSבקובץkubeletל-100 mebibytes יותר מהזיכרון השמור הנוכחי, כדי להביא בחשבון את סף הפינוי. אם אין זיכרון שמור, אפשר לדלג על השלב הזה.לדוגמה, אם הזיכרון השמור הוא
3470Miמהדוגמה בשלב הקודם, אתם שומרים זיכרון של3570Miבקובץkubelet:KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static --topology-manager-policy=restricted --reserved-memory=0:memory=3570Mi"
מסירים את קובצי תמונת המצב של המעבד (CPU) והזיכרון מהספרייה
/var/lib:rm /var/lib/cpu_manager_state rm /var/lib/memory_manager_stateמפעילים מחדש את kubelet:
systemctl start kubelet
מידע נוסף על הגדרות המדיניות האלה זמין במאמרי העזרה הבאים של Kubernetes:
הגדרת הצומת לשימוש ב-hugepages
אחרי שמפעילים את Memory Manager באמצעות המדיניות Static, אפשר להוסיף דפים ענקיים כדי לשפר עוד יותר את הביצועים של עומסי העבודה של מאגרים בצומתי NUMA.
כמו שאפשר להבין מהשם, Hugepages מאפשרים לציין דפי זיכרון שגדולים יותר מהגודל הרגיל של 4 קיביבייט (KiB). ב-VM Runtime on GDC יש תמיכה בדפים גדולים בנפח 2MiB ו-1GiB. אפשר להגדיר דפים גדולים לצומת בזמן הריצה, או כשהמכונה של הצומת מבצעת אתחול. מומלץ להגדיר hugepages בכל צומת שבו רוצים להריץ מכונות וירטואליות עם תמיכה ב-NUMA.
כדי להגדיר את מספר ה-hugepages בגודל מסוים בצומת NUMA בזמן הריצה, משתמשים בפקודה הבאה:
echo HUGEPAGE_QTY > \ /sys/devices/system/node/NUMA_NODE/hugepages/hugepages-HUGEPAGE_SIZEkB/nr_hugepagesמחליפים את מה שכתוב בשדות הבאים:
HUGEPAGE_QTY: מספר ה-hugepages שצריך להקצות בגודל שצוין.
NUMA_NODE: צומת ה-NUMA, כמוnode0, שאליו מקצים דפים גדולים.
HUGEPAGE_SIZE: הגודל של דפי ה-hugepages ב-KiB, 2048(2MiB) או1048576(1GiB).
הגדרת מכונה וירטואלית לשימוש בצומת NUMA
אחרי שמתאימים את צומתי האשכול ל-NUMA, אפשר ליצור מכונות וירטואליות שתומכות ב-NUMA. מכונות וירטואליות שתומכות ב-NUMA מתוזמנות בצומתי NUMA.
כדי ליצור מכונה וירטואלית שתואמת ל-NUMA:
פועלים לפי ההוראות ליצירת VM ממניפסט.
כדי להגדיר את המכונה הווירטואלית כך שתהיה מותאמת ל-NUMA, משתמשים בהגדרות הבאות של
compute:
spec.compute.guaranteed: מגדירים אתguaranteedלהיותtrue. בהגדרה הזו, ה-Pod שלvirt-launcherמוגדר כך שיוצב ב-Kubernetes Guaranteed Quality of Service (QoS) class.spec.compute.advancedCompute:-
dedicatedCPUPlacement: מגדירים אתdedicatedCPUPlacementלהיותtrue. ההגדרה הזו מצמידה מעבדים וירטואליים למעבדים הפיזיים של הצומת. -
hugePageSize: מגדירים אתhugePageSizeלערך2Miאו1Giכדי לציין את גודל ה-hugepages לשימוש ב-VM, 2 mebibyte או 1 gibibyte. -
numaGuestMappingPassthrough: צריך לכלול מבנה ריק ({}) להגדרה הזו. ההגדרה הזו קובעת את הזיקה ל-NUMA, כך שהמכונה הווירטואלית תתוזמן רק בצומתי NUMA.
-
במניפסט הבא של VirtualMachine אפשר לראות איך נראית הגדרה של VM עם תמיכה ב-NUMA:
apiVersion: vm.cluster.gke.io/v1 kind: VirtualMachine metadata: name: vm1 spec: compute: cpu: vcpus: 2 guaranteed: true advancedCompute: dedicatedCPUPlacement: true hugePageSize: 2Mi numaGuestMappingPassthrough: {} memory: capacity: 256Mi interfaces: - name: eth0 networkName: pod-network default: true disks: - virtualMachineDiskName: disk-from-gcs boot: true readOnly: true