コンテンツにスキップ
最終更新日: 2020年9月21日

RouterOSでk8sロードバランサー

GKEやAKS、EKS等のクラウドプロバイダのKubernetesクラスター上で L4ロードバランサーを使用する場合、Kubernetes ServiceのタイプをLoadBalancerに設定すると クラウドプロバイダが提供するGoogle Cloud Load Balancerや、Azure Load Balancerなどの 外部ロードバランサーサービスと連携して、負荷分散と可用性向上をしてくれます。

しかし、クラウドプロバイダではない、自身で構築したKubernetesクラスタでロードバランシングしたい場合は、 外部連携するロードバランサーを用意する必要があります。

今回は、RouterOSとMetalLBを使用して、 ベアメタルKubernetesクラスターでロードバランサーを利用できるようにします。

MetalLB

MetalLB1 は、ベアメタル環境のKubernetesでLoadBalancerタイプのServiceを使用するための実装です。 BGPまたは、ARPやNDPなどの標準的なプロトコルを使用して、Kubernetes上でロードバランサー機能を提供することができます。

KubernetesのService

MetalLBをインストールする前に、KubernetesのServiceについて説明します。 今すぐMetalLBを使用したい方は、MetalLBのインストールまで読み飛ばしてください。

Kubernetesでアプリケーションを外部へ公開する場合には、Serviceというものを利用します。

Serviceにはいくつかのタイプがあり、外部からKubernetesクラスター内部へのアクセスを提供するには NodePortタイプもしくは、LoadBalancerタイプのServiceを使用します。2

NodePortタイプのServiceでは、アプリケーションのPodが動作しているノードのIPアドレスにTCP/UDPポートが割り当てられます。
複数のノードが存在する場合にどのノードへ割り当てられるかは、デプロイされるまで分かりません。 もし、NodePortタイプのServiceで公開する場合には、以下のような構成にする必要があります。

  • シングルノードで構成する
  • デプロイするノードを事前に割り当てておく
  • 動的にDNSやDestination NATを設定する仕組みを用意する

そのため、マルチノードで高可用性の構成にしたい場合は、あまり現実的でない選択肢になります。

もう一方のLoadBalancerタイプのServiceでは、Kubernetesクラスターの外部にあるロードバランサーが必要になります。 通常、クラウドプロバイダーが提供でするロードバランサー機能と連携して、アプリケーションへのアクセスを提供します。

もし、マルチノード環境かつ、クラウドではなくベアメタル環境で、 アプリケーションを外部へ公開するには、LoadBalancerタイプのServiceと連携する 外部ロードバランサーにあたる機能を自身で用意する必要があります。

そこで、MetalLBは標準的なBGPルーティングやARP/NDPといったLayer2プロトコルを利用して、 市販のルーターと連携し、一般的なベアメタル環境でのロードバランシングを実現をします。

MetalLBのインストール

MetalLB 公式サイトのManifestからのインストール方法に従って インストールします。

MetalLBのインストール

METALLB_VERSION="v0.9.3"
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/${METALLB_VERSION}/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/${METALLB_VERSION}/manifests/metallb.yaml
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

続いて、BGPで対向ルータの 192.168.5.1 と通信するよう設定を追加します。 MetalLBのAS番号は65001、対向ルータのAS番号は65000のプライベートAS番号を設定しています。

metallb/config-map.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    peers:
    - peer-address: 192.168.5.1
      peer-asn: 65000
      my-asn: 65001
    address-pools:
    - name: default
      protocol: bgp
      avoid-buggy-ips: true
      addresses:
      - 192.168.128.0/24

上記の設定後、しばらくするとMetalLBに設定したレンジのIPアドレスが、Ingressなどに表示されるようになります。
ここでは、すでに作成済みのアプリケーションが2つのIPアドレスに、 192.168.128.1 が表示されています。

IngressへのIPアドレス割り当て確認

> kubectl get ingress
NAME           CLASS    HOSTS                         ADDRESS         PORTS     AGE
api-ingress    <none>   api.roy-n-roy.test            192.168.128.1   80, 443   26d
web-ingress    <none>   www.roy-n-roy.test            192.168.128.1   80, 443   26d

RouterOSでのBGP設定

今度はRouterOS側で、各Kubernetesノードと通信するための設定を追加します。 対向のノードは4台で、192.168.5.250~254としています。

BGP設定

/routing bgp instance
add name=private as=65000 router-id=192.168.5.1
/routing bgp peer
add multihop=yes name=kube-metallb-worker1 remote-address=192.168.5.253 \
    remote-as=65001 ttl=private
add multihop=yes name=kube-metallb-worker2 remote-address=192.168.5.252 \
    remote-as=65001 ttl=private
add multihop=yes name=kube-metallb-worker3 remote-address=192.168.5.251 \
    remote-as=65001 ttl=private
add multihop=yes name=kube-metallb-worker4 remote-address=192.168.5.250 \
    remote-as=65001 ttl=private

正常に設定されると、動的ルーティングが確認できるようになります。

BGP ルーティング確認

# BGP広告の表示
/routing bgp advertisements print
PEER     PREFIX               NEXTHOP          AS-PATH                          ORIGIN     LOCAL-PREF
kube-... 192.168.128.1/32     192.168.5.1      65001                            incomplete
kube-... 192.168.128.1/32     192.168.5.1      65001                            incomplete
kube-... 192.168.128.1/32     192.168.5.1      65001                            incomplete

# ルーティングテーブルを表示
# Kubernetes上のIngressのClusterIP(192.168.128.1/32)への動的ルーティングとして
# 192.168.5.251と.253がDynamicで表示され、.251がActiveになっている。
/ip route print  
Flags: X - disabled, A - active, D - dynamic, 
C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme, 
B - blackhole, U - unreachable, P - prohibit 
#      DST-ADDRESS        PREF-SRC        GATEWAY            DISTANCE
0 ADS  0.0.0.0/0                          pppoe-out1                1
  ・・・
4 ADb  192.168.128.1/32                   192.168.5.251            20
5  Db  192.168.128.1/32                   192.168.5.253            20

この段階で、確認のためにhostsなどへ名前解決を登録して ブラウザからアクセスすると、Ingressで設定したサービスが表示されます。

以下の例では、2つのURLに 192.168.128.1 を設定しています。

/etc/hosts もしくは C:\Windows\System32\drivers\etc\hosts

192.168.128.1       api.roy-n-roy.test
192.168.128.1       www.roy-n-roy.test

RouterOSにリバースNATを設定

最後に、外部へのアクセスにNATを使用している場合は、アプリケーションをインターネットに公開するために HTTP(S)アクセスをKubernetes IngressサービスのIPアドレスへ転送する設定をします。

リバースNAT設定

# ether1のPort 80,443(HTTP(S))アクセスを192.168.128.1へ転送
/ip firewall nat add action=dst-nat chain=dstnat in-interface=ether1 protocol=tcp port=80 to-addresses=192.168.128.1
/ip firewall nat add action=dst-nat chain=dstnat in-interface=ether1 protocol=tcp port=443 to-addresses=192.168.128.1