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 コミュニティのイングレス コントローラー" を使います。
開始する前に
この記事は、イングレス コントローラーとアプリケーションが設定されていることを前提としています。 イングレス コントローラーまたはサンプル アプリケーションが必要な場合は、「イングレス コントローラーを作成する」を参照してください。
この記事では Helm 3 を使用して、サポートされているバージョンの Kubernetes に NGINX イングレス コントローラーをインストールします。 最新リリースの Helm を使用しており、
ingress-nginx
およびjetstack
Helm リポジトリにアクセスできることを確認します。 この記事に記載されている手順は、以前のバージョンの Helm グラフ、NGINX イングレス コントローラー、または Kubernetes と互換性がない可能性があります。- Helm の構成および使用方法の詳細については、AKS での Helm を使ったアプリケーションのインストールに関する記事を参照してください。 アップグレード手順については、「Helm のインストール ドキュメント」を参照してください。Helm の構成と使用について詳しくは、「Azure Kubernetes Service (AKS) での Helm を使用したアプリケーションのインストール」を参照してください。
この記事では、Azure Container Registry が統合された既存の AKS クラスターがあることを前提としています。 ACR を統合した AKS クラスターの作成については、AKS からの ACR を使った認証に関する記事を参照してください。
Azure CLI を使用している場合、この記事では、Azure CLI バージョン 2.0.64 以降を実行している必要があります。 バージョンを確認するには、
az --version
を実行します。 インストールまたはアップグレードする必要がある場合は、Azure CLI のインストールに関するページを参照してください。Azure PowerShell を使用している場合、この記事では、Azure PowerShell バージョン 5.9.0 以降実行している必要があります。 バージョンを確認するには、
Get-InstalledModule -Name Az
を実行します。 インストールまたはアップグレードする必要がある場合は、Azure PowerShell のインストールに関するページをご覧ください。
シークレット ストア 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 を構成します。
az aks show
コマンドを使用して AKS クラスターのリソース グループ名を取得します。az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
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 アドレスが存在するリソース グループの名前に置き換える。
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>"
パラメーターを追加します。 DNS ラベルは、イングレス コントローラーを最初にデプロイするときに設定することも、後で構成することもできます。--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 についてのページを参照してください。
次のマニフェスト例を使用して、
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
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.yaml
の hello-world-ingress.MY_CUSTOM_DOMAIN を demo-aks-ingress.eastus.cloudapp.azure.com に置き換えます。
次の YAML ファイルの例を使用して、
hello-world-ingress.yaml
ファイルを作成または更新します。spec.tls.hosts
とspec.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
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
コマンドを使用して、READY が True になっていることを確認します。 出力されるまでに数分かかることがあります。
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
リソースを個々に削除する
または、リソースを個別に削除することもできます。
クラスター発行者リソースを削除します。
kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
helm list
コマンドを使用して、Helm リリースを一覧表示します。 次の出力例に示すように、nginx と cert-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
helm uninstall
コマンドを使用してリリースをアンインストールします。 次の例では、NGINX イングレスと cert-manager のデプロイをアンインストールします。$ helm uninstall cert-manager nginx --namespace ingress-basic release "cert-manager" uninstalled release "nginx" uninstalled
2 つのサンプル アプリケーションを削除します。
kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
サンプル アプリにトラフィックを送信していたイングレス ルートを削除します。
kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
名前空間自体を削除します。
kubectl delete
コマンドを使用して、名前空間の名前を指定します。kubectl delete namespace ingress-basic
次のステップ
この記事には、AKS への外部コンポーネントが含まれています。 これらのコンポーネントの詳細については、次のプロジェクト ページを参照してください。
次のこともできます。
Azure Kubernetes Service