TheKoguryo's 기술 블로그

 Version 2024.04.01

1.10.4 Custom Scheduler 사용하기

OKE에서는 default-scheduler를 사용자에게 열어주고 있지 않습니다. 이런 상황에서 스케줄러를 확장하기 위해 쿠버네티스에서 제공하는 multiple schedulers 기능이 잘 동작하는 지 쿠버네티스 문서상의 내용을 따라 확인해 봅니다.

스케줄러 패키징
  1. 여기서는 default-scheduler 원 소스 Kubernetes source code from GitHub를 이용하여 두 번째 스케줄러를 배포합니다. 여기서는 이후 옵션, 설정값만으로 커스터마이징하겠습니다. 필요에 따라 스케줄러 소스를 자체를 변경할 수도 있겠습니다.

  2. 복제한 kube-scheduler 소소를 패키징합니다.

    git clone --depth 1 --single-branch --branch release-1.26 https://github.com/kubernetes/kubernetes.git
    cd kubernetes
    make all WHAT=cmd/kube-scheduler GOFLAGS=-v
    
    • 빌드후 생성된 바이너리를 확인할 수 있습니다.
    thekoguryo@cloudshell:kubernetes (ap-chuncheon-1)$ ls -la ./_output/local/bin/linux/amd64/kube-scheduler 
    -rwxr-xr-x. 1 thekoguryo oci 53497856 Aug  1 04:46 ./_output/local/bin/linux/amd64/kube-scheduler
    
  3. 컨테이너 이미지를 생성하기 위해 Dockerfile을 만듭니다.

    FROM busybox
    ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler
    
  4. 이미지를 빌드해서 OCIR에 등록합니다.

    # 로그인
    docker login -u '<tenancy-namespace>/<username>' yny.ocir.io
    
    # 이미지 빌드후 등록: 예, 춘천 리전
    docker build -t yny.ocir.io/<tenancy-namespace>/my-kube-scheduler:1.0 .
    docker push yny.ocir.io/<tenancy-namespace>/my-kube-scheduler:1.0
    
    • 편의상 OCIR Repository는 Public으로 전환하였습니다.
스케줄러 배포 파일 수정
  1. 배포 파일을 다운로드 받습니다.

    wget https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/admin/sched/my-scheduler.yaml
    
  2. 배포 파일에서 이미지 주소를 변경합니다.

    • image 주소를 본인이 등록한 OCIR 주소로 변경합니다.
    • 스케줄러 실행 옵션
      • kube-scheduler
      • 옵션 값을 변경할 수 있습니다. 여기서는 예시로 command에 - --v=4 을 추가하여 로그 레벨을 변경합니다.
    ...
          containers:
          - command:
            - /usr/local/bin/kube-scheduler
            - --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
            - --v=4        
            image: yny.ocir.io/<tenancy-namespace>/my-kube-scheduler:1.0
    ...
    
  3. OKE 클러스터 버전인 1.25 이상에 배포하는 경우, 배포 파일에서 apiVersion의 /v1으로 변경합니다.

    • 스케줄러 설정
      • default-scheduler와 소스코드 동일하더라도, 여기 있는 KubeSchedulerConfiguration 설정을 통해 스케줄러 설정을 커스터마이징할 수 있습니다.
      • 예시는 NodeResourcesFit 플러그인의 스코어링 정책을 일부 변경적용한 예입니다.
      • 추가 설정은 KubeSchedulerConfiguration 을 참고합니다.
    ...
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: my-scheduler-config
      namespace: kube-system
    data:
      my-scheduler-config.yaml: |
        apiVersion: kubescheduler.config.k8s.io/v1
        kind: KubeSchedulerConfiguration
        profiles:
          - schedulerName: my-scheduler
            pluginConfig:
            - name: NodeResourcesFit
              args:
                scoringStrategy:
                  resources:
                  - name: cpu
                    weight: 1
                  type: MostAllocated
        leaderElection:
          leaderElect: false      
    ...      
    
클러스터에 두번째 스케줄러 배포
  1. 작성한 배포 파일로 배포합니다.

    kubectl apply -f my-scheduler.yaml
    
  2. 배포된 스케줄러를 확인합니다.

    kubectl get pods --namespace=kube-system
    
    • 결과
    $ kubectl get pods --namespace=kube-system
    NAME                                   READY   STATUS    RESTARTS        AGE
    ...
    my-scheduler-5fb44c4fb9-kqwqc          1/1     Running   0               4m17s
    ...
    
