5

我在一个吊舱内有两个容器。一个是我的应用程序容器,第二个是 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 一个。

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

4

1 回答 1

6

目前,Kubernetes pod API 无法直接实现这一点。容器可以按任何顺序终止。Cloud SQL pod 可能会比您的应用程序更快地死亡,例如,如果要执行的清理较少或要消耗的运行中请求较少。

Pod 的终止

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


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

此解决方案不适用于 Cloud SQL 代理的 1.16 版本(请参阅评论),因为此版本不再将外壳与容器捆绑在一起。1.17 版本现在可用于 Alpine 或 Debian Buster 变体,因此该版本现在是一个可行的升级目标,再次与该解决方案兼容。

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

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 代理容器中拦截SIGTERMKubernetes 主管在关闭时传递给每个 pod 容器的信号。在该容器中运行的“主进程”是一个 shell,它产生了一个运行 Cloud SQL 代理的子进程。因此,Cloud SQL 代理不会立即终止。相反,shell 代码会阻塞等待它已成功退出的主容器的信号(通过文件系统中出现的文件的简单方式)。只有在此时,Cloud SQL 代理进程才会终止,sidecar 容器才会返回。

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

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

于 2018-09-03T20:56:51.983 回答