Kube-scheduler เป็นส่วนประกอบที่สำคัญของ Kubernetes ซึ่งมีหน้าที่รับผิดชอบในการกำหนดเวลาพ็อดข้ามโหนดตามนโยบายที่ระบุ บ่อยครั้ง ระหว่างการทำงานของคลัสเตอร์ Kubernetes เราไม่ต้องคิดให้แน่ชัดว่าจะใช้นโยบายใดในการจัดกำหนดการพ็อด เนื่องจากชุดนโยบายเริ่มต้นของ kube-scheduler เหมาะสำหรับงานประจำวันส่วนใหญ่ อย่างไรก็ตาม มีบางสถานการณ์ที่เราต้องปรับแต่งการกระจายของพ็อดโดยละเอียด และมีสองวิธีในการทำงานนี้ให้สำเร็จ:
- สร้าง kube-scheduler ด้วยชุดกฎที่กำหนดเอง
- เขียนตัวกำหนดตารางเวลาของคุณเองและสอนให้ทำงานกับคำขอเซิร์ฟเวอร์ API
ในบทความนี้ ฉันจะอธิบายการใช้งานจุดแรกอย่างตรงจุดเพื่อแก้ปัญหาการตั้งเวลาพ็อดที่ไม่สม่ำเสมอในโครงการใดโครงการหนึ่งของเรา
แนะนำสั้น ๆ เกี่ยวกับการทำงานของ kube-scheduler'a
ข้อควรสังเกตคือข้อเท็จจริงที่ว่า kube-scheduler ไม่ได้มีหน้าที่รับผิดชอบในการตั้งเวลาพ็อดโดยตรง - มีหน้าที่เพียงกำหนดโหนดที่จะวางพ็อดเท่านั้น กล่าวอีกนัยหนึ่ง ผลลัพธ์ของการทำงานของ kube-scheduler คือชื่อของโหนดที่ส่งคืนไปยังเซิร์ฟเวอร์ API สำหรับคำขอการตั้งเวลา และนี่คือจุดสิ้นสุดของการทำงาน
ขั้นแรก kube-scheduler จะแสดงรายการโหนดที่ Pod สามารถกำหนดเวลาได้ตามนโยบายเพรดิเคต นอกจากนี้ แต่ละโหนดจากรายการนี้จะได้รับคะแนนจำนวนหนึ่งตามนโยบายลำดับความสำคัญ เป็นผลให้เลือกโหนดที่มีคะแนนสูงสุด หากมีโหนดที่มีคะแนนสูงสุดเท่ากัน ระบบจะเลือกโหนดแบบสุ่ม รายการและคำอธิบายของนโยบายเพรดิเคต (การกรอง) และลำดับความสำคัญ (การให้คะแนน) สามารถพบได้ใน
คำอธิบายของเนื้อหาปัญหา
แม้จะมีคลัสเตอร์ Kubernetes ที่แตกต่างกันจำนวนมากที่ดูแลอยู่ใน Nixys ในตอนแรก เราพบปัญหาของการจัดตารางเวลาพ็อดเมื่อไม่นานมานี้ เมื่อหนึ่งในโปรเจ็กต์ของเราจำเป็นต้องรันงานเป็นระยะจำนวนมาก (ประมาณ 100 เอนทิตี CronJob) เพื่อลดความซับซ้อนของคำอธิบายปัญหาให้มากที่สุดเท่าที่จะเป็นไปได้ ยกตัวอย่าง ไมโครเซอร์วิสหนึ่งตัว ซึ่งภายในนั้นงาน cron จะถูกเรียกใช้งานนาทีละครั้ง โดยสร้างโหลดบางอย่างบน CPU สำหรับการทำงานของงาน cron มีการจัดสรรโหนดที่เหมือนกันสามโหนด (24 vCPU ในแต่ละโหนด)
ในขณะเดียวกัน ก็ไม่สามารถบอกได้แน่ชัดว่า CronJob จะทำงานนานเท่าใด เนื่องจากจำนวนข้อมูลอินพุตมีการเปลี่ยนแปลงตลอดเวลา โดยเฉลี่ยแล้ว ระหว่างการดำเนินการ kube-scheduler ปกติ แต่ละโหนดจะรันอินสแตนซ์งาน 3-4 รายการ ซึ่งสร้าง ~ 20-30% ของโหลดบน CPU ของแต่ละโหนด:
ปัญหาคือบางครั้งพ็อดงาน cron หยุดการกำหนดเวลาสำหรับหนึ่งในสามโหนด นั่นคือ ณ เวลาใดเวลาหนึ่ง ไม่มีการวางแผนพ็อดเดียวสำหรับหนึ่งในโหนด ขณะที่อินสแตนซ์งาน 6-8 รายการกำลังทำงานบนโหนดอีกสองโหนด ซึ่งสร้าง ~ 40-60% ของโหลดบน CPU:
ปัญหาเกิดขึ้นซ้ำแล้วซ้ำเล่าด้วยความถี่แบบสุ่ม และบางครั้งก็สัมพันธ์กับช่วงเวลาของการเปิดตัวโค้ดเวอร์ชันใหม่
ด้วยการเพิ่มระดับการบันทึกของ kube-scheduler เป็นระดับ 10 (-v=10) เราจึงเริ่มบันทึกคะแนนที่แต่ละโหนดได้คะแนนในกระบวนการประเมิน ระหว่างการจัดกำหนดการปกติ ข้อมูลต่อไปนี้สามารถเห็นได้ในบันทึก:
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node03: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1387 millicores 4161694720 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node02: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1347 millicores 4444810240 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node03: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1387 millicores 4161694720 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node01: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1687 millicores 4790840320 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node02: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1347 millicores 4444810240 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node01: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1687 millicores 4790840320 memory bytes, score 9
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: NodeAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: NodeAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: NodeAffinityPriority, Score: (0)
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node01: InterPodAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: TaintTolerationPriority, Score: (10)
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node02: InterPodAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: TaintTolerationPriority, Score: (10)
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node01: SelectorSpreadPriority, Score: (10)
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node03: InterPodAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: TaintTolerationPriority, Score: (10)
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node02: SelectorSpreadPriority, Score: (10)
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node03: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:781] Host Node01 => Score 100043
generic_scheduler.go:781] Host Node02 => Score 100043
generic_scheduler.go:781] Host Node03 => Score 100043
เหล่านั้น. พิจารณาจากข้อมูลที่ได้รับจากบันทึก แต่ละโหนดได้คะแนนสุดท้ายเท่ากันและเลือกหนึ่งโหนดแบบสุ่มสำหรับการวางแผน ในขณะที่วางแผนปัญหา บันทึกจะมีลักษณะดังนี้:
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1587 millicores 4581125120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1087 millicores 3532549120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1587 millicores 4581125120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 987 millicores 3322833920 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 987 millicores 3322833920 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1087 millicores 3532549120 memory bytes, score 9
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node03: InterPodAffinityPriority, Score: (0)
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node02: InterPodAffinityPriority, Score: (0)
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node01: InterPodAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: TaintTolerationPriority, Score: (10)
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node03: SelectorSpreadPriority, Score: (10)
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node02: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: TaintTolerationPriority, Score: (10)
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node01: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: NodeAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: TaintTolerationPriority, Score: (10)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: NodeAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: NodeAffinityPriority, Score: (0)
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: SelectorSpreadPriority, Score: (10)
generic_scheduler.go:781] Host Node03 => Score 100041
generic_scheduler.go:781] Host Node02 => Score 100041
generic_scheduler.go:781] Host Node01 => Score 100038
จากที่จะเห็นได้ว่าโหนดหนึ่งทำคะแนนรวมได้น้อยกว่าโหนดอื่น ดังนั้นการวางแผนจึงดำเนินการเฉพาะสำหรับสองโหนดที่ทำคะแนนได้สูงสุด ดังนั้นเราจึงแน่ใจว่าปัญหาอยู่ที่การวางแผนของพ็อดอย่างแน่นอน
อัลกอริทึมเพิ่มเติมสำหรับการแก้ปัญหานั้นชัดเจนสำหรับเรา - เพื่อวิเคราะห์บันทึกทำความเข้าใจว่าลำดับความสำคัญใดที่โหนดไม่ได้รับคะแนนและหากจำเป็นให้ปรับนโยบายของ kube-scheduler เริ่มต้น อย่างไรก็ตาม ที่นี่เราเผชิญกับปัญหาสำคัญสองประการ:
- ระดับการบันทึกสูงสุด (10) แสดงถึงชุดของคะแนนสำหรับบางลำดับความสำคัญเท่านั้น ในข้อความที่ตัดตอนมาจากบันทึกข้างต้น คุณจะเห็นว่าสำหรับลำดับความสำคัญทั้งหมดที่แสดงในบันทึก โหนดให้คะแนนจำนวนคะแนนเท่ากันในการจัดกำหนดการปกติและปัญหา แต่ผลลัพธ์สุดท้ายในกรณีของการจัดกำหนดการที่มีปัญหาจะแตกต่างกัน ดังนั้นเราจึงสามารถสรุปได้ว่าสำหรับลำดับความสำคัญบางอย่าง การให้คะแนนเกิดขึ้น "เบื้องหลัง" และเราไม่มีทางเข้าใจได้ว่าลำดับความสำคัญใดที่โหนดไม่ได้รับคะแนน เราได้อธิบายปัญหานี้อย่างละเอียดใน
ปัญหา พื้นที่เก็บข้อมูล Kubernetes บน Github ในขณะที่เขียน นักพัฒนาได้รับการตอบสนองว่าการสนับสนุนการบันทึกจะถูกเพิ่มในการอัปเดต Kubernetes v1.15,1.16 และ 1.17 - ไม่มีวิธีที่ง่ายในการทำความเข้าใจว่าชุดนโยบายใดที่ kube-scheduler กำลังทำงานด้วย ใช่ใน
เอกสาร รายการนี้แสดงอยู่ แต่ไม่มีข้อมูลเกี่ยวกับการกำหนดน้ำหนักเฉพาะสำหรับแต่ละนโยบายลำดับความสำคัญ คุณสามารถดูน้ำหนักหรือแก้ไขนโยบายของ kube-scheduler เริ่มต้นเท่านั้นแหล่งที่มา .
เป็นที่น่าสังเกตว่าเมื่อเราจัดการเพื่อแก้ไขโหนดไม่ได้รับคะแนนตามนโยบาย ImageLocalityPriority ซึ่งให้รางวัลแก่โหนดหากมีอิมเมจที่จำเป็นในการเรียกใช้แอปพลิเคชันอยู่แล้ว นั่นคือ ในขณะที่เปิดตัวแอปพลิเคชันเวอร์ชันใหม่ งาน cron มีเวลาทำงานบนโหนดสองโหนด ดาวน์โหลดอิมเมจใหม่จากรีจีสทรีนักเทียบท่าไปยังโหนดทั้งสอง โหนดทั้งสองได้รับคะแนนสุดท้ายที่สูงกว่าเมื่อเทียบกับ อันที่สาม
ดังที่ฉันได้เขียนไว้ข้างต้น เราไม่เห็นข้อมูลเกี่ยวกับการประเมินนโยบาย ImageLocalityPriority ในบันทึก ดังนั้นเพื่อตรวจสอบสมมติฐานของเรา เราจึงสพูลอิมเมจด้วยแอปพลิเคชันเวอร์ชันใหม่ไปยังโหนดที่สาม หลังจากนั้นการวางแผน ทำงานได้อย่างถูกต้อง เป็นเพราะนโยบาย ImageLocalityPriority ที่ทำให้พบปัญหาการจัดตารางเวลาค่อนข้างน้อย โดยมักจะเกี่ยวข้องกับสิ่งอื่นมากกว่า เนื่องจากเราไม่สามารถดีบักนโยบายแต่ละรายการในรายการลำดับความสำคัญของตัวกำหนดตารางเวลา kube เริ่มต้นได้อย่างสมบูรณ์ เราจึงจำเป็นต้องมีการจัดการที่ยืดหยุ่นของนโยบายการจัดตารางเวลาของพ็อด
คำแถลงปัญหา
เราต้องการให้วิธีแก้ปัญหาตรงเป้าหมายมากที่สุดเท่าที่จะเป็นไปได้ กล่าวคือ เอนทิตีหลักของ Kubernetes (ในที่นี้หมายถึงตัวกำหนดตารางเวลา kube เริ่มต้น) ไม่ควรเปลี่ยนแปลง เราไม่ต้องการแก้ปัญหาในที่หนึ่งแล้วสร้างปัญหาในอีกที่หนึ่ง ดังนั้นเราจึงมาถึงสองตัวเลือกสำหรับการแก้ปัญหาที่ประกาศไว้ในบทนำของบทความ - สร้างตัวกำหนดตารางเวลาเพิ่มเติมหรือเขียนของคุณเอง ข้อกำหนดหลักสำหรับการจัดกำหนดการงาน cron คือการกระจายโหลดอย่างสม่ำเสมอทั่วทั้งสามโหนด ข้อกำหนดนี้สามารถปฏิบัติตามได้โดยนโยบาย kube-scheduler ที่มีอยู่ ดังนั้นจึงไม่มีเหตุผลที่จะเขียนตัวกำหนดตารางเวลาของเราเองสำหรับงานของเรา
คำแนะนำสำหรับการสร้างและปรับใช้ kube-scheduler เพิ่มเติมมีอธิบายไว้ใน
- ต้องปรับใช้บริการเป็น Static Pod บนต้นแบบคลัสเตอร์ทั้งหมด
- ควรจัดเตรียมเฟลโอเวอร์ไว้ในกรณีที่พ็อดที่ใช้งานกับ kube-scheduler ไม่พร้อมใช้งาน
- ลำดับความสำคัญหลักในการวางแผนควรเป็นจำนวนทรัพยากรที่มีอยู่บนโหนด (LeastRequestedPriority)
โซลูชั่นการใช้งาน
ควรสังเกตทันทีว่าเราจะทำงานทั้งหมดใน Kubernetes v1.14.7 เพราะ เวอร์ชันนี้ใช้ในโครงการ เริ่มต้นด้วยการเขียนรายการสำหรับ kube-scheduler ใหม่ของเรา ลองใช้รายการเริ่มต้น (/etc/kubernetes/manifests/kube-scheduler.yaml) เป็นพื้นฐานและนำมาไว้ในแบบฟอร์มต่อไปนี้:
kind: Pod
metadata:
labels:
component: scheduler
tier: control-plane
name: kube-scheduler-cron
namespace: kube-system
spec:
containers:
- command:
- /usr/local/bin/kube-scheduler
- --address=0.0.0.0
- --port=10151
- --secure-port=10159
- --config=/etc/kubernetes/scheduler-custom.conf
- --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
- --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
- --v=2
image: gcr.io/google-containers/kube-scheduler:v1.14.7
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /healthz
port: 10151
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 15
name: kube-scheduler-cron-container
resources:
requests:
cpu: '0.1'
volumeMounts:
- mountPath: /etc/kubernetes/scheduler.conf
name: kube-config
readOnly: true
- mountPath: /etc/localtime
name: localtime
readOnly: true
- mountPath: /etc/kubernetes/scheduler-custom.conf
name: scheduler-config
readOnly: true
- mountPath: /etc/kubernetes/scheduler-custom-policy-config.json
name: policy-config
readOnly: true
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/kubernetes/scheduler.conf
type: FileOrCreate
name: kube-config
- hostPath:
path: /etc/localtime
name: localtime
- hostPath:
path: /etc/kubernetes/scheduler-custom.conf
type: FileOrCreate
name: scheduler-config
- hostPath:
path: /etc/kubernetes/scheduler-custom-policy-config.json
type: FileOrCreate
name: policy-config
สั้น ๆ เกี่ยวกับการเปลี่ยนแปลงหลัก:
- เปลี่ยนชื่อพ็อดและคอนเทนเนอร์เป็น kube-scheduler-cron
- ระบุให้ใช้พอร์ต 10151 และ 10159 ตามอ็อพชันที่กำหนดไว้
hostNetwork: true
และเราไม่สามารถใช้พอร์ตเดียวกันกับ kube-scheduler เริ่มต้น (10251 และ 10259) - ใช้พารามิเตอร์ --config ระบุไฟล์คอนฟิกูเรชันที่ควรเริ่มบริการ
- กำหนดค่าให้ติดตั้งไฟล์การกำหนดค่า (scheduler-custom.conf) และไฟล์นโยบายการจัดกำหนดการ (scheduler-custom-policy-config.json) จากโฮสต์
อย่าลืมว่า kube-scheduler ของเราต้องการสิทธิ์ที่คล้ายกับค่าเริ่มต้น แก้ไขบทบาทของคลัสเตอร์:
kubectl edit clusterrole system:kube-scheduler
...
resourceNames:
- kube-scheduler
- kube-scheduler-cron
...
ตอนนี้เรามาพูดถึงสิ่งที่ควรมีในไฟล์คอนฟิกูเรชันและไฟล์นโยบายการจัดกำหนดการ:
- ไฟล์คอนฟิกูเรชัน (scheduler-custom.conf)
ในการรับการกำหนดค่าของ kube-scheduler เริ่มต้น คุณต้องใช้พารามิเตอร์--write-config-to
ของเอกสาร . เราจะวางการกำหนดค่าที่เป็นผลลัพธ์ในไฟล์ /etc/kubernetes/scheduler-custom.conf และนำไปไว้ในแบบฟอร์มต่อไปนี้:
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
schedulerName: kube-scheduler-cron
bindTimeoutSeconds: 600
clientConnection:
acceptContentTypes: ""
burst: 100
contentType: application/vnd.kubernetes.protobuf
kubeconfig: /etc/kubernetes/scheduler.conf
qps: 50
disablePreemption: false
enableContentionProfiling: false
enableProfiling: false
failureDomains: kubernetes.io/hostname,failure-domain.beta.kubernetes.io/zone,failure-domain.beta.kubernetes.io/region
hardPodAffinitySymmetricWeight: 1
healthzBindAddress: 0.0.0.0:10151
leaderElection:
leaderElect: true
leaseDuration: 15s
lockObjectName: kube-scheduler-cron
lockObjectNamespace: kube-system
renewDeadline: 10s
resourceLock: endpoints
retryPeriod: 2s
metricsBindAddress: 0.0.0.0:10151
percentageOfNodesToScore: 0
algorithmSource:
policy:
file:
path: "/etc/kubernetes/scheduler-custom-policy-config.json"
สั้น ๆ เกี่ยวกับการเปลี่ยนแปลงหลัก:
- ตั้งค่า schedulerName เป็นชื่อบริการ kube-scheduler-cron ของเรา
- ในพารามิเตอร์
lockObjectName
เราต้องตั้งชื่อบริการของเราและตรวจสอบให้แน่ใจว่าพารามิเตอร์นั้นleaderElect
ตั้งค่าเป็นจริง (ถ้าคุณมีโหนดหลักหนึ่งโหนด คุณสามารถตั้งค่าเป็นเท็จ) - ระบุพาธไปยังไฟล์พร้อมคำอธิบายของนโยบายการจัดกำหนดการในพารามิเตอร์
algorithmSource
.
มันคุ้มค่าที่จะอาศัยรายละเอียดเพิ่มเติมในย่อหน้าที่สองซึ่งเราแก้ไขพารามิเตอร์สำหรับคีย์ leaderElection
. เราได้เปิดใช้งาน (leaderElect
) กระบวนการเลือกผู้นำ (หลัก) ระหว่างพ็อดของ kube-scheduler ของเราโดยใช้จุดสิ้นสุดเดียวสำหรับพวกเขา (resourceLock
) ชื่อ kube-scheduler-cron (lockObjectName
) ในเนมสเปซระบบ kube (lockObjectNamespace
). วิธีที่ Kubernetes ทำให้ส่วนประกอบหลักมีความพร้อมใช้งานสูง (รวมถึง kube-scheduler) สามารถดูได้ใน
- ไฟล์นโยบายการจัดกำหนดการ (scheduler-custom-policy-config.json)
อย่างที่ฉันเขียนไปก่อนหน้านี้ เราสามารถค้นหาได้ว่านโยบายเฉพาะใดที่ kube-scheduler เริ่มต้นทำงานด้วยโดยการวิเคราะห์โค้ด นั่นคือเราไม่สามารถรับไฟล์ที่มีนโยบายการตั้งเวลาเริ่มต้นของ kube-scheduler ได้โดยการเปรียบเทียบกับไฟล์การกำหนดค่า เรามาอธิบายนโยบายการจัดกำหนดการที่เราสนใจในไฟล์ /etc/kubernetes/scheduler-custom-policy-config.json ดังต่อไปนี้:
{
"kind": "Policy",
"apiVersion": "v1",
"predicates": [
{
"name": "GeneralPredicates"
}
],
"priorities": [
{
"name": "ServiceSpreadingPriority",
"weight": 1
},
{
"name": "EqualPriority",
"weight": 1
},
{
"name": "LeastRequestedPriority",
"weight": 1
},
{
"name": "NodePreferAvoidPodsPriority",
"weight": 10000
},
{
"name": "NodeAffinityPriority",
"weight": 1
}
],
"hardPodAffinitySymmetricWeight" : 10,
"alwaysCheckAllPredicates" : false
}
ดังนั้น kube-scheduler จะแสดงรายการโหนดที่ Pod สามารถกำหนดเวลาได้ตามนโยบาย GeneralPredicates (ซึ่งรวมถึงชุดนโยบาย PodFitsResources, PodFitsHostPorts, HostName และ MatchNodeSelector) จากนั้นแต่ละโหนดจะได้รับการประเมินตามชุดของนโยบายในลำดับความสำคัญ เพื่อให้บรรลุเงื่อนไขของงาน เราพิจารณาว่าชุดนโยบายดังกล่าวจะเป็นทางออกที่ดีที่สุด ฉันขอเตือนคุณว่ามีชุดนโยบายพร้อมคำอธิบายโดยละเอียดอยู่ใน
รายการ kube-scheduler ใหม่ที่เราสร้างขึ้นในตอนต้นของบทนี้จะเรียกว่า kube-scheduler-custom.yaml และวางไว้ใน /etc/kubernetes/manifests บนโหนดหลักสามโหนด หากทำทุกอย่างถูกต้อง Kubelet จะเริ่มพ็อดในแต่ละโหนด และในบันทึกของ kube-scheduler ใหม่ เราจะเห็นข้อมูลว่าไฟล์นโยบายของเราถูกนำไปใช้สำเร็จ:
Creating scheduler from configuration: {{ } [{GeneralPredicates <nil>}] [{ServiceSpreadingPriority 1 <nil>} {EqualPriority 1 <nil>} {LeastRequestedPriority 1 <nil>} {NodePreferAvoidPodsPriority 10000 <nil>} {NodeAffinityPriority 1 <nil>}] [] 10 false}
Registering predicate: GeneralPredicates
Predicate type GeneralPredicates already registered, reusing.
Registering priority: ServiceSpreadingPriority
Priority type ServiceSpreadingPriority already registered, reusing.
Registering priority: EqualPriority
Priority type EqualPriority already registered, reusing.
Registering priority: LeastRequestedPriority
Priority type LeastRequestedPriority already registered, reusing.
Registering priority: NodePreferAvoidPodsPriority
Priority type NodePreferAvoidPodsPriority already registered, reusing.
Registering priority: NodeAffinityPriority
Priority type NodeAffinityPriority already registered, reusing.
Creating scheduler with fit predicates 'map[GeneralPredicates:{}]' and priority functions 'map[EqualPriority:{} LeastRequestedPriority:{} NodeAffinityPriority:{} NodePreferAvoidPodsPriority:{} ServiceSpreadingPriority:{}]'
ตอนนี้ยังคงเป็นเพียงการระบุในข้อมูลจำเพาะของ CronJob ของเราว่าคำขอทั้งหมดสำหรับการตั้งเวลาพ็อดควรได้รับการดำเนินการโดย kube-scheduler ใหม่ของเรา:
...
jobTemplate:
spec:
template:
spec:
schedulerName: kube-scheduler-cron
...
ข้อสรุป
ในท้ายที่สุด เราได้รับตัวจัดตารางเวลา kube เพิ่มเติมพร้อมชุดนโยบายการจัดตารางเวลาที่ไม่เหมือนใคร ซึ่ง kubelet ตรวจสอบโดยตรง นอกจากนี้ เรายังตั้งค่าการเลือกผู้นำคนใหม่ระหว่างพ็อดของตัวจัดกำหนดการ kube ของเรา ในกรณีที่ผู้นำคนเก่าไม่ว่างด้วยเหตุผลบางประการ
แอปพลิเคชันและบริการปกติยังคงถูกกำหนดเวลาผ่าน kube-scheduler เริ่มต้น และงาน cron ทั้งหมดได้ถูกถ่ายโอนไปยังอันใหม่อย่างสมบูรณ์ โหลดที่สร้างโดยงาน cron จะถูกกระจายอย่างเท่าๆ กันในทุกโหนด เมื่อพิจารณาว่างาน cron ส่วนใหญ่จะดำเนินการบนโหนดเดียวกันกับแอปพลิเคชันหลักของโครงการ สิ่งนี้ช่วยลดความเสี่ยงของการย้ายพ็อดเนื่องจากขาดทรัพยากรได้อย่างมาก หลังจากเปิดตัว kube-scheduler เพิ่มเติม ก็ไม่มีปัญหาอีกต่อไปกับการจัดตารางงาน cron ที่ไม่สม่ำเสมอ
อ่านบทความอื่น ๆ ในบล็อกของเราด้วย:
การจัดการการรับส่งข้อมูลในคลัสเตอร์ Kubernetes ด้วย Calico ทำความเข้าใจเกี่ยวกับตัวเลือกการบังคับใช้นโยบายเครือข่ายด้วย Calico เมื่อ Linux conntrack ไม่ใช่เพื่อนของคุณอีกต่อไป 4 ตัวอย่างของ iota enums การอัปเกรดคลัสเตอร์ Kubernetes โดยไม่ต้องหยุดทำงาน Zero Downtime Deployment และฐานข้อมูล Kubernetes: เหตุใดการตั้งค่าการจัดการทรัพยากรระบบจึงมีความสำคัญ
ที่มา: will.com