はじめに
3-shakeのSreake事業部に所属する早川(@bells17)です。第7回目の今回は、大規模なKubernetesクラスターの検証を容易にする「kwok」について紹介します。
kwokとは“Kubernetes WithOut Kubelet”の略で、実際のKubernetes Nodeではなく仮想的なNodeやPodを使用することで、1,000台以上のNodeのあるKubernetesクラスターを手元環境で手軽にセットアップして検証を行えるツールキットです。
つまり、kwokを使用することで実際のNodeを用意することなく大規模なKubernetesクラスターの検証を部分的に行えるようになります。
kwokを試してみる
「実際のNodeを使用しない」と言われてもピンとこないと思うので、まずは試してみましょう。
kwokは「kwok」と「kwokctl」の2つのコマンドラインツールによって構成されているので、はじめにインストールを行います(kwokコマンドが仮想的なNodeやPodが動作してるかのように振る舞うためのアプリケーション本体、kwokctlがkwokを便利に使うためのコマンドラインツールとなっています)。
Installationページを見ると、下記の3つの方法でインストールできます。
- Package Manager
go install
コマンド- バイナリのダウンロード
ここでは、go install
コマンド使ってインストールを行います。今回はv0.6.0を使用するため、下記のコマンドでインストールしてください(事前にGoがインストールされている必要があります)。
1 | $ go install sigs.k8s.io/kwok/cmd/{kwok,kwokctl}@v0.6.0 |
インストールが完了したら、続けて下記のコマンドを実行してクラスターと3台のNodeを構築します。
1 | $ kwokctl create cluster |
2 | $ kwokctl scale node --replicas=3 |
kwokctlには対象クラスター向けのkubectlやetcdctlなども含まれるので、今回はkwokctl経由でkubectlを使って行きましょう。
上記のコマンドを実行後kwokctl kubectl get nodeコマンドを実行すると、下記のように3台のNodeが作成されていることを確認できます。
1 | $ kwokctl kubectl get node |
2 | NAME STATUS ROLES AGE VERSION |
3 | node-000000 Ready agent 7s kwok-v0.6.0 |
4 | node-000001 Ready agent 7s kwok-v0.6.0 |
5 | node-000002 Ready agent 7s kwok-v0.6.0 |
Manage nodes and pods with kwokページのCreate a Nodeにあるように、Nodeを手動で作成することもできます。
実際に下記のようにして作成してみましょう。
コマンド実行後にkwokctl kubectl get node
コマンドを実行してみると、下記のように手動で作成したkwok-node-0
が作成されていることを確認できます。
1 | $ kwokctl kubectl get node |
2 | NAME STATUS ROLES AGE VERSION |
3 | kwok-node-0 Ready agent 1m57s kwok-v0.6.0 |
4 | node-000000 Ready agent 5m kwok-v0.6.0 |
5 | node-000001 Ready agent 5m kwok-v0.6.0 |
6 | node-000002 Ready agent 5m kwok-v0.6.0 |
それでは、引き続き下記のコマンドでPodを3個作成してみます。
1 | $ kwokctl scale pod --replicas=3 |
kwokctl kubectl get pod
コマンドを実行してみると、すぐにPodがRunningになっていることを確認できます。
1 | $ kwokctl kubectl get pod |
2 | NAME READY STATUS RESTARTS AGE |
3 | pod-000000 1/1 Running 0 4s |
4 | pod-000001 1/1 Running 0 4s |
5 | pod-000002 1/1 Running 0 4s |
このように、簡単にNodeを作成し、作成したNodeでPodを動かしているのが確認できたかと思います。ちなみにkwokctl scale pod
コマンドで生成されるPodが下記のようなmanifestsになります(不要そうなフィールドは除去しています)。
05 | kwok.x-k8s.io/kwokctl-scale: pod |
11 | imagePullPolicy: Always |
14 | - mountPath: /var/run/secrets/kubernetes.io/serviceaccount |
15 | name: kube-api-access-742pf |
19 | key: node.kubernetes.io/not-ready |
21 | tolerationSeconds: 300 |
23 | key: node.kubernetes.io/unreachable |
25 | tolerationSeconds: 300 |
27 | - name: kube-api-access-742pf |
31 | - serviceAccountToken: |
32 | expirationSeconds: 3607 |
38 | name: kube-root-ca.crt |
43 | fieldPath: metadata.namespace |
kwokで多くのリソースを作ってみる
それでは、実際に大量のNodeやPodを作成できるのか試してみます。まずは下記のコマンドを実行してNode数を増やしてみましょう。
1 | $ kwokctl scale node --replicas=20 |
kubectl get node
コマンドを実行すると、node-000xx
のNodeが20台に増えていることを確認できます。
01 | $ kwokctl kubectl get node --no-headers=true | wc -l |
03 | $ kwokctl kubectl get node |
04 | NAME STATUS ROLES AGE VERSION |
05 | kwok-node-0 Ready agent 7m kwok-v0.6.0 |
06 | node-000000 Ready agent 10m kwok-v0.6.0 |
07 | node-000001 Ready agent 10m kwok-v0.6.0 |
08 | node-000002 Ready agent 10m kwok-v0.6.0 |
09 | node-000003 Ready agent 7s kwok-v0.6.0 |
10 | node-000004 Ready agent 7s kwok-v0.6.0 |
11 | node-000005 Ready agent 7s kwok-v0.6.0 |
12 | node-000006 Ready agent 7s kwok-v0.6.0 |
13 | node-000007 Ready agent 7s kwok-v0.6.0 |
14 | node-000008 Ready agent 7s kwok-v0.6.0 |
15 | node-000009 Ready agent 7s kwok-v0.6.0 |
16 | node-000010 Ready agent 7s kwok-v0.6.0 |
17 | node-000011 Ready agent 7s kwok-v0.6.0 |
18 | node-000012 Ready agent 7s kwok-v0.6.0 |
19 | node-000013 Ready agent 7s kwok-v0.6.0 |
20 | node-000014 Ready agent 7s kwok-v0.6.0 |
21 | node-000015 Ready agent 7s kwok-v0.6.0 |
22 | node-000016 Ready agent 7s kwok-v0.6.0 |
23 | node-000017 Ready agent 7s kwok-v0.6.0 |
24 | node-000018 Ready agent 7s kwok-v0.6.0 |
25 | node-000019 Ready agent 7s kwok-v0.6.0 |
次に、下記のコマンドでPodもスケールしてみましょう。
1 | $ kwokctl scale pod --replicas=20 |
続けてkubectl get pod
コマンドを実行すると、Podが20台起動していることを確認できます。
01 | $ kubectl get node --no-headers=true | wc -l |
04 | NAME READY STATUS RESTARTS AGE |
05 | pod-000000 1/1 Running 0 2m54s |
06 | pod-000001 1/1 Running 0 2m54s |
07 | pod-000002 1/1 Running 0 2m54s |
08 | pod-000003 1/1 Running 0 19s |
09 | pod-000004 1/1 Running 0 19s |
10 | pod-000005 1/1 Running 0 19s |
11 | pod-000006 1/1 Running 0 19s |
12 | pod-000007 1/1 Running 0 19s |
13 | pod-000008 1/1 Running 0 19s |
14 | pod-000009 1/1 Running 0 19s |
15 | pod-000010 1/1 Running 0 19s |
16 | pod-000011 1/1 Running 0 19s |
17 | pod-000012 1/1 Running 0 19s |
18 | pod-000013 1/1 Running 0 19s |
19 | pod-000014 1/1 Running 0 19s |
20 | pod-000015 1/1 Running 0 19s |
21 | pod-000016 1/1 Running 0 19s |
22 | pod-000017 1/1 Running 0 19s |
23 | pod-000018 1/1 Running 0 19s |
24 | pod-000019 1/1 Running 0 19s |
先ほどは簡単に確認するためにNodeもPodも20台にスケールしましたが、手元の環境でも簡単に1000台程度にスケールさせることができました。
02 | $ kwokctl scale node --replicas=1000 |
03 | No resource found, use default resource resource=node cluster=kwok |
04 | Load resources counter=980 elapsed=4.2s resource=nodes replicas=1000 name=node cluster=kwok |
05 | $ kubectl get node --no-headers=true | wc -l |
09 | $ kwokctl scale pod --replicas=1000 |
10 | No resource found, use default resource resource=pod cluster=kwok |
11 | Load resources counter=980 elapsed=2.9s namespace=default resource=pods replicas=1000 name=pod cluster=kwok |
12 | $ kubectl get pod --no-headers=true | wc -l |
Nodeについては少し待つだけで1,000台に増やすことができましたが、PodについてはDeploymentのreplicas変更を受けて徐々にスケールするようでした。
クラスターのクリーンアップ
これで基本的な動作が確認できたので、最後に作成したクラスターを削除してみます。削除するにはkwokctl delete cluster
コマンドを実行するだけです。実行すると、下記のようにクラスターが削除されたことを確認できます。
1 | $ kwokctl delete cluster |
2 | Cluster is stopping cluster=kwok |
3 | Cluster is stopped elapsed=0.9s cluster=kwok |
4 | Cluster is deleting cluster=kwok |
kwokのアーキテクチャ
このように、NodeやPodを仮想的に動作させる仕組みを持つkwokは、指定されたラベルやアノテーションが設定されたNodeを仮想的なNodeとして扱います。そして、仮想的なNodeにスケジュールされたPodに対し、kwokが管理するカスタムリソースであるStageリソースの条件をもとにPodのステータスをreadyに変更することで、Podが起動している状態をシミュレートする実装みになっているようでした。
また、その他Stageリソースを使ってNodeのステータス管理を行ったり、仮想的なNodeのNode Leaseを更新することでKubernetesから見て正常に動作しているNodeであると認識させるといったことも行っているようです。
Stageリソースは、例えば下記のようになっています。
01 | apiVersion: kwok.x-k8s.io/v1alpha1 |
11 | - key: '.status.conditions.[] | select( .type == "Ready" ) | .status' |
18 | {{ $lastTransitionTime := or .metadata.creationTimestamp $now }} |
20 | {{ range NodeConditions }} |
21 | - lastHeartbeatTime: {{ $now | Quote }} |
22 | lastTransitionTime: {{ $lastTransitionTime | Quote }} |
23 | message: {{ .message | Quote }} |
24 | reason: {{ .reason | Quote }} |
25 | status: {{ .status | Quote }} |
26 | type: {{ .type | Quote}} |
30 | {{ with .status.addresses }} |
34 | - address: {{ . | Quote }} |
38 | - address: {{ . | Quote }} |
50 | {{ with .status.allocatable }} |
58 | {{ with .status.capacity }} |
66 | {{ $nodeInfo := .status.nodeInfo }} |
67 | {{ $kwokVersion := printf "kwok-%s" Version }} |
69 | architecture: {{ or $nodeInfo.architecture "amd64" }} |
70 | bootID: {{ or $nodeInfo.bootID `""` }} |
71 | containerRuntimeVersion: {{ or $nodeInfo.containerRuntimeVersion $kwokVersion }} |
72 | kernelVersion: {{ or $nodeInfo.kernelVersion $kwokVersion }} |
73 | kubeProxyVersion: {{ or $nodeInfo.kubeProxyVersion $kwokVersion }} |
74 | kubeletVersion: {{ or $nodeInfo.kubeletVersion $kwokVersion }} |
75 | machineID: {{ or $nodeInfo.machineID `""` }} |
76 | operatingSystem: {{ or $nodeInfo.operatingSystem "linux" }} |
77 | osImage: {{ or $nodeInfo.osImage `""` }} |
78 | systemUUID: {{ or $nodeInfo.systemUUID `""` }} |
このリソースで、kwokに下記のような指示を出すことにより対象リソースを更新しています。
- どのリソースが(.spec.resourceRef)
- どの条件の際に(.spec.selector)
- どのようなステータスに設定されるのか?(.spec.next.statusTemplate)
これにより、NodeやPodの状態をコントロールして仮想的なNodeやPodとして動作するような状態を構築しています。今回のようにkwokctlを使用して環境を構築した際は実際にはStageリソースは作られず、組み込みのStageリソースが使用されます。
一方、kwokはDeploy kwok in a Clusterページにあるように、既存のクラスターに対してデプロイすることも可能です。
Stageリソースは、こういったケースで使用されるようになっているようです。
kwokの利用用途
kwokは元々はfake-kubeletとfake-k8sというリポジトリが元となっており、現在はKubernetesコミュニティのsig-schedulingのサブプロジェクトとして開発されているようです。
IntroductionページのUser Storiesを見ると、下記のような主にパフォーマンスに対するテストを中心としたユースケースが想定されているようです。
- 多数のNodeとPodを使用したkube-schedulerのテスト
- CRD Controllerの開発
- control planeのパフォーマンステスト
Adoptersページを見ると実際にkwokを使用したテストの例を見ることができますが、特に下記からパフォーマンステストやスケーラビリティのテストに使用されていることが伺えます。
また、Kubernetesにおけるe2eテストツールでの利用がサポートされていたり、kube-scheduler-simulatorというKubernetesのスケジューラーの動作をシュミレートするツールの内部でkwokが利用されているようです。
おわりに
今回は仮想的なNodeとPodを使用して、大量のNodeやPodを起動した際のシュミレートを行い、パフォーマンスやスケーラビリティのテストなどを簡単に行えるkwokについて紹介しました。
ソースコードを見ると「kubeletなしでNodeやPodをどのようにしてreadyな状態で管理するのか」といったKubernetesの仕組みに対する理解にも繋がり非常に面白いツールだと感じたので、ぜひみなさんも利用してみてください。