云原生Devops最佳实践(2):GitOps + OpenKruise CloneSet

什么是GitOps?

GitOps是一种持续交付的方式。它的核心思想是将应用系统的声明性基础架构和应用程序存放在Git版本库中。

将Git作为交付流水线的核心,每个开发人员都可以提交拉取请求(Pull Request)并使用Git来加速和简化Kubernetes的应用程序部署和运维任务。通过使用像Git这样的简单工具,开发人员可以更高效地将注意力集中在创建新功能而不是运维相关任务上(例如,应用系统安装、配置、迁移等)。

随着gitops越来越深入人心,社区涌现了非常多的优秀产品,例如:Jenkins X、Argo CD、Weave Flux等。本文将以argo-cd为例介绍一下如何使用gitops发布kruise workload,方便社区的用户能够更加方便的使用openKruise。

argo-cd

GitOps + OpenKruise CloneSet实践

前置条件

  • Kubernetes集群,从v1.0.0(alpha/beta)开始,OpenKruise要求在Kubernetes >= 1.16以上版本的集群中安装和使用。
  • 安装Tekton, 参考官方文档,Tekton是一种适用于创建持续集成和持续部署/交付(CI/CD)系统的谷歌开源的Kubernetes原生框架。
  • 安装argo-cd, 参考官方文档,Argo-cd是用于Kubernetes的声明性GitOps连续交付工具。

Install OpenKruise(Enable: TemplateNoDefaults)

默认安装的OpenKruise会进行pod/pvc template的默认值注入,这个行为会跟argo-cd的sync判断逻辑冲突,所以在安装OpenKruise需要打开Gates TemplateNoDefaults,如下:

  1. # Firstly add openkruise charts repository if you haven't do this.
  2. $ helm repo add openkruise https://openkruise.github.io/charts/
  3. # [Optional]
  4. $ helm repo update
  5. # Install the latest version.
  6. $ helm install kruise openkruise/kruise --set featureGates="TemplateNoDefaults=true"
  7. # Those that have been installed need to be upgraded
  8. $ helm upgrade kruise openkruise/kruise --set featureGates="TemplateNoDefaults=true"

CloneSet部署无状态应用

CloneSet是OpenKruise提供的高效管理无状态应用的能力,它可以对标原生的 Deployment,但 CloneSet 提供了很多增强功能,例如:原地升级、分批发布,请参考文档:CloneSet。 本篇文章提供了一个hello world服务 Demo,它包含Helm charts,其中CloneSet配置如下:

  1. apiVersion: apps.kruise.io/v1alpha1
  2. kind: CloneSet
  3. metadata:
  4. name: helloworld-server
  5. labels:
  6. app: helloworld-server
  7. spec:
  8. updateStrategy:
  9. # CloneSet会优先尝试原地升级 Pod,如果不行再采用重建升级
  10. type: InPlaceIfPossible
  11. # 分批发布,当前批次只升级1个Pod
  12. partition: 1
  13. replicas: 2
  14. selector:
  15. matchLabels:
  16. app: helloworld-server
  17. template:
  18. metadata:
  19. labels:
  20. app: helloworld-server
  21. spec:
  22. containers:
  23. - name: helloworld
  24. image: "openkruise/kruise:hello_world-d92ae174b"

Argo-cd CloneSet Health Check

配置CloneSet Argo-cd Custom CRD Health ChecksArgo-cd根据该配置能够实现CloneSet自定义资源的检查,如CloneSet是否发布完成,以及Pod是否ready等,如下:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. labels:
  5. app.kubernetes.io/name: argocd-cm
  6. app.kubernetes.io/part-of: argocd
  7. name: argocd-cm
  8. namespace: argocd
  9. data:
  10. resource.customizations.health.apps.kruise.io_CloneSet: |
  11. hs = {}
  12. -- if paused
  13. if obj.spec.updateStrategy.paused then
  14. hs.status = "Suspended"
  15. hs.message = "CloneSet is Suspended"
  16. return hs
  17. end
  18. -- check cloneSet status
  19. if obj.status ~= nil then
  20. if obj.status.observedGeneration < obj.metadata.generation then
  21. hs.status = "Progressing"
  22. hs.message = "Waiting for rollout to finish: observed cloneSet generation less then desired generation"
  23. return hs
  24. end
  25. if obj.status.updatedReplicas < obj.spec.replicas then
  26. hs.status = "Progressing"
  27. hs.message = "Waiting for rollout to finish: replicas hasn't finished updating..."
  28. return hs
  29. end
  30. if obj.status.updatedReadyReplicas < obj.status.updatedReplicas then
  31. hs.status = "Progressing"
  32. hs.message = "Waiting for rollout to finish: replicas hasn't finished updating..."
  33. return hs
  34. end
  35. hs.status = "Healthy"
  36. return hs
  37. end
  38. -- if status == nil
  39. hs.status = "Progressing"
  40. hs.message = "Waiting for cloneSet"
  41. return hs

kruise内部自定义CRD资源除CloneSet,其它如:Advanced StatefulSet、SidecarSet等都可以类似上面的方式实现Custom Resource Health。

