草庐IT

使用jenkins流水线完成自动部署服务到K8s

凌霜傲雪归来 2023-08-07 原文

说明

通过本文章,您可以轻松入门cicd过程。本地测试环境为springboot微服务项目。用户提交代码到gitlab,触发jenkins拉取gitllab上的代码,然后完成编译构建成jar包,同步完成sonarsqube代码质量检测。然后在jenkins内部完成生成镜像,并将镜像推送到harbor仓库中,然后通过K8s完成服务的部署。

依赖环境部署

环境准备

使用环境说明

使用的虚拟机环境centos7.9,使用vmware安装

同步主机时区为亚洲,并同步时间

[root@linux-node ~]# echo "ZONE=Asia/Shanghai" >> /etc/sysconfig/clock         
[root@linux-node ~]# rm -f /etc/localtime
#链接到上海时区文件       
[root@linux-node ~]# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

关闭防火墙和selinux

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost ~]# setenforce 0
[root@localhost ~]# sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

设置yum源

wget -O /etc/yum.repos.d/CentOS-Base.repo  http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo  http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache

安装docker

linux安装docker

创建数据目录将数据持久话到该目录下,以便后期好维护

mkdir -p /data

安装maven

linux安装maven

gitlab安装部署

docker安装gitlab

harbor安装部署

docker安装harbor

jenkins安装部署

docker安装jenkins

sonarqube部署

docker安装sonarsqube

k8s部署

部署过程略

创建java工程并测试将代码上传到gitlab仓库

gitlab上创建项目

创建springboot工程,并将代码提交到hello-test工程下

idea创建springboot项目

编写Jenkinsfile的方式

流水线语法

我们在编写jenkins流水线脚本时可以先将框架写好,然后再补齐内容。

pipeline {
    //指定任务在哪个集群节点上执行
    agent any
	//声明环境变量,方便后面使用
	environment {
	    key='value'
	
	}
		
    stages {
        stage('拉取git仓库代码') {
            steps {
                echo '拉取git仓库代码-SUCCESS'
            }
        }
		stage('通过maven构建项目') {
            steps {
                echo '通过maven构建项目-SUCCESS'
            }
        }
		stage('通过sonarqube做代码质量检测') {
            steps {
                echo '代码质量检测-SUCCESS'
            }
        }
		stage('通过docker制作自定义镜像') {
            steps {
                echo 'docker制作自定义镜像-SUCCESS'
            }
        }
		stage('将自定义镜像推送到harbor仓库中') {
            steps {
                echo '推送到harbor仓库-SUCCESS'
            }
        }
		stage('通过publish  over  ssh通知目标服务器') {
            steps {
                echo '通知目标服务器-SUCCESS'
            }
        }
    }
}

生成jenkins 流水线脚本

点击下方的流水线语法
例如:我要从git上下载代码

下面填好之后

点击生成流水线脚本

把生成的脚本粘贴到对应的步骤下

这样就完成了流水线代码的生成。
可以在对应的stage处查看对应步骤的日志。

使用git维护Jenkinsfile文件

在gitlab一个项目中创建Jenkinsfile,可以在一个单独的项目中,也可放到对应项目中
在项目目录下创建Jenkinsfile文件,名称必须是这样的。J为大写的。
将内容放到该文件中

点击commit changes
这样工程根目录下就多了个Jenkinsfile文件,我们就可以在gitlab上去维护该文件了。

jenkins上配置使用gitlab上的Jenkinsfile

构建后发现多了该步骤

jenkins全局配置

管理Jenkins中点击

配置maven

手动配置:
主机上安装maven后将maven的安装目录移动到jenkins数据卷中

重命名文件夹

在页面上配置,MAVEN_HOME要使用容器内部目录,不要使用宿主机目录

配置jdk


页面配置jdk

使用 jenkins流水线完成cicd

新建任务,选择流水线

git下载代码到本地


下面填好之后

点击生成流水线脚本

把生成的脚本粘贴到对应的步骤下

通过maven构建项目

使用sh:shell script步骤

将生成的脚本粘贴到gitlab Jenkinsfile对应的步骤下

通过sonarqube做代码质量检测

通过docker制作自定义镜像

配置使得jenkins内部具有构建镜像能力 docker in docker配置

修改/var/run/docker.sock权限,使其属于root组,并且其他用户有读和写的权限

修改jenkins数据数据卷,jenkins内部要有执行docker命令的能力,需要将下面文件挂载到容器内部。

Jenkins docker-compose.yml文件

version: '3.1'
services:
  jenkins:
    image: jenkins/jenkins:2.319.1-lts
    container_name: jenkins
    ports:
      - 8090:8080
      - 8091:50000
    volumes:
      - /data/jenkins_home/:/var/jenkins_home/
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker
      - /etc/docker/daemon.json:/etc/docker/daemon.json

由于之前使用docker run方式启动的jenkins,此时需要删除掉容器,不要删除之前创建的数据卷就可以,然后使用docker-compose方式启动,此时不会删除数据,以后推荐改成docker-compose方式,这样运维人员也知道你的启动时加了哪些参数了,易于维护。

docker  stop jenkins
docker  rm  jenkins
docker-compose  up -d 


进入到容器内部,测试,发现成功。

生成构建镜像的jenkinsfile内容

将自定义镜像推送到harbor仓库中

使用K8s编排容器完成部署

准备部署的yaml文件

放到项目的根目录下,放到项目的根路径下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pipline-deployment
  namespace: dev