스케줄러 테스트
  1. 스케줄러 이름 지정없이 Pod를 배포합니다.

    kind: Pod
    metadata:
      name: no-annotation
      labels:
        name: multischeduler-example
    spec:
      containers:
      - name: pod-with-no-annotation-container
        image: registry.k8s.io/pause:2.0
    
    • 실행
    wget https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/admin/sched/pod1.yaml
    kubectl apply -f pod1.yaml
    
  2. default-scheduler로 지정 배포합니다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: annotation-default-scheduler
      labels:
        name: multischeduler-example
    spec:
      schedulerName: default-scheduler
      containers:
      - name: pod-with-default-annotation-container
        image: registry.k8s.io/pause:2.0
    
    • 실행
    wget https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/admin/sched/pod2.yaml
    kubectl apply -f pod2.yaml
    
  3. my-scheduler로 지정 배포합니다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: annotation-second-scheduler
      labels:
        name: multischeduler-example
    spec:
      schedulerName: my-scheduler
      containers:
      - name: pod-with-second-annotation-container
        image: registry.k8s.io/pause:2.0
    
    • 실행
    wget https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/admin/sched/pod3.yaml
    kubectl apply -f pod3.yaml
    
결과 확인
  1. 첫번째 배포한 pod1은 스케줄러를 지정하지 않은 경우, default-scheduler가 스케줄링한 것을 볼 수 있습니다.

    $ kubectl describe pod no-annotation
    Name:             no-annotation
    ...
    Events:
      Type    Reason     Age   From               Message
      ----    ------     ----  ----               -------
      Normal  Scheduled  4s    default-scheduler  Successfully assigned default/no-annotation to 10.0.10.112
      ...
    
  2. default-scheduler를 지정한 두번째 pod2는, default-scheduler가 스케줄링한 것을 볼 수 있습니다.

    $ kubectl describe pod annotation-default-scheduler
    Name:             annotation-default-scheduler
    ...
    Events:
      Type    Reason     Age   From               Message
      ----    ------     ----  ----               -------
      Normal  Scheduled  16s   default-scheduler  Successfully assigned default/annotation-default-scheduler to 10.0.10.112
    
  3. 두번째 스케줄러인 my-scheduler로 지정한 세번째 pod3는, my-scheduler가 스케줄링한 것을 볼 수 있습니다.

    $ kubectl describe pod annotation-second-scheduler
    Name:             annotation-second-scheduler
    ...
    Events:
      Type    Reason     Age   From          Message
      ----    ------     ----  ----          -------
      Normal  Scheduled  15s   my-scheduler  Successfully assigned default/annotation-second-scheduler to 10.0.10.112
    
  4. 배포한 스케줄러의 로그를 확인합니다. FLAG: --v="4" 에서 변경한 로그레벨이 적용된 것을 볼 수 있습니다. 두 번째 pod2(annotation-default-scheduler)에 대해서는 직접 스케줄하지 않았고, 세 번째 pod3(annotation-second-scheduler)는 “Attempting to schedule pod” 로그에서 보듯이 배포한 두 번째 스케줄러가 스케줄링한 것을 확인할 수 있습니다.

    $ kubectl logs -n kube-system -f my-scheduler-587dd655fb-sf9w5
    ...
    I0801 07:12:36.759716       1 flags.go:64] FLAG: --v="4"
    ...
    I0801 07:13:56.973413       1 eventhandlers.go:197] "Add event for scheduled pod" pod="default/annotation-default-scheduler"
    I0801 07:13:56.991814       1 eventhandlers.go:218] "Update event for scheduled pod" pod="default/annotation-default-scheduler"
    I0801 07:13:58.711914       1 eventhandlers.go:218] "Update event for scheduled pod" pod="default/annotation-default-scheduler"
    ...
    I0801 07:14:26.843405       1 eventhandlers.go:126] "Add event for unscheduled pod" pod="default/annotation-second-scheduler"
    I0801 07:14:26.843517       1 schedule_one.go:80] "About to try and schedule pod" pod="default/annotation-second-scheduler"
    I0801 07:14:26.843527       1 schedule_one.go:93] "Attempting to schedule pod" pod="default/annotation-second-scheduler"
    I0801 07:14:26.843792       1 default_binder.go:53] "Attempting to bind pod to node" pod="default/annotation-second-scheduler" node="10.0.10.112"
    I0801 07:14:26.854440       1 eventhandlers.go:171] "Delete event for unscheduled pod" pod="default/annotation-second-scheduler"
    I0801 07:14:26.854457       1 eventhandlers.go:197] "Add event for scheduled pod" pod="default/annotation-second-scheduler"
    I0801 07:14:26.856109       1 schedule_one.go:285] "Successfully bound pod to node" pod="default/annotation-second-scheduler" node="10.0.10.112" evaluatedNodes=1 feasibleNodes=1
    I0801 07:14:26.878836       1 eventhandlers.go:218] "Update event for scheduled pod" pod="default/annotation-second-scheduler"
    
참고


이 글은 개인으로서, 개인의 시간을 할애하여 작성된 글입니다. 글의 내용에 오류가 있을 수 있으며, 글 속의 의견은 개인적인 의견입니다.

Last updated on 1 Aug 2023