Proxmox環境でサクッと作ってサクっと壊せる高可用性なkubernetesクラスタを作ってみる
Proxmox Virtual Environment 7.2-4
クラスタ構成にすると、proxmoxホスト間でrootユーザーによるSSH接続が可能となります。
これはクラスタの各種機能を維持するために使用されています。また、手順やスクリプトの一部はこのSSH接続を前提としています。
以下は本リポジトリのサクッと作ってサクッと壊す対象外なので別途用意しておく
proxmoxのホストコンソール上でdeploy-vm.sh
を実行すると、各種VMが沸き、クラスタの初期セットアップ、ArgoCDの導入などが行われます。TARGET_BRANCH
はデプロイ対象のコードが反映されたブランチ名に変更してください。
export TARGET_BRANCH=main
/bin/bash <(curl -s https://raw.githubusercontent.com/unchama/kube-cluster-on-proxmox/${TARGET_BRANCH}/deploy-vm.sh) ${TARGET_BRANCH}
deploy-vm.sh
ではProxmoxホスト間でSSH接続を行っています。クラスタ構成済みのProxmoxホストを前提としているため追加の認証情報の入力は不要ですが、Proxmoxホストを新規もしくはクリーンインストールした後にdeploy-vm.sh
を実行する場合、ホスト公開鍵の登録を確認するプロンプトが出る場合がありますので対応してください。
ローカル端末上で~/.ssh/config
をセットアップ
Host <踏み台サーバーホスト名>
HostName <踏み台サーバーホスト名>
ProxyCommand cloudflared access ssh --hostname %h
User <踏み台サーバーユーザー名>
IdentityFile ~/.ssh/id_ed25519
Host unc-k8s-cp-1
HostName 172.16.17.11
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
Host unc-k8s-cp-2
HostName 172.16.17.12
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
Host unc-k8s-cp-3
HostName 172.16.17.13
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
Host unc-k8s-wk-1
HostName 172.16.17.21
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
Host unc-k8s-wk-2
HostName 172.16.17.22
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
Host unc-k8s-wk-3
HostName 172.16.17.23
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
ローカル端末上でコマンド実行
# known_hosts登録削除(VM作り直す度にホスト公開鍵が変わる為)
ssh-keygen -R 172.16.17.11
ssh-keygen -R 172.16.17.12
ssh-keygen -R 172.16.17.13
ssh-keygen -R 172.16.17.21
ssh-keygen -R 172.16.17.22
ssh-keygen -R 172.16.17.23
# 接続チェック(ホスト公開鍵の登録も兼ねる)
ssh unc-k8s-cp-1 "hostname"
ssh unc-k8s-cp-2 "hostname"
ssh unc-k8s-cp-3 "hostname"
ssh unc-k8s-wk-1 "hostname"
ssh unc-k8s-wk-2 "hostname"
ssh unc-k8s-wk-3 "hostname"
# クラスタセットアップが終わっているかチェック
ssh unc-k8s-cp-1 "kubectl get node -o wide && kubectl get pod -A -o wide"
ssh unc-k8s-cp-2 "kubectl get node -o wide && kubectl get pod -A -o wide"
ssh unc-k8s-cp-3 "kubectl get node -o wide && kubectl get pod -A -o wide"
# cloudinitの実行ログチェック(トラブルシュート用)
# だいたいのスクリプトは unc-k8s-cp-1で動いてます
## check /var/log/cloud-init-output.log
ssh unc-k8s-cp-1 "sudo cat /var/log/cloud-init-output.log"
ssh unc-k8s-cp-2 "sudo cat /var/log/cloud-init-output.log"
ssh unc-k8s-cp-3 "sudo cat /var/log/cloud-init-output.log"
ssh unc-k8s-wk-1 "sudo cat /var/log/cloud-init-output.log"
ssh unc-k8s-wk-2 "sudo cat /var/log/cloud-init-output.log"
ssh unc-k8s-wk-3 "sudo cat /var/log/cloud-init-output.log"
## cloud-init.service - Initial cloud-init job (metadata service crawler)
ssh unc-k8s-cp-1 "sudo journalctl -u cloud-init.service"
ssh unc-k8s-cp-2 "sudo journalctl -u cloud-init.service"
ssh unc-k8s-cp-3 "sudo journalctl -u cloud-init.service"
ssh unc-k8s-wk-1 "sudo journalctl -u cloud-init.service"
ssh unc-k8s-wk-2 "sudo journalctl -u cloud-init.service"
ssh unc-k8s-wk-3 "sudo journalctl -u cloud-init.service"
## cloud-init-local.service - Initial cloud-init job (pre-networking)
ssh unc-k8s-cp-1 "sudo journalctl -u cloud-init-local.service"
ssh unc-k8s-cp-2 "sudo journalctl -u cloud-init-local.service"
ssh unc-k8s-cp-3 "sudo journalctl -u cloud-init-local.service"
ssh unc-k8s-wk-1 "sudo journalctl -u cloud-init-local.service"
ssh unc-k8s-wk-2 "sudo journalctl -u cloud-init-local.service"
ssh unc-k8s-wk-3 "sudo journalctl -u cloud-init-local.service"
## cloud-config.service - Apply the settings specified in cloud-config
ssh unc-k8s-cp-1 "sudo journalctl -u cloud-config.service"
ssh unc-k8s-cp-2 "sudo journalctl -u cloud-config.service"
ssh unc-k8s-cp-3 "sudo journalctl -u cloud-config.service"
ssh unc-k8s-wk-1 "sudo journalctl -u cloud-config.service"
ssh unc-k8s-wk-2 "sudo journalctl -u cloud-config.service"
ssh unc-k8s-wk-3 "sudo journalctl -u cloud-config.service"
## cloud-final.service - Execute cloud user/final scripts
## k8s-node-setup.sh などのログはここにあります
ssh unc-k8s-cp-1 "sudo journalctl -u cloud-final.service"
ssh unc-k8s-cp-2 "sudo journalctl -u cloud-final.service"
ssh unc-k8s-cp-3 "sudo journalctl -u cloud-final.service"
ssh unc-k8s-wk-1 "sudo journalctl -u cloud-final.service"
ssh unc-k8s-wk-2 "sudo journalctl -u cloud-final.service"
ssh unc-k8s-wk-3 "sudo journalctl -u cloud-final.service"
Enjoy ;)
ローカル端末上で以下コマンドを実行してargoCDの初期パスワードを取得する
ssh unc-k8s-cp-1 "kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d"
ローカル端末上でssh-portforward用の~/.ssh/config
をセットアップ。ちなみに、LocalForward先のIPアドレスはここで定義している
Host <踏み台サーバーホスト名>
HostName <踏み台サーバーホスト名>
ProxyCommand cloudflared access ssh --hostname %h
User <踏み台サーバーユーザー名>
IdentityFile ~/.ssh/id_ed25519
Host unc-k8s-cp-1_fwd
HostName 172.16.3.11
User cloudinit
IdentityFile ~/.ssh/id_ed25519
ProxyCommand ssh -W %h:%p <踏み台サーバーホスト名>
# ArgoCD web-panel
LocalForward 4430 172.16.3.240:443
トンネル用のSSHセッションを開始する
ssh unc-k8s-cp-1_fwd
ローカルブラウザでhttps://localhost:4430にアクセスし、ユーザーIDadmin
でログインする。パスワードは先の手順で取得した初期パスワードを使用する
Enjoy;)
synology-csi-driver
により、Synology NAS(DS1621+)上から動的プロビジョンされたストレージ領域を使用可能です。
利用に必要なsynology-csi-driver
およびstorage-class
はArgoCDによりデプロイされます。NASへの接続に必要な認証情報のみ、以下の方法でSecretとして入れ込んでください。
クラスタにkubectlでアクセス可能な端末(unc-k8s-cp-1
など)で以下コマンドを実行
# ファイル名は client-info.yml である必要があるので変更しないこと
export config_file=/tmp/client-info.yml
export csi_user=<ユーザーID>
export csi_password=<パスワード>
cat > $config_file <<EOF
---
clients:
- host: 172.16.15.245
port: 5000
https: false
username: ${csi_user}
password: ${csi_password}
EOF
kubectl create secret -n synology-csi generic client-info-secret --from-file="$config_file"
rm $config_file
proxmoxのホストコンソール上で以下コマンド実行
# stop vm
## on sc-tst-proxmox-02
ssh 172.16.0.112 qm stop 1001
ssh 172.16.0.112 qm stop 1101
ssh 172.16.0.112 qm stop 1002
ssh 172.16.0.112 qm stop 1102
ssh 172.16.0.112 qm stop 1003
ssh 172.16.0.112 qm stop 1103
# delete vm
## on sc-tst-proxmox-02
ssh 172.16.0.112 qm destroy 1001 --destroy-unreferenced-disks true --purge true
ssh 172.16.0.112 qm destroy 1101 --destroy-unreferenced-disks true --purge true
ssh 172.16.0.112 qm destroy 9050 --destroy-unreferenced-disks true --purge true
ssh 172.16.0.112 qm destroy 1002 --destroy-unreferenced-disks true --purge true
ssh 172.16.0.112 qm destroy 1102 --destroy-unreferenced-disks true --purge true
ssh 172.16.0.112 qm destroy 1003 --destroy-unreferenced-disks true --purge true
ssh 172.16.0.112 qm destroy 1103 --destroy-unreferenced-disks true --purge true
クラスタの削除後、同じVMIDでVMを再作成できず、クラスタの作成に失敗することがあります。
これは、クラスタの削除時に複数ノードでコマンドqm destroy
が実行された際に、Device Mapperで生成された仮想ディスクデバイスの一部が消えずに残留することがあるためです。
上記事象に遭遇した場合は、以下いずれかの方法で解決を試みてください。
残った仮想ディスクデバイスを手動で削除する
クラスタを構成するVMが一部でも存在する場合は、事前にクラスタの削除を実施してください。
その後、proxmoxをホストしている物理マシンのターミナル上で次のコマンドを実行し、残ったデバイスを削除します。
for host in 172.16.0.112 ; do
ssh $host dmsetup remove vg01-vm--1101--cloudinit
ssh $host dmsetup remove vg01-vm--1102--cloudinit
ssh $host dmsetup remove vg01-vm--1103--cloudinit
ssh $host dmsetup remove vg01-vm--1001--cloudinit
ssh $host dmsetup remove vg01-vm--1002--cloudinit
ssh $host dmsetup remove vg01-vm--1003--cloudinit
ssh $host dmsetup remove vg01-vm--1101--disk--0
ssh $host dmsetup remove vg01-vm--1102--disk--0
ssh $host dmsetup remove vg01-vm--1103--disk--0
ssh $host dmsetup remove vg01-vm--1001--disk--0
ssh $host dmsetup remove vg01-vm--1002--disk--0
ssh $host dmsetup remove vg01-vm--1003--disk--0
done
参考: cannot migrate - device-mapper:create ioctl on cluster failed - proxmox forum
全proxmoxホストを再起動する
proxmoxホスト上の全てのVMの停止を伴うため、サービス提供中の本番環境では推奨されません。