在Google Kubernetes集群创建分布式Jenkins(一)

news2024/11/8 13:56:10

因为项目需要,在GKE的集群上需要创建一个CICD的环境,记录一下安装部署一个分布式Jenkins集群的过程。

分布式Jenkins由一个主服务器和多个Agent组成,Agent可以执行主服务器分派的任务。如下图所示:

如上图,Jenkins Agent可以运行不同的操作系统,执行主服务器分派的编译打包或测试等任务。

在Jenkins的官网上介绍了在K8S上安装的几种方式,包括了Helm, operator等。但是我直接用Helm最新版的Jenkins安装始终遇到问题,日志报错信息是Google的OAUTH插件编译有问题,如果用旧版本的可以安装成功,但是我不想用旧的版本,而新版本的问题暂时没找到解决的思路,另外Helm安装的values配置过于繁杂。我考虑用最传统的Yaml manifest的方式来部署这个Jenkins。

创建Jenkin主服务器

首先是创建namespace的manifest,配置如下:

apiVersion: v1
kind: Namespace
metadata:
  name: "jenkins"
  labels:
    name: "jenkins"

定义Storage class的manifest

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storage-jenkins
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  fstype: ext4
volumeBindingMode: WaitForFirstConsumer

定义PVC,保存Jenkins的相关数据

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: jenkins-pvc 
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: "storage-jenkins" 
  resources:
    requests:
      storage: 30Gi 

然后就是创建一个deployment,部署Jenkins pod

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  selector:
    matchLabels:
      app: jenkins
  replicas: 1
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      volumes:
        - name: pvc-jenkins 
          persistentVolumeClaim:
            claimName: jenkins-pvc 
      containers:
      - name: jenkins
        image: "jenkins/jenkins:lts"
        securityContext:
          runAsUser: 0
        volumeMounts:
          - mountPath: "/var/jenkins_home/"
            name: pvc-jenkins 
        ports:
        - containerPort: 8080
        - containerPort: 50000 
        resources:
          limits:
            cpu: "2"
            memory: "4Gi"
          requests:
            cpu: "1"
            memory: "2Gi"
        livenessProbe:
          httpGet:
            path: "/login"
            port: 8080
          initialDelaySeconds: 90
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: "/login"
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3

创建一个service来暴露Jenkins的地址和端口,注意这里加了GCP的neg注解,使得可以使用ingress来暴露

apiVersion: v1
kind: Service
metadata:
  name: jenkins-svc
  namespace: jenkins
  annotations:
   cloud.google.com/neg: '{"ingress": true}'
  labels:
    app: jenkins
spec:
  ports:
  - name: jenkinsport
    port: 8080
    targetPort: 8080
  - name: slaveconnectors
    port: 50000
    targetPort: 50000
  selector:
    app: jenkins

再创建一个ingress,使得可以从公网访问

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins-ingress
  namespace: jenkins
