SUPER-G.EEK.JP

twitter: @hum_op_dev
github: ophum

さくらのクラウドのLBアプライアンスでk8sのingress controllerの負荷分散をする

目次

さくらのクラウドの LB アプライアンスを使って k8s の ingress controller の負荷分散を行います。

さくらのクラウドの LB アプライアンスは DSR の LB なので、VIP のポートと実サーバーのポートは同一である必要があります。 k8s では Pod の公開を行う際、大抵 Type が LoadBalancer や NodePort な Service リソースを作成し公開を行います。 Type LoadBalancer が利用できない(から LB アプライアンスを利用する)ので NodePort が選択肢に上がりますが、NodePort はデフォルトで 30000~32767 に割り当てられます。 LB アプライアンスの仕様上 80 か 443 にしたいですが、NodePort ではできません。

そこで、今回は hostPort を利用して公開することにします。 hostPort を利用することで、Pod をホストのIP:portで公開できるようになります。 Pod をホストのIP:portで公開するため、Pod が存在しないノードの hostPort にアクセスしても Pod にはアクセス出来ないということに注意が必要です。 今回は、LB アプライアンスのヘルスチェックで Pod が存在するノードだけで負荷分散するようにし、Deployment でデプロイするパターンと DaemonSet でデプロイするパターンを試してみます。

構成

作業ログ

k8s のデプロイ

以下のディレクトリで作業を行います。 ophum/kubenetes-practice-lab: ansible/

1ansible-playbook -i 02-hosts --become -u ubuntu kubespray/cluster.yml

以降 control-plane で作業を行います。 control-plane と各 node が Ready になっていることを確認します。

1root@control-plane-01:~# kubectl get node
2NAME                                          STATUS   ROLES           AGE     VERSION
3control-plane-01.test02.cloud.t-inagaki.net   Ready    control-plane   9m42s   v1.29.2
4node-01.test02.cloud.t-inagaki.net            Ready    <none>          8m55s   v1.29.2
5node-02.test02.cloud.t-inagaki.net            Ready    <none>          8m56s   v1.29.2
6node-03.test02.cloud.t-inagaki.net            Ready    <none>          8m56s   v1.29.2

helm をインストールします。

参考: https://helm.sh/ja/docs/intro/install/

1curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
2sudo apt-get install apt-transport-https --yes
3echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
4sudo apt-get update
5sudo apt-get install helm

helm で ingress-nginx をインストールします。

 1# helm upgrade --install ingress-nginx ingress-nginx \
 2  --repo https://kubernetes.github.io/ingress-nginx \
 3  --namespace ingress-nginx --create-namespace \
 4  --set controller.hostPort.enabled="true"
 5Release "ingress-nginx" does not exist. Installing it now.
 6NAME: ingress-nginx
 7LAST DEPLOYED: Fri Mar 15 17:15:19 2024
 8NAMESPACE: ingress-nginx
 9STATUS: deployed
10REVISION: 1
11TEST SUITE: None
12NOTES:
13The ingress-nginx controller has been installed.
14It may take a few minutes for the load balancer IP to be available.
15You can watch the status by running 'kubectl get service --namespace ingress-nginx ingress-nginx-controller --output wide --watch'

controller が動作していることを確認します。 node-03 で動作していることがわかります。

1# kubectl get pods -n ingress-nginx -o wide
2NAME                                        READY   STATUS    RESTARTS   AGE     IP               NODE                                 NOMINATED NODE   READINESS GATES
3ingress-nginx-controller-6647957864-dgdn4   1/1     Running   0          2m46s   10.233.118.130   node-03.test02.cloud.t-inagaki.net   <none>           <none>

curl で ingress-controller にアクセスできることを確認します。

1# curl node-03.test02.cloud.t-inagaki.net
2<html>
3<head><title>404 Not Found</title></head>
4<body>
5<center><h1>404 Not Found</h1></center>
6<hr><center>nginx</center>
7</body>
8</html>

この時点での LB アプライアンスの実サーバーのステータスはこのようになります。

手元から VIP に curl してアクセスできることを確認します。

1$ curl app.test02.cloud.t-inagaki.net
2<html>
3<head><title>404 Not Found</title></head>
4<body>
5<center><h1>404 Not Found</h1></center>
6<hr><center>nginx</center>
7</body>
8</html>

