NGINX Ingress ControllerによるIPアクセス制御
Kubernetes(AKS)に複数のWebアプリケーションがデプロイされていて、それぞれに対し特定のIPアドレスからのみアクセスを許可する方法を試してみました。
大まかな手順は下のとおりです。
事前準備
Helmのインストール
公式の手順に従い、インストールします。
sudo apt-get update curl https://helm.baltorepo.com/organization/signing.asc | sudo apt-key add - sudo apt-get install apt-transport-https --yes echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list sudo apt-get update sudo apt-get install helm
Ingress Controllerのデプロイ
Ingress用のnamespaceを作っておきます。
kubectl create namespace ingress-basic
HelmでNGINX Ingress Controllerをデプロイします。AKSの公式手順ではnodeSelectorを指定していますが、Nodeの種類が複数あるわけではないので省き、レプリカも1に減らしています。
またこのとき externalTrafficPolicy=Local を指定することが重要です。これによってリクエストの送信元IPを扱うことができるようになります。指定しない場合、送信元IPによるアクセス制御はできません。
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm install nginx-ingress ingress-nginx/ingress-nginx \ --namespace ingress-basic \ --set controller.replicaCount=1 \ --set controller.service.externalTrafficPolicy=Local
デプロイされたリソースを確認してみます。
kubectl --namespace ingress-basic get deployments NAME READY UP-TO-DATE AVAILABLE AGE nginx-ingress-ingress-nginx-controller 1/1 1 1 17h
kubectl --namespace ingress-basic get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-ingress-nginx-controller LoadBalancer 10.0.190.67 xx.xx.xx.xx 80:31238/TCP,443:32076/TCP 17h nginx-ingress-ingress-nginx-controller-admission ClusterIP 10.0.155.88 <none> 443/TCP 17h
検証用アプリケーションのデプロイ
2つのnamespaceを作成し、それぞれにWebサーバーのPodを立ち上げ、Serviceでクラスター内に公開しておきます。
kubectl create namespace app1 kubectl create namespace app2 kubectl -n app1 run webapp1 --image=nginx kubectl -n app2 run webapp2 --image=httpd kubectl -n app1 expose pod webapp1 --port=80 kubectl -n app2 expose pod webapp2 --port=80
アクセス制御の設定
Ingressリソースのデプロイ
それぞれのnamespaceに、WebサーバーServiceへのルーティングを定義したIngressを作成します。このときannotationsのwhitelist-source-rangeで、送信元IPのホワイトリストを指定できます。
注意点としてspec.rulesのbackend.service.nameでは、ServiceのFQDNを指定できません。したがってIngressを作成するnamespaceは、Serviceと同じである必要があります。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/whitelist-source-range: aa.aa.aa.aa/32 name: ingress1 namespace: app1 spec: rules: - http: paths: - backend: service: name: webapp1 port: number: 80 path: /app1 pathType: Prefix --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/whitelist-source-range: bb.bb.bb.bb/32 name: ingress2 namespace: app2 spec: rules: - http: paths: - backend: service: name: webapp2 port: number: 80 path: /app2 pathType: Prefix
動作確認
app1にaa.aa.aa.aaのIPアドレスからアクセスします。
app2にbb.bb.bb.bbのIPアドレスからアクセスします。
app2に許可されていないaa.aa.aa.aaのIPアドレスからアクセスします。
許可されていないIPアドレスからのアクセスは、NGINX Ingress Controllerがエラーを返していることがわかりますね!