在 Azure Kubernetes 服务 (AKS) 中创建 HTTPS 入口控制器Create an HTTPS ingress controller on Azure Kubernetes Service (AKS)

入口控制器是一个软件片段,为 Kubernetes 服务提供反向代理、可配置的流量路由和 TLS 终止。An ingress controller is a piece of software that provides reverse proxy, configurable traffic routing, and TLS termination for Kubernetes services. Kubernetes 入口资源用于配置各个 Kubernetes 服务的入口规则和路由。Kubernetes ingress resources are used to configure the ingress rules and routes for individual Kubernetes services. 借助入口控制器和入口规则,可以使用单个 IP 地址将流量路由到 Kubernetes 群集中的多个服务。Using an ingress controller and ingress rules, a single IP address can be used to route traffic to multiple services in a Kubernetes cluster.

本文介绍如何在 Azure Kubernetes 服务 (AKS) 群集中部署 NGINX 入口控制器This article shows you how to deploy the NGINX ingress controller in an Azure Kubernetes Service (AKS) cluster. cert-manager 项目用于自动生成和配置 Let's Encrypt 证书。The cert-manager project is used to automatically generate and configure Let's Encrypt certificates. 最后,在 AKS 群集中运行两个应用程序(可通过单个 IP 地址访问其中的每个应用程序)。Finally, two applications are run in the AKS cluster, each of which is accessible over a single IP address.

也可执行以下操作:You can also:

准备阶段Before you begin

本文假定你拥有现有的 AKS 群集。This article assumes that you have an existing AKS cluster. 如果需要 AKS 群集,请参阅 AKS 快速入门使用 Azure CLI使用 Azure 门户If you need an AKS cluster, see the AKS quickstart using the Azure CLI or using the Azure portal.

本文还假定你在 AKS 群集所在的资源组中有一个具有 DNS 区域的自定义域。This article also assumes you have a custom domain with a DNS Zone in the same resource group as your AKS cluster.

本文使用 Helm 3 安装 NGINX 入口控制器和证书管理器。This article uses Helm 3 to install the NGINX ingress controller and cert-manager. 请确保使用最新版本的 Helm,并且有权访问 ingress-nginx 和 jetstack Helm 存储库 。Make sure that you are using the latest release of Helm and have access to the ingress-nginx and jetstack Helm repositories. 有关升级说明,请参阅 Helm 安装文档。有关配置和使用 Helm 的详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中使用 Helm 安装应用程序For upgrade instructions, see the Helm install docs. For more information on configuring and using Helm, see Install applications with Helm in Azure Kubernetes Service (AKS).

本文还要求运行 Azure CLI 2.0.64 或更高版本。This article also requires that you are running the Azure CLI version 2.0.64 or later. 运行 az --version 即可查找版本。Run az --version to find the version. 如果需要进行安装或升级,请参阅安装 Azure CLIIf you need to install or upgrade, see Install Azure CLI.

创建入口控制器Create an ingress controller

若要创建入口控制器,请使用 helm 命令来安装 nginx-ingressTo create the ingress controller, use the helm command to install nginx-ingress. 对于增加的冗余,NGINX 入口控制器的两个副本会在部署时具备 --set controller.replicaCount 参数。For added redundancy, two replicas of the NGINX ingress controllers are deployed with the --set controller.replicaCount parameter. 若要充分利用正在运行的入口控制器副本,请确保 AKS 群集中有多个节点。To fully benefit from running replicas of the ingress controller, make sure there's more than one node in your AKS cluster.

还需要在 Linux 节点上计划入口控制器。The ingress controller also needs to be scheduled on a Linux node. Windows Server 节点不应运行入口控制器。Windows Server nodes shouldn't run the ingress controller. 使用 --set nodeSelector 参数指定节点选择器,以告知 Kubernetes 计划程序在基于 Linux 的节点上运行 NGINX 入口控制器。A node selector is specified using the --set nodeSelector parameter to tell the Kubernetes scheduler to run the NGINX ingress controller on a Linux-based node.

提示

以下示例为名为 ingress-basic 的入口资源创建 Kubernetes 命名空间。The following example creates a Kubernetes namespace for the ingress resources named ingress-basic. 根据需要为你自己的环境指定一个命名空间。Specify a namespace for your own environment as needed.

提示

