アンマネージド イングレス コントローラーを作成する

イングレス コントローラーは、リバース プロキシ、構成可能なトラフィック ルーティング、および Kubernetes サービスの TLS 終端を提供するソフトウェアです。 個別の Kubernetes サービスのイングレス ルールとルートを構成するには、Kubernetes イングレス リソースが使われます。 イングレス コントローラーとイングレス ルールを使用すると、1 つの IP アドレスで Kubernetes クラスター内の複数のサービスにトラフィックをルーティングできます。

この記事では、Azure Kubernetes Service (AKS) クラスターに NGINX イングレス コントローラーを展開する方法について説明します。 続いて、それぞれが 1 つの IP アドレスでアクセスできる、2 つのアプリケーションを AKS クラスターで実行します。

重要

AKS でのイングレスには、アプリケーション ルーティング アドオンをお勧めします。 詳細については、「アプリケーション ルーティング アドオンでのマネージド nginx イングレス」をご覧ください。

Note

Nginx に基づく Kubernetes 用のオープンソース イングレス コントローラーは 2 つあります。1 つは Kubernetes コミュニティによって管理され (kubernetes/ingress-nginx)、もう 1 つは NGINX, Inc. によって管理されています (nginxinc/kubernetes-ingress)。 この記事では、Kubernetes コミュニティのイングレス コントローラーを使用します。

開始する前に

  • この記事では、Helm 3 を使用して、サポートされているバージョンの Kubernetes に NGINX イングレス コントローラーをインストールします。 最新リリースの Helm を使用していること、および ingress-nginx Helm リポジトリにアクセスできることを確認します。 この記事に記載されている手順は、以前のバージョンの Helm グラフ、NGINX イングレス コントローラー、または Kubernetes と互換性がない可能性があります。
  • この記事では、Azure Container Registry が統合された既存の AKS クラスターがあることを前提としています。 ACR が統合された AKS クラスターを作成する方法の詳細については、「Azure Kubernetes Service から Azure Container Registry の認証を受ける」を参照してください。
  • Kubernetes API 正常性エンドポイント healthz は、Kubernetes v1.16 で非推奨となりました。 代わりに、このエンドポイントを livez および readyz エンドポイントで置き換えることができます。 シナリオに使用するエンドポイントを決定するには、正常性のための Kubernetes API エンドポイントに関するページをご覧ください。
  • Azure CLI を使用している場合、この記事では、Azure CLI バージョン 2.0.64 以降を実行している必要があります。 バージョンを確認するには、az --version を実行します。 インストールまたはアップグレードする必要がある場合は、Azure CLI のインストールに関するページを参照してください。
  • Azure PowerShell を使用している場合、この記事では、Azure PowerShell バージョン 5.9.0 以降実行している必要があります。 バージョンを確認するには、Get-InstalledModule -Name Az を実行します。 インストールまたはアップグレードする必要がある場合は、Azure PowerShell のインストールに関するページをご覧ください。

基本構成

既定値をカスタマイズせずに基本的な NGINX イングレス コントローラーを作成するには、Helm を使用します。 次の構成では、わかりやすくするために既定の構成が使用されています。 --set controller.replicaCount=3 など、デプロイをカスタマイズするためのパラメーターを追加できます。

Note

クラスター内のコンテナーへの要求でクライアント ソース IP の保持を有効にする場合は、Helm インストール コマンドに --set controller.service.externalTrafficPolicy=Local を追加します。 クライアント ソース IP が要求ヘッダーの X-Forwarded-For の下に格納されます。 クライアント ソース IP の保持が有効になっているイングレス コントローラーを使用する場合、TLS パススルーは機能しません。

NAMESPACE=ingress-basic

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --create-namespace \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
  --set controller.service.externalTrafficPolicy=Local

Note

このチュートリアルでは、service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path/healthz に設定します。 これは、/healthz への要求の応答コードが 200 でない場合、イングレス コントローラー全体がダウンすることを意味します。 独自のシナリオでは、値を他の URI に変更できます。 この部分を削除したり、値を設定解除したりすることはできません。これを行った場合も、イングレス コントローラーはダウンします。 このチュートリアルで使用するパッケージ ingress-nginx は、Kubernetes 公式で提供されているものであり、イングレス ルールにより上書きされない限り、ユーザーがすぐに始められるように既定のバックエンドとして設計されているため、/healthz を要求すると常に応答コード 200 を返します。

