我在运行最新版本 Kubernetes ( 1.18.15-gke.1501
) 的 GKE Autopilot 集群上使用 GKE 设置了一个(非常)简单的部署,并附加了一个链接到简单 ClusterIP
的入口(外部 HTTP(s) 负载均衡器)。服务。
每当我使用新镜像更新部署时,我都会遇到大约 5-15 分钟的停机时间,此时负载均衡器会返回 502 错误。似乎控制平面创建了新的、更新的 pod,允许通过服务级别的健康检查(不是负载均衡器,它尚未创建 NEG),然后同时杀死旧的 pod是时候设置新 NEG 了。然后它不会删除旧的 NEG,直到一段时间后。
Pod 上的日志显示运行状况检查正在通过,但 GKE 仪表板显示 Ingress 状态的结果不一致。入口将显示为正常,但服务将显示 502。
我尝试过的事情
maxSurge
到 1 和 maxUnavailable
到 0。这根本没有改善停机时间。 lifecycle.preStop.exec.command: ["sleep", "60"]
到部署上的容器。 This was suggested in the GKE docs here. 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
服务配置: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
后端配置:apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: foundation-service-config
spec:
# sessionAffinity:
# affinityType: "GENERATED_COOKIE"
# affinityCookieTtlSec: 120
connectionDraining:
drainingTimeoutSec: 60
入口配置: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
最佳答案
您的 Autopilot 集群在新部署期间遇到延迟的原因是集群的主节点正在进行更新。每次用户在集群上部署时,GKE Autopilot 系统都会更新主节点。
但是,为了防止在生产的关键时刻发生这种情况,您可以为此集群创建一个维护时段,以便您可以控制自动集群维护(例如自动升级)何时可以和不可以在您的 GKE Autopilot 集群上发生.
我希望这能解释这个问题。
供您引用:
Kubernetes 的就绪探测默认值为 10 分钟。这意味着,即使部署仍在进行,就绪探针也会在 10 分钟后将其标记为失败。
GKE Autopilot 在整个部署步骤(不仅仅是等待就绪状态)上设置了一个可配置的超时时间,在等待就绪状态期间,Kubernetes 会调用就绪探针来监控部署。
就绪探针基于 Kubernetes 默认值,在 10 分钟后标记部署失败。 GKE Autopilot 会看到来自就绪探测器的消息,并报告部署由于超出截止日期而失败。
作为一种可能的解决方案,可以通过以秒为单位指定“progressDeadlineSeconds”[5] 值,在您的 YAML 中扩展就绪探测默认超时。默认值为 600 秒(10 分钟)。关于它的更多细节在这里[6]。我建议尝试将其添加到您的 YAML 文件并增加超时以查看这是否能解决手头的问题。
当出现过度缩小时。我们建议客户将 minNodes 自动缩放配置值设置为等于 maxNodes。
Cluster Autoscaler 认为可以在现有节点之一上调度 pod,但调度程序表示不能。 Pod 不会被安排,也不会发生扩展。在这种情况下,我们建议创建一个新的节点池或调整支持现有节点池的 MIG 的大小作为快速缓解措施。
正如您所提到的,您多次重新创建入口、服务、部署和集群,请确保遵循以下步骤:
不完整的垃圾收集
Google Kubernetes Engine 垃圾收集器每两分钟收集一次容器原生负载均衡器。如果集群在负载均衡器完全移除之前被删除,您需要手动删除负载均衡器的 NEG。
通过运行以下命令查看项目中的 NEG:
gcloud compute network-endpoint-groups list
在命令输出中,查找相关 NEG。要删除 NEG,请运行以下命令,其中 neg 是 NEG 的名称:
gcloud compute network-endpoint-groups delete [neg]
将工作负载推出与端点传播保持一致https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
备注 :在使用 Pod 就绪反馈来管理工作负载推出的集群中不会发生此问题。有关更多信息,请参阅 Pod 准备情况。
当您将工作负载部署到集群或更新现有工作负载时,容器原生负载均衡器传播新端点所需的时间可能比完成工作负载推出所需的时间更长。您在本指南中部署的示例部署使用两个字段来使其推出与端点的传播保持一致:terminationGracePeriodSeconds 和 minReadySeconds。
TerminationGracePeriodSeconds 允许 Pod 通过在计划删除 Pod 后等待连接终止来正常关闭。
minReadySeconds 在创建 Pod 后添加一个延迟期。您指定新 Pod 应处于就绪状态的最短秒数,而其任何容器都不会崩溃,以便将 Pod 视为可用。
您应该将工作负载的 minReadySeconds 和 terminateGracePeriodSeconds 值配置为 60 秒或更高,以确保服务不会因工作负载推出而中断。
TerminationGracePeriodSeconds 适用于所有 Pod 规范,而 minReadySeconds 适用于 Deployments 和 DaemonSets。
要了解有关微调部署的更多信息,请参阅 RollingUpdateStrategy。
Pod readinessProbe 中的 initialDelaySeconds 不受尊重
您可能希望容器原生负载均衡器遵守 Pod 的 readinessProbe 中的 initialDelaySeconds 配置;但是,readinessProbe 是由 kubelet 实现的,initialDelaySeconds 配置控制 kubelet 健康检查,而不是容器原生负载均衡器。容器原生负载均衡有自己的负载均衡健康检查。
部署失败
您的 Deployment 可能会在尝试部署其最新的 ReplicaSet 而从未完成时卡住。这可能是由于以下一些因素造成的:
Insufficient quota
Readiness probe failures
Image pull errors
Insufficient permissions
Limit ranges
Application runtime misconfiguration
For more information on failed deployments please refer [4].
由于这个产品比较新,我想分享以下关于GKE Autopilot的文档以供引用:https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview
https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-architecture
https://medium.com/polarsquad/check-your-kubernetes-deployments-46dbfbc47a7c
[4]。部署失败:
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#failed-deployment
[5]。进度截止秒数:
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#progress-deadline-seconds
[6]部署:
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
关于docker - GKE Autopilot Ingress 在部署后 5-15 分钟内返回 502 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66810269/