はじめに
自宅ラボでは外部のNginxを利用して、Kubernetes内部のアプリに対してホストベースルーティングを設定している。
この場合、Kubernetesへの通信はNodePortを利用して通信しているが、アプリが増えるたびに外部のNginxの設定変更が必要となる。
外部のNginxの変更はメンテナンス性がよろしくないので、Ingressを設定してKubernetes内部でルーティング可能とする。
現状の構成
以下の通り、アプリが増えるたびにNodePortが必要となり、外部Nginxの設定変更が必要となっている状態となっている。 これを、Ingressを用いて解決する。
Ingress導入後の構成
Ingressを導入することで、Kubernetes内部でホストベースルーティングが可能となり、外部Nginxの設定変更が不要となる。 また、NodePortを必要としないため、不要なIPアドレスを公開する必要が無くなる。
Ingress導入
Ingressを利用するためにはIngress Controllerの導入が必要です。
上記のURLを確認すると、AWS GCP Nginxがメインでサポートされているようです。
今回は自宅ラボなので、Nginxを利用します。
Ingress Controllerのインストール
以下を参考にNginx Ingress Controllerをインストールします。
今回は自宅ラボで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の導入を今後検討します。
MetalLBを導入することで、Ingress ControllerのServiceをLoadBalancerタイプにして、NodePortを使わずに外部IPを割り当てることができます。 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を利用して解消することが可能です。
MetalLBの導入方法については以下の記事を参照してください。