Translate tasks/extend-kubernetes/configure-multiple-schedulers to Korean
Reflected bconfiden2's comments and deleted unnecessary blank spaces between links Reflected seokho-son's comments Reflected seokho-sons' comments (fixed missed errors)
This commit is contained in:
parent
63045d8842
commit
39dd9a88b1
|
@ -0,0 +1,219 @@
|
|||
---
|
||||
reviewers:
|
||||
|
||||
|
||||
title: 다중 스케줄러 설정
|
||||
content_type: task
|
||||
weight: 20
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
쿠버네티스는 [여기](/docs/reference/command-line-tools-reference/kube-scheduler/)에서
|
||||
설명한 스케줄러를 기본 스케줄러로 사용한다.
|
||||
만일 기본 스케줄러가 사용자의 필요를 만족시키지 못한다면 직접 스케줄러를 구현하여 사용할 수 있다.
|
||||
이에 더해, 기본 스케줄러와 함께 여러 스케줄러를 동시에 사용하여
|
||||
쿠버네티스가 각 파드에 대해 어떤 스케줄러를 적용할지에 대한 설정도 할 수 있다.
|
||||
예제와 함께 쿠버네티스에서 다중 스케줄러를 사용하는 방법에 대해 배워보도록 하자.
|
||||
|
||||
스케줄러를 구현하는 방법에 대한 자세한 설명은 해당 문서에서 다루지 않는다.
|
||||
kube-scheduler 구현을 다루는 공식 예시는 쿠버네티스 소스 디렉토리에 있는
|
||||
[pkg/scheduler](https://github.com/kubernetes/kubernetes/tree/master/pkg/scheduler)
|
||||
를 참고한다.
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## 스케줄러 패키징
|
||||
|
||||
스케줄러 바이너리를 컨테이너 이미지로 패키징한다. 해당 예제를 통해
|
||||
기본 스케줄러 (kube-scheduler)를 두 번째 스케줄러로 사용할 수 있다.
|
||||
[GitHub 쿠버네티스 소스코드](https://github.com/kubernetes/kubernetes)를
|
||||
클론하고 소스를 빌드하자.
|
||||
|
||||
```shell
|
||||
git clone https://github.com/kubernetes/kubernetes.git
|
||||
cd kubernetes
|
||||
make
|
||||
```
|
||||
|
||||
kube-scheduler 바이너리를 담은 컨테이너 이미지를 생성하자.
|
||||
이미지를 빌드 하기 위한 `Dockerfile`은 다음과 같다.
|
||||
|
||||
```docker
|
||||
FROM busybox
|
||||
ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler
|
||||
```
|
||||
|
||||
파일을 `Dockerfile`로 저장하고 이미지를 빌드한 후 레지스트리로 푸시하자. 해당 예제에서는 이미지를
|
||||
[Google Container Registry (GCR)](https://cloud.google.com/container-registry/)로
|
||||
푸시하고 있다.
|
||||
이에 대한 자세한 내용은 GCR
|
||||
[문서](https://cloud.google.com/container-registry/docs/)를 참고하자.
|
||||
|
||||
```shell
|
||||
docker build -t gcr.io/my-gcp-project/my-kube-scheduler:1.0 .
|
||||
gcloud docker -- push gcr.io/my-gcp-project/my-kube-scheduler:1.0
|
||||
```
|
||||
|
||||
## 스케줄러에서 사용할 쿠버네티스 디플로이먼트 정의하기
|
||||
|
||||
이제 스케줄러 컨테이너 이미지가 있으니, 해당 이미지를 포함하는 파드 구성을 생성하고
|
||||
쿠버네티스 클러스터 내에서 실행해보자. 해당 예제에서는, 클러스터 내에 직접 파드를 생성하는 대신에
|
||||
[디플로이먼트](/ko/docs/concepts/workloads/controllers/deployment/)를 사용해도 된다.
|
||||
[디플로이먼트](/ko/docs/concepts/workloads/controllers/deployment/)는
|
||||
[레플리카 셋](/ko/docs/concepts/workloads/controllers/replicaset/)을 관리하며,
|
||||
이는 또 파드를 관리하기 때문에 스케줄러에 대한 회복 탄력성을 제공한다.
|
||||
다음은 디플로이먼트에 대한 구성 파일이다. 이 파일을 `my-scheduler.yaml`으로 저장한다.
|
||||
|
||||
{{< codenew file="admin/sched/my-scheduler.yaml" >}}
|
||||
|
||||
해당 매니페스트에서는 [KubeSchedulerConfiguration](/ko/docs/reference/scheduling/config/)을
|
||||
사용하여 구현할 스케줄러의 특성을 정의한다. 이러한 설정은 초기화 과정에서 `--config` 옵션을 통해 `kube-scheduler`에게 전달된다.
|
||||
해당 구성 파일은 `my-scheduler-config` 컨피그맵에 저장된다. `my-scheduler` 디플로이먼트의 파드에서는 `my-scheduler-config` 컨피그맵을 볼륨으로 마운트 시킨다.
|
||||
|
||||
앞서 언급한 스케줄러 구성에서는, 구현한 스케줄러가
|
||||
[KubeSchedulerProfile](/docs/reference/config-api/kube-scheduler-config.v1beta3/#kubescheduler-config-k8s-io-v1beta3-KubeSchedulerProfile)의 형식으로 나타나게 된다.
|
||||
{{< note >}}
|
||||
스케줄러가 특정 파드에 대한 스케줄링을 수행하는지 판단하기 위해서는, PodTemplate 또는 파드 매니페스트의
|
||||
`spec.schedulerName` 필드가 `KubeSchedulerProfile`의 `schedulerName` 필드와 일치하는지 확인해야 한다.
|
||||
클러스터 내 실행되고 있는 모든 스케줄러는 고유한 이름을 가져야 한다.
|
||||
{{< /note >}}
|
||||
|
||||
또한, `kube-scheduler`와 같은 권한을 부여받기 위해서는 전용 서비스 어카운트 `my-scheduler`를 생성하고
|
||||
해당 서비스 어카운트를 클러스터롤 `system:kube-scheduler`와 바인딩해야 한다.
|
||||
|
||||
이외의 커맨드 라인 인자에 대한 자세한 설명은
|
||||
[kube-scheduler 문서](/docs/reference/command-line-tools-reference/kube-scheduler/)에서 참고하고
|
||||
이외의 사용자 정의 `kube-scheduler` 구성에 대한 자세한 설명은
|
||||
[스케줄러 구성 레퍼런스](/docs/reference/config-api/kube-scheduler-config.v1beta3/)
|
||||
에서 참고한다.
|
||||
|
||||
## 두 번째 스케줄러를 클러스터에서 실행하기
|
||||
|
||||
쿠버네티스 클러스터에서 스케줄러를 실행하기 위해서,
|
||||
위의 구성 파일에서 명시한 디플로이먼트를 쿠버네티스 클러스터 내에 생성한다.
|
||||
|
||||
```shell
|
||||
kubectl create -f my-scheduler.yaml
|
||||
```
|
||||
|
||||
스케줄러 파드가 실행되고 있는지 확인한다.
|
||||
|
||||
```shell
|
||||
kubectl get pods --namespace=kube-system
|
||||
```
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
....
|
||||
my-scheduler-lnf4s-4744f 1/1 Running 0 2m
|
||||
...
|
||||
```
|
||||
|
||||
기본 kube-scheduler 파드와 더불어,
|
||||
my-scheduler 파드가 실행("Running")되고 있다는 것을 목록에서 볼 수 있을 것이다.
|
||||
|
||||
### 리더 선출 활성화
|
||||
|
||||
리더 선출이 활성화된 상태로 다중 스케줄러를 실행하기 위해서는 다음과 같은 작업을 수행해야 한다.
|
||||
|
||||
`my-scheduler-config` 컨피그맵의 YAML 파일에서 KubeSchedulerConfiguration의 다음과 같은 필드들을 갱신한다.
|
||||
|
||||
* `leaderElection.leaderElect` 를 `true` 로
|
||||
* `leaderElection.resourceNamespace` 를 `<lock-object-namespace>` 로
|
||||
* `leaderElection.resourceName` 을 `<lock-object-name>` 으로
|
||||
|
||||
{{< note >}}
|
||||
컨트롤 플레인이 잠금 오브젝트를 생성해 주지만, 해당 네임스페이스가 존재하는 상태이어야 한다.
|
||||
`kube-system` 네임스페이스를 사용해도 된다.
|
||||
{{< /note >}}
|
||||
|
||||
클러스터 내에 RBAC가 활성화되어 있는 상태라면, `system:kube-scheduler` 클러스터롤을 업데이트 해야 한다.
|
||||
다음 예시와 같이, 구현한 스케줄러의 이름을 `endpoints`와 `leases` 리소스에 적용되는 룰의 resourceNames에 추가하자.
|
||||
|
||||
```shell
|
||||
kubectl edit clusterrole system:kube-scheduler
|
||||
```
|
||||
|
||||
{{< codenew file="admin/sched/clusterrole.yaml" >}}
|
||||
|
||||
## 파드의 스케줄러를 지정하기
|
||||
|
||||
이제 두 번째 스케줄러가 실행되고 있으니,
|
||||
파드를 몇 개 생성하여 기본 스케줄러 또는 새로 배치한 스케줄러에 의해 스케줄링이 되도록 설정해 보자.
|
||||
특정 스케줄러를 이용하여 파드를 스케줄링하기 위해서는
|
||||
해당 파드의 명세에 해당 스케줄러의 이름을 명시해야 한다. 세 가지 예시를 참고해 보자.
|
||||
|
||||
- 스케줄러 이름을 명시하지 않은 파드 명세
|
||||
|
||||
{{< codenew file="admin/sched/pod1.yaml" >}}
|
||||
|
||||
스케줄러 이름을 제공받지 못했다면,
|
||||
파드는 자동으로 기본 스케줄러에 의해 스케줄링이 수행된다.
|
||||
|
||||
해당 파일을 `pod1.yaml`로 저장하고 쿠버네티스 클러스터에 제출해 보자.
|
||||
|
||||
```shell
|
||||
kubectl create -f pod1.yaml
|
||||
```
|
||||
|
||||
- `default-scheduler`를 명시한 파드 명세
|
||||
|
||||
{{< codenew file="admin/sched/pod2.yaml" >}}
|
||||
|
||||
`spec.schedulerName`의 값으로 스케줄러 이름을 제공함으로써 스케줄러가 정해진다.
|
||||
이와 같은 경우에서는, 기본 스케줄러의 이름인 `default-scheduler`를 명시하고 있다.
|
||||
|
||||
해당 파일을 `pod2.yaml`로 저장하고 쿠버네티스 클러스터에 제출해 보자.
|
||||
|
||||
```shell
|
||||
kubectl create -f pod2.yaml
|
||||
```
|
||||
|
||||
- `my-scheduler`를 명시한 파드 명세
|
||||
|
||||
{{< codenew file="admin/sched/pod3.yaml" >}}
|
||||
|
||||
이와 같은 경우에서는, 직접 배치한 스케줄러 - `my-scheduler`를 통해
|
||||
해당 파드의 스케줄링이 수행되어야 한다는 것을 명시하고 있다.
|
||||
`spec.schedulerName`의 값은 `KubeSchedulerProfile` 매핑의 `schedulerName` 필드와 일치해야 한다.
|
||||
|
||||
해당 파일을 `pod3.yaml`로 저장하고 쿠버네티스 클러스터에 제출해 보자.
|
||||
|
||||
```shell
|
||||
kubectl create -f pod3.yaml
|
||||
```
|
||||
|
||||
세 개의 파드가 모두 실행되고 있는지 확인해 보자.
|
||||
|
||||
```shell
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
<!-- discussion -->
|
||||
|
||||
### 파드가 원하는 스케줄러에 의해 스케줄링 되었는지 확인해보기
|
||||
|
||||
이번 예제들을 수월하게 진행하기 위해,
|
||||
파드가 실제로 원하는 스케줄러에 의해 스케줄링되고 있는지 확인해 보지 않았다.
|
||||
해당 사항은 파드와 디플로이먼트 구성 파일의 제출 순서를 바꿔보면 확인해 볼 수 있다.
|
||||
만일 스케줄러 디플로이먼트 구성 파일을 제출하기 전에 모든 파드의 구성 파일을 쿠버네티스 클러스터에 제출한다면,
|
||||
다른 두 개의 파드는 스케줄링 되는 와중에 `annotation-second-scheduler` 파드는
|
||||
무기한 "Pending" 상태에 머무르는 것을 관찰할 수 있다.
|
||||
스케줄러 디플로이먼트 구성 파일을 제출하여 새로운 스케줄러가 실행되기 시작하면,
|
||||
`annotation-second-scheduler` 파드도 스케줄링 된다.
|
||||
|
||||
다른 방법으로는, 이벤트 로그에서 "Scheduled" 항목을 찾아
|
||||
파드가 원하는 스케줄러에 의해 스케줄링 되었는지 확인해 볼 수 있다.
|
||||
|
||||
```shell
|
||||
kubectl get events
|
||||
```
|
||||
또한, 관련된 컨트롤 플레인 노드들의 스태틱 파드 매니페스트를 수정하면 클러스터의 메인 스케줄러로
|
||||
[사용자 정의 스케줄러 구성](/ko/docs/reference/scheduling/config/#multiple-profiles)
|
||||
또는 사용자 정의 컨테이너 이미지를 사용할 수도 있다.
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
annotations:
|
||||
rbac.authorization.kubernetes.io/autoupdate: "true"
|
||||
labels:
|
||||
kubernetes.io/bootstrapping: rbac-defaults
|
||||
name: system:kube-scheduler
|
||||
rules:
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resourceNames:
|
||||
- kube-scheduler
|
||||
- my-scheduler
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resourceNames:
|
||||
- kube-scheduler
|
||||
- my-scheduler
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
|
@ -0,0 +1,99 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: my-scheduler
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: my-scheduler-as-kube-scheduler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: my-scheduler
|
||||
namespace: kube-system
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: system:kube-scheduler
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: my-scheduler-as-volume-scheduler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: my-scheduler
|
||||
namespace: kube-system
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: system:volume-scheduler
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my-scheduler-config
|
||||
namespace: kube-system
|
||||
data:
|
||||
my-scheduler-config.yaml: |
|
||||
apiVersion: kubescheduler.config.k8s.io/v1beta2
|
||||
kind: KubeSchedulerConfiguration
|
||||
profiles:
|
||||
- schedulerName: my-scheduler
|
||||
leaderElection:
|
||||
leaderElect: false
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
component: scheduler
|
||||
tier: control-plane
|
||||
name: my-scheduler
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
component: scheduler
|
||||
tier: control-plane
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
component: scheduler
|
||||
tier: control-plane
|
||||
version: second
|
||||
spec:
|
||||
serviceAccountName: my-scheduler
|
||||
containers:
|
||||
- command:
|
||||
- /usr/local/bin/kube-scheduler
|
||||
- --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
|
||||
image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10259
|
||||
scheme: HTTPS
|
||||
initialDelaySeconds: 15
|
||||
name: kube-second-scheduler
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10259
|
||||
scheme: HTTPS
|
||||
resources:
|
||||
requests:
|
||||
cpu: '0.1'
|
||||
securityContext:
|
||||
privileged: false
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/kubernetes/my-scheduler
|
||||
hostNetwork: false
|
||||
hostPID: false
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: my-scheduler-config
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: no-annotation
|
||||
labels:
|
||||
name: multischeduler-example
|
||||
spec:
|
||||
containers:
|
||||
- name: pod-with-no-annotation-container
|
||||
image: k8s.gcr.io/pause:2.0
|
|
@ -0,0 +1,11 @@
|
|||
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: k8s.gcr.io/pause:2.0
|
|
@ -0,0 +1,11 @@
|
|||
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: k8s.gcr.io/pause:2.0
|
Loading…
Reference in New Issue