rancher で k8sクラスタをおうちに用意する - 令和最新版(2023/06)のカバー画像
rancher で k8sクラスタをおうちに用意する - 令和最新版(2023/06)
2024/7/24
このエントリーをはてなブックマークに追加

このたびおうちのクラスタを作り直したので記録しておきます。

kubespray や ansible で頑張っていましたが、力尽きてしまったのでもっと良い感じになうでやんぐな若者がやってるやり方を調べて実践しました。(当社調べ)

今回は rancher を使ってクラスタを作っていきます。
rancher は k8s クラスタの管理をしてくれるもので、マルチプラットフォームに対応しており、gke や eks その他クラウドベンダーの k8s クラスタをまとめて管理できるものです。
本来は組織的に管理しているものを管理しやすくするためのものですが、 rancher ではオンプレ環境でのクラスタの作成も行える為、おうちのクラスタの作成・管理を目的として使用しています。

その為、この記事では作成することを目的とした内容になっています。
自分がクラスタ作って任意のリソースをクラスタ上に作成できるようになるまでの備忘録のようなものです。
ググってすぐ出てきたようなものはすっ飛ばして躓いた部分を書いています。

これまでの構成

k8s,インフラ的な部分とソフトウェア的な部分の境界がわかりにくくて色んなレイヤーの話が混ざってしまい、構成図書くの難しい。
何か標準的なものがあるのかな。ありそう。

新バージョン(KVM/QEMU + Opennebula + Rancher + nginx-ingress)

new arch

この構成にしてよくなったところ

  • rancherでk8sクラスタを立ち上げるようにしたことでそもそもterraformが不要になった
  • ノードの増減がGUIでポチポチで良くなった
  • ノードが落ちてしまった時rancherが勝手に新しいノードを作成して割り当ててくれる

手順

以下の物をインストールしていった

  • KVM/QEMU
  • Opennebula
  • Rancher
  • nginx-ingress-controller

KVM/QEMU

opennebulaがubuntu 22.04だと上手く動かなかったので一度20.04をインストールし直す必要があったくらい
備忘録も兼ねているので一応参考リンクを貼っておく

https://ubuntu.com/blog/kvm-hyphervisor">https://ubuntu.com/blog/kvm-hyphervisor

Opennebula

本家のドキュメントを見ながらインストールした
minioneを使ってポンって最初やっていたがやってくうちによくわからんくなったので順に手動でインストールした

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

物理マシンは1台なのでfrontendと本体?も一緒にインストールした

ケチ臭い人間なのでrancherを動かす用のVMを動かすのも嫌だったのでホスト上で直接docker動かしてrancherを動かしている。

rancher

このあたりから結構躓いた
基本は以下のドキュメントを見ながらインストールした
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

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はデフォルトでインストールされてしまうが、自分でいろいろ設定してまとめてインストールしたかったのでデフォルトでインストールされないようにした。
disable-nginx-ingress.png

ここまでで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

values.yaml
https://github.com/Im-neko/helm-charts/blob/main/charts/ingress-nginx/values.yamlhttps://github.com/Im-neko/helm-charts/blob/main/charts/ingress-nginx/values.yaml

変更点
  • 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: &quot;letsencrypt&quot;
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にいい感じに振り分けられてるのを感じられる
bootcamp response
力尽きたのでcert-managerの設定の話とその他諸々はまた書く

rancher で k8sクラスタをおうちに用意する - 令和最新版(2023/06) - ねこの部屋