はじめに

久しぶりの個人ブログへの投稿です。

4月に転職してから会社ブログのほうに投稿する機会ができた結果、個人ブログのほうが疎かになってしまいました。 仕事でもプライベートでもやってること大体同じなんで投稿ネタがなくなるよね……。

というわけで、しばらく個人ブログのほうは自宅ラボという盆栽のお手入れ内容をメインに扱っていきます。

身の上話はここらへんにしておいて、今回は kube-vip というツールを使って、盆栽(おうち K8s クラスタ)用に構築していたロードバランサを削除した話です。

どうしてロードバランサを無くしたいの?

我が家の K8s クラスタは、Proxmox VE を使った仮想基盤上の VM で動いていました。 物理は NUC と DeskMini の2台構成です。

かつてラズパイを使った Ceph クラスタを Rook から使っていましたが、不安定極まりないためラズパイをコントロールプレーンとして転生させました。

この時点で以下のような構成でしたが、VM を使わずに K8s クラスタを作りたいという思いを捨てきれず、現在は3台目のマシンをお迎えして絶賛移行中です。

用途 種別 台数
コントロールプレーン ラズパイ 3
ワーカー VM 3
ロードバランサ VM 2

ロードバランサは kube-apiserver 用に作成したものです。 kubeadm の高可用性クラスタを作る際のドキュメントにも記載があります。 DNS に Keepalived 用の VIP を A レコードとして登録して、クラスタ外からアクセスするのに使っています。

K8s クラスタを物理だけで動かそうとしたとき、このロードバランサがネックになりました。 手持ちのラズパイ3台はすでにコントロールプレーンとして使ってますし、ワーカー用の筐体もやっと3台揃えたところです。 ロードバランサとして使える余剰筐体は我が家にはありません。

高可用性である必要があるの?と思われるかもしれませんが、それはアレですよ、“ロマン” ですよ。

というわけで、今の手持ちで物理 K8s クラスタを作るためにも、以下の要件を満たす方法を検討しました。

  • ロードバランサ用のマシンは使わない
  • 高可用性は維持する

kube-vip を使ってみる

元々ロードバランサ@VM は RHEL に Keepalived と HAProxy を入れてアクティブ/スタンバイの構成としていました。 ロードバランサを無くすに当たって、最初はコントロールプレーンに直接 Keepalived を入れようとしましたが、うまくサービスが上がってこず原因調査で時間を溶かしていました。

そんなところにフォロワーさんから kube-vip の情報をいただきました。

https://kube-vip.io/

kube-vip は、外部のハードウェアやソフトウェアに依存せずに、コントロール プレーン (高可用性クラスターを構築するため) とタイプ LoadBalancer の Kubernetes サービスの両方に仮想 IP とロード バランサーを備えた Kubernetes クラスターを提供します。

ということで、コントロールプレーンで kube-vip を動かすことでロードバランサを使わずとも高可用性を実現できそうです。 その他にも色々機能があるようなので気になったら公式を見てください。

kube-vip のデプロイ方法は Static PodsDaemonSet の2パターンあって、DaemonSet がオススメのようですが今回は簡単に入れられる Static Pods で動かします。

https://kube-vip.io/docs/installation/static/

ドキュメントには Docker をベースにしてマニフェストを動的生成するための手順が載っていたのですが、Podman を使っている環境ではうまくいかなかったので、同じくドキュメントに載っているサンプルマニフェストをいじって、コントロールプレーンに配置するマニフェストを準備しました。

サンプルから変更したのは VIP で使用するインターフェース名 vip_interface と VIP アドレス address、そして kube-vip のバージョンくらいです。

apiVersion: v1
kind: Pod
metadata:
  name: kube-vip
  namespace: kube-system
spec:
  containers:
  - args:
    - manager
    env:
    - name: vip_arp
      value: "true"
    - name: port
      value: "6443"
    - name: vip_interface
      value: eth0
    - name: vip_cidr
      value: "32"
    - name: cp_enable
      value: "true"
    - name: cp_namespace
      value: kube-system
    - name: vip_ddns
      value: "false"
    - name: svc_enable
      value: "true"
    - name: vip_leaderelection
      value: "true"
    - name: vip_leaseduration
      value: "5"
    - name: vip_renewdeadline
      value: "3"
    - name: vip_retryperiod
      value: "1"
    - name: address
      value: 192.168.2.20
    image: ghcr.io/kube-vip/kube-vip:v0.6.0
    imagePullPolicy: Always
    name: kube-vip
    resources: {}
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
        - NET_RAW
        - SYS_TIME
    volumeMounts:
    - mountPath: /etc/kubernetes/admin.conf
      name: kubeconfig
  hostAliases:
  - hostnames:
    - kubernetes
    ip: 127.0.0.1
  hostNetwork: true
  volumes:
  - hostPath:
      path: /etc/kubernetes/admin.conf
    name: kubeconfig

このマニフェストを各コントロールプレーンの /etc/kubernetes/manifests/kube-vip.yaml に配置すると、Static Pods として kube-vip が起動してきます。

NAME                               READY   STATUS      RESTARTS      AGE     IP              NODE                     NOMINATED NODE   READINESS GATES
kube-vip-kube-cp1                  1/1     Running     1             12d     192.168.2.60    kube-cp1                 <none>           <none>
kube-vip-kube-cp2                  1/1     Running     0             12d     192.168.2.73    kube-cp2                 <none>           <none>
kube-vip-kube-cp3                  1/1     Running     0             12d     192.168.2.198   kube-cp3                 <none>           <none>

kube-vip が正常に起動してきたら、コントロールプレーンのどこかで VIP が割り振られています。

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.73/24 metric 100 brd 192.168.2.255 scope global dynamic eth0
       valid_lft 55678sec preferred_lft 55678sec
    inet 192.168.2.20/32 scope global eth0                <- VIP
       valid_lft forever preferred_lft forever
    inet6 fe80::dea6:32ff:fe9a:21a2/64 scope link 
       valid_lft forever preferred_lft forever

ここまで来たら既存のロードバランサを停止しても大丈夫でした。 DNS に登録している A レコードも変えずに済みました。

さいごに

というわけで、kube-vip を使うことで盆栽(K8s クラスタ)の kube-apiserver 用ロードバランサを排除することができて、Proxmox VE で動いている VM が減って物理 K8s クラスタに一歩近づきました。

正直 kube-vip の各種機能を知ったわけではないですが、盆栽に使えそうということは分かったので一旦ここまでにしておきます。