Kubernetes中如何在一个容器完成某些操作后再启动另一个容器

47次阅读
没有评论

问题描述

在迁移应用程序到Kubernetes(K8s)时,有些应用程序需要大量的配置文件,这些配置文件最好保存在GIT中,因为它们的大小超过了configmap的最大大小限制。用户已经使用一个名为git-sync的镜像,可以将持久卷与Git存储库保持同步,并希望将其用作某些部署的sidecar。

问题的关键在于,某些应用程序(例如无法控制的供应商应用程序)要求在应用程序启动之前配置文件必须存在。这意味着不能只将git-sync容器作为sidecar运行,因为无法保证主应用程序启动之前它已经克隆了git存储库。用户已经通过为git同步使用一个单独的部署,然后为主应用程序使用一个initContainer来检查克隆的git存储库的存在来解决了这个问题。

虽然这种解决方案可以工作,但感觉有点混乱。用户想了解是否有更简洁的方法来处理这种情况。

以下是用户部署的一个yaml片段,以供参考:

# 主要部署
...
initContainers:
  - name: wait-for-git-sync
    image: my-git-sync:1.0
    command: ["/bin/bash"]
    args: ["-c", "until [ -d /myapp-config/stuff ] ; do echo \"config not present yet\"; sleep 1; done; exit;"]
    volumeMounts:
    - mountPath: /myapp-config
      name: myapp-config
containers:
  - name: myapp
    image: myapp:1.0
    volumeMounts:
    - mountPath: /myapp-config
      name: myapp-config
volumes:
  - name: myapp-config
    persistentVolumeClaim:
      claimName: myapp-config
...

解决方案

请注意以下操作可能存在版本差异或风险,建议在实施前备份相关数据。

使用readiness probe

一种更干净的方法是使用readiness probe。Kubernetes API服务器将在此情况下通过调用Pod的/health端点来检查Pod的准备状态,如果返回HTTP状态错误代码,表示未就绪,否则表示就绪。只要服务未准备好,调用将不会被路由。

在代码中,你可以这样处理:

@app.route("/health")
def health():
    if not os.path.exists('gitfile'):
        return "not ok", 500
    return "OK", 200

在你的Deployment配置中添加readiness probe:

containers:
  - name: name
    image: "docker.io/app:1.0"
    imagePullPolicy: Always
    readinessProbe:
      httpGet:
        path: /health
        port: 5000
      initialDelaySeconds: 5

使用initContainer来克隆仓库

另一种方法是在initContainer中克隆存储库。不要等待文件出现,只需拉取或克隆你的配置。

这里需要注意的是,这个方法可能需要解决并发/数据一致性问题,因为主应用程序和Job可能同时尝试写入相同的文件。如果你不确定主应用程序是否能够正确读取文件系统上的文件(例如通过git pull/push同步的情况),那么你最好让Job重新启动你的Deployment。

希望这些解决方案对你有所帮助。如果有其他问题,请随时提出。

正文完