本章节主要讲的是 springboot 项目发到 gitlab 仓库,触发 gitlab ci/cd 实现项目自动集成和部署,其中部署是以 k8s 方式部署

关于 gitlab-runner 安装和注册可以参考我的另一篇博客 Docker安装gitlab-runner 实现自动 CI/CD (持续集成/持续部署) 配置

关于 k8s 集群搭建可以参考我的另一篇博客 k8

s 集群之使用 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);

    @GetMapping
    public 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 上配置,如下图

springboot的libraries在哪 springboot ci_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_NAME
  namespace: demo
  labels:
    app: ci-cd-demo
spec:
  type: NodePort
  ports:
  - name: ci-cd-demo
    port: 8080
    protocol: TCP
    nodePort: 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-demo
  template:
    metadata:
      labels:
        app: ci-cd-demo
    spec:
      containers: #docker容器的配置
      - name: $DEPLOYMENT_NAME
        image: $PROJECT_IMAGE
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
        env: 
        - name: JAVA_OPTS
          value: -Xms256m -Xmx256m
      imagePullSecrets:
      - 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:stable

variables:
  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-cache
  DEPLOYMENT_NAME: springboot-ci-cd-demo  # 项目在 k8s 中部署的名称
  K8S_NS: demo  # k8s 命名空间

stages:
  - package
  - build
  - deploy

# 打包
package:
  stage: package
  # 打包用到了maven, 所有需要拉取maven镜像, 这是我自己构建的阿里云maven私服的maven镜像
  image: $MAVEM_IMAGE
  script:
    - echo "=============== mvn package  ==============="
    - mvn $MAVEN_OPTS clean package -Dmaven.test.skip=true
  # 只作用在master分支
  only:
    - master
  # 使用缓存速度更快,如果希望在gitlab-ci页面上可以下载jar包,可以使用下边的 artifacts 方式
  cache:
    key: $PACKAGE_CACHE_REF_NAME
    paths:
      - target/*.jar
  # 这里可以将maven 打包好的文件传递给下一个 stage ,然后下一步的docker 就可以根据 这个 jar 包 和Dockerfile 构建镜像
#    artifacts:
#      # 指定下过期时间和路径
#      # expire_in: 1 days
#      paths:
#        - target/*.jar

# 构建docker镜像并推送到镜像仓库
build:
  stage: build
  cache:
    key: $PACKAGE_CACHE_REF_NAME
    policy: pull
    paths:
      - target/*.jar
  script:
    - echo "=============== docker build image  ==============="
    - docker build -t $PROJECT_IMAGE .
    - docker login --username $USERNAME --password $PASSWORD $PROJECT_IMAGE_SERVER
    - docker push $PROJECT_IMAGE
  only:
    - master

# 使用 k8s 部署
deploy:
  stage: deploy
  image: $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_profile
  script:
    - 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
    - fi
  only:
    - 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,如下图

springboot的libraries在哪 springboot ci_kubernetes_02

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

springboot的libraries在哪 springboot ci_ci/cd_03

如上显示说明项目已经部署成功

`

k8s 默认容器如果重建,则容器中的数据文件将会丢失,所以需要将一些数据文件挂载到外部目录,可以参考我的另一篇博客 k8s 集群之使用 nfs 网络存储挂载外部目录和文件