spec:
  rules:
      - http:
         paths:
            - path: /*
              pathType: ImplementationSpecific
              backend:
                 service:
                     name: jenkins-svc
                     port:
                       number: 8080

最后创建一个kustomization.yaml,把以上部分组合起来

resources:
  - namespace.yaml
  - storage-class.yaml
  - pvc.yaml
  - deployment.yaml
  - service.yaml
  - ingress.yaml

然后运行命令kubectl apply -k kustomization_dir/即可部署。等待ingress创建完成后,在gcp console的网页上找到相应的地址,我们还需要在Firewall里面增加一条规则,放开ingress相应的端口,然后在浏览器上访问即可进入jenkins的配置页面。

初次访问配置页面,需要输入admin password,这个可以从Jenkins pod的日志查到。

kubectl logs <jenkins_pod_name> -n jenkins

之后我们可以安装建议的插件,然后创建一个Jenkins的用户

安装Jenkins动态Agent

有了主服务器之后,我们就可以配置动态Agent了。以下是Jenkins创建动态Agent的流程图

  1. 当触发Jenkins任务的时候,Jenkins kubernetes插件会给K8S服务器发起一个API调用,创建一个Agent pod.
  2. 这个Jenkins agent pod会运行在K8S上来运行Jenkins任务,当任务完成时会自动中止。
  3. 当Jenkins agent pod启动时,会读取环境变量配置并和Jenkins主服务器通过JNLP的方式沟通。

安装Jenkins kubernetes插件

在Jenkins的Manage Jenkins页面,选择Plugin,搜索Kubernetes并安装。安装完成后重启Jenkins

1. 连接Kubernetes

在Jenkins的Manage Jenkins->Clouds->New Cloud,类型选择Kubernetes.

然后在配置项里面,Kubernetes url和Kubernetes server certificate key都不用输入,因为我们的Jenkins master server是在同一个Kubernetes里面。Namespace输入jenkins。点击Test Connection,如果正常就会显示连接成功。

2. 配置Jenkins URL

输入Jenkins service的internal DNS的名称,即http://jenkins-svc.jenkins.svc.cluster.local:8080

3. 创建Pod和Container template

Pod label key设置为jenkins,value设置为slave。Pod template name输入jenkins-slave,namespace输入Jenkins,labels输入slave。Containers里面先不加container template,Jenkins默认是用Jenkins/inbound-agent这个镜像

然后需要Add volume detail,因为我们的Jenkins agent是docker in docker,所以需要选择Host path volume,然后把kubernetes节点的docker daemon socket mount到Jenkins agent pod. 在Host path和mount path分别输入/var/run/docker.sock

4. 配置Service Account

因为Jenkins agent pod需要权限来调用GCP的服务,例如推送image到repository等。需要创建一个service account来给agent使用。

首先在K8S的jenkins namespace创建一个service account

kubectl create serviceaccount jenkins-sa --namespace jenkins

在GCP IAM里面创建一个service account

gcloud iam service-accounts create jenkins-sa --project=PROJECT_ID

给这个service account赋予需要的role,可以用以下命令

gcloud projects add-iam-policy-binding PROJECT_ID --member "serviceAccount:jenkins-sa@PROJECT_ID.iam.gserviceaccount.com" --role "ROLE_NAME"

把这两个service account绑定起来,使得K8S的service account可以模仿GCP的service account

gcloud iam service-accounts add-iam-policy-binding jenkins-
sa@PROJECT_ID.iam.gserviceaccount.com --role roles/iam.workloadIdentityUser --member
"serviceAccount:PROJECT_ID.svc.id.goog[jenkins/jenkins-sa]"

Annotate K8S的service account,加上email地址

kubectl annotate serviceaccount jenkins-sa --namespace jenkins
iam.gke.io/gcp-service-account=jenkins-sa@PROJECT_ID-
v1.iam.gserviceaccount.com

最后还要把Run as user id设为0,使得jenkins agent pod以root用户来运行,以避免权限问题。最后Save即可完成配置。

运行Jenkins CICD pipeline

现在可以构建一个CICD pipeline了。下图是构建CICD的一个流程图

这里面包括了几个步骤

  1. 往Git仓库提交代码,通过hook触发jenkins任务
  2. Jenkins启动agent pod,运行打包任务
  3. 把打包的镜像推送到registry
  4. 更新部署的manifest,更新镜像的标签
  5. 把应用部署到GKE

我这里将扩展一下这些步骤,增加Jenkin和Github webhook的集成,使得用户提交PR的时候自动触发UT检查,然后当用户执行merge操作的时候来触发打包任务。因为篇幅所限,我将在下一篇博客中记录具体的操作过程。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据毕业设计选题推荐-系统运行情况监控系统-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

openGauss学习笔记-112 openGauss 数据库管理-管理用户及权限-行级访问控制

文章目录 openGauss学习笔记-112 openGauss 数据库管理-管理用户及权限-行级访问控制 openGauss学习笔记-112 openGauss 数据库管理-管理用户及权限-行级访问控制 行级访问控制特性将数据库访问控制精确到数据表行级别&#xff0c;使数据库达到行级访问控制的能力。不同用户执…

Github 自动化部署到腾讯云服务器

1.准备工作 新建仓库 新建项目 推送到远程仓库 2.配置仓库密钥 点击 Settings -> Sectets and variables -> Actions -> New repository sectet 依次添加以下变量 Name&#xff1a;SERVER_HOST / Secret&#xff1a;服务器公网IP Name&#xff1a;SERVER_USERNAME /…

软件测试/测试开发丨Python:易学、强大、多用途的编程语言

点此获取更多相关资料 Python 发展历史 Python 是一门高级编程语言&#xff0c;由 Guido van Rossum&#xff08;龟叔&#xff09; 在 1989 年发明&#xff0c;设计 Python 语言的初衷是为了创造一种介于 C 和 shell 之间&#xff0c;简洁方便&#xff0c;易学易用&#xff0…

第十三章,枚举与泛型例题

例题1 package 例题;interface SeasonInterface{//四季接口int SPRING 1, SUMMER 2, AUTUMN 3, WINTER 4; }enum SeasonEnum{//四季枚举SPRING,SUMMER,AUTUMN,WINTER }public class 例题1 {//定义方法public static void printSeason1(int season){switch (season) {case …

MAA连不上MUMU模拟器

之前一直能正常用&#xff0c;最近突然连接不上&#xff0c;最终发现是adb版本不同造成的&#xff0c;我系统变量的adb版本如下&#xff1a; MUMU自带adb版本如下&#xff1a; 解决办法&#xff1a; 把mumu的adb复制到系统变量路径下&#xff0c;或者把adb的系统变量删除

基于OpenHarmony的启航开发板的基础操作

文章目录 前言一、前提准备二、基础操作1.hb set命令的使用2.hb build -f 命令的使用3.Hello World 案例 前言 在物联网&#xff08;IoT&#xff09;领域&#xff0c;开发板扮演着至关重要的角色&#xff0c;为开发人员提供了实验和原型设计的平台。而OpenHarmony作为一个开源…

NOR Flash基本原理

目录 1. Flash Memory中存储的信息 2. Flash操作 2.1 Read操作 2.2 Program操作 2.3 Erase操作 3 电压阈值分布 4 Block Erase 4.1 Pre-Program Phase 4.2 Erase Phase 4.3 Recovery Phase 5 Erase 中断 6 注意要点 这是之前搞Flash IP时的一个学习笔记&#xff0c…

力扣 搜索旋转排序数组 二分

&#x1f468;‍&#x1f3eb; 33. 搜索旋转排序数组 class Solution {public int search(int[] nums, int target){int l 0;int r nums.length - 1;while (l < r){int m l r >> 1;//else大法&#xff0c;把无序段抛给else&#xff0c;if只处理有序段 // 需要特…

Flutter屏幕适配

文章目录 一、Flutter单位二、设备信息三、常见适配方案四、flutter_screenutil 一、Flutter单位 Flutter使用的是类似IOS中的点pt&#xff08;point&#xff09;。 iPhone6的尺寸是375x667&#xff0c;分辨率为750x1334。 iPhone6的dpr( devicePixelRatio ) 是2.0。 DPR 物…

论文 辅助笔记:t2vec train.py

1 train 1.1 加载training和validation数据 def train(args):logging.basicConfig(filenameos.path.join(args.data, "training.log"), levellogging.INFO)设置了日志的基本配置。将日志信息保存到名为 "training.log" 的文件中日志的级别被设置为 INFO&…

Vue动态树、配置请求路径、表格数据显示、实现分页、创建书本管理组件、点击菜单实现路由跳转以及系统首页配置。

目录 1. 准备工作 2. 动态树 2.1 在配置请求路径 2.2 使用动态数据构建导航菜单 2.2.1 通过接口获取数据 2.2.3 通过后台获取的数据构建菜单导航 2.2.3.1 先构建一级导航菜单 2.3 点击菜单实现路由跳转 2.3.1 创建书本管理组件 3. 系统首页配置 4. 表格数据显示 4.…

探密工业互联网网络体系:构建端到端的稳定传输

什么是工业互联网网络&#xff1f; 工业互联网网络是一种将工业设备、传感器和计算机系统连接到一起&#xff0c;以便它们可以共同工作、共享数据和实现更高效的生产和控制。这个网络体系的目标是提高工业过程的效率、可靠性和安全性。 在数字时代的今天&#xff0c;工业互联网…

无广告弹出的便签工具选择哪一款?

广告弹窗&#xff0c;是许多人在日常办公中比较反感的问题&#xff0c;打开一个软件正准备使用时&#xff0c;突然冒出一个广告弹窗&#xff0c;这会给人一种特别反感的情绪&#xff0c;尤其是在专注记录工作任务备忘的时候&#xff0c;意外冒出的广告窗口可真让人心烦。那么&a…

Apple 苹果发布 M3、M3 Pro 和 M3 Max 芯片

本心、输入输出、结果 文章目录 Apple 苹果发布 M3、M3 Pro 和 M3 Max 芯片前言M3、M3 Pro 和 M3 Max 芯片的性能相关资料图M3 Pro规格M3 Max规格弘扬爱国精神 Apple 苹果发布 M3、M3 Pro 和 M3 Max 芯片 编辑&#xff1a;简简单单 Online zuozuo 地址&#xff1a;https://blog…

若依框架中SpringSecurity的实现流程

文章目录 Spring Security概述核心原理 若依Sprint Security分析配置类分析流程分析图过滤器分析 若依登录/退出流程流程图登录退出 写在开头: 本篇博客与核桃共同完成 Spring Security 概述 Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架&#xff0c…

go微信开发sdk-简单使用_已设置图床

go微信开发sdk-简单使用 GitHub - silenceper/wechat: WeChat SDK for Go &#xff08;微信SDK&#xff1a;简单、易用&#xff09; 使用的sdk为上述的&#xff0c;这边给出快速的项目实例 git clone https://github.com/gowechat/example.git简单的项目结构 这边简单用dock…

多线程锁的升级原理是什么

在 Java 中&#xff0c;锁共有 4 种状态&#xff0c;级别从低到高依次为&#xff1a;无状态锁&#xff0c;偏向锁&#xff0c;轻量级锁和重量级锁状态&#xff0c;这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。 多线程锁锁升级过程 如下图所示 多线程锁的升级过程…

数字孪生技术:城市交通的智能引领

城市交通问题一直是我们日常生活中的头等大事。交通拥堵、公共交通不便、环境污染等问题常常困扰着城市居民。然而&#xff0c;数字孪生技术正以令人兴奋的方式改变着城市交通的面貌&#xff0c;为城市交通带来了新的变化。 实时交通监测&#xff1a;数字孪生技术通过网络连接的…

动态规划:“以宇换宙”的优雅工艺

Those who do not remember the past are condemned to repeat it. 那些不能铭记历史的人注定要重蹈覆辙。 在动态规划——经典案例分析中我们提到了斐波那契数列的求解思路。知道动态规划的主要优点是能够在解决问题时避免重复计算&#xff0c;通过利用已经计算过的结果来加速…