K8S + GitLab + Jenkins自动化发布项目实践(二)

K8S + GitLab + Jenkins自动化发布项目实践(二)

  • Jenkins容器化部署
    • 部署NFS PV存储
    • Jenkins部署
    • Jenkins初始化
    • 安装Jenkins插件
  • Jenkins主从架构配置
    • Kubernetes插件配置
    • 安装nerdctl工具
    • 自定义Jenkins Slave镜像
    • 测试主从架构是否正常

前置工作:已部署5节点k8s集群,并搭建了代码仓库和镜像仓库(GitLab + Harbor)。

主机名IP角色
k8s-master1192.168.124.ak8s控制平面
k8s-master2192.168.124.bk8s控制平面
k8s-master3192.168.124.ck8s控制平面
k8s-worker1192.168.124.dk8s工作节点
k8s-worker2192.168.124.ek8s工作节点
harborgit192.168.124.f代码仓库 & 镜像仓库

Jenkins容器化部署

Jenkins是一款开源的、用于自动化构建、测试和部署的CI-CD工具。

部署NFS PV存储

🔥配置参考:https://blog.csdn.net/Sebastien23/article/details/126276294

在工作节点k8s-worker1上部署NFS服务器:

[root@k8s-worker1 ~]# mkdir -p /ifs/kubernetes
[root@k8s-worker1 ~]# yum install nfs-utils -y
[root@k8s-worker1 ~]# vi /etc/exports
/ifs/kubernetes *(rw,sync,no_root_squash)

[root@k8s-worker1 ~]# systemctl start nfs
[root@k8s-worker1 ~]# systemctl enable nfs

在其他工作节点挂载NFS共享目录:

[root@k8s-worker2 ~]# mkdir -p /ifs/kubernetes
[root@k8s-worker2 ~]# yum install nfs-utils -y
[root@k8s-worker2 ~]# echo '192.168.124.d:/ifs/kubernetes  /ifs/kubernetes  nfs4  defaults  0 0' >> /etc/fstab
[root@k8s-worker2 ~]# mount -a

修改目录权限:

[root@k8s-worker1 ~]# mkdir /ifs/kubernetes/jenkins
[root@k8s-worker1 ~]# chmod -R 777 /ifs/kubernetes

定义一个nfs类型的PV资源:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-jenkins
spec:
  capacity:
    storage: 5Gi       
  accessModes:
    - ReadWriteMany     
  nfs:
    path: /ifs/kubernetes/jenkins
	server: 192.168.124.d

创建PV资源:

[root@k8s-master1 jenkins]# kubectl apply -f pv-nfs-jenkins.yml
persistentvolume/pv-nfs-jenkins created
[root@k8s-master1 jenkins]# kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs-jenkins   5Gi        RWX            Retain           Available                                   6s

Jenkins部署

通过Deployment控制器来部署Jenkins官方镜像,会对外暴露8080(Web访问端口)和50000(Slave通信端口)两个端口。Jenkins容器的数据存储默认在/var/jenkins_home目录下,需要对该目录进行PV持久化。

🚋官方镜像地址:https://hub.docker.com/r/jenkins/jenkins
🚋部署配置:https://www.jenkins.io/doc/book/installing/kubernetes/

