具有应用程序路由附加产品的高级 Ingress 配置

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

本文介绍如何设置高级 Ingress 配置来加密流量,并使用 Azure DNS 管理 DNS 区域。

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

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

  • 基于 [Kubernetes nginx Ingress 控制器][kubernetes-nginx-ingress] 轻松配置托管 nginx Ingress 控制器。
  • 与外部 DNS(例如 Azure DNS)集成,以便进行公共区域和专用区域管理
  • SSL 终止,证书存储在密钥保管库中,例如 Azure Key Vault

先决条件

  • 具有应用程序路由附加产品的 AKS 群集。
  • 如果要配置 SSL 终止并将证书存储在 Azure 中托管的保管库中,则使用 Azure Key Vault。
  • 如果要配置公共区域和专用区域管理,并将其托管在 Azure 中,则使用 Azure DNS。

连接到 AKS 群集

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

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

az aks get-credentials -g <ResourceGroupName> -n <ClusterName>

终止 HTTPS 流量

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

  • azure-keyvault-secrets-provider:需要使用 Azure Key Vault 的机密存储 CSI 提供程序从 Azure Key Vault 检索证书。

    重要

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

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

启用密钥保管库机密提供程序

若要在群集上启用应用程序路由,请使用 az aks enable-addons 命令并指定 azure-keyvault-secrets-provider 以及 --addons 自变量和 --enable-secret-rotation 自变量。

az aks enable-addons -g <ResourceGroupName> -n <ClusterName> --addons azure-keyvault-secrets-provider --enable-secret-rotation

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

注意

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

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

az keyvault create -g <ResourceGroupName> -l <Location> -n <KeyVaultName>

创建并导出自签名 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> -n <KeyVaultCertificateName> -f aks-ingress-tls.pfx [--password <certificate password if specified>]

检索加载项的托管标识对象 ID

可在后续步骤使用托管标识授予管理 Azure DNS 区域以及从 Azure 密钥保管库检索机密和证书的权限。

使用 az aks show 命令并将输出设置为名为 MANAGEDIDENTITY_OBJECTID 的变量,获取附加产品的托管标识对象 ID。

# Provide values for your environment
RGNAME=<ResourceGroupName>
CLUSTERNAME=<ClusterName>
MANAGEDIDENTITY_OBJECTID=$(az aks show -g ${RGNAME} -n ${CLUSTERNAME} --query ingressProfile.webAppRouting.identity.objectId -o tsv)

授予加载项从 Azure 密钥保管库检索证书的权限

应用程序路由加载项在群集资源组中创建用户创建的托管标识。 需要向托管标识授予权限,以便它可以从 Azure Key Vault 检索 SSL 证书。

Azure 密钥保管库提供了两个授权系统:在管理平面上运行的 Azure 基于角色的访问控制 (Azure RBAC) 和同时在管理平面和数据平面上运行的访问策略模型。 要了解密钥保管库使用的系统,可以查询 enableRbacAuthorization 属性。

az keyvault show --name <KeyVaultName> --query properties.enableRbacAuthorization

如果为密钥保管库启用了 Azure RBAC 授权,则应使用 Azure RBAC 配置权限。 运行以下命令,将 Key Vault Secrets User 角色分配添加到密钥保管库。

KEYVAULTID=$(az keyvault show --name <KeyVaultName> --query "id" --output tsv)
az role assignment create --role "Key Vault Secrets User" --assignee $MANAGEDIDENTITY_OBJECTID --scope $KEYVAULTID

如果没有为密钥保管库启用 Azure RBAC 授权,则应使用访问策略模型配置权限。 使用 az keyvault set-policy 命令为应用程序路由加载项授予 GET 权限,使其能够从 Azure Key Vault 检索证书。

az keyvault set-policy --name <KeyVaultName> --object-id $MANAGEDIDENTITY_OBJECTID --secret-permissions get --certificate-permissions get

将加载项配置为使用 Azure DNS 来管理 DNS 区域

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

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

    注意

    如果计划使用 Azure DNS,则需要更新附加产品以包含 --dns-zone-resource-ids 自变量。 可以传递多个公共或专用 Azure DNS 区域资源 ID 的逗号分隔列表。

创建全局 Azure DNS 区域

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

    az network dns zone create -g <ResourceGroupName> -n <ZoneName>
    
  2. 使用 az network dns zone show 命令并将输出设置为名为 ZONEID 的变量,检索 DNS 区域的资源 ID。

    ZONEID=$(az network dns zone show -g <ResourceGroupName> -n <ZoneName> --query "id" --output tsv)
    
  3. 使用 az role assignment create 命令授予对 DNS 区域的“DNS 区域参与者”权限。

    az role assignment create --role "DNS Zone Contributor" --assignee $MANAGEDIDENTITY_OBJECTID --scope $ZONEID
    
  4. 使用 az aks addon update 命令更新加载项以启用与 Azure DNS 的集成,并安装 external-dns 控制器。

    az aks addon update -g <ResourceGroupName> -n <ClusterName> --addon web_application_routing --dns-zone-resource-ids=$ZONEID
    

创建 Ingress

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

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

    az keyvault certificate show --vault-name <KeyVaultName> -n <KeyVaultCertificateName> --query "id" --output tsv
    
  2. 将以下 YAML 清单复制到名为 ingress.yaml 的新文件中,并将该文件保存到本地计算机。

    注意

    使用你的 DNS 主机名更新 <Hostname>,并使用从 Azure 密钥保管库返回的 ID 更新 <KeyVaultCertificateUri>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