
kube-scheduler-simulatorを本物のK8sクラスターに繋いでスケジューラ実装のデモを行う
English version here.
前回の記事で、kube-scheduler-simulatorを用いて独自K8sスケジューラの開発環境を構築する方法を説明しました。 スケジューラを作ったら、本物のクラスターで試したくなるでしょう。
本稿では、kube-scheduler-simulator内で作成したスケジューラ実装を本物のクラスターに移植する方法と、 kube-scheduler-simulatorを使ってデフォルトスケジューラとの動作の違いを可視化する方法を説明します。
スケジューラを本物のクラスターにデプロイする
公式ドキュメント「Configure Multiple Schedulers」でスケジューラをデプロイする手順が紹介されています。 スケジューラというと特別なコンポーネントに思えるかもしれませんが、スケジューラもほかのコントローラと同じように動作します。 ここで重要なのは、スケジューラは実行可能ファイルだということです。
前回の記事で説明したようにkube-scheduler-simulatorツリー内でスケジューラを作成した場合、Go言語のパッケージとして実装したはずです。
これを本物のクラスターで動作させるには、main()
でラップしてコマンドにする必要があります。
minischedを実行可能なコマンドとしてビルドする
前回から引き続き、愉快な例としてminisched (initial-random-scheduler
バージョン)を使うことにします。
デフォルトのスケジューラと全く動作が異なるため、変化が分かりやすいでしょう。
以下にminischedを実行可能なmain()
の例を示します。
package main
import (
"context"
"flag"
"k8s.io/apiserver/pkg/server"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"
"example.com/kube-random-scheduler/minisched"
)
func main() {
kubeconfig := flag.String("kubeconfig", "", "kubeconfig config file")
flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
klog.Fatalf("Error building kubeconfig: %s", err.Error())
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
klog.Fatalf("Error building example clientset: %s", err.Error())
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
stopCh := server.SetupSignalHandler()
<-stopCh
cancel()
}()
informerFactory := informers.NewSharedInformerFactory(clientset, 0)
sched := minisched.New(clientset, informerFactory)
informerFactory.Start(ctx.Done())
informerFactory.WaitForCacheSync(ctx.Done())
sched.Run(ctx)
}
これをビルドするには、以下のツリーを作成してください。
kube-random-scheduler
├── main.go
└── minisched
ツリー内のminisched
ディレクトリはmini-kube-schedulerからコピーしてください。
またminisched/initialize.go
内のimport
を以下のように変更する必要があります。
Patch license: MIT (same as mini-kube-scheduler)
--- a/minisched/initialize.go
+++ b/minisched/initialize.go
@@ -1,7 +1,7 @@
package minisched
import (
- "github.com/sanposhiho/mini-kube-scheduler/minisched/queue"
+ "example.com/kube-random-scheduler/minisched/queue"
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
)
以下のコマンドでビルドします。
$ go mod init example.com/kube-random-scheduler
$ go mod tidy
$ CGO_ENABLED=0 go build -v -o kube-random-scheduler main.go
実行ファイルをビルドできたら公式ドキュメントのConfigure Multiple Schedulersに従ってデプロイできます。
ただし上記のmain()
はhealthz
の実装がないため、ドキュメント内のマニフェストからlivenessProbe
とreadinessProbe
を削除する必要があります。
kube-scheduler-simulatorでスケジューラの動作を可視化する
スケジューラのローレベルな動作を可視化したいのですが、Dashboardの機能では十分でないため、 kube-scheduler-simulatorのフロントエンドを使うことにしました。
kube-scheduler-simulatorはsimulator-server, simulator-etcd, simulator-frontendの3個のコンテナで動作します。 simulator-frontendはNuxt.jsアプリで、simulator-serverとREST APIで通信します。 このREST APIはオリジナルのK8sと互換性があるので、simulator-frontendを本物のクラスタで動作しているkube-apiserverと接続できます。 これにより本物のクラスタで動作しているスケジューラのローレベルな動作を可視化できるようになります。


まずkube-apiserver
に--cors-allowed-origins
オプションを追加します。
--- kube-apiserver.yaml.orig 2022-09-01 18:06:34.983636661 +0900
+++ kube-apiserver.yaml 2022-09-01 18:06:12.459666678 +0900
@@ -13,6 +13,7 @@
containers:
- command:
- kube-apiserver
+ - --cors-allowed-origins=http://*
- --advertise-address=192.168.1.51
- --allow-privileged=true
- --anonymous-auth=True
次にkube-scheduler-simulatorが動作しているホスト上でkubectl proxy
を実行します。
simulator-pc$ docker-compose up -d simulator-frontend
simulator-pc$ kubectl proxy
最後にウェブブラウザを動作させるホスト上でkube-scheduler-simulatorとkubectl proxy
へのトンネルを作成します。
frontend-pc$ ssh -L 3000:localhost:3000 -L 3131:localhost:8001 simulator-pc
うまくいったら、ブラウザ上でランダムスケジューラの動作を確認できます。

まとめ
- スケジューラは実行可能ファイルの形式でビルドします
- kube-scheduler-simulatorを使って本物のクラスターの動作を可視化できます
参考文献
- https://github.com/kubernetes-sigs/kube-scheduler-simulator
- https://github.com/sanposhiho/mini-kube-scheduler/tree/initial-random-scheduler/minisched
- https://kubernetes.io/docs/tasks/extend-kubernetes/configure-multiple-schedulers/