CI/CD git基本操作 启动jenkins jenkins.maven 需要在gitlab上放上jenkins的公钥以便jenkins可以拉取gitlab的仓库 ! 配置全局变量 ! 配置mvn ...
CICD¶
git基本操作¶
git init //初始化
git add main.cpp //将某一个文件添加到暂存区
git add . //将文件夹下的所有的文件添加到暂存区
git commit -m ‘note‘ //将暂存区中的文件保存成为某一个版本
git log //查看所有的版本日志
git status //查看现在暂存区的状况
git diff //查看现在文件与上一个提交-commit版本的区别
git reset --hard HEAD^ //回到上一个版本
git reset --hard XXXXX //XXX为版本编号,回到某一个版本
git pull origin master //从主分支pull到本地
git push -u origin master //从本地push到主分支
git pull //pull默认主分支
git push //push默认主分支 ...
git checkout -b dev // 创建dev分支,然后切换到dev分支
git checkout // 命令加上-b参数表示创建并切换,相当于以下两条命令:
git branch dev git checkout dev
git branch // 命令查看当前分支,
git branch // 命令会列出所有分支,当前分支前面会标一个*号
git branch * dev master
git add readme.txt git commit -m "branch test" // 在dev分支上正常提交.
启动jenkins¶
jenkins.maven¶
¶
需要在gitlab上放上jenkins的公钥以便jenkins可以拉取gitlab的仓库¶

配置全局变量¶

配置mvn git jdk环境
下载mvn插件能够让job构建一个maven项目¶


执行docker远程主机命令需要下载插件Publish Over SSH¶

执行webhoob钩子需要下载插件Generic Webhook Trigger¶

需要在gitlab上配置 搭配webhook¶


pipeline¶
pipeline {
agent any
tools {
maven "mvn" ##配置mvn环境 mvn是在配置变量里面写的名字
}
stages {
stage('拉取仓库') {
steps {
git branch: 'slave', url: 'git@192.168.85.131:ceshi/test.git'
echo '拉取成功'
}
}
stage('mvn打包') {
steps {
sh '''cd /root/.jenkins/workspace/java-pipeline
mvn clean package'''
echo '打包完成'
}
}
stage('docker执行') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'docker-java', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/root', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '**/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''cd /root/root
docker stop java
docker rm -f java
docker rmi java
docker build -t java .
docker run -d --name java -p 8081:8080 java''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/root', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '**/Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo '执行成功'
}
}
}
}
基于k8s流水线¶
需要让jenkins机器能够调用api¶
gitlab的配置¶

