Kubernetes:在多容器Pod/Job中停止CloudSQL-proxy sidecar容器

pky*_*eck 17 google-cloud-sql docker kubernetes

我有一个Kubernetes JOB在CloudSQL数据库上进行数据库迁移.
从GKE访问CloudSQL数据库的一种方法是使用CloudSQL代理容器然后通过连接localhost.太棒了 - 到目前为止工作正常.但是因为我在K8s中这样做,JOB所以作业没有被标记为成功完成,因为代理继续运行.

$ kubectrl get po
NAME                      READY     STATUS      RESTARTS   AGE
db-migrations-c1a547      1/2       Completed   0          1m
Run Code Online (Sandbox Code Playgroud)

即使输出显示"已完成",最初的两个容器之一仍在运行 - 代理.

如何在完成容器1内的迁移时使代理退出?

小智 10

一种可能的解决方案是使用匹配服务的单独的cloudql-proxy部署.然后,您只需要在连接到代理服务的作业中使用迁移容器.

这有一些缺点:

  • 更高的网络延迟,没有pod本地mysql通信
  • 如果您将sql端口提供给整个kubernetes集群,则可能存在安全问题

如果你想打开CLOUDSQL代理整个集群必须更换tcp:3306tcp:0.0.0.0:3306-instance上CLOUDSQL代理参数.


Gro*_*Src 10

我发现的最好方法是在容器之间共享进程命名空间并使用 SYS_PTRACE securityContext 功能来允许您终止 sidecar。

apiVersion: batch/v1
kind: Job
metadata:
  name: my-db-job
spec:
  template:
    spec:
      restartPolicy: OnFailure
      shareProcessNamespace: true
      containers:
      - name: my-db-job-migrations
        command: ["/bin/sh", "-c"]
        args:
          - |
            <your migration commands>;
            sql_proxy_pid=$(pgrep cloud_sql_proxy) && kill -INT $sql_proxy_pid;
        securityContext:
          capabilities:
            add:
              - SYS_PTRACE
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.17
        command:
          - "/cloud_sql_proxy"
        args:
          - "-instances=$(DB_CONNECTION_NAME)=tcp:5432"
          
Run Code Online (Sandbox Code Playgroud)

  • 这个答案值得更多的选票。这是对我有用的唯一选择! (3认同)
  • 谢谢,这个答案为我们指明了正确的方向!请注意,如果迁移命令退出并出现错误代码,上述答案中的代码不会导致您的作业失败。如果您希望迁移失败时您的作业也失败,您可以执行以下操作:&lt;您的迁移命令&gt;;migration_exit_code=$?; sql_proxy_pid=$(pgrep cloud_sql_proxy) &amp;&amp; 杀死 -INT $sql_proxy_pid &amp;&amp; 退出 $migration_exit_code (3认同)

Mar*_*elo 6

有 3 种方法可以做到这一点。

1- 如@newoxo 在其中一个答案中所述,使用私有 IP 将您的 K8s 作业连接到 Cloud SQL。为此,您的集群需要是 VPC 原生集群。我的不是,我也不想将我所有的东西移动到一个新的集群。所以我无法做到这一点。

2- 如@Christian Kohler 所述,将 Cloud SQL 代理容器与服务放在单独的部署中。这看起来是一个不错的方法,但 Google Cloud 支持并不推荐这样做。

我正要朝这个方向前进(解决方案 #2),但我决定尝试其他方法。

这是对我有用的解决方案:

3- 您可以使用文件系统在同一个 Pod/Job 中的不同容器之间进行通信。思路是告诉Cloud SQL Proxy容器什么时候完成主要工作,然后kill掉cloud sql代理。这是如何做到的:

在 yaml 文件中 (my-job.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: my-job-pod
  labels:
    app: my-job-app
spec:
  restartPolicy: OnFailure
  containers:
  - name: my-job-app-container
    image: my-job-image:0.1
    command: ["/bin/bash", "-c"]
    args:
      - |
        trap "touch /lifecycle/main-terminated" EXIT
        { your job commands here }
    volumeMounts:
      - name: lifecycle
        mountPath: /lifecycle
  - name: cloudsql-proxy-container
    image: gcr.io/cloudsql-docker/gce-proxy:1.11
    command: ["/bin/sh", "-c"]
    args:
      - |
        /cloud_sql_proxy -instances={ your instance name }=tcp:3306 -credential_file=/secrets/cloudsql/credentials.json &
        PID=$!
        while true
            do
                if [[ -f "/lifecycle/main-terminated" ]] 
                then
                    kill $PID
                    exit 0
                fi
                sleep 1
            done
    securityContext:
      runAsUser: 2  # non-root user
      allowPrivilegeEscalation: false
    volumeMounts:
      - name: cloudsql-instance-credentials
        mountPath: /secrets/cloudsql
        readOnly: true
      - name: lifecycle
        mountPath: /lifecycle
  volumes:
  - name: cloudsql-instance-credentials
    secret:
      secretName: cloudsql-instance-credentials
  - name: lifecycle
    emptyDir:
Run Code Online (Sandbox Code Playgroud)

基本上,当您的主要工作完成后,它会在 /lifecycle 中创建一个文件,该文件将由添加到 cloud-sql-proxy 容器的观察者识别,这将终止代理并终止容器。

我希望它有帮助!如果您有任何问题,请告诉我。

基于:https : //stackoverflow.com/a/52156131/7747292


Pat*_*her 3

看起来 Kubernetes 无法单独完成此操作,一旦迁移退出,您需要手动终止代理。这里提出了类似的问题:Kubernetes Jobs 中的 Sidecar 容器?