Լրացուցիչ kube-ի ժամանակացույցի ստեղծում՝ պլանավորման կանոնների հատուկ հավաքածուով

Լրացուցիչ kube-ի ժամանակացույցի ստեղծում՝ պլանավորման կանոնների հատուկ հավաքածուով

Kube-scheduler-ը Kubernetes-ի անբաժանելի բաղադրիչն է, որը պատասխանատու է հանգույցների միջև պլանավորման համար՝ համաձայն սահմանված քաղաքականության: Հաճախ, Kubernetes կլաստերի շահագործման ընթացքում, մենք ստիպված չենք լինի մտածել, թե կոնկրետ ինչ քաղաքականություններ են օգտագործվում բլոկների ժամանակացույցի համար, քանի որ լռելյայն kube-scheduler-ի կանոնների փաթեթը հարմար է առօրյա առաջադրանքների մեծ մասի համար: Այնուամենայնիվ, կան իրավիճակներ, երբ մեզ համար կարևոր է մանրակրկիտ կարգավորել պատիճների բաշխումը, և այս խնդիրն իրականացնելու երկու եղանակ կա.

  1. Ստեղծեք kube-ժամանակացույց՝ հատուկ կանոններով
  2. Գրեք ձեր սեփական ժամանակացույցը և սովորեցրեք նրան աշխատել API սերվերի հարցումների հետ

Այս հոդվածում ես նկարագրելու եմ հենց առաջին կետի իրականացումը մեր նախագծերից մեկի վրա պատիճների անհավասար պլանավորման խնդիրը լուծելու համար:

Համառոտ ներածություն kube-scheduler'a-ի աշխատանքի մասին

Ուշադրության է արժանի այն փաստը, որ kube-scheduler-ը պատասխանատվություն չի կրում pods ուղղակիորեն պլանավորելու համար. նա պատասխանատու է միայն որոշելու այն հանգույցը, որի վրա պետք է տեղադրվի pod: Այլ կերպ ասած, kube-scheduler-ի աշխատանքի արդյունքը այն հանգույցի անունն է, որը նա վերադարձնում է API սերվեր՝ պլանավորման հարցման համար, և այստեղ ավարտվում է նրա աշխատանքը։

Նախ, kube-scheduler-ը թվարկում է այն հանգույցները, որոնց համար Pod-ը կարող է պլանավորվել ըստ պրեդիկատների քաղաքականության: Ավելին, այս ցանկից յուրաքանչյուր հանգույց ստանում է որոշակի քանակությամբ միավորներ՝ ըստ առաջնահերթությունների քաղաքականության: Արդյունքում ընտրվում է ամենաբարձր միավոր ունեցող հանգույցը։ Եթե ​​կան նույն առավելագույն միավորներ ունեցող հանգույցներ, ընտրվում է պատահական մեկը: Նախադրյալների (զտման) և առաջնահերթությունների (գնահատման) քաղաքականության ցանկը և նկարագրությունը կարելի է գտնել այստեղ. փաստաթղթավորում.

Խնդրի մարմնի նկարագրությունը

Չնայած Nixys-ում պահպանվող Kubernetes-ի տարբեր կլաստերների մեծ թվին, մենք առաջին անգամ բախվեցինք pods պլանավորման խնդրին միայն վերջերս, երբ մեր նախագծերից մեկի համար անհրաժեշտություն առաջացավ կատարել մեծ թվով պարբերական առաջադրանքներ (~ 100 CronJob միավոր): Խնդրի նկարագրությունը հնարավորինս պարզեցնելու համար, որպես օրինակ, վերցնենք մեկ միկրոսերվիս, որի շրջանակներում րոպեն մեկ գործարկվում է cron առաջադրանքը՝ որոշակի բեռ ստեղծելով պրոցեսորի վրա։ Cron առաջադրանքի աշխատանքի համար հատկացվել են երեք բացարձակապես նույնական հանգույցներ (յուրաքանչյուրի վրա 24 vCPU):

Միևնույն ժամանակ, անհնար է հստակ ասել, թե որքան ժամանակ կաշխատի CronJob-ը, քանի որ մուտքագրված տվյալների քանակը անընդհատ փոխվում է: Միջին հաշվով, նորմալ kube-scheduler-ի շահագործման ժամանակ յուրաքանչյուր հանգույց գործարկում է 3-4 աշխատանքային դեպք, որոնք ստեղծում են յուրաքանչյուր հանգույցի պրոցեսորի վրա բեռի ~ 20-30%-ը.

