使用应用程序路由加载项设置自定义域名和 SSL 证书

Ingress 是一个定义规则的 API 对象,允许对 Azure Kubernetes 服务 (AKS) 群集中的服务进行外部访问。 创建使用应用程序路由附加产品 nginx Ingress 类的 Ingress 对象时,附加产品会在 AKS 群集中创建、配置和管理一个或多个 Ingress 控制器。

本文介绍如何设置高级 Ingress 配置,以使用存储在 Azure Key Vault 中的 SSL/TLS 证书来加密流量,并使用 Azure DNS 管理 DNS 区域。

具有 nginx 功能的应用程序路由附加产品

具有 nginx 的应用程序路由附加产品提供以下内容:

  • 轻松配置托管 nginx 入口控制器。
  • 与外部 DNS(例如 Azure DNS)集成,以便进行全球和专用区域管理
  • SSL 终止,证书存储在密钥保管库中,例如 Azure Key Vault

先决条件

  • 具有应用程序路由附加产品的 AKS 群集。
  • 如果要配置 SSL 终止并将证书存储在 Azure 中托管的保管库中,则使用 Azure Key Vault。
  • 如果你要配置全球和专用区域管理并将其托管在 Azure 中,请使用 Azure DNS。
  • 若要附加 Azure Key Vault 或 Azure DNS 区域,需要 Azure 订阅上的所有者Azure 帐户管理员Azure 共同管理员角色。
  • 所有公共 DNS 区域都必须位于同一订阅和资源组中。

连接到 AKS 群集

若要从本地计算机连接到 Kubernetes 群集,请使用 Kubernetes 命令行客户端 kubectl。 可以使用 az aks install-cli 命令在本地安装它。

使用 az aks get-credentials 命令将 kubectl 配置为连接到 Kubernetes 群集。

az aks get-credentials --resource-group <ResourceGroupName> --name <ClusterName>

使用 Azure Key Vault 中的证书终止 HTTPS 流量

若要启用对 HTTPS 流量的支持,请参阅以下先决条件:

  • SSL 证书。 如果没有证书,则可以创建证书

创建 Azure 密钥保管库用于存储证书

注意

如果你已经有一个 Azure Key Vault,可以跳过此步骤。

使用 az keyvault create 命令创建 Azure Key Vault。

az keyvault create --resource-group <ResourceGroupName> --location <Location> --name <KeyVaultName> --enable-rbac-authorization true

创建并导出自签名 SSL 证书

注意

如果已有证书,则可跳过此步骤。

  1. 使用 openssl req 命令创建要与 Ingress 一起使用的自签名 SSL 证书。 请确保将 <Hostname> 替换为正在使用的 DNS 名称。

    openssl req -new -x509 -nodes -out aks-ingress-tls.crt -keyout aks-ingress-tls.key -subj "/CN=<Hostname>" -addext "subjectAltName=DNS:<Hostname>"
    
  2. 使用 openssl pkcs12 -export 命令导出 SSL 证书并跳过密码提示。

    openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out aks-ingress-tls.pfx
    

将证书导入 Azure Key Vault

使用 az keyvault certificate import 命令将 SSL 证书导入 Azure Key Vault。 如果证书受密码保护,则可以通过 --password 标志传递密码。

az keyvault certificate import --vault-name <KeyVaultName> --name <KeyVaultCertificateName> --file aks-ingress-tls.pfx [--password <certificate password if specified>]

重要

若要使该加载项能够在证书更改时从 Azure 密钥保管库重新加载证书,应使用 --enable-secret-rotation 参数启用机密存储 CSI 驱动程序的机密自动轮换功能。 启用自动轮换后,驱动程序会根据定义的轮换轮询间隔定期轮询更改来更新 pod 装载和 Kubernetes 机密。 默认的轮换轮询间隔为两分钟。

启用 Azure Key Vault 集成

在启用了应用程序路由附加产品的群集上,使用具有 --enable-kv--attach-kv 参数的 az aks approuting update 命令,为机密存储 CSI 驱动程序启用 Azure Key Vault 提供程序并应用所需的角色分配。

Azure 密钥保管库提供了两个授权系统:在管理平面上运行的 Azure 基于角色的访问控制 (Azure RBAC) 和同时在管理平面和数据平面上运行的访问策略模型--attach-kv 操作将选择要使用的适当访问模型。

注意

az aks approuting update --attach-kv 命令使用运行该命令的用户的权限来创建 Azure Key Vault 角色分配。 此角色分配给附加产品的托管标识。 有关 AKS 托管标识的详细信息,请参阅托管标识摘要

检索 Azure Key Vault 资源 ID。

KEYVAULTID=$(az keyvault show --name <KeyVaultName> --query "id" --output tsv)

