云原生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。

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,如下:
# Firstly add openkruise charts repository if you haven't do this.$ helm repo add openkruise https://openkruise.github.io/charts/# [Optional]$ helm repo update# Install the latest version.$ helm install kruise openkruise/kruise --set featureGates="TemplateNoDefaults=true"# Those that have been installed need to be upgraded$ helm upgrade kruise openkruise/kruise --set featureGates="TemplateNoDefaults=true"
CloneSet部署无状态应用
CloneSet是OpenKruise提供的高效管理无状态应用的能力,它可以对标原生的 Deployment,但 CloneSet 提供了很多增强功能,例如:原地升级、分批发布,请参考文档:CloneSet。 本篇文章提供了一个hello world服务 Demo,它包含Helm charts,其中CloneSet配置如下:
apiVersion: apps.kruise.io/v1alpha1kind: CloneSetmetadata:name: helloworld-serverlabels:app: helloworld-serverspec:updateStrategy:# CloneSet会优先尝试原地升级 Pod,如果不行再采用重建升级type: InPlaceIfPossible# 分批发布,当前批次只升级1个Podpartition: 1replicas: 2selector:matchLabels:app: helloworld-servertemplate:metadata:labels:app: helloworld-serverspec:containers:- name: helloworldimage: "openkruise/kruise:hello_world-d92ae174b"
Argo-cd CloneSet Health Check
配置CloneSet Argo-cd Custom CRD Health Checks, Argo-cd根据该配置能够实现CloneSet自定义资源的检查,如CloneSet是否发布完成,以及Pod是否ready等,如下:
apiVersion: v1kind: ConfigMapmetadata:labels:app.kubernetes.io/name: argocd-cmapp.kubernetes.io/part-of: argocdname: argocd-cmnamespace: argocddata:resource.customizations.health.apps.kruise.io_CloneSet: |hs = {}-- if pausedif obj.spec.updateStrategy.paused thenhs.status = "Suspended"hs.message = "CloneSet is Suspended"return hsend-- check cloneSet statusif obj.status ~= nil thenif obj.status.observedGeneration < obj.metadata.generation thenhs.status = "Progressing"hs.message = "Waiting for rollout to finish: observed cloneSet generation less then desired generation"return hsendif obj.status.updatedReplicas < obj.spec.replicas thenhs.status = "Progressing"hs.message = "Waiting for rollout to finish: replicas hasn't finished updating..."return hsendif obj.status.updatedReadyReplicas < obj.status.updatedReplicas thenhs.status = "Progressing"hs.message = "Waiting for rollout to finish: replicas hasn't finished updating..."return hsendhs.status = "Healthy"return hsend-- if status == nilhs.status = "Progressing"hs.message = "Waiting for cloneSet"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中使用,如下:
apiVersion: v1data:# argo-cd admin secretusername: xxxxxpassword: xxxxxserver: xxxxxkind: Secretmetadata:name: argosecret---apiVersion: tekton.dev/v1beta1kind: Taskmetadata:labels:app: helloworldname: helloworld-argocdspec:params:- name: gitrepositoryurltype: string- name: branchtype: string- name: short_shatype: string- name: docker_repotype: string- name: app_nametype: string- name: app_nstype: string- name: k8s_servertype: stringsteps:- name: argocd-deployimage: argoproj/argocd:latestcommand:- shargs:- '-ce'- >set -eecho "upgrade app $(params.app_name)"; username=`cat /var/secret/username`; password=`cat /var/secret/password`; server=`cat /var/secret/server`;argocd login ${server} --insecure --username ${username} --password ${password}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)argocd app list; argocd app sync $(params.app_name)argocd app wait $(params.app_name) --healthvolumeMounts:- name: argocd-secretmountPath: "/var/secret"volumes:- name: argocd-secretsecret:secretName: argosecret---apiVersion: tekton.dev/v1beta1kind: Pipelinemetadata:name: helloworld-pipelinespec:params:- name: gitrepositoryurltype: string- name: branchtype: string- name: short_shatype: string- name: docker_repotype: string- name: app_nametype: string- name: app_nstype: string- name: k8s_servertype: string# 此处可以与CI流程打通,实现CI/CD Pipelinetasks:- name: helloworld-argocdtaskRef:name: helloworld-argocdparams:- name: gitrepositoryurlvalue: $(params.gitrepositoryurl)- name: short_shavalue: $(params.short_sha)- name: branchvalue: $(params.branch)- name: docker_repovalue: $(params.docker_repo)- name: app_namevalue: $(params.app_name)- name: app_nsvalue: $(params.app_ns)- name: k8s_servervalue: $(params.k8s_server)
执行Tekton Pipeline
定义PipelineRun CRD资源,并kubectl apply -f 到k8s集群执行Pipeline,如下:
apiVersion: tekton.dev/v1beta1kind: PipelineRunmetadata:name: helloworld-pipeline-run-1spec:pipelineRef:name: helloworld-pipelineparams:- name: gitrepositoryurlvalue: https://github.com/zmberg/samples.git- name: branchvalue: hello_world- name: short_shavalue: d92ae174b- name: docker_repovalue: zhaomingshan/kruise- name: app_namevalue: helloworld- name: app_nsvalue: helloworld- name: k8s_servervalue: https://kubernetes.default.svc
可以通过Argo-cd cli查看部署情况,如下:

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