之前一直在生产环境没有使用过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
安装后重启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-系统管理-凭据管理-全局-新增凭据
如下图:
来到新建凭据界面
新建一个Secret file类型的凭据
然后去K8S管理节点,安装K8S用户,它的家目录下.kube/config这个文件下载到本地。
cat .kube/config
大概是这个样子
然后将下载下来的文件 上传到jenkins新增凭据。
完成后,他会自己生成ID。记下ID后面会使用。
四: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的都知道。可以配置结束后发邮件,发钉钉,或者流水线失败了怎么样,成功了怎么样,是否清理工作目录。等等。。。。
最后贴一张成功的图
在K8S里面POD已经跑起来了。但是由于其它服务没有配置,启动报错。
评论区