カスタマイズされた構成

次の一連の手順では、上のセクションで説明した基本的な構成の代わりに、カスタマイズされたイングレス コントローラーをデプロイする方法を示します。 内部静的 IP アドレスを使用するか、動的パブリック IP アドレスを使用するオプションがあります。

Helm Chart で使用されるイメージを ACR にインポートする

イメージのバージョンを管理するために、独自の Azure Container Registry にイメージをインポートできます。 NGINX イングレス コントローラー Helm グラフでは、3 つのコンテナー イメージを使用します。 これらのイメージを ACR にインポートするには、az acr import を使用します。

REGISTRY_NAME=<REGISTRY_NAME>
SOURCE_REGISTRY=registry.k8s.io
CONTROLLER_IMAGE=ingress-nginx/controller
CONTROLLER_TAG=v1.8.1
PATCH_IMAGE=ingress-nginx/kube-webhook-certgen
PATCH_TAG=v20230407
DEFAULTBACKEND_IMAGE=defaultbackend-amd64
DEFAULTBACKEND_TAG=1.5

az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$CONTROLLER_IMAGE:$CONTROLLER_TAG --image $CONTROLLER_IMAGE:$CONTROLLER_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$PATCH_IMAGE:$PATCH_TAG --image $PATCH_IMAGE:$PATCH_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG --image $DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG

Note

コンテナー イメージを ACR にインポートするだけでなく、Helm Chart を ACR にインポートすることもできます。 詳細については、「Azure Container Registry に対する Helm chart のプッシュおよびプル」を参照してください。

イングレス コントローラーを作成する

イングレス コントローラーを作成するには、Helm を使用して ingress-nginx をインストールします。 イングレス コントローラーは Linux ノード上でスケジュールする必要があります。 Windows Server ノードでは、イングレス コントローラーを実行しないでください。 ノード セレクターは、--set nodeSelector パラメーターを使用して指定され、Linux ベース ノード上で NGINX イングレス コントローラーを実行するように Kubernetes スケジューラに指示されます。

追加された冗長性については、NGINX イングレス コントローラーの 2 つのレプリカが --set controller.replicaCount パラメーターでデプロイされています。 イングレス コントローラーのレプリカの実行から十分にメリットを享受するには、AKS クラスターに複数のノードが存在していることを確認します。

次の例では、ingress-basic という名前のイングレス リソースの Kubernetes 名前空間が作成され、その名前空間内で動作することを想定しています。 必要に応じて、ご自身の環境の名前空間を指定できます。 AKS クラスターで Kubernetes ロールベースのアクセス制御が有効でない場合は、Helm コマンドに --set rbac.create=false を追加してください。

Note

クラスター内のコンテナーへの要求でクライアント ソース IP の保持を有効にする場合は、Helm インストール コマンドに --set controller.service.externalTrafficPolicy=Local を追加します。 クライアント ソース IP が要求ヘッダーの X-Forwarded-For の下に格納されます。 クライアント ソース IP の保持が有効になっているイングレス コントローラーを使用する場合、TLS パススルーは機能しません。

# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --version 4.7.1 \
    --namespace ingress-basic \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.image.registry=$ACR_LOGIN_SERVER \
    --set controller.image.image=$CONTROLLER_IMAGE \
    --set controller.image.tag=$CONTROLLER_TAG \
    --set controller.image.digest="" \
    --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.service.externalTrafficPolicy=Local \
    --set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
    --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
    --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
    --set controller.admissionWebhooks.patch.image.digest="" \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
    --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
    --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
    --set defaultBackend.image.digest=""

内部 IP アドレスを使用してイングレス コントローラーを作成する

