Azure Kubernetes Service (AKS) のイングレス コントローラーで TLS を使用する

トランスポート層セキュリティ (TLS) プロトコルは、証明書を使用して、通信、暗号化、認証、および整合性のセキュリティを提供します。 AKS 上のイングレス コントローラーで TLS を使用すると、アプリケーション間の通信をセキュリティで保護しながら、イングレス コントローラーの利点を得ることができます。

独自の証明書を持ち込み、シークレット ストア CSI ドライバーを使用して統合できます。 または、cert-manager を使用することができます。これは Let's Encrypt 証明書を自動的に生成して構成します。 それぞれが 1 つの IP アドレスでアクセスできる 2 つのアプリケーションを AKS クラスターで実行します。

重要

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

重要

Microsoft は、cert-manager とその使用に起因する問題の管理またはサポートをしていません cert-manager に関する問題については、cert-manager のトラブルシューティング ドキュメントを参照してください。

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

開始する前に

シークレット ストア CSI ドライバーを使用して独自の証明書で TLS を使用する

シークレット ストア CSI ドライバーを使用して独自の証明書で TLS を使用するには、シークレット ストア CSI ドライバーが構成された AKS クラスターと、Azure Key Vault インスタンスが必要です。

詳細については、「TLS を使用して NGINX イングレス コントローラーを有効にするようにシークレット ストア CSI ドライバーを設定する」を参照してください。

Let's Encrypt 証明書で TLS を使用する

Let's Encrypt 証明書で TLS を使用するには、Let's Encrypt 証明書を自動的に生成して構成する cert-manager をデプロイします。

Helm chart で使用される cert-manager イメージを ACR にインポートする

  • 次のイメージを ACR にインポートするには、az acr import を使用します。

    REGISTRY_NAME=<REGISTRY_NAME>
    CERT_MANAGER_REGISTRY=quay.io
    CERT_MANAGER_TAG=v1.8.0
    CERT_MANAGER_IMAGE_CONTROLLER=jetstack/cert-manager-controller
    CERT_MANAGER_IMAGE_WEBHOOK=jetstack/cert-manager-webhook
    CERT_MANAGER_IMAGE_CAINJECTOR=jetstack/cert-manager-cainjector
    
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG
    

Note

また、Helm chart を ACR にインポートすることもできます。 詳細については、「Helm chart を ACR にプッシュおよびプルする」を参照してください。

イングレス コントローラーの構成オプション

NGINX イングレス コントローラーは、静的なパブリック IP アドレスまたは動的なパブリック IP アドレスのいずれかを使って構成できます。 カスタム ドメインを使用している場合は、DNS ゾーンに A レコードを追加する必要があります。 カスタム ドメインを使っていない場合、イングレス コントローラーの IP アドレス用に完全修飾ドメイン名 (FQDN) を構成できます。

静的または動的なパブリック IP アドレスの作成

静的パブリック IP アドレスの使用

イングレス コントローラーに、静的なパブリック IP アドレスを構成できます。 イングレス コントローラーが削除されても、静的パブリック IP アドレスはそのまま残ります。 AKS クラスターを削除した場合、IP アドレスは "残りません"。

イングレス コントローラーをアップグレードする場合、割り当てられるロード バランサーをイングレス コントローラー サービスに認識させるために、Helm リリースにパラメーターを渡す必要があります。 HTTPS 証明書が正しく機能するように、DNS ラベルを使って、イングレス コントローラーの IP アドレス用に FQDN を構成します。

  1. az aks show コマンドを使用して AKS クラスターのリソース グループ名を取得します。

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
  2. az network public-ip create コマンドを使って、"静的" 割り当て方法でパブリック IP アドレスを作成します。 次の例では、前の手順で取得した AKS クラスター リソース グループに myAKSPublicIP という名前のパブリック IP アドレスを作成します。

    az network public-ip create --resource-group MC_myResourceGroup_myAKSCluster_eastus --name myAKSPublicIP --sku Standard --allocation-method static --query publicIp.ipAddress -o tsv
    

