Kubernetes中的GitOps:如何使用GitLab CI和Argo CD进行操作
最近,Cloud Native一直在谈论GitOps。现在云原生圈里面基本上都会浮现以及说道gitops的话题,而实际上,这种持续交付模式是现代IT世界的一种革命。为什么这么说,前几天我在云原生CTO交流群发了一版高清的云原生布道图,图中描绘了整个云原生在各领域的路线map,在整合交付这块最引人注意的就是argo,当然后面我会通过示例教给你如何使用它,而这里我不会描述GitOps是什么,因为你可以在Internet上找到很多有关它的资源。
因为找到GitOps的definition是比较容易的事情,但是从另一方面找到这样的工作流程的例子是相当有难度。这也是我写这个博客的主要原因。我希望你可以在这里找到很多有用的信息,这些信息可以帮助你在当前基础架构设置中创建GitOps。
1 目录介绍
Argo CD安装 GitLab项目设置 GitLab项目 CI Pipeline 这个怎么运作? 概要
2 介绍
下图显示了此项目中演示的GitOps工作流程

gitops工作流程
复制
GitLab和Argo CD在这里起主要作用,所以我现在想谈谈它们。
Argo CD 是用于Kubernetes的声明性GitOps连续交付工具。我喜欢它,因为它相对容易配置和使用(需要基本的Kubernetes知识)。它带有漂亮且易于理解的GUI。对我而言,重要的是Argo CD以多种方式支持清单(kustomize,helm,ksonnet甚至jsonnet文件)。可以以Argo CD添加的专用“自定义资源定义”的形式配置应用程序。它可以自动在指定的目标环境中部署所需的应用程序状态。有关体系结构的更多信息,请访问官方项目网站上的可用功能。
顾名思义,GitLab CI是GitLab的持续集成和持续交付工具。对我来说,与其他竞争对手相比,它是CI CD任务的很好选择。我喜欢它,因为与其他工具(例如Jenkins)相比,创建管道非常容易(简单的.gitlab-ci.yaml文件)。对于此演示,我将使用一个支持大多数必要功能的免费版本。因此,让我们开始吧!
3 Argo CD安装
我将在PC上托管的Minikube群集上设置GitOps 。第一步是确保我可以通过kubectl访问集群。我通常为此列出节点,另外现在Kubernetes还支持在线集群的调试,比如你使用Play with Kubernetes等,或者自建的kubeadm都可以尝试去使用
~> kubectl get nodes
NAME STATUS ROLES AGE VERSION
m01 Ready master 42s v1.17.3复制
我还需要一个入口控制器来访问Argo CD GUI。在Minikube中,只需启用额外的附件即可。
~> minikube addons enable ingress
复制
接下来,我将使用Helm(首选版本3)安装Argo CD:
~> kubectl create namespace argocd
~> helm repo add argo https://argoproj.github.io/argo-helm
~> helm install argocd -n argocd argo/argocd --values values.yaml复制
这是我在此示例中使用的values.yaml文件:
appVersion: "1.4.2"
version: 1.8.7
server:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
hosts:
- argocd.minikube.local复制
之后,将安装我的Argo CD。要访问它,请获取入口地址,并将必要的条目添加到本地/ etc hosts中。
~> kubectl get ingress -n argocd
NAME HOSTS ADDRESS PORTS AGE
argocd-server argocd.minikube.local 192.168.99.105 80 15m
~> echo '192.168.99.105 argocd.minikube.local' | sudo tee -a /etc/hosts复制
现在,我可以从浏览器访问Argo CD GUI。
默认用户名是admin,密码是pod的名称。例:
~> kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2
argocd-server-5cbcf6864-587hr复制

目前为止就这样了。下一步是使用示例代码创建GitLab项目。
4 GitLab项目设置
对于此演示,我有一个用Go编写的小应用程序。这是一个网络应用程序,在其旁边显示文本消息和窗格名称。
GitLab不仅随附CI CD,而且还为每个项目提供了容器注册表。我想在示例中使用它。还必须创建具有API范围的访问令牌。稍后将在管道中将其用于git commit。你可以在USER-> SETTINGS-> ACCESS TOKENS中创建自己的 接下来,将必要的环境变量添加到项目中(设置-> CI CD->变量):CI_PUSH_TOKEN-令牌 CI_USERNAME-令牌所有者的用户名
5 ArgoCD应用程序设置
是时候使用GitOps在Kubernetes中配置我们的应用程序了。如前所述,Argo CD带有一组CRD,可用于声明式配置。当然,这是推荐的方法,因为我们希望将基础结构保留为代码。以下是为开发人员和产品环境配置Web应用程序的清单:
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-dev
namespace: argocd
spec:
project: default
source:
repoURL: https://gitlab.com/andrew.kaczynski/gitops-webapp.git
targetRevision: HEAD
path: deployment/dev
destination:
server: https://kubernetes.default.svc
namespace: dev
syncPolicy:
automated:
prune: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-prod
namespace: argocd
spec:
project: default
source:
repoURL: https://gitlab.com/andrew.kaczynski/gitops-webapp.git
targetRevision: HEAD
path: deployment/prod
destination:
server: https://kubernetes.default.svc
namespace: prod
syncPolicy:
automated:
prune: true复制
这里最重要的部分是:名称-Argo CD应用程序的名称 名称空间-必须与Argo CD实例相同 项目—将在其中配置应用程序的项目名称(这是在Argo CD中组织应用程序的方式) repoURL-我们的源代码存储库的URL targetRevision —你要使用的git分支 path-Kubernetes清单存储在存储库中的路径 destination — Kubernetes与目的地相关的事物(在这种情况下,群集与托管Argo CD的群集相同) 像使用kubectl的其他清单一样应用这些清单。在您的集群中将创建两个对象类型“ application”。
~> kubectl get application -n argocd
NAME AGE
web-app-dev 20m
web-app-prod 17m复制
当你访问Argo CD Web仪表板时,可以看到这两个应用程序。
Argo CD中的应用程序部署
单击其中之一以查看有关应用程序和已部署的Kubernetes对象的更多详细信息。你可以在gitops-webapp存储库中的deployment 目录中找到该对象。你可以看到在每个文件夹中,我创建了kustomization.yaml。Argo CD可以识别它,并且无需任何其他设置即可使用Kustomize 进行应用!我建议你看看可用的选项。GUI非常直观,因此理解它应该没有任何问题。
6 Gitlab CI Pipeline
下一步是创建管道,该管道将自动构建我们的应用程序,推送到容器注册表并在所需环境中更新Kubernetes清单。下面的示例远非完美(缺少测试等),但是它应该向你演示整个GitOps工作流程。基本上,想法是,开发人员在自己的分支上工作。对于分支的每次提交和推送,都会触发阶段构建。当他们将其更改与master分支合并时,将触发整个管道。它将构建应用程序,对其进行容器化,将镜像推送到镜像仓库并根据阶段自动更新Kubernetes清单。此外,部署到Prod需要DevOps手动操作。GitLab CI中的管道定义存储在项目根目录下的.gitlab-ci.yml文件中。文件的顶部是阶段的定义以及默认环境变量,镜像或脚本步骤之前。我的管道摘录:
stages:
- build
- publish
- deploy-dev
- deploy-prod复制
接下来是阶段定义和必需的任务。这里的构建过程非常简单。它仅在docker image golang中执行一个命令。然后将其保存为下一个阶段的工件。此步骤适用于任何分支中的任何新提交。
build:
stage: build
image:
name: golang:1.13.1
script:
- go build -o main main.go
artifacts:
paths:
- main
variables:
CGO_ENABLED: 0复制
下一步是将应用程序部署到开发环境。在GitOps中,这意味着要更新Kubernetes清单,以便Argo CD可以提取更新的版本并应用更改。在这里,我使用为项目定义的环境变量以及用户名和令牌,这些变量需要将更改推送到master分支。当GitLab CI收到带有消息[skip ci]的提交时,不会触发管道(在发布与kustomize清单相关的更改时,我们不想再次运行它)
publish:
stage: publish
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile ./Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
dependencies:
- build
only:
- master复制
下一步是将应用程序部署到开发环境。在GitOps中,这意味着要更新Kubernetes清单,以便Argo CD可以提取更新的版本并应用更改。在这里,我使用为项目定义的环境变量以及用户名和令牌,这些变量需要将更改推送到master分支。当GitLab CI收到带有消息[skip ci]的提交时,不会触发管道(在发布与kustomize清单相关的更改时,我们不想再次运行它)
deploy-dev:
stage: deploy-dev
image: alpine:3.8
before_script:
- apk add --no-cache git curl bash
- curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
- mv kustomize /usr/local/bin/
- git remote set-url origin https://${CI_USERNAME}:${CI_PUSH_TOKEN}@gitlab.com/andrew.kaczynski/gitops-webapp.git
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B master
- cd deployment/dev
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] DEV image update'
- git push origin master
only:
- master复制
最后,我们可以部署到生产环境。它与上一个非常相似,但是需要手动操作才能开始。
deploy-prod:
stage: deploy-prod
image: alpine:3.8
before_script:
- apk add --no-cache git curl bash
- curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
- mv kustomize /usr/local/bin/
- git remote set-url origin https://${CI_USERNAME}:${CI_PUSH_TOKEN}@gitlab.com/andrew.kaczynski/gitops-webapp.git
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B master
- git pull origin master
- cd deployment/prod
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] PROD image update'
- git push origin master
only:
- master
when: manual复制
这是完整的管道定义。我希望你看到与Jenkins相比在GitLab中创建管道是多么容易:)这就是为什么我喜欢它!
7 这个怎么运作?
现在,让我们看看它们如何协同工作。首先,获取应用程序入口的IP,并将必要的条目添加到本地/ etc hosts文件中。
~> kubectl get ingress --all-namespaces |grep gitops
dev gitops-webapp webapp.dev.minikube.local 192.168.99.105 80 25m
prod gitops-webapp webapp.prod.minikube.local 192.168.99.105 80 25m
~> echo "192.168.99.105 webapp.dev.minikube.local" | sudo tee -a /etc/hosts
~> echo "192.168.99.105 webapp.prod.minikube.local" | sudo tee -a /etc/hosts复制
现在,你可以使用浏览器显示Web应用程序消息。让我们看一下dev webapp。
然后是时候进行一些小的更改并将其推送给主服务器了。只需编辑main.go文件,然后将变量ANDREW的名称ANDREW更改为GITOPS
func main() {
welcome := Welcome{"GITOPS", time.Now().Format(time.Stamp), os.Getenv("HOSTNAME")}
复制
提交更改并将其推送给主服务器。然后转到GitLab项目-> CI / CD->管道。你将看到一条刚刚开始的新管道。
等待几分钟,当部署到开发阶段完成时,你将看到一条状态已跳过的新管道(该管道已经为dev更新了清单)。自动同步模式下的Argo CD将在不到一分钟的时间内更新Kubernetes状态。你可以在Argo GUI中查看进度。再次检查网络应用程序以查看更新的消息。
GitLab CI / CD管道
复制

更新了webapp消息
复制
最后,通过批准管道阶段来手动触发产品构建。之后,产品中的镜像也会被更新。

GitLab CI / CD产品部署
复制
同步就绪后,这是Argo CD更新的仪表板。

至此,应用程序已使用GitOps成功部署到开发和生产环境中!
共勉
生命不是要超越别人,而是要超越自己。
如果喜欢😍文章的话,点点关注,就差你的关注了,更多好玩有趣的云原生前沿技术尽在云原生CTO,如果对你有帮助,欢迎分享给更多人
