与应用程序路由附加产品配合使用的高级 NGINX 入口控制器和入口配置

应用程序路由附加产品支持使用两种方法来配置入口控制器和入口对象:

先决条件

具有应用程序路由附加产品的 AKS 群集。

连接到 AKS 群集

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

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

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

NGINX 入口控制器的配置

应用程序路由附加产品使用称作 NginxIngressController 的 Kubernetes 自定义资源定义 (CRD) 来配置 NGINX 入口控制器。 你可以创建更多入口控制器或修改现有配置。

下面是对可设置为配置 NginxIngressController 的属性的引用。

properties 说明
ingressClassName 将用于 NGINX 入口控制器的 IngressClass 的名称。 默认为 NginxIngressController 的名称(如果未指定)。
controllerNamePrefix 用于为托管 NGINX 入口控制器资源添加前缀的名称。 默认为 nginx
loadBalancerAnnotations 用于通过设置负载均衡器注释来控制 NGINX 入口控制器服务的行为的一组注释
scaling NGINX 入口控制器缩放方式的配置选项。
scaling.minReplicas 入口控制器副本数的下限。 默认为 2 个 Pod。
scaling.maxReplicas 入口控制器副本数的上限。 默认为 100 个 Pod。
scaling.threshold 定义 NGINX 入口控制器 Pod 应以多快速度根据工作负载进行缩放。 Rapid 表示入口控制器将快速积极地进行缩放,以处理突发的严重流量高峰。 Steady 通过更少的副本处理更多工作,确定成本效益的优先级。 Balanced 是两者之间适用于大多数用例的良好组合。 如果未指定,此字段默认为 Balanced
defaultBackendService NGINX 入口控制器应默认使用的 Kubernetes 服务,其处理 Ingress-NGINX 控制器不了解的所有 URL 路径和主机(即,未使用 Ingress 映射的所有请求)。 该控制器将流量定向到服务的第一个端口。 如果未指定,将使用内置的默认后端
defaultBackendService.namespace 服务的命名空间。
defaultBackendService.name 服务的名称。
defaultSSLCertificate 此属性引用的机密包含访问默认后端服务时要使用的默认证书。 如果未提供此属性,则 NGINX 将使用自签名证书。 如果未在 Ingress 上设置 tls: 部分,则 NGINX 将提供默认证书,但不会强制执行 HTTPS 重定向。
defaultSSLCertificate.forceSSLRedirect 强制不指定 tls: 部分的 Ingress 进行重定向。
defaultSSLCertificate.keyVaultURI 可在其中找到默认 SSL 证书的 Azure Key Vault URI。 加载项需要配置为使用密钥保管库
defaultSSLCertificate.secret 配置群集上有默认 SSL 机密的名称和命名空间。
defaultSSLCertificate.secret.name 机密的名称。
defaultSSLCertificate.secret.namespace 机密的命名空间。

常见配置

控制默认 NGINX 入口控制器配置(预览版)

注意

API 2024-06-02-preview、Kubernetes 1.30 或更高版本,以及 aks-preview Azure CLI 扩展版本 7.0.0b5 或更高版本中提供了在启用加载项时控制 NGINX 入口控制器配置的功能。 要查看 AKS 群集版本,请参阅检查可用的 AKS 群集升级

当启用使用 NGINX 的应用程序路由附加产品时,它会在 app-routing-namespace 中创建一个名为 default 的入口控制器,该控制器配置有面向公众的 Azure 负载均衡器。 该入口控制器使用入口类名 webapprouting.kubernetes.azure.com

你还可以控制默认配置是要获取公共 IP 还是内部 IP,或者是否在启用加载项时创建全新的配置。

下面是可能的配置选项:

  • None:不创建默认的 Nginx 入口控制器,但如果已存在,也不会将其删除。 如果需要,用户应手动删除默认的 NginxIngressController 自定义资源。
  • Internal:使用内部负载均衡器创建默认的 Nginx 入口控制器。 将覆盖对 NginxIngressController 自定义资源进行的任何注释更改(这些更改的目的是使其成为外部资源)。
  • External:使用外部负载均衡器创建默认的 Nginx 入口控制器。 将覆盖对 NginxIngressController 自定义资源进行的任何注释更改(这些更改的目的是使其成为内部资源)。
  • AnnotationControlled(默认):使用外部负载均衡器创建默认的 Nginx 入口控制器。 用户可以编辑默认的 NginxIngressController 自定义资源来配置负载均衡器注释。

创建群集时控制默认入口控制器配置

若要在新群集上启用应用程序路由,请使用 [az aks create][az-aks-create] 命令,并指定 --enable-app-routing--app-routing-default-nginx-controller 标志。 需要将 <DefaultIngressControllerType> 设置为前面所述的配置选项之一。

az aks create \
--resource-group <ResourceGroupName> \
--name <ClusterName> \
--location <Location> \
--enable-app-routing \
--app-routing-default-nginx-controller <DefaultIngressControllerType>

更新现有群集上的默认入口控制器配置

若要更新现有群集上的应用程序路由默认入口控制器配置,请使用 az aks approuting update 命令并指定 --nginx 标志。 需要将 <DefaultIngressControllerType> 设置为前面所述的配置选项之一。

az aks approuting update --resource-group <ResourceGroupName> --name <ClusterName> --nginx <DefaultIngressControllerType>

创建另一个面向公众的 NGINX 入口控制器

若要创建具有面向公众的 Azure 负载均衡器的另一个 NGINX 入口控制器,请执行以下操作:

  1. 将以下 YAML 清单复制到名为 nginx-public-controller.yaml 的新文件中,并将该文件保存到本地计算机。

    apiVersion: approuting.kubernetes.azure.com/v1alpha1
    kind: NginxIngressController
    metadata:
      name: nginx-public
    spec:
      ingressClassName: nginx-public
      controllerNamePrefix: nginx-public
    
  2. 使用 kubectl apply 命令创建 NGINX 入口控制器资源。

    kubectl apply -f nginx-public-controller.yaml
    

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

    nginxingresscontroller.approuting.kubernetes.azure.com/nginx-public created
    

创建具有专用 IP 地址的内部 NGINX 入口控制器

若要创建具有面向内部的 Azure 负载均衡器(使用专用 IP 地址)的 NGINX 入口控制器,请执行以下操作:

  1. 将以下 YAML 清单复制到名为 nginx-internal-controller.yaml 的新文件中,并将该文件保存到本地计算机。

    apiVersion: approuting.kubernetes.azure.com/v1alpha1
    kind: NginxIngressController
    metadata:
      name: nginx-internal
    spec:
      ingressClassName: nginx-internal
      controllerNamePrefix: nginx-internal
      loadBalancerAnnotations: 
        service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    
  2. 使用 kubectl apply 命令创建 NGINX 入口控制器资源。

    kubectl apply -f nginx-internal-controller.yaml
    

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

    nginxingresscontroller.approuting.kubernetes.azure.com/nginx-internal created
    

创建具有静态 IP 地址的 NGINX 入口控制器

若要创建 Azure 负载均衡器使用静态 IP 地址的 NGINX 入口控制器,请执行以下操作:

  1. 使用 az group create 命令创建 Azure 资源组。

    az group create --name myNetworkResourceGroup --location chinanorth3
    
  2. 使用命令“az network public ip create”创建静态公共 IP 地址。

    az network public-ip create \
        --resource-group myNetworkResourceGroup \
        --name myIngressPublicIP \
        --sku Standard \
        --allocation-method static
    

    注意

    如果在 AKS 群集中使用了“基本”SKU 负载平衡器,请在定义公共 IP 时为 --sku 参数使用值 Basic基本 SKU IP 兼容基本 SKU 负载均衡器,仅标准 SKU IP 兼容标准 SKU 负载均衡器。

  3. 使用 az role assignment create 命令确保 AKS 群集使用的群集标识已将权限委托给公共 IP 的资源组。

    注意

    <ClusterName><ClusterResourceGroup> 更新为你的 AKS 群集的名称和资源组名称。

    CLIENT_ID=$(az aks show --name <ClusterName> --resource-group <ClusterResourceGroup> --query identity.principalId -o tsv)
    RG_SCOPE=$(az group show --name myNetworkResourceGroup --query id -o tsv)
    az role assignment create \
        --assignee ${CLIENT_ID} \
        --role "Network Contributor" \
        --scope ${RG_SCOPE}
    
  4. 将以下 YAML 清单复制到名为 nginx-staticip-controller.yaml 的新文件中,并将该文件保存到本地计算机。

    注意

    可以将 service.beta.kubernetes.io/azure-pip-name 用于公共 IP 名称,或将 service.beta.kubernetes.io/azure-load-balancer-ipv4 用于 IPv4 地址并将 service.beta.kubernetes.io/azure-load-balancer-ipv6 用于 IPv6 地址,如示例 YAML 中所示。 添加 service.beta.kubernetes.io/azure-pip-name 批注可确保创建最有效的 LoadBalancer,强烈建议避免潜在的限制。

    apiVersion: approuting.kubernetes.azure.com/v1alpha1
    kind: NginxIngressController
    metadata:
      name: nginx-static
    spec:
      ingressClassName: nginx-static
      controllerNamePrefix: nginx-static
      loadBalancerAnnotations: 
        service.beta.kubernetes.io/azure-pip-name: "myIngressPublicIP"
        service.beta.kubernetes.io/azure-load-balancer-resource-group: "myNetworkResourceGroup"
    
  5. 使用 kubectl apply 命令创建 NGINX 入口控制器资源。

    kubectl apply -f nginx-staticip-controller.yaml
    

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

    nginxingresscontroller.approuting.kubernetes.azure.com/nginx-static created
    

验证是否已创建入口控制器

可以使用 kubectl get nginxingresscontroller 命令验证 NGINX 入口控制器的状态。

注意

<IngressControllerName> 替换为你创建 NginxIngressController 时使用的名称。

kubectl get nginxingresscontroller -n <IngressControllerName>

以下示例输出显示了创建的资源。 控制器可能需要几分钟时间才可用:

NAME           INGRESSCLASS   CONTROLLERNAMEPREFIX   AVAILABLE
nginx-public   nginx-public   nginx                  True

你还可以查看情况来排查任何问题:

kubectl get nginxingresscontroller -n <IngressControllerName> -o jsonpath='{range .items[*].status.conditions[*]}{.lastTransitionTime}{"\t"}{.status}{"\t"}{.type}{"\t"}{.message}{"\n"}{end}'

以下示例输出显示了正常入口控制器的情况:

2023-11-29T19:59:24Z    True    IngressClassReady       Ingress Class is up-to-date
2023-11-29T19:59:50Z    True    Available               Controller Deployment has minimum availability and IngressClass is up-to-date
2023-11-29T19:59:50Z    True    ControllerAvailable     Controller Deployment is available
2023-11-29T19:59:25Z    True    Progressing             Controller Deployment has successfully progressed

在入口中使用入口控制器

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

    注意

    <Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: aks-helloworld
      namespace: hello-web-app-routing
    spec:
      ingressClassName: <IngressClassName>
      rules:
      - host: <Hostname>
        http:
          paths:
          - backend:
              service:
                name: aks-helloworld
                port:
                  number: 80
            path: /
            pathType: Prefix
    
  2. 使用 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

以下示例输出显示了创建的托管入口。 入口类、主机和 IP 地址可能有所不同:

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

入口控制器的清理

你可以使用 kubectl delete nginxingresscontroller 命令移除 NGINX 入口控制器。

注意

<IngressControllerName> 替换为你创建 NginxIngressController 时使用的名称。

kubectl delete nginxingresscontroller -n <IngressControllerName>

通过注释进行每个入口资源的配置

NGINX 入口控制器支持向特定入口对象添加注释以自定义其行为。

可以通过在 metadata.annotations 字段中添加相应的注释来注释入口对象。

注意

注释键和值只能是字符串。 其他类型(例如布尔值或数值)必须括在引号中,即 "true""false""100"

下面是对常见配置的一些示例注释。 请查看 NGINX 入口注释文档来获取完整列表。

自定义最大正文大小

对于 NGINX,当请求中的大小超过允许的客户端请求正文最大大小时,将向客户端返回 413 错误。 要替代默认值,请使用以下注释:

nginx.ingress.kubernetes.io/proxy-body-size: 4m

下面是使用此注释的示例入口配置:

注意

<Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  namespace: hello-web-app-routing
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 4m
spec:
  ingressClassName: <IngressClassName>
  rules:
  - host: <Hostname>
    http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix

自定义连接超时

你可以更改 NGINX 入口控制器在关闭与你的工作负载的连接时等待的超时时间。 所有超时值都是无单位的,以秒为单位。 若要替代默认超时,请使用以下注释设置有效的 120 秒代理读取超时:

nginx.ingress.kubernetes.io/proxy-read-timeout: "120"

请查看自定义超时来了解其他配置选项。

下面是使用此注释的示例入口配置:

注意

<Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  namespace: hello-web-app-routing
  annotations:
    nginx.ingress.kubernetes.io/proxy-read-timeout: "120"
spec:
  ingressClassName: <IngressClassName>
  rules:
  - host: <Hostname>
    http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix

后端协议

默认情况下,NGINX 入口控制器使用 HTTP 来访问服务。 若要配置备用后端协议(例如 HTTPSGRPC),请使用以下注释:

nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

nginx.ingress.kubernetes.io/backend-protocol: "GRPC"

请查看后端协议来了解其他配置选项。

下面是使用此注释的示例入口配置:

注意

<Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  namespace: hello-web-app-routing
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: <IngressClassName>
  rules:
  - host: <Hostname>
    http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix

跨源资源共享 (CORS)

若要在入口规则中启用跨来源资源共享 (CORS),请使用以下注释:

nginx.ingress.kubernetes.io/enable-cors: "true"

请查看启用 CORS 来了解其他配置选项。

下面是使用此注释的示例入口配置:

注意

<Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  namespace: hello-web-app-routing
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
spec:
  ingressClassName: <IngressClassName>
  rules:
  - host: <Hostname>
    http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix

禁用 SSL 重定向

默认情况下,如果为入口启用了 TLS,则控制器会将 (308) 重定向到 HTTPS。 若要为特定入口资源禁用此功能,请使用以下注释:

nginx.ingress.kubernetes.io/ssl-redirect: "false"

请查看通过重定向在服务器端强制实施 HTTPS 来了解其他配置选项。

下面是使用此注释的示例入口配置:

注意

<Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  namespace: hello-web-app-routing
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  ingressClassName: <IngressClassName>
  rules:
  - host: <Hostname>
    http:
      paths:
      - backend:
          service:
            name: aks-helloworld
            port:
              number: 80
        path: /
        pathType: Prefix

URL 重写

在某些情况下,后端服务中公开的 URL 不同于入口规则中的指定路径。 如果没有重写,则任何请求都将返回 404。 此配置对于基于路径的路由很有用,在该路由类型中,可以在同一域下为两个不同的 Web 应用程序提供服务。 可以使用以下注释设置服务预期的路径:

nginx.ingress.kubernetes.io/rewrite-target": /$2

下面是使用此注释的示例入口配置:

注意

<Hostname> 更新为你的 DNS 主机名。 <IngressClassName> 是你在创建 NginxIngressController 时定义的那个。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aks-helloworld
  namespace: hello-web-app-routing
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: <IngressClassName>
  rules:
  - host: <Hostname>
    http:
      paths:
      - path: /app-one(/|$)(.*)
        pathType: Prefix 
        backend:
          service:
            name: app-one
            port:
              number: 80
      - path: /app-two(/|$)(.*)
        pathType: Prefix 
        backend:
          service:
            name: app-two
            port:
              number: 80