我们使用jenkins.yml来部署Jenkins容器,通过PVC来请求PV资源,同时定义好Service访问和RBAC服务账号权限。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      name: jenkins
  template:
    metadata:
      name: jenkins
      labels:
        name: jenkins
    spec:
      serviceAccountName: jenkins
      containers:
        - name: jenkins
          image: jenkins/jenkins:lts
          ports:
            - containerPort: 8080
            - containerPort: 50000
          volumeMounts:
            - name: jenkins-home
              mountPath: /var/jenkins_home
      securityContext:
        fsGroup: 1000
      volumes:
      - name: jenkins-home
        persistentVolumeClaim:
          claimName: jenkins

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
spec:
  selector:
    name: jenkins
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 8080
      protocol: TCP
      nodePort: 30008
    - name: agent
      port: 50000
      protocol: TCP

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
- apiGroups: [""]
  resources: ["pods","events"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["secrets","events"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins
subjects:
- kind: ServiceAccount
  name: jenkins

部署Jenkins容器:

[root@k8s-master1 jenkins]# kubectl apply -f jenkins.yml
deployment.apps/jenkins created
persistentvolumeclaim/jenkins created
service/jenkins created
serviceaccount/jenkins created
role.rbac.authorization.k8s.io/jenkins created
rolebinding.rbac.authorization.k8s.io/jenkins created

部署完成后,通过查看Pod日志来获取Jenkins初始化的管理员口令:

kubectl get pods 
kubectl logs <jenkins-pod-name> 

# 也可以在宿主机的以下路径找到
cat /ifs/kubernetes/jenkins/secrets/initialAdminPassword

Jenkins初始化

通过暴露的NodePort访问Jenkins首页,我这里是http://192.168.124.a:30008

[root@k8s-master1 jenkins]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                        AGE
jenkins      NodePort    10.106.152.176   <none>        80:30008/TCP,50000:30282/TCP   22m
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP                        11d

在自定义Jenkins界面,选择插件来安装(不要安装推荐的插件),选择“无”来取消自动勾选的所有插件。

在这里插入图片描述

定义好管理员用户和实例信息后,来到Jenkins首页。

在这里插入图片描述

安装Jenkins插件

Manage Jenkins → \rightarrow System Configuration → \rightarrow Manage Plugins → \rightarrow Available plugins中分别搜索安装以下插件(install without restart):

  • Git:用于拉取代码。
  • Git Parameter:Git参数化构建。
  • Pipeline:流水线。
  • kubernetes:连接k8s动态创建Slave代理。
  • Config File Provider:存储配置文件。
  • Extended Choice Parameter:扩展选择框参数。

在这里插入图片描述

Jenkins下载插件默认服务器在国外,如果下载速度很慢,可以修改为国内源:

cd /ifs/kubernetes/jenkins/updates
sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json

然后通过浏览器重启Jenkins:

http://NodeIP:30008/restart

如果重启Jenkins Pod所在服务器后,Jenkins容器状态一直为Unknown,可以直接删除Pod,Deployment控制器会重新再创建一个新的Pod。而且由于/var/jenkins_home被挂载在NFS存储中,也不用担心丢失Jenkins数据。

[root@k8s-master1 jenkins]# kubectl get pods,deploy
NAME                            READY   STATUS              RESTARTS   AGE
pod/jenkins-5bddd99684-w9glp    0/1     Unknown             5          11h
pod/jenkins-slave-nhfbm-0xd6f   0/1     ContainerCreating   0          58m

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/jenkins   0/1     1            0           11h

[root@k8s-master1 jenkins]# kubectl delete pod/jenkins-5bddd99684-w9glp
pod "jenkins-5bddd99684-w9glp" deleted

Jenkins主从架构配置

Master(Jenkins本身)提供Web页面来让用户管理项目和Slave(从节点)。项目任务可以运行在Master本机,也可以分配到从节点运行。一个Master可以关联多个Slave。Slave节点起到了分担工作任务和隔离构建环境的作用。

当触发Jenkins任务时,Jenkins会调用Kubernetes API创建Slave Pod。Slave Pod启动后会连接Jenkins,接受任务处理。

Kubernetes插件配置

Kubernetes插件用于Jenkins在k8s集群中运行动态代理。

🌻插件介绍:https://github.com/jenkinsci/kubernetes-plugin

配置插件:Manage Jenkins → \rightarrow Manage Nodes and Clouds → \rightarrow Configure Clouds中添加Kubernetes。

点击打开Kubernetes Cloud Details,输入Kubernetes地址:

https://kubernetes.default

表示default命名空间中的kubernetes服务,并点击“连接测试”,出现Connected to Kubernetes v1.x.x即表示连接成功。

最后输入Jenkins地址并保存。

http://jenkins.default

安装nerdctl工具

Jenkins Slave工作需要用到OpenJDK、Maven、git命令、kubectl命令、以及docker build和docker push命令。由于我们的k8s集群使用的容器运行时为containerd,自带的crictl工具不支持build和push操作,因此需要安装nerdctl工具。

🐻Nerdctl官方下载地址:https://github.com/containerd/nerdctl/releases

查看containerd版本:

kubectl get nodes -o wide
#CONTAINER-RUNTIME中的版本信息为containerd://1.6.18

下载兼容的nerdctl版本,并解压到/usr/local目录下:

tar Cxzvvf /usr/local nerdctl-full-1.2.1-linux-amd64.tar.gz

启动nerdctl和buildkit服务:

nerdctl run -d --name nginx -p 80:80 nginx:alpine

# nerdctl使用buildkit服务来build镜像
systemctl enable buildkit.service --now

自定义Jenkins Slave镜像

用于构建Jenkins Slave镜像的Dockerfile如下:

FROM centos:7
LABEL maintainer kratos

RUN yum install -y java-1.8.0-openjdk maven git libtool-ltdl-devel && \
    yum clean all && \
    rm -rf /var/cache/yum/* && \
    mkdir -p /usr/share/jenkins

COPY slave.jar /usr/share/jenkins/slave.jar
COPY jenkins-slave /usr/bin/jenkins-slave
COPY settings.xml /etc/maven/settings.xml
RUN chmod +x /usr/bin/jenkins-slave
COPY kubectl /usr/bin/

ENTRYPOINT ["jenkins-slave"]

其中:

  • slave.jar为agent程序,用于接收master下发的任务。
  • jenkins-slave是用于启动slave.jar的Shell脚本。
  • settings.xml配置中需要将Maven官方源修改为阿里云源。
  • 另外还需要kubectl客户端工具。

在Dockerfile同级目录下准备好要打包进镜像的文件。

[root@k8s-master1 jenkins]# ls
Dockerfile  jenkins-slave  kubectl  settings.xml  slave.jar

构建镜像并推送到Harbor镜像仓库:

# 注意命令最后面的'.'
nerdctl build -t 192.168.124.f/library/jenkins-slave-jdk:1.8 .
nerdctl push 192.168.124.f/library/jenkins-slave-jdk:1.8

推送成功后在Harbor仓库中可以看到上传的镜像。

如果推送失败,报错类似如下:

ERRO[0000] server "192.168.124.f" does not seem to support HTTPS  error="failed to do request: ...
... dial tcp 192.168.124.f:443: connect: connection refused
... unexpected status from GET request to https://auth.docker.io/token?offline_token=true&service=registry.docker.io: 401 Unauthorized

则需要配置容器运行时的HTTP传输。如果是docker,只需要在/etc/docker/daemon.json中增加insecure-registries并配置Harbor地址,然后重启docker服务即可。Containerd则需要修改/etc/containerd/config.toml中的多项配置。

# 备份containerd配置文件
[root@k8s-master1 jenkins]# cp /etc/containerd/config.toml /etc/containerd/config.toml.bak

# 修改containerd配置文件
[root@k8s-master1 jenkins]# vi /etc/containerd/config.toml
...
      [plugins."io.containerd.grpc.v1.cri".registry.configs]
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.harborgit".tls]
          insecure_skip_verify = true     # 跳过TLS认证
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.harborgit".auth]
          username = "admin"      # 配置Harbor登陆用户和密码
          password = "XXXXXX"

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

      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.haborgit"]
          endpoint = ["http://192.168.124.f"]     # 配置Harbor访问地址
...

# 重启containerd
[root@k8s-master1 jenkins]# systemctl restart containerd

登录后重新推送即可(要加--insecure-registry):

[root@k8s-master1 jenkins]# nerdctl login http://192.168.124.f --insecure-registry
[root@k8s-master1 jenkins]# nerdctl push 192.168.124.f/library/jenkins-slave-jdk:1.8 --insecure-registry

☕️参考:https://goharbor.io/docs/2.0.0/install-config/run-installer-script/#connect-http

测试主从架构是否正常

点击New Item输入名称java-demo,选中Pipeline再点击OK确认。

在这里插入图片描述

创建完成后,在java-demo → \rightarrow Configure → \rightarrow Advanced Project Options → \rightarrow Pipeline中选择“Pipeline Script”。

将下面的测试脚本粘贴进去并保存。

pipeline {
  agent {
    kubernetes {
      label "jenkins-slave"
      yaml '''
apiVersion: v1
kind: Pod
metadata:
  name: jenkins-slave
spec:
  containers:
  - name: jnlp
    image: "192.168.124.f/library/jenkins-slave-jdk:1.8"
'''
    }
  }
  stages {
    stage('Main'){
      steps {
        sh 'hostname'
      }
    }
  }
}

保存Pipeline脚本后,在新建项目中点击Build Now,然后在Build History中查看Console Output日志,直到输出Build成功的信息。

可以通过kubectl get pods命令检查k8s集群中是否会自动创建和销毁jenkins-slave Pod。

如果Console Output中收到以下报错,不一定是服务账号权限的原因。

Failure executing: 
POST at: https://kubernetes.default/api/v1/namespaces/default/pods. 
Message: Unauthorized! Configured service account doesn't have access. 
Service account may have been revoked. Unauthorized.

具体原因我们下次进一步排查。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/3881.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux中滴计划任务

计划任务计划任务计划任务分类at命令load averagecrontab命令配置文件通常包含三个部分cron服务配置文件cron服务的日志文件时间数值的特殊表示方法应用实例案例anacron服务计划任务 计划任务&#xff08;Cron Job&#xff09;是指在预定的时间自动执行一些指定的任务或脚本。…

【蓝桥杯专题】 树状数组(C++ | 洛谷 | acwing | 蓝桥)

菜狗现在才开始备战蓝桥杯QAQ 文章目录【蓝桥杯专题】 &#xff08;C | 洛谷 | acwing | 蓝桥&#xff09;什么是线段数组??1264. 动态求连续区间和数星星线段树AcWing 1270. 数列区间最大值PPPPPPP【蓝桥杯专题】 &#xff08;C | 洛谷 | acwing | 蓝桥&#xff09; 什么是…

华为OD机试用java实现 -【最多获得的短信条数】(2023-Q1 新题)

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧本篇题解:最多获得的短信条数 题目 某…

linxu学习之进程

文章目录进程程序和进程产生进程销毁进程多进程高并发设计孤儿僵尸守护进程孤儿进程&#xff1a;守护进程(重点)僵尸进程&#xff1a;进程 程序和进程 操作系统可以运行多个程序&#xff0c;那他是如何运行的&#xff1f;实际上&#xff0c;CPU的执行是很快的&#xff0c;而待…

【FreeRTOS(一)】FreeRTOS新手入门——初识FreeRTOS

初识FreeRTOS一、实时操作系统概述1、概念2、RTOS的必要性3、RTOS与裸机的区别4、FreeRTOS的特点二、FreeRTOS的架构三、FreeRTOS的代码架构一、实时操作系统概述 1、概念 RTOS&#xff1a;根据各个任务的要求&#xff0c;进行资源&#xff08;包括存储器、外设等&#xff09…

【TypeScript入门】TypeScript入门篇——枚举(enum)

TypeScript是一种静态类型、可选的编程语言&#xff0c;它在JavaScript的基础上添加了类型检查、接口、枚举等新特性&#xff0c;可以让开发更加高效、代码更加健壮。在TypeScript中&#xff0c;枚举是一种特殊的数据类型&#xff0c;它可以用来定义一组命名的常量&#xff0c;…

网络通信之应用层协议--Linux

文章目录关于应用层协议的理解应用层协议的制定理论部分代码部分完整代码以及测试HTTP协议代码测试HTTP协议HTTPS协议加密原因基础的加密方式数据摘要&#xff08;数据指纹&#xff09;数字签名HTTPS的加密方式的选择总结关于应用层协议的理解 在之前的一篇关于套接字实现网络…

天梯赛刷题小记 —— L2

最近在重刷 天梯赛&#xff0c;浅浅记录一下&#xff0c;进入L2阶段了 L2-001 紧急救援 解题思路&#xff1a;典型的dijkstra模板题&#xff0c;带路径记录与权重&#xff0c;方案数记录&#xff0c;解析出过 Dijkstra(兼路径) #include <bits/stdc.h> #define inf…

【数据分析之道-基础知识(三)】元组

文章目录专栏导读1、元组简介2、元组创建3、元组查找操作4、元组删除操作5、元组修改操作6、元组增加操作7、元组内置函数专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN Python领域新星创作者&#xff0c;专注于分享python领域知识。 ✍ 本文录入于《数据分析之道》&…

自动驾驶控制概况

文章目录1. 第一章行为决策在自动驾驶系统架构中的位置2. 路径跟踪控制的种类2.1 基于自行车模型的路径跟踪控制算法2.1.1 纯跟踪控制&#xff08;Pure Pursuit&#xff09;算法2.1.2 后轮反馈控制算法&#xff08;Rear wheel feedback&#xff09;2.1.3前轮反馈控制算法&#…

防火墙 NAT地址转换

网络地址转换&#xff08;NAT&#xff09;是一种用于访问Internet访问模式广域网&#xff08;WAN&#xff09;的技术&#xff0c;用于将私有&#xff08;保留&#xff09;地址转换为合法IP地址。NAT不仅能够有效地额抵抗外部网络攻击&#xff0c;还能够在IP地址分配不理想&…

Windows权限提升—令牌窃取、UAC提权、进程注入等提权

Windows权限提升—令牌窃取、UNC提权、进程注入等提权1. 前言2. at本地命令提权2.1. 适用范围2.2. 命令使用2.3. 操作步骤2.3.1. 模拟提权2.3.2. at配合msf提权2.3.2.1. 生成木马文件2.3.2.2. 设置监听2.3.2.3. 设置反弹2.3.2.4. 查看反弹效果3. sc本地命令提权3.1. 适用范围3.…

瑟瑟发抖吧——用了这款软件,我的开发效率提升了50%

一、前言 开发中&#xff0c;一直听到有人讨论是否需要重复造轮子&#xff0c;我觉得有能力的人&#xff0c;轮子得造。但是往往开发周期短&#xff0c;用轮子所节省的时间去更好的理解业务&#xff0c;应用到业务中&#xff0c;也能清晰发现轮子的利弊&#xff0c;一定意义上…

Warshall算法

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;> 算法 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我…

树莓派Linux源码配置,树莓派Linux内核编译,树莓派Linux内核更换

目录 一 树莓派Linux的源码配置 ① 内核源码下载说明 ② 三种方法配置源码 二 树莓派Linux内核编译 ① 内核编译 ② 编译时报错及解决方案&#xff08;亲测&#xff09; 三 更换树莓派Linux内核 操作步骤说明 ● dmesg报错及解决方案&#xff08;亲测&#xff0…

算法刷题笔记

特定方法 KMP算法&#xff1a;字符串匹配 逆波兰表达式&#xff1a;计算值 斐波那契数&#xff1a;动态规划 强制类型转换&#xff1a;整型->字符串&#xff1a;to_string&#xff0c;字符串->整型&#xff1a;stoi 一、数组 数组&#xff1a;下标从0开始&#xff0c;内存…

蓝桥杯嵌入式--LCD屏幕使用提升

前言之前在专栏里已经介绍过LCD相关库文件的移植&#xff0c;今天来介绍一下对于LCD屏幕的使用技巧。屏幕基本配置与函数一、屏幕初始化使用lcd前的必要步骤就是对LCD屏幕进行初始化操作&#xff0c;这也是一个容易忘记的操作。LCD_Init();\\使用lcd前的必要步骤就是对LCD屏幕进…

蓝桥杯倒计时 | 倒计时17天

作者&#x1f575;️‍♂️&#xff1a;让机器理解语言か 专栏&#x1f387;&#xff1a;蓝桥杯倒计时冲刺 描述&#x1f3a8;&#xff1a;蓝桥杯冲刺阶段&#xff0c;一定要沉住气&#xff0c;一步一个脚印&#xff0c;胜利就在前方&#xff01; 寄语&#x1f493;&#xff1a…

将一段数字转为字符串

将一段数字转为字符串 string turn(long long x){string str;while(x){int tx%10;// 数字0的ascii码为48&#xff01;char ct48;strc;// string类拼接方式x/10;}reverse(str.begin(),str.end()); // 不要忘了反转字符串return str; }例: #include<iostream> #include&l…

使用VS Code 配置Ubuntu远程C++开发环境

使用VS Code 配置Ubuntu远程C开发环境 环境准备 VS CodeWSL Ubuntu 虚拟机 配置步骤 在Ubuntu 中配置ssh远程登录 Ubuntu 配置远程登录 VsCode 安装 Remote-ssh 插件 打开vscode ssh configure ,填入相关信息 ​ Host : 主机名称&#xff0c;在左侧列表中显示的名称 ​ …