AKS(Azure Kubernetes Service)의 수신 컨트롤러와 함께 TLS 사용

TLS(전송 계층 보안) 프로토콜은 인증서를 사용하여 통신, 암호화, 인증 및 무결성에 대한 보안을 제공합니다. AKS에서 수신 컨트롤러와 함께 TLS를 사용하면 애플리케이션 간의 통신을 보호하고 수신 컨트롤러의 이점을 경험할 수 있습니다.

고유한 인증서를 가져와서 비밀 저장소 CSI 드라이버와 통합할 수 있습니다. 또는 Let's Encrypt 인증서를 자동으로 생성하고 구성하는 cert-manager를 사용할 수 있습니다. AKS 클러스터에서 실행되는 두 개의 애플리케이션은 각각 단일 IP 주소를 통해 액세스할 수 있습니다.

Important

애플리케이션 라우팅 추가 기능은 AKS의 수신에 권장됩니다. 자세한 내용은 애플리케이션 라우팅 추가 기능을 사용하여 관리되는 nginx 수신을 참조하세요.

Important

Microsoft는 cert-manager 및 그 사용으로 인한 문제를 관리하거나 지원하지 않습니다. cert-manager 관련 문제는 cert-manager 문제 해결 설명서를 참조하세요.

Nginx를 기반으로 하는 Kubernetes에는 두 개의 오픈 소스 수신 컨트롤러가 있습니다. 하나는 Kubernetes 커뮤니티(kubernetes/ingress-nginx)에 의해 유지 관리되고 하나는 NGINX, Inc.(nginxinc/kubernetes-ingress)에 의해 유지 관리됩니다. 이 문서에서는 Kubernetes 커뮤니티 수신 컨트롤러를 사용합니다.

시작하기 전에

  • 이 문서에서는 수신 컨트롤러와 애플리케이션이 설정되어 있다고 가정합니다. 수신 컨트롤러 또는 예제 애플리케이션이 필요한 경우 수신 컨트롤러 만들기를 참조하세요.

  • 이 문서에서는 Helm 3을 사용하여 지원되는 Kubernetes 버전에 NGINX 수신 컨트롤러를 설치합니다. 최신 릴리스의 Helm을 사용하고 있고 ingress-nginxjetstack Helm 리포지토리에 대한 액세스 권한이 있는지 확인합니다. 이 문서에 설명된 단계는 이전 버전의 Helm 차트, NGINX 수신 컨트롤러 또는 Kubernetes와 호환되지 않을 수 있습니다.

  • 이 문서에서는 통합 ACR(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 차트에서 사용하는 cert-manager 이미지를 ACR로 가져오기

  • az acr import를 사용하여 다음 이미지를 ACR로 가져옵니다.

    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
    

참고 항목

Helm 차트를 ACR로 가져올 수도 있습니다. 자세한 내용은 ACR에 Helm 차트 푸시 및 풀을 참조하세요.

수신 컨트롤러 구성 옵션

고정 공용 IP 주소 또는 동적 공용 IP 주소를 사용하여 NGINX 수신 컨트롤러를 구성할 수 있습니다. 사용자 지정 도메인을 사용하는 경우 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
    

참고 항목

또는 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
    

자세한 내용은 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를 사용하여 NGINX 서비스의 외부 IP 주소로 DNS 영역에 A 레코드를 추가합니다.

    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 형식을 따라야 합니다.

Important

DNS 레이블은 Azure 위치 내에서 고유해야 합니다.

다음 방법 중 하나를 사용하여 FQDN을 구성할 수 있습니다.

  • Azure CLI 또는 Azure PowerShell을 사용하여 DNS 레이블을 설정합니다.
  • Helm 차트 설정을 사용하여 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 차트 설정을 사용하여 DNS 레이블 설정

--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" 매개 변수를 사용하여 helm 차트 구성에 주석 설정을 전달할 수 있습니다. 이 매개 변수는 수신 컨트롤러가 처음 배포될 때 설정하거나 나중에 구성할 수 있습니다.

다음 예제에서는 컨트롤러가 배포된 후 이 설정을 업데이트하는 방법을 보여 줍니다. <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

인증서 관리자 설치

NGINX 수신 컨트롤러는 TLS 종료를 지원합니다. 몇 가지 방법으로 HTTPS 인증서를 검색하고 구성할 수 있습니다. 이 문서에서는 자동 Let’s 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에 다음 발급자가 필요합니다.

  • 단일 네임스페이스에서 작동하는 Issuer.
  • 모든 네임스페이스에서 작동하는 ClusterIssuer 리소스.

자세한 내용은 cert-manager 발급자 설명서를 참조하세요.

  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이라는 서비스로 라우팅됩니다.

참고 항목

사용자 지정 도메인 대신 수신 컨트롤러 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_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 인증서를 참조하세요.

Cert-manager는 v0.2.2부터 cert-manager와 함께 자동으로 배포되는 ingress-shim을 사용하여 인증서 개체를 자동으로 만듭니다. 자세한 내용은 수신 shim 설명서를 참조하세요.

인증서가 성공적으로 만들어졌는지 확인하려면 kubectl get certificate --namespace ingress-basic 명령을 사용하고 READYTrue인지 확인합니다. 출력을 가져오는 데 몇 분 정도 걸릴 수 있습니다.

kubectl get certificate --namespace ingress-basic

다음 출력은 인증서의 상태를 보여 줍니다.

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

수신 구성 테스트

웹 브라우저를 Kubernetes 수신 컨트롤러의 hello-world-ingress.MY_CUSTOM_DOMAIN 또는 FQDN에 개방합니다. 다음 사항이 참인지 확인합니다.

  • HTTPS를 사용하도록 리디렉션됩니다.
  • 인증서는 신뢰할 수 있습니다.
  • 데모 애플리케이션이 웹 브라우저에 표시됩니다.
  • 도메인 끝에 /hello-world-two를 추가하고 사용자 지정 제목이 있는 두 번째 데모 애플리케이션이 표시되는지 확인합니다.

리소스 정리

이 문서에서는 Helm을 사용하여 수신 구성 요소, 인증서 및 샘플 앱을 설치했습니다. Helm 차트를 배포하면 다수의 Kubernetes 리소스가 생성됩니다. 이러한 리소스에는 Pod, 배포 및 서비스가 포함됩니다. 해당 리소스를 정리하려면 전체 샘플 네임스페이스 또는 개별 리소스를 삭제하면 됩니다.

샘플 네임스페이스 및 모든 리소스 삭제

샘플 네임스페이스를 삭제하면 네임스페이스의 모든 리소스도 삭제됩니다.

  • 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. 두 개의 샘플 애플리케이션을 제거합니다.

    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의 몇 가지 외부 구성 요소가 포함되었습니다. 이러한 구성 요소에 대한 자세한 내용은 다음 프로젝트 페이지를 참조하세요.

다음도 가능합니다.