在kubernetes中,默认场景下,initContainers中的容器是按照顺序启动的,且存在先后依赖关系,即前一个启动完了,才会启动后一个,containers中则是按照顺序启动,但是不存在依赖关系,这就给一些使用场景带来了麻烦。例如,在使用pod作为流水线的时候,containers中的容器顺序需要存在先后依赖关系。以下记录一些实践方案:

方案一

利用原生的postStart机制,该机制保证了后一个容器在前一个容器发出该信号前不会创建。

实例:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. creationTimestamp: null
  5. labels:
  6. run: my-pipline
  7. name: my-pipline
  8. spec:
  9. volumes:
  10. - name: data
  11. emptyDir: {}
  12. initContainers:
  13. - image: "alpine/git"
  14. name: prepare
  15. env:
  16. - name: repo
  17. value: "https://github.com/linjinbao666/vrmanager.git"
  18. args:
  19. - clone
  20. - --single-branch
  21. - --branch=main
  22. - --
  23. - "https://github.com/linjinbao666/vrmanager.git"
  24. - "/opt/workspace"
  25. volumeMounts:
  26. - name: data
  27. mountPath: "/opt/workspace"
  28. containers:
  29. - image: "docker.io/linjinbao66/dt-maven:0.0.2"
  30. name: my-pipline
  31. workingDir: "/opt/workspace"
  32. env:
  33. - name: repo
  34. value: "https://github.com/linjinbao666/vrmanager.git"
  35. command:
  36. - "/bin/sh"
  37. - "-c"
  38. args:
  39. - "mvn clean package; /bin/sidecar"
  40. lifecycle:
  41. postStart:
  42. exec:
  43. command:
  44. - "/bin/entrypoint"
  45. - "wait"
  46. volumeMounts:
  47. - name: data
  48. mountPath: "/opt/workspace"
  49. - image: "busybox:latest"
  50. name: busybox
  51. command:
  52. - "/bin/sh"
  53. - "-c"
  54. args: ["date; echo 'app container started'"]
  55. dnsPolicy: ClusterFirst
  56. restartPolicy: Never
  57. status: {}

实例中的2个容器,my-pipline和busybox,busybox一定会在my-pipline的entrypoint wait信号给出返回后,才会创建。

该方案的技术要点:

  • 需要重写前一容器的启动脚本,使得该容器启动时,执行完主程序命令后,启动sidecar一个端口,(或者监听文件),该端口给entrypoint探测用,entryoint是一只在探测,只有得到想要的结果后,才会放行。
  • 该方案需要前容器会保持Running状态,由于sidecar程序监听,所以整个Pod不会出现Completed状态,如果后一容器会执行完则退出,则会出现NotReady状态。
  • 该方案在前一容器sidecar程序执行前的日志无法实时获取,如果该阶段比较耗时,例如是mvn build命令,则不利于日志的实时推出

方案二

该方案利用多容器间共享存储卷实现

实例:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. creationTimestamp: null
  5. labels:
  6. run: my-pipline
  7. name: my-pipline
  8. spec:
  9. volumes:
  10. - name: data
  11. emptyDir: {}
  12. initContainers:
  13. - image: "alpine/git"
  14. name: prepare
  15. env:
  16. - name: repo
  17. value: "https://github.com/linjinbao666/vrmanager.git"
  18. args:
  19. - clone
  20. - --single-branch
  21. - --branch=main
  22. - --
  23. - "https://github.com/linjinbao666/vrmanager.git"
  24. - "/opt/workspace"
  25. volumeMounts:
  26. - name: data
  27. mountPath: "/opt/workspace"
  28. containers:
  29. - image: "docker.io/linjinbao66/dt-maven:0.0.3"
  30. name: my-pipline
  31. workingDir: "/opt/workspace"
  32. env:
  33. - name: repo
  34. value: "https://github.com/linjinbao666/vrmanager.git"
  35. command:
  36. - "/bin/sh"
  37. - "-c"
  38. args:
  39. - "mvn clean package && echo 'build finished' > /opt/workspace/mvn.log"
  40. volumeMounts:
  41. - name: data
  42. mountPath: "/opt/workspace"
  43. - image: "busybox:latest"
  44. name: busybox
  45. command:
  46. - "/bin/sh"
  47. - "-c"
  48. args: ["while true; do sleep 10 && [ -f '/opt/workspace/mvn.log' ] && exit 0|| echo 'file not exists' ; done"]
  49. volumeMounts:
  50. - name: data
  51. mountPath: "/opt/workspace"
  52. dnsPolicy: ClusterFirst
  53. restartPolicy: Never
  54. status: {}

容器my-pipline将执行完的结果写入共享文件/opt/workspace/mvn.log,容器busybox检测共享文件是否存在,存在则执行自身命令,执行完退出。

该方案可以同时查看2个容器的日志。

参考链接: