使用 Azure Kubernetes 服务 (AKS) 群集(预览版)中的 Web 应用程序路由加载项

Web 应用程序路由加载项在支持 SSL 终止的 Azure Kubernetes 服务 (AKS) 群集中通过存储在 Azure Key Vault 中的证书配置一个入口控制器。 它可以与 Open Service Mesh (OSM) 集成,以使用相互 TLS (mTLS) 对群集间通信进行端到端加密。 部署入口时,加载项将为 Azure DNS 区域中的终结点创建可公开访问的 DNS 名称。

重要

AKS 预览功能是可选择启用的自助功能。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

Web 应用程序路由加载项概述

Web 应用程序路由加载项部署以下组件:

  • nginx 入口控制器:该入口控制器向 Internet 公开。
  • External-DNS 控制器:该控制器监视 Kubernetes 入口资源并在特定于群集的 DNS 区域中创建 DNS A 记录。 仅在传入了 --dns-zone-resource-id 参数时才会部署此组件。

先决条件

  • Azure 订阅。 如果你没有 Azure 订阅,可以创建一个试用版订阅
  • 安装并配置了 Azure CLI 版本 2.47.0 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI
  • 用于存储证书的 Azure 密钥保管库。
  • 已安装 aks-preview Azure CLI 扩展版本 0.5.137 或更高版本。 如果需要安装或更新,请参阅安装或更新 aks-preview 扩展
  • (可选)DNS 解决方案,例如 Azure DNS

安装或更新 aks-preview Azure CLI 扩展

  • 使用 az extension add 命令安装 aks-preview Azure CLI 扩展。

    az extension add --name aks-preview
    
  • 如果需要更新扩展版本,可以使用 az extension update 命令执行此操作。

    az extension update --name aks-preview
    

创建并导出自签名 SSL 证书

注意

如果已有一个 SSL 证书,则可以跳过此步骤。

  1. 使用 openssl req 命令创建要与入口一起使用的自签名 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 密钥保管库用于存储证书

注意

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

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

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

将证书导入 Azure Key Vault

  • 使用 az keyvault certificate import 命令将 SSL 证书导入 Azure Key Vault。

    az keyvault certificate import --vault-name <KeyVaultName> -n <KeyVaultCertificateName> -f aks-ingress-tls.pfx
    

创建 Azure DNS 区域

注意

如果你希望该加载项通过 Azure DNS 自动管理主机名创建过程,需要创建一个 Azure DNS 区域(如果没有)。

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

    az network dns zone create -g <ResourceGroupName> -n <ZoneName>
    

使用 Azure CLI 启用 Web 应用程序路由

需要以下附加加载项:

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

重要

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

在新群集上启用 Web 应用程序路由

  • 通过在以下加载项中使用 az aks create 命令和 --enable-addons 参数,在新 AKS 群集上启用 Web 应用程序路由:

    az aks create -g <ResourceGroupName> -n <ClusterName> -l <Location> --enable-addons azure-keyvault-secrets-provider,web_application_routing --generate-ssh-keys --enable-secret-rotation
    

在现有群集上启用 Web 应用程序路由

  • 通过在以下加载项中使用 az aks enable-addons 命令和 --addons 参数,在现有群集上启用 Web 应用程序路由:

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

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

可以使用此托管标识在后续步骤授予管理 Azure DNS 区域以及从 Azure Key Vault 检索证书的权限。

  • 使用 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 DNS 来管理 DNS 区域

注意

如果计划使用 Azure DNS,需要更新加载项以传入 --dns-zone-resource-id

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

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

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

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

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

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

  • 使用 az keyvault set-policy 命令为 Web 应用程序路由加载项授予 GET 权限,使其能够从 Azure Key Vault 检索证书。

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

连接到 AKS 群集

若要从本地计算机连接到 Kubernetes 群集,请使用 kubectl(Kubernetes 命令行客户端)。 可以使用 az aks install-cli 命令在本地进行安装。 如果使用 Azure 本地 Shell,则 kubectl 已安装。

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

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

部署应用程序

Web 应用程序路由使用 Kubernetes 入口对象上的注释来创建相应的资源,在 Azure DNS 上创建记录,并从 Azure Key Vault 检索 SSL 证书。

创建应用程序命名空间

  • 创建名为 hello-web-app-routing 的命名空间,以使用 kubectl create namespace 命令运行示例 Pod。

    kubectl create namespace hello-web-app-routing
    

创建部署

  • 将以下 YAML 复制到名为 deployment.yaml 的新文件中,并将该文件保存到本地计算机。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld  
      namespace: hello-web-app-routing
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld
      template:
        metadata:
          labels:
            app: aks-helloworld
        spec:
          containers:
          - name: aks-helloworld
            image: mcr.azk8s.cn/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
    

创建服务

  • 将以下 YAML 复制到名为 service.yaml 的新文件中,并将该文件保存到本地计算机。

    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld
      namespace: hello-web-app-routing
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld
    

创建入口

Web 应用程序路由加载项在名为 webapprouting.kubernetes.azure.com 的群集上创建一个入口类。 使用此类创建入口对象时,会激活加载项。

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

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

    注意

    使用你的 DNS 主机名更新 <Hostname>,并使用从 Azure 密钥保管库返回的 ID 更新 <KeyVaultCertificateUri>secretName 是要生成的用于存储证书的机密的名称。 此证书将出现在浏览器中。

    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-aks-helloworld
    

在群集上创建资源

  • 使用 kubectl apply 命令在群集上创建资源。

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

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

    deployment.apps/aks-helloworld created
    service/aks-helloworld created
    ingress.networking.k8s.io/aks-helloworld created
    

验证是否已创建托管入口

  • 验证是否使用 kubectl get ingress 命令创建了托管入口。

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

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

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

通过 DNS 主机名访问终结点

如果你尚未配置 Azure DNS 集成,则需要使用指向入口 IP 地址的 A 记录以及为入口配置的主机名(例如 myapp.contoso.com)来配置自己的 DNS 提供程序。

删除 Web 应用程序路由加载项

  1. 使用 kubectl delete namespace 命令删除关联的命名空间。

    kubectl delete namespace hello-web-app-routing
    
  2. 使用 az aks disable-addons 命令从群集中删除 Web 应用程序路由加载项。

    az aks disable-addons --addons web_application_routing --name myAKSCluster --resource-group myResourceGroup 
    

当禁用了 Web 应用程序路由加载项时,某些 Kubernetes 资源可能会保留在群集中。 这些资源包括 configMap 和 secret,并且是在 app-routing-system 命名空间中创建的。 如果需要,可以删除这些资源。