微服务自动化部署CI/CD

一直有人说想了解微服务的自动化部署,今天它来了。


在微服务化的时代,自动化部署越来越成为企业的重中之重了,因为这样减少了人员的成本,开发人员将代码提交后,触发相关事件即可部署测试环境,甚至得到许可后部署到线上。这样,原先开发人员、运维人员等要做的事,通通不必再重复劳作了。这对于一个企业来说,leader比较在乎的一件事。今天讲解通过jenkins、gitlab、harbor、k8s来作简单的CI/CD平台,暂时未涉及到代码检测等。


环境:

1
2
3
ubuntu16.04
docker18.04
k8s1.13.x +

1. 准备

以上系统环境准备好,本文讲述的是用 k8s 来进行部署 jenkins


2. 部署 jenkins

新建部署脚本 jenkins.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
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
apiVersion: v1
kind: Service
metadata:
name: jenkins-service
namespace: default
labels:
app: jenkins
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
protocol: TCP
nodePort: 30600
name: jenkins
- port: 30000
targetPort: 30000
nodePort: 30000
protocol: TCP
name: agent
selector:
app: jenkins
tier: jenkins

---

apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-deployment
labels:
app: jenkins
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: jenkins
tier: jenkins
spec:
containers:
- name: jenkins
image: jenkinsci/blueocean:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: jenkins
- containerPort: 30000
name: agent
volumeMounts:
- mountPath: /var/jenkins_home
name: jenkins-data
- mountPath: /data/jenkins
name: jenkins-log-path
volumes:
- name: jenkins-data
hostPath:
path: /home/demo/jenkins
- name: jenkins-log-path
hostPath:
path: /data/jenkins

执行脚本:

1
kubectl apply -f jenkins.yaml

查看部署成功的 pod

1
kubectl get pod

同时会看到一个 service 生成,映射端口到外部。

接下来通过页面访问该服务,首次打开后,会让输入一个 admin 的密钥,这一串字符可以在日志中找到,执行 kubectl logs -f test-jenkins-c6bd58bf9-tgmsa 即可,输入一串字符后,进入下一步,需要安装一些插件,在安装插件的时候,需要注意的是,选择 jenkins 的 image 不同,其所需安装的插件也是不一样的,有的可能 image 已经存在了。
具体请看:https://jenkins.io/zh/doc/book/installing/

安装完插件后,进入下一步,创建第一个账户,管理员账户,一般建议创建,方便后面使用,注:邮箱也需要填写。


完成以上后,我们进入正式界面:


第一步:点击系统管理—>插件管理,添加一些插件,这里有用到kubernetes的插件,故安装了kubernetes plugins,其他的可根据自行项目确定下载、安装。


第二步:点击系统管理—>系统设置

添加jenkins的地址以及邮件地址


第三步:拉动滚动框到最下面,新增一个云

这里我加了kubernetes的配置,为什么后面会讲。


第四步:新建任务

在触发器中新增规则,最下面要生成token。


第五步:

接下来就是选择与gitlab互动,gitlab的地址以及凭据,凭据可通过首页加上可访问gitlab的用户信息,脚本路径需要根据自身的Jenkinsfile路径情况填写。


第六步:

如果启用全局安全,这个端口本身是50000,但由于k8s的默认nodePort范围是30000-32767,故可以修改在这区间内,比如:30000,这也是为什么上面创建时service的nodePort是30000了。


至此,jenkins环境配置完成


第七步:配置gitlab

这里的url就是在新建任务时生成的Gitlab webhook,token就是上面截图生成的token,最后add webhook。


第八步:

关于Harbor,自己可以简单搭建一个harbor服务,找度娘问一下很多,此处略。


第九步:

新建Jenkinsfile文件,如果刚才的路径是在项目根目录,则直接在项目根目录下创建Jenkinsfile文件:

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
def label = "mypod-${UUID.randomUUID().toString()}"


def k8sPodYaml = """
apiVersion: "v1"
kind: "Pod"
metadata:
labels:
jenkins: "slave"
name: "${label}"
spec:
containers:
- env:
- name: "CI_ENV"
value: "YES"
- name: "JENKINS_AGENT_WORKDIR"
value: "/home/jenkins/agent"
image: "jenkins/jnlp-slave"
imagePullPolicy: "Always"
name: "jnlp"
resources:
limits: {}
requests: {}
securityContext:
privileged: false
tty: false
volumeMounts:
- mountPath: "/home/jenkins/.kube"
name: "volume-2"
readOnly: false
- mountPath: "/var/run/docker.sock"
name: "volume-0"
readOnly: false
- mountPath: "/var/inference/config"
name: "volume-1"
readOnly: false
- mountPath: "/usr/local/bin/kubectl"
name: "volume-3"
readOnly: false
- mountPath: "/home/jenkins/agent"
name: "workspace-volume"
readOnly: false
workingDir: "/home/jenkins/agent"
nodeSelector: {}
restartPolicy: "Never"
volumes:
- hostPath:
path: "/var/run/docker.sock"
name: "volume-0"
- hostPath:
path: "/home/leinao/.kube"
name: "volume-2"
- hostPath:
path: "/home/leinao/inference-deploy/output_config"
name: "volume-1"
- emptyDir: {}
name: "workspace-volume"
- hostPath:
path: "/usr/local/bin/kubectl"
name: "volume-3"

下面是自己的任务构建项目时的逻辑,由于我们这块用了自己的框架写的编译逻辑,故比较简单的,这里不合适公开,但是逻辑都差不多,大家可自行编写。

这块解释上面的k8s的yaml,这个就是为了在k8s中启动一个pod,通过该pod来执行构建逻辑的过程。



到此,关于Jenkins结合harbor、gitlab、k8s来实现CI/CD结束了,有几点注意的地方:

1. 如果jenkins是在容器中启动的一定要记得将这个端口(30000)暴露到外部,不然jenkins-master会不知道slave是否已经启动,会反复去创建pod只到超过重试次数。

2. 如果提示Jenkins doesn’t have label jenkins-jnlp-slave,可能原因:

    1). 因为slave节点无法链接到jenkins节点开放端口50000导致

    2). 因为slave镜像中slave启动失败导致的

    3). 因为jenkins和k8s通信有延时导致超时jenkins会反复创建pod

    4). 因为slave pod启动失败

    5). 因为pipeline中指定的label与配置中的不一致导致

3. 也可以通过Ingress暴露的方式来进行暴露。

结束福利

开源实战利用 k8s 作微服务的架构设计代码:

1
2
3
https://gitee.com/damon_one/spring-cloud-k8s
https://gitee.com/damon_one/spring-cloud-oauth2
https://gitee.com/damon_one/Springcloud-Learning-Dalston

欢迎大家 star,多多指教。


关于作者

  笔名:Damon,技术爱好者,长期从事 Java 开发、Spring Cloud 的微服务架构设计,以及结合 Docker、K8s 做微服务容器化,自动化部署等一站式项目部署、落地。目前主要从事基于 K8s 云原生架构研发的工作。Golang 语言开发,长期研究边缘计算框架 KubeEdge、调度框架 Volcano 等。公众号 交个朋友之猿天地 发起人。个人微信 DamonStatham,星球:《交个朋友之猿田地》,个人网站:交个朋友之猿天地 | 微服务 | 容器化 | 自动化,欢迎來撩。


欢迎关注:InfoQ

欢迎关注:腾讯自媒体专栏


欢迎关注

公号:交个朋友之猿天地

公号:damon8

公号:天山六路折梅手


打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2023 交个朋友之猿天地
  • Powered By Hexo | Title - Nothing
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信