jenkins使用自定义方式结合k8s实现ci/cd-后端实战

前情交代:

  1. 在开发环境已经打好了镜像包,并且次镜像包在test环境已经测试通过,现在开发生产环境实现流水线的k8s部署
  2. k8s 应部署完毕,环境ok
  3. jenkins部署完毕
  4. 工作重点在jenkins的部署流程配置和通知k8s拉取镜像。

1. 原有的微服务代码一个字符都不用变

那么问题来了怎么让镜像在prod环境使用nacos上的*-prod.yaml文件呢?归根到底是要通知k8s设置spring-profile-action=prod.
怎么实现这个功能嗯?

  1. 先看一下现有的dockerfile文件:
FROM 10.1.8.151:8082/blade/jdk1.8-skywalking:latest

MAINTAINER Fengkai

RUN mkdir -p /wy/user

WORKDIR /wy/user

EXPOSE 8310

ADD ./target/user.jar ./app.jar

#设置环境变量
ENV SPRING_PROFILES_ACTIVE=dev APP_NAME=wy-user BACKEND_ADDER=10.1.33.131:11800

ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom  -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -Dserver.port=8310 -Duser.timezone=GMT+8 -server -Xms512m -Xmx512m -javaagent:/usr/local/skywalking/skywalking-agent.jar  -Dskywalking.agent.service_name=$APP_NAME-$SPRING_PROFILES_ACTIVE -Dskywalking.collector.backend_service=$BACKEND_ADDER -jar app.jar

在这里插入图片描述
关注点在这里,怎么在k8s的yaml中可以替换这个地方的值,结论是可以的,解决方案语法如下:
在这里插入图片描述

spec: # 规格详情
  minReadySeconds: 20
  replicas: ${REPLICAS}
  selector:
    matchLabels:
      app: ${deploymentName} #匹配的就是lab中定义的
  template:
    metadata:
      labels:
        app: ${deploymentName}
    spec:
      containers:
        - name: ${deploymentName} #容器的名字 docker run --name 后面的名字
          image: ${imageName} # harbor中获取,可能是环境变量的值
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: ${SPRING_PROFILES_ACTIVE}
          ports:
            - containerPort: ${EXPOSEPORT} # 每一个容器都是默认$servicePort启动,因为在容器内不没有问题的。

其他的问题应该都不存在,扫清了这个障碍,我们可以开始需求的开发了。
这里以一个微服务为例展开,最后会总总结,让其他30个微服务复用这一套流程即可,记住,对原来的代码一定不能有入侵性,即要解耦,要不然你有1000000个微服务的时候,你会烦死的。

2. jenkins配置

jenkins的配置值方式这里有三种方式:

  1. 自由风格
  2. pom风格
  3. 流水线

这里采用自由风格。为什么呢?因为本公司均采用的是这种自由风,不过后期我想修改下这个风格使用流水线的风格。
这里特别说明一下哦,这是三条路,每一条均能到达彼岸,所以不要纠结啊。知道语法后都是很简单的。解决问题才是关键。
所有不要纠结号码???嘿嘿嘿!~~
在这里插入图片描述

3. jenkins devops服务器脚本书写

3.1 新建一个item

没有个微服务创建一个item便于管理
在这里插入图片描述

3.2 配置参数

在这里插入图片描述
在这里插入图片描述

3.3 书写脚本

在这里插入图片描述

# docker暴露的端口  EXPOSE 7002
EXPOSEPORT='8310'
# k8s 编排service 端口
NODEPORT='30021'


# blade/blade-demo:12
echo ${DOCKER_IMAGE}

# 先跳到工作目录下:/data/jenkins/workspace/zz
# cd ${WORKSPACE}

# 再次切换到当前项目的路径下,主要是为了那yaml文件
# cd blade-ops/blade-admin/



#仓库地址
registryUrl='10.1.8.151:8082'
#项目名:
projectName=wy
#服务名
serviceName=user


#环境标签
SPRING_PROFILES_ACTIVE=prod



#pod的名字,如:blade-saber-prod
deploymentName=$projectName-$serviceName-$SPRING_PROFILES_ACTIVE

# 容器名字, 如blade-saber-prod
containerName=$projectName-$serviceName-$SPRING_PROFILES_ACTIVE
#镜像名字,如:10.1.8.151:8082/blade/blade-demo:12
imageName=$registryUrl/${DOCKER_IMAGE}

echo '============通知k8s拉取镜像开始==============='

#k8s master ip
MASTER='10.1.33.61'
# k8s 服务器上用于存放配置的目录 推动deploy_k8s.sh和*.yaml去的目录需要推送到k8smaster上
CONF_DIR='/data/kube-conf' 
 # 登录k8s username
K8S_USERNAME='root'
# jenkins服务器用于存放和k8s相关文件的目录
LOCAL_CON_DIR="/data/k8s" 
SH_NAME='deploy_k8s.sh'

# file name of yaml 如:k8s-prod-deploy.yaml
YAML_NAME='deploy_k8s.yaml'
SH_NAME='deploy_k8s.sh'

