基于K8s的DevOps平台实践(一)

文章目录

  • 前言
  • 1. DevOps介绍
    • 瀑布式流程
    • 敏捷开发
    • DevOps
  • 2. Jenkins初体验
    • K8s环境中部署jenkins
    • 安装汉化插件
  • 3. Jenkins基本使用演示
    • 演示目标
    • 演示准备
    • 演示过程
  • 4. Master-Slaves(agent)模式
  • 5. Jenkins定制化容器
  • 6. 总结


前言

本篇文章基于 k8s 集群部署 gitlab、sonarQube、Jenkins 等工具,并把上述工具集成到 Jenkins 中,以 Django 项目和 SpringBoot 项目为例,通过多分支流水线及 Jenkinsfile 实现项目代码提交到不同的仓库分支,实现自动代码扫描、单元测试、docker 容器构建、k8s 服务的自动部署。

1. DevOps介绍

Continuous Integration (CI) 和 Continuous Delivery (CD)

传统的软件交付流程如下:

基于K8s的DevOps平台实践(一)_第1张图片

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

瀑布式流程

前期需求确立之后,软件开发人员花费数周和数月编写代码,把所有需求一次性开发完,然后将代码交给 QA(质量保障)团队进行测试,然后将最终的发布版交给运维团队去部署。

瀑布模型,简单来说,就是等一个阶段所有工作完成之后,再进入下一个阶段。这种模式的问题也很明显,产品迭代周期长,灵活性差。一个周期动辄几周几个月,适应不了当下产品需要快速迭代的场景。

基于K8s的DevOps平台实践(一)_第2张图片

敏捷开发

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

基于K8s的DevOps平台实践(一)_第3张图片

DevOps

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

基于K8s的DevOps平台实践(一)_第4张图片

我们是否可以认为 DevOps = 提倡开发、测试、运维协同工作来实现持续开发、持续交付的一种软件交付模式?

大家想一下为什么最初的开发模式没有直接进入 DevOps 的时代?

原因是:沟通成本。

各角色人员去沟通协作的时候都是手动去做,交流靠嘴,靠人去指挥,很显然会出大问题。所以说不能认为 DevOps 就是一种交付模式,因为解决不了沟通协作成本,这种模式就不具备可落地性。

那 DevOps 时代如何解决角色之间的成本问题?DevOps 的核心就是自动化。自动化的能力靠什么来支撑,工具和技术。

DevOps工具链

基于K8s的DevOps平台实践(一)_第5张图片

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

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

因此 devops 不是某一个具体的技术,而是一种思想+自动化能力,来使得构建、测试、发布软件能够更加地便捷、频繁和可靠的落地实践。

本篇文章的核心内容就是要教会大家如何利用工具和技术来实现完整的 DevOps 平台的建设。我们主要使用的工具有:

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

2. Jenkins初体验

关于 Jenkins 的介绍这里不过多叙述,除了下面我自己的部署方案,大家还可以参考这个网站:Jenkins部署方案

K8s环境中部署jenkins

安装的注意点:

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

(1)jenkins/jenkins-all.yaml 文件

apiVersion: v1
kind: Namespace
metadata:
  name: jenkins
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: jenkins
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: nfs
  resources:
    requests:
      storage: 200Gi
---
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:
      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.24.7
        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
        persistentVolumeClaim:
          claimName: jenkins
---
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: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins-web
  namespace: jenkins
spec:
  rules:
  - host: jenkins.luffy.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: jenkins
            port:
              number: 8080

(2)创建服务:

## 部署服务
$ 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

*************************************************************

(3)访问服务:

配置 hosts 解析,172.21.51.143 jenkins.luffy.com,然后使用浏览器域名访问服务。第一次访问需要大概几分钟的初始化时间。

基于K8s的DevOps平台实践(一)_第6张图片

使用 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 (新密码),登录即可。

基于K8s的DevOps平台实践(一)_第7张图片

安装汉化插件

Jenkins -> manage Jenkins -> Plugin Manager -> Avaliable,搜索 chinese 关键字

基于K8s的DevOps平台实践(一)_第8张图片

选中后,选择 [Install without restart],等待下载完成,然后点击 [ Restart Jenkins when installation is complete and no jobs are running ],让 Jenkins 自动重启

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

3. Jenkins基本使用演示

演示目标

  • 代码提交 gitlab,自动触发 Jenkins 任务
  • Jenkins 任务完成后发送钉钉消息通知

演示准备

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 部署:

(1)准备 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

(2)部署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
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: postgredb
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: nfs
  resources:
    requests:
      storage: 200Gi
---
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:
      tolerations:
      - operator: "Exists"
      containers:
      - name: postgres
        image:  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
        persistentVolumeClaim:
          claimName: postgredb
          


#创建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

(3)部署 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

(4)部署gitlab

注意点:

  • 使用 ingress 暴漏服务
  • 添加 annotation,指定 nginx 端上传大小限制,否则推送代码时会默认被限制 1m 大小,相当于给 nginx 设置 client_max_body_size 的限制大小
  • 使用服务发现地址来访问 postgres 和 redis
  • 在 secret 中引用数据库账户和密码
  • 数据库名称为 gitlab
   $ cat gitlab.yaml
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: gitlab
     namespace: jenkins
     annotations:
       nginx.ingress.kubernetes.io/proxy-body-size: "50m"
   spec:
     rules:
     - host: gitlab.luffy.com
       http:
         paths:
         - path: /
           pathType: Prefix
           backend:
             service: 
               name: gitlab
               port:
                 number: 80
   ---
   kind: PersistentVolumeClaim
   apiVersion: v1
   metadata:
     name: gitlab
     namespace: jenkins
   spec:
     accessModes:
       - ReadWriteOnce
     storageClassName: nfs
     resources:
       requests:
         storage: 200Gi
   ---
   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:
         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
           persistentVolumeClaim:
             claimName: gitlab
   
   
   # 创建
   $ kubectl create -f gitlab.yaml
   

配置 hosts 解析:

172.21.51.143 gitlab.luffy.com

设置root密码

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

配置 k8s-master 节点的 hosts

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

myblog 项目推送到 gitlab

mkdir demo
cp -r python-demo 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=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
   -H 'Content-Type: application/json' \
   -d '{"msgtype": "text", 
        "text": {
             "content": "基于K8s的DevOps平台实践"
        }
      }'
      

演示过程

流程示意图:

基于K8s的DevOps平台实践(一)_第9张图片

(1)安装 gitlab plugin

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

(2)配置 Gitlab

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

基于K8s的DevOps平台实践(一)_第10张图片

(3)获取 AccessToken

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

(4)配置 host 解析

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

  • 在容器内配置hosts

  • 配置coredns的静态解析

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

(5)创建自由风格项目

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

(6)到 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

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

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

Collapse,勾选第一项即可。再次 test push events,成功。

在这里插入图片描述

(8)配置 free 项目,增加构建步骤,执行 shell,将发送钉钉消息的 shell 保存

(9)提交代码到 gitlab 仓库,查看构建是否自动执行

4. Master-Slaves(agent)模式

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

(1)添加 slave 节点

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

基于K8s的DevOps平台实践(一)_第11张图片

(2)执行 java 命令启动 agent 服务

## 登录172.21.51.68,下载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           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.21.51.68/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

若出现如下错误:

SEVERE: http://jenkins.luffy.com/ provided port:50000 is not reachable
java.io.IOException: http://jenkins.luffy.com/ provided port:50000 is not reachable
        at org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver.resolve(JnlpAgentEndpointResolver.java:311)
        at hudson.remoting.Engine.innerRun(Engine.java:689)
        at hudson.remoting.Engine.run(Engine.java:514)

可以选择: 配置从节点 -> 高级 -> Tunnel连接位置,参考下图进行设置:

基于K8s的DevOps平台实践(一)_第12张图片

(3)查看 Jenkins 节点列表,新节点已经处于可用状态

基于K8s的DevOps平台实践(一)_第13张图片

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

  • 配置 free 项目

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

  • 立即构建

  • 查看构建日志

Started by user admin
Running as SYSTEM
Building remotely on 172.21.51.68 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
 ...

5. Jenkins定制化容器

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

Dockerfile

FROM jenkinsci/blueocean:1.23.2
LABEL maintainer="[email protected]"

ENV JENKINS_UC https://updates.jenkins-zh.cn
ENV JENKINS_UC_DOWNLOAD https://mirrors.tuna.tsinghua.edu.cn/jenkins
ENV JENKINS_OPTS="-Dhudson.model.UpdateCenter.updateCenterUrl=https://updates.jenkins-zh.cn/update-center.json"
ENV JENKINS_OPTS="-Djenkins.install.runSetupWizard=false"

## 用最新的插件列表文件替换默认插件文件
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/.*?([\w-]+).*?([^<]+)()(<\/\w+>)+/\1:\2\n/g'|sed 's/ /:/' > plugins.txt

执行构建,定制 jenkins 容器

$ docker build . -t 172.21.51.143:5000/jenkins:v20200414 -f Dockerfile
$ docker push 172.21.51.143:5000/jenkins:v20200414

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

## 删掉当前服务
$ kubectl delete -f jenkins-all.yaml

## 删掉已挂载的数据
$ rm -rf /var/jenkins_home

## 替换使用定制化镜像
$ sed -i 's#jenkinsci/blueocean#172.21.51.143:5000/jenkins:v20200404#g' jenkins-all.yaml

## 重新创建服务
$ kubectl create -f jenkins-all.yaml

6. 总结

自由风格项目弊端:

  • 任务的完成需要在Jenkins端维护大量的配置
  • 没法做版本控制
  • 可读性、可移植性很差,不够优雅

你可能感兴趣的:(「云原生的进阶之路」,devops,kubernetes,云原生,docker)