环境准备
部署gitlab
1
| docker run --detach --hostname 10.8.242.28 --publish 443:443 --publish 80:80 --publish 1022:22 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/logs:/var/log/gitlab --volume /srv/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:12.10.3-ce.0
|
替换hostname为实际节点外网IP
部署Harbor
Harbor部署与管理
部署前先修改docker
编辑docker
1 2 3 4
| vim /etc/docker/daemon.json { "insecure-registries" : ["0.0.0.0/0"] }
|
重启docker
1
| systemctl restart docker
|
安装docker-compose
1 2
| curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
|
下载harbor
1
| https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-online-installer-v1.10.2.tgz
|
配置harbo.yaml
1
| hostname: 172.31.48.86 //修改为实际节点IP
|
屏蔽https配置
安装harbor
1
| ./install.sh --with-clair
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| docker-compose ps Name Command State Ports --------------------------------------------------------------------------------------------- clair /docker-entrypoint.sh Up (healthy) 6060/tcp, 6061/tcp harbor-core /harbor/start.sh Up (healthy) harbor-db /entrypoint.sh postgres Up (healthy) 5432/tcp harbor-jobservice /harbor/start.sh Up harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514->10514/tcp harbor-portal nginx -g daemon off; Up (healthy) 80/tcp nginx nginx -g daemon off; Up (healthy) 0.0.0.0:80->80/tcp redis docker-entrypoint.sh redis ... Up 6379/tcp registry /entrypoint.sh /etc/regist ... Up (healthy) 5000/tcp registryctl /harbor/start.sh Up (healthy)
|
访问http://node_ip
admin/Harbor12345

Drone配置使用
Rancher应用商店已经提供了Drone的部署安装及配置,通过Rancher应用商店即可将Drone部署并配置对接
在gitlab上创建一个项目名为go-server,编写个应用
server.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main import ( "fmt" "log" "net/http" ) func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") } func main() { http.HandleFunc("/", hello) if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatal(err) } }
|
创建Dockerfile
Dockerfile
1 2 3 4
| FROM golang WORKDIR /go ADD server /go CMD ["./server"]
|
1、配置gitlab外部认证

回调接口填写其中一个节点的http://ip/login

如下

保存好对应的ApplicationID和secret

部署Drone
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| docker run \ --volume=/var/run/docker.sock:/var/run/docker.sock \ --volume=/var/lib/drone:/data \ --env=DRONE_LOGS_DEBUG=true \ --env=DRONE_GIT_ALWAYS_AUTH=false \ --env=DRONE_GITLAB_SERVER=http://114.215.25.58 \ --env=DRONE_GITLAB_CLIENT_ID=d6272993ac02c3bb4069d73bf0ff8dabeaff47c0739ae27d1a23e8b80e33faa5 \ --env=DRONE_GITLAB_CLIENT_SECRET=01f454fe0a55256a974d420b8ca023df6efc80b33d8a917dd16138b152b73253 \ --env=DRONE_RPC_SECRET=12345678\ --env=DRONE_RUNNER_CAPACITY=3 \ --env=DRONE_SERVER_HOST=114.215.130.36\ --env=DRONE_SERVER_PROTO=http \ --env=DRONE_TLS_AUTOCERT=false \ --publish=80:80 \ --publish=443:443 \ --restart=always \ --detach=true \ --name=drone \ drone/drone:1
|
参数说明:
参数 |
说明 |
DRONE_RPC_SECRET |
runner连接server的凭证 |
DRONE_RUNNER_CAPACITY |
server调用runner的并发数 |
DRONE_SERVER_HOST |
server的ip |
DRONE_SERVER_PROTO |
server对外提供的协议可选http和https |
部署Drone-runner
采用Docker的方式
1 2 3 4 5 6 7 8 9 10 11
| docker run -d \ -v /var/run/docker.sock:/var/run/docker.sock \ -e DRONE_RPC_PROTO=http \ -e DRONE_RPC_HOST=172.31.227.147 \ -e DRONE_RPC_SECRET=12345678 \ -e DRONE_RUNNER_CAPACITY=3 \ -e DRONE_RUNNER_NAME=${HOSTNAME} \ -p 3000:3000 \ --restart always \ --name runner \ drone/drone-runner-docker:1
|
检查日志查看是否部署成功

