目 录CONTENT

文章目录

jenkins部署服务到K8S

Seven
2024-06-03 / 0 评论 / 1 点赞 / 93 阅读 / 23989 字 / 正在检测是否收录...

之前一直在生产环境没有使用过K8S自动部署,现在自己研究了一下可行,但是听朋友说效率特别高,可能是我的出发点不对,感觉快不了多少。如果有懂的小伙伴可以留言,我们探讨一下。
基础环境:

计算机名 IP地址 系统
master 192.168.10.241 ubuntu 22.04
node01 192.168.10.242 ubuntu 22.04
node02 192.168.10.243 ubuntu 22.04
node03 192.168.10.244 ubuntu 22.04
jenkins 192.168.10.245 ubuntu 22.04

一、安装JENKINS

此次安装的JENKINS并不是在K8S集群里面安装
因为JENKINS有一些老环境的流水线,也不想迁移,就将就使用了。
安装教程:点击这里
我看了一下有许多教程都是在K8S集群里面安装,我也不知道在集群里安装jenkins有什么不一样的,但是我感觉像JDK多版本、MAVEN多版本,应该是不好控制。

二、kubernetes集群安装

安装教程:点击这里
此次安装的是单MASTER节点,版本是最新的1.28.2 为了测试,并未使用多管理节点。
containerd使用的是官方最新版本1.7.17
具体如下

root@master:/etc/containerd# kubectl get no -A -o wide
NAME     STATUS   ROLES           AGE    VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
master   Ready    <none>          6d     v1.28.2   192.168.10.243   <none>        Ubuntu 22.04.4 LTS   5.15.0-107-generic   containerd://1.7.17
node     Ready    control-plane   6d3h   v1.28.2   192.168.10.241   <none>        Ubuntu 22.04.4 LTS   5.15.0-107-generic   containerd://1.7.17
node01   Ready    <none>          6d3h   v1.28.2   192.168.10.242   <none>        Ubuntu 22.04.4 LTS   5.15.0-107-generic   containerd://1.7.17
node03   Ready    <none>          5d4h   v1.28.2   192.168.10.244   <none>        Ubuntu 22.04.4 LTS   5.15.0-107-generic   containerd://1.7.17

基础配置安装如下:

