この記事は以下の記事での検証内容を発展させた内容です。この記事を読む前に読んで頂くと理解が深まります。
Dockerとvctlコンテナでkind @ Mac by @plumchang
執筆の動機
K8Sの勉強をやろうやろうと思いつつ、先延ばしに。。。ところが、以前、ひょんなことから一念発起して専門書まで買って勉強しようとしたことが有りました。ところが、マルチノードK8Sの環境構築はその当時結構な難易度でした。故にそこで挫折。。。 しかし、以前に比べて環境構築が容易になったと知り、@plumchangさんにお願いして検証して貰ったのが、お正月明け。 (@plumchangさん、協力感謝)ところが、マルチノード(例: Master x 1, Worker x 3)といった環境はあまりにもメモリを消費するため、検証が難しかったとのこと。そこで、メモリが豊富に使える環境を用意して筆者が検証をしてみることにしました。
検証環境
- macOS 11.4 Big Sur (MacBook Air 2018 DRAM 16GB)1
- Docker Desktop Version 3.4.0
- Docker Compose Version 1.29.2
- Go 1.16.4
- VMWare Fusion 12.1.2
- kind v0.11.1
- Homebrew 3.1.12
- kind v0.9.0(vctlコンテナ用)
環境構築
今回検証を行った環境では、既にDocker Desktop、Docker Compose、Go言語、VMWare Fusionのセットアップは完了していました。故に以下の行程は、これらのアプリケーションのインストールが完了してから実施して下さい。
kind(Kubernetes in Docker)のインストール
まずは、kindをインストールします。Go言語のパッケージマネージャーであるgo get
コマンドでインストール出来ます。
go get sigs.k8s.io/kind
2021/12/5追記: Homebrewでインストール可能になりました。
macOS 12.0.1 Montereyで以下の方法でインストール出来ることを確認しました。
brew install kind
kind v0.11.1がインストールされました。
kubectlのインストール
K8Sを操作するコマンドです。Homebrewで簡単にインストール出来ます。
brew install kubectl
インストールが完了したら、以下の内容を.bashrc
に追記します。
source <(kubectl completion bash)
.bashrc
を再読込し、有効化します。
source .bashrc
以上で、環境構築が完了しました。それでは、いよいよマルチクラスターK8Sの環境を構築します。
マルチクラスターK8S環境の構築
今回構築するK8Sの環境は、Masterノード x 1、Workerノード x 3という構成です。Dockerのコンテナを用いて構築する方法、vctlコンテナ(VMWare Fusion)を用いて構築する方法の2種類を試します。
Dockerのコンテナを用いて構築する場合
まずはオーソドックスにDockerのコンテナを用いて環境構築を実施してみます。
config.ymlの作成
マルチノード環境を構築するための設定を記述したconfig.ymlファイルを作成します。公式のドキュメントを参考にします。
2022/11/20追記: 外部アクセスへの対応
K8s上で立てたサービスを外部からアクセスしたい場合が有りますが,デフォルトではアクセス出来ません.よってconfig.ymlに設定を追加し,サービスタイプをNodePortに設定したサービスを外部からアクセス出来る様にします.
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30950
hostPort: 9898
- role: worker
- role: worker
- role: worker
サービスを立てる時にポートを開放する場合,以下の記入例の様にコンテナ内部のポート番号に関係無く,常に30950と紐付けて立てる必要が有ります.外部からアクセスする時,例えばK8sを動作させているマシン上からアクセスする場合は,http://localhost:9898
でアクセス出来ます.
spec:
type: NodePort
ports:
- name: http
nodePort: 30950
port: 5678
参考
kind
コマンドを実行します。これでマルチノードK8Sが起動します。
kind create cluster --name k8s --config=config.yml
実行結果
$ kind create cluster --name k8s --config=config.yml
Creating cluster "k8s" ...
✓ Ensuring node image (kindest/node:v1.21.1) 🖼
✓ Preparing nodes 📦 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-k8s"
You can now use your cluster with:
kubectl cluster-info --context kind-k8s
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
ノードの確認
kubectl
コマンドで確認すると、マルチノード環境が起動していることが分かります。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control-plane Ready control-plane,master 3m19s v1.21.1
k8s-worker Ready <none> 2m49s v1.21.1
k8s-worker2 Ready <none> 2m49s v1.21.1
k8s-worker3 Ready <none> 2m49s v1.21.1
Deployの動作確認
動作確認を兼ねてnginxをデプロイしてみます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
以下のコマンドを順に実行します。
kubectl apply -f deployment.yml
kubectl create service nodeport nginx --tcp=8080:80
kubectl port-forward --address localhost svc/nginx 8080:8080
実行結果
$ kubectl apply -f deployment.yml
deployment.apps/nginx-deployment created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-fnj9z 1/1 Running 0 48s
nginx-deployment-66b6c48dd5-kssdc 1/1 Running 0 48s
nginx-deployment-66b6c48dd5-x6kcn 1/1 Running 0 48s
$ kubectl create service nodeport nginx --tcp=8080:80
service/nginx created
$ kubectl port-forward --address localhost svc/nginx 8080:8080
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
新規ウィンドウでターミナルを起動し、以下のコマンドを実行します。
curl http://localhost:8080
実行結果
$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
後片付け
以下のコマンドを実行します。
kubectl delete services nginx
kubectl delete -f deployment.yml
$ kubectl delete services nginx
service "nginx" deleted
$ kubectl delete -f deployment.yml
deployment.apps "nginx-deployment" deleted
環境を破棄する場合
以下のコマンドを実行します。
kind delete cluster --name k8s
実行結果
$ kind delete cluster --name k8s
Deleting cluster "k8s" ...
シェル化してみる
kindによる環境構築は永続的な環境と言うよりは、お試しの環境構築で必要な時に作って、要らなくなった破棄という様な使い方が出来るのではと思いました。(あくまで筆者の主観です)今回はお勉強に使う環境構築なので、必要な時に起動して、終わったら破棄できるように、起動シェルと終了シェルを作っておくことにします。
#!/bin/bash
kind create cluster --name k8s --config=config.yml
#!/bin/bash
kind delete cluster --name k8s
実行権限付与は以下のコマンドを実行します。
chmod +x build_env.sh
chmod +x delete_env.sh
vctlコンテナを用いて構築する場合
以下の行程はVMWare Fusionがインストールされている環境で実行されることを前提としています。VMWare Fusion Playerは無料で利用できます。今回は検証にMacを使用した為、Fusionを利用していますが、Linux/Windowsを利用されている方は、同じくVMWareのWorkstation ProまたはWorkstatio Playerを利用すると同様に構築出来る様です。(参考)
初期セットアップ
ターミナルを新しく起動し、以下のコマンドを順に実行します。初回のみkubectlやkindとの連携処理が実行されます。
vctl環境は起動を実行したターミナルを終了した時点で構築した環境が破棄されます。
vctl system start
実行結果
$ vctl system start
Downloading 3 files...
Downloading [kind-darwin-amd64 99.44% kubectl 84.97% crx.vmdk 46.15%]
Finished kind-darwin-amd64 100.00%
Downloading [kubectl 99.88% crx.vmdk 60.89%]
Finished kubectl 100.00%
Downloading [crx.vmdk 99.42%]
Finished crx.vmdk 100.00%
3 files successfully downloaded.
Preparing storage...
Container storage has been prepared successfully under /Users/yuhkiyano/.vctl/storage
Launching container runtime...
Container runtime has been started.
vctl kind
実行結果
$ vctl kind
vctl-based KIND is ready now. KIND will run local Kubernetes clusters by using vctl containers as "nodes"
* All Docker commands has been aliased to vctl in the current terminal. Docker commands performed in current window would be executed through vctl. If you need to use regular Docker commands, please use a separate terminal window.
kindのバージョンが異なることが分かります。vctl用のkindがインストールされました。
$ kind version
kind v0.9.0 go1.15.2 darwin/amd64
ここまで完了したら、一旦PCを再起動します。このまま実行すると、何故かエラー終了してマルチノード環境が構築出来ませんでした。(エラーメッセージの魚拓が残せず。。。)
マルチノード環境の起動
PC再起動後に以下のコマンドを実行します。
kind create cluster --name k8s --config=config.yml
実行結果
筆者はシェルで実行してます。
$ kind create cluster --name k8s --config=config.yml
Creating cluster "k8s" ...
✓ Ensuring node image (kindest/node:v1.19.1) 🖼
✓ Preparing nodes 📦 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-k8s"
You can now use your cluster with:
kubectl cluster-info --context kind-k8s
Thanks for using kind! 😊
以下の様にマルチノード環境が構築出来ています。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control-plane Ready master 2m48s v1.19.1
k8s-worker Ready <none> 86s v1.19.1
k8s-worker2 Ready <none> 86s v1.19.1
k8s-worker3 Ready <none> 85s v1.19.1
完成後のデスクトップは以下の様にVM集団に占拠されています。
Deployの動作確認
Dockerのコンテナと同様にDeployの動作確認をしました。動作は全く同じであるため割愛します。
後始末
以下のコマンドを順に実行します。
kubectl delete service nginx
kubectl delete -f deployment.yml
kind delete cluster --name k8s
vctl system stop
実行結果
$ kubectl delete service nginx
service "nginx" deleted
$ kubectl delete -f deployment.yml
deployment.apps "nginx-deployment" deleted
$ kind delete cluster --name k8s
Deleting cluster "k8s" ...
$ vctl system stop
Terminating container runtime...
Container runtime has been stopped.
Detaching storage...
Container storage has been detached.
まとめ
kindを用いてDockerコンテント及びvctlコンテナを用いてマルチノードK8Sの環境構築を試みました。どちらも最終的に出来上がる環境の構成は同じですが、vctlコンテナはVMベースとなっているためか、動作速度がDockerコンテナを用いた環境より遅く感じます。また、メモリなどのリソースも多く消費します。手軽に利用するのであれば、余程の理由(Dockerが嫌い等)が無い限り、Dockerコンテナを用いる方が賢明だと思います。
今後の目標
- K8S完全マスター
- GPUサーバーにK8SをKVMで構築して、GPUも使えるWorkerノードを持つ環境を構築
- @plumchangさんも巻き込んでK8S資格 x 3に挑戦
補足事項
kubectl get nodes
コマンドで、ノード情報をを取得した時に、workerノードだけROLESが<none>
となっており、気持ち悪い状態です。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control-plane Ready control-plane,master 5h31m v1.21.1
k8s-worker Ready <none> 5h31m v1.21.1
k8s-worker2 Ready <none> 5h31m v1.21.1
k8s-worker3 Ready <none> 5h31m v1.21.1
以下のコマンドで解消。
kubectl label nodes k8s-worker kubernetes.io/role=worker
実行結果
$ kubectl label nodes k8s-worker kubernetes.io/role=worker
node/k8s-worker labeled
$ kubectl label nodes k8s-worker2 kubernetes.io/role=worker
node/k8s-worker2 labeled
$ kubectl label nodes k8s-worker3 kubernetes.io/role=worker
node/k8s-worker3 labeled
以下の様に、workerノードのROLESがworker
になりました。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control-plane Ready control-plane,master 5h38m v1.21.1
k8s-worker Ready worker 5h38m v1.21.1
k8s-worker2 Ready worker 5h38m v1.21.1
k8s-worker3 Ready worker 5h38m v1.21.1
Reference
- Dockerとvctlコンテナでkind @ Mac
- vctl コマンドを使用したコンテナの管理と Kubernetes クラスタの実行
- VMware Workstation 16 Proでvctl kindを試してみた
- kind公式
- kubectlのインストールおよびセットアップ
- How to add roles to nodes in Kubernetes?
-
DRAM 8GBでは今回構築するマルチノード環境は動作が厳しい様です。 ↩