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

简介: 基于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一一对应。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
存储 jenkins 持续交付
660 2
|
jenkins Devops Java
DevOps实践:Jenkins在持续集成与持续部署中的价值
【10月更文挑战第27天】在快速发展的软件开发领域,DevOps实践日益重要。Jenkins作为一款流行的开源自动化服务器,在持续集成(CI)和持续部署(CD)中扮演关键角色。本文通过案例分析,探讨Jenkins在Java项目中的应用,展示其自动化构建、测试和部署的能力,提高开发效率和软件质量。
437 2
|
jenkins Devops 测试技术
DevOps实践:Jenkins在持续集成与持续部署中的价值
【10月更文挑战第26天】随着DevOps理念的普及,Jenkins作为一款开源自动化服务器,在持续集成(CI)与持续部署(CD)中发挥重要作用。本文通过某中型互联网企业的实际案例,展示了Jenkins如何通过自动化构建、持续集成和持续部署,显著提升开发效率、代码质量和软件交付速度,帮助企业解决传统手工操作带来的低效和错误问题。
522 4
|
持续交付 jenkins Devops
WPF与DevOps的完美邂逅:从Jenkins配置到自动化部署,全流程解析持续集成与持续交付的最佳实践
【8月更文挑战第31天】WPF与DevOps的结合开启了软件生命周期管理的新篇章。通过Jenkins等CI/CD工具,实现从代码提交到自动构建、测试及部署的全流程自动化。本文详细介绍了如何配置Jenkins来管理WPF项目的构建任务,确保每次代码提交都能触发自动化流程,提升开发效率和代码质量。这一方法不仅简化了开发流程,还加强了团队协作,是WPF开发者拥抱DevOps文化的理想指南。
322 1
|
持续交付 jenkins C#
“WPF与DevOps深度融合:从Jenkins配置到自动化部署全流程解析,助你实现持续集成与持续交付的无缝衔接”
【8月更文挑战第31天】本文详细介绍如何在Windows Presentation Foundation(WPF)项目中应用DevOps实践,实现自动化部署与持续集成。通过具体代码示例和步骤指导,介绍选择Jenkins作为CI/CD工具,结合Git进行源码管理,配置构建任务、触发器、环境、构建步骤、测试及部署等环节,显著提升开发效率和代码质量。
362 0
|
敏捷开发 jenkins 测试技术
阿里云云效产品使用问题之如何进行类似于jenkins那样参数化构建
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
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
236 0
|
jenkins Devops 机器人
【DevOps】(五)Jenkins构建给企业微信推送消息
【DevOps】(五)Jenkins构建给企业微信推送消息
727 1
|
12月前
|
监控 jenkins Shell
jenkins结合gitlab实现CI(持续集成)
通过本文的介绍,我们详细了解了如何结合Jenkins和GitLab实现持续集成。从环境准备、插件配置到Pipeline任务创建和CI流程监控,每一步都提供了详细的操作步骤和示例代码。希望本文能帮助开发者快速搭建起高效的CI系统,提高项目开发效率和代码质量。
1189 9
|
Java jenkins 持续交付
Jenkins集成Maven
通过以上步骤,可以在Jenkins中成功集成Maven,实现自动化构建和部署。通过定时构建、SCM轮询等方式,可以确保代码库中的最新变更能够及时构建和测试,提高开发效率和代码质量。这种集成方式在实际项目中具有广泛的应用前景,能够显著提升团队的协作效率。
446 8

推荐镜像

更多