root@master:/etc/containerd# kubectl get po -A -o wide
NAMESPACE              NAME                                         READY   STATUS             RESTARTS       AGE     IP               NODE     NOMINATED NODE   READINESS GATES
calico-apiserver       calico-apiserver-856c975f99-9bbn2            1/1     Running            0              6d3h    10.244.167.133   node     <none>           <none>
calico-apiserver       calico-apiserver-856c975f99-thl7r            1/1     Running            0              6d3h    10.244.196.130   node01   <none>           <none>
calico-system          calico-kube-controllers-599ff9759-bfpzc      1/1     Running            0              6d3h    10.244.167.132   node     <none>           <none>
calico-system          calico-node-nxlzf                            1/1     Running            0              6d3h    192.168.10.242   node01   <none>           <none>
calico-system          calico-node-qmh69                            1/1     Running            0              5d4h    192.168.10.244   node03   <none>           <none>
calico-system          calico-node-rbxb5                            1/1     Running            0              6d      192.168.10.243   master   <none>           <none>
calico-system          calico-node-wckc4                            1/1     Running            0              6d3h    192.168.10.241   node     <none>           <none>
calico-system          calico-typha-6c5f7fc58f-989gm                1/1     Running            0              6d3h    192.168.10.242   node01   <none>           <none>
calico-system          calico-typha-6c5f7fc58f-bz58d                1/1     Running            0              6d      192.168.10.243   master   <none>           <none>
calico-system          csi-node-driver-b7hzk                        2/2     Running            0              5d4h    10.244.186.193   node03   <none>           <none>
calico-system          csi-node-driver-f669p                        2/2     Running            0              6d3h    10.244.196.129   node01   <none>           <none>
calico-system          csi-node-driver-hxjhb                        2/2     Running            0              6d      10.244.219.65    master   <none>           <none>
calico-system          csi-node-driver-rqgp5                        2/2     Running            0              6d3h    10.244.167.131   node     <none>           <none>
kube-system            coredns-66f779496c-bn56v                     1/1     Running            0              6d3h    10.244.167.129   node     <none>           <none>
kube-system            coredns-66f779496c-zdmrc                     1/1     Running            0              6d3h    10.244.167.130   node     <none>           <none>
kube-system            etcd-node                                    1/1     Running            0              6d3h    192.168.10.241   node     <none>           <none>
kube-system            kube-apiserver-node                          1/1     Running            0              6d3h    192.168.10.241   node     <none>           <none>
kube-system            kube-controller-manager-node                 1/1     Running            0              6d3h    192.168.10.241   node     <none>           <none>
kube-system            kube-proxy-bp2jd                             1/1     Running            0              6d3h    192.168.10.242   node01   <none>           <none>
kube-system            kube-proxy-gp4qk                             1/1     Running            0              6d      192.168.10.243   master   <none>           <none>
kube-system            kube-proxy-gv4f2                             1/1     Running            0              5d4h    192.168.10.244   node03   <none>           <none>
kube-system            kube-proxy-z9zzk                             1/1     Running            0              6d3h    192.168.10.241   node     <none>           <none>
kube-system            kube-scheduler-node                          1/1     Running            0              6d3h    192.168.10.241   node     <none>           <none>
kube-system            metrics-server-5647f99f9b-fqmtp              1/1     Running            0              5d19h   10.244.196.134   node01   <none>           <none>
kubernetes-dashboard   dashboard-metrics-scraper-5657497c4c-g4s9l   1/1     Running            0              5d20h   10.244.219.67    master   <none>           <none>
kubernetes-dashboard   kubernetes-dashboard-78f87ddfc-2b2fg         1/1     Running            3 (5d4h ago)   5d20h   10.244.219.66    master   <none>           <none>
pbb                    test-6555ffd6fd-xdftd                        0/1     CrashLoopBackOff   47 (40s ago)   4h11m   10.244.219.69    master   <none>           <none>
tigera-operator        tigera-operator-699bf9f4d9-klj2c             1/1     Running            3 (5d4h ago)   6d3h    192.168.10.242   node01   <none>           <none>

特别说明:其中安装了dashboard、metrics-server、网络组件calico。里面的pbb test-6555ffd6fd-xdftd 就是本次测试的服务。因为集群里面没有安装NACOS,MYSQL,MQ,等公共服务。所以跑不起来,但是不影响此次教程。
可能大家也注意到了,master节点并不是管理节点,node才是,是因为改名称的时候忘记了,但是IP地址是对的。

三、基础环境配置。

3.1 jenkins 安装插件 kubernetes

jenkins-系统管理-插件管理-Available plugins
搜索Kubernetes
image
安装后重启jenkins服务。

3.2 安装docker

很多小伙伴会问为什么不直接使用containerd呢?没有毛病,可以直接使用,但是我使用DOCKER打镜像习惯了。
安装教程:点击这里

在此注意,如果安装DOCKER之前你自己安装过了containerd,系统会提示你更换runtime,因为我的containerd版本太高,选择docker的老版本及可,只是用来构建镜像,没有什么区别。

3.3 安装kubectl 命令工具

安装这个工具是为了和k8s集群进行交互,不然jenkins服务器无法直接交互集群,当然有很多其它的方法,比如API,URL。。。等等。这个使用起来我感觉还是不错的。

3.3.1 配置阿里kubectl源
sudo apt-get install -y ca-certificates curl software-properties-common apt-transport-https curl
sudo curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
sudo tee /etc/apt/sources.list.d/kubernetes.list <<EOF 
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
sudo apt update
3.3.2 安装kubectl
sudo apt install -y kubectl