然后更新应用路由附加产品以启用 Azure Key Vault 机密存储 CSI 驱动程序并应用角色分配。

az aks approuting update --resource-group <ResourceGroupName> --name <ClusterName> --enable-kv --attach-kv ${KEYVAULTID}

启用 Azure DNS 集成

若要启用对 DNS 区域的支持,请查看以下先决条件:

  • 可以将应用路由加载项配置为为 Ingress 资源上定义的主机自动在一个或多个 Azure 全球和专用 DNS 区域上创建记录。 所有全局 Azure DNS 区域都需要位于同一资源组中,并且所有专用 Azure DNS 区域都需要位于同一资源组中。 如果没有 Azure DNS 区域,则可以创建一个

创建公用 Azure DNS 区域

注意

如果已有 Azure DNS 区域,可以跳过此步骤。

  1. 使用 az network dns zone create 命令创建 Azure DNS 区域。

    az network dns zone create --resource-group <ResourceGroupName> --name <ZoneName>
    

将 Azure DNS 区域附加到应用程序路由附加产品

注意

az aks approuting zone add 命令使用运行该命令的用户的权限来创建 Azure DNS 区域角色分配。 此角色分配给附加产品的托管标识。 有关 AKS 托管标识的详细信息,请参阅托管标识摘要

  1. 使用 az network dns zone show 命令并将输出设置为名为 ZONEID 的变量,检索 DNS 区域的资源 ID。

    ZONEID=$(az network dns zone show --resource-group <ResourceGroupName> --name <ZoneName> --query "id" --output tsv)
    
  2. 更新附加产品以使用 az aks approuting zone 命令启用与 Azure DNS 的集成。 可以传递以逗号分隔的 DNS 区域资源 ID 列表。

    az aks approuting zone add --resource-group <ResourceGroupName> --name <ClusterName> --ids=${ZONEID} --attach-zones
    

从 Azure Key Vault 创建使用主机名和证书的入口

应用程序路由附加产品在名为 webapprouting.kubernetes.azure.com 的群集上创建一个 Ingress 类。 使用此类创建 Ingress 对象时,会激活附加产品。

  1. 使用 az keyvault certificate show 命令从 Azure Key Vault 获取要在 Ingress 中使用的证书 URI。

    az keyvault certificate show --vault-name <KeyVaultName> --name <KeyVaultCertificateName> --query "id" --output tsv
    

    以下示例输出显示了从命令返回的证书 URI:

    https://KeyVaultName.vault.azure.cn/certificates/KeyVaultCertificateName/ea62e42260f04f17a9309d6b87aceb44
    
  2. 将以下 YAML 清单复制到名为 ingress.yaml 的新文件中,并将该文件保存到本地计算机。

    使用 DNS 主机的名称更新 <Hostname>,并使用在上述步骤 1 中用于查询 Azure Key Vault 的命令返回的 URI 更新 <KeyVaultCertificateUri>*<KeyVaultCertificateUri>* 的字符串值应仅包含 https://yourkeyvault.vault.azure.cn/certificates/certname。 为了获取当前版本,应省略 URI 字符串末尾的证书版本

    secretName 部分中的 tls 密钥定义机密的名称,该机密包含此入口资源的证书。 当客户端浏览到 <Hostname> 密钥中指定的 URL 时,将在浏览器中显示此证书。 确保 secretName 的值等于 keyvault-(后跟入口资源名称的值)(来自 metadata.name)。 在示例 YAML 中,secretName 需要等于 keyvault-<your Ingress name>

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.azure.com/tls-cert-keyvault-uri: <KeyVaultCertificateUri>
      name: aks-helloworld
      namespace: hello-web-app-routing
    spec:
      ingressClassName: webapprouting.kubernetes.azure.com
      rules:
      - host: <Hostname>
        http:
          paths:
          - backend:
              service:
                name: aks-helloworld
                port:
                  number: 80
            path: /
            pathType: Prefix
      tls:
      - hosts:
        - <Hostname>
        secretName: keyvault-<your ingress name>
    
  3. 使用 kubectl apply 命令创建群集资源。

    kubectl apply -f ingress.yaml -n hello-web-app-routing
    

    以下示例输出显示了已创建的资源:

    Ingress.networking.k8s.io/aks-helloworld created
    

验证是否已创建托管 Ingress

可以使用 kubectl get ingress 命令验证是否已创建托管 Ingress。

kubectl get ingress -n hello-web-app-routing

以下示例输出显示了创建的托管 Ingress:

NAME             CLASS                                HOSTS               ADDRESS       PORTS     AGE
aks-helloworld   webapprouting.kubernetes.azure.com   myapp.contoso.com   20.51.92.19   80, 443   4m