複数のスケジューラーを設定する
Kubernetesにはこちらで説明されているデフォルトのスケジューラーが付属します。 もしデフォルトのスケジューラーがあなたの要求を満たさない場合、独自にスケジューラーを実装できます。 さらに、デフォルトのスケジューラーと一緒に複数のスケジューラーを同時に実行し、どのPodにどのスケジューラーを使うかKubernetesに指示できます。 具体例を見ながらKubernetesで複数のスケジューラーを実行する方法を学びましょう。
スケジューラーの実装方法の詳細は本ドキュメントの範囲外です。 標準的な例としてKubernetesのソースディレクトリのpkg/schedulerにあるkube-schedulerの実装が参照できます。
始める前に
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください: kubectl version
.
スケジューラーをパッケージ化する
スケジューラーのバイナリをコンテナイメージとしてパッケージ化します。 例として、デフォルトのスケジューラー(kube-scheduler)を2つ目のスケジューラーとして使用します。 GitHubからKubernetesのソースコードをクローンし、ビルドします。
git clone https://github.com/kubernetes/kubernetes.git
cd kubernetes
make
kube-schedulerバイナリを含むコンテナイメージを作成します。
そのためのDockerfile
は次のとおりです:
FROM busybox
ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler
これをDockerfile
として保存し、イメージをビルドしてレジストリにプッシュします。
次の例ではGoogle Container Registry (GCR)を使用します。
詳細はGCRのドキュメントから確認できます。
代わりにDocker Hubを使用することもできます。
Docker Hubの詳細はドキュメントから確認できます。
docker build -t gcr.io/my-gcp-project/my-kube-scheduler:1.0 . # The image name and the repository
gcloud docker -- push gcr.io/my-gcp-project/my-kube-scheduler:1.0 # used in here is just an example
スケジューラー用のKubernetes Deploymentを定義する
スケジューラーをコンテナイメージとして用意できたら、それ用のPodの設定を作成してクラスター上で動かします。
この例では、直接Podをクラスターに作成する代わりに、Deploymentを使用します。
DeploymentはReplicaSetを管理し、そのReplicaSetがPodを管理することで、スケジューラーを障害に対して堅牢にします。
my-scheduler.yaml
として保存するDeploymentの設定を示します:
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: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-scheduler-extension-apiserver-authentication-reader
namespace: kube-system
roleRef:
kind: Role
name: extension-apiserver-authentication-reader
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: my-scheduler
namespace: kube-system
---
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
上に示したマニフェストでは、KubeSchedulerConfigurationを使用してあなたのスケジューラー実装の振る舞いを変更できます。
この設定ファイルはkube-scheduler
の初期化時に--config
オプションから渡されます。
この設定ファイルはmy-scheduler-config
ConfigMapに格納されており、my-scheduler
DeploymentのPodはmy-scheduler-config
ConfigMapをボリュームとしてマウントします。
前述のスケジューラー設定において、あなたのスケジューラー実装はKubeSchedulerProfileを使って表現されます。
備考:
特定のPodをどのスケジューラーが処理するかを指定するには、PodTemplateやPodのマニフェストにあるspec.schedulerName
フィールドをKubeSchedulerProfile
のschedulerName
フィールドに一致させます。
クラスターで動作させるすべてのスケジューラーの名前は一意的である必要があります。また、専用のサービスアカウントmy-scheduler
を作成してsystem:kube-scheduler
ClusterRoleに紐づけを行い、スケジューラーにkube-scheduler
と同じ権限を付与している点に注意します。
その他のコマンドライン引数の詳細はkube-schedulerのドキュメントから、その他の変更可能なkube-scheduler
の設定はスケジューラー設定のリファレンスから確認できます。
クラスターで2つ目のスケジューラーを実行する
2つ目のスケジューラーをクラスター上で動かすには、前述のDeploymentをKubernetesクラスターに作成します:
kubectl create -f my-scheduler.yaml
スケジューラーのPodが実行中であることを確認します:
kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
....
my-scheduler-lnf4s-4744f 1/1 Running 0 2m
...
このリストにはデフォルトのkube-schedulerのPodに加えて、my-schedulerのPodが「Running」になっているはずです。
リーダー選出を有効にする
リーダー選出を有効にして複数のスケジューラーを実行するには、次の対応が必要です:
YAMLファイルにあるmy-scheduler-config
ConfigMap内のKubeSchedulerConfiguration
の次のフィールドを更新します:
leaderElection.leaderElect
をtrue
に設定しますleaderElection.resourceNamespace
を<lock-object-namespace>
に設定しますleaderElection.resourceName
を<lock-object-name>
に設定します
備考:
ロックオブジェクトはコントロールプレーンが自動的に作成しますが、使用するNamespaceはあらかじめ存在している必要があります。kube-system
Namespaceを使うこともできます。クラスターでRBACが有効になっている場合、system:kube-scheduler
ClusterRoleを更新し、endpoints
とleases
リソースに適用されるルールのresourceNamesにスケジューラー名を追加します。
例を示します:
kubectl edit clusterrole system:kube-scheduler
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
Podにスケジューラーを指定する
2つ目のスケジューラーが動作している状態で、Podをいくつか作成し、デフォルトのスケジューラーまたは新しいスケジューラーのどちらで配置するか指定します。 あるPodを特定のスケジューラーで配置するには、Podのspecにスケジューラー名を指定します。 3つの例を確認しましょう。
スケジューラー名を指定しないPodの設定
apiVersion: v1 kind: Pod metadata: name: no-annotation labels: name: multischeduler-example spec: containers: - name: pod-with-no-annotation-container image: registry.k8s.io/pause:3.8
スケジューラー名が指定されていない場合、Podは自動的にdefault-schedulerによって配置されます。
このファイルを
pod1.yaml
として保存し、Kubernetesクラスターに投入します。kubectl create -f pod1.yaml
default-scheduler
を指定するPodの設定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:3.8
使用するスケジューラーは
spec.schedulerName
の値にスケジューラー名を与えることで指定します。 この場合、デフォルトのスケジューラーであるdefault-scheduler
を指定します。このファイルを
pod2.yaml
として保存し、Kubernetesクラスターに投入します。kubectl create -f pod2.yaml
my-scheduler
を指定するPodの設定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:3.8
この場合、前述の手順でデプロイした
my-scheduler
を使用してPodを配置することを指定します。spec.schedulerName
の値はKubeSchedulerProfile
のschedulerName
フィールドに設定した名前と一致する必要があります。このファイルを
pod3.yaml
として保存し、クラスターに投入します。kubectl create -f pod3.yaml
3つのPodがすべて実行中であることを確認します。
kubectl get pods
Podが目的のスケジューラーによって配置されたことを確認する
わかりやすさのため、前述の例ではPodが実際に指定したスケジューラーによって配置されたことを確認していません。
確認したい場合はPodとDeploymentの設定の適用順序を変えてみてください。
もしPodの設定をすべて先に適用し、その後にスケジューラーのDeploymentを適用した場合、annotation-second-scheduler
Podは「Pending」のままになり、他の2つのPodが先に配置されることを確認できます。
その後にスケジューラーのDeploymentを適用して新しいスケジューラーが動作すると、annotation-second-scheduler
Podも配置されます。
あるいは、イベントログの「Scheduled」の項目を見ることで、どのPodがどのスケジューラーによって配置されたかを確認できます。
kubectl get events
クラスターのメインのスケジューラーについては、独自のスケジューラー設定を適用することや、関連するコントロールプレーンノードにある静的Podのマニフェストを変更し独自のコンテナイメージを使うことができます。