Tekton Pipeline + Argo-cd

通过Tekton Pipeline进行Argo-cd部署应用,可以更好的践行Devops思想,与CI流程打通。其中需要将Argo-cd的密钥(密钥获取方法)存储到Secret当中,进而在Tekton Pipeline中使用,如下:

  1. apiVersion: v1
  2. data:
  3. # argo-cd admin secret
  4. username: xxxxx
  5. password: xxxxx
  6. server: xxxxx
  7. kind: Secret
  8. metadata:
  9. name: argosecret
  10. ---
  11. apiVersion: tekton.dev/v1beta1
  12. kind: Task
  13. metadata:
  14. labels:
  15. app: helloworld
  16. name: helloworld-argocd
  17. spec:
  18. params:
  19. - name: gitrepositoryurl
  20. type: string
  21. - name: branch
  22. type: string
  23. - name: short_sha
  24. type: string
  25. - name: docker_repo
  26. type: string
  27. - name: app_name
  28. type: string
  29. - name: app_ns
  30. type: string
  31. - name: k8s_server
  32. type: string
  33. steps:
  34. - name: argocd-deploy
  35. image: argoproj/argocd:latest
  36. command:
  37. - sh
  38. args:
  39. - '-ce'
  40. - >
  41. set -e
  42. echo "upgrade app $(params.app_name)"; username=`cat /var/secret/username`; password=`cat /var/secret/password`; server=`cat /var/secret/server`;
  43. argocd login ${server} --insecure --username ${username} --password ${password}
  44. argocd app create $(params.app_name) --upsert --repo $(params.gitrepositoryurl) --path $(params.app_name)/charts --dest-namespace $(params.app_ns) --dest-server $(params.k8s_server) --revision $(params.branch) --helm-set image.repository=$(params.docker_repo) --helm-set image.tag=$(params.branch)-$(params.short_sha) --helm-set installation.namespace=$(params.app_ns)
  45. argocd app list; argocd app sync $(params.app_name)
  46. argocd app wait $(params.app_name) --health
  47. volumeMounts:
  48. - name: argocd-secret
  49. mountPath: "/var/secret"
  50. volumes:
  51. - name: argocd-secret
  52. secret:
  53. secretName: argosecret
  54. ---
  55. apiVersion: tekton.dev/v1beta1
  56. kind: Pipeline
  57. metadata:
  58. name: helloworld-pipeline
  59. spec:
  60. params:
  61. - name: gitrepositoryurl
  62. type: string
  63. - name: branch
  64. type: string
  65. - name: short_sha
  66. type: string
  67. - name: docker_repo
  68. type: string
  69. - name: app_name
  70. type: string
  71. - name: app_ns
  72. type: string
  73. - name: k8s_server
  74. type: string
  75. # 此处可以与CI流程打通,实现CI/CD Pipeline
  76. tasks:
  77. - name: helloworld-argocd
  78. taskRef:
  79. name: helloworld-argocd
  80. params:
  81. - name: gitrepositoryurl
  82. value: $(params.gitrepositoryurl)
  83. - name: short_sha
  84. value: $(params.short_sha)
  85. - name: branch
  86. value: $(params.branch)
  87. - name: docker_repo
  88. value: $(params.docker_repo)
  89. - name: app_name
  90. value: $(params.app_name)
  91. - name: app_ns
  92. value: $(params.app_ns)
  93. - name: k8s_server
  94. value: $(params.k8s_server)

执行Tekton Pipeline

定义PipelineRun CRD资源,并kubectl apply -f 到k8s集群执行Pipeline,如下:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: PipelineRun
  3. metadata:
  4. name: helloworld-pipeline-run-1
  5. spec:
  6. pipelineRef:
  7. name: helloworld-pipeline
  8. params:
  9. - name: gitrepositoryurl
  10. value: https://github.com/zmberg/samples.git
  11. - name: branch
  12. value: hello_world
  13. - name: short_sha
  14. value: d92ae174b
  15. - name: docker_repo
  16. value: zhaomingshan/kruise
  17. - name: app_name
  18. value: helloworld
  19. - name: app_ns
  20. value: helloworld
  21. - name: k8s_server
  22. value: https://kubernetes.default.svc

可以通过Argo-cd cli查看部署情况,如下:

guestbook

总结

OpenKruise更多是Kubernetes层面扩展的能力,如 原地升级、镜像预热等,所以很多社区的用户在生产环境使用OpenKruise还有一些额外的成本,需要集成或自研容器PaaS方案。 本文的主要目的是想将社区的一些优秀的Paas方案与OpenKruise结合起来,尽量让更多的人能够更小的成本享受云原生带来的红利。Argo-cd是目前社区非常优秀的一款产品, 并且它对于OpenKruise众多的自定义CRD资源也能够非常便捷的对接,对使用者而言很友好。本文也算是一个抛砖引玉,希望社区的众多小伙伴能够提供更多的思路,后面也会尝试与一些其它CI/CD流水线结合,争取能够更好的践行devops理念。