26 Kubernetes APIサーバの前面のMetalLB #
このガイドでは、MetalLBサービスを使用して、3つのコントロールプレーンノードを持つHAクラスタ上でRKE2/K3s
APIを外部に公開する方法を示します。これを実現するために、LoadBalancer
タイプのKubernetes
ServiceとEndpointsを手動で作成します。Endpointsは、クラスタで使用可能なすべてのコントロールプレーンノードのIPを保持します。Endpointsをクラスタで発生するイベント(ノードの追加/削除やノードのオフライン化)と継続的に同期するためにEndpoint
Copier Operator (第20章 「Endpoint Copier Operator」)がデプロイされます。Operatorはデフォルトのkubernetes
Endpointで発生するイベントを監視し、管理対象を自動的に更新して同期を維持します。管理対象のServiceはLoadBalancer
タイプであるため、MetalLBは静的なExternalIP
を割り当てます。このExternalIP
はAPI
Serverとの通信に使用されます。
26.1 前提条件 #
RKE2/K3sをデプロイするための3つのホスト。
ホスト名は各ホストで違う名前にしてください。
テストの場合は仮想マシンを使用できます。
ネットワーク内で2つ以上のIPが使用可能(Traefik/Nginx用に1つ、管理対象サービス用に1つ)。
Helm
26.2 RKE2/K3sのインストール #
新しいクラスタを使用せず、既存のクラスタを使用する場合は、この手順をスキップして次の手順に進んでください。
まず、ネットワーク内の空きIPを、後で管理対象のServiceのExternalIP
で使用できるように予約する必要があります。
最初のホストにSSHで接続して、クラスタモードで必要なディストリビューションをインストールします。
RKE2の場合:
# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
curl -sfL https://get.rke2.io | INSTALL_RKE2_EXEC="server \
--write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
--tls-san=https://${VIP_SERVICE_IP}.sslip.io" sh -
systemctl enable rke2-server.service
systemctl start rke2-server.service
# Fetch the cluster token:
RKE2_TOKEN=$(tr -d '\n' < /var/lib/rancher/rke2/server/node-token)
K3sの場合:
# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init \
--disable=servicelb --write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
--tls-san=https://${VIP_SERVICE_IP}.sslip.io" K3S_TOKEN=foobar sh -
必ず、k3s
server
コマンドで--disable=servicelb
フラグを指定してください。
これ以降、コマンドはローカルマシンで実行する必要があります。
APIサーバに外部からアクセスするには、RKE2/K3s VMのIPを使用します。
# Replace <node-ip> with the actual IP of the machine
export NODE_IP=<node-ip>
export KUBE_DISTRIBUTION=<k3s/rke2>
scp ${NODE_IP}:/etc/rancher/${KUBE_DISTRIBUTION}/${KUBE_DISTRIBUTION}.yaml ~/.kube/config && sed \
-i '' "s/127.0.0.1/${NODE_IP}/g" ~/.kube/config && chmod 600 ~/.kube/config
26.3 既存のクラスタの設定 #
この手順は、既存のRKE2/K3sクラスタを使用する 場合にのみ有効です。
既存のクラスタを使用するには、tls-san
フラグを修正する必要があります。また、K3sではservicelb
LBを無効にする必要があります。
RKE2またはK3sサーバのフラグを変更するには、ディストリビューションに応じて、クラスタのすべてのVM上で/etc/systemd/system/rke2.service
または/etc/systemd/system/k3s.service
ファイルを変更する必要があります。
フラグはExecStart
に挿入する必要があります。例:
RKE2の場合:
# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/rke2 \
server \
'--write-kubeconfig-mode=644' \
'--tls-san=<vip-service-ip>' \
'--tls-san=https://<vip-service-ip>.sslip.io' \
K3sの場合:
# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/k3s \
server \
'--cluster-init' \
'--write-kubeconfig-mode=644' \
'--disable=servicelb' \
'--tls-san=<vip-service-ip>' \
'--tls-san=https://<vip-service-ip>.sslip.io' \
次に、次のコマンドを実行して、新しい設定をロードする必要があります。
systemctl daemon-reload
systemctl restart ${KUBE_DISTRIBUTION}
26.4 MetalLBのインストール #
MetalLB
をデプロイするには、K3s上のMetalLB (第25章 「K3s上のMetalLB (レイヤ2モードを使用)」)のガイドを使用できます。
メモ: ip-pool
IPAddressPoolのIPアドレスが、以前にLoadBalancer
サービスに対して選択したIPアドレスと重複していないことを確認してください。
管理対象サービスにのみ使用するIpAddressPool
を別途作成します。
# Export the VIP_SERVICE_IP on the local machine
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- ${VIP_SERVICE_IP}/32
serviceAllocation:
priority: 100
namespaces:
- default
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- ip-pool
- kubernetes-vip-ip-pool
EOF
26.5 Endpoint Copier Operatorのインストール #
helm install \
endpoint-copier-operator oci://registry.suse.com/edge/charts/endpoint-copier-operator \
--namespace endpoint-copier-operator \
--create-namespace
上記のコマンドは2つのレプリカを持つendpoint-copier-operator
オペレータのデプロイメントをデプロイします。一方がリーダーとなり、他方は必要に応じてリーダーの役割を引き継ぎます。
これで、kubernetes-vip
サービスがデプロイされ、オペレータによって調整され、設定されたポートとIPを持つエンドポイントが作成されるはずです。
RKE2の場合:
cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
spec:
ports:
- name: rke2-api
port: 9345
protocol: TCP
targetPort: 9345
- name: k8s-api
port: 6443
protocol: TCP
targetPort: 6443
type: LoadBalancer
EOF
K3sの場合:
cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
spec:
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: https
port: 6443
protocol: TCP
targetPort: 6443
sessionAffinity: None
type: LoadBalancer
EOF
kubernetes-vip
サービスのIPアドレスが正しいことを確認します。
kubectl get service kubernetes-vip -n default \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}'
default
ネームスペースのkubernetes-vip
およびkubernetes
のEndpointsリソースが同じIPを指していることを確認します。
kubectl get endpoints kubernetes kubernetes-vip
すべて問題なければ、最後にKubeconfig
でVIP_SERVICE_IP
を使用します。
sed -i '' "s/${NODE_IP}/${VIP_SERVICE_IP}/g" ~/.kube/config
これ以降、kubectl
はすべてkubernetes-vip
サービスを経由するようになります。
26.6 コントロールプレーンノードの追加 #
プロセス全体を監視するため、端末タブを2つ以上開くことができます。
最初の端末:
watch kubectl get nodes
2つ目の端末:
watch kubectl get endpoints
次に、以下のコマンドを2つ目のノードと3つ目のノードで実行します。
RKE2の場合:
# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="server" sh -
systemctl enable rke2-server.service
mkdir -p /etc/rancher/rke2/
cat <<EOF > /etc/rancher/rke2/config.yaml
server: https://${VIP_SERVICE_IP}:9345
token: ${RKE2_TOKEN}
EOF
systemctl start rke2-server.service
K3sの場合:
# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
--server https://${VIP_SERVICE_IP}:6443 --disable=servicelb \
--write-kubeconfig-mode=644" K3S_TOKEN=foobar sh -