前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于ArgoCD的GitOps实践

基于ArgoCD的GitOps实践

作者头像
100000798482
发布2023-03-19 13:35:28
1.1K0
发布2023-03-19 13:35:28
举报
文章被收录于专栏:一个番茄说一个番茄说

GitOps是什么

GitOps 是 Weaveworks 提出的一种持续交付方式,它的核心思想是将应用系统的声明性基础架构 和应用程序存放在 Git 版本库中。将 Git 作为交付流水线的核心,每个开发人员都可以提交拉取请求 (Pull Request)并使用 Git 来加速和简化 Kubernetes 的应用程序部署和运维任务。通过使用像 Git 这样的简单工具,开发人员可以更高效地将注意力集中在创建新功能而不是运维相关任务上(例如,应用系统安装、配置、迁移等)。

GitOps主要包含的技术实践

1. Infrastructure as code

如k8s里应用部署的声明、pipeline as code等都应该属于基础设施的版本控制。

2. Pull request

所有的改动都应该通过合并请求review之后纳入主干分支,GitOps中会以git作为唯一可信源,去判 断应用当前的状态是否符合期望,同时也便于审计。

3. CI \ CD

主要涉及的软件包括Jenkins(X)、Gitlab CI 、Argo CD、Spinnaker、Flux等。

使用GitOps前后对比

在没有实践GitOps之前我们的部署过程如下图,我们称之为push模式。当我们需要部署的时候,通过工具或者人工的方式,将应用部署到k8s集群中。其中会带来一系列的问题,如需要依赖外部的客户端(kubectl等)才能操作,这会带来安全隐患,会把服务器以及k8s的访问权限暴露出来。同时操作也没办法进行审计和快速回滚,也没办法实时知道应用部署状态的反馈。

实践GitOps之后我们的部署过程如下图,我们称之为pull模式。可以看出整个过程是由部署在k8s内部的cd主动从git pull信息驱动的。它可以避免管理权限暴露带来的问题,同时所有的操作都有git做版本记录,cd平台会实时监控集群中应用的部署状态是否和git中期望的状态一致,能快速做出回滚等操作响应。

再贴一张整体的研发工作流,以便有一个更加宏观的认识

1. 研发提交代码到git发起合并请求,审查后合并到master,接下来触发持续集成,这里以Jenkins为例。

2. CI流水线大体包含的任务有,拉取代码 -> 构建镜像 -> 执行自动化测试 -> 归档制品(这里的制品主要是容器镜像)

3. CD部分,这里可以看到CD追踪了另一个代码库,也就是说一个git仓库是业务代码,一个仓库存放的是关于这个应用的描述,可以用helm、yaml或者是kustomize。由于部署操作是ArgoCD自动将git与集群中应用的状态进行对比。因此我们需要commit期望的应用状态(比如版本、副本数量等)到这个git仓库中,可以是由开发提交,也可以是由CI上的插件来辅助提交变更。ArgoCD检测到变更后,便会根据git中的定义,将应用部署或者是更新到集群中。

4. 其他的环节和本文主体关联不大,简单提一下还有准入门禁,这里使用了Gate Keeper,可以检测将要部署的应用有没有符合约定的规则,比如是否限制了memory。然后还有一块比较复杂的就是全链路的反馈机制,比如监控、日志、分布式追踪等等,以后有机会再谈。

GitOps实操

前面进行了基本的介绍,接下来就进行实操演示,这里主要是写Jenkins和Argo CD相关的操作,前置准备需要提前完成,包含了如下的东西。

  • kubernetes集群,本文版本v1.21.4
  • 使用calico作为网络组件、rook ceph作为组件、Traefik作为Ingress且完成域名相关配置、 minio作为对象存储、搭建好Gitlab。

1

使用helm在k8s里搭建Jenkins

直接使用Jenkins的helm工程部署

代码语言:javascript
复制
helm repo add jenkinsci https://charts.jenkins.io
helm repo update
kubectl create ns jenkins
helm upgrade --install jenkins -n jenkins -f jenkins-values.yaml jenkinsci/jenkins

可以通过如下命令查看管理员密码,登录上去后请到系统设置里配置和k8s集群的连接,因为我们需要用pod动态做jenkins slave节点。

代码语言:javascript
复制
kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/
chart-admin-password && echo

另外我还创建了IngressRoute以便能外部访问

代码语言:javascript
复制
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: jenkins-ingress
  namespace: jenkins
spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`jenkins.infra.yourdomain.com`)
    kind: Rule
    services:
    - name: jenkins
      port: 8080
  tls:
    certResolver: le

2

使用helm在k8s里搭建ArgoCD

我修改了chart中默认的一些value,chart-values.yaml内容如下

代码语言:javascript
复制

redis-ha:
  enabled: true

controller:
  enableStatefulSet: true

server:
  extraArgs: ["--insecure"] 
  autoscaling:
    enabled: true
    minReplicas: 2

repoServer:
  autoscaling:
    enabled: true
    minReplicas: 2

