本章节主要讲的是 springboot 项目发到 gitlab 仓库,触发 gitlab ci/cd 实现项目自动集成和部署,其中部署是以 k8s 方式部署
关于 gitlab-runner 安装和注册可以参考我的另一篇博客 Docker安装gitlab-runner 实现自动 CI/CD (持续集成/持续部署) 配置
关于 k8s 集群搭建可以参考我的另一篇博客 k8s 集群之使用 kubeadm 在 Centos8 上部署 kubernetes 1.20
先创建 springboot 项目 push 到 gitlab 远程仓库,这里项目名称是 springboot-ci-cd-demo
新建一个 Controller 用于测试,如下
@RestController
@RequestMapping("/demo")
public class DemoController {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoController.class);@GetMappingpublic String demo() throws UnknownHostException {
String hostAddress = InetAddress.getLocalHost().getHostAddress();LOGGER.info("{} : Hello, 2021 Happy New Year", hostAddress);return hostAddress + " : Hello, 2021 Happy New Year";}
}
gitlab-runner 安装好之后,注册 gitlab-runner 可使用如下命令,url 和 registration-token 在 gitlab 页面获取(注册如有不理解可以参考我的另一篇博客 Docker安装gitlab-runner 实现自动 CI/CD (持续集成/持续部署) 配置)
docker run -it --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner register \--non-interactive \--executor "docker" \--docker-privileged \--docker-image docker:latest \--url "https://gitlab.com/" \--registration-token "2xAmgi-WmzWh9evSH*****" \--description "ci-runner" \--tag-list "" \--run-untagged="true" \--locked="false" \--access-level="not_protected";
部分变量需要在 gitlab 上配置,如下图
REG_USERNAME 和 REG_PASSWORD 是镜像仓库的用户名和密码
K8S_ADMIN_CONF :value 的值取之 k8s 集群环境 master 节点的 admin.conf 配置文件,拷贝文件里边的内容放到 value 里
K8S_DEMO_YAML:value 的值如下(值里边的变量需要在当前页面定义或者在,gitlab-ci.yml文件里边定义)
---
apiVersion: v1
kind: Service
metadata:name: $DEPLOYMENT_NAMEnamespace: demolabels:app: ci-cd-demo
spec:type: NodePortports:- name: ci-cd-demoport: 8080protocol: TCPnodePort: 30080 selector:app: ci-cd-demo---
apiVersion: apps/v1
kind: Deployment #对象类型
metadata:name: $DEPLOYMENT_NAME #名称labels:app: ci-cd-demo #标注
spec:replicas: 1 #运行容器的副本数,修改这里可以快速修改分布式节点数量selector:matchLabels:app: ci-cd-demotemplate:metadata:labels:app: ci-cd-demospec:containers: #docker容器的配置- name: $DEPLOYMENT_NAMEimage: $PROJECT_IMAGEimagePullPolicy: Alwaysports:- containerPort: 8080protocol: TCPenv: - name: JAVA_OPTSvalue: -Xms256m -Xmx256mimagePullSecrets:- name: regsecret
编写 Dockerfile 文件,放在项目根目录
FROM openjdk:8-jdk
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
编写 .gitlab-ci.yml 文件,放在项目根目录
# 因为我们Runner执行器设置为docker, 所以这里需要指定docker的版本
image: docker:stablevariables:MAVEM_IMAGE: registry.cn-hangzhou.aliyuncs.com/sanchar/maven:1.0 # maven 打包使用的镜像K8S_IMAGE: registry.cn-hangzhou.aliyuncs.com/sanchar/kubectl:v1.20.1 # k8s 部署使用的镜像PROJECT_IMAGE_SERVER: registry.cn-hangzhou.aliyuncs.com # 阿里云镜像地址PROJECT_IMAGE: registry.cn-hangzhou.aliyuncs.com/sanchar/springboot-ci-cd-demo:1.0 # 项目镜像链接MAVEN_OPTS: -Dmaven.repo.local=/.m2 # 指定 maven 本地仓库路径,以便做缓存PACKAGE_CACHE_REF_NAME: springboot-ci-cd-demo-cacheDEPLOYMENT_NAME: springboot-ci-cd-demo # 项目在 k8s 中部署的名称K8S_NS: demo # k8s 命名空间stages:- package- build- deploy# 打包
package:stage: package# 打包用到了maven, 所有需要拉取maven镜像, 这是我自己构建的阿里云maven私服的maven镜像image: $MAVEM_IMAGEscript:- echo "=============== mvn package ==============="- mvn $MAVEN_OPTS clean package -Dmaven.test.skip=true# 只作用在master分支only:- master# 使用缓存速度更快,如果希望在gitlab-ci页面上可以下载jar包,可以使用下边的 artifacts 方式cache:key: $PACKAGE_CACHE_REF_NAMEpaths:- target/*.jar# 这里可以将maven 打包好的文件传递给下一个 stage ,然后下一步的docker 就可以根据 这个 jar 包 和Dockerfile 构建镜像
# artifacts:
# # 指定下过期时间和路径
# # expire_in: 1 days
# paths:
# - target/*.jar# 构建docker镜像并推送到镜像仓库
build:stage: buildcache:key: $PACKAGE_CACHE_REF_NAMEpolicy: pullpaths:- target/*.jarscript:- echo "=============== docker build image ==============="- docker build -t $PROJECT_IMAGE .- docker login --username $USERNAME --password $PASSWORD $PROJECT_IMAGE_SERVER- docker push $PROJECT_IMAGEonly:- master# 使用 k8s 部署
deploy:stage: deployimage: $K8S_IMAGE# 构建 k8s 可执行环境before_script:- mkdir -p /etc/kubernetes- mv $K8S_ADMIN_CONF /etc/kubernetes/admin.conf- echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile- source ~/.bash_profilescript:- echo "=============== deploy ==============="- if [ "$(kubectl get deployment -n $K8S_NS | grep $DEPLOYMENT_NAME | awk '{print $1}')" ]; then- kubectl set image deploy $DEPLOYMENT_NAME $DEPLOYMENT_NAME=$PROJECT_IMAGE -n $K8S_NS- kubectl scale deployment $DEPLOYMENT_NAME --replicas=0 -n $K8S_NS- kubectl scale deployment $DEPLOYMENT_NAME --replicas=1 -n $K8S_NS- else- mv $K8S_DEMO_YAML $DEPLOYMENT_NAME.yaml- kubectl apply -f $DEPLOYMENT_NAME.yaml -n $K8S_NS- fionly:- master
镜像是私有的,在发布代码跑 CI/CD 之前,k8s 需要配置 imagePullSecrets,在集群环境 master 节点下执行如下命令生成 regsecret
[root@master ~]# kubectl create secret docker-registry regsecret --docker-server=registry.cn-hangzhou.aliyuncs.com --docker-username=用户名 --docker-password=密码 -n 命名空间
配置里镜像仓库的 secret 之后,本地修改的代码推送到远程仓库,gitlab 会自动跑 CI/CD,如下图
CI/CD 跑成功之后,可在 k8s 集群中查看发布的 pod 状态
[root@master ~]# kubectl get pod -n demo
NAME READY STATUS RESTARTS AGE
springboot-ci-cd-demo-5694574854-8xxh9 1/1 Running 0 29m
页面访问接口 http://192.168.1.25:30080/demo
如上显示说明项目已经部署成功
`
k8s 默认容器如果重建,则容器中的数据文件将会丢失,所以需要将一些数据文件挂载到外部目录,可以参考我的另一篇博客 k8s 集群之使用 nfs 网络存储挂载外部目录和文件