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

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

先决条件

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

连接到 AKS 群集

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

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

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

NGINX 入口控制器的配置

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

NginxIngressController CRD 有一个 loadBalancerAnnotations 字段,该字段通过设置负载均衡器注释来控制 NGINX 入口控制器的行为。

默认 NGINX 入口控制器

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

可以通过编辑默认入口控制器的配置来修改其配置。

kubectl edit nginxingresscontroller default -n app-routing-system

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

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

  1. 将以下 YAML 清单复制到名为 ingress.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][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