spec:
  replicas: 2
  selector:
    matchLabels:
      app: pipline-pod
  template:
    metadata:
      labels:
        app: pipline-pod
    spec:
      containers:
        - name: pipline
          image: 192.168.59.129:8888/hello/pipline-test:latest
          ports:
            - containerPort: 8080
---

apiVersion: v1
kind: Service
metadata:
  name: pipline-service
  namespace: dev
spec:
  selector:
    app: pipline-pod
  type: NodePort
  ports:
    - port: 30002
      targetPort: 8080

配置jenkins可以ssh连接到K8s master节点

系统配置里配置K8S主节点

将pipline.yaml文件传送到K8s-master节点上


生成代码放到Jenkinsfile文件中

查看K8s-master节点对应的目录里是否有pipline.yaml文件

在k8s-master节点上执行kubectl apply -f pipline.yaml 命令将服务部署起来

解决jenkins上执行ssh命令时需要输入密码问题

ssh无密码登录设置
docker exec -it jenkins bash
cd ~
mkdir .ssh
$ cd ~/.ssh
ssh-keygen -t rsa -C “email@example.com”
系统提示输入文件保存位置等信息,连续按三次回车即可,生成的SSH key文件的保存路径会在终端中给出:id_rsa id_rsa.pub
cat id_rsa.pub 将内容追加到k8s-master节点/root/.ssh/authorized_keys文件后面
验证
在jenkins容器内部验证,发现不用再输入密码了

配置远程执行命令


gitlab jenkinsfile增加以下步骤

测试验证,注意每次提交需要打tag,不修改pipline文件时并不会重新部署服务。

集成钉钉通知将部署结果发送到钉钉里

安装DingTalk插件

创建钉钉群,获取到webhook

创建过程略

系统配置钉钉

系统管理–系统配置

自动化ci操作

配置提交代码后jenkins自动拉取代码 (webhook配置)

需要安装gitlab插件

勾选下面当代码推送后触发构建

在gitlab上


点击下面的Add webhook后提示
不能填写本地主机的url允许本地地址构建webhook

需要在admin settings network 处勾选

重新添加
会在项目下看到webhook的地址

点击此处测试自动化构建


解决测试webhook返回403问题

解决:
在系统配置里将此处勾选去掉
系统管理 -> 系统设置 -> Enable authentication for ‘/project’ end-point

重新测试会发现jenkins已经开始自动构建了。

ps://img-blog.csdnimg.cn/09cfd85cec5944fb84c039cce83a5314.png)
解决构建过程中提交代码后然后发现没有改动的问题:

解决办法:
需要使用kubectl rollout命令重新滚动一次

 kubectl rollout restart deployment pipline-deployment -n dev

修改Jenkinsfile

自动化ci Jenkinsfile文件

pipeline {
    //指定任务在哪个集群节点上执行
    agent any
	//声明环境变量,方便后面使用
	environment {
	    harbor_user='admin'
        harbor_password='Harbor12345'
        harbor_addr='192.168.59.129:8888'
        harbor_repo='hello'
	
	}
		
    stages {
        stage('拉取git仓库代码') {
            steps {
               checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'hello-demo', url: 'http://192.168.59.129:8099/root/hello-demo.git']]])
            }
        }
    
		stage('通过maven构建项目') {
            steps {
                sh '/var/jenkins_home/maven/bin/mvn  clean package -DskipTests'
            }
        }
		stage('通过sonarqube做代码质量检测') {
		steps {
            sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner   -Dsonar.sources=./   -Dsonar.projectname=${JOB_NAME}   -Dsonar.projectKey=${JOB_NAME} -Dsonar.java.binaries=./target/  -Dsonar.login=23adbf175860533b91bd72d5795ad4f74ab81989'
     
            }
        }
		stage('通过docker制作自定义镜像') {
            steps {
               sh '''mv ./target/*.jar  ./docker/
                docker build -t  ${JOB_NAME}:latest  ./docker/'''
            }
        }
		stage('将自定义镜像推送到harbor仓库中') {
            steps {
                sh '''docker login -u ${harbor_user} -p ${harbor_password} ${harbor_addr}
                docker tag ${JOB_NAME}:latest  ${harbor_addr}/${harbor_repo}/${JOB_NAME}:latest
                docker push ${harbor_addr}/${harbor_repo}/${JOB_NAME}:latest'''
            }
        }
		stage('将pipline.yaml传送到K8s-master节点') {
            steps {
            sshPublisher(publishers: [sshPublisherDesc(configName: 'k8s', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'pipline.yaml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }
        }

        	stage('在k8s-master上执行部署命令') {
            steps {

               sh '''ssh   root@192.168.59.128   kubectl apply  -f  /root/deploy/pipline.yaml
               ssh   root@192.168.59.128    kubectl rollout restart deployment pipline-deployment -n dev'''
            }
        }

    }
	post {
	    success {
		dingtalk(
		    robot: 'jenkins-dingding',
			type: 'MARKDOWN',
			title: "success: ${JOB_NAME}",
			text: ["- 成功构建: ${JOB_NAME}! \n - 版本:latest \n - 持续时间:${currentBuild.durationString}"]
		)
				
		}
		failure {
		dingtalk(
			robot: 'jenkins-dingding',
			type: 'MARKDOWN',
			title: "success: ${JOB_NAME}",
			text: ["- 失败构建: ${JOB_NAME}! \n - 版本:latest \n - 持续时间:${currentBuild.durationString}"]
		
		)
		
		}
	
	}
	
}

有关使用jenkins流水线完成自动部署服务到K8s的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