gitops
基于Arg CD 和 Gitlab CI 实现的自动同步镜像到k8s集群中
前置环境
- helm
- k8s集群
- ingress
- gitlab
- gitlab-runner 不需要在k8s集群中,任意runner
helm 安装参考:https://gaodongfei.com/archives/h-e-l-m
Argo CD 安装
首先创建argocd 的命名空间
kubectl create ns argocd
然后添加 argocd 的 chart 仓库地址:
helm repo add argo https://argoproj.github.io/argo-helm
接下来我们就可以使用 Helm 安装 Argo CD 了:
- 创建ingress定制化values.yaml文件,只是暴露argocd-server来访问dashboard
cat << 'EOF' > ./values.yaml
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.k8s.local
EOF
- 安装argocd
helm install argocd -n argocd argo/argo-cd --values values.yaml
helm ls -n argocd # 查看helm安装的chart情况
helm delete argocd -n argocd # 删除chart
等待:pod全部running状态
kubectl get pods -n argocd
通过dashboard登录
-
协议:https协议
-
Host: argocd.k8s.local
-
端口:ingress-svc 的https端口
-
用户名:admin
-
密码:argocd-server的pod名称
GitLab项目配置
CI的变量中添加:
-
CI_REGISTRY 镜像仓库地址,值为:https://index.docker.io/v1/
-
CI_REGISTRY_IMAGE 镜像名称,值为:cnych/gitops-webapp
-
CI_REGISTRY_USER Docker Hub 仓库用户名,值为 cnych
-
CI_REGISTRY_PASSWORD Docker Hub 仓库密码
-
CI_PASSWORD Git 仓库访问密码
-
CI_USERNAME Git 仓库访问用户名
ArgoCD配置
现在我们可以开始使用 GitOps 来配置我们的 Kubernetes 中的应用了。Argo CD 自带了一套 CRD 对象,可以用来进行声明式配置,这当然也是推荐的方式,把我们的基础设施作为代码来进行托管:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-test
namespace: argocd
spec:
project: default
source:
repoURL: http://gitlab.intsig.net/dongfei_gao/textin_studio_cloud.git
targetRevision: HEAD
path: kubernetes/test
destination:
server: https://kubernetes.default.svc
namespace: test
syncPolicy:
automated:
prune: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-pre
namespace: argocd
spec:
project: default
source:
repoURL: http://gitlab.intsig.net/dongfei_gao/textin_studio_cloud.git
targetRevision: HEAD
path: kubernetes/pre
destination:
server: https://kubernetes.default.svc
namespace: pre
syncPolicy:
automated:
prune: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-pro
namespace: argocd
spec:
project: default
source:
repoURL: http://gitlab.intsig.net/dongfei_gao/textin_studio_cloud.git
targetRevision: HEAD
path: kubernetes/pro
destination:
server: https://kubernetes.default.svc
namespace: pro
syncPolicy:
automated:
prune: true
上面定义的 Application 这个资源,就是 Argo CD 用于描述应用的 CRD 对象:
-
name:Argo CD 应用程序的名称
-
project:应用程序将被配置的项目名称,这是在 Argo CD 中应用程序的一种组织方式
-
repoURL:源代码的仓库地址
-
targetRevision:想要使用的 git 分支
-
path:Kubernetes 资源清单在仓库中的路径
-
destination:Kubernetes 集群中的目标
项目结构:
然后同样使用 kubectl 工具直接部署上面的资源对象即可,将会创建两个 Application 类型的对象:
$ kubectl apply -f gitops-demo-app.yaml
application.argoproj.io/web-app-test created
application.argoproj.io/web-app-pre created
application.argoproj.io/web-app-pro created
$ kubectl get application -n argocd
此时我们再去 Argo CD 的 Dashboard 首页同样将会看到两个 Application 的信息:
点击其中一个就可以看到关于应用的详细信息,我们可以在 gitops-webapp 代码仓库的 deployment/
目录里面找到资源对象。我们可以看到,在每个文件夹下面都有一个 kustomization.yaml
文件,Argo CD 可以识别它,不需要任何其他的设置就可以使用。
由于我们这里的代码仓库是私有的 GitLab,所以我们还需要配置对应的仓库地址,在页面上 Settings → Repositories,点击 Connect Repo using HTTPS
按钮:
添加我们的代码仓库认证信息:
需要注意的是这里默认使用的是 HTTPS,所以我们需要勾选下方的 Skip server verification
,然后点击上方的 CONNECT
按钮添加即可。然后重新同步上面的两个 Application,就可以看到正常的状态了。
GitLab CI 流水线
接下来我们需要为应用程序创建流水线,自动构建我们的应用程序,推送到镜像仓库,然后更新 Kubernetes 的资源清单文件。
下面的示例并不是一个多么完美的流水线,但是基本上可以展示整个 GitOps 的工作流。开发人员在自己的分支上开发代码,他们分支的每一次提交都会触发一个阶段性的构建,当他们将自己的修改和主分支合并时,完整的流水线就被触发。将构建应用程序,打包成 Docker 镜像,将镜推送到 Docker 仓库,并自动更新 Kubernetes 资源清单,此外,一般情况下将应用部署到生产环境需要手动操作。
GitLab CI 中的流水线默认定义在代码仓库根目录下的 .gitlab-ci.yml
文件中,在该文件的最上面定义了一些构建阶段和环境变量、镜像以及一些前置脚本
然后就是构建镜像并推送到镜像仓库,这里我们使用 Kaniko,当然也可以使用 DinD 模式进行构建,只是安全性不高,这里我们可以使用 GIT 提交的 commit 哈希值作为镜像 tag,关于 Docker 镜像仓库的认证和镜像地址信息可以通过项目的参数来进行传递,不过这个阶段只在主分支发生变化时才会触发:
下一个阶段就是将应用程序部署到开发环境中,在 GitOps 中就意味着需要更新 Kubernetes 的资源清单,这样 Argo CD 就可以拉取更新的版本来部署应用。这里我们使用了为项目定义的环境变量,包括用户名和 TOKEN,此外在提交消息里面增加 [skip ci]
这样的关键字,这样流水线就不会被触发:
最后添加一个部署到 prod 环境的阶段,和前面非常类似,只是添加了一个手动操作的流程:
需要修改的是 deploy阶段中的git url地址
image: studio_cloud:v1
stages:
- publish
- deploy-test
- deploy-pre
- deploy-pro
publish:
stage: publish
image:
name: cnych/kaniko-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_SHORT_SHA
only:
- master
deploy-test:
stage: deploy-test
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin http://${CI_USERNAME}:${CI_PASSWORD}@gitlab.intsig.net/dongfei_gao/textin_studio_cloud.git
- git config --global user.email "gitlab@git.k8s.local"
- git config --global user.name "gitLab-ci-robot"
script:
- git checkout -B master
- git pull origin master
- cd kubernetes/test
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] DEV image update'
- git push origin master
only:
- master
deploy-pre:
stage: deploy-pre
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin http://${CI_USERNAME}:${CI_PASSWORD}@gitlab.intsig.net/dongfei_gao/textin_studio_cloud.git
- git config --global user.email "gitlab@git.k8s.local"
- git config --global user.name "gitLab-ci-robot"
script:
- git checkout -B master
- git pull origin master
- cd kubernetes/pre
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] PROD image update'
- git push origin master
only:
- master
when: manual
deploy-pro:
stage: deploy-pro
image: cnych/kustomize:v1.0
before_script:
- git remote set-url origin http://${CI_USERNAME}:${CI_PASSWORD}@gitlab.intsig.net/dongfei_gao/textin_studio_cloud.git
- git config --global user.email "gitlab@git.k8s.local"
- git config --global user.name "gitLab-ci-robot"
script:
- git checkout -B master
- git pull origin master
- cd kubernetes/pro
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] PROD image update'
- git push origin master
only:
- master
when: manual
部署完!
原理:
-
argocd 中部署的application 会自动监听并且识别kubernetes中的kustomization中的变化,并且同步到集群中。
-
Gitlab CI 中做的是将镜像推送到harbour中,kustomize 会自动更新kustomization中的image镜像,形成commit记录