既定では、NGINX イングレス コントローラーは動的パブリック IP アドレスの割り当てによって作成されます。 一般的な構成要件は、内部のプライベート ネットワークと IP アドレスを使用することです。 この手法では、外部アクセスなしで、サービスへのアクセスを内部ユーザーに制限できます。

--set controller.service.loadBalancerIP および --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true パラメーターを使用して、イングレス コントローラーに内部 IP アドレスを割り当てます。 イングレス コント ローラーで使用する場合は、独自の内部 IP アドレスを指定します。 この IP アドレスが仮想ネットワーク内でまだ使用されていないことを確認します。 既存の仮想ネットワークとサブネットを使用している場合は、仮想ネットワークとサブネットを管理するための適切なアクセス許可を使用して AKS クラスターを構成する必要があります。 詳細については、「Azure Kubernetes Service (AKS) の独自の IP アドレス範囲で kubenet ネットワークを使用する」または「Azure Kubernetes Service (AKS) で Azure CNI ネットワークを構成する」を参照してください。

# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --version 4.7.1 \
    --namespace ingress-basic \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.image.registry=$ACR_LOGIN_SERVER \
    --set controller.image.image=$CONTROLLER_IMAGE \
    --set controller.image.tag=$CONTROLLER_TAG \
    --set controller.image.digest="" \
    --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.loadBalancerIP=10.224.0.42 \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
    --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
    --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
    --set controller.admissionWebhooks.patch.image.digest="" \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
    --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
    --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
    --set defaultBackend.image.digest="" 

ロード バランサー サービスを確認する

kubectl get services を使用してロード バランサー サービスを確認します。

kubectl get services --namespace ingress-basic -o wide -w ingress-nginx-controller

NGINX イングレス コントローラー用の Kubernetes ロード バランサー サービスが作成されると、次の出力例に示すように、内部 IP アドレスが EXTERNAL-IP の下に割り当てられます。

NAME                       TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE   SELECTOR
ingress-nginx-controller   LoadBalancer   10.0.65.205   EXTERNAL-IP     80:30957/TCP,443:32414/TCP   1m   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx

この段階で外部 IP アドレスを参照すると、404 ページが表示されます。 これは、次のセクションで行うように、引き続き外部 IP への接続を設定する必要があるためです。

デモ アプリケーションを実行する

動作中のイングレス コントローラーを確認するには、AKS クラスターで 2 つのデモ アプリケーションを実行します。 この例では、kubectl apply を使って、シンプルな Hello world アプリケーションのインスタンスを 2 つデプロイします。

  1. aks-helloworld-one.yaml ファイルを作成し、次の YAML の例をコピーします。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. aks-helloworld-two.yaml ファイルを作成し、次の YAML の例をコピーします。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. kubectl apply を使用して、次の 2 つのデモ アプリケーションを実行します。

    kubectl apply -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl apply -f aks-helloworld-two.yaml --namespace ingress-basic
    

イングレス ルートを作成する

両方のアプリケーションは、Kubernetes クラスターで実行するようになります。 各アプリケーションにトラフィックをルーティングするには、Kubernetes イングレス リソースを作成します。 イングレス リソースでは、2 つのアプリケーションのいずれかにトラフィックをルーティングするルールを構成します。

