前回の記事では、KubesprayによるKubernetesのインストールを行いました。今回は、MetalLBを使ったロードバランサーのインストールを試してみました。
構成
- vCenter 7.0 U3
- ESXi 7.0 Update 3
- Ubuntu 22.04 (テンプレートVM)
- open-vm-tools 11.3.5
- cloud-init 22.2
- Kubespray
- kubernetes v1.25.5
- MetalLB v0.12.1
MetalLBのインストール
KubesprayでMetalLBのインストールを行うことが可能なため、inventoryのgroup_varsに設定を入れていきます。
L2モードでの動作を行うため、以下のようにARPの設定を有効にします。
$ vi k8s-cluster.yml # configure arp_ignore and arp_announce to avoid answering ARP queries from kube-ipvs0 interface # must be set to true for MetalLB, kube-vip(ARP enabled) to work kube_proxy_strict_arp: true
以下のように、MetalLBを有効にし、MetalLBから払い出すIPアドレス帯を指定します。
$ vi addons.yml # MetalLB deployment metallb_enabled: true metallb_speaker_enabled: "{{ metallb_enabled }}" metallb_ip_range: - "10.0.50.201-10.0.50.254" # metallb_pool_name: "loadbalanced" # metallb_auto_assign: true metallb_avoid_buggy_ips: true
クラスタ作成
masterノードとworkerノードを再作成し、前回と同様に、クラスタを構築します。
$ ansible-playbook -i inventory/mycluster/hosts.yml --become --become-user=root cluster.yml
MetalLBがインストールされているか確認します。
$ kubectl get all -n metallb-system NAME READY STATUS RESTARTS AGE pod/controller-5ffbbd5949-pmxf9 1/1 Running 0 2d14h pod/speaker-4d4v8 1/1 Running 0 2d14h pod/speaker-9f9lh 1/1 Running 0 2d14h pod/speaker-h8c97 1/1 Running 0 2d14h pod/speaker-jxwgm 1/1 Running 0 2d14h pod/speaker-xdbml 1/1 Running 0 2d14h NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/speaker 5 5 5 5 5 kubernetes.io/os=linux 2d14h NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/controller 1/1 1 1 2d14h NAME DESIRED CURRENT READY AGE replicaset.apps/controller-5ffbbd5949 1 1 1 2d14h
MetalLBの動作確認
以下のように、nginxをデプロイします。
$ kubectl create deployment nginx --image=nginx
デプロイ後の状態は以下の通りです。
$ kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/nginx-76d6c9b8c-4cqrc 1/1 Running 0 17s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 4h15
デプロイしたnginxをserviceとして公開します。この時、 typeにLoadBalancerを指定します。
$ kubectl expose deployment nginx --port 80 --type LoadBalancer
nginxがLoadBalancerで公開され、EXTERNAL-IPにMetalLBで設定したIPアドレスが付与されていることが分かります。
$ kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/nginx-76d6c9b8c-4cqrc 1/1 Running 0 43s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 4h16m service/nginx LoadBalancer 10.233.51.192 10.0.50.201 80:31592/TCP 2s
nginxに対してEXTERNAL-IPでアクセスできるか確認します。
$ INGRESS_EXTERNAL_IP=`kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}'` $ curl $INGRESS_EXTERNAL_IP <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
MetalLBのL2モード(ARP)の動作
MetalLB には、ControllerとSpeakerの 2 つのコンポーネントが含まれています。Controllerはmasterノードにデプロイされ、SpeakerはDaemonsetモードでworkerノードの各ノードにデプロイされます。
Controllerは、事前に定義したIPプールからIPアドレスの割り当てを管理し、Speakerは、選択したモード(L2モード(ARP/NDP)、BGP)に従ってPodへの通信ができるようにします。
今回利用したL2モード(ARP)では、1 つのノードがサービスをローカル ネットワークに通知する役割を担います。ノードを確認すると、ネットワーク インターフェイスに複数の IP アドレスが割り当てられているように見えます。
ARP要求が来た場合、SpeakerがARPのリプライを返します。
また、サービス IP のすべてのトラフィックが 1 つのノードに送信されます。そこから kube-proxyを経由してトラフィックをすべてのサービスのポッドに分散します。
EXTERNAL-IPに対して、arpingを実行します。
$ sudo arping -I ens192 10.0.50.201
ARP応答を行うノードについて以下のコマンドで確認します。
$ kubectl describe service nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal IPAllocated 37m metallb-controller Assigned IP ["10.0.50.201"] Normal nodeAssigned 33m (x2 over 37m) metallb-speaker announcing from node "kube-worker01"
ARP応答を行うノードで、tcpdumpを行い、ARP要求とARP応答が行われていることを確認します。
$ sudo tcpdump -n -i ens192 arp tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on ens192, link-type EN10MB (Ethernet), snapshot length 262144 bytes 22:33:19.405011 ARP, Request who-has 10.0.50.201 tell 10.0.50.163, length 46 22:33:19.405155 ARP, Reply 10.0.50.201 is-at 00:50:56:88:f9:61, length 46 22:33:20.406228 ARP, Request who-has 10.0.50.201 tell 10.0.50.163, length 46 22:33:20.406378 ARP, Reply 10.0.50.201 is-at 00:50:56:88:f9:61, length 46 22:33:21.406975 ARP, Request who-has 10.0.50.201 tell 10.0.50.163, length 46 22:33:21.407122 ARP, Reply 10.0.50.201 is-at 00:50:56:88:f9:61, length 46
リソースの削除
動作確認ができたので、リソースを削除しておきます。
kubectl delete deployment nginx kubectl delete svc nginx