Լրացուցիչ kube-ի ժամանակացույցի ստեղծում՝ պլանավորման կանոնների հատուկ հավաքածուով

Խնդիրն ինքնին այն է, որ երբեմն cron task pods-ը դադարել է պլանավորվել երեք հանգույցներից մեկի համար: Այսինքն, ժամանակի ինչ-որ պահի հանգույցներից մեկի համար ոչ մի պատիճ նախատեսված չէր, մինչդեռ մյուս երկու հանգույցների վրա աշխատում էին 6-8 առաջադրանքների օրինակներ՝ ստեղծելով պրոցեսորի բեռնվածության ~ 40-60%-ը.

Լրացուցիչ kube-ի ժամանակացույցի ստեղծում՝ պլանավորման կանոնների հատուկ հավաքածուով

Խնդիրը կրկնվում էր բացարձակապես պատահական հաճախականությամբ և երբեմն փոխկապակցվում էր կոդի նոր տարբերակի հրապարակման պահի հետ։

Բարձրացնելով 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-ի քաղաքականությունը: Այնուամենայնիվ, այստեղ մենք բախվում ենք երկու էական դժվարության.

  1. Հատումների առավելագույն մակարդակը (10) արտացոլում է միավորների հավաքածուն միայն որոշ առաջնահերթությունների համար: Վերոնշյալ գրանցամատյանի հատվածում դուք կարող եք տեսնել, որ տեղեկամատյաններում արտացոլված բոլոր առաջնահերթությունների համար հանգույցները հավաքում են նույն թվով միավորներ նորմալ և խնդիրների ժամանակացույցում, բայց վերջնական արդյունքը խնդրի պլանավորման դեպքում տարբեր է: Այսպիսով, մենք կարող ենք եզրակացնել, որ որոշ առաջնահերթությունների համար միավորները տեղի են ունենում «կուլիսներում», և մենք ոչ մի կերպ չենք հասկանում, թե որ առաջնահերթության համար հանգույցը միավորներ չի ստացել: Մենք մանրամասն նկարագրել ենք այս հարցը թողարկում Kubernetes պահոց Github-ում: Գրելու պահին ծրագրավորողներից պատասխան է ստացվել, որ լոգինգի աջակցությունը կավելացվի Kubernetes v1.15,1.16 և 1.17 թարմացումներում։
  2. Չկա հեշտ ճանապարհ հասկանալու, թե որ քաղաքականության որոշակի փաթեթի հետ է աշխատում kube-scheduler-ը: Այո, ներս փաստաթղթավորում այս ցանկը թվարկված է, բայց այն չի պարունակում տեղեկատվություն այն մասին, թե ինչ հատուկ կշիռներ են սահմանվել գերակայությունների յուրաքանչյուր քաղաքականության համար: Դուք կարող եք տեսնել միայն կշիռները կամ խմբագրել լռելյայն kube-scheduler-ի քաղաքականությունը աղբյուրները.

Հարկ է նշել, որ մի անգամ մեզ հաջողվեց ֆիքսել, որ հանգույցը միավորներ չի հավաքել՝ համաձայն ImageLocalityPriority քաղաքականության, որը միավորներ է շնորհում հանգույցին, եթե այն արդեն ունի հավելվածը գործարկելու համար պահանջվող պատկերը: Այսինքն՝ հավելվածի նոր տարբերակի հրապարակման պահին cron առաջադրանքը ժամանակ ուներ գործարկել երկու հանգույցների վրա՝ ներբեռնելով նոր պատկեր դոկերի ռեեստրից, և այդպիսով երկու հանգույց ստացան ավելի բարձր վերջնական միավոր՝ համեմատած երրորդը.

