问题描述
在迁移应用程序到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。
希望这些解决方案对你有所帮助。如果有其他问题,请随时提出。