基于Jenkins+Argocd+Argo Rollouts的DevOps实现并用金丝雀发布(上)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 基于Jenkins+Argocd+Argo Rollouts的DevOps实现并用金丝雀发布

优化Argocd触发CD的速度


Argo CD每三分钟轮询一次Git存储库,以检测清单的变化。为了消除轮询带来的延迟,可以将API服务器配置为接收Webhook事件。Argo CD支持来自GitHub,GitLab,Bitbucket,Bitbucket Server和Gogs的Git Webhook通知,更多点击官网:

https://argoproj.github.io/argo-cd/


我这里使用Gitlab作为仓库地址。


(1)在argocd中配置webhook token


使用kubectl edit secret argocd-secret -n argocd命令进行配置:


apiVersion: v1
kind: Secret
metadata:
  name: argocd-secret
  namespace: argocd
type: Opaque
data:
...
stringData:
  # gitlab webhook secret
  webhook.gitlab.secret: coolops


配置完点击保存会自动生成一个secret,如下:


# kubectl describe secret argocd-secret -n argocd
Name:         argocd-secret
Namespace:    argocd
Labels:       app.kubernetes.io/name=argocd-secret
              app.kubernetes.io/part-of=argocd
Annotations:  
Type:         Opaque
Data
====
admin.passwordMtime:    20 bytes
server.secretkey:       44 bytes
tls.crt:                1237 bytes
tls.key:                1679 bytes
webhook.gitlab.secret:  7 bytes
admin.password:         60 bytes


(2)在gitlab的代码仓库配置webhook,如下:


640.png


由于集群内部证书是无效证书,所有要把Enabled SSL去掉,如下:


640.png


然后点击保存,点击测试,看是否链接成功。如果有如下提示则表示webhook配置没问题了。


640.png


现在可以进行修改gitlab仓库,观察是否一提交,argocd那边就可以响应了。


使用argo rollouts进行金丝雀发布


关于argo rollouts的更多介绍可以查看之前的文章《使用argo-rollouts实现金丝雀发布》


按着官方文档进行安装,官方地址为:https://argoproj.github.io/argo-rollouts/installation/#kubectl-plugin-installation


(1)在Kubernetes集群中安装argo-rollouts


kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml


(2)安装argo-rollouts的kubectl plugin


curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x ./kubectl-argo-rollouts-linux-amd64
mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts


(3)我们这里主要是要重写deployment的配置文件,主要的配置清单如下。


rollout.yaml


apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-simple-java
spec:
  replicas: 3
  strategy:
    canary:
      canaryService: rollouts-simple-java-canary
      stableService: rollouts-simple-java-stable
      trafficRouting:
        nginx:
          stableIngress: rollouts-simple-java-stable
      steps:
      - setWeight: 20
      - pause: {duration: 60}
      - setWeight: 50
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollouts-simple-java
  template:
    metadata:
      labels:
        app: rollouts-simple-java
    spec:
      containers:
        - args:
            - -jar
            - /opt/myapp.jar
            - --server.port=8080
          command:
            - java
          env:
            - name: HOST_IP
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: status.hostIP
          image: registry.cn-hangzhou.aliyuncs.com/rookieops/myapp:latest
          imagePullPolicy: IfNotPresent
          lifecycle:
            preStop:
              exec:
                command:
                  - /bin/sh
                  - -c
                  - /bin/sleep 30
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /hello
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 60
            periodSeconds: 15
            successThreshold: 1
            timeoutSeconds: 1
          name: myapp
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /hello
              port: 8080
              scheme: HTTP
            periodSeconds: 15
            successThreshold: 1
            timeoutSeconds: 1
          resources:
            limits:
              cpu: "1"
              memory: 2Gi
            requests:
              cpu: 100m
              memory: 1Gi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      dnsPolicy: ClusterFirstWithHostNet
      imagePullSecrets:
        - name: gitlab-registry


services.yaml


apiVersion: v1
kind: Service
metadata:
  name: rollouts-simple-java-canary
spec:
  ports:
  - port: 8080
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollouts-simple-java
    # This selector will be updated with the pod-template-hash of the canary ReplicaSet. e.g.:
    # rollouts-pod-template-hash: 7bf84f9696
---
apiVersion: v1
kind: Service
metadata:
  name: rollouts-simple-java-stable
spec:
  ports:
  - port: 8080
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollouts-simple-java
    # This selector will be updated with the pod-template-hash of the stable ReplicaSet. e.g.:
    # rollouts-pod-template-hash: 789746c88d


ingress.yaml


apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: rollouts-simple-java-stable
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: rollouts-simple-java.coolops.cn
    http:
      paths:
      - path: /
        backend:
          # Reference to a Service name, also specified in the Rollout spec.strategy.canary.stableService field
          serviceName: rollouts-simple-java-stable
          servicePort: 8080


kustomization.yaml


# Example configuration for the webserver
# at https://github.com/monopole/hello
commonLabels:
  app: rollouts-simple-java
resources:
- rollout.yaml
- services.yaml
- ingress.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: registry.cn-hangzhou.aliyuncs.com/rookieops/myapp
  newTag: "latest"
namespace: dev


让后将这些文件保存到gitlab yaml仓库里,比如:


640.png


这里的金丝雀发布是才有的时间暂停的方式,还可以采用手动继续的方式。我这里方便测试就才有了时间暂停。


给代码仓库打Tag


为啥要给代码仓库打Tag呢?


当一个代码仓库进过长时间的迭代,针对不同的时期和需求,必定会有不同的版本。而借助 Git 提供的标签功能,可以快捷方便地记录代码版本。无论什么时候,想取回某个版本,不再需要查找冗长的commit_id,只需要取出打标签的历史版本即可。


可以这么理解:标签是版本库的一个快照。在主流的 Git 平台上,版本可以直接下载的,节省了开发者的不少精力。


这里通过gitlab的api对代码仓库打tag。API的具体操作见

https://docs.gitlab.com/ee/api/tags.html


这里在shareLibrary的代码仓库中创建了gitlab.groovy文件。


640.png


具体内容如下:


package org.devops
//封装HTTP请求
def HttpReq(reqType,reqUrl,reqBody){
    def gitServer = "http://172.17.100.135:32080/api/v4"
    withCredentials([string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {
      result = httpRequest customHeaders: [[maskValue: true, name: 'PRIVATE-TOKEN', value: "${gitlabToken}"]], 
                httpMode: reqType, 
                contentType: "APPLICATION_JSON",
                consoleLogResponseBody: true,
                ignoreSslErrors: true, 
                requestBody: reqBody,
                url: "${gitServer}/${reqUrl}"
                //quiet: true
    }
    return result
}
//获取项目ID
def GetProjectID(projectName){
    projectApi = "projects?search=${projectName}"
    response = HttpReq('GET',projectApi,'')
    def result = readJSON text: """${response.content}"""
    for (repo in result){
       // println(repo['path_with_namespace'])
        if (repo['path'] == "${projectName}"){
            repoId = repo['id']
            println(repoId)
        }
    }
    return repoId
}
// 给仓库打tag
def TagGitlab(projectId,tag_name,tag_ref){
    def apiUrl = "projects/${projectId}/repository/tags"
    reqBody = """{"tag_name": "${tag_name}","ref": "${tag_ref}"}"""
    HttpReq('POST',apiUrl,reqBody)
}


首先通过GetProjectID获取到项目仓库的ID,然后再调用TagGitlab进行打Tag。


然后我们需要在Jenkins上创建一个名叫gitlab-token的token凭据。


(1)在gitlab上生成token


640.png


(2)在Jenkins上创建凭据


系统管理->凭据管理->全局凭据->添加凭据


640.png


注意这个ID,要和gitlab.groovy中的ID一一对应。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
18天前
|
jenkins Devops Java
DevOps实践:Jenkins在持续集成与持续部署中的价值
【10月更文挑战第27天】在快速发展的软件开发领域,DevOps实践日益重要。Jenkins作为一款流行的开源自动化服务器,在持续集成(CI)和持续部署(CD)中扮演关键角色。本文通过案例分析,探讨Jenkins在Java项目中的应用,展示其自动化构建、测试和部署的能力,提高开发效率和软件质量。
40 2
|
19天前
|
jenkins Devops 测试技术
DevOps实践:Jenkins在持续集成与持续部署中的价值
【10月更文挑战第26天】随着DevOps理念的普及,Jenkins作为一款开源自动化服务器,在持续集成(CI)与持续部署(CD)中发挥重要作用。本文通过某中型互联网企业的实际案例,展示了Jenkins如何通过自动化构建、持续集成和持续部署,显著提升开发效率、代码质量和软件交付速度,帮助企业解决传统手工操作带来的低效和错误问题。
45 4
|
6月前
|
jenkins Devops 机器人
【DevOps】(五)Jenkins构建给企业微信推送消息
【DevOps】(五)Jenkins构建给企业微信推送消息
268 1
|
3月前
|
持续交付 jenkins Devops
WPF与DevOps的完美邂逅:从Jenkins配置到自动化部署,全流程解析持续集成与持续交付的最佳实践
【8月更文挑战第31天】WPF与DevOps的结合开启了软件生命周期管理的新篇章。通过Jenkins等CI/CD工具,实现从代码提交到自动构建、测试及部署的全流程自动化。本文详细介绍了如何配置Jenkins来管理WPF项目的构建任务,确保每次代码提交都能触发自动化流程,提升开发效率和代码质量。这一方法不仅简化了开发流程,还加强了团队协作,是WPF开发者拥抱DevOps文化的理想指南。
85 1
|
3月前
|
持续交付 jenkins C#
“WPF与DevOps深度融合:从Jenkins配置到自动化部署全流程解析,助你实现持续集成与持续交付的无缝衔接”
【8月更文挑战第31天】本文详细介绍如何在Windows Presentation Foundation(WPF)项目中应用DevOps实践,实现自动化部署与持续集成。通过具体代码示例和步骤指导,介绍选择Jenkins作为CI/CD工具,结合Git进行源码管理,配置构建任务、触发器、环境、构建步骤、测试及部署等环节,显著提升开发效率和代码质量。
76 0
|
5月前
|
敏捷开发 jenkins 测试技术
阿里云云效产品使用问题之如何进行类似于jenkins那样参数化构建
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
5月前
|
Kubernetes Cloud Native jenkins
云原生时代:从Jenkins到Argo Workflows,构建高效CI Pipeline
基于Argo Workflows可以构建大规模、高效率、低成本的CI流水线
|
6月前
|
jenkins Devops Shell
【DevOps】jenkins出现stderr: fatal: cannot exec ‘/tmp/pass2225150599970077606.sh‘: Text file busy
【DevOps】jenkins出现stderr: fatal: cannot exec ‘/tmp/pass2225150599970077606.sh‘: Text file busy
71 0
|
3月前
|
jenkins 持续交付 开发者
自动化部署:使用Jenkins和Docker实现持续集成与交付
【8月更文挑战第31天】本文旨在为读者揭示如何通过Jenkins和Docker实现自动化部署,从而加速软件开发流程。我们将从基础概念讲起,逐步深入到实际操作,确保即使是初学者也能跟上步伐。文章将提供详细的步骤说明和代码示例,帮助读者理解并应用这些工具来优化他们的工作流程。
|
6天前
|
运维 jenkins Java
Jenkins在持续集成与持续部署中的价值
Jenkins在持续集成与持续部署中的价值