# transfer yaml & sh to k8s
scp ${LOCAL_CON_DIR}/${YAML_NAME} ${MASTER}:${CONF_DIR} #远程传送yaml
scp ${LOCAL_CON_DIR}/${SH_NAME} ${MASTER}:${CONF_DIR} #远程传送sh

# run k8s script

echo "+x----->"
# k8s 服务器上/data/kube-conf/deploy_k8s.给执行权限
ssh -p '22' ${K8S_USERNAME}@${MASTER} chmod +x ${CONF_DIR}/${SH_NAME}
echo "sh----->"
# k8s 服务器上/data/kube-conf/deploy_k8s.执行
ssh -p '22' ${K8S_USERNAME}@${MASTER} sh ${CONF_DIR}/${SH_NAME} ${deploymentName} ${imageName} ${REPLICAS} ${NAMESPACE} ${YAML_NAME} ${SPRING_PROFILES_ACTIVE} ${EXPOSEPORT} ${NODEPORT}

echo '============通知k8s拉取镜像结束==============='
echo '============ THE END ==============='

脚本注释,解释的已经很清楚了吧。
总之一句话,就是把harbor上的镜像名字拿到手,然后传给下面的脚本去执行:在此服务器上有两个文件,把这两个文件上传的k8s上去拉取镜像,并且启动镜像的过程
在这里插入图片描述

3.4 deploy_k8s.sh 内容:

#!/bin/bash
CONF_DIR="/data/kube-conf" # k8s 服务器上用于存放配置的目录
imageName=$2 # like wy/h5:2

deploymentName=$1  #添加一个-prod表示生产环境 wy-h5-prod
imageName=$2 # like wy/h5:2
REPLICAS=$3 # like 3
NAMESPACE=$4 #like wy
YAML_NAME=$5 # file name of yaml like wy-h5-prod_deploy_k8s.yaml
SPRING_PROFILES_ACTIVE=$6
EXPOSEPORT=$7 # 7002
NODEPORT=$8 # 30003



# Pod running process
RUN=$(kubectl get po -n wy | grep -w ${deploymentName}|wc -l)
echo ${RUN}
if [ $RUN -eq 0 ];then
        echo " deploy------>"
        # apply pod service
        export deploymentName=${deploymentName}
        export imageName=${imageName}
        export REPLICAS=${REPLICAS}
        export NAMESPACE=${NAMESPACE}
        export SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}
        export EXPOSEPORT=${EXPOSEPORT}
        export NODEPORT=${NODEPORT}

        envsubst < ${CONF_DIR}/${YAML_NAME}| kubectl apply -f  -

else
        # Delete pod service
        echo " delete first----->"
        
        #传参数进yaml文件
        export deploymentName=${deploymentName}
        export imageName=${imageName}   
        export REPLICAS=${REPLICAS}
        export NAMESPACE=${NAMESPACE}
        export SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}
        export EXPOSEPORT=${EXPOSEPORT}
        export NODEPORT=${NODEPORT}

        envsubst < ${CONF_DIR}/${YAML_NAME}| kubectl delete  -f -


        echo " sleep 20s to waitting delete old pods service----->"
        sleep 20 # sleep 5 s to wait

        echo " deply second----->"
        # apply pod service
        export deploymentName=${deploymentName}
        export imageName=${imageName}   
        export REPLICAS=${REPLICAS}
        export NAMESPACE=${NAMESPACE}
        export SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE}
        export EXPOSEPORT=${EXPOSEPORT}
        export NODEPORT=${NODEPORT}


        envsubst < ${CONF_DIR}/${YAML_NAME}| kubectl apply  -f -
fi

exit

3.5 deploy_k8s.yaml内容

这个文件就是k8s执行的yaml文件,如果你对k8s一无所知,建议先去学习下。
${**}是传参过来的额,在deploy_k8s.sh中传递过来的。最初是由jenkins的脚本传递过来的。

kind: Deployment  # 一次部署
apiVersion: apps/v1 # 版本号
metadata:
  name: ${deploymentName} # 微服务服务的名字
  namespace: ${NAMESPACE} # k8s中项目的名字
  labels:
    app: ${deploymentName} # id一样,唯一标识
spec: # 规格详情
  minReadySeconds: 20
  replicas: ${REPLICAS}
  selector:
    matchLabels:
      app: ${deploymentName} #匹配的就是lab中定义的
  template:
    metadata:
      labels:
        app: ${deploymentName}
    spec:
      containers:
        - name: ${deploymentName} #容器的名字 docker run --name 后面的名字
          image: ${imageName} # harbor中获取,可能是环境变量的值
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: ${SPRING_PROFILES_ACTIVE}
          ports:
            - containerPort: ${EXPOSEPORT} # 每一个容器都是默认$servicePort启动,因为在容器内不没有问题的。
              protocol: TCP
          imagePullPolicy: IfNotPresent #Always 总是拉取,IfNotPresent如果不存在才拉取
      imagePullSecrets: # 使用密码登录
        - name: harbor-login-registry
      restartPolicy: Always # 如果镜像出问题,就自己重新启动
      terminationGracePeriodSeconds: 10 #优雅停机的秒数
  strategy:
    type: RollingUpdate #k8s滚动跟新,1.0,2.0, 保证高可用
    rollingUpdate:
      maxUnavailable: 25% # 最大不可用4 台每次关一个。
      maxSurge: 25%
