【问题标题】:Kubernetes: stop CloudSQL-proxy sidecar container in multi container Pod/JobKubernetes:在多容器 Pod/Job 中停止 CloudSQL-proxy sidecar 容器
【发布时间】:2017-05-31 11:12:44
【问题描述】:

我有一个 Kubernetes JOB,它在 CloudSQL 数据库上进行数据库迁移。
从 GKE 访问 CloudSQL 数据库的一种方法是使用 CloudSQL-proxy 容器,然后通过localhost 连接。太好了 - 到目前为止有效。但因为我是在 K8s JOB 内执行此操作,所以该作业未标记为成功完成,因为代理继续运行。

$ kubectrl get po
NAME                      READY     STATUS      RESTARTS   AGE
db-migrations-c1a547      1/2       Completed   0          1m

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

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

【问题讨论】:

  • 不发表评论就投反对票?会有所帮助添加注释可以改进的地方...
  • 嗨@Phillip,您是否在此期间找到了解决方案,或者任何替代方法来进行迁移?
  • @MarkVincze 我采用了 Christian 的方法,即创建一个单独的代理服务,该工作可以连接到该服务 - 然后不需要边车

标签: docker kubernetes google-cloud-sql


【解决方案1】:

我发现最好的方法是在容器之间share the process namespace 并使用 SYS_PTRACE securityContext 功能来让你杀死边车。

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"
          

【讨论】:

  • 这个答案值得更多的投票。这是唯一对我有用的选择!
  • 这对我根本不起作用。我不知道为什么。我看不到发生了什么,但是如果我执行到容器中并尝试手动运行此命令,则会出现不允许的操作。
【解决方案2】:

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

这有一些缺点:

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

如果您想对整个集群开放 cloudsql-proxy,您必须在 cloudsql-proxy 上的 -instance 参数中将 tcp:3306 替换为 tcp:0.0.0.0:3306

【讨论】:

  • 是的,也试过了。但我花了一段时间才弄清楚0.0.0.0 部分;)
  • Google 支持不建议使用独立的 cloudsqlproxy 部署
【解决方案3】:

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

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

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

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

这是适合我的解决方案:

3- 您可以使用文件系统在同一个 Pod/Job 中的不同容器之间进行通信。这个想法是在主要工作完成时告诉 Cloud SQL Proxy 容器,然后杀死 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:

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

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

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

【讨论】:

  • kill: (7) - 不允许操作,每次,kill 命令都不起作用
【解决方案4】:

看起来 Kubernetes 无法单独执行此操作,您需要在迁移退出后手动终止代理。类似的问题在这里问:Sidecar containers in Kubernetes Jobs?

【讨论】:

    【解决方案5】:

    Google cloud sql 最近推出了 cloudsql 的私有 IP 地址连接。如果云 sql 实例和 kubernetes 集群在同一区域,您可以不使用云 sql 代理连接到 cloudsql。

    https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine#private-ip

    【讨论】:

    【解决方案6】:

    一个可能的解决方案是在作业spec 中设置concurrencyPolicy: Replace ...这将在需要再次运行时用新实例替换当前pod。但是,您必须确保后续的 cron 运行足够分离。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-25
      • 1970-01-01
      • 2021-12-28
      • 2016-07-12
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 2020-05-12
      相关资源
      最近更新 更多