... ...
Progress: [ 60%] [######################################################....................................] 
Scanning processes...                                                                                           
Scanning candidates...                                                                                          
Scanning linux images...                                                                                        

Running kernel seems to be up-to-date.

Restarting services...
 systemctl restart cron.service irqbalance.service jenkins.service multipathd.service open-vm-tools.service packagekit.service polkit.service rsyslog.service snapd.service ssh.service systemd-journald.service systemd-networkd.service systemd-resolved.service systemd-timesyncd.service systemd-udevd.service udisks2.service upower.service vgauth.service
Service restarts being deferred:
 systemctl restart ModemManager.service
 /etc/needrestart/restart.d/dbus.service
 systemctl restart docker.service
 systemctl restart getty@tty1.service
 systemctl restart networkd-dispatcher.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

安装完后如上,它会自动重启一大堆服务。比如docker,dbus.jenkins.cron。

4、配置kubernetes config

– 这个的目的是给jenkins服务器和k8s交互的权限。
jenkins-系统管理-凭据管理-全局-新增凭据
如下图:
image-1717399173349
image-1717399207066
image-1717399240138
来到新建凭据界面
新建一个Secret file类型的凭据
然后去K8S管理节点,安装K8S用户,它的家目录下.kube/config这个文件下载到本地。

cat .kube/config

大概是这个样子
image-1717400104821
然后将下载下来的文件 上传到jenkins新增凭据。
完成后,他会自己生成ID。记下ID后面会使用。
image-1717401572394

四:containerd配置私有仓库

这个需要在K8S所有节点去配置,以确保所有节点能正常获取私有仓库镜像
之前我有单独写过一篇文章: 传送门

这里我简单说一下,打开containerd的配置文件 ,定位到registry

vim /etc/containerd/config.toml
... ... #省略前面
        [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]

    [plugins."io.containerd.grpc.v1.cri".image_decryption]
      key_model = "node"

    [plugins."io.containerd.grpc.v1.cri".registry]        #这里表示私有配置开始,下面的每一行都有自己的意义,可以通过上面的传送门去看详细,比如认证,TLS,CA认证,等等,
      config_path = ""

      [plugins."io.containerd.grpc.v1.cri".registry.auths]

      [plugins."io.containerd.grpc.v1.cri".registry.configs]

      [plugins."io.containerd.grpc.v1.cri".registry.headers]

      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]

        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] #添加了阿里去仓库,和docker官方仓库 下面是具体值。

          endpoint = ["https://fogjl973.mirror.aliyuncs.com", "https://registry-1.docker.io"]

        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.10.245:5000"]   #添加了私有仓库,下面是地址。

          endpoint = ["http://XXX.XXX.XXX.XXX:5000"]

    [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
      tls_cert_file = ""
      tls_key_file = ""

到此containerd从私有仓库拉取镜像配置结束。

五、配置jenkins流水线

先贴一个,我这里配置好的jenkins pipeline script

pipeline {
    agent any
    environment {
    //私有仓库
    HARBOR_URL = "xxx.xxx.xxx.xxx:5000"
    //HARBOR_PROJECT = "pbb"
    // 镜像标签
    IMAGE_TAG = "${BUILD_NUMBER}"
    // 镜像名称
    IMAGE_NAME = "${HARBOR_URL}/${JOB_BASE_NAME}:${IMAGE_TAG}"
    CONTAINER_PORT = 8930
    
    }

    stages {
        stage('GitPull') {
            steps {
                git branch: 'prod',credentialsId: '凭据123', url: 'http://xxx.xxx.xxx/xxx/xxx.git'

            }
        }

        stage('Package'){
            steps{
                sh 'mvn clean package -U -Dmaven.skip.test=true'
            }
        }
        
        stage('构建镜像') {
            steps {
                echo 'dockerfilecp'
                script {
                    sh "cp /var/lib/jenkins/dockerfile/Dockerfile ${WORKSPACE}"
                }
                echo 'dockerfile cp 结束'
                echo '开始构建镜像'
                script {
                    sh "sudo docker build --build-arg JARPATH=lmkj-pbb-ry/ruoyi-gateway/target -t ${IMAGE_NAME} . "
                }
                echo '构建镜像完成'
                echo '开始推送镜像'
                script {
                    sh "sudo docker push ${IMAGE_NAME}"
                }
                echo '推送镜像完成'
                echo '开始删除镜像'
                script {
                    sh "sudo docker rmi ${IMAGE_NAME}"
                }
                echo '删除镜像完成'
            }
        }
        stage('修改资源清单'){
            steps {
                echo '开始修改资源清单'
                script {
                    sh "cp /var/lib/jenkins/k8s/deploy.yaml ${WORKSPACE}"
                }
                script{
                    withEnv ([
                        "SERVICE_NAME=${JOB_BASE_NAME}",
                        "IMAGE_NAME=${IMAGE_NAME}",
                        "CONTAINER_PORT=${CONTAINER_PORT}"
                        ]) {
                    sh """ envsubst < deploy.yaml > test.yaml"""
                    //sh "cat test.yaml"
                    }
                }   
                echo '修改资源清单完成'
            }
        }
        stage('项目部署') {
            steps {
                script {
                   withKubeConfig([credentialsId: 'c6fee21d-af1f-4a99-8ee8-a815e307aa79']){
                    echo '开始部署资源清单'
                    sh "kubectl apply -f test.yaml"
                    echo "${IMAGE_NAME}"
                    }
                }
            }
        }

    post {
        always {
            echo 'One way or another, I have finished'
           // deleteDir() /* clean up our workspace */
        }
        success {
            echo 'I succeeeded!'
        }
        unstable {
            echo 'I am unstable :/'
        }
        failure {
            echo 'I failed :('
        }
        changed {
            echo 'Things were different before...'
        }
    }

    
}

这个流水线就比较简单,一看就能明白。

首先:全局变量

所有服务都会使用的参数:

environment {
    HARBOR_URL = "xxx.xxx.xxx.xxx:5000"        #私有仓库地址,我为了方便没有使用HARBOR就是DOCKER 的 REGISTRY做的测试。
    HARBOR_PROJECT = "pbb"	                       #如果使用HARBOR,可以把这个项目名称加上。
    // 镜像标签
    IMAGE_TAG = "${BUILD_NUMBER}"            #镜像的版本号,直接使用了JENKINS的构建ID
    // 镜像名称
    IMAGE_NAME = "${HARBOR_URL}/${JOB_BASE_NAME}:${IMAGE_TAG}"    #镜像名
    //容器端口
    CONTAINER_PORT = 8930                       #容器使用端口。
    }

然后:拉代码打包

        stage('GitPull') {
            steps {
                git branch: 'prod',credentialsId: '凭据123', url: 'http://xxx.xxx.xxx/xxx/xxx.git'

            }
        }

        stage('Package'){
            steps{
                sh 'mvn clean package -U -Dmaven.skip.test=true'
            }
        }

继续:构建镜像推到私有仓库

stage('构建镜像') {
            steps {
                echo 'dockerfilecp'
                script {
                    sh "cp /var/lib/jenkins/dockerfile/Dockerfile ${WORKSPACE}"
                }
                echo 'dockerfile cp 结束'
                echo '开始构建镜像'
                script {
                    sh "sudo docker build --build-arg JARPATH=lmkj-pbb-ry/ruoyi-gateway/target -t ${IMAGE_NAME} . " #最后面的“.”不要忘了。
                }
                echo '构建镜像完成'
                echo '开始推送镜像'
                script {
                    sh "sudo docker push ${IMAGE_NAME}"
                }
                echo '推送镜像完成'
                echo '开始删除镜像'
                script {
                    sh "sudo docker rmi ${IMAGE_NAME}"
                }
                echo '删除镜像完成'
            }
        }

这里涉及到一个dockerfile文件。
我将原文件贴到这里:

FROM freshworks/oraclejdk8:latest    #初始镜像
MAINTAINER seven  #维护者
ARG JARPATH #新增一个变量,用来接收--build-arg传进来的路径。
ENV JAVA_OPTS="-server -Xms256m -Xmx256m -Xmn128m -Dspring.profiles.active=test -Dserver.connection-timeout=60000  -Dserver.tomcat.accept-count=100  -Dserver.tomcat.max-threads=300" JARPATH=${JARPATH} #变量赋值
COPY ./$JARPATH/*.jar /opt/server/bootstrap.jar #将jar包放到镜像里面,注意这里的JAR包位置,只支持相对路径,不支持绝对路径,这里小坑了一把。
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone #配置时区
WORKDIR /opt/server #配置工作目录
CMD ["/bin/sh","-c","java -jar $JAVA_OPTS /opt/server/bootstrap.jar"] #启动命令

到这里镜像部分结束。

再来:更新配置清单

其实就是更新k8s部署的YAML文件。

        stage('修改资源清单'){
            steps {
                echo '开始修改资源清单'
                script {
                    sh "cp /var/lib/jenkins/k8s/deploy.yaml ${WORKSPACE}"
                }
                script{
                    withEnv ([
                        "SERVICE_NAME=${JOB_BASE_NAME}",
                        "IMAGE_NAME=${IMAGE_NAME}",
                        "CONTAINER_PORT=${CONTAINER_PORT}"
                        ]) {
                    sh """ envsubst < deploy.yaml > test.yaml"""
                    //sh "cat test.yaml"
                    }
                }   
                echo '修改资源清单完成'
            }
        }

其中,withEnv就是对变量进行赋值,然后使用envsubst传到YAML文件里面,并且输出来新的文件test.yaml。涉及到主要的几个:
1、服务名称
2、镜像名称
3、服务端口
当然,你可以根据你的项目需求来配置。
withEnv是JENKINS自带的工具,envsubst是SHELL里面变量占位符工具。
下面我将涉及到的YAML文件贴出来:

deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
 name: ${SERVICE_NAME}
 namespace: pbb  #我这里定义了命名空间,需要在集群里先给他建好。
spec:
 selector:
   matchLabels:
     app: ${SERVICE_NAME}
 template:
   metadata:
     labels:
       app: ${SERVICE_NAME}
   spec:
     containers:
     - name: ${SERVICE_NAME}
       image: ${IMAGE_NAME}
       ports:
       - containerPort: ${CONTAINER_PORT}
       resources:
         requests:
           memory: "512Mi"
           cpu: "500m"
         limits:
           memory: "1024Mi"
           cpu: "1000m"

在流水线里我屏蔽了一条//sh “cat test.yaml” 这个主要是调试的时候排错用的。自己调试的时候 可以取消屏蔽,检查一下生成的YAML文件是否正确。

最后:部署

        stage('项目部署') {
            steps {
                script {
                   withKubeConfig([credentialsId: 'c6fee21d-af1f-4a99-8ee8-a815e307aa79']){
                    echo '开始部署资源清单'
                    sh "kubectl apply -f test.yaml"
                    echo "${IMAGE_NAME}"
                    }
                }
            }

这步就是我们安装的kubernetes插件的功能。
withKubeConfig可以去jenkins官方看一下使用方法。官方地址点这里
credentialsId这个后面跟的就是上传.kube/config文件后,生成的凭据ID
下面的-- sh “kubectl apply -f test.yaml” 就不用解释了

部署完成

后面的 post {} 了解jenkins的都知道。可以配置结束后发邮件,发钉钉,或者流水线失败了怎么样,成功了怎么样,是否清理工作目录。等等。。。。

最后贴一张成功的图

image-1717410805158

在K8S里面POD已经跑起来了。但是由于其它服务没有配置,启动报错。

1

评论区