このたびおうちのクラスタを作り直したので記録しておきます。
kubespray や ansible で頑張っていましたが、力尽きてしまったのでもっと良い感じになうでやんぐな若者がやってるやり方を調べて実践しました。(当社調べ)
今回は rancher を使ってクラスタを作っていきます。
rancher は k8s クラスタの管理をしてくれるもので、マルチプラットフォームに対応しており、gke や eks その他クラウドベンダーの k8s クラスタをまとめて管理できるものです。
本来は組織的に管理しているものを管理しやすくするためのものですが、 rancher ではオンプレ環境でのクラスタの作成も行える為、おうちのクラスタの作成・管理を目的として使用しています。
その為、この記事では作成することを目的とした内容になっています。
自分がクラスタ作って任意のリソースをクラスタ上に作成できるようになるまでの備忘録のようなものです。
ググってすぐ出てきたようなものはすっ飛ばして躓いた部分を書いています。
これまでの構成
k8s,インフラ的な部分とソフトウェア的な部分の境界がわかりにくくて色んなレイヤーの話が混ざってしまい、構成図書くの難しい。
何か標準的なものがあるのかな。ありそう。
新バージョン(KVM/QEMU + Opennebula + Rancher + nginx-ingress)
<img src="https://strapi.im-neko.net/uploads/new_topology_drawio_a927559d9f.png" alt="new-arch">
この構成にしてよくなったところ
- rancherでk8sクラスタを立ち上げるようにしたことでそもそもterraformが不要になった
- ノードの増減がGUIでポチポチで良くなった
- ノードが落ちてしまった時rancherが勝手に新しいノードを作成して割り当ててくれる
手順
以下の物をインストールしていった
- KVM/QEMU
- Opennebula
- Rancher
- nginx-ingress-controller
KVM/QEMU
opennebulaがubuntu 22.04だと上手く動かなかったので一度20.04をインストールし直す必要があったくらい
備忘録も兼ねているので一応参考リンクを貼っておく
<a href="https://ubuntu.com/blog/kvm-hyphervisor">https://ubuntu.com/blog/kvm-hyphervisor</a>
Opennebula
本家のドキュメントを見ながらインストールした
minioneを使ってポンって最初やっていたがやってくうちによくわからんくなったので順に手動でインストールした
<a href="https://docs.opennebula.io/6.4/installation_and_configuration/frontend_installation/install.html">https://docs.opennebula.io/6.4/installation_and_configuration/frontend_installation/install.html</a>
物理マシンは1台なのでfrontendと本体?も一緒にインストールした
ケチ臭い人間なのでrancherを動かす用のVMを動かすのも嫌だったのでホスト上で直接docker動かしてrancherを動かしている。
rancher
このあたりから結構躓いた
基本は以下のドキュメントを見ながらインストールした
<a href="https://docs.opennebula.io/6.4/integration_and_development/automation_tools_integration/rancher.html">https://docs.opennebula.io/6.4/integration_and_development/automation_tools_integration/rancher.html</a>
rancherの起動
まずdockerを動かすときに --plivileged
オプションが必要だった
また、opennebulaを80番で動かしていてポートが被ったので別ポートで動かしている
docker run -d --restart=unless-stopped --privileged -v rancher-data:/var/lib/rancher -p 8080:80 -p 8443:443 rancher/rancher:v2.7.4
node driverのインストール
ドキュメントにあるURL(https://downloads.opennebula.io/packages/opennebula-6.4.0/opennebula-docker-machine-6.4.0.tar.gz)をそのまま使うと上手く読み込めていなかった
どうも複数のバイナリが入っていていい感じに選べなかったらしい
ホストのアーキテクチャに合うバイナリだけ選んでtarで固めた物を適当な所においてhttpで参照できるようにしてそのURLをDownloadURLとして指定すると上手くいった
クラスタの作成
k8sのノードに使用するイメージもubuntu 22.04を使おうとするとdockerのインストールまでは上手くいくのにsshが途中で出来なくなってこけていた
ubuntu 20.04を使うとすんなり上手くいった
node templateの設定でtemplateを使うと上手くいかなかったのでimage id, network idを指定して設定した
最終的には以下のようになった
NodeTemplates > View API > Editで出てくる情報
(環境次第で可変になりそうなところはマスクしてます)
{"b2dSize":"","cpu":"4","devPrefix":"vd","disableVnc":false,"diskResize":"20480","imageId":"0","imageName":"","imageOwner":"oneadmin","memory":"16384","networkId":"<networkId>","networkName":"","networkOwner":"<networkOwner>","password":"<opennebulaのpassword>","sshUser":"<VMのssh可能なユーザー>","startRetries":"600","templateId":"","templateName":"","user":"<opennebulaのユーザー>","vcpu":"4","xmlrpcurl":"http://<host ip>:2633/RPC2"}
クラスタの設定
nginx-ingressはデフォルトでインストールされてしまうが、自分でいろいろ設定してまとめてインストールしたかったのでデフォルトでインストールされないようにした。
ここまででk8s側はだいたいOK
サービスのデプロイ
サービスを外部公開する為の物をデプロイ
nginx-ingress
デプロイコマンド
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm upgrade --install -f ../values/ingress-nginx/values.yaml ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.metrics.enabled=true \
--set-string controller.podAnnotations."prometheus\.io/scrape"="true" \
--set-string controller.podAnnotations."prometheus\.io/port"="10254" \
--version 4.4.0
変更点
- nginx-ingress-controllerをdaemonsetでデプロイ
- ssl-redirectの無効化
- その他nginxのパラメータの変更
- TCP,UDPで受けたいサービス用にポートの追加
- nodeSelectorでcontrolplaneにのみデプロイされるように
動作確認用のbootcampのデプロイ
動作確認用にbootcampをデプロイする
yamlは以下の通り
bootcampフォルダを作ってそこに配置する
後でapplyが楽なので
bootcamp/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: bootcamp
name: bootcamp
spec:
replicas: 2
selector:
matchLabels:
app: bootcamp
template:
metadata:
labels:
app: bootcamp
spec:
containers:
- image: gcr.io/google-samples/kubernetes-bootcamp:v1
name: bootcamp
ports:
- containerPort: 8080
dnsPolicy: ClusterFirst
restartPolicy: Always
bootcamp/service.yaml
apiVersion: v1
kind: Service
metadata:
name: bootcamp
labels:
app: bootcamp
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: bootcamp
bootcamp/ingress.yaml
cert-managerの設定とかも入ってるけどこれは今度また書く
kind: Ingress
metadata:
name: bootcamp
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/issuer: "letsencrypt"
spec:
tls:
- hosts:
- bootcamp.example.com
secretName: bootcamp-tls
rules:
- host: bootcamp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bootcamp
port:
number: 80
デプロイ
kubectl apply -f bootcamp
チェック
ingressがhostにIPの指定を許していないのでとりあえず適当に名前を割り当てておく
ちゃんとノードにリクエストが飛ぶ名前にしておけばこれでもうつながる
ただし、うちには外部接続性のない貧しい家庭なので追加の手順が必要になる
各ノードにリクエストを振り分けるnginxの設定
うちは家に外部からの接続性がないのでリクエストを受け付ける用のVMを vultr に用意している
(最近固定回線を引いたので今はもう直接受けているが最初にロードバランサーとしてnginxを置いているので結局構成は変わらない)
k8sのクラスタ外にあるそのVMでnginxを動かしてそこからVPN経由でクラスタにリクエストをプロキシしている
自分の場合は以下みたいな感じで外から接続する用のnginxが各masterノードにリクエストを振り分けてる
厳密にはVPNで繋いでいるプロキシ用のVMが宅内側にもう一台いるがやっていることは同じくVPN経由の外からのリクエストをnginxでプロキシしているだけなので省略
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
stream {
upstream http {
server 10.1.0.1:80 max_fails=10 fail_timeout=10;
server 10.1.0.2:80 max_fails=10 fail_timeout=10;
server 10.1.0.3:80 max_fails=10 fail_timeout=10;
}
server {
listen 80;
proxy_pass http;
}
upstream https {
server 10.1.0.1:443 max_fails=10 fail_timeout=10;
server 10.1.0.2:443 max_fails=10 fail_timeout=10;
server 10.1.0.3:443 max_fails=10 fail_timeout=10;
}
server {
listen 443;
proxy_pass https;
}
}
この状態で http://bootcamp.example.com
に接続すると bootcamp につながっている
リロードしてると2個あるpodにいい感じに振り分けられてるのを感じられる
力尽きたのでcert-managerの設定の話とその他諸々はまた書く