Note

または、AKS クラスターとは別に管理できる別のリソース グループに IP アドレスを作成することもできます。 別のリソース グループに IP アドレスを作成する場合は、次のことを確認します。

  • AKS クラスターで使用されるクラスター ID に、ネットワーク共同作成者などのリソース グループへの委任されたアクセス許可が含まれている。
  • --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="<RESOURCE_GROUP>"パラメーターを追加します。 <RESOURCE_GROUP> を IP アドレスが存在するリソース グループの名前に置き換える。
  1. --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>"パラメーターを追加します。 DNS ラベルは、イングレス コントローラーを最初にデプロイするときに設定することも、後で構成することもできます。

  2. --set controller.service.loadBalancerIP="<STATIC_IP>"パラメーターを追加します。 前の手順で作成された独自のパブリック IP アドレスを指定します。

    DNS_LABEL="<DNS_LABEL>"
    NAMESPACE="ingress-basic"
    STATIC_IP=<STATIC_IP>
    
    helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
      --namespace $NAMESPACE \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNS_LABEL \
      --set controller.service.loadBalancerIP=$STATIC_IP \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz
    

詳細については、「Azure Kubernetes Service (AKS) ロード バランサーで静的パブリック IP アドレスと DNS ラベルを使用する」を参照してください。

動的パブリック IP アドレスの使用

作成時にイングレス コントローラー用の Azure パブリック IP アドレスが作成されます。 このパブリック IP アドレスは、イングレス コントローラーが存続している間は静的です。 イングレス コントローラーを削除すると、パブリック IP アドレスは "残りません"。 新しいイングレス コントローラーを作成した場合は、新しいパブリック IP アドレスが割り当てられます。 出力は次のサンプル出力のようになります。

  • kubectl get service コマンドを使って、イングレス コントローラーのパブリック IP アドレスを取得します。

    # Get the public IP address for your ingress controller
    
    kubectl --namespace ingress-basic get services -o wide -w nginx-ingress-ingress-nginx-controller
    
    # Sample output
    
    NAME                                     TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE   SELECTOR
    nginx-ingress-ingress-nginx-controller   LoadBalancer   10.0.74.133   EXTERNAL_IP     80:32486/TCP,443:30953/TCP   44s   app.kubernetes.io/component=controller,app.kubernetes.io/instance=nginx-ingress,app.kubernetes.io/name=ingress-nginx
    

DNS ゾーンに A レコードを追加する

カスタム ドメインを使用している場合は、DNS ゾーンに A レコードを追加する必要があります。 カスタム ドメインを使っていない場合は、FQDN を使ってパブリック IP アドレスを構成できます。

  • az network dns record-set a add-record を使用して、A レコードを NGINX サービスの外部 IP アドレスが使用された DNS ゾーンに追加します。

    az network dns record-set a add-record \
        --resource-group myResourceGroup \
        --zone-name MY_CUSTOM_DOMAIN \
        --record-set-name "*" \
        --ipv4-address MY_EXTERNAL_IP
    

イングレス コントローラーの FQDN を構成する

必要に応じて、DNS ラベルを設定することにより、カスタム ドメインではなくイングレス コントローラーの IP アドレスに FQDN を構成できます。 FQDN は、次の形式に従う必要があります。<CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com

重要

DNS ラベルは、Azure の場所内で一意である必要があります。

次のいずれかの方法を使って、FQDN を構成できます。

  • Azure CLI または Azure PowerShell を使って DNS ラベルを設定する。
  • Helm chart の設定を使って DNS ラベルを設定する。

詳細については、パブリック IP アドレスの DNS 名ラベルに関する記事を参照してください。

Azure CLI または Azure PowerShell を使って DNS ラベルを設定する

<DNS_LABEL> は必ずご自分の一意の DNS ラベルに置き換えてください。

# Public IP address of your ingress controller
IP="MY_EXTERNAL_IP"