Ինչպես վերևում գրեցի, տեղեկամատյաններում մենք տեղեկատվություն չենք տեսնում ImageLocalityPriority քաղաքականության գնահատման մասին, հետևաբար, մեր ենթադրությունը ստուգելու համար մենք հավելվածի նոր տարբերակով պատկերը փաթաթեցինք երրորդ հանգույց, որից հետո պլանավորումը ճիշտ է աշխատել: Հենց ImageLocalityPriority քաղաքականության պատճառով էր, որ ժամանակացույցի խնդիրը բավականին հազվադեպ էր նկատվում, ավելի հաճախ այն կապված էր այլ բանի հետ: Հաշվի առնելով այն հանգամանքը, որ մենք չկարողացանք ամբողջությամբ վրիպազերծել լռելյայն kube-ի ժամանակացույցի առաջնահերթությունների ցանկի կանոններից յուրաքանչյուրը, մենք կարիք ունեինք ճկուն կառավարելու pod-ի ժամանակացույցի քաղաքականությունը:

Խնդրի ձևակերպում

Մենք ցանկանում էինք, որ խնդրի լուծումը լինի հնարավորինս հասցեական, այսինքն՝ Kubernetes-ի հիմնական սուբյեկտները (այստեղ նկատի ունենք լռելյայն kube-scheduler-ը) պետք է մնան անփոփոխ։ Մենք չէինք ուզում մի տեղ խնդիր լուծել, մեկ այլ տեղում ստեղծել։ Այսպիսով, մենք հասանք խնդրի լուծման երկու տարբերակի, որոնք հայտարարվել էին հոդվածի ներածության մեջ՝ ստեղծել լրացուցիչ ժամանակացույց կամ գրել ձեր սեփականը: Cron-ի առաջադրանքների պլանավորման հիմնական պահանջը բեռը երեք հանգույցների վրա հավասարաչափ բաշխումն է: Այս պահանջը կարող է բավարարվել գոյություն ունեցող kube-scheduler քաղաքականության միջոցով, ուստի անիմաստ է գրել մեր սեփական ժամանակացույցը մեր առաջադրանքի համար:

Լրացուցիչ kube-ծրագրավորողի ստեղծման և տեղադրման հրահանգները նկարագրված են փաստաթղթավորում. Այնուամենայնիվ, մեզ թվում էր, որ Deployment կառույցը բավարար չէ, որպեսզի ապահովի սխալների հանդուրժողականություն այնպիսի կարևոր ծառայության մեջ, ինչպիսին է kube-scheduler-ը, ուստի մենք որոշեցինք տեղակայել նոր kube-scheduler-ը որպես Static Pod, որը Kubelet-ն ուղղակիորեն կվերահսկի: . Այսպիսով, մենք ունենք հետևյալ պահանջները նոր kube-scheduler-ի համար.

  1. Ծառայությունը պետք է տեղադրվի որպես Static Pod բոլոր կլաստերի վարպետների վրա
  2. Failover-ը պետք է տրամադրվի այն դեպքում, երբ ակտիվ pod-ը kube-scheduler-ով անհասանելի է
  3. Պլանավորման ժամանակ հիմնական առաջնահերթությունը պետք է լինի հանգույցում առկա ռեսուրսների քանակը (LeastRequestedPriority)

Իրականացման լուծումներ