若要为对群集中容器的请求启用客户端源 IP 保留,请将 --set controller.service.externalTrafficPolicy=Local 添加到 Helm install 命令中。If you would like to enable client source IP preservation for requests to containers in your cluster, add --set controller.service.externalTrafficPolicy=Local to the Helm install command. 客户端源 IP 存储在 X-Forwarded-For 下的请求头中。The client source IP is stored in the request header under X-Forwarded-For. 使用启用了“客户端源 IP 保留”的入口控制器时,TLS 直通将不起作用。When using an ingress controller with client source IP preservation enabled, TLS pass-through will not work.

# Create a namespace for your ingress resources
kubectl create namespace ingress-basic

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

# Use Helm to deploy an NGINX ingress controller
helm install nginx-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-basic \
    --set controller.replicaCount=2 \
    --set controller.image.registry=usgcr.azk8s.cn \
    --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.image.repository=gcr.azk8s.cn/google_containers/defaultbackend-amd64

在安装过程中,将为入口控制器创建一个 Azure 公共 IP 地址。During the installation, an Azure public IP address is created for the ingress controller. 此公共 IP 地址在入口控制器的寿命期内是静态的。This public IP address is static for the life-span of the ingress controller. 如果你删除入口控制器,则公共 IP 地址分配会丢失。If you delete the ingress controller, the public IP address assignment is lost. 如果你然后创建了另外的入口控制器,则会分配新的公共 IP 地址。If you then create an additional ingress controller, a new public IP address is assigned. 如果希望保持使用此公共 IP 地址,则可以改为创建具有静态公共 IP 地址的入口控制器If you wish to retain the use of the public IP address, you can instead create an ingress controller with a static public IP address.

若要获取公共 IP 地址,请使用 kubectl get service 命令。To get the public IP address, use the kubectl get service command. 将 IP 地址分配给服务需要几分钟时间。It takes a few minutes for the IP address to be assigned to the service.

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

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

尚未创建入口规则。No ingress rules have been created yet. 如果浏览到公共 IP 地址,将显示 NGINX 入口控制器的默认 404 页面。If you browse to the public IP address, the NGINX ingress controller's default 404 page is displayed.

将 A 记录添加到 DNS 区域Add an A record to your DNS zone

使用 az network dns record-set a add-recordA 记录添加到使用 NGINX 服务的外部 IP 地址的 DNS 区域。Add an A record to your DNS zone with the external IP address of the NGINX service using az network dns record-set a add-record.

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

备注

(可选)可以为入口控制器 IP 地址而不是自定义域配置 FQDN。Optionally, you can configure an FQDN for the ingress controller IP address instead of a custom domain. 请注意,此示例适用于 Bash shell。Note that this sample is for a Bash shell.

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

# Name to associate with public IP address
DNSNAME="demo-aks-ingress"

# 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 $DNSNAME

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

安装证书管理器Install cert-manager

NGINX 入口控制器支持 TLS 终止。The NGINX ingress controller supports TLS termination. 可通过多种方法为 HTTPS 检索和配置证书。There are several ways to retrieve and configure certificates for HTTPS. 本文演示如何使用证书管理器,该管理器提供自动 Lets Encrypt 证书生成和管理功能。This article demonstrates using cert-manager, which provides automatic Lets Encrypt certificate generation and management functionality.

若要安装证书管理器控制器,请执行以下命令:To install the cert-manager controller:

# 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 \
  --namespace ingress-basic \
  --version v0.16.1 \
  --set installCRDs=true \
  --set nodeSelector."beta\.kubernetes\.io/os"=linux \
  jetstack/cert-manager

若要详细了解证书管理器配置,请参阅证书管理器项目For more information on cert-manager configuration, see the cert-manager project.

创建 CA 群集证书颁发者Create a CA cluster issuer

证书管理器需要 IssuerClusterIssuer 资源,才能颁发证书。Before certificates can be issued, cert-manager requires an Issuer or ClusterIssuer resource. 这两种 Kubernetes 资源的功能完全相同,区别在于 Issuer 适用于单一命名空间,而 ClusterIssuer 适用于所有命名空间。These Kubernetes resources are identical in functionality, however Issuer works in a single namespace, and ClusterIssuer works across all namespaces. 有关详细信息,请参阅证书管理器颁发者文档。For more information, see the cert-manager issuer documentation.

使用以下示例清单创建群集证书颁发者,例如 cluster-issuer.yamlCreate a cluster issuer, such as cluster-issuer.yaml, using the following example manifest. 将电子邮件地址更新为组织提供的有效地址:Update the email address with a valid address from your organization:

apiVersion: cert-manager.io/v1alpha2
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 命令。To create the issuer, use the kubectl apply command.

kubectl apply -f cluster-issuer.yaml