# Name to associate with public IP address
DNSLABEL="<DNS_LABEL>"

# Get the resource-id of the public IP
PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv)

# Update public IP address with DNS name
az network public-ip update --ids $PUBLICIPID --dns-name $DNSLABEL

# Display the FQDN
az network public-ip show --ids $PUBLICIPID --query "[dnsSettings.fqdn]" --output tsv

Helm chart の設定を使って DNS ラベルを設定する

--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" パラメーターを使うことで、注釈の設定を、Helm chart の構成に渡すことができます。 このパラメーターは、イングレス コントローラーの初回デプロイ時に設定することも、後から構成することもできます。

次の例は、コントローラーをデプロイした後にこの設定を更新する方法を示しています。 <DNS_LABEL> は必ずご自分の一意の DNS ラベルに置き換えてください。

DNSLABEL="<DNS_LABEL>"
NAMESPACE="ingress-basic"

helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNSLABEL \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz

cert-manager をインストールする

NGINX イングレス コントローラーは、TLS の終端をサポートしています。 HTTPS の証明書を取得および構成するには、いくつかの方法があります。 この記事では、Lets Encrypt 証明書を自動的に作成および管理する機能を提供する cert-manager を使用します。

cert-manager コントローラーをインストールするには、次のコマンドを使います。

# Set variable for ACR location to use for pulling images
ACR_URL=<REGISTRY_URL>

# Label the ingress-basic namespace to disable resource validation
kubectl label namespace ingress-basic cert-manager.io/disable-validation=true

# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io

# Update your local Helm chart repository cache
helm repo update

# Install the cert-manager Helm chart
helm install cert-manager jetstack/cert-manager \
  --namespace ingress-basic \
  --version=$CERT_MANAGER_TAG \
  --set installCRDs=true \
  --set nodeSelector."kubernetes\.io/os"=linux \
  --set image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CONTROLLER \
  --set image.tag=$CERT_MANAGER_TAG \
  --set webhook.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_WEBHOOK \
  --set webhook.image.tag=$CERT_MANAGER_TAG \
  --set cainjector.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CAINJECTOR \
  --set cainjector.image.tag=$CERT_MANAGER_TAG

cert-manager の構成の詳細については、cert-manager プロジェクトについてのページを参照してください。

CA クラスター発行者を作成する

証明書を発行する前に、cert-manager は次の発行者のいずれかを必要とします。

  • 1 つの名前空間で機能する Issuer
  • すべての名前空間で機能する ClusterIssuer リソース。

詳細については、cert-manager issuer についてのページを参照してください。

  1. 次のマニフェスト例を使用して、cluster-issuer.yaml などのクラスター発行者を作成します。 MY_EMAIL_ADDRESS を組織の有効なアドレスに置き換えてください。

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: MY_EMAIL_ADDRESS
        privateKeySecretRef:
          name: letsencrypt
        solvers:
        - http01:
            ingress:
              class: nginx
              podTemplate:
                spec:
                  nodeSelector:
                    "kubernetes.io/os": linux
    
  2. kubectl apply コマンドを使用して発行者を適用します。

    kubectl apply -f cluster-issuer.yaml --namespace ingress-basic
    

イングレス ルートを更新する

FQDN またはカスタム ドメインへのトラフィックを処理するようにイングレス ルートを更新する必要があります。

次の例では、トラフィックは次のようにルーティングされます。

  • hello-world-ingress.MY_CUSTOM_DOMAIN へのトラフィックが aks-helloworld-one サービスにルーティングされます。
  • hello-world-ingress.MY_CUSTOM_DOMAIN/hello-world-two へのトラフィックは、aks-helloworld-two サービスにルーティングされます。
  • hello-world-ingress.MY_CUSTOM_DOMAIN/static へのトラフィックは、静的アセット用の aks-helloworld-one というサービスにルーティングされます。

Note

