转自
讲正文开始前先回顾一下以往传统的代码部署方式。
通常运维人员在接到代码(新项目)上线的任务前都要做大量的准备工作,包括:物理主机、虚拟机、代码运行环境、数据库安装配置、各种帐号创建,、运行后期的系统监控、应用的日志收集,性能优化等一系列的工作。
想一想这个流程不是很复杂但是很繁琐,效率低下,如需要调试还需要给开发人员提供线上系统权限等等,细节没有注意的话,还会造成解决问题的难度等各种问题。
OK,说完以上的问题,那接下来就有相对应的解决方案。
方案大概的架构组成:
Jenkins+Gitlab+Harbor+Rancher+k8s
各个组件的功能描述
(1)下载gitlab中项目代码
(2)负载执行镜像的构建、上传下载
(3)部署到k8s集群
(1)项目代码以及配置
(2)Dockerfile文件
这个是vmware公司开源的docker镜像仓库管理系统,比较方便管理维护镜像
(1)负责构建后镜像的存储
容器编排管理工具
(1)更新stack/service
(2)实现服务的扩容缩容
(1)简化应用部署
(2)提高硬件资源利用率
(3)健康检查和自修复
(4)自动扩容缩容
(5)服务发现和负载均衡
项目开发语言是java,使用了比较流行的spring boot框架,manven更新源采用阿里云,编译生成jar文件
① 开发人员提交代码到gitlab
② 手动执行jenkins构建(或者gitlab钩子触发jenkins执行构建),下载最新版本的代码,代码里面包含Dockerfile
③ jenkins执行shell脚本:mvn编译生成jar文件。通过docker build 指令打包成镜像
④ 上传构建好的镜像push到harbor镜像仓库
⑤ jenkins远程到k8s master节点,更新service镜像地址,达到更升级容器的目的(也就是更新代码版本)。
以上流程完整的实现了CI/CD,这里主要是jenkins部分是关键位置之一。
系统 | ip | 主机名 | 配置 | 版本 |
CentOS 7.6 | 10.212.20.94 | k8s-master | 2核4g | Kubernetes1.18.1 |
CentOS 7.6 | 10.212.20.240 | k8s-node01 | 2核4g | Kubernetes1.18.1 |
CentOS 7.6 | 10.212.82.89 | jenkins | 2核4g | 2.222.4 |
CentOS 7.6 | 10.212.82.90 | gitlab | 2核4g | 10.5.1 |
CentOS 7.6 | 10.212.82.86 | harbor | 2核4g | v2.0.0 |
CentOS 7.6 | 10.212.82.87 | rancher | 2核4g | v2.4.3 |
关于k8s 1.18.1安装,请参考链接:
CentOS7安装Kubernetes1.18.1并使用flannel - 肖祥 - 博客园
关于jenkins安装,请参考链接:
centos7安装jenkins - 肖祥 - 博客园
关于Gitlab和Harbor安装,请自行百度
关于rancher安装以及导入现有k8s集群,请参考链接:
Rancher管理k8s集群 - 肖祥 - 博客园
基于Spring Boot/Spring Security/thymeleaf的通用后台管理系统
项目地址:
https://github.com/jonsychen/admin
此项目依赖于mysql,因此需要提前在Rancher里面部署mysql才行。
登录k8s-node01主机,创建数据目录
mkdir -p /data/mysql/data
访问Harbor后台,点击部署服务
端口映射
设置环境变量
TZ=Asia/Shanghai MYSQL_ROOT_PASSWORD=abcd@1234
数据卷映射
点击启动
下载代码:https://github.com/jonsychen/admin
解压之后,进入目录admin-mastersrcmain esources
修改application-default.yaml,修改红色部分。
server: port: 8088 compression: enabled: true connection-timeout: 3000 debug: false ##登录记住我的token加密key remember: key: yintong ##actuator config,actuator运行在一个独立的webappcontext中,see AnnotationConfigEmbeddedWebApplicationContext management: context-path: /management security: enabled: false spring: application: name: admin datasource: url: jdbc:mysql://db-mysql.default.svc.cluster.local:3306/admin?characterEncoding=utf-8 username: root password: abcd@1234
说明:
port: 8088 项目运行的端口号
db-mysql.default.svc.cluster.local 表示db-mysql服务的svc地址。
格式说明:服务名.命令空间.default.svc.cluster.local ,其中服务名和命名空间是根据实际情况来的,后半部分是固定的。这一长串域名,会解析为svc地址。
password: abcd@1234 mysql的root用户密码
application-prod.yaml的配置修改同上。
在此项目的根目录创建dockerfile
FROM mayan31370/openjdk-alpine-with-chinese-timezone:8-jdk ADD admin-0.1.0.jar / EXPOSE 8088 ENTRYPOINT [ "java","-jar","/admin-0.1.0.jar"]
此时顶层目录结构如下:
# tree -L 1 . ├── dockerfile ├── etc ├── pom.xml ├── README.md └── src
将此项目代码,提交到gitlab中。
登录k8s-master节点,查看svc映射端口。因为使用Rancher部署mysql时,nodeport端口是随机的。
# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE db-mysql ClusterIP 10.1.116.03306/TCP 61s db-mysql-nodeport NodePort 10.1.86.36 3306:31959/TCP 61s kubernetes ClusterIP 10.1.0.1 443/TCP 20d
可以看到随机映射的端口是31959
使用navicat软件连接mysql
新建数据库book
create database admin default character set utf8mb4 collate utf8mb4_unicode_ci;
进入book,执行项目中的sql文件,路径为:etc/ddl.sql
执行成功后,表如下:
新建一个项目java,访问级别是公开。注意:设置公开后,下载镜像不需要认证。
进入jenkins主机,下载gitlab代码。
git clone ssh://[email protected]:/home/git/git_storage/admin-master
修改docker配置,增加Harbor库地址。
vim /etc/docker/daemon.json
增加insecure-registries
{"insecure-registries": ["10.212.82.86"]}
重启服务
systemctl restart docker
登录Harbor,否则无法推送镜像
docker login 10.212.82.86:1180
进入项目目录,使用mvn编译代码
mvn -f pom.xml clean package
推送镜像,执行命令:
cp dockerfile target/ cd target docker build -t 10.212.82.86:1180/java/admin-master:1 . docker push 10.212.82.86:1180/java/admin-master:1 docker rmi 10.212.82.86:1180/java/admin-master:1
登录k8s-node01节点
修改docker配置,增加Harbor库地址。
vim /etc/docker/daemon.json
增加insecure-registries
{"insecure-registries": ["192.168.10.122"]}
重启服务
systemctl restart docker
访问Harbor后台,点击部署服务
端口映射
点击启动
等待几分钟,Running表示运行正常。
登录k8s-master节点,查看svc映射端口。因为使用Rancher部署时,nodeport端口是随机的。
# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE admin-master ClusterIP 10.1.10.238088/TCP 10m admin-master-nodeport NodePort 10.1.238.46 8088:31581/TCP 10m db-mysql ClusterIP 10.1.116.0 3306/TCP 61s db-mysql-nodeport NodePort 10.1.86.36 3306:31959/TCP 61s kubernetes ClusterIP 10.1.0.1 443/TCP 20d
可以看到nodeport映射的随机端口是31581
访问admin-master
http://10.212.20.94:31581/
输入用户名和密码,都是root
首页效果如下:
前面已经通过Rancher部署了mysql和admin-master,接下来演示一下,如何通过jenkins实现基于Pipeline,实现发布和回滚。
这个插件是用来做参数化构建的
新建一个job,名称为:test_admin,选择流水线。
通用设置
参数化构建
Pipeline脚本
完整代码如下:
env.CREDENTIALSID = '7a294fc5-2b2b-4d2d-92ff-54324e1b032a' env.BRANCHES = 'master' env.GIT_URL = 'ssh://[email protected]:/home/git/git_storage/admin-master' env.HARBOR_PROJECT = '10.212.82.86:1180/java/admin-master' env.PROJECT = 'admin-master' env.K8S_MASTER = '10.212.20.94' env.NAMESPACE = 'default' node { if (env.Status == 'Deploy'){ stage('code pull') { checkout([$class: 'GitSCM', branches: [[name: env.BRANCHES]], doGenerateSubmoduleConfigurations: false, userRemoteConfigs: [[credentialsId: env.CREDENTIALSID, url: env.GIT_URL]]]) } stage('code Build') { sh 'mvn -f pom.xml clean package' } stage('docker push') { sh 'cd ${WORKSPACE} && cp dockerfile target' sh 'cd ${WORKSPACE}/target && docker build -t ${HARBOR_PROJECT}:${BUILD_NUMBER} .' sh 'docker push ${HARBOR_PROJECT}:${BUILD_NUMBER}' sh 'docker rmi ${HARBOR_PROJECT}:${BUILD_NUMBER}' } stage('k8s deploy') { sh 'ssh ${K8S_MASTER} "kubectl -n ${NAMESPACE} set image deploy ${PROJECT} *=${HARBOR_PROJECT}:${BUILD_NUMBER}"' } }else{ stage('k8s rollback') { sh 'ssh ${K8S_MASTER} "kubectl -n ${NAMESPACE} set image deploy ${PROJECT}*=${HARBOR_PROJECT}:${BUILD_ID}"' } } }
根据实际情况,修改红色文字参数,也就是全局变量。
说明:
7a294fc5-2b2b-4d2d-92ff-54324e1b032a 这个是jenkins全局凭据,针对gitlab设置的。
点击构建
直接点击构建
构建成功后,效果如下:
如果需要回滚到上一个版本,输入BUILD_ID。
由于最近成功一次的BUILD_ID是10,所以输入9
效果如下: