GKE Nginx Ingress Controller 前面的全局负载均衡器(HTTPS 负载均衡器)

Mau*_*cio 8 nginx google-kubernetes-engine nginx-ingress google-cloud-armor gke-networking

我有一个 GKE 集群,它使用 Nginx Ingress Controller 作为其入口引擎。目前,当我设置 Nginx Ingress Controller 时,我定义了一项服务kind: LoadBalancer并将其指向先前在 GCP 上保留的外部静态 IP。问题是它只绑定到区域静态 IP 地址(如果我没记错的话,是 L4 负载均衡器)。我想要一个全局负载均衡器。

我知道我可以通过使用 GKE 入口控制器而不是 Nginx 入口控制器来实现这一点。但我仍然想使用 Nginx Ingress,因为它具有强大的注释功能,例如根据条件重写标头等;GKE Ingress 注释不可用的内容。

最后,有没有办法将全局负载均衡器与 nginx 入口控制器结合起来,或者将全局负载均衡器放在 Nginx 创建的 L4 负载均衡器前面?

我们需要有全局负载均衡器才能受到 Cloud Armor 的保护。

Mau*_*cio 7

我终于成功地让 Nginx Ingress Controller 和 L7 HTTP(S) 负载均衡器一起工作。

根据@rrob 的回复和他自己的问题,我设法让它发挥作用。唯一的区别是他的解决方案将安装经典的 HTTP(S) LoadBalancer,而不是新版本,并且我还介绍了 IP 地址的创建、自签名证书以及从 HTTP 到 HTTPS 的 HTTP 代理重定向。我将在这里列出对我有用的详细步骤。

此步骤假设我们已经创建了一个VPC-native traffic routing启用的集群。

在需要HTTP(S) LoadBalancer之前,我只需应用 Nginx DOCS 页面提供的清单来安装 Nginx Ingress Controller,它将创建一个类型的服务LoadBalancer,然后自动创建一个区域 L4 LoadBalancer 。

但现在我需要有Cloud Armor和WAF,L4负载均衡器不支持它。Cloud Armor 需要 HTTPS(S) 负载均衡器才能正常工作。

为了让Nginx Ingress 控制器与新的HTTPS(S) LoadBalancer一起工作,我们需要将Nginx Ingress Controller服务type: LoadBalancer上的 改为,并向其添加NEG注释。通过此网络注释,GCP 将自动创建一个网络端点组,该组将指向在 GKE 中运行的 Nginx Ingress Controller 服务。该网络端点组将作为我们的 HTTPS 负载均衡器的后端。ClusterIPcloud.google.com/neg: '{"exposed_ports": {"80":{"name": "ingress-nginx-80-neg"}}}'

注意:使用cloud.google.com/neg注释时,GCP 将为包含带有Nginx Ingress Controller pod的节点的每个区域创建一个网络端点组。例如,如果您将 NodePool 设置为分布在us-central1-aus-central1-bus-central1-f上,并且每个节点中都有一个入口控制器副本,则 GCP 将创建三个网络端点组。因此,当您设置负载均衡器的后端时,您需要将它们全部添加为后端,如步骤 5 中所述。

apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    helm.sh/chart: ingress-nginx-4.0.15
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 1.1.1
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "ingress-nginx-80-neg"}}}'
spec:
  type: ClusterIP
  ipFamilyPolicy: SingleStack
  ipFamilies:
    - IPv4
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
      appProtocol: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
      appProtocol: https
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller
Run Code Online (Sandbox Code Playgroud)

如果您使用 HELM 安装 Nginx Ingress Controller,则需要覆盖配置以将 NEG 注释添加到服务中。所以values.yaml看起来像这样:

controller:
  service:
    type: ClusterIP
    annotations:
      cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "ingress-nginx-80-neg"}}}'
Run Code Online (Sandbox Code Playgroud)

要安装它,请将 ingress-nginx 添加到 helm 存储库:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
Run Code Online (Sandbox Code Playgroud)

然后安装它:

helm install -f values.yaml ingress-nginx ingress-nginx/ingress-nginx
Run Code Online (Sandbox Code Playgroud)

接下来的步骤将是:

PROJECT_ID=<project-id>
ZONE=us-central1-a
CLUSTER_NAME=<cluster-name>
HEALTH_CHECK_NAME=nginx-ingress-controller-health-check
NETWORK_NAME=<network-name>
CERTIFICATE_NAME=self-managed-exp-<day>-<month>-<year>
GKE_NODE_METADATA=$(kubectl get nodes -o jsonpath='{.items[0].metadata}')
GKE_SAMPLE_NODE_NAME=$(echo $GKE_NODE_METADATA | jq -r .name)
GKE_SAMPLE_NODE_ZONE=$(echo $GKE_NODE_METADATA | jq -r .labels | jq -r '."topology.kubernetes.io/zone"')
NETWORK_TAGS=$(gcloud compute instances describe \
    $GKE_SAMPLE_NODE_NAME --project $PROJECT_ID \
    --zone=$GKE_SAMPLE_NODE_ZONE --format="value(tags.items[0])")
Run Code Online (Sandbox Code Playgroud)
  1. 创建静态 IP 地址(如果已有,请跳过):

必须是高级级别和全球级别

gcloud compute addresses create ${CLUSTER_NAME}-loadbalancer-ip \
    --global \
    --ip-version IPV4
Run Code Online (Sandbox Code Playgroud)
  1. 创建防火墙规则,允许 L7 HTTP(S) 负载均衡器访问我们的集群
gcloud compute firewall-rules create ${CLUSTER_NAME}-allow-tcp-loadbalancer \
    --allow tcp:80 \
    --source-ranges 130.211.0.0/22,35.191.0.0/16 \
    --target-tags $NETWORK_TAGS \
    --network $NETWORK_NAME
Run Code Online (Sandbox Code Playgroud)
  1. 为我们即将创建的后端服务创建健康检查
gcloud compute health-checks create http ${CLUSTER_NAME}-nginx-health-check \
  --port 80 \
  --check-interval 60 \
  --unhealthy-threshold 3 \
  --healthy-threshold 1 \
  --timeout 5 \
  --request-path /healthz
Run Code Online (Sandbox Code Playgroud)
  1. 创建一个后端服务,用于通知 LoadBalancer 如何连接 Pod 并将流量分配给 Pod。
gcloud compute backend-services create ${CLUSTER_NAME}-backend-service \
    --load-balancing-scheme=EXTERNAL \
    --protocol=HTTP \
    --port-name=http \
    --health-checks=${CLUSTER_NAME}-nginx-health-check \
    --global
Run Code Online (Sandbox Code Playgroud)
  1. 现在是时候将 Nginx NEG 服务(前面注释的那个)添加到上一步中创建的后端服务中了:

如前所述,将为包含 Nginx Ingress Controller Pod 的每个区域创建一个网络端点组。所以我的设置的当前布局是:

a. **Node Pool** configured to span across **us-central1-a** and **us-central1-c**.
b. **Nginx Ingress Controller** configured to have 4 replicas.
c. **Node 1** in **us-central1-a** will have 2 replicas.
d. **Node 2** in **us-central1-c** will have 2 replicas.
e. GCP generated two Network Endpoint Groups. One for **us-central1-a** and other for **us-central1-c**.
Run Code Online (Sandbox Code Playgroud)

因此,对于下面的示例,我为每个区域绑定两个 NEG,作为负载均衡器的后端服务。

# us-central1-a
gcloud compute backend-services add-backend ${CLUSTER_NAME}-backend-service \
  --network-endpoint-group=ingress-nginx-80-neg \
  --network-endpoint-group-zone=us-central1-a \
  --balancing-mode=RATE \
  --capacity-scaler=1.0 \
  --max-rate-per-endpoint=100 \
  --global

# us-central1-c
gcloud compute backend-services add-backend ${CLUSTER_NAME}-backend-service \
  --network-endpoint-group=ingress-nginx-80-neg \
  --network-endpoint-group-zone=us-central1-c \
  --balancing-mode=RATE \
  --capacity-scaler=1.0 \
  --max-rate-per-endpoint=100 \
  --global
  
Run Code Online (Sandbox Code Playgroud)
  1. 创建负载均衡器本身(URL MAPS)
gcloud compute url-maps create ${CLUSTER_NAME}-loadbalancer \
    --default-service ${CLUSTER_NAME}-backend-service

Run Code Online (Sandbox Code Playgroud)
  1. 创建自我管理证书(可能是 Google 管理的证书,但这里我们将介绍自我管理的证书)。也可以从控制台创建
gcloud compute ssl-certificates create $CERTIFICATE_NAME \
    --certificate=my-cert.pem \
    --private-key=my-privkey.pem \
    --global
Run Code Online (Sandbox Code Playgroud)

最后,我将通过控制台界面设置负载均衡器前端,这要容易得多。

  1. 要创建 LoadBalancer 前端,请在控制台上输入 Loadbalancer,然后单击“编辑”。

  2. 前端配置选项卡将不完整。去那里图像

  3. 点击“添加前端IP和端口”

  4. 为其命名并在“协议”字段中选择“HTTPS” 。

  5. IP 地址从临时 IP更改为之前分配的静态 IP

  6. 选择您的证书并标记启用 HTTP 到 HTTPS 重定向(如果需要)。(我做到了)图像

  7. 保存负载均衡器。进入 LoadBalancer 页面时,我们应该看到我们的 nginx 实例健康且绿色。就我而言,我已将 Nginx Ingress Controller 设置为具有 4 个副本: 图像

最后,我们只需将我们的域指向 LoadBalancer IP 并创建我们的 Ingress 文件。

注意:Ingress 现在不会处理证书。该证书现在将由 LoadBalancer 在外部进行管理。所以 Ingress 不会有tls定义:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/upstream-fail-timeout: "1200"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      set $http_origin "${scheme}://${host}";
      more_set_headers "server: hide";
      more_set_headers "X-Content-Type-Options: nosniff";
      more_set_headers "Referrer-Policy: strict-origin";
  name: ingress-nginx
  namespace: prod

spec:
  rules:
  - host: app.mydomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80
Run Code Online (Sandbox Code Playgroud)