# cat k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{PACKAGE_NAME}}
namespace: {{K8S_NAMESPACE}}
spec:
replicas: {{K8S_REPLICAS}}
selector:
matchLabels:
app: {{PACKAGE_NAME}}
template:
metadata:
labels:
app: {{PACKAGE_NAME}}
spec:
containers:
- name: {{PACKAGE_NAME}}
image: "{{IMAGE_NAME}}"
imagePullPolicy: Always
ports:
- containerPort: 8080
# cat Dockerfile
from openjdk
expose 8080
add ./target/simple-jar-project-1.0-SNAPSHOT.jar /root/
entrypoint ["java", "-jar", "/root/simple-jar-project-1.0-SNAPSHOT.jar"]
# cat Jenkinsfile
pipeline {
agent any
tools {
maven 'mvn'
}
parameters {
// GitLab 分支选择,允许用户选择需要部署的分支
string(name: 'GITLAB_BRANCH', defaultValue: 'slave', description: 'GitLab 分支名称')
// Java 包名字,允许用户自定义包名
string(name: 'PACKAGE_NAME', defaultValue: 'your-java-app', description: 'Java 包名字')
// 版本号,允许用户自定义
string(name: 'VERSION', defaultValue: '1.0.0', description: 'Java 包版本号')
// 部署类型选择,用户选择 deploy 或 update
choice(name: 'DEPLOY_TYPE', choices: ['deploy', 'update'], description: '选择部署或更新操作')
// Docker Registry,允许用户指定 Docker 镜像仓库
string(name: 'DOCKER_REGISTRY', defaultValue: '192.168.85.128', description: 'Docker 镜像仓库地址')
// Kubernetes 部署命名空间,允许用户自定义
string(name: 'K8S_NAMESPACE', defaultValue: 'default', description: 'Kubernetes 命名空间')
// Kubernetes 部署副本数,用户可以自定义
string(name: 'K8S_REPLICAS', defaultValue: '1', description: 'Kubernetes 部署副本数')
// 服务暴露端口,允许用户指定
string(name: 'SERVICE_PORT', defaultValue: '8080', description: '服务暴露端口')
// 自定义 Kubernetes 部署的其他信息,比如镜像仓库、标签等
string(name: 'K8S_DEPLOYMENT_FILE', defaultValue: 'k8s/deployment.yaml', description: 'Kubernetes 部署文件路径')
}
environment {
// 构建 Docker 镜像标签
IMAGE_NAME = "${params.DOCKER_REGISTRY}/nb/${params.PACKAGE_NAME}:${params.VERSION}"
// Kubernetes 配置文件临时路径
K8S_TEMP_FILE = "${WORKSPACE}/k8s-deployment-temp.yaml"
}
stages {
stage('检出代码') {
steps {
script {
echo "正在从 GitLab 拉取分支 ${params.GITLAB_BRANCH} 的代码..."
git branch: "${params.GITLAB_BRANCH}", url: 'git@192.168.85.131:ceshi/test.git'
}
}
}
stage('构建 Java 应用') {
steps {
script {
echo "正在构建 Java 包 ${params.PACKAGE_NAME} 版本 ${params.VERSION}..."
sh "pwd && /usr/local/apache-maven-3.8.8/bin/mvn clean package -DskipTests -DartifactId=${params.PACKAGE_NAME} -Dversion=${params.VERSION}"
}
}
}
stage('构建 Docker 镜像') {
steps {
script {
echo "正在构建 Docker 镜像 ${env.IMAGE_NAME}..."
sh "docker build -t ${env.IMAGE_NAME} ."
}
}
}
stage('推送 Docker 镜像到镜像仓库') {
steps {
script {
echo "正在将 Docker 镜像 ${env.IMAGE_NAME} 推送到 ${params.DOCKER_REGISTRY}..."
sh "docker push ${env.IMAGE_NAME}"
}
}
}
stage('生成动态 Kubernetes 部署文件') {
steps {
script {
// 替换 Kubernetes 部署模板中的变量
echo "正在生成动态的 Kubernetes 部署文件..."
// 读取 Kubernetes 部署模板
def yamlTemplate = readFile("${params.K8S_DEPLOYMENT_FILE}")
// 使用 Groovy 的字符串替换功能,替换变量
def modifiedYaml = yamlTemplate.replace("{{IMAGE_NAME}}", env.IMAGE_NAME)
.replace("{{K8S_NAMESPACE}}", params.K8S_NAMESPACE)
.replace("{{K8S_REPLICAS}}", params.K8S_REPLICAS)
.replace("{{PACKAGE_NAME}}", params.PACKAGE_NAME)
// 写入临时文件
writeFile file: env.K8S_TEMP_FILE, text: modifiedYaml
echo "生成的 Kubernetes 部署文件路径: ${env.K8S_TEMP_FILE}"
}
}
}
stage('在 Kubernetes 上部署或更新') {
steps {
script {
echo "正在执行 Kubernetes 部署或更新..."
// 根据部署类型选择执行的操作
if (params.DEPLOY_TYPE == 'deploy') {
echo "正在将 ${params.PACKAGE_NAME} 版本 ${params.VERSION} 部署到 Kubernetes 命名空间 ${params.K8S_NAMESPACE}..."
// 执行 Kubernetes 部署,使用自定义的副本数和命名空间
sh """
kubectl apply -f ${env.K8S_TEMP_FILE} \
--namespace=${params.K8S_NAMESPACE}
"""
} else if (params.DEPLOY_TYPE == 'update') {
echo "正在更新 Kubernetes 中的 ${params.PACKAGE_NAME} 版本 ${params.VERSION}..."
// 更新 Kubernetes 部署镜像
// 更新副本数
sh """
# kubectl set image deployment/${params.PACKAGE_NAME} \
# ${params.PACKAGE_NAME}=${env.IMAGE_NAME} \
# --namespace=${params.K8S_NAMESPACE} --record \
# && \
# kubectl scale deployment ${params.PACKAGE_NAME} \
# --replicas=${params.K8S_REPLICAS} \
# --namespace=${params.K8S_NAMESPACE} --record 这样是分别记录 但是会有两个吧N本
kubectl apply -f ${env.K8S_TEMP_FILE} --namespace=${params.K8S_NAMESPACE}
"""
} else {
error "未知的部署类型: ${params.DEPLOY_TYPE}"
}
}
}
}
stage('创建 Kubernetes Service') {
steps {
script {
echo "正在创建 Kubernetes 服务 ${params.PACKAGE_NAME}..."
// 创建 Kubernetes 服务,将容器端口暴露出来
if (params.DEPLOY_TYPE == 'deploy') {
sh """
kubectl expose deployment ${params.PACKAGE_NAME} \
--type=NodePort \
--name=${params.PACKAGE_NAME}-svc \
--port=${params.SERVICE_PORT} \
--target-port=8080 \
--namespace=${params.K8S_NAMESPACE}
"""
}
}
}
}
}
post {
success {
echo "流水线执行成功!"
}
failure {
echo "流水线执行失败!"
}
}
}
测试¶
1.在gitlab修改java代码¶

2.在jenkins构建¶


就是把变量赋值到gitlab 的 k8s/deployment.yaml下 然后 写入到jenkins机器上 writeFile file: env.K8S_TEMP_FILE, text: modifiedYaml
3.构建¶

有红的也不用慌 控制台有报错原因 找找原因即可
再看下k8s机器 pod有两个容器因为里面我注入了sidecar

