Ingress-nginx環境をデプロイして動作確認を行う

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

前回Helmを使ってMetalLBをデプロイ。LoadBalancerを使える環境を構築し、実際に使ってみました。

https://qiita.com/ohtsuka-shota/items/f8f2c1d9a447d4c122ee

今回はIngress-nginxをこの環境にデプロイし、使ってみたいと思います。

# 用語
## Ingressとは？

>Ingressはクラスター外からクラスター内ServiceへのHTTPとHTTPSのルートを公開します。トラフィックのルーティングはIngressリソース上で定義されるルールによって制御されます。

https://kubernetes.io/ja/docs/concepts/services-networking/ingress/

## Ingress-nginxとは？

おそらく様々な種類のあるIngressの中の1つの種類という認識でいいかと思います。
他にもHAProxy IngressとかIstio Ingress等様々ありそうです。

https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#additional-controllers

https://www.nginx.com/products/nginx-ingress-controller/




# 構築イメージ
今回構築する環境は以下となります。ingress-nginx namespace上にingressに必要な環境をHelmを使ってデプロイ。wp namespace上にあったWordpress用のLoadbalancerを削除し、新しくClusterIPをデプロイ。さらにIngressを同namespaceにデプロイし、デプロイ時にWordpressのClusterIPと紐づけることでIngress経由でWordpressにアクセスしたいと思います。

![k8s_3-ページ12.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/5cfeefbf-a4b5-b547-dcc3-06fa4ef1cbfd.png)

# 構築
## Ingress-nginxをHelmを作ってデプロイ
以下のサイトを参考に環境を作っていきます。

https://kubernetes.github.io/ingress-nginx/deploy/#quick-start

まず、ingress-nginx namespaceを作成します。
```
root@k8s-master:~# kubectl create ns ingress-nginx
namespace/ingress-nginx created
root@k8s-master:~# kubectl get ns
NAME              STATUS   AGE
default           Active   21d
ingress-nginx     Active   5s
kube-node-lease   Active   21d
kube-public       Active   21d
kube-system       Active   21d
metal-lb          Active   135m
observability     Active   7d7h
wp                Active   135m
```

上記Webサイトに記載されているコマンドを実行してデプロイします。NOTEより下に色々書かれていますが、いったん気にしないで問題ありません。
```
root@k8s-master:~# helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace
Release "ingress-nginx" does not exist. Installing it now.

NAME: ingress-nginx
LAST DEPLOYED: Sat Jul  1 16:16:50 2023
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller'
An example Ingress that makes use of the controller:
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: example
    namespace: foo
  spec:
    ingressClassName: nginx
    rules:
      - host: www.example.com
        http:
          paths:
            - pathType: Prefix
              backend:
                service:
                  name: exampleService
                  port:
                    number: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
      - hosts:
        - www.example.com
        secretName: example-tls
If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:
  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls
```

helm lsでデプロイされているか確認します。
```
root@k8s-master:~# helm ls -A
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
ingress-nginx   ingress-nginx   1               2023-07-01 16:16:50.572819104 +0000 UTC deployed        ingress-nginx-4.7.1     1.8.1
metallb         metal-lb        1               2023-07-01 14:01:52.7948106 +0000 UTC   deployed        metallb-0.13.10         v0.13.10
```

nginx-ingress namespaceのpodやserviceを確認します。
デプロイに問題はなさそうに見えます。LoadBalancerがデプロイされていることから、Ingress環境を作る前段階としてMetalLB環境を作っておく必要がありそうです。
※最も回避する方法もありそうではありますが。
```
root@k8s-master:~# kubectl get pod,svc -n ingress-nginx
NAME                                            READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-5fcb5746fc-96lhp   1/1     Running   0          78s

NAME                                         TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   10.111.144.184   192.168.2.46   80:32147/TCP,443:31546/TCP   78s
service/ingress-nginx-controller-admission   ClusterIP      10.96.215.248    <none>         443/TCP                      78s
```

## WordpressのLoadbalancerを削除しClusterIPを用意する
以下のコマンドを実行して既にデプロイされていたWordpressのLoadBalancerを削除しました。
```
root@k8s-master:~/yaml/wp# kubectl delete -f wordpress-loadbalancer.yaml
service "wordpress-loadbalancer" deleted
```

次にIngressと連携するためのClusterIPのデプロイをしていきます。
今回用意したyamlは以下となります。
```wordpress-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-clusterip
  namespace: wp
spec:
  selector:
    app: wordpress
  type: ClusterIP
  ports:
  - name: wordpress
    port: 80
    protocol: TCP
    targetPort: 80
```

デプロイします。
```
root@k8s-master:~/yaml/wp# kubectl apply -f wordpress-clusterip.yaml
service/wordpress-clusterip created
```

## ingressをデプロイする
以下のyamlを用意しました。アクセスしたいpod(ClusterIP)と同じnamespace上にデプロイされるように気を付けましょう。pathに"/"に指定していることから、IPアドレス後に何も入力をしないとWorpressのClusterIPに処理を投げるような処理を行います。
PythonのDjangoをやっている方であれば、あれのurls.pyをイメージいただけると近いのかと思います。またJavaのSprinBootをやっている方であればRestControllerが近いように感じます。
```wp-pod-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wp-pod-ingress
  namespace: wp
spec:
  ingressClassName: "nginx"
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: wordpress-clusterip
            port:
              number: 80
```

デプロイします。
```
root@k8s-master:~/yaml/ingress# kubectl apply -f wp-pod-ingress.yaml
ingress.networking.k8s.io/wp-pod-ingress created
```

実行結果を確認します。ingressにあたっているIPアドレスは後で接続確認で使用します。
```
root@k8s-master:~/yaml/ingress# kubectl get pod,svc,ingress -n wp -o wide
NAME                READY   STATUS    RESTARTS   AGE    IP              NODE           NOMINATED NODE   READINESS GATES
pod/mysql-pod       1/1     Running   0          170m   172.16.69.207   k8s-worker02   <none>           <none>
pod/wordpress-pod   1/1     Running   0          170m   172.16.39.209   k8s-worker03   <none>           <none>

NAME                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE    SELECTOR
service/mysql-clusterip       ClusterIP   10.96.152.58     <none>        3306/TCP   170m   app=mysql
service/wordpress-clusterip   ClusterIP   10.104.178.189   <none>        80/TCP     30m    app=wordpress

NAME                                       CLASS   HOSTS   ADDRESS        PORTS   AGE
ingress.networking.k8s.io/wp-pod-ingress   nginx   *       192.168.2.46   80      6m45s

root@k8s-master:~/yaml/ingress# kubectl describe ingress -n wp wp-pod-ingress
Name:             wp-pod-ingress
Labels:           <none>
Namespace:        wp
Address:          192.168.2.46
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /   wordpress-clusterip:80 (172.16.39.209:80)
Annotations:  <none>
Events:
  Type    Reason  Age                    From                      Message
  ----    ------  ----                   ----                      -------
  Normal  Sync    2m29s (x2 over 3m14s)  nginx-ingress-controller  Scheduled for sync
```

アクセス結果は以下です。
ingressに割り当たっているアドレスを指定すれば行けるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/f9ea2661-1168-3575-85ff-4f13e1f9b9bc.png)