今の状態では、ingress-controller が稼働しているのが node-03 の 1Pod だけになっているので、すべてのノードで Pod を動かして負荷分散できるようにします。

デフォルト設定では ingress-controller は Deployment でデプロイされます。 これを Daemonset にすることで各ノードで動かすことができます。

 1# helm upgrade --install ingress-nginx ingress-nginx \
 2  --repo https://kubernetes.github.io/ingress-nginx \
 3  --namespace ingress-nginx \
 4  --set controller.hostPort.enabled="true" \
 5  --set controller.kind="DaemonSet"
 6Release "ingress-nginx" has been upgraded. Happy Helming!
 7NAME: ingress-nginx
 8LAST DEPLOYED: Fri Mar 15 17:26:18 2024
 9NAMESPACE: ingress-nginx
10STATUS: deployed
11REVISION: 2
12TEST SUITE: None
13NOTES:
14The ingress-nginx controller has been installed.
15It may take a few minutes for the load balancer IP to be available.
16You can watch the status by running 'kubectl get service --namespace ingress-nginx ingress-nginx-controller --output wide --watch'

各ノードで Pod が動作していることが確認できました。

1# kubectl get pods -n ingress-nginx -o wide
2NAME                             READY   STATUS    RESTARTS   AGE   IP               NODE                                 NOMINATED NODE   READINESS GATES
3ingress-nginx-controller-tmq6q   1/1     Running   0          22s   10.233.82.131    node-01.test02.cloud.t-inagaki.net   <none>           <none>
4ingress-nginx-controller-vzw2l   1/1     Running   0          22s   10.233.118.132   node-03.test02.cloud.t-inagaki.net   <none>           <none>
5ingress-nginx-controller-zlt8b   1/1     Running   0          22s   10.233.103.3     node-02.test02.cloud.t-inagaki.net   <none>           <none>

LB アプライアンスの実サーバーの状態は以下のようになりました。

Web アプリを動かして ingress でアクセスしてみる

Ingress リソースでアクセスできることを確認してみます。 今回は GitBucket を動かしてみます。

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: gitbucket
 5  namespace: default
 6  labels:
 7    app: gitbucket
 8spec:
 9  replicas: 1
10  selector:
11    matchLabels:
12      app: gitbucket
13  template:
14    metadata:
15      labels:
16        app: gitbucket
17    spec:
18      containers:
19        - name: gitbucket
20          image: ghcr.io/gitbucket/gitbucket
21          command:
22            - sh
23            - -c
24            - java -jar /opt/gitbucket.war --port=8080
25          ports:
26            - name: http
27              containerPort: 8080
28              protocol: TCP
29---
30apiVersion: v1
31kind: Service
32metadata:
33  name: gitbucket
34  namespace: default
35  labels:
36    app: gitbucket
37spec:
38  selector:
39    app: gitbucket
40  ports:
41    - protocol: TCP
42      port: 80
43      targetPort: 8080
44---
45apiVersion: networking.k8s.io/v1
46kind: Ingress
47metadata:
48  name: example
49  namespace: default
50  labels:
51    app: gitbucket
52spec:
53  ingressClassName: nginx
54  rules:
55    - host: app.test02.cloud.t-inagaki.net
56      http:
57        paths:
58          - path: /
59            pathType: Prefix
60            backend:
61              service:
62                name: gitbucket
63                port:
64                  number: 80

デプロイします。

1# kubectl apply -f manifest.yaml
2deployment.apps/gitbucket created
3service/gitbucket created
4ingress.networking.k8s.io/example created

稼働していることを確認します。

 1# kubectl get pods
 2NAME                         READY   STATUS    RESTARTS   AGE
 3gitbucket-57b89d5bfc-6zqk2   1/1     Running   0          46s
 4# kubectl get svc
 5NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
 6gitbucket    ClusterIP   10.233.13.13   <none>        80/TCP    7m37s
 7kubernetes   ClusterIP   10.233.0.1     <none>        443/TCP   59m
 8# kubectl get ing
 9NAME      CLASS   HOSTS                            ADDRESS   PORTS   AGE
10example   nginx   app.test02.cloud.t-inagaki.net             80      7m39s

Ingress で指定したホスト名でブラウザでアクセスできることを確認します。

おわり

以上、さくらのクラウドの LB アプライアンスで k8s の ingress controller を冗長化する方法でした。

Tags: