利用应用程序路由加载项实现高级 NGINX Ingress 控制器和 Ingress 配置,适用于 Azure Kubernetes 服务 (AKS)

注意

Kubernetes SIG Network和安全响应委员会宣布即将停用Ingress NGINX项目, 维护将于2026年3月结束。 目前,使用 NGINX 的应用程序路由加载项的 AKS 群集无需立即执行任何操作。 Microsoft将为应用程序路由加载项的NGINX Ingress资源的重要安全补丁提供正式支持,支持截止至2026年11月。

AKS 正在迁移到 网关 API,这将作为入口和 L7 流量管理的长期标准,以便与上游 Kubernetes 社区保持一致。 建议根据当前设置开始规划迁移路径:

本文介绍如何使用应用程序路由加载项为 Azure Kubernetes 服务 (AKS) 配置 Ingress 控制器和 Ingress 对象的两种方法:

先决条件

连接到 AKS 群集

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

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

    az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
    

NGINX 入口控制器的配置属性

应用程序路由加载项使用 Kubernetes 自定义资源定义(CRD)(名为 NginxIngressController)来配置 NGINX 入口控制器。 可以创建更多入口控制器或修改现有配置。

下表列出了用于配置NginxIngressController的属性:

领域 类型 说明 必选 违约
controllerNamePrefix 字符串 托管 NGINX 入口控制器资源的名称。 是的 nginx
customHTTPErrors 数组 出现错误时,将错误代码数组发送到默认后端。
defaultBackendService 对象 用于路由不匹配的 HTTP 流量的服务。 包含嵌套属性:
name 字符串 服务名称。 是的
namespace 字符串 服务命名空间。 是的
defaultSSLCertificate 对象 包含用于访问默认后端服务的默认证书。 包含嵌套属性:
forceSSLRedirect 布尔 设置证书时强制 HTTPS 重定向。 false
keyVaultURI 字符串 用于存储证书的 密钥保管库 机密的 URI。
secret 对象 保存默认 SSL 证书的机密信息。 包含嵌套属性:
  name 字符串 机密名称。 是的
  namespace 字符串 机密命名空间。 是的
httpDisabled 布尔 用于禁用到控制器的 HTTP 流量的标志。
ingressClassName 字符串 控制器使用的 IngressClass 名称。 是的 nginx.approuting.kubernetes.azure.com
loadBalancerAnnotations 对象 通过设置与负载均衡器相关的注解来控制NGINX入口控制器服务的行为。
scaling 对象 用于缩放控制器的配置。 包含嵌套属性:
maxReplicas 整数 副本上限。 100
minReplicas 整数 副本的下限。 2
threshold 字符串 用于定义缩放积极程度的缩放阈值。 rapid 应对突发高峰快速扩展,steady 注重成本效益,balanced 是一种混合模式。 balanced

控制默认 NGINX 入口控制器配置

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

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

可能的配置选项包括:

  • None:未创建默认 NGINX 入口控制器,如果已存在,则不会将其删除。 如果需要,应手动删除默认 NginxIngressController 自定义资源。
  • Internal:默认的 NGINX Ingress 控制器是使用内部负载均衡器创建的。 任何为了使自定义资源NginxIngressController可外部访问的批注更改都会被覆盖。
  • External:由外部负载均衡器创建的默认 NGINX Ingress 控制器。 任何在 NginxIngressController 自定义资源上为使其变为内部资源而进行的注释更改都会被覆盖。
  • AnnotationControlled (默认值):默认的 NGINX 入口控制器是使用外部负载均衡器创建的。 可以编辑默认的NginxIngressController自定义资源以配置负载均衡器的注解。

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

  • 使用带有 az aks create--enable-app-routing 标志的 --app-routing-default-nginx-controller 命令在新群集上启用应用程序路由。 需要将<DefaultIngressControllerType>设置为《控制默认 NGINX Ingress 控制器配置》中所述的配置选项之一。

    az aks create \
      --resource-group $RESOURCE_GROUP \
      --name $CLUSTER_NAME \
      --location $LOCATION \
      --enable-app-routing \
      --app-routing-default-nginx-controller <DefaultIngressControllerType>
    

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

  • 在现有群集上使用 az aks approuting update 命令和 --nginx 标志更新应用程序路由的默认入口控制器配置。 需要将<DefaultIngressControllerType>设置为《控制默认 NGINX Ingress 控制器配置》中所述的配置选项之一。

    az aks approuting update \
      --resource-group $RESOURCE_GROUP \
      --name $CLUSTER_NAME \
      --nginx <DefaultIngressControllerType>
    

创建另一个面向公众的 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 入口控制器

  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 入口控制器

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

    az group create --name $NETWORK_RESOURCE_GROUP --location $LOCATION
    
  2. 使用 az network public ip create 命令创建静态公共 IP 地址。

    az network public-ip create \
      --resource-group $NETWORK_RESOURCE_GROUP \
      --name $PUBLIC_IP_NAME \
      --sku Standard \
      --allocation-method static
    

    注意事项

    如果在 AKS 群集中使用 Basic SKU load balancer,请在定义公共 IP 时对 Basic 参数使用 --sku。 只有 Basic SKU IP 适用于 Basic SKU load balancer,并且只有 Standard SKU IP 与 Standard SKU 负载均衡器配合使用。

  3. 确保 AKS 群集使用的群集标识通过 az role assignment create 命令将委托权限授予公共 IP 所属的资源组。

    CLIENT_ID=$(az aks show --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --query identity.principalId -o tsv)
    RG_SCOPE=$(az group show --name $NETWORK_RESOURCE_GROUP --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 名称,也可以对 IPv4 地址使用 service.beta.kubernetes.io/azure-load-balancer-ipv4,对 IPv6 地址使用 service.beta.kubernetes.io/azure-load-balancer-ipv6,如示例 YAML 所示。 添加 service.beta.kubernetes.io/azure-pip-name 批注可确保以最高效率创建 负载均衡器,并强烈建议这样做以避免潜在的限流。

    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: "$PUBLIC_IP_NAME"
        service.beta.kubernetes.io/azure-load-balancer-resource-group: "$NETWORK_RESOURCE_GROUP"
    
  5. 使用 kubectl apply 命令创建 NGINX 入口控制器资源。

    kubectl apply -f nginx-staticip-controller.yaml
    

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

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

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

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

    kubectl get nginxingresscontroller --name $INGRESS_CONTROLLER_NAME
    

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

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

查看入口控制器的条件

  • 查看入口控制器的条件,以使用 kubectl get nginxingresscontroller 命令排查任何问题。

    kubectl get nginxingresscontroller --name $INGRESS_CONTROLLER_NAME -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 --namespace hello-web-app-routing
    

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

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

验证是否已创建托管入口

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

    kubectl get ingress --namespace 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
    

删除入口控制器

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

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,请使用以下注释之一:

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

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

查看 backend 协议以获取其他配置选项。

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

注意事项

<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"

查看 enable 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。 此配置适用于基于 path 的路由,可以在同一域中为两个不同的 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

NGINX 运行状况探测路径更新

与 NGINX 入口控制器关联的Azure 负载均衡器的默认运行状况探测路径必须设置为 "/healthz"。 若要确保进行正确的健康检查,请验证入口控制器服务是否具有以下注解:

metadata:
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: "/healthz"

如果您使用 Helm 来管理 NGINX 入口控制器,可以在 “values” 文件中定义 Azure 负载均衡器 的运行状况探测注释,并在升级期间应用该注释:

controller:
  service:
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: "/healthz"

此配置有助于维护服务可用性,并避免升级期间出现意外流量中断。