控制 Kubernetes 中单个 pod 中容器终止的顺序

2024-02-09

我的一个容器内有两个容器。第一个是我的应用程序容器,第二个是 CloudSQL 代理容器。基本上我的应用程序容器依赖于这个 CloudSQL 容器。

问题是,当 pod 终止时,CloudSQL 代理容器首先终止,并且仅在几秒钟后我的应用程序容器才终止。

因此,在我的容器终止之前,它不断向 CloudSQL 容器发送请求,从而导致错误:

could not connect to server: Connection refused Is the server running on host "127.0.0.1" and accepting TCP/IP connections on port 5432

这就是为什么,我认为指定终止顺序是一个好主意,这样我的应用程序容器首先终止,然后才是 cloudsql 容器。

我在文档中找不到任何可以做到这一点的东西。但也许有某种办法。


目前使用 Kubernetes pod API 还不能直接实现这一点。容器可以按任何顺序终止。 Cloud SQL Pod 可能比您的应用程序更快消亡,例如,如果它需要执行的清理工作较少或需要消耗的正在进行的请求较少。

From Pod 的终止 https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods:

当用户请求删除 Pod 时,系统会记录允许强制杀死 Pod 之前的预期宽限期,并向每个容器中的主进程发送 TERM 信号。


您可以通过将 Cloud SQL 和主容器包装在不同的入口点中来在一定程度上解决此问题,这些入口点使用共享的 Pod 级文件系统在彼此之间传达退出状态。

此解决方案不适用于 Cloud SQL 代理 1.16 版本(看评论 https://stackoverflow.com/questions/52148322/control-order-of-container-termination-in-a-single-pod-in-kubernetes/52156131?noredirect=1#comment110296216_52156131)因为此版本不再将外壳与容器捆绑在一起。 1.17 版本是现在有 Alpine 或 Debian Buster 版本 https://console.cloud.google.com/gcr/images/cloudsql-docker/GLOBAL/gce-proxy?gcrImageListsize=30,因此该版本现在是一个可行的升级目标,再次与该解决方案兼容。

像下面这样的包装器可能会有所帮助:

containers:
- command: ["/bin/bash", "-c"]
  args:
  - |
    trap "touch /lifecycle/main-terminated" EXIT
    <your entry point goes here>
  volumeMounts:
  - name: lifecycle
    mountPath: /lifecycle
- name: cloudsql_proxy
  image: gcr.io/cloudsql-docker/gce-proxy
  command: ["/bin/bash", "-c"]
  args:
  - |
    /cloud_sql_proxy <your flags> &
    PID=$!

    function stop {
        while true; do
            if [[ -f "/lifecycle/main-terminated" ]]; then
                kill $PID
            fi
            sleep 1
        done
    }
    trap stop EXIT
    # We explicitly call stop to ensure the sidecar will terminate
    # if the main container exits outside a request from Kubernetes
    # to kill the Pod.
    stop &
    wait $PID
  volumeMounts:
  - name: lifecycle
    mountPath: /lifecycle

您还需要一个本地暂存空间来用于通信生命周期事件:

volumes:
- name: lifecycle
  emptyDir:

这个解决方案如何运作?它在 Cloud SQL 代理容器中拦截SIGTERM关闭时 Kubernetes Supervisor 向每个 Pod 容器传递的信号。该容器中运行的“主进程”是一个 shell,它生成了一个运行 Cloud SQL 代理的子进程。因此,Cloud SQL 代理不会立即终止。相反,shell 代码会阻塞等待来自主容器的已成功退出的信号(通过文件系统中出现的简单方式)。仅在此时,Cloud SQL 代理进程才会终止,并且 sidecar 容器才会返回。

当然,如果您的容器关闭时间过长并超过配置的宽限期,这对强制终止没有影响。

解决方案取决于您正在运行的容器是否有可用的 shell; Cloud SQL 代理也是如此(1.16 和 1.17 及以上版本除外,当使用alpine or debian变体),但您可能需要对本地容器构建进行更改,以确保您自己的应用程序容器也是如此。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

控制 Kubernetes 中单个 pod 中容器终止的顺序 的相关文章

  • 通过 nginx 入口控制器进行基本身份验证

    我正在使用 nginx 入口控制器 https kubernetes github io ingress nginx deploy https kubernetes github io ingress nginx deploy 在 AWS
  • 将代码/文件直接注入 Google Cloud Engine 上的 Kubernetes 容器中

    如何将代码 文件直接注入 Google Cloud Engine 上的 Kubernetes 容器中 类似于使用 Docker 挂载主机文件 目录的方式 例如 docker run d name nginx p 443 443 v ngin
  • 从头开始使用映像部署无法启动

    我正在使用以下内容构建图像Dockerfile FROM golang 1 19 2 bullseye as builder COPY src src WORKDIR src RUN CGO ENABLED 1 go build race
  • Kubernetes Pod 已终止 - 退出代码 137

    我需要一些关于 k8s 1 14 和在其上运行 gitlab 管道所面临的问题的建议 许多作业都会抛出退出代码 137 错误 我发现这意味着容器突然终止 集群信息 库伯内特版本 1 14 使用的云 AWS EKS 节点 C5 4xLarge
  • kubernetes 集群中 django 应用程序的 Nginx 配置

    我在为部署在 kubernetes 中的 django 应用程序创建 nginx 配置文件时遇到困难 Nginx 和 app 是同一集群中的两个独立容器 据我了解 容器可以通过 127 0 0 1 XX 和主机名相互通信 我为此使用 min
  • 从 celery 工作人员到普罗米修斯的自定义指标

    我有一些 celery 工作人员在 kubernetes 下的容器中运行 它们不会由 celery 自动缩放 并且每个都在单个进程中运行 即没有多处理 我想从他们那里获取一堆不同的指标到普罗米修斯中 我研究过 celery promethe
  • kubectl --token=$TOKEN 未使用令牌的权限运行

    当我使用命令时kubectl与 token标记并指定令牌 它仍然使用来自kubeconfig file 这就是我所做的 NAMESPACE default SERVICE ACCOUNT NAME sa1 kubectl create sa
  • kubectl 运行本地 docker 镜像 - ImagePullBackOff 状态

    我在本地计算机上构建 docker 映像 并尝试使用 kubectl 拉取 docker 映像 但它没有启动 docker 容器 图像以 docker 命令开头 REPOSITORY TAG IMAGE ID CREATED SIZE to
  • 如何从 Kubernetes 服务背后的 HTTP 请求读取客户端 IP 地址?

    我的 Web 应用程序作为 Kubernetes pod 在 SSL 的 nginx 反向代理后面运行 代理和我的应用程序都使用 Kubernetes 服务进行负载平衡 如所述here http blog kubernetes io 201
  • Kubernetes - 服务之间的通信

    我目前正在开发 kubernetes 集群 集群工作正常 我需要在不使用代理的情况下建立服务之间的通信 例如我有以下服务 worker app1 app2 app3 Worker 需要直接通过 SSH 登录应用程序容器并执行一些命令 在 d
  • Spring OAuth2 Keycloak Kubernetes 内部/外部访问

    我在 Kubernetes 集群内配置了 Keycloak 10 0 3 服务器 keycloak 服务器必须处理外部用户的身份验证 使用外部 url 并处理用于 Spring 微服务通信的 oauth2 令牌 然后Web应用程序Sprin
  • 如何将新的 Kubernetes Minion 添加到当前集群

    我有一个运行在 3 台服务器上的 Kubernetes 集群 一台主服务器和 2 台服务器 我想添加另一个小黄人 是否可以添加 Minion 而无需再次进行完整安装 到目前为止 在寻找执行此操作的指南时 我只能找到有关建立整个集群的优秀指南
  • 允许 Kubernetes 用户列表/获取命名空间

    我有以下用户清单 我希望允许 myapp user 获取集群内所有命名空间的列表 根据我的查找 我应该创建一个 ClusterRole 但我无法真正找到足够的详细信息 是否有所有 apiGroup 以及相应资源和动词的列表 apiVersi
  • Kubernetes Web UI(仪表板)缺少图表

    我已经使用 Kubeadm v1 6 安装了 Docker v1 13 和 Kubernetes 然后我安装了 Web UI 仪表板 我可以访问它 但缺少 CPU 内存使用图 为什么会发生这种情况 对我来说 安装后使用图就起作用了heaps
  • Kubernetes 通过基于时间的触发器扩展 Pod

    我有一台在 Kubernetes 上运行的服务器来处理每小时的处理作业 考虑使用服务来公开 pod 并使用 外部 cron 作业来访问负载均衡器 以便 kubernetes 可以根据需要自动缩放以处理更高的负载 然而在实现中 如果 cron
  • k8s书签解决什么问题?

    我正在尝试做什么 我正在尝试进行部署并监视 k8s 事件 直到部署准备好使用k8s节点API 手表 https github com kubernetes client javascript blob master examples typ
  • Helm 3 图表安装错误:验证数据时出错:未设置 apiVersion

    我有一个简单的 helm 图表 它将通过 docker 桌面将应用程序部署到我的 kubernetes 本地副本 如果我使用 kubectl 一次部署一个 yaml 文件 一切都会正常工作 但是 当我尝试创建 helm 图表以方便部署时 出
  • Kubernetes - 尝试部署时“安装卷失败”

    我部署了第一个容器 我得到了信息 deployment apps frontarena ads deployment created 但后来我看到我的容器创建陷入等待状态 然后我看到日志使用kubectl describe pod fron
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某
  • 如何将我的 pod 日志存储在持久存储中?

    我已经使用以下命令为我的 Pod 生成了日志kubectl logs pod name 但我想将这些日志保存在一个卷 某种持久存储 中 因为如果 Pod 宕机 容器日志将被清除 有没有办法做到这一点 我必须写某种脚本吗 我已经阅读了很多答案

随机推荐