Անմիջապես պետք է նշել, որ մենք ամբողջ աշխատանքը կիրականացնենք Kubernetes v1.14.7-ում, քանի որ այս տարբերակը օգտագործվել է նախագծում: Եկեք սկսենք գրել մանիֆեստ մեր նոր kube-ծրագրավորողի համար: Եկեք որպես հիմք վերցնենք լռելյայն մանիֆեստը (/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

Հակիրճ հիմնական փոփոխությունների մասին.

  1. Փոդի և կոնտեյների անունը փոխվեց kube-scheduler-cron-ի
  2. Նշված է 10151 և 10159 նավահանգիստներն օգտագործելու համար, քանի որ ընտրված է hostNetwork: true և մենք չենք կարող օգտագործել նույն պորտերը, ինչ լռելյայն kube-scheduler (10251 և 10259)
  3. Օգտագործելով --config պարամետրը, նշեք կազմաձևման ֆայլը, որով պետք է սկսվի ծառայությունը
  4. Կազմաձևված է կազմաձևման ֆայլը (scheduler-custom.conf) և պլանավորման քաղաքականության ֆայլը (scheduler-custom-policy-config.json) տեղադրելու համար:

Մի մոռացեք, որ մեր kube-ծրագրավորողին անհրաժեշտ են իրավունքներ, որոնք նման են լռելյայնին: Խմբագրել իր կլաստերի դերը՝

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"

Հակիրճ հիմնական փոփոխությունների մասին.

  1. Սահմանեք schedulerName-ը մեր ծառայության անվանման համար, kube-scheduler-cron:
  2. Պարամետրով lockObjectName մենք նաև պետք է սահմանենք մեր ծառայության անվանումը և համոզվենք, որ պարամետրը leaderElect սահմանել true (եթե ունեք մեկ հիմնական հանգույց, կարող եք արժեքը սահմանել false):
  3. Նշեց ֆայլի ուղին պարամետրում պլանավորման քաղաքականության նկարագրությամբ algorithmSource.

Արժե ավելի մանրամասն անդրադառնալ երկրորդ պարբերությանը, որտեղ մենք խմբագրում ենք բանալիի պարամետրերը. leaderElection. Սխալների հանդուրժողականության համար մենք միացրել ենք (leaderElect) մեր kube-ծրագրավորողի պատիճների միջև առաջնորդի (վարպետի) ընտրության գործընթացը՝ օգտագործելով դրանց համար մեկ վերջնական կետ (resourceLock) անունով kube-scheduler-cron (lockObjectName) kube-system անվանումների տարածքում (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-ը կարող է պլանավորվել՝ համաձայն General Predicates քաղաքականության (որը ներառում է PodFitsResources, PodFitsHostPorts, HostName և MatchNodeSelector քաղաքականության հավաքածուն): Եվ այնուհետև յուրաքանչյուր հանգույց գնահատվում է առաջնահերթությունների զանգվածի քաղաքականությունների շարքին համապատասխան: Մեր առաջադրանքի պայմանները կատարելու համար մենք համարում էինք, որ քաղաքականության նման փաթեթը կլինի լավագույն լուծումը։ Հիշեցնեմ, որ քաղաքականությունների մի շարք՝ դրանց մանրամասն նկարագրությամբ հասանելի է փաստաթղթավորում. Ձեր առաջադրանքն իրականացնելու համար դուք կարող եք պարզապես փոխել օգտագործվող քաղաքականությունների շարքը և համապատասխան կշիռներ նշանակել դրանց:

Նոր kube-scheduler մանիֆեստը, որը մենք ստեղծել ենք գլխի սկզբում, կկոչվի kube-scheduler-custom.yaml և կտեղադրվի /etc/kubernetes/manifests-ում երեք հիմնական հանգույցների վրա: Եթե ​​ամեն ինչ ճիշտ է արված, Kubelet-ը կսկսի pod յուրաքանչյուր հանգույցի վրա, և մեր նոր 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-ծրագրավորողի կողմից.

...
 jobTemplate:
    spec:
      template:
        spec:
          schedulerName: kube-scheduler-cron
...

Ամփոփում

Ի վերջո, մենք ստացանք լրացուցիչ kube-scheduler՝ ուրվագծային քաղաքականության եզակի փաթեթով, որը վերահսկվում է անմիջապես kubelet-ի կողմից: Բացի այդ, մենք ստեղծեցինք նոր առաջնորդի ընտրություն մեր kube-ծրագրավորողի պատյանների միջև, եթե հին առաջնորդը ինչ-ինչ պատճառներով անհասանելի դառնա:

Սովորական հավելվածներն ու ծառայությունները շարունակում են պլանավորվել լռելյայն kube-scheduler-ի միջոցով, և cron-ի բոլոր առաջադրանքները ամբողջությամբ փոխանցվել են նորին: Cron առաջադրանքների կողմից ստեղծված բեռը այժմ հավասարապես բաշխված է բոլոր հանգույցներում: Հաշվի առնելով, որ cron առաջադրանքների մեծ մասն իրականացվում է նույն հանգույցների վրա, ինչ նախագծի հիմնական հավելվածները, դա զգալիորեն նվազեցրեց ռեսուրսների բացակայության պատճառով pods-ի տեղափոխման ռիսկը: Լրացուցիչ kube-scheduler-ի ներդրումից հետո այլևս խնդիրներ չկային cron-ի աշխատանքների անհավասար պլանավորման հետ կապված:

Կարդացեք նաև մեր բլոգի այլ հոդվածներ.

Source: www.habr.com

Добавить комментарий