LoginSignup
0
2

More than 1 year has passed since last update.

MicroK8s+MetalLBでロードバランサの動きを理解する

Last updated at Posted at 2021-03-30

まえがき

前回の記事で作成した3ノードのK8sクラスタをより実運用に向けとするため、 MetalLB を導入し、負荷分散と外部アクセス環境の構築を行う
構築の手順、構築してみて解ったことなどをまとめる

MetalLBには Layer 2 modeBGP mode の2つのモードがあるが、 BGP mode で構築を行う
※BGP mode を使用するには、上流にBGPを喋れるルータが必要

何番煎じかはわからないが、MetalLB, BGP の仕組みも交えて解説をする

IMG_5029.jpeg

検証に使用する3台の物理マシン(白いタワーPC)

MetalLB (BGP mode) の仕組み

1. 前提条件 - 構成

前回クラスタ構築完了時点では、K8sノードはClientと同じセグメントに属していたが、新たにVLANを切り、別のネットワークセグメントへと切り出し、図の構成となった

bgp-nexthop-構成.png

2. 経路情報の広告

MetalLB (BGP mode) では、BGP (Border Gateway Protocol) を使用して、metallb:controller が払い出す ExternalIP セグメントを metallb:speaker が BGP Router へ広告することで動的なルーティングを実現するミドルウェアである
BGPをルーティングに使用することで特別な機器を必要とせず、L3のみでロードバランサのような振る舞いをさせることができる

経路広告の流れは以下の通りである

  1. controller が Service へ ExternalIP の払い出しを行う
  2. controller が speaker へ 払い出しを通知
  3. speaker が 上流の BGP Router へ 経路情報を広告

bgp-nexthop-bgp.png

3. next hop による負荷分散

経路情報が広告され、ExternalIP への接続要求があるとルータは BGP table (next hop) に記載されたノードへパケットを通す
論理的には青い点線で描かれた、 ipvs へとセッションが張られる
ipvs は自ノードもしくは他ノードで Listen している pod へパケットを転送する

2段構えのロードバランサとなっているが、この仕組みがあることで、 ノードレベルでの負荷分散とノードと BGP 間の経路情報を単純化している
ルータは next hup に指定された対向へパケットを通すだけなので、接続を受けたノードに pod が居ない可能性は十分に考えられる。そこで、 ipvs が接続を受け、クラスタ内の適切な pod へパケットを転送することで、pod レベルの負荷分散と障害耐性を実現する

クライアントからの通信の流れは以下の通りである

  1. クライアントが service (172.16.x.x) へ接続要求
  2. BGP ルータが next hop に指示されたIPノードへパケットを通す
  3. ipvs がセッションを受け、いずれかのノードで動く pod へ転送
  4. 元の経路をたどり、 pod がクライアントへ接続を返す

bgp-nexthop-next hop.png

MetalLB 導入

MicroK8sの場合、 いずれかのノードで add-on を有効にするだけで使用可能な状態となる

$ sudo microk8s.enable metallb

設定を行う

ルータ側設定

ルータには Sophos XG Firewall を使用している
VyOS を使用した構築例1や EdgerouterX を使用した構築例2 なども参考とした

ルータID にルータのIPアドレス、ローカルAS には 64512 - 65534 3 から採番し入力 64512 とした。
ネイバーには対向(ノード)のIPアドレスとルータ同様、AS番号の採番を行うが ルータから1インクリメントした 64513 とした。

K8s側設定

MetalLB 公式ドキュメントの例をベースに、設定ファイルを作成した。

最小構成としては、以下の内容で機能する

metallb-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    peers:
    - peer-address: 10.227.0.1
      peer-asn: 64512
      my-asn: 64513
    address-pools:
    - name: default
      protocol: bgp
      addresses:
      - 172.16.192.0/20

適用は kubectl apply で行う

$ kubectl apply -f metallb-config.yaml

yaml の内容について

  • data.config.peers.peer-address は 対向(上流ルータ)のIPアドレス
  • data.config.peers.peer-asn は 対向(上流ルータ)のAS番号
  • data.config.peers.my-asn は 自分(ノード)に割り当てるAS番号
  • data.config.address-pools.protocol は ロードバランシングに使用するプロトコル "layer2" または "bgp" を指定
  • data.config.address-pools.address は service に割り当てる IPアドレスのプール範囲指定

