はじめに
自宅ラボでは外部のNginxを利用して、Kubernetes内部のアプリに対してホストベースルーティングを設定している。
この場合、Kubernetesへの通信はNodePortを利用して通信しているが、アプリが増えるたびに外部のNginxの設定変更が必要となる。
外部のNginxの変更はメンテナンス性がよろしくないので、Ingressを設定してKubernetes内部でルーティング可能とする。
現状の構成
以下の通り、アプリが増えるたびにNodePortが必要となり、外部Nginxの設定変更が必要となっている状態となっている。 これを、Ingressを用いて解決する。
Ingress導入後の構成
Ingressを導入することで、Kubernetes内部でホストベースルーティングが可能となり、外部Nginxの設定変更が不要となる。 また、NodePortを必要としないため、不要なIPアドレスを公開する必要が無くなる。
Ingress導入
Ingressを利用するためにはIngress Controllerの導入が必要です。
https://kubernetes.io/ja/docs/concepts/services-networking/ingress-controllers/
上記のURLを確認すると、AWS GCP Nginxがメインでサポートされているようです。
今回は自宅ラボなので、Nginxを利用します。
Ingress Controllerのインストール
以下を参考にNginx Ingress Controllerをインストールします。
https://github.com/kubernetes/ingress-nginx https://kubernetes.github.io/ingress-nginx/deploy/
今回は自宅ラボでkubeadmを利用してにKubernetes環境を構築済みのため、Bare metal Clusters用の設定を行います。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.3/deploy/static/provider/baremetal/deploy.yamlまた、Bare metalの場合、NodePortでServiceが公開されます。
外部NginxからはNodePortを意識したくないため、CloudのLoadBalancerのようにBare metalでも利用可能となる、MetalLBの導入を今後検討します。
今回はNodePortのまま進めるため、以下コマンドで該当のポートを確認します。
今回はport 80に対しては30901でした。
kubectl get svc -n ingress-nginx
-------NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGEingress-nginx-controller             NodePort    10.103.154.124   <none>        80:30901/TCP,443:30771/TCP   5m11singress-nginx-controller-admission   ClusterIP   10.108.187.52    <none>        443/TCP                      5m11sなお、NodePortを固定したい場合はKustomizationを準備し、以下のように設定します
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources:  - https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.3/deploy/static/provider/baremetal/deploy.yaml
patches:  # NodePortを固定  - target:      kind: Service      name: ingress-nginx-controller    patch: |-      - op: add        path: /spec/ports/0/nodePort        value: 30080      - op: add        path: /spec/ports/1/nodePort        value: 30443これで、HTTPは30080、HTTPSは30443でアクセス可能です。
NAME                                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGEservice/ingress-nginx-controller             NodePort    10.111.186.246   <none>        80:30080/TCP,443:30443/TCP   20sservice/ingress-nginx-controller-admission   ClusterIP   10.96.80.110     <none>        443/TCP                      20sこれでingress controllerの導入が完了したので、次はingressの定義です。
Ingressへの変更
これまでは、以下のような形でアプリごとのServiceをNodePortで定義していましたが、これをClusterIPで定義し、Ingressを追加します。
apiVersion: v1kind: Servicemetadata:  name: redmine-servicespec:  type: NodePort  type: ClusterIP  ports:    - port: 80      targetPort: 3000      nodePort: 30001  selector:    app: redminebackendに指定するserviceは上記のserviceのnameと一致させてください。
hostを設定することでkubernetesがホストベースルーティングを実施してくれます。
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: redmine  namespace: redmine  labels:    app.kubernetes.io/name: redminespec:  ingressClassName: nginx  rules:    - host: redmine.home.tessy.dev      http:        paths:          - pathType: Prefix            path: '/'            backend:              service:                name: redmine-service                port:                  number: 80クラスタ外部からのアクセス
これまではクラスタ外部のNginxからアプリごとのNodePortに通信を行なっていましたが、Ingressを導入したことによって、IngressのNodePortに集約することが出来ました。
また、同一のドメインであれば、まとめてkubernetesに転送できるため、外部Nginx側のメンテナンス性も上がりました。
upstream k8s-home {    server k8s:30080; # Ingress Controllerで確認したNodePort}server {    listen 80;    server_name *.home.tessy.com; # サブドメインをまとめて転送し、k8sのIngressでルーティングを行う。
    location / {        proxy_pass http://k8s-home/;
        proxy_set_header Host $host; # これを設定しないとk8sにHost情報が伝達されない。        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;    }}これらの設定を反映することで、Ingress経由でアクセスが可能です。
まとめ
Ingressを導入する前は、これまではアプリごとにNodePortを消費しており、外部からのアクセスもそれに応じた設定を行う必要がありました。
Ingress導入でこれらの問題を解決することが出来、Kubernetes側でホストベースルーティングを行うことでメンテナンス性が向上しました。。
ただし、まだIngress向けのNodePortは指定する必要があるため、MetalLBを利用して今後解消したいと思います。