运行演示应用程序Run demo applications

入口控制器和证书管理解决方案已配置完毕。An ingress controller and a certificate management solution have been configured. 现在让我们在你的 AKS 群集中运行两个演示应用程序。Now let's run two demo applications in your AKS cluster. 此示例使用 Helm 来部署一个简单“Hello world”应用程序的两个实例。In this example, Helm is used to deploy two instances of a simple Hello world application.

若要查看运行中的入口控制器,请在 AKS 群集中运行两个演示应用程序。To see the ingress controller in action, run two demo applications in your AKS cluster. 此示例使用 kubectl apply 来部署一个简单“Hello world”应用程序的两个实例。In this example, you use kubectl apply to deploy two instances of a simple Hello world application.

创建“aks-helloworld-one.yaml”文件,并将其复制到以下示例 YAML 中:Create a aks-helloworld-one.yaml file and copy in the following example 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: neilpeterson/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

创建“aks-helloworld-two.yaml”文件,并将其复制到以下示例 YAML 中:Create a aks-helloworld-two.yaml file and copy in the following example 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: neilpeterson/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

使用 kubectl apply 运行这两个演示应用程序:Run the two demo applications using kubectl apply:

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

创建入口路由Create an ingress route

两个应用程序现在都在 Kubernetes 群集中运行。Both applications are now running on your Kubernetes cluster. 但是,它们使用类型为 ClusterIP 的服务进行配置,并且无法从 Internet 进行访问。However they're configured with a service of type ClusterIP and aren't accessible from the internet. 若要公开发布这两个应用程序,请创建 Kubernetes 入口资源。To make them publicly available, create a Kubernetes ingress resource. 该入口资源配置将流量路由到这两个应用程序之一的规则。The ingress resource configures the rules that route traffic to one of the two applications.

在以下示例中,到地址 hello-world-ingress.MY_CUSTOM_DOMAIN 的流量会路由到 aks-helloworld 服务。In the following example, traffic to the address hello-world-ingress.MY_CUSTOM_DOMAIN is routed to the aks-helloworld service. 到地址 hello-world-ingress.MY_CUSTOM_DOMAIN/hello-world-two 的流量会路由到 aks-helloworld-two 服务。Traffic to the address hello-world-ingress.MY_CUSTOM_DOMAIN/hello-world-two is routed to the aks-helloworld-two service. hello-world-ingress.MY_CUSTOM_DOMAIN/static 的流量会路由到静态资产的名为 aks-helloworld 的服务。Traffic to hello-world-ingress.MY_CUSTOM_DOMAIN/static is routed to the service named aks-helloworld for static assets.

备注

如果为入口控制器 IP 地址(而不是自定义域)配置了 FQDN,请使用 FQDN 而不是 hello-world-ingress.MY_CUSTOM_DOMAIN。If you configured an FQDN for the ingress controller IP address instead of a custom domain, use the FQDN instead of hello-world-ingress.MY_CUSTOM_DOMAIN. 例如,如果 FQDN 为“demo-aks-ingress.chinaeast2.cloudapp.chinacloudapi.cn”,则在 hello-world-ingress.yaml 中将“hello-world-ingress.MY_CUSTOM_DOMAIN”替换为“demo-aks-ingress.chinaeast2.cloudapp.chinacloudapi.cn”。For example if your FQDN is demo-aks-ingress.chinaeast2.cloudapp.chinacloudapi.cn, replace hello-world-ingress.MY_CUSTOM_DOMAIN with demo-aks-ingress.chinaeast2.cloudapp.chinacloudapi.cn in hello-world-ingress.yaml.

使用下面的示例 YAML 创建名为 hello-world-ingress.yaml 的文件。Create a file named hello-world-ingress.yaml using below example YAML. hostshost 更新为在前面步骤中创建的 DNS 名称。Update the hosts and host to the DNS name you created in a previous step.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: hello-world-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/use-regex: "true"
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
  - hosts:
    - hello-world-ingress.MY_CUSTOM_DOMAIN
    secretName: tls-secret
  rules:
  - host: hello-world-ingress.MY_CUSTOM_DOMAIN
    http:
      paths:
      - backend:
          serviceName: aks-helloworld-one
          servicePort: 80
        path: /hello-world-one(/|$)(.*)
      - backend:
          serviceName: aks-helloworld-two
          servicePort: 80
        path: /hello-world-two(/|$)(.*)
      - backend:
          serviceName: aks-helloworld-one
          servicePort: 80
        path: /(.*)
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: hello-world-ingress-static
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /static/$2
    nginx.ingress.kubernetes.io/use-regex: "true"
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
  - hosts:
    - hello-world-ingress.MY_CUSTOM_DOMAIN
    secretName: tls-secret
  rules:
  - host: hello-world-ingress.MY_CUSTOM_DOMAIN
    http:
      paths:
      - backend:
          serviceName: aks-helloworld-one
          servicePort: 80
        path: /static(/|$)(.*)