動作確認

BGP セッションの確認

XG Firewall に限らず、ルータにはBGPの状態確認ができるコマンドがある
設定が正常に完了すると以下のような出力がされる

BGP router identifier 10.227.0.1, local AS number 64512
RIB entries 7, using 448 bytes of memory
Peers 3, using 7452 bytes of memory

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
192.168.11.11   4 64513    7352    7365        0    0    0 2d13h04m        3
192.168.11.12   4 64513    6145    6174        0    0    0 16:34:39        3
192.168.11.13   4 64513    7352    7368        0    0    0 2d13h04m        3

Total number of neighbors 3

Up/DownneverdownMsgRcvd, MsgSent0 となっている場合は、BGPセッションに失敗している
AS番号やIPアドレスの確認、ゾーンポリシーやファイアウォールなどの確認を行う

小生もルータ側のゾーンポリシー設定で、 dynamic routing を Allow にしておらず小一時間ハマった。
(ノード側のサブネットも間違っていた…)

確認用サービス (nginx) を立ち上げる

唐突だが、metallb:speaker の経路広告がルータの BGP Table に反映されるか、Clientからの疎通確認を行うために、nginx のサービスを立ち上げる

nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

spec.replicas は適宜書き換える

適用は kubectl apply で行う

$ kubectl apply -f nginx.yaml

service と pods の状態は以下のコマンドで確認できる

$ kubectl get svc,po

NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
service/kubernetes      ClusterIP      10.152.183.1     <none>         443/TCP        3d13h
service/nginx           LoadBalancer   10.152.183.53    172.16.192.1   80:31778/TCP   3d11h

NAME                        READY   STATUS    RESTARTS   AGE
pod/nginx-8c9df995d-j7w8t   1/1     Running   4          3d11h
pod/nginx-8c9df995d-d9djn   1/1     Running   4          3d11h
pod/nginx-8c9df995d-fwvbd   1/1     Running   6          3d11h

ExternalIP には 172.16.192.1 が割り当てられ、80/tcp で Listen している
pods も replicas に設定した3つが立ち上がっている

BGP table (next hop) の確認

service/nginx に ExternalIP が割り当てられる頃には、ルータのBGPテーブルに経路情報が反映されているはず
ルータによって確認方法や出力は異なるが、 172.16.192.1/32 に対し、Next Hop が割り当てられていることが確認できる

kubectl get svc で ExternalIP が割り当てられているにも関わらず、BGPテーブルへの反映が行われていない場合は、speaker pod の状態確認や、そもそも BGP セッション がコケている可能性が高いので確認して欲しい

BGP table version is 0, local router ID is 10.227.0.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.227.0.0/20    0.0.0.0                  0         32768 i
*  172.16.192.1/32  192.168.11.12                          0 64513 ?
*                   192.168.11.11                          0 64513 ?
*>                  192.168.11.13                          0 64513 ?

Total number of prefixes 4

クライアントからの疎通確認

ブラウザから http://172.16.192.1/へアクセスして、おなじみの Welcome to nginx! が表示されれば動作確認は完了となる

image.png

アクセスできない場合は、ルータ, ノードへ ping が通るかを確認し、 traceroute で経路を追ってどこに原因があるかを探ると良い

まとめ

目的と手段が入れ替わっていそうな気がするが、ロードバランサが利用可能となり Kubernetes を使用した Homebridge の実運用へ一歩前進した。BGP とはなんぞや状態だったが、実際に構築して触れてみることで概要だけでも理解することが出来た。
次回は、PersistentVolume の構築を予定しているが、NFSマウントするだけな気もするので、Ceph を使用した、分散ストレージ環境の構築と合わせて記事を公開する予定(予定)

その頃には脱ESXiと脱XG Firewall計画が進んでるはず。

ちゃんと理解している方が読むと、ちゃんと理解していないのがバレそうな記事だが、お気づきの点があればコメントで指摘お願いします。
(開発エンジニアなので細かい部分は目を瞑って欲しい…。)

参考資料

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2