我终于成功地让 Nginx Ingress Controller 和 L7 HTTP(S) 负载均衡器一起工作。
根据 @rrob 的回复和他自己的问题,我设法让它发挥作用。唯一的区别是他的解决方案将安装经典的 HTTP(S) LoadBalancer,而不是新版本,并且我还介绍了 IP 地址的创建、自签名证书以及从 HTTP 到 HTTPS 的 HTTP 代理重定向。我将在这里列出对我有用的详细步骤。
此步骤假设我们已经创建了一个集群VPC-native traffic routing
已启用。
在需要之前HTTP(S) 负载均衡器,我只需应用 Nginx DOCS 页面提供的清单来安装 Nginx Ingress Controller,它将创建一个类型的服务LoadBalancer
然后,这将自动创建一个区域 L4 LoadBalancer。
但现在我需要有Cloud Armor和WAF,L4负载均衡器不支持它。 Cloud Armor 需要 HTTPS(S) 负载均衡器才能正常工作。
为了有Nginx 入口控制器与新人合作HTTPS(S) 负载均衡器我们需要改变type: LoadBalancer
on the Nginx 入口控制器服务于ClusterIP
相反,并添加NEG对其进行注释cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "ingress-nginx-80-neg"}}}'
。有了这个net注解,GCP 将自动创建一个网络端点组,该组将指向在 GKE 中运行的 Nginx Ingress Controller 服务。该网络端点组将作为我们的 HTTPS 负载均衡器的后端。
注意:使用时cloud.google.com/neg注释,GCP 将创建一个网络端点组对于每个region包含节点Nginx Ingress 控制器 Pod。例如,如果您将节点池设置为分布在美国中央1-a, 美国中央1-b and us-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
如果您使用 HELM 安装 Nginx Ingress Controller,则需要覆盖配置以将 NEG 注释添加到服务中。所以values.yaml
看起来像这样:
controller:
service:
type: ClusterIP
annotations:
cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "ingress-nginx-80-neg"}}}'
要安装它,请将 ingress-nginx 添加到 helm 存储库:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
然后安装它:
helm install -f values.yaml ingress-nginx ingress-nginx/ingress-nginx
接下来的步骤将是:
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])")
- 创建静态 IP 地址(如果已有,请跳过):
必须Premium层级和全球
gcloud compute addresses create ${CLUSTER_NAME}-loadbalancer-ip \
--global \
--ip-version IPV4
- 创建防火墙规则,允许 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
- 为我们即将创建的后端服务创建健康检查
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
- 创建一个后端服务,用于通知负载均衡器如何连接 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
- 现在是时候将 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**.
因此,对于下面的示例,我为每个区域绑定两个 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
- 创建负载均衡器本身(URL MAPS)
gcloud compute url-maps create ${CLUSTER_NAME}-loadbalancer \
--default-service ${CLUSTER_NAME}-backend-service
- 创建自我管理证书(可能是 Google 管理的证书,但这里我们将介绍自我管理的证书)。也可以从控制台创建HERE.
gcloud compute ssl-certificates create $CERTIFICATE_NAME \
--certificate=my-cert.pem \
--private-key=my-privkey.pem \
--global
最后,我将通过控制台界面设置负载均衡器前端,这要容易得多。
-
要创建 LoadBalancer 前端,请在控制台上输入 Loadbalancer,然后单击“编辑”。
-
The Frontend configuration tab will be incomplete. Go there
-
点击“添加前端IP和端口”
-
为其命名并选择HTTPS现场协议。
-
On IP地址改变自短暂的到您之前分配的静态IP
-
Select your certificate and mark Enable HTTP to HTTPS redirect if you want. (I did)
-
Save the LoadBalancer.
The entering the LoadBalancer page we should see our nginx instance(s) healthy and green. In my case I've setup the Nginx Ingress Controller to have 4 replicas:
最后,我们只需将我们的域指向 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