我有一个 Kubernetes
JOB
,它可以在 CloudSQL 数据库上进行数据库迁移。localhost
连接。太棒了 - 到目前为止还有效。但因为我是在 K8s 中执行此操作,所以该作业未标记为已成功完成,因为代理继续运行。JOB
即使输出显示“已完成”,最初的两个容器之一仍在运行 - 代理。
如何让代理在完成容器 1 内的迁移后退出?
这有一些缺点:
网络延迟较高,没有pod本地mysql通信
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"
参数中的
tcp:3306
替换为 tcp:0.0.0.0:3306
。1- 使用私有 IP 将您的 K8s 作业连接到 Cloud SQL,如 @newoxo 在答案之一中所述。为此,您的集群需要是 VPC 本机集群。我的不是,而且我不想将所有东西移动到新集群。所以我没能做到这一点。
2- 将 Cloud SQL 代理容器与服务一起放置在单独的部署中,如 @Christian Kohler 所述。这看起来是一个不错的方法,但 Google Cloud 支持人员不建议这样做。
我正打算朝这个方向前进(解决方案#2),但我决定尝试其他方法。
这是
对我有用的解决方案:3-您可以使用文件系统在同一 Pod/Job 中的不同容器之间进行通信。这个想法是告诉Cloud SQL代理容器主要工作何时完成,然后终止云SQL代理。以下是具体操作方法:
在yaml文件(my-job.yaml)中
-instance
基本上,当你的主要工作完成时,它将在 /lifecycle 中创建一个文件,该文件将由添加到 cloud-sql-proxy 容器的观察程序识别,这将杀死代理并终止容器。
希望有帮助!如果您有任何疑问,请告诉我。
基于:
https://stackoverflow.com/a/52156131/7747292apiVersion: 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:
concurrencyPolicy: Replace
...这将在需要再次运行时用新实例替换当前 pod。但是,您必须确保后续的 cron 运行足够分开。与我的部署捆绑在一起并运行 bash 脚本来启动 CloudSQLProxy 然后启动我的应用程序来解决这个问题。
Dockerfile:
spec
FROM golang:1.19.4
RUN apt update
COPY . /etc/mycode/
WORKDIR /etc/mycode
RUN chmod u+x ./scripts/run_migrations.sh
RUN chmod u+x ./bin/cloud_sql_proxy.linux-amd64
RUN go install
ENTRYPOINT ["./scripts/run_migrations.sh"]
#!/bin/sh
# This script is run from the parent directory
dbConnectionString=$1
cloudSQLProxyPort=$2
echo "Starting Cloud SQL Proxy"
./bin/cloud_sql_proxy.linux-amd64 -instances=${dbConnectionString}=tcp:5432 -enable_iam_login -structured_logs &
CHILD_PID=$!
echo "CloudSQLProxy PID: $CHILD_PID"
echo "Migrating DB..."
go run ./db/migrations/main.go
MAIN_EXIT_CODE=$?
kill $CHILD_PID;
echo "Migrations complete.";
exit $MAIN_EXIT_CODE
import * as k8s from '@pulumi/kubernetes'
const jobDBMigrations = new k8s.batch.v1.Job("job-db-migrations", {
metadata: {
namespace: namespaceName,
labels: appLabels,
},
spec: {
backoffLimit: 4,
template: {
spec: {
containers: [
{
image: pulumi.interpolate`gcr.io/${gcpProject}/${migrationsId}:${migrationsVersion}`,
name: "server-db-migration",
args: [
dbConnectionString,
],
},
],
restartPolicy: "Never",
serviceAccount: k8sSAMigration.metadata.name,
},
},
},
},
{
provider: clusterProvider,
});
端点,可用于关闭 sidecar 代理。不再需要共享进程空间或写入文件等解决方法。
只需将quitquitquit
标志添加到 sql-cloud-proxy 并通过在作业定义的参数中发送 POST 请求来终止 sidecar:
--quitquitquit
在此处了解更多信息:https://github.com/GoogleCloudPlatform/cloud-sql-proxy/issues/828