KubernetesにMetalLBをインストールして、オンプレでも「Service: LoadBalancer」を利用出来るようにする


はじめに

Kubernetesではpodへの負荷分散を行うためにAWSのEKSなどのCloudサービス上で、ServiceとしてLoadBalancerを定義することが可能です。

AWSのALB等のサービスを利用して、podへの負荷分散を行える便利なServiceリソースなのですが、オンプレミスでは利用出来ません。 これをオンプレミスで利用出来るようにするのがMetalLBです。

今回は以下のリファレンスを参照して、MetalLBをインストールしていきます。

構成

MetalLB導入前の構成

Ingress ControllerNodePortで公開する必要があり、外部からはNodePortを経由してアクセスします。

インターネット

外部Nginx

NodePort:30080

Ingress Controller

ClusterIP: A

ClusterIP: B

ClusterIP: C

アプリ1

アプリ2

アプリ3

MetalLB導入後の構成

MetalLBを導入することで、Ingress ControllerLoadBalancerタイプに変更でき、NodePortを使わずに外部からアクセス可能になります。

インターネット

外部Nginx

LoadBalancer

(MetalLB)

Ingress Controller

ClusterIP: A

ClusterIP: B

ClusterIP: C

アプリ1

アプリ2

アプリ3

インストール

MetalLBにはBGP用と、BGPを利用していない小規模NW用のインストール方法が存在します。
今回は後者を利用します。

インストール実行

本記事執筆時点ではMetalLBのバージョンは「v0.15.2」です。 以下のコマンドを実行します。

Terminal window
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml

Kustomizeを利用している場合は以下の定義を利用します。

kustomization.yml
namespace: metallb-system
# URLをhttp経由で取得するために、公式ドキュメントのgit経由からURLを変更しています。
resources:
- https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml

Helmでのインストールの場合は以下の定義を利用します。

Terminal window
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb
or
helm install metallb metallb/metallb -f values.yaml

MetalLB用のOperatorもあるようです。

今回はKustomizeを利用するため、以下のコマンドでデプロイします。

Terminal window
kubectl apply -k .

デプロイすると以下のようになります。

Terminal window
[root@k8s-bastion ~]# kubectl get all -n metallb-system
NAME READY STATUS RESTARTS AGE
pod/controller-58fdf44d87-4j2zp 1/1 Running 1 (117s ago) 2m37s
pod/speaker-4vjbx 1/1 Running 0 2m37s
pod/speaker-js6p6 1/1 Running 0 2m37s
pod/speaker-khxhd 1/1 Running 0 2m37s
pod/speaker-lkdk6 1/1 Running 0 2m37s
pod/speaker-xq59w 1/1 Running 0 2m37s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/metallb-webhook-service ClusterIP 10.108.202.241 <none> 443/TCP 2m38s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 5 5 5 5 5 kubernetes.io/os=linux 2m37s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 2m37s
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-58fdf44d87 1 1 1 2m37s

現状、利用するIPアドレスを設定していないため、 このままではLoadBalancerを定義してもIPアドレスが割り振られないため、IPアドレスを設定していきます。

利用するIPアドレスの設定

MetalLBで利用するIPアドレスの範囲を設定するために、IPAddressPoolL2Advertisementの2つのリソースを定義します。

IPAddressPool の作成

IPAddressPoolリソースでは、LoadBalancerに割り当てるIPアドレスの範囲を定義します。 単一のIP,CIDR指定等可能ですが、今回は単一のIP指定にします。

ipaddresspool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.0.50/32

L2Advertisement の作成

L2Advertisementリソースでは、L2モード(ARP)でIPアドレスをアドバタイズする設定を行います。

l2advertisement.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default-l2
namespace: metallb-system
spec:
ipAddressPools:
- default-pool # 上記で定義したIPAddressPoolの名前を指定

デプロイ

上記の2つのリソースをデプロイします。 せっかくKustomizeを利用しているので、resourcesに追加しちゃいましょう。

kustomization.yaml
namespace: metallb-system
resources:
- https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml
- ipaddresspool.yaml
- l2advertisement.yaml

Ingress ControllerをLoadBalancerタイプに変更

Ingress Controllerを事前に設定しているため、Ingress ControllerServiceLoadBalancerタイプに変更します。

これにより、外部からMetalLBが割り当てたIPアドレス経由でIngress Controllerにアクセス可能となり、portを意識する必要が無くなります。

なお、Ingress Controllerのセットアップについては以下の記事を参照してください。

Ingress ControllerをLoadBalancerに変更

Ingress ControllerはデフォルトでNodePortで公開されていますが、これをLoadBalancerに変更します。

Kustomizeを利用している場合は、以下のようにpatchで変更できます。
利用していない場合は、kubectl edit service/ingress-nginx-controller -n ingress-nginxでも修修正可能です。

kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.3/deploy/static/provider/baremetal/deploy.yaml
patches:
- target:
kind: Service
name: ingress-nginx-controller
namespace: ingress-nginx
patch: |-
- op: replace
path: /spec/type
value: LoadBalancer
Terminal window
kubectl apply -k .

デプロイ後、Ingress ControllerTypeLoadBalancerに変わり、EXTERNAL-IPが割り振られます。

Terminal window
[root@k8s-bastion ]# kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.111.186.246 192.168.0.50 80:30080/TCP,443:30443/TCP 46h

これで外部からhttp://192.168.0.50Ingress Controllerにアクセスできるようになります。

各アプリケーション(Redmine等)はClusterIPのServiceのままで、Ingressリソースで定義したホスト名(例:redmine.home.tessy.dev)でアクセス可能になります。

まとめ

オンプレミス環境では、通常LoadBalancerタイプのServiceを利用できず、NodePortを使う必要がありました。 MetalLBを導入することで、Cloud環境と同様にLoadBalancerタイプのServiceを利用できるようになり、IPアドレスのみでアクセス可能となりました。 これにより、外部サービスからportを意識する必要がなくなるため、より汎用的な設定が可能となりました。

同じカテゴリの記事