カスタム ドメインではなく、イングレス コントローラーの IP アドレスの FQDN を構成した場合は、hello-world-ingress.MY_CUSTOM_DOMAIN ではなく、FQDN を使用します。

たとえば、FQDN が demo-aks-ingress.eastus.cloudapp.azure.com の場合は、hello-world-ingress.yamlhello-world-ingress.MY_CUSTOM_DOMAINdemo-aks-ingress.eastus.cloudapp.azure.com に置き換えます。

  1. 次の YAML ファイルの例を使用して、hello-world-ingress.yaml ファイルを作成または更新します。 spec.tls.hostsspec.rules.host を前の手順で作成した DNS 名に更新します。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
        nginx.ingress.kubernetes.io/use-regex: "true"
        cert-manager.io/cluster-issuer: letsencrypt
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - hello-world-ingress.MY_CUSTOM_DOMAIN
        secretName: tls-secret
      rules:
      - host: hello-world-ingress.MY_CUSTOM_DOMAIN
        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
      tls:
      - hosts:
        - hello-world-ingress.MY_CUSTOM_DOMAIN
        secretName: tls-secret
      rules:
      - host: hello-world-ingress.MY_CUSTOM_DOMAIN
        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
    

証明書オブジェクトが作成されたことを確認する

次に、証明書リソースを作成する必要があります。 証明書リソースでは、必要な X.509 証明書を定義します。 詳細については、cert-manager の証明書についてのページを参照してください。

証明書マネージャーによって証明書オブジェクトが ingress-shim を使用して自動的に作成されており、その証明書オブジェクトは v0.2.2 以降の証明書マネージャーで自動的にデプロイされます。 詳しくは、ingress-shim のドキュメントをご覧ください。

証明書が正常に作成されたことを確認するには、kubectl get certificate --namespace ingress-basic コマンドを使用して、READYTrue になっていることを確認します。 出力されるまでに数分かかることがあります。

kubectl get certificate --namespace ingress-basic

次の出力は、証明書の状態を示しています。

NAME         READY   SECRET       AGE
tls-secret   True    tls-secret   11m

イングレスの構成をテストする

Web ブラウザーを開いて、hello-world-ingress.MY_CUSTOM_DOMAIN またはお使いの Kubernetes イングレス コントローラーの FQDN にアクセスします。 次のことが当てはまることを確認してください。

  • HTTPS を使用するようにリダイレクトされる。
  • 証明書は信頼されている
  • Web ブラウザーには、アプリケーションのデモが表示されている。
  • ドメインの末尾に /hello-world-two を追加し、カスタム タイトルを持つ 2 番目のデモ アプリケーションが表示されていることを確認します。

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

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

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

サンプル名前空間を削除すると、名前空間内のすべてのリソースも削除されます。

  • kubectl delete コマンドを使用し、名前空間の名前を指定することで、サンプルの名前空間全体を削除します。

    kubectl delete namespace ingress-basic
    

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

または、リソースを個別に削除することもできます。

  1. クラスター発行者リソースを削除します。

    kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
    
  2. helm list コマンドを使用して、Helm リリースを一覧表示します。 次の出力例に示すように、nginxcert-manager という名前のグラフを探します。

    $ helm list --namespace ingress-basic
    
    NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
    cert-manager            ingress-basic   1               2020-01-15 10:23:36.515514 -0600 CST    deployed        cert-manager-v0.13.0    v0.13.0
    nginx                   ingress-basic   1               2020-01-15 10:09:45.982693 -0600 CST    deployed        nginx-ingress-1.29.1    0.27.0
    
  3. helm uninstall コマンドを使用してリリースをアンインストールします。 次の例では、NGINX イングレスと cert-manager のデプロイをアンインストールします。

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. 2 つのサンプル アプリケーションを削除します。

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

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. 名前空間自体を削除します。 kubectl delete コマンドを使用して、名前空間の名前を指定します。

    kubectl delete namespace ingress-basic
    

次のステップ

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

次のこともできます。