使用 kubectl apply 命令创建入口资源。Create the ingress resource using the kubectl apply command.

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

验证是否已创建证书对象Verify a certificate object has been created

接下来,必须创建证书资源。Next, a certificate resource must be created. 证书资源定义了必需的 X.509 证书。The certificate resource defines the desired X.509 certificate. 有关详细信息,请参阅证书管理器证书For more information, see cert-manager certificates. 证书管理器已使用 ingress-shim(自 v0.2.2 以来随证书管理器自动部署)为你自动创建了证书对象。Cert-manager has automatically created a certificate object for you using ingress-shim, which is automatically deployed with cert-manager since v0.2.2. 有关详细信息,请参阅 ingress-shim 文档For more information, see the ingress-shim documentation.

若要验证证书是否已成功创建,请使用 kubectl get certificate --namespace ingress-basic 命令,并验证 READY 是否为 True,这可能需要数分钟。To verify that the certificate was created successfully, use the kubectl get certificate --namespace ingress-basic command and verify READY is True, which may take several minutes.

$ kubectl get certificate --namespace ingress-basic

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

测试入口配置Test the ingress configuration

将 Web 浏览器打开到 Kubernetes 入口控制器的 hello-world-ingress.MY_CUSTOM_DOMAINOpen a web browser to hello-world-ingress.MY_CUSTOM_DOMAIN of your Kubernetes ingress controller. 请注意,系统会将你重定向,让你使用 HTTPS。证书是受信任的,演示应用程序显示在 Web 浏览器中。Notice you are redirect to use HTTPS and the certificate is trusted and the demo application is shown in the web browser. 添加 /hello-world-two 路径,并注意显示了自定义标题的第二个演示应用程序。Add the /hello-world-two path and notice the second demo application with the custom title is shown.

清理资源Clean up resources

本文使用 Helm 来安装入口组件、证书和示例应用。This article used Helm to install the ingress components, certificates, and sample apps. 在部署 Helm 图表时,会创建若干 Kubernetes 资源。When you deploy a Helm chart, a number of Kubernetes resources are created. 这些资源包括 pod、部署和服务。These resources includes pods, deployments, and services. 若要清理这些资源,可以删除整个示例命名空间,也可以删除单个资源。To clean up these resources, you can either delete the entire sample namespace, or the individual resources.

删除示例命名空间以及所有资源Delete the sample namespace and all resources

若要删除整个示例命名空间,请使用 kubectl delete 命令并指定命名空间名称。To delete the entire sample namespace, use the kubectl delete command and specify your namespace name. 将会删除命名空间中的所有资源。All the resources in the namespace are deleted.

kubectl delete namespace ingress-basic

单独删除资源Delete resources individually

也可采用更细致的方法来删除单个已创建的资源。Alternatively, a more granular approach is to delete the individual resources created. 首先,删除群集颁发者资源:First, remove the cluster issuer resources:

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

使用 helm list 命令列出 Helm 版本。List the Helm releases with the helm list command. 查找名为“nginx”和“cert-manager”的图表,如以下示例输出中所示 :Look for charts named nginx and cert-manager, as shown in the following example output:

$ 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 命令卸载这些版本。Uninstall the releases with the helm uninstall command. 以下示例将卸载 NGINX 入口和证书管理器部署。The following example uninstalls the NGINX ingress and cert-manager deployments.

$ helm uninstall cert-manager nginx --namespace ingress-basic

release "cert-manager" uninstalled
release "nginx" uninstalled

接下来,删除两个示例应用程序:Next, remove the two sample applications:

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

删除将流量定向到示例应用的入口路由:Remove the ingress route that directed traffic to the sample apps:

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

最后,可以删除自身命名空间。Finally, you can delete the itself namespace. 使用 kubectl delete 命令并指定命名空间名称。Use the kubectl delete command and specify your namespace name:

kubectl delete namespace ingress-basic

后续步骤Next steps

本文包含 AKS 的一些外部组件。This article included some external components to AKS. 若要详细了解这些组件,请参阅以下项目页面:To learn more about these components, see the following project pages:

也可执行以下操作:You can also: