zoukankan      html  css  js  c++  java
  • DevOps平台实践

    基于Kubernetes的DevOps平台实践

    持续集成工具:

    • Jenkins
    • gitlabci
    • Tekton

    DevOps、CI、CD介绍

    Continuous Integration (CI) / Continuous Delivery (CD)

    软件交付流程
    image
    一个软件从零开始到最终交付,大概包括以下几个阶段:规划、编码、构建、测试、发布、部署和维护,基于这些阶段,我们的软件交付模型大致经历了几个阶段:

    瀑布式流程

    image
    前期需求确立之后,软件开发人员花费数周和数月编写代码,把所有需求一次性开发完,然后将代码交给QA(质量保障)团队进行测试,然后将最终的发布版交给运维团队去部署。瀑布模型,简单来说,就是等一个阶段所有工作完成之后,再进入下一个阶段。这种模式的问题也很明显,产品迭代周期长,灵活性差。一个周期动辄几周几个月,适应不了当下产品需要快速迭代的场景。

    敏捷开发

    image
    任务由大拆小,开发、测试协同工作,注重开发敏捷,不重视交付敏捷

    DevOps

    image
    开发、测试、运维协同工作, 持续开发+持续交付。

    DevOps工具链
    image

    靠这些工具和技术,才实现了自动化流程,进而解决了协作成本,使得devops具备了可落地性。因此我们可以大致给devops一个定义:

    Devops = 提倡开发、测试、运维协同工作来实现持续开发、持续交付的一种软件交付模式 + 基于工具和技术支撑的自动化流程的落地实践。

    因此devops不是某一个具体的技术,而是一种思想+自动化能力,来使得构建、测试、发布软件能够更加地便捷、频繁和可靠的落地实践。本次课程核心内容就是要教会大家如何利用工具和技术来实现完整的DevOps平台的建设。我们主要使用的工具有:

    1. gitlab,代码仓库,企业内部使用最多的代码版本管理工具。
    2. Jenkins, 一个可扩展的持续集成引擎,用于自动化各种任务,包括构建、测试和部署软件。
    3. robotFramework, 基于Python的自动化测试框架
    4. sonarqube,代码质量管理平台
    5. maven,java包构建管理工具
    6. Kubernetes
    7. Docker

    Jenkins初体验

    Kubernetes环境中部署jenkins

    其他部署方式
    注意点:

    1. 第一次启动很慢
    2. 因为后面Jenkins会与kubernetes集群进行集成,会需要调用kubernetes集群的api,因此安装的时候创建了ServiceAccount并赋予了cluster-admin的权限
    3. 默认部署到jenkins=true的节点
    4. 初始化容器来设置权限
    5. ingress来外部访问
    6. 数据存储通过hostpath挂载到宿主机中

    jenkins/jenkins-all.yaml

    apiVersion: v1
    kind: Namespace
    metadata:
      name: jenkins
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: jenkins
      namespace: jenkins
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: jenkins-crb
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: jenkins
      namespace: jenkins
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: jenkins-master
      namespace: jenkins
    spec:
      replicas: 1
      selector:
        matchLabels:
          devops: jenkins-master
      template:
        metadata:
          labels:
            devops: jenkins-master
        spec:
          nodeSelector:
            jenkins: "true"
          serviceAccount: jenkins #Pod 需要使用的服务账号
          initContainers:
          - name: fix-permissions
            image: busybox
            command: ["sh", "-c", "chown -R 1000:1000 /var/jenkins_home"]
            securityContext:
              privileged: true
            volumeMounts:
            - name: jenkinshome
              mountPath: /var/jenkins_home
          containers:
          - name: jenkins
            image: jenkinsci/blueocean:1.23.2
            imagePullPolicy: IfNotPresent
            ports:
            - name: http #Jenkins Master Web 服务端口
              containerPort: 8080
            - name: slavelistener #Jenkins Master 供未来 Slave 连接的端口
              containerPort: 50000
            volumeMounts:
            - name: jenkinshome
              mountPath: /var/jenkins_home
            env:
            - name: JAVA_OPTS
              value: "-Xms4096m -Xmx5120m -Duser.timezone=Asia/Shanghai -Dhudson.model.DirectoryBrowserSupport.CSP="
          volumes:
          - name: jenkinshome
            hostPath:
              path: /var/jenkins_home/
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: jenkins
      namespace: jenkins
    spec:
      ports:
      - name: http
        port: 8080
        targetPort: 8080
      - name: slavelistener
        port: 50000
        targetPort: 50000
      type: ClusterIP
      selector:
        devops: jenkins-master
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: jenkins-web
      namespace: jenkins
    spec:
      rules:
      - host: jenkins.luffy.com
        http:
          paths:
          - backend:
              serviceName: jenkins
              servicePort: 8080
            path: /
    

    创建服务:

    ## 为k8s-slave1打标签,将jenkins-master部署在k8s-slave1节点
    $ kubectl label node k8s-slave1 jenkins=true
    ## 部署服务
    $ kubectl create -f jenkins-all.yaml
    ## 查看服务
    $ kubectl -n jenkins get po
    NAME                              READY   STATUS    RESTARTS   AGE
    jenkins-master-767df9b574-lgdr5   1/1     Running   0          20s
    
    # 查看日志,第一次启动提示需要完成初始化设置
    $ kubectl -n jenkins logs -f jenkins-master-767df9b574-lgdr5
    ......
    *************************************************************
    
    Jenkins initial setup is required. An admin user has been created and a password generated.
    Please use the following password to proceed to installation:
    
    5396b4e1c395450f8360efd8ee641b18
    
    This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
    
    *************************************************************
    
    

    访问服务:

    配置hosts解析,192.168.136.10 jenkins.luffy.com,然后使用浏览器域名访问服务。第一次访问需要大概几分钟的初始化时间。
    image
    使用jenkins启动日志中的密码,或者执行下面的命令获取解锁的管理员密码:

    $ kubectl -n jenkins exec jenkins-master-767df9b574-lgdr5 bash 
    / # cat /var/jenkins_home/secrets/initialAdminPassword
    35b083de1d25409eaef57255e0da481a
    
    

    点击叉号,跳过选择安装推荐的插件环节,直接进入Jenkins。由于默认的插件地址安装非常慢,我们可以替换成国内清华的源,进入 jenkins 工作目录,目录下面有一个 updates 的目录,下面有一个 default.json 文件,我们执行下面的命令替换插件地址:

    $ cd /var/jenkins_home/updates
    $ sed -i 's/http://updates.jenkins-ci.org/download/https://mirrors.tuna.tsinghua.edu.cn/jenkins/g' default.json 
    $ sed -i 's/http://www.google.com/https://www.baidu.com/g' default.json
    
    

    暂时先不用重新启动pod,汉化后一起重启。

    选择右上角admin->configure->password重新设置管理员密码,设置完后,会退出要求重新登录,使用admin/xxxxxx(新密码),登录即可。
    image

    安装汉化插件

    Jenkins -> manage Jenkins -> Plugin Manager -> Avaliable,搜索 chinese关键字
    image
    选中后,选择[Install without restart],等待下载完成,然后点击[ Restart Jenkins when installation is complete and no jobs are running ],让Jenkins自动重启

    启动后,界面默认变成中文。

    Jenkins基本使用演示
    演示目标
    • 代码提交gitlab,自动触发Jenkins任务
    • Jenkins任务完成后发送钉钉消息通知
    演示准备
    演示准备

    gitlab代码仓库搭建

    https://github.com/sameersbn/docker-gitlab

    ## 全量部署的组件
    $ gitlab-ctl status
    run: alertmanager: (pid 1987) 27s; run: log: (pid 1986) 27s
    run: gitaly: (pid 1950) 28s; run: log: (pid 1949) 28s
    run: gitlab-exporter: (pid 1985) 27s; run: log: (pid 1984) 27s
    run: gitlab-workhorse: (pid 1956) 28s; run: log: (pid 1955) 28s
    run: logrotate: (pid 1960) 28s; run: log: (pid 1959) 28s
    run: nginx: (pid 2439) 1s; run: log: (pid 1990) 27s
    run: node-exporter: (pid 1963) 28s; run: log: (pid 1962) 28s
    run: postgres-exporter: (pid 1989) 27s; run: log: (pid 1988) 27s
    run: postgresql: (pid 1945) 28s; run: log: (pid 1944) 28s
    run: prometheus: (pid 1973) 28s; run: log: (pid 1972) 28s
    run: puma: (pid 1968) 28s; run: log: (pid 1966) 28s
    run: redis: (pid 1952) 28s; run: log: (pid 1951) 28s
    run: redis-exporter: (pid 1971) 28s; run: log: (pid 1964) 28s
    run: sidekiq: (pid 1969) 28s; run: log: (pid 1967) 28s
    

    部署分析:

    1. 依赖postgres

    2. 依赖redis
      使用k8s部署:

    3. 准备secret文件

      $ cat gitlab-secret.txt
      postgres.user.root=root
      postgres.pwd.root=1qaz2wsx
      
      $ kubectl -n jenkins create secret generic gitlab-secret --from-env-file=gitlab-secret.txt
      
    4. 部署postgres

      注意点:

      • 使用secret来引用账户密码
      • 使用postgres=true来指定节点
      $ cat postgres.yaml
      apiVersion: v1
      kind: Service
      metadata:
        name: postgres
        labels:
          app: postgres
        namespace: jenkins
      spec:
        ports:
        - name: server
          port: 5432
          targetPort: 5432
          protocol: TCP
        selector:
          app: postgres
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        namespace: jenkins
        name: postgres
        labels:
          app: postgres
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: postgres
        template:
          metadata:
            labels:
              app: postgres
          spec:
            nodeSelector:
              postgres: "true"
            tolerations:
            - operator: "Exists"
            containers:
            - name: postgres
              image:  192.168.136.10:5000/postgres:11.4 #若本地没有启动该仓库,换成postgres:11.4
              imagePullPolicy: "IfNotPresent"
              ports:
              - containerPort: 5432
              env:
              - name: POSTGRES_USER           #PostgreSQL 用户名
                valueFrom:
                  secretKeyRef:
                    name: gitlab-secret
                    key: postgres.user.root
              - name: POSTGRES_PASSWORD       #PostgreSQL 密码
                valueFrom:
                  secretKeyRef:
                    name: gitlab-secret
                    key: postgres.pwd.root
              resources:
                limits:
                  cpu: 1000m
                  memory: 2048Mi
                requests:
                  cpu: 50m
                  memory: 100Mi
              volumeMounts:
              - mountPath: /var/lib/postgresql/data
                name: postgredb
            volumes:
            - name: postgredb
              hostPath:
                path: /var/lib/postgres/
                
      
      #部署到k8s-slave2节点
      $ kubectl label node k8s-slave2 postgres=true
      
      #创建postgres
      $ kubectl create -f postgres.yaml
      
      # 创建数据库gitlab,为后面部署gitlab组件使用
      $ kubectl -n jenkins exec -ti postgres-7ff9b49f4c-nt8zh bash
      root@postgres-7ff9b49f4c-nt8zh:/# psql
      root=# create database gitlab;
      CREATE DATABASE
      
    5. 部署redis

      $ cat redis.yaml
      apiVersion: v1
      kind: Service
      metadata:
        name: redis
        labels:
          app: redis
        namespace: jenkins
      spec:
        ports:
        - name: server
          port: 6379
          targetPort: 6379
          protocol: TCP
        selector:
          app: redis
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        namespace: jenkins
        name: redis
        labels:
          app: redis
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: redis
        template:
          metadata:
            labels:
              app: redis
          spec:
            tolerations:
            - operator: "Exists"
            containers:
            - name: redis
              image:  sameersbn/redis:4.0.9-2
              imagePullPolicy: "IfNotPresent"
              ports:
              - containerPort: 6379
              resources:
                limits:
                  cpu: 1000m
                  memory: 2048Mi
                requests:
                  cpu: 50m
                  memory: 100Mi
                  
      # 创建
      $ kubectl create -f redis.yaml
      
    6. 部署gitlab

      注意点:

      • 使用ingress暴漏服务
      • 添加annotation,指定nginx端上传大小限制,否则推送代码时会默认被限制1m大小,相当于给nginx设置client_max_body_size的限制大小
      • 使用gitlab=true来选择节点
      • 使用服务发现地址来访问postgres和redis
      • 在secret中引用数据库账户和密码
      • 数据库名称为gitlab
      $ cat gitlab.yaml
      apiVersion: extensions/v1beta1
      kind: Ingress
      metadata:
        name: gitlab
        namespace: jenkins
        annotations:
          nginx.ingress.kubernetes.io/proxy-body-size: "50m"
      spec:
        rules:
        - host: gitlab.luffy.com
          http:
            paths:
            - backend:
                serviceName: gitlab
                servicePort: 80
              path: /
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: gitlab
        labels:
          app: gitlab
        namespace: jenkins
      spec:
        ports:
        - name: server
          port: 80
          targetPort: 80
          protocol: TCP
        selector:
          app: gitlab
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        namespace: jenkins
        name: gitlab
        labels:
          app: gitlab
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: gitlab
        template:
          metadata:
            labels:
              app: gitlab
          spec:
            nodeSelector:
              gitlab: "true"
            tolerations:
            - operator: "Exists"
            containers:
            - name: gitlab
              image:  sameersbn/gitlab:13.2.2
              imagePullPolicy: "IfNotPresent"
              env:
              - name: GITLAB_HOST
                value: "gitlab.luffy.com"
              - name: GITLAB_PORT
                value: "80"
              - name: GITLAB_SECRETS_DB_KEY_BASE
                value: "long-and-random-alpha-numeric-string"
              - name: GITLAB_SECRETS_DB_KEY_BASE
                value: "long-and-random-alpha-numeric-string"
              - name: GITLAB_SECRETS_SECRET_KEY_BASE
                value: "long-and-random-alpha-numeric-string"
              - name: GITLAB_SECRETS_OTP_KEY_BASE
                value: "long-and-random-alpha-numeric-string"
              - name: DB_HOST
                value: "postgres"
              - name: DB_NAME
                value: "gitlab"
              - name: DB_USER
                valueFrom:
                  secretKeyRef:
                    name: gitlab-secret
                    key: postgres.user.root
              - name: DB_PASS
                valueFrom:
                  secretKeyRef:
                    name: gitlab-secret
                    key: postgres.pwd.root
              - name: REDIS_HOST
                value: "redis"
              - name: REDIS_PORT
                value: "6379"
              ports:
              - containerPort: 80
              resources:
                limits:
                  cpu: 2000m
                  memory: 5048Mi
                requests:
                  cpu: 100m
                  memory: 500Mi
              volumeMounts:
              - mountPath: /home/git/data
                name: data
            volumes:
            - name: data
              hostPath:
                path: /var/lib/gitlab/
      
      #部署到k8s-slave2节点
      $ kubectl label node k8s-slave2 gitlab=true
      
      # 创建
      $ kubectl create -f gitlab.yaml
      

    配置hosts解析:

    192.168.136.10 gitlab.luffy.com
    

    设置root密码

    访问http://gitlab.luffy.com,设置管理员密码

    配置k8s-master节点的hosts

    $ echo "192.168.136.10 gitlab.luffy.com" >>/etc/hosts
    

    myblog项目推送到gitlab

    mkdir demo
    cp -r myblog demo/
    cd demo/myblog
    git remote rename origin old-origin
    git remote add origin http://gitlab.luffy.com/root/myblog.git
    git push -u origin --all
    git push -u origin --tags
    
    

    钉钉推送

    官方文档

    配置机器人

    • 试验发送消息

      $ curl 'https://oapi.dingtalk.com/robot/send?access_token=5a68888fbecde75b1832ff024d7374e51f2babd33f1078e5311cdbb8e2c00c3a' 
         -H 'Content-Type: application/json' 
         -d '{"msgtype": "text", 
              "text": {
                   "content": "我就是我, 是不一样的烟火"
              }
            }'
      
      
    演示过程

    流程示意图:
    image

    1. 安装gitlab plugin

      插件中心搜索并安装gitlab,直接安装即可

    2. 配置Gitlab

      系统管理->系统配置->Gitlab,其中的API Token,需要从下个步骤中获取
      image

    3. 获取AccessToken

      登录gitlab,选择user->Settings->access tokens新建一个访问token

    4. 创建自由风格项目

      • gitlab connection 选择为刚创建的gitlab
      • 源码管理选择Git,填项项目地址
      • 新建一个 Credentials 认证,使用用户名密码方式,配置gitlab的用户和密码
      • 构建触发器选择 Build when a change is pushed to GitLab
      • 生成一个Secret token
      • 保存
    5. 到gitlab配置webhook

      • 进入项目下settings->Integrations
      • URL: http://jenkins.luffy.com/project/free
      • Secret Token 填入在Jenkins端生成的token
      • Add webhook
      • test push events会不通过,因为gitlab中无法解析自定义域名
    6. 配置host解析

      由于我们的Jenkins域名是本地解析,因此需要让gitlab服务可以解析到该域名。两种方式:

      • 在容器内配置hosts

      • 配置coredns的静态解析

                hosts {
                    192.168.136.10 jenkins.luffy.com  gitlab.luffy.com
                    fallthrough
                }
        

      再次test push events,会由于安全设置,报错:Requests to the local network are not allowed

    7. 设置gitlab允许向本地网络发送webhook请求

      访问 Admin Aera -> Settings -> Network ,展开Outbound requests

      Collapse,勾选第一项即可。再次test push events,成功。
      image
      8. 配置free项目,增加构建步骤,执行shell,将发送钉钉消息的shell保存

    8. 提交代码到gitlab仓库,查看构建是否自动执行

    Master-Slaves(agent)模式

    上面演示的任务,默认都是在master节点执行的,多个任务都在master节点执行,对master节点的性能会造成一定影响,如何将任务分散到不同的节点,做成多slave的方式?

    1. 添加slave节点

      • 系统管理 -> 节点管理 -> 新建节点
      • 比如添加192.168.136.12,选择固定节点,保存
      • 远程工作目录/opt/jenkins_jobs
      • 标签为任务选择节点的依据,如192.168.136.12
      • 启动方式选择通过java web启动代理,代理是运行jar包,通过JNLP(是一种允许客户端启动托管在远程Web服务器上的应用程序的协议 )启动连接到master节点服务中
        image
    2. 执行java命令启动agent服务

      ## 登录192.168.136.12,下载agent.jar
      $ wget http://jenkins.luffy.com/jnlpJars/agent.jar
      ## 会提示找不到agent错误,因为没有配置地址解析,由于连接jenkins master会通过50000端口,直接使用cluster-ip
      $ kubectl -n jenkins get svc #在master节点执行查询cluster-ip地址
      NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)              AGE
      jenkins   ClusterIP   10.99.204.208   <none>        8080/TCP,50000/TCP   4h8m
      
      ## 再次回到131节点
      $ wget 10.99.204.208:8080/jnlpJars/agent.jar
      $ java -jar agent.jar -jnlpUrl http://10.99.204.208:8080/computer/192.168.136.12/slave-agent.jnlp -secret 4be4d164f861d2830835653567867a1e695b30c320d35eca2be9f5624f8712c8 -workDir "/opt/jenkins_jobs"
      ...
      INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping]
      Apr 01, 2020 7:03:51 PM hudson.remoting.jnlp.Main$CuiListener status
      INFO: Agent discovery successful
        Agent address: 10.99.204.208
        Agent port:    50000
        Identity:      e4:46:3a:de:86:24:8e:15:09:13:3d:a7:4e:07:04:37
      Apr 01, 2020 7:03:51 PM hudson.remoting.jnlp.Main$CuiListener status
      INFO: Handshaking
      Apr 01, 2020 7:03:51 PM hudson.remoting.jnlp.Main$CuiListener status
      INFO: Connecting to 10.99.204.208:50000
      Apr 01, 2020 7:03:51 PM hudson.remoting.jnlp.Main$CuiListener status
      INFO: Trying protocol: JNLP4-connect
      Apr 01, 2020 7:04:02 PM hudson.remoting.jnlp.Main$CuiListener status
      INFO: Remote identity confirmed: e4:46:3a:de:86:24:8e:15:09:13:3d:a7:4e:07:04:37
      Apr 01, 2020 7:04:03 PM hudson.remoting.jnlp.Main$CuiListener status
      INFO: Connected
      
      
    3. 查看Jenkins节点列表,新节点已经处于可用状态image

    4. 测试使用新节点执行任务

      • 配置free项目

      • 限制项目的运行节点 ,标签表达式选择192.168.136.12

      • 立即构建

      • 查看构建日志

        Started by user admin
        Running as SYSTEM
        Building remotely on 192.168.136.12 in workspace /opt/jenkins_jobs/workspace/free-demo
        using credential gitlab-user
        Cloning the remote Git repository
        Cloning repository http://gitlab.luffy.com/root/myblog.git
         > git init /opt/jenkins_jobs/workspace/free-demo # timeout=10
         ...
        
        
    Jenkins定制化容器

    由于每次新部署Jenkins环境,均需要安装很多必要的插件,因此考虑把插件提前做到镜像中

    Dockerfile

    FROM jenkinsci/blueocean:1.23.2
    LABEL maintainer="inspur_lyx@hotmail.com"
    
    ## 用最新的插件列表文件替换默认插件文件
    COPY plugins.txt /usr/share/jenkins/ref/
    
    ## 执行插件安装
    RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
    
    

    plugins.txt

    ace-editor:1.1
    allure-jenkins-plugin:2.28.1
    ant:1.10
    antisamy-markup-formatter:1.6
    apache-httpcomponents-client-4-api:4.5.10-1.0
    authentication-tokens:1.3
    ...
    
    

    get_plugin.sh

    admin:123456@localhost 需要替换成Jenkins的用户名、密码及访问地址

    #!/usr/bin/env bash
    curl -sSL  "http://admin:123456@localhost:8080/pluginManager/api/xml?depth=1&xpath=/*/*/shortName|/*/*/version&wrapper=plugins" | perl -pe 's/.*?<shortName>([w-]+).*?<version>([^<]+)()(</w+>)+/1:2
    /g'|sed 's/ /:/' > plugins.txt
    
    
    ## 执行构建,定制jenkins容器
    $ docker build . -t 192.168.136.10:5000/jenkins:v20200414 -f Dockerfile
    $ docker push 192.168.136.10:5000/jenkins:v20200414
    
    

    至此,我们可以使用定制化的镜像启动jenkins服务

    ## 删掉当前服务
    $ kubectl delete -f jenkins-all.yaml
    
    ## 删掉已挂载的数据
    $ rm -rf /var/jenkins_home
    
    ## 替换使用定制化镜像
    $ sed -i 's#jenkinsci/blueocean#192.168.136.10:5000/jenkins:v20200404#g' jenkins-all.yaml
    
    ## 重新创建服务
    $ kubectl create -f jenkins-all.yaml
    
    

    流水线入门

    官方文档
    image

    为什么叫做流水线,和工厂产品的生产线类似,pipeline是从源码到发布到线上环境。关于流水线,需要知道的几个点:

    • 重要的功能插件,帮助Jenkins定义了一套工作流框架;

    • Pipeline 的实现方式是一套 Groovy DSL( 领域专用语言 ),所有的发布流程都可以表述为一段 Groovy 脚本;

    • 将WebUI上需要定义的任务,以脚本代码的方式表述出来;

    • 帮助jenkins实现持续集成CI(Continue Integration)和持续部署CD(Continue Deliver)的重要手段;

    流水线基础语法

    官方文档
    两种语法类型:

    • Scripted Pipeline,脚本式流水线,最初支持的类型
    • Declarative Pipeline,声明式流水线,为Pipeline plugin在2.5版本之后新增的一种脚本类型,后续Open Blue Ocean所支持的类型。与原先的Scripted Pipeline一样,都可以用来编写脚本。Declarative Pipeline 是后续Open Blue Ocean所支持的类型,写法简单,支持内嵌Scripted Pipeline代码

    为与BlueOcean脚本编辑器兼容,通常建议使用Declarative Pipeline的方式进行编写,从jenkins社区的动向来看,很明显这种语法结构也会是未来的趋势。

    脚本示例
    pipeline { 
        agent {label '192.168.136.12'}
        environment { 
            PROJECT = 'myblog'
        }
        stages {
            stage('Checkout') { 
                steps { 
                    checkout scm 
                }
            }
            stage('Build') { 
                steps { 
                    sh 'make' 
                }
            }
            stage('Test'){
                steps {
                    sh 'make check'
                    junit 'reports/**/*.xml' 
                }
            }
            stage('Deploy') {
                steps {
                    sh 'make publish'
                }
            }
        }
    	post {
            success { 
                echo 'Congratulations!'
            }
    		failure { 
                echo 'Oh no!'
            }
            always { 
                echo 'I will always say Hello again!'
            }
        }
    }
    
    
    脚本解释:
    • checkout步骤为检出代码; scm是一个特殊变量,指示checkout步骤克隆触发此Pipeline运行的特定修订

    • agent:指明使用哪个agent节点来执行任务,定义于pipeline顶层或者stage内部

      • any,可以使用任意可用的agent来执行

      • label,在提供了标签的 Jenkins 环境中可用的代理上执行流水线或阶段。 例如: agent { label 'my-defined-label' },最常见的使用方式

      • none,当在 pipeline 块的顶部没有全局代理, 该参数将会被分配到整个流水线的运行中并且每个 stage 部分都需要包含他自己的 agent 部分。比如: agent none

      • docker, 使用给定的容器执行流水线或阶段。 在指定的节点中,通过运行容器来执行任务

        agent {
            docker {
                image 'maven:3-alpine'
                label 'my-defined-label'
                args  '-v /tmp:/tmp'
            }
        }
        
        
    • options: 允许从流水线内部配置特定于流水线的选项。

      • buildDiscarder , 为最近的流水线运行的特定数量保存组件和控制台输出。例如: options { buildDiscarder(logRotator(numToKeepStr: '10')) }
      • disableConcurrentBuilds ,不允许同时执行流水线。 可被用来防止同时访问共享资源等。 例如: options { disableConcurrentBuilds() }
      • timeout ,设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线。例如: options { timeout(time: 1, unit: 'HOURS') }
      • retry,在失败时, 重新尝试整个流水线的指定次数。 For example: options { retry(3) }
    • environment: 指令制定一个 键-值对序列,该序列将被定义为所有步骤的环境变量

    • stages: 包含一系列一个或多个 stage指令, stages 部分是流水线描述的大部分"work" 的位置。 建议 stages 至少包含一个 stage 指令用于连续交付过程的每个离散部分,比如构建, 测试, 和部署。

      pipeline {
          agent any
          stages { 
              stage('Example') {
                  steps {
                      echo 'Hello World'
                  }
              }
          }
      }
      
      
    • steps: 在给定的 stage 指令中执行的定义了一系列的一个或多个steps

    • post: 定义一个或多个steps ,这些阶段根据流水线或阶段的完成情况而运行post 支持以下 post-condition 块中的其中之一: always, changed, failure, success, unstable, 和 aborted

      • always, 无论流水线或阶段的完成状态如何,都允许在 post 部分运行该步骤
      • changed, 当前流水线或阶段的完成状态与它之前的运行不同时,才允许在 post 部分运行该步骤
      • failure, 当前流水线或阶段的完成状态为"failure",才允许在 post 部分运行该步骤, 通常web UI是红色
      • success, 当前流水线或阶段的完成状态为"success",才允许在 post 部分运行该步骤, 通常web UI是蓝色或绿色
      • unstable, 当前流水线或阶段的完成状态为"unstable",才允许在 post 部分运行该步骤, 通常由于测试失败,代码违规等造成。通常web UI是黄色
      • aborted, 只有当前流水线或阶段的完成状态为"aborted",才允许在 post 部分运行该步骤, 通常由于流水线被手动的aborted。通常web UI是灰色

    创建pipeline示意:

  • 相关阅读:
    发布基于C#的机器视觉库 *版本1.0.1*
    5月28日介绍这几年机器学习经历的讲演材料
    初识 PLINQ
    推荐博文:鸟瞰淘宝开放平台
    发布一款基于C#的网络爬虫程序
    发布基于C#的网络爬虫程序 *版本1.0.1*
    神秘园与班得瑞
    发布一款基于C#的机器视觉库
    《阿凡达》观影归来
    朝花夕识 和 Google Goggles 的差别
  • 原文地址:https://www.cnblogs.com/Mr-Axin/p/14768266.html
Copyright © 2011-2022 走看看