次の例では、EXTERNAL_IP/hello-world-one へのトラフィックが aks-helloworld-one という名前のサービスにルーティングされます。 EXTERNAL_IP/hello-world-two へのトラフィックは、aks-helloworld-two サービスにルーティングされます。 静的資産の場合、EXTERNAL_IP/static へのトラフィックは aks-helloworld-one という名前のサービスにルーティングされます。

  1. hello-world-ingress.yaml という名前のファイルを作成し、次の例の YAML にコピーします。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.ingress.kubernetes.io/use-regex: "true"
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    spec:
      ingressClassName: nginx
      rules:
      - http:
          paths:
          - path: /hello-world-one(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
          - path: /hello-world-two(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-two
                port:
                  number: 80
          - path: /(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress-static
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.ingress.kubernetes.io/rewrite-target: /static/$2
    spec:
      ingressClassName: nginx
      rules:
      - http:
          paths:
          - path: /static(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port: 
                  number: 80
    
  2. kubectl apply コマンドを使用してイングレス リソースを作成します。

    kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic
    

イングレス コントローラーをテストする

イングレス コント ローラーに対してルートをテストするには、2 つのアプリケーションを参照します。 Web ブラウザーを開き、EXTERNAL_IP などの NGINX イングレス コントローラーの IP アドレスに移動します。 次の例に示すように、最初のデモ アプリケーションが Web ブラウザーに表示されます。

First app running behind the ingress controller

ここで /hello-world-two パスを IP アドレスに追加し、EXTERNAL_IP/hello-world-two などとします。 カスタム タイトル付きの 2 番目のデモ アプリケーションが表示されます。

Second app running behind the ingress controller

内部 IP アドレスをテストする

  1. テスト ポッドを作成し、それにターミナル セッションをアタッチします。

    kubectl run -it --rm aks-ingress-test --image=mcr.microsoft.com/dotnet/runtime-deps:6.0 --namespace ingress-basic
    
  2. apt-get を使用して、curl をポッドにインストールします。

    apt-get update && apt-get install -y curl
    
  3. curl を使用して、http://10.224.0.42 などの Kubernetes イングレス コントローラーのアドレスにアクセスします。 イングレス コントローラーをデプロイしたときに指定した、独自の内部 IP アドレスを指定します。

    curl -L http://10.224.0.42
    

    アドレスにはパスは指定されなかったため、イングレス コントローラーは既定の / ルートに設定されます。 次の簡約された出力例に示すように、最初のデモ アプリケーションが返されます。

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>Welcome to Azure Kubernetes Service (AKS)</title>
    [...]
    
  4. http://10.224.0.42/hello-world-two などの /hello-world-two パスをアドレスに追加します。

    curl -L -k http://10.224.0.42/hello-world-two
    

    次の簡約された出力例に示すように、カスタム タイトル付きの 2 番目のデモ アプリケーションが返されます。

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>AKS Ingress Demo</title>
    [...]
    

リソースをクリーンアップする

この記事では、Helm を使用して、イングレス コンポーネントおよびサンプル アプリをインストールしました。 Helm グラフをデプロイすると、多数の Kubernetes リソースが作成されます。 これらのリソースには、ポッド、デプロイ、およびサービスが含まれます。 これらのリソースをクリーンアップするには、サンプルの名前空間全体を削除するか、またはリソースを個々に削除します。

サンプルの名前空間とすべてのリソースを削除する

サンプルの名前空間全体を削除するには、kubectl delete コマンドを使用して、名前空間の名前を指定します。 名前空間内のすべてのリソースが削除されます。

kubectl delete namespace ingress-basic

リソースを個々に削除する

作成したリソースを個々に削除するという、きめ細かな方法もあります。

  1. helm list コマンドを使用して、Helm リリースを一覧表示します。

    helm list --namespace ingress-basic
    

    次の出力例に示すように、ingress-nginx および aks-helloworld という名前のグラフを探します。

    NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
    ingress-nginx           ingress-basic   1               2020-01-06 19:55:46.358275 -0600 CST    deployed        nginx-ingress-1.27.1    0.26.1  
    
  2. helm uninstall コマンドでリリースをアンインストールします。

    helm uninstall ingress-nginx --namespace ingress-basic
    
  3. 2 つのサンプル アプリケーションを削除します。

    kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
    
  4. サンプル アプリにトラフィックを送信していたイングレス ルートを削除します。

    kubectl delete -f hello-world-ingress.yaml
    
  5. kubectl delete コマンドを使用し、名前空間の名前を指定することで、名前空間を削除します。

    kubectl delete namespace ingress-basic
    

次のステップ

既存のイングレス コンポーネントを使用して TLS を構成するには、イングレス コントローラーでの TLS の使用に関する記事を参照してください。

HTTP アプリケーション ルーティングを使用するように AKS クラスターを構成するには、HTTP アプリケーション ルーティング アドオンの有効化に関する記事を参照してください。

この記事には、AKS への外部コンポーネントが含まれています。 これらのコンポーネントの詳細については、次のプロジェクト ページを参照してください。