---
kind: Service
apiVersion: v1
metadata:
  name: ${deploymentName}
  namespace: ${NAMESPACE}
  labels:
    app: ${deploymentName}
spec:
  ports:
    - name: http
      protocol: TCP
      port: ${EXPOSEPORT} # 暴露出来的端口,可以让客户端访问的端口
      targetPort: ${EXPOSEPORT} # 容器内部的端口,可以均设置为$servicePort
      nodePort: ${NODEPORT} # 代理的端口。 要规划好,修改K8S中NodePort方式暴露服务的端口的默认范围(30000-32767)
  selector:
    app: ${deploymentName}
  type: NodePort
  sessionAffinity: None # 无须 会话亲和

特别注意:

env:
            - name: SPRING_PROFILES_ACTIVE
              value: ${SPRING_PROFILES_ACTIVE}

设置的不同的环境,可以通过传参的方式传递过来。

4. 测试

整个开发工作完成了。但感觉还是碎片化的,我们来实战一波。

4.1 构建项目

在这里插入图片描述

4.2 选择适当的值

关于 脚本,谁负责的微服务在dev环境中打的那个版本应该很清楚,这个要沟通好,别打错了。
副本集的个数,也可以根据业务情况选择哦:
在这里插入图片描述

4.3 点击开始构建

点击开始构建就会开始

4.4 查看构建日志

在这里插入图片描述


Success控制台输出
Started by user admin
Running as SYSTEM
Building on master in workspace /data/jenkins/workspace/wy-user-prod
[wy-user-prod] $ /bin/sh -xe /tmp/jenkins2172421775510506537.sh
+ EXPOSEPORT=8310
+ NODEPORT=30021
+ echo wy/user:16
wy/user:16
+ registryUrl=10.1.8.151:8082
+ projectName=wy
+ serviceName=user
+ SPRING_PROFILES_ACTIVE=prod
+ deploymentName=wy-user-prod
+ containerName=wy-user-prod
+ imageName=10.1.8.151:8082/wy/user:16
+ echo ============通知k8s拉取镜像开始===============
============通知k8s拉取镜像开始===============
+ MASTER=10.1.33.61
+ CONF_DIR=/data/kube-conf
+ K8S_USERNAME=root
+ LOCAL_CON_DIR=/data/k8s
+ SH_NAME=deploy_k8s.sh
+ YAML_NAME=deploy_k8s.yaml
+ SH_NAME=deploy_k8s.sh
+ scp /data/k8s/deploy_k8s.yaml 10.1.33.61:/data/kube-conf
+ scp /data/k8s/deploy_k8s.sh 10.1.33.61:/data/kube-conf
+ echo '+x----->'
+x----->
+ ssh -p 22 root@10.1.33.61 chmod +x /data/kube-conf/deploy_k8s.sh
+ echo 'sh----->'
sh----->
+ ssh -p 22 root@10.1.33.61 sh /data/kube-conf/deploy_k8s.sh wy-user-prod 10.1.8.151:8082/wy/user:16 3 wy deploy_k8s.yaml prod 8310 30021
3
 delete first----->
deployment.apps "wy-user-prod" deleted
service "wy-user-prod" deleted
 sleep 20s to waitting delete old pods service----->
 deply second----->
deployment.apps/wy-user-prod created
service/wy-user-prod created
+ echo ============通知k8s拉取镜像结束===============
============通知k8s拉取镜像结束===============
+ echo '============ THE END ==============='
============ THE END ===============
Finished: SUCCESS

提示构建完成。

4.5 去k8s看下是否完成了发布

在这里插入图片描述
发布完成。
同理我们可以吧我们其他的微服务也创建一个items,做一些配置,做各自的发版工作,最后的结果如下:在这里插入图片描述
整个部署就完成了。

5 总结,流程解释

5.1 说明

  1. 各个微服务使用的部署脚本deploy_k8s.sh deploy_k8s.yaml是一模一样的,没有变化
  2. jenkins中的脚本也仅有此处不同,如果你想在优化,可以他这些也写在一个脚本中,我此处觉得挺好的,不再优化了:嘿嘿嘿~~
    在这里插入图片描述

5.2 流程说明

  1. jenkens发起构建流程
  2. 需要执行的脚本会传输到k8s服务器上
  3. 执行传输的k8s服务器上的脚本去harbor拉取镜像,使用
kubectl apply -f deploy_k8s.yaml

执行拉取镜像和启动镜像的任务。整个流程完成。

下一篇:jenkins使用自定义方式结合k8s实现ci/cd-前端代码实战https://blog.csdn.net/fsjwin/article/details/110739581

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值