DEVOPS架构师 -- 05从零开始构建基于Kubernetes的DevOps平台
文章目录
- 基于Kubernetes的DevOps平台实践
- DevOps、CI、CD介绍
- 瀑布式流程
- 敏捷开发
- DevOps
- Jenkins初体验
- Kubernetes环境中部署jenkins
- 安装汉化插件
- Jenkins基本使用演示
- 演示目标
- 演示准备
- 演示过程
- Master-Slaves(agent)模式
- Jenkins定制化容器
- 本章小结
- 流水线入门
- 流水线基础语法
- 脚本示例
- 脚本解释:
- Blue Ocean:
- Jenkinsflie
- 演示1:使用Jenkinsfile管理**pipeline**
- 演示2:优化及丰富流水线内容
- 演示3:使用k8s部署服务
- 演示4:使用凭据管理敏感信息
- 本章小结
- 多分支流水线
- 演示1:多分支流水线的使用
- 演示2:美化消息通知内容
- 演示3:通知gitlab构建状态
- 本章小节
- 工具集成与Jenkinsfile实践篇
- 集成Kubernetes
- 插件安装及配置
- 演示动态slave pod
- Pod-Template中容器镜像的制作
- 实践通过Jenkinsfile实现demo项目自动发布到kubenetes环境
- 集成sonarQube实现代码扫描
- sonarqube架构简介
- sonarqube on kubernetes环境搭建
- 插件安装及配置
- Jenkinsfile集成sonarqube演示
- 集成RobotFramework实现验收测试
- robot用例简介
- 与tools工具镜像集成
- 插件安装及配置
- 实践通过Jenkinsfile实现demo项目的验收测试
基于Kubernetes的DevOps平台实践
持续集成工具:
- Jenkins
- gitlabci
- Tekton
本章基于k8s集群部署gitlab、sonarQube、Jenkins等工具,并把上述工具集成到Jenkins中,以Django项目和SpringBoot项目为例,通过多分支流水线及Jenkinsfile实现项目代码提交到不同的仓库分支,实现自动代码扫描、单元测试、docker容器构建、k8s服务的自动部署。
- DevOps、CI、CD介绍
- Jenkins、sonarQube、gitlab的快速部署
- Jenkins初体验
- 流水线入门及Jenkinsfile使用
- Jenkins与Kubernetes的集成
- sonarQube代码扫描与Jenkins的集成
- 实践Django项目的基于Jenkinsfile实现开发、测试环境的CI/CD
DevOps、CI、CD介绍
Continuous Integration (CI) / Continuous Delivery (CD)
软件交付流程
一个软件从零开始到最终交付,大概包括以下几个阶段:规划、编码、构建、测试、发布、部署和维护,基于这些阶段,我们的软件交付模型大致经历了几个阶段:
瀑布式流程
前期需求确立之后,软件开发人员花费数周和数月编写代码,把所有需求一次性开发完,然后将代码交给QA(质量保障)团队进行测试,然后将最终的发布版交给运维团队去部署。瀑布模型,简单来说,就是等一个阶段所有工作完成之后,再进入下一个阶段。这种模式的问题也很明显,产品迭代周期长,灵活性差。一个周期动辄几周几个月,适应不了当下产品需要快速迭代的场景。
敏捷开发
任务由大拆小,开发、测试协同工作,注重开发敏捷,不重视交付敏捷
DevOps
开发、测试、运维协同工作, 持续开发+持续交付。
我们是否可以认为DevOps = 提倡开发、测试、运维协同工作来实现持续开发、持续交付的一种软件交付模式?
大家想一下为什么最初的开发模式没有直接进入DevOps的时代?
原因是:沟通成本。
各角色人员去沟通协作的时候都是手动去做,交流靠嘴,靠人去指挥,很显然会出大问题。所以说不能认为DevOps就是一种交付模式,因为解决不了沟通协作成本,这种模式就不具备可落地性。
那DevOps时代如何解决角色之间的成本问题?DevOps的核心就是自动化。自动化的能力靠什么来支撑,工具和技术。
DevOps工具链
靠这些工具和技术,才实现了自动化流程,进而解决了协作成本,使得devops具备了可落地性。因此我们可以大致给devops一个定义:
devops = 提倡开发、测试、运维协同工作来实现持续开发、持续交付的一种软件交付模式 + 基于工具和技术支撑的自动化流程的落地实践。
因此devops不是某一个具体的技术,而是一种思想+自动化能力,来使得构建、测试、发布软件能够更加地便捷、频繁和可靠的落地实践。本次课程核心内容就是要教会大家如何利用工具和技术来实现完整的DevOps平台的建设。我们主要使用的工具有:
- gitlab,代码仓库,企业内部使用最多的代码版本管理工具。
- Jenkins, 一个可扩展的持续集成引擎,用于自动化各种任务,包括构建、测试和部署软件。
- robotFramework, 基于Python的自动化测试框架
- sonarqube,代码质量管理平台
- maven,java包构建管理工具
- Kubernetes
- Docker
Jenkins初体验
Kubernetes环境中部署jenkins
其他部署方式
注意点:
- 第一次启动很慢
- 因为后面Jenkins会与kubernetes集群进行集成,会需要调用kubernetes集群的api,因此安装的时候创建了ServiceAccount并赋予了cluster-admin的权限
- 默认部署到jenkins=true的节点
- 初始化容器来设置权限
- ingress来外部访问
- 数据存储通过hostpath挂载到宿主机中
jenkins/jenkins-all.yaml
apiVersion: v1
kind: Namespace
metadata:name: jenkins
---
apiVersion: v1
kind: ServiceAccount
metadata:name: jenkinsnamespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:name: jenkins-crb
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-admin
subjects:
- kind: ServiceAccountname: jenkinsnamespace: jenkins
---
apiVersion: apps/v1
kind: Deployment
metadata:name: jenkins-masternamespace: jenkins
spec:replicas: 1selector:matchLabels:devops: jenkins-mastertemplate:metadata:labels:devops: jenkins-masterspec:nodeSelector:jenkins: "true"serviceAccount: jenkins #Pod 需要使用的服务账号initContainers:- name: fix-permissionsimage: busyboxcommand: ["sh", "-c", "chown -R 1000:1000 /var/jenkins_home"]securityContext:privileged: truevolumeMounts:- name: jenkinshomemountPath: /var/jenkins_homecontainers:- name: jenkinsimage: jenkinsci/blueocean:1.23.2imagePullPolicy: IfNotPresentports:- name: http #Jenkins Master Web 服务端口containerPort: 8080- name: slavelistener #Jenkins Master 供未来 Slave 连接的端口containerPort: 50000volumeMounts:- name: jenkinshomemountPath: /var/jenkins_homeenv:- name: JAVA_OPTSvalue: "-Xms4096m -Xmx5120m -Duser.timezone=Asia/Shanghai -Dhudson.model.DirectoryBrowserSupport.CSP="volumes:- name: jenkinshomehostPath:path: /var/jenkins_home/
---
apiVersion: v1
kind: Service
metadata:name: jenkinsnamespace: jenkins
spec:ports:- name: httpport: 8080targetPort: 8080- name: slavelistenerport: 50000targetPort: 50000type: ClusterIPselector:devops: jenkins-master
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: jenkins-webnamespace: jenkins
spec:rules:- host: jenkins.luffy.comhttp:paths:- backend:serviceName: jenkinsservicePort: 8080path: /
创建服务:
## 为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:5396b4e1c395450f8360efd8ee641b18This may also be found at: /var/jenkins_home/secrets/initialAdminPassword*************************************************************
访问服务:
配置hosts解析,172.16.1.26 jenkins.luffy.com
,然后使用浏览器域名访问服务。第一次访问需要大概几分钟的初始化时间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iGktNWlb-1635080888344)(images\jenkins_setup.jpg)]
使用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(新密码),登录即可。
安装汉化插件
Jenkins -> manage Jenkins -> Plugin Manager -> Avaliable,搜索 chinese
关键字
选中后,选择[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
部署分析:
- 依赖postgres
- 依赖redis
使用k8s部署:
准备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
部署postgres
注意点:
- 使用secret来引用账户密码
- 使用postgres=true来指定节点
$ cat postgres.yaml apiVersion: v1 kind: Service metadata:name: postgreslabels:app: postgresnamespace: jenkins spec:ports:- name: serverport: 5432targetPort: 5432protocol: TCPselector:app: postgres --- apiVersion: apps/v1 kind: Deployment metadata:namespace: jenkinsname: postgreslabels:app: postgres spec:replicas: 1selector:matchLabels:app: postgrestemplate:metadata:labels:app: postgresspec:nodeSelector:postgres: "true"tolerations:- operator: "Exists"containers:- name: postgresimage: 172.16.1.26:5000/postgres:11.4 #若本地没有启动该仓库,换成postgres:11.4imagePullPolicy: "IfNotPresent"ports:- containerPort: 5432env:- name: POSTGRES_USER #PostgreSQL 用户名valueFrom:secretKeyRef:name: gitlab-secretkey: postgres.user.root- name: POSTGRES_PASSWORD #PostgreSQL 密码valueFrom:secretKeyRef:name: gitlab-secretkey: postgres.pwd.rootresources:limits:cpu: 1000mmemory: 2048Mirequests:cpu: 50mmemory: 100MivolumeMounts:- mountPath: /var/lib/postgresql/dataname: postgredbvolumes:- name: postgredbhostPath: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
部署redis
$ cat redis.yaml apiVersion: v1 kind: Service metadata:name: redislabels:app: redisnamespace: jenkins spec:ports:- name: serverport: 6379targetPort: 6379protocol: TCPselector:app: redis --- apiVersion: apps/v1 kind: Deployment metadata:namespace: jenkinsname: redislabels:app: redis spec:replicas: 1selector:matchLabels:app: redistemplate:metadata:labels:app: redisspec:tolerations:- operator: "Exists"containers:- name: redisimage: sameersbn/redis:4.0.9-2imagePullPolicy: "IfNotPresent"ports:- containerPort: 6379resources:limits:cpu: 1000mmemory: 2048Mirequests:cpu: 50mmemory: 100Mi# 创建 $ kubectl create -f redis.yaml
部署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: gitlabnamespace: jenkinsannotations:nginx.ingress.kubernetes.io/proxy-body-size: "50m" spec:rules:- host: gitlab.luffy.comhttp:paths:- backend:serviceName: gitlabservicePort: 80path: / --- apiVersion: v1 kind: Service metadata:name: gitlablabels:app: gitlabnamespace: jenkins spec:ports:- name: serverport: 80targetPort: 80protocol: TCPselector:app: gitlab --- apiVersion: apps/v1 kind: Deployment metadata:namespace: jenkinsname: gitlablabels:app: gitlab spec:replicas: 1selector:matchLabels:app: gitlabtemplate:metadata:labels:app: gitlabspec:nodeSelector:gitlab: "true"tolerations:- operator: "Exists"containers:- name: gitlabimage: sameersbn/gitlab:13.2.2imagePullPolicy: "IfNotPresent"env:- name: GITLAB_HOSTvalue: "gitlab.luffy.com"- name: GITLAB_PORTvalue: "80"- name: GITLAB_SECRETS_DB_KEY_BASEvalue: "long-and-random-alpha-numeric-string"- name: GITLAB_SECRETS_DB_KEY_BASEvalue: "long-and-random-alpha-numeric-string"- name: GITLAB_SECRETS_SECRET_KEY_BASEvalue: "long-and-random-alpha-numeric-string"- name: GITLAB_SECRETS_OTP_KEY_BASEvalue: "long-and-random-alpha-numeric-string"- name: DB_HOSTvalue: "postgres"- name: DB_NAMEvalue: "gitlab"- name: DB_USERvalueFrom:secretKeyRef:name: gitlab-secretkey: postgres.user.root- name: DB_PASSvalueFrom:secretKeyRef:name: gitlab-secretkey: postgres.pwd.root- name: REDIS_HOSTvalue: "redis"- name: REDIS_PORTvalue: "6379"ports:- containerPort: 80resources:limits:cpu: 2000mmemory: 5048Mirequests:cpu: 100mmemory: 500MivolumeMounts:- mountPath: /home/git/dataname: datavolumes:- name: datahostPath:path: /var/lib/gitlab/#部署到k8s-slave2节点 $ kubectl label node k8s-slave2 gitlab=true# 创建 $ kubectl create -f gitlab.yaml
配置hosts解析:
172.16.1.26 gitlab.luffy.com
设置root密码
访问http://gitlab.luffy.com,设置管理员密码
配置k8s-master节点的hosts
$ echo "172.16.1.26 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=67e81175c6ebacb1307e83f62680f36fbcf4524e8f43971cf2fb2049bc58723d' \-H 'Content-Type: application/json' \-d '{"msgtype": "text", "text": {"content": "我就是我, 是不一样的烟火"}}'
演示过程
流程示意图:
安装gitlab plugin
插件中心搜索并安装gitlab,直接安装即可
配置Gitlab
系统管理->系统配置->Gitlab,其中的API Token,需要从下个步骤中获取
获取AccessToken
登录gitlab,选择user->Settings->access tokens新建一个访问token
配置host解析
由于我们的Jenkins和gitlab域名是本地解析,因此需要让gitlab和Jenkins服务可以解析到对方的域名。两种方式:
在容器内配置hosts
配置coredns的静态解析
hosts {172.16.1.26 jenkins.luffy.com gitlab.luffy.comfallthrough}
创建自由风格项目
- gitlab connection 选择为刚创建的gitlab
- 源码管理选择Git,填项项目地址
- 新建一个 Credentials 认证,使用用户名密码方式,配置gitlab的用户和密码
- 构建触发器选择 Build when a change is pushed to GitLab
- 生成一个Secret token
- 保存
到gitlab配置webhook
- 进入项目下settings->Integrations
- URL: http://jenkins.luffy.com/project/free
- Secret Token 填入在Jenkins端生成的token
- Add webhook
- test push events,报错:Requests to the local network are not allowed
设置gitlab允许向本地网络发送webhook请求
访问 Admin Aera -> Settings -> Network ,展开Outbound requests
Collapse,勾选第一项即可。再次test push events,成功。
配置free项目,增加构建步骤,执行shell,将发送钉钉消息的shell保存
提交代码到gitlab仓库,查看构建是否自动执行
Master-Slaves(agent)模式
上面演示的任务,默认都是在master节点执行的,多个任务都在master节点执行,对master节点的性能会造成一定影响,如何将任务分散到不同的节点,做成多slave的方式?
添加slave节点
- 系统管理 -> 节点管理 -> 新建节点
- 比如添加172.16.1.25,选择固定节点,保存
- 远程工作目录/opt/jenkins_jobs
- 标签为任务选择节点的依据,如172.16.1.25
- 启动方式选择通过java web启动代理,代理是运行jar包,通过JNLP(是一种允许客户端启动托管在远程Web服务器上的应用程序的协议 )启动连接到master节点服务中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-stnoircc-1635080888350)(images\jenkins-new-node.jpg)]
执行java命令启动agent服务
## 登录172.16.1.25,下载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## 再次回到68节点 $ wget 10.99.204.208:8080/jnlpJars/agent.jar $ java -jar agent.jar -jnlpUrl http://10.99.204.208:8080/computer/172.16.1.25/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 successfulAgent address: 10.99.204.208Agent port: 50000Identity: 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
若出现如下错误:
SEVERE: http://jenkins.luffy.com/tcpSlaveAgentListener/ appears to be publishing an invalid X-Instance-Identity. java.io.IOException: http://jenkins.luffy.com/tcpSlaveAgentListener/ appears to be publishing an invalid X-Instance-Identity.at org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver.resolve(JnlpAgentEndpointResolver.java:287)at hudson.remoting.Engine.innerRun(Engine.java:694)at hudson.remoting.Engine.run(Engine.java:519)
可以选择: 配置从节点 -> 高级 -> Tunnel连接位置,参考下图进行设置:
- 查看Jenkins节点列表,新节点已经处于可用状态
测试使用新节点执行任务
配置free项目
限制项目的运行节点 ,标签表达式选择172.16.1.25
立即构建
查看构建日志
Started by user admin Running as SYSTEM Building remotely on 172.16.1.25 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\n/g'|sed 's/ /:/' > plugins.txt
## 执行构建,定制jenkins容器
$ docker build . -t 172.16.1.26:5000/jenkins:v20200414 -f Dockerfile
$ docker push 172.16.1.26:5000/jenkins:v20200414
至此,我们可以使用定制化的镜像启动jenkins服务
## 删掉当前服务
$ kubectl delete -f jenkins-all.yaml## 删掉已挂载的数据
$ rm -rf /var/jenkins_home## 替换使用定制化镜像
$ sed -i 's#jenkinsci/blueocean#172.16.1.26:5000/jenkins:v20200404#g' jenkins-all.yaml## 重新创建服务
$ kubectl create -f jenkins-all.yaml
本章小结
自由风格项目弊端:
- 任务的完成需要在Jenkins端维护大量的配置
- 没法做版本控制
- 可读性、可移植性很差,不够优雅
流水线入门
官方文档
为什么叫做流水线,和工厂产品的生产线类似,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 '172.16.1.25'}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) }
- buildDiscarder , 为最近的流水线运行的特定数量保存组件和控制台输出。例如:
environment: 指令制定一个 键-值对序列,该序列将被定义为所有步骤的环境变量
stages: 包含一系列一个或多个 stage指令,
stages
部分是流水线描述的大部分"work" 的位置。 建议stages
至少包含一个 stage 指令用于连续交付过程的每个离散部分,比如构建, 测试, 和部署。pipeline {agent anystages { 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是灰色
- always, 无论流水线或阶段的完成状态如何,都允许在
创建pipeline示意:
新建任务 -> 流水线
jenkins/pipelines/p1.yaml
pipeline {agent {label '172.16.1.25'}environment { PROJECT = 'myblog'}stages {stage('printenv') {steps {echo 'Hello World'sh 'printenv'}}stage('check') {steps {checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-user', url: 'http://gitlab.luffy.com/root/myblog.git']]])}}stage('build-image') {steps {sh 'docker build . -t myblog:latest -f Dockerfile'}}stage('send-msg') {steps {sh """curl 'https://oapi.dingtalk.com/robot/send?access_token=67e81175c6ebacb1307e83f62680f36fbcf4524e8f43971cf2fb2049bc58723d' \-H 'Content-Type: application/json' \-d '{"msgtype": "text", "text": {"content": "我就是我, 是不一样的烟火"}}'"""}}}
}
点击“立即构建”,同样的,我们可以配置触发器,使用webhook的方式接收项目的push事件,
- 构建触发器选择 Build when a change is pushed to GitLab.
- 生成 Secret token
- 配置gitlab,创建webhook,发送test push events测试
Blue Ocean:
官方文档
我们需要知道的几点:
- 是一个插件, 旨在为Pipeline提供丰富的体验 ;
- 连续交付(CD)Pipeline的复杂可视化,允许快速和直观地了解Pipeline的状态;
- 目前支持的类型仅针对于Pipeline,尚不能替代Jenkins 经典版UI
思考:
- 每个项目都把大量的pipeline脚本写在Jenkins端,对于谁去维护及维护成本是一个问题
- 没法做版本控制
Jenkinsflie
Jenkins Pipeline 提供了一套可扩展的工具,用于将“简单到复杂”的交付流程实现为“持续交付即代码”。Jenkins Pipeline 的定义通常被写入到一个文本文件(称为 Jenkinsfile
)中,该文件可以被放入项目的源代码控制库中。
演示1:使用Jenkinsfile管理pipeline
- 在项目中新建Jenkinsfile文件,拷贝已有script内容
- 配置pipeline任务,流水线定义为Pipeline Script from SCM
- 执行push 代码测试
Jenkinsfile:
jenkins/pipelines/p2.yaml
pipeline {agent { label '172.16.1.25'}stages {stage('printenv') {steps {echo 'Hello World'sh 'printenv'}}stage('check') {steps {checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-user', url: 'http://gitlab.luffy.com/root/myblog.git']]])}}stage('build-image') {steps {retry(2) { sh 'docker build . -t myblog:latest'}}}stage('send-msg') {steps {sh """curl 'https://oapi.dingtalk.com/robot/send?access_token=67e81175c6ebacb1307e83f62680f36fbcf4524e8f43971cf2fb2049bc58723d' \-H 'Content-Type: application/json' \-d '{"msgtype": "text", "text": {"content": "我就是我, 是不一样的烟火"}}'"""}}}
}
演示2:优化及丰富流水线内容
优化代码检出阶段
由于目前已经配置了使用git仓库地址,且使用SCM来检测项目,因此代码检出阶段完全没有必要再去指定一次
构建镜像的tag使用git的commit id
增加post阶段的消息通知,丰富通知内容
配置webhook,实现myblog代码推送后,触发Jenkinsfile任务执行
jenkins/pipelines/p3.yaml
pipeline {agent { label '172.16.1.25'}stages {stage('printenv') {steps {echo 'Hello World'sh 'printenv'}}stage('check') {steps {checkout scm}}stage('build-image') {steps {retry(2) { sh 'docker build . -t myblog:${GIT_COMMIT}'}}}}post {success { echo 'Congratulations!'sh """curl 'https://oapi.dingtalk.com/robot/send?access_token=67e81175c6ebacb1307e83f62680f36fbcf4524e8f43971cf2fb2049bc58723d' \-H 'Content-Type: application/json' \-d '{"msgtype": "text", "text": {"content": "
DEVOPS架构师 -- 05从零开始构建基于Kubernetes的DevOps平台相关推荐
- 40-60K/月,北森云计算招聘Devops架构师(地点:北京)
想找钱多事少离家近的工作, 关注我们吧! 北森云计算招聘devops架构师(薪酬40-60k/月,有期权,地点:北京) gogo姐说:北森云计算是一家很不错的公司哦!现招聘Devops架构师,有兴趣的 ...
- 《开源容器云OpenShift:构建基于Kubernetes的企业应用云平台》一2.3 完善OpenShift集群...
本节书摘来自华章出版社<开源容器云OpenShift:构建基于Kubernetes的企业应用云平台>一书中的第2章,第2.3节,作者 陈耿 ,更多章节内容可以访问云栖社区"华章计 ...
- 从零开始构建基于textcnn的文本分类模型(上),word2vec向量训练,预训练词向量模型加载,pytorch Dataset、collete_fn、Dataloader转换数据集并行加载
伴随着bert.transformer模型的提出,文本预训练模型应用于各项NLP任务.文本分类任务是最基础的NLP任务,本文回顾最先采用CNN用于文本分类之一的textcnn模型,意在巩固分词.词向量 ...
- 基于 Kubernetes 的 FaaS 平台开源实现——Kubeless 的应用实践
通常我们认为Serverless包含两个部分,FaaS和BaaS,本次主要讲的是FaaS部分. 什么是Serverless 通常我们认为Serverless包含两个部分,FaaS和BaaS,本次主要讲 ...
- 知乎基于Kubernetes的kafka平台的设计和实现
我是知乎技术中台工程师,负责知乎存储相关的组件.我的分享主要基于三个,第一,简单介绍一下Kafka在知乎的应用,第二,为什么做基于Kubernetes的Kafka平台.第三,我们如何去实现基于Kube ...
- 白瑜庆:知乎基于Kubernetes的kafka平台的设计和实现
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文首发在云+社区,未经许可,不得转载. 自我介绍 我是知乎的技术中台工程师,现在是负责知乎的存储相关组件.我的分享主要基于三个,一个是简单 ...
- 架构师成长系列 | 云原生时代的 DevOps 之道
作者 | 郝树伟(花名:流生) 阿里云高级研发工程师 本文整理自架构师成长系列 2 月17 日直播课程. 关注"阿里巴巴云原生"公众号,回复 "217",即可 ...
- 龙腾出行基于Kubernetes的DevOps流水线实战
伴随着微服务架构的普及,龙腾内部很多业务线从单体架构转向微服务架构,在根据业务边界进行拆分时,带来的服务实例数目成倍数增长,这给开发.运维.测试增加了不少复杂度和工作量,此时我们利用Kubernete ...
- PPmoney基于Kubernetes的DevOps实践
在微服务带来便利的同时产生了新的挑战,如何对所有微服务进行快速部署?本文将介绍PPmoney如何践行推广容器化,建立应用从开发测试到部署的DevOps流程,提高团队工作效率. 云平台介绍 先给大家看看 ...
最新文章
- 【联邦学习】FATE 集群部署 step2
- 2.3.1 进程同步 进程互斥
- 广东48.6万人资产超600万 华东超600万人群最多
- oracle12c ora 12545,11gR2 ORA-12545故障处理
- Spring解决循环依赖
- DotNetCore中异步编程的实用演练
- 为什么计算机要学电路与电子技术,电路与电子技术基础(计算机科学与技术面向新工科专业建设计算机系列教材)...
- 【刷爆LeetCode】七月算法集训(14)栈
- 单片机——点阵2(Proteus和KeilC51)
- Linux rpm -ivm,PowerLinux 7R1项目实施手册PDF
- 使用HttpClient下载网页
- AES加密,由S盒计算逆S盒程序
- RokcetMq基本概念
- MySQL 1075错误
- 学c语言笔记本电脑推荐,2020年大学生笔记本电脑推荐
- 荒岛特训服务器维护中,《荒岛特训》高手吃鸡心得一览,这把稳了!
- “中国POS机龙头”的数据化转型之道
- 美菜网php源码,哪里有免费文章网站模板下?我要带后台的那种,PHP?寻一php源码类似于美菜网的展示型网站(带后台)?...
- 放假啦,高兴...........
- web开发知识点大总结
热门文章
- SAP S4 FI后台详细配置教程- PART1 (通用配置及基础架构篇)
- 浙江大学计算机学院博士论文格式,浙江大学外语学院英文版博士学位论文格式.pdf...
- Paper reading (九十一):Bifidobacterium breve Bif195 Protects Against Small-Intestinal Damage
- Camera基本结构及原理
- Arduino开发(二)_基于Arduino UNO开发板的RGB灯光控制方法
- 天嵌科技——TQIMX6Q光盘8月更新说明
- 通过Python绘制九种二次曲面
- dout java_一段关于Java文件流操作的代码问题
- 关注IT精英:微利时代如何赚大钱 (转载)
- Win8.1 安装nltk及nltk_data数据