然后使用这个value创建helm应用

代码语言:javascript
复制
helm upgrade --install argo argo/argo-cd --version 3.29.0  -f chart-values.yaml -n argocd

同样创建了IngressRoute以便能外部访问

代码语言:javascript
复制
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: argocd-server
  namespace: argocd
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`argocd.infra.youedata.com`)
      priority: 10
      services:
        - name: argo-argocd-server
          port: 80
    - kind: Rule
      match: Host(`argocd.infra.youedata.com`) && Headers(`Content-Type`, `application/grpc`)
      priority: 11
      services:
        - name: argo-argocd-server
          port: 80
          scheme: h2c
  tls:
    certResolver: le

3

‍‍Jenkins pipeline的创建示例

CI流水线通过Jenkinsfile描述,纳入版本控制中作为Infrastructure as code。

下面的示例代码中,描述的过程包括拉取代码、运行测试、构建容器、归档容器等操作,需要根据团队实际情况调整。

代码语言:javascript
复制
podTemplate(label: 'jnlp-slave', cloud: 'kubernetes', containers: [
  containerTemplate(name: 'maven', image: 'maven:3.6.0-jdk-8', ttyEnabled: true, command: 'cat'),
  containerTemplate(name: 'docker', image: 'docker:19.03.1-dind', privileged: true)
]) {
  node("jnlp-slave") {
    withCredentials([usernamePassword(credentialsId: 'harbor', passwordVariable: 'harborPassword', usernameVariable: 'harborUser')]) {
      stage('clone code') {
        git credentialsId: 'yq_key', url: 'ssh://git@gitlab-gitlab-shell.gitlab.svc.cluster.local:443/root/springbootstarter.git'
        env.imageTag = sh (script: 'git rev-parse --short HEAD ${GIT_COMMIT}', returnStdout: true).trim()
        sh 'echo $imageTag'
        container('maven') {
          stage('test') {
            sh 'mvn clean package
          }
        }
      }

      container('docker') {
        stage('build image') {
          sh '''
          docker login -u $harborUser -p $harborPassword https://harbor.infra.yourdomain.com
          docker build -t harbor.infra.yourdomain.com/library/springboot-starter-demo:$imageTag .
          docker images
          '''
        }

        stage('push image to registry') {
          sh 'docker push harbor.infra.yourdomain.com/library/springboot-starter-demo:$imageTag'
        }
      }
    }
  }
}

这里定义了一个Pod Template,因为我们的Jenkins利用了k8s的能力做横向扩展,每一个Job都跑在一个Pod内,相当于一个slave节点,这样可以多个构建任务同步进行。在上述的Pod内,安装了maven还有docker,因此后续的job可以使用maven进行jar包构建、测试等,也能够有构建docker容器的能力。 4

ArgoCD部署应用

Argo CD中可以利用GUI界面创建任务,最终生成的是一个CRD对象,类型是Application。因此我们其实也可以直接编写这个Application类型的yaml文件,然后提交到k8s中。下面的示例里部署了一个harbor的应用,这个应用是一个helm工程。里面的destination表明了要把它部署到哪里去,因为示例里是要部署到ArgoCD所在的k8s集群,因此这里的server就直接是用的默认的k8s service。然后source指定是要让Argo去追踪的仓库地址。它会去pull需要部署的内容,然后和k8s中的状态进行sync,具体的syncPolicy中可以指定你期望的行为。

代码语言:javascript
复制
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: harbor
spec:
  destination:
    name: ''
    namespace: harbor
    server: 'https://kubernetes.default.svc'
  source:
    path: ''
    repoURL: 'https://charts.bitnami.com/bitnami'
    targetRevision: 11.1.6
    chart: harbor
    helm:
      parameters:
        - name: global.storageClass
          value: ceph-rbd
        - name: harborAdminPassword
          value: devops
        - name: service.type
          value: ClusterIP
        - name: persistence.persistentVolumeClaim.chartmuseum.size
          value: 1000Gi
        - name: persistence.persistentVolumeClaim.jobservice.size
          value: 50Gi
        - name: persistence.persistentVolumeClaim.registry.size
          value: 1000Gi
        - name: persistence.persistentVolumeClaim.trivy.size
          value: 50Gi
        - name: service.tls.enabled
          value: 'false'
  project: infra
  syncPolicy:
    automated:
      prune: true
      selfHeal: false
    syncOptions:
      - CreateNamespace=true

完成上述工作后,我们就可以在Argo CD的界面里看到应用部署的状态。可以很直观地看到这个应用都生成了哪些对象,拓扑结构如何。也可以很方便地了解到应用部署的状态是否健康。

最后,我想强调的是,我们在做GitOps的时候,工具只是其中很小的一部分,更重要的是我们的工程实践,比如有没有一个好的代码提交习惯,代码的分支管理是否对于持续集成足够友好,测试策略是否能够提前反馈问题,基础设施即代码有没有做等等。只有做好了这些实践,那么才能够最大限度地发挥工具的价值。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 拍篮球的键盘侠 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档