在gitlab go-server项目创建名为.drone文件填入以下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| kind: pipeline type: docker name: build steps: - name: build-code image: golang:alpine pull: if-not-exists # always never commands: - pwd - ls - go build server.go - ls - name: build-image image: plugins/docker settings: repo: 172.31.227.151/go-server/go-server registry: 172.31.227.151 use_cache: true username: from_secret: registry_username password: from_secret: registry_password tags: ${DRONE_BUILD_NUMBER} insecure: true mirror: https://yefnfc9c.mirror.aliyuncs.com/ trigger: branch: - master event: - push
|
连接镜像仓库的凭证环境变量可在Drone对应的项目中定义好

参数说明:
参数 |
说明 |
DRONE_RPC_PROTO |
runner连接server协议 |
DRONE_RPC_HOST |
server的地址 |
DRONE_RPC_SECRET |
连接server的凭证 |
commit代码后会自动运行CI

Jenkins配置使用
应用概述

整体CICD流程
- push code to trigger Gitlab webhook
- compiling the code and build image
- test
- upload image to harbor
- Generate a new YML file
- deploy/upgrade
先决条件
1、clone front-end项目
1
| git clone https://gitee.com/wanshaoyuan/front-end.git
|
2、并上传到内部gitlab上
3、在harbor中创建front-ent项目
4、在jenkins中安装好gitlab、docker、Kubernetes插件
5、部署sock-shap
1
| git clone https://gitee.com/wanshaoyuan/microservices-demo.git
|
1 2
| kubectl create namespace sock-shop kubectl apply -f microservices-demo/deploy/kubernetes/manifests/.
|
访问
Jenkins安装
1
| docker run -itd --name jenkins -u root -p 50000:50000 -p 8080:8080 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkins/jenkins:lts
|
节点安装git
获取jenkins密码
1
| docker logs jenkins |grep password
|

安装推荐的Jenkins插件

Jenkins对接Gitlab
安装gitlab插件

Gitlab中申请AccessToken



将申请成功的token保存好
配置Jenkins对接gitlab


测试连接

测试
在gitlab中创建项目
上传个test.txt文件通过Jenkins读取


配置连接gitlab私有项目的密钥可以用ssh密钥也可以使用账号密码


构建

去cat这个文件输出内容

执行立即构建

输出结果

Jenkins对接Kubernetes
安装Kubernetes插件

Jenkins-CI对接Kubernetes
配置
系统管理—>系统设置—>新增一个云

配置Jenkins URL,这里我们没有配置api-server地址和证书key,连接kubernetes,所以默认会去读取放在JENKINS_HOME的.kube/目录的kubeconfig文件,用于连接集群。我这里是通过安装包的方式安装的Jenkins HOME在/var/lib/jenkins/目录,如果是通过容器方式启动,将kubeconfig文件直接放~/.kube/目录。
从RancherUI上复制配置文件

保存到Jenkins主机的config文件中
复制粘贴到Jenkins容器内的~/.kube/config文件中
1 2
| docker exec -it jenkins mkdir /root/.kube/ docker cp config jenkins:/root/.kube/config
|
在编译集群对应项目下创建secret
在jenkins系统设置中创建一个Kubernetes云

演示效果
修改前,先展示前端。(https://github.com/microservices-demo/front-end)这里我们演示修改前端logo,然后git push到代码仓库,触发Jenkins进行cicd操作,修改front-end/public/navbar.html的<img src=”img/logo.png”为新的图片地址,然后将代码提交触发cicd重新打开前端看见logo变了。
创建cicd Pipeline
生成连接gitlab的凭证Grove语句

添加Harbor凭证


创建流水线任务

添加以下Pipeline任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| pipeline { environment { registry = "172.31.227.151" project_name = "/front-end" app_name = "/front-end" registryCredential = 'harbor' } agent { kubernetes { defaultContainer 'wanshaoyuan/jnlp-slave:3.27-1-alpine' yaml """ apiVersion: v1 kind: Pod metadata: labels: some-label: some-label-value spec: containers: - name: jnlp image: 'wanshaoyuan/jnlp-slave:3.27-1-alpine' args: ['\$(JENKINS_SECRET)', '\$(JENKINS_NAME)'] - name : docker image: wanshaoyuan/docker:19.03.2 tty: true volumeMounts: - name: repo-docker-sock mountPath: /var/run/docker.sock - name: kubectl image: wanshaoyuan/jenkins-tools:v1.0 tty: true volumeMounts: - mountPath: "/root/.kube" name: "volume-0" readOnly: false volumes: - name: "volume-0" secret: secretName: "kubeconfig" - name: repo-docker-sock hostPath: path: /var/run/docker.sock """ } } stages { stage('clone code') { steps { git credentialsId: '9371d980-6bc2-47aa-a47f-04cf78871e7a', url: 'http://114.215.25.58/root/front-end.git' } } stage('image build ') { steps { container('docker') { script { docker.withRegistry( 'http://172.31.227.151', registryCredential ) { def dockerImage=docker.build registry + project_name + app_name +":$BUILD_NUMBER" dockerImage.push() } } } } } stage('deploy app ') { steps { container('kubectl') { sh 'sed -i "s/image: .*front-end:.*/image: 172.31.227.151\\/front-end\\/front-end:$BUILD_ID/g" front-end-dep.yaml' sh 'kubectl apply -f front-end-dep.yaml' } } } } }
|
- 定义环境变量:镜像仓库地址、项目名称、应用名称、连接镜像仓库的认证信息。
- 定义jnlp-agent POD所启动的container,包括jnlp容器,用于根jenkins进行通信,maven容器用于代码编译、docker 容器,用于容器镜像编译,kubectl容器用于连接对应的kubernetes集群用于应用创建和更新。
- 定义四个阶段,每个阶段定义对应的步骤,调用对应的容器实现功能(clone代码阶段、代码编译阶段、容器镜像构建阶段、应用部署阶段)
- 每个阶段调用对应的容器实现,如代码编译阶段调用编译容器进行、容器镜像构建阶段调用docker镜像映射宿主机socket进行。
配置gitlab自动触发Jenkins CICD
编辑jenkins项目

配置使用Build when a change is pushed to GitLab. GitLab CI Service URL: http://191.8.2.112:12000/project/test-go-dev
当代码有更新的时候触发,通过GitLab CI
打开gitlab,配置webhook回掉地址,填入jenkins对应项目地址
gitlab对应的项目设置页

默认触发器是push事件时,触发webhook,需要注意的是因为我们这里的Jenkins配置了用户名和密码所以
url需要在原来基础上添加用户名和密码其他不变
格式为
http://username:password@192.168.1.4:1080/project/dashboard-build
默认测试webhook调用

默认一个代码commit的请求
下载logo放置
1
| wget https://rancher.com/img/brand-guidelines/assets/logos/png/cow/rancher-logo-cow-blue.png
|
修改前端logo,然后git push到代码仓库,触发Jenkins进行cicd操作,修改front-end/public/navbar.html的<img src=”img/logo.png”为新的图片地址,然后将代码提交触发cicd重新打开前端看见logo变了。


Rancher-Pipeline配置使用
概述
Rancher2.x Pipeline支持在发布阶段直接将应用发布到应用商店,部署阶段直接从应用商店部署应用,以下为操作步骤
先决条件
- 提前创建好存放统一chart的目录目录结构如下:
./charts/app_name/version
将app_name和Version替换为实际应用名和版本号
CICD到应用商店流程
1 2 3 4 5 6
| graph LR A[源码库]-- "Jenkins clone源码完成其他CI环节" --> B[clone catalog 模板并通过Jenkins修改模板] B -- "git push" --> C[push到统一存放catalog目录] C-- "Rancher-server自动同步更新" --> c[UI显示新版本可更新]
|
应用chart制作
继续使用go-server项目的例子
创建应用源码目录创建专属chart目录
目录结构如下
创建目录
1
| mkdir /go-server/go-server-chart
|
在目录go-server-chartt内创建以下文件和文件夹
1 2 3 4 5 6 7 8 9 10
| go-server-chart │ ├── 0 │ │ ├── Chart.yaml │ │ ├── questions.yml │ │ ├── templates │ │ │ ├── _helpers.tpl │ │ │ ├── go-server-dep.yaml │ │ │ └── go-server-svc.yaml │ │ └── values.yaml │ └── README.md
|
0表示版本文件夹,如果要发布新版本只需要创建个1或者另外文件夹,然后修改Chart.yaml文件里面的版本号。
README.md 内定义对应用的说明
Chart.yaml
1 2 3 4 5
| apiVersion: v1 description: go-server name: go-server version: ${CICD_EXECUTION_SEQUENCE} icon: http://ohx02qrb8.bkt.clouddn.com/micheling.png
|
详细环境变量参考
1
| https://rancher.com/docs/rancher/v2.x/en/k8s-in-rancher/pipelines/
|
定义软件的描述、名字、版本、图标地址
questions.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| questions: - variable: replicaCount default: "1" description: "Replica count" type: string required: true label: Replicas - variable: imageName default: "172.31.227.151/go-server/go-server" description: "image name" type: string required: true label: image_name - variable: imageTage default: "latest" description: "image version" type: string required: true label: image_version - variable: nodeport default: "30000" description: "NodePort port number(to set explicitly, choose port between 30000-32767)" type: string required: true label: nginx Service NodePort number
|
定义变量,主要与ui上对应
variable: 对应template里面的.Values.xxx值
default:当用户没有设置自定义值时的默认值
description: ui上用户自定义值的描述
type: 自定义值的数据类型
required: 是否必填
label:标签
values.yaml: values.yaml 则提供了这些配置参数的默认值。
templates :放置实际要执行的应用的yaml文件
go-server-dep.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| apiVersion: apps/v1 kind: Deployment metadata: labels: cattle.io/creator: norman workload.user.cattle.io/workloadselector: deployment-default-test name: test namespace: default spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: workload.user.cattle.io/workloadselector: deployment-default-test template: metadata: labels: workload.user.cattle.io/workloadselector: deployment-default-test spec: containers: - image: {{ .Values.imageName }}:{{ .Values.imageTage }} imagePullPolicy: Always name: test ports: - containerPort: 8080 name: 8080tcp01 protocol: TCP stdin: true tty: true
|
go-server-svc.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| apiVersion: v1 kind: Service metadata: labels: cattle.io/creator: norman name: test-nodeport namespace: default spec: ports: - name: 8080tcp01 nodePort: {{ .Values.nodeport }} port: 8080 protocol: TCP targetPort: 8080 selector: workload.user.cattle.io/workloadselector: deployment-default-test type: NodePort
|
_helpers.tpl 定义一些系统通用的继承变量一般不需要,直接用默认就好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| {{/* vim: set filetype=mustache: */}} {{/* Expand the name of the chart. */}} {{- define "name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). */}} {{- define "fullname" -}} {{- $name := default .Chart.Name .Values.nameOverride -}} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} {{- end -}}
|
同时创建实际的catalog目录
继续按上面方式创建一个go-server的chart应用,需要修改Chart.yaml文件这里就不能在用变量了,因为使用添加私有应用商店时是读取不出变量的,在源码库内的chart.yaml用变量是因为需要动态更新。
Chart.yaml
1 2 3 4 5
| apiVersion: v1 description: go-server name: go-server version: v1.0 icon: http://ohx02qrb8.bkt.clouddn.com/micheling.png
|
然后push到代码仓库的chart项目
Pipeline配置
创建secret用于push时的代码仓库的帐号密码

如果push是ssh方式这里的secret就放置公钥
USERNAME和PASSWORD两个key
创建镜像仓库凭证用于上传镜像

选择代码库创建Pipeline

创建代码编译步骤

创建编译上传镜像步骤

创建发布应用模板步骤

类型选择Publish Catalog Template


- Chart Folder:填写源码库内的chart的相对路径
- Catalog Template Version:这里填写Rancher Pipeline环境变量根在代码库内chart目录Chart.yaml Version一致
- Catalog Template Name:为你的catalog应用的名称,如果你是生成一个新的catalog。统一存放catalog目录没有这个应用则可以根据实际需求取名字,如果是在原有基础上更新则有已有的catalog,则用原目录名
运行Pipeline

catalog自动更新

对应代码目录下 .rancher-pipeline.yml
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| stages: - name: cod_build steps: - runScriptConfig: image: golang:latest shellScript: go build server.go - name: image_build steps: - publishImageConfig: dockerfilePath: ./Dockerfile buildContext: . tag: go-server/go-server:${CICD_GIT_COMMIT} pushRemote: true registry: 172.31.227.151 env: PLUGIN_INSECURE: "true" PLUGIN_MIRROR: https://yefnfc9c.mirror.aliyuncs.com - name: update_catalog steps: - publishCatalogConfig: path: ./go-server-chart/0 catalogTemplate: go-server version: ${CICD_EXECUTION_SEQUENCE} gitUrl: http://114.215.25.58/root/chart.git gitBranch: master gitAuthor: root gitEmail: shaoyua@rancher.com envFrom: - sourceName: gitlab sourceKey: USERNAME targetKey: USERNAME - sourceName: gitlab sourceKey: PASSWORD targetKey: PASSWORD timeout: 60
|