說(shuō)到GitOps就一定要提DevOps了滋尉,如果說(shuō)DevOps是前浪,那GitOps就是后浪了。為了表達(dá)對(duì)前輩的尊重富腊,我們?cè)俅位仡櫼幌翫evOps:
DevOps(Development和Operations的組合詞)是一種重視“軟件開發(fā)人員(Dev)”和“IT運(yùn)維技術(shù)人員(Ops)”之間溝通合作的文化、運(yùn)動(dòng)或慣例域帐。透過(guò)自動(dòng)化“軟件交付”和“架構(gòu)變更”的流程赘被,來(lái)使得構(gòu)建、測(cè)試肖揣、發(fā)布軟件能夠更加地快捷民假、頻繁和可靠。
誠(chéng)然龙优,DevOps是一種講究合作的文化羊异,一定程序上打破了開發(fā)、運(yùn)維彤断、測(cè)試等軟件開發(fā)的職能界限野舶,讓整個(gè)軟件開發(fā)的流程更快,以此為標(biāo)尺瓦糟,我們可以度量一個(gè)公司是存在DevOps文化筒愚,是否在推動(dòng)、踐行DevOps文化菩浙。
回歸正題巢掺,說(shuō)到浪,沒(méi)有前浪劲蜻,哪來(lái)后浪陆淀,沒(méi)有DevOps, GitOps也只是空談先嬉,那么GitOps到底是翻的是哪種浪花轧苫?
GitOps的思想源自于一家叫做Weaveworks的公司,這家公司開源了一個(gè)名為Flux的GitOps的Operator疫蔓,它運(yùn)行在Kubernetes或OpenShift集群內(nèi)含懊。作用是提供自動(dòng)監(jiān)控,保證Kubernetes集群的狀態(tài)與Git中提供的配置相匹配衅胀。
但GitOps不僅僅是Flux岔乔,也不僅僅是ArgoCD等同類工具。得益于從DevOps以及可靠性工程的思想經(jīng)驗(yàn)滚躯,GitOps已經(jīng)成為云原生開發(fā)的最新熱點(diǎn)趨勢(shì)雏门。
如果它不是簡(jiǎn)單的工具嘿歌,那么GitOps到底是什么?采用它所倡導(dǎo)的最佳實(shí)踐會(huì)給DevOps團(tuán)隊(duì)及其構(gòu)建的應(yīng)用帶來(lái)哪些優(yōu)勢(shì)茁影?
GitOps到底是什么宙帝?
Weaveworks將GitOps總結(jié)為Kubernetes和其他用于云原生開發(fā)的技術(shù)的一種運(yùn)營(yíng)模式,
- 提供一套最佳實(shí)踐募闲,為容器化集群和應(yīng)用統(tǒng)一部署步脓、管理和監(jiān)控。
- 提供了一條端到端的CI/CD管道以及Git工作流蝇更。
對(duì)GitOps的擴(kuò)展定義是沪编,它是一個(gè)為云原生應(yīng)用實(shí)現(xiàn)持續(xù)部署的標(biāo)準(zhǔn)雏搂,它注重以開發(fā)者為中心的基礎(chǔ)設(shè)施運(yùn)營(yíng)體驗(yàn)娱颊。通過(guò)使用開發(fā)者已經(jīng)熟悉的工具--Git以及持續(xù)部署工具(可選工具很多园蝠,比如我們正在用的Jenkins豪直,但我推薦GitLab)--來(lái)實(shí)現(xiàn)Kubernetes集群管理及應(yīng)用交付仅醇。
Git擔(dān)負(fù)起聲明式基礎(chǔ)設(shè)施和應(yīng)用的唯一定義工具秧倾。任何Git和K8s集群中實(shí)際運(yùn)行的內(nèi)容之間的差異都會(huì)被監(jiān)測(cè)到咨油。然后Kubernetes控制器可以回滾集群以與Git相匹配承桥,或自動(dòng)更新它况脆。
將Git置于交付管道的中心饭宾,允許開發(fā)人員使用他們熟悉的工具(不用重新學(xué)習(xí),沒(méi)有認(rèn)知負(fù)擔(dān))進(jìn)行拉取請(qǐng)求格了。一個(gè)自動(dòng)化的流程將倉(cāng)庫(kù)中的描述狀態(tài)與生產(chǎn)環(huán)境進(jìn)行匹配看铆。 GitOps被描述為 "在生產(chǎn)環(huán)境中管理應(yīng)用程序的控制器"。
GitOps原則分解
GitOps管理Kubernetes集群的工作流程基于以下4個(gè)原則盛末。
1 聲明式描述整個(gè)系統(tǒng)
GitOps與包括Kubernetes在內(nèi)的云原生工具經(jīng)常代表的聲明式系統(tǒng)合作弹惦。聲明式系統(tǒng)可以被視為代碼,因?yàn)榕渲檬怯墒聦?shí)而不是指令來(lái)保證的悄但。當(dāng)一個(gè)應(yīng)用程序用聲明的方式在Git中進(jìn)行版本化時(shí)棠隐,那它就一定是明確的-這就是GitOps的核心所在。
由于聲明或者說(shuō)是定義真實(shí)明確的記錄在Git中檐嚣,應(yīng)用程序可以很容易地從Kubernetes部署或者回滾助泽。在最壞的情況下,集群的基礎(chǔ)架構(gòu)可以從Git倉(cāng)庫(kù)中準(zhǔn)確而快速地恢復(fù)嚎京。
2 Git決定了系統(tǒng)狀態(tài)
如果生產(chǎn)版本的聲明(K8s中的資源部署)與Git版本(聲明式定義)有出入嗡贺,就應(yīng)該發(fā)出警報(bào)。如果需要回滾鞍帝,簡(jiǎn)單的Git還原就能恢復(fù)正確的系統(tǒng)聲明暑刃。
Git強(qiáng)大的安全性意味著代碼的作者和出處始終是可追蹤的,這意味著系統(tǒng)的每一次變更都有跡可尋膜眠。
3 自動(dòng)化部署
以Git作為生產(chǎn)集群必須準(zhǔn)確反映聲明的狀態(tài),對(duì)該狀態(tài)的更改可以自動(dòng)更新部署。由于狀態(tài)定義存在于生產(chǎn)環(huán)境之外的Git中宵膨,所以系統(tǒng)變更時(shí)不需要集群憑證架谎。所以,GitOps可以實(shí)現(xiàn)做什么和怎么做的分離辟躏。
4 軟件代理如果出現(xiàn)分歧就會(huì)報(bào)警
如果生產(chǎn)集群的實(shí)際情況與你所期望的系統(tǒng)軟件不一致谷扣,可以發(fā)出警報(bào)。這樣就能整個(gè)系統(tǒng)的自我修復(fù)捎琐,包括在發(fā)生人為錯(cuò)誤的情況下会涎。
GitOps工作流
為什么要在云原生開發(fā)中采用 GitOps?
我們已經(jīng)介紹了GitOps的特點(diǎn)瑞凑,但具體的商業(yè)案例對(duì)系統(tǒng)的好處是什么末秃?你很難找到一種持續(xù)部署技術(shù)或方法論不承諾更快、更頻繁的部署(真實(shí)需求就是快速頻繁的迭代和部署)籽御。GitOps也不例外练慕,但有很多東西可以支持這個(gè)承諾。
自動(dòng)交付管道會(huì)將Git上的變更推送到你的基礎(chǔ)架構(gòu)中技掏。GitOps更進(jìn)一步铃将。它使用像 Weaveworks 的 Flux 這樣的工具來(lái)自動(dòng)比較集群的狀態(tài)和 Git 配置。集群中的操作者會(huì)觸發(fā)Kubernetes內(nèi)部的部署哑梳,從而使任何其他CD工具的需求變得多余劲阎。
這意味著CI不需要訪問(wèn)集群。每一次更新都是原子的鸠真、事務(wù)性的悯仙,并且在Git提交日志中。要么成功弧哎,要么失敗雁比。由于完全基于代碼,不需要增加新的基礎(chǔ)設(shè)施撤嫩。
Git作為基礎(chǔ)架構(gòu)和應(yīng)用代碼的 "真相之源"偎捎,可以加快部署和可靠性,因?yàn)槿魏五e(cuò)誤都會(huì)被迅速發(fā)現(xiàn)序攘。這樣一來(lái)茴她,無(wú)論是回滾生產(chǎn)狀態(tài)還是從Git上更新,都非常容易
XOps
無(wú)論是DevOps還是GitOps亦或是AIOpx程奠,最終的目的都是為了Ops丈牢,將軟件產(chǎn)品提供給受眾,在X這一端也可以說(shuō)是部署之前有很多種方法以及工具瞄沙,我們姑且將X理解為CI己沛,那Jenkins作為這一領(lǐng)域的前浪慌核,依舊發(fā)揮著能量,不過(guò)后浪GitLab的發(fā)展也是迅猛
公司目前使用的CI工具正是Jenkins申尼,當(dāng)我試圖使用jenkins去實(shí)踐DevOps甚至是GitOps, 我需要做以下幾件事
- 登錄Jenkins平臺(tái)上垮卓,新建一個(gè)PipeLine流水線;
- 配置好代碼倉(cāng)庫(kù)demo以及代碼訪問(wèn)權(quán)限师幕;
- 編寫Jenkinsfile粟按;
- 因?yàn)闇y(cè)試環(huán)境Jenkins暫時(shí)沒(méi)有與我們的代碼倉(cāng)庫(kù)GitLab做集成,所以我不得不找到自己的項(xiàng)目霹粥,新建一個(gè)webhook灭将,指向步驟1)的任務(wù)
- 因?yàn)樾枰懒魉€最終的運(yùn)行結(jié)果,還需要配置任務(wù)通知
對(duì)于我而言后控,有以下幾個(gè)問(wèn)題:
- 我給項(xiàng)目demo配置了Jenkins流水線庙曙,這個(gè)項(xiàng)目也可能有其它貢獻(xiàn)者,如果我不寫文檔忆蚀,他們可能并不知道這件事矾利,結(jié)果就需要問(wèn)我,如同我給其它項(xiàng)目貢獻(xiàn)需要問(wèn)其它人一樣馋袜。
- 其它人就算知道我配置了Jenkins流水線男旗,總還得知道Jenkins服務(wù)的地址以及開通對(duì)應(yīng)的權(quán)限
所以測(cè)試環(huán)境常規(guī)發(fā)布過(guò)程歸納起來(lái)就是:
- 開發(fā)完成,push代碼欣鳖;
- 登錄Jenkins察皇,選擇分支,并完成發(fā)布
- 關(guān)注發(fā)布結(jié)果
當(dāng)然泽台,這樣做依然可以達(dá)到最終完成部署的目的什荣。
可以設(shè)想一下,當(dāng)一個(gè)新人開發(fā)者拿到代碼倉(cāng)庫(kù)時(shí)怀酷,他沒(méi)法快速知道整個(gè)CI/CD流程稻爬,但是實(shí)際上這些CI/CD流程是相對(duì)固定,是有規(guī)律可循可以用語(yǔ)言描述的的蜕依,是可以固化在代碼倉(cāng)庫(kù)里面的桅锄,這就是為什么我更傾向于使用GitLab CI/CD的原因。
- 天然與GitLab集成(與GitLab同出一家)
- 符合Iac(基礎(chǔ)設(shè)施即代碼)的哲學(xué)
CI/CD各階段需要做的事情在.gitlab-ci.yml文件中
.....
stages:
- test
- build
- deploy-dev
- deploy-prod
lint:
stage: test
image: harbor.yourprivate.com/base/golangci-lint:v1.21-alpine
script:
- golangci-lint run -v
allow_failure: false
build:
stage: build
script:
- docker build . -t harbor.yourprivate.com/alert-service/gitops:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA
- docker login --username=$DOCKER_PRIVATE_USEE harbor.yourprivate.com --password $DOCKER_PRIVATE_KEY
- docker push harbor.yourprivate.com/alert-service/gitops:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA
deploy-dev:
stage: deploy-dev
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin https://${CI_USERNAME}:${CI_TOKEN}@git.myprivate.com/wuql/gitops.git
- git config --global user.email "gitlab@git.k8s.local"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B $CI_COMMIT_BRANCH
- git pull origin $CI_COMMIT_BRANCH
- cd deployment/dev
- kustomize edit set image harbor.yourprivate.com/alert-service/gitops:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] DEV image update'
- git push origin $CI_COMMIT_BRANCH
only:
- dev
deploy-prod:
stage: deploy-prod
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin https://${CI_USERNAME}:${CI_TOKEN}@git.myprivate.com/wuql/gitops.git
- git config --global user.email "gitlab@git.k8s.local"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B $CI_COMMIT_BRANCH
- git pull origin $CI_COMMIT_BRANCH
- cd deployment/prod
- kustomize edit set image harbor.yourprivate.com/alert-service/gitops:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] PROD image update'
- git push origin $CI_COMMIT_BRANCH
only:
- master
when: manual
忽略細(xì)節(jié)部分样眠,這段描述可以相對(duì)容易地理解為做了以下幾件事
- Test:此處是靜態(tài)檢查)
- Build:構(gòu)建鏡像
- Deploy:根據(jù)分支名部署到對(duì)應(yīng)環(huán)境(master分支的部署需要手動(dòng)執(zhí)行)
雖然Weaveworks最早提出了GitOps這一理念友瘤,也有許多GitOps工具,比如flux檐束、argocd辫秧、jenkins-X, 我們選用其中的argocd被丧。
目前公司的CI/CD平臺(tái)使用的是jenkins, 雖然也可以用盟戏,但是需要在jenkins配置任務(wù)以及倉(cāng)庫(kù)的代碼訪問(wèn)權(quán)限绪妹,相對(duì)繁瑣,其實(shí)公司的代碼托管平臺(tái)gitlab不僅僅可以用來(lái)做代碼倉(cāng)庫(kù)抓半,也可以做CI/CD, 因此喂急,我自己搭建了gitlab runner將集成到公司的gitlab,項(xiàng)目代碼目錄如下
其中main.go為http server代碼
Dockerfile將倉(cāng)庫(kù)代碼通過(guò)Multistage打包成開箱即用的窗口鏡像
deployment為k8s部署的資源描述笛求,dev為開發(fā)環(huán)境,prod為生產(chǎn)環(huán)境糕簿,對(duì)應(yīng)的探入,我們需要在argocd的管理平臺(tái)上新建兩個(gè)應(yīng)用
背后就是在k8s中創(chuàng)建了applications.argoproj.io這個(gè)crd的實(shí)例
應(yīng)用的描述如下所示
...
spec:
destination:
namespace: dev
server: https://kubernetes.default.svc
project: default
source:
path: deployment/dev
repoURL: https://git.myprivate.com/wuql/gitops.git
targetRevision: dev
syncPolicy:
automated:
prune: true
selfHeal: true
...
當(dāng)有人誤將生產(chǎn)應(yīng)用刪除的時(shí)候,
kubectl delete deploy gitops -n dev
argocd會(huì)監(jiān)測(cè)到這一情況
并重新將應(yīng)用資源建立起來(lái)
至此懂诗,算是實(shí)踐了一下gitops的思想蜂嗽。
解決了什么問(wèn)題?
仔細(xì)想想殃恒,如果我們不用gitops這一套思路植旧,gitlab runner本身就在k8sk, 我可以在gitlab的ci完成后直接apply部署,這樣最終也能達(dá)到部署這一目的离唐,gitops思路很大的一點(diǎn)不同在于【部署】這件事由opertaor來(lái)保證病附,并且持續(xù)檢查部署狀態(tài)是否與git倉(cāng)庫(kù)定義的是否一致,如果說(shuō)在gitlab runner中可以一氣呵成完成CI/CD, 那么gitops就是將CI/CD解耦了亥鬓,這樣帶來(lái)的好處是否大于收益完沪,個(gè)人認(rèn)為需要看基礎(chǔ)設(shè)施是否完善,如果本身CI/CD本身都做的很好嵌戈,可以嘗試覆积,但是根據(jù)筆者的觀察,IaC的思路并不是那么容易被接受的熟呛,思路可以借鑒宽档,自動(dòng)化確實(shí)很美好,不過(guò)也是道阻且長(zhǎng)庵朝,最重要還是能解決團(tuán)隊(duì)當(dāng)時(shí)當(dāng)下的具體問(wèn)題吗冤。
參考
- https://zh.wikipedia.org/wiki/DevOps
- https://www.weave.works/technologies/gitops/
- https://docs.docker.com/develop/develop-images/multistage-build/
- https://argoproj.github.io/argo-cd/getting_started/
- https://kruschecompany.com/gitops/
- https://www.qikqiak.com/post/gitlab-ci-argo-cd-gitops/
- https://about.gitlab.com/devops-tools/jenkins-vs-gitlab/
- https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/