sam*_*ght 6 docker google-cloud-platform kubernetes google-kubernetes-engine gke-networking
我在运行最新版本 Kubernetes ( ) 的 GKE Autopilot 集群上使用 GKE 设置了一个(非常)简单的部署1.18.15-gke.1501,并附加了一个链接到简单ClusterIP服务的入口(外部 HTTP(s) 负载均衡器)。
每当我使用新映像更新部署时,我都会遇到大约 5-15 分钟的停机时间,其中负载均衡器返回 502 错误。看起来控制平面创建了新的、更新的 Pod,允许进行服务级别运行状况检查(不是负载均衡器的健康检查,它还没有创建 NEG),然后同时杀死旧的 Pod是时候设置新的 NEG 了。然后,直到一段可变的时间后,它才会删除旧的 NEG。
Pod 上的日志显示运行状况检查正在进行,但 GKE 仪表板显示 Ingress 状态的结果不一致。入口将显示正常,但服务将显示 502。
maxSurge为 1 和maxUnavailable0。这根本没有改善停机时间。lifecycle.preStop.exec.command: ["sleep", "60"]到部署上的容器。这是 GKE 文档中建议的。BackendConfig在服务中添加一个会增加其消耗速度。上述任何一项都没有帮助或对事情的持续时间产生任何明显的影响。
我真的非常困惑为什么这不起作用。感觉就像我错过了一些非常明显的东西,但这也是一个如此简单的配置,你会认为它......只是工作?有人知道发生了什么事吗?
部署配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: foundation-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: foundation-web
template:
metadata:
labels:
app: foundation-web
spec:
readinessGates:
- conditionType: "cloud.google.com/load-balancer-neg-ready"
serviceAccountName: foundation-database-account
containers:
# Run Cloud SQL proxy so we can safely connect to Postgres on localhost.
- name: cloud-sql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.17
resources:
requests:
cpu: "250m"
memory: 100Mi
limits:
cpu: "500m"
memory: 100Mi
command:
- "/cloud_sql_proxy"
- "-instances=nine-foundation:us-central1:foundation-staging=tcp:5432"
securityContext:
runAsNonRoot: true
# Main container config
- name: foundation-web
image: gcr.io/project-name/foundation_web:latest
imagePullPolicy: Always
lifecycle:
preStop:
exec:
command: ["sleep", "60"]
env:
# Env variables
resources:
requests:
memory: "500Mi"
cpu: "500m"
limits:
memory: "1000Mi"
cpu: "1"
livenessProbe:
httpGet:
path: /healthz
port: 4000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
port: 4000
initialDelaySeconds: 10
periodSeconds: 10
ports:
- containerPort: 4000
Run Code Online (Sandbox Code Playgroud)
服务配置:
apiVersion: v1
kind: Service
metadata:
name: foundation-web-service
annotations:
cloud.google.com/neg: '{"ingress": true}'
cloud.google.com/backend-config: '{"ports": {"4000": "foundation-service-config"}}'
spec:
type: ClusterIP
selector:
app: foundation-web
ports:
- port: 4000
targetPort: 4000
Run Code Online (Sandbox Code Playgroud)
后端配置:
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: foundation-service-config
spec:
# sessionAffinity:
# affinityType: "GENERATED_COOKIE"
# affinityCookieTtlSec: 120
connectionDraining:
drainingTimeoutSec: 60
Run Code Online (Sandbox Code Playgroud)
入口配置:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: foundation-web-ingress
labels:
name: foundation-web-ingress
spec:
backend:
serviceName: foundation-web-service
servicePort: 4000
Run Code Online (Sandbox Code Playgroud)
我认为这可能与云 sql 身份验证代理 sidecar 未正确终止有关,导致负载均衡器陷入困境。
请注意GCP 文档中的这一点(我已将关键部分设为斜体)
症状
502 错误或拒绝连接。潜在原因 新端点通常在连接到负载均衡器后变得可访问,前提是它们响应运行状况检查。如果流量无法到达端点,您可能会遇到 502 错误或拒绝连接。
502 错误和拒绝连接也可能是由不处理 SIGTERM 的容器引起的。如果容器没有显式处理 SIGTERM,它会立即终止并停止处理请求。负载均衡器继续将传入流量发送到已终止的容器,从而导致错误。
容器本机负载均衡器只有一个后端端点。在滚动更新期间,旧端点在新端点编程之前被取消编程。
配置容器本机负载均衡器后,后端 Pod 首次部署到新区域中。当区域中至少有一个端点时,负载均衡器基础设施就在该区域中进行编程。当新端点添加到区域时,负载均衡器基础设施将被编程并导致服务中断。
解决
配置容器以处理 SIGTERM 并在整个终止宽限期内(默认为 30 秒)继续响应请求。将 Pod 配置为在收到 SIGTERM 时开始失败运行状况检查。这会指示负载均衡器在端点取消编程过程中停止向 Pod 发送流量。
默认情况下,代理不能很好地处理 SIGTERM,并且不会在 SIGTERM 上正常退出(请参阅相关问题),但是它现在有一个很好的标志来处理此问题,因此您可以使用类似的东西
- name: cloud-sql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.23.1
command:
- "/cloud_sql_proxy"
- "-instances={{ .Values.postgresConnectionName }}=tcp:5432"
- "-term_timeout=60s"
securityContext:
runAsNonRoot: true
resources:
requests:
memory: "2Gi"
cpu: "1"
Run Code Online (Sandbox Code Playgroud)
添加 term_timeout 标志主要是为我解决了这个问题,但在部署期间仍然偶尔会看到 502。一旦我设置了 term_timeout,将副本增加到 3 个(我的集群是区域性的,所以我想覆盖所有区域)似乎有所帮助。
| 归档时间: |
|
| 查看次数: |
1867 次 |
| 最近记录: |