Files
more_dots/Jenkinsfile
T
2026-03-02 17:41:04 +08:00

255 lines
12 KiB
Groovy

pipeline {
agent any
environment {
// GitLab配置
GITLAB_URL = 'https://gitlab.xpaas.lenovo.com'
GITLAB_REPO = 'artificial-intelligence-platform/lenovo-ipc'
GITLAB_CREDENTIALS_ID = 'more_dots'
// 新镜像仓库配置 (10.128.62.130:8843)
REGISTRY_URL = '10.128.62.130:8843'
REGISTRY_CREDENTIALS_ID = 'docker-registry-130'
// 镜像配置
IMAGE_NAME = 'more_dots'
FULL_IMAGE_NAME = "${REGISTRY_URL}/${IMAGE_NAME}"
// 是否跳过构建(运行时赋值)
SKIP_BUILD = 'false'
}
parameters {
choice(name: 'DEPLOY_ENV', choices: ['dev', 'staging', 'prod'], description: '选择部署环境')
choice(name: 'TARGET_CLUSTER', choices: ['cluster1', 'cluster2', 'both'], description: '选择目标集群')
}
stages {
stage('Checkout') {
steps {
git(
url: "${GITLAB_URL}/${GITLAB_REPO}.git",
credentialsId: GITLAB_CREDENTIALS_ID,
branch: 'master'
)
script {
env.GIT_COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
env.SOURCE_TREE = sh(script: 'git rev-parse HEAD:more_dots', returnStdout: true).trim()
env.IMAGE_TAG = env.SOURCE_TREE.take(12)
echo "GIT_COMMIT: ${env.GIT_COMMIT}"
echo "SOURCE_TREE: ${env.SOURCE_TREE}"
echo "IMAGE_TAG: ${env.IMAGE_TAG}"
echo "FULL_IMAGE_NAME: ${FULL_IMAGE_NAME}:${env.IMAGE_TAG}"
}
}
}
stage('Check Code Changes') {
steps {
script {
def prev = env.GIT_PREVIOUS_SUCCESSFUL_COMMIT ?: ''
if (!prev?.trim()) {
echo "未找到上次成功构建提交,默认执行构建"
env.SKIP_BUILD = 'false'
} else {
int rc = sh(
script: "git diff --quiet ${prev} HEAD -- more_dots",
returnStatus: true
)
env.SKIP_BUILD = (rc == 0) ? 'true' : 'false'
}
echo "代码变更检查结果: SKIP_BUILD=${env.SKIP_BUILD}"
}
}
}
stage('Build Docker Image') {
when {
expression { env.SKIP_BUILD != 'true' }
}
steps {
dir('more_dots') {
sh "docker build --progress=plain -t ${IMAGE_NAME}:${env.IMAGE_TAG} ."
}
}
}
stage('Push to Registry') {
when {
expression { env.SKIP_BUILD != 'true' }
}
steps {
script {
withCredentials([usernamePassword(
credentialsId: REGISTRY_CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PASS'
)]) {
sh """
set -eux
echo "登录到镜像仓库 ${REGISTRY_URL}..."
echo "${REGISTRY_PASS}" | docker login ${REGISTRY_URL} -u ${REGISTRY_USER} --password-stdin
"""
}
sh """
set -eux
echo "打标签: ${IMAGE_NAME}:${IMAGE_TAG} -> ${FULL_IMAGE_NAME}:${IMAGE_TAG}"
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${FULL_IMAGE_NAME}:${IMAGE_TAG}
echo "推送镜像到仓库..."
docker push ${FULL_IMAGE_NAME}:${IMAGE_TAG}
echo "镜像推送完成: ${FULL_IMAGE_NAME}:${IMAGE_TAG}"
"""
}
}
}
stage('Deploy to k3s') {
steps {
dir('more_dots') {
script {
def cluster = params.TARGET_CLUSTER
def fullImageWithTag = "${FULL_IMAGE_NAME}:${env.IMAGE_TAG}"
if (cluster == 'cluster1' || cluster == 'both') {
withCredentials([
file(credentialsId: 'k3s-cluster1-config', variable: 'KUBECONFIG_CLUSTER1'),
usernamePassword(credentialsId: REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')
]) {
sh """
set -eux
# 查找kubectl路径
KUBECTL_PATH=\$(command -v kubectl 2>/dev/null || true)
if [ -z "\$KUBECTL_PATH" ]; then
for p in /usr/local/bin/kubectl /usr/bin/kubectl /bin/kubectl; do
if [ -x "\$p" ]; then
KUBECTL_PATH="\$p"
break
fi
done
fi
if [ -z "\$KUBECTL_PATH" ]; then
echo "kubectl 未找到,请检查 Jenkins 节点环境"
exit 1
fi
echo "使用kubectl路径: \$KUBECTL_PATH"
# 定义kubectl函数
k() {
sudo \$KUBECTL_PATH --kubeconfig=${KUBECONFIG_CLUSTER1} "\$@"
}
# 检查命名空间
k get namespace ${params.DEPLOY_ENV} || k create namespace ${params.DEPLOY_ENV}
# 创建imagePullSecret
k create secret docker-registry regcred-130 \\
--docker-server=${REGISTRY_URL} \\
--docker-username=${REGISTRY_USER} \\
--docker-password=${REGISTRY_PASS} \\
--namespace=${params.DEPLOY_ENV} \\
--dry-run=client -o yaml | k apply -f -
# 替换镜像并部署
sed "s|image:.*python-app.*|image: ${fullImageWithTag}|g" k8s/deployment.yaml > /tmp/deployment-${params.DEPLOY_ENV}.yaml
k apply -f /tmp/deployment-${params.DEPLOY_ENV}.yaml -n ${params.DEPLOY_ENV}
# 确保使用imagePullSecret
k patch deployment python-app -n ${params.DEPLOY_ENV} \\
-p '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"regcred-130"}]}}}}' || true
# 重启并等待
k rollout restart deployment/python-app -n ${params.DEPLOY_ENV} 2>/dev/null || true
k rollout status deployment/python-app -n ${params.DEPLOY_ENV} --timeout=300s
"""
}
}
if (cluster == 'cluster2' || cluster == 'both') {
withCredentials([
file(credentialsId: 'k3s-cluster2-config', variable: 'KUBECONFIG_CLUSTER2'),
usernamePassword(credentialsId: REGISTRY_CREDENTIALS_ID, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')
]) {
sh """
set -eux
# 查找kubectl路径
KUBECTL_PATH=\$(command -v kubectl 2>/dev/null || true)
if [ -z "\$KUBECTL_PATH" ]; then
for p in /usr/local/bin/kubectl /usr/bin/kubectl /bin/kubectl; do
if [ -x "\$p" ]; then
KUBECTL_PATH="\$p"
break
fi
done
fi
if [ -z "\$KUBECTL_PATH" ]; then
echo "kubectl 未找到,请检查 Jenkins 节点环境"
exit 1
fi
echo "使用kubectl路径: \$KUBECTL_PATH"
# 定义kubectl函数
k() {
sudo \$KUBECTL_PATH --kubeconfig=${KUBECONFIG_CLUSTER2} "\$@"
}
# 检查命名空间
k get namespace ${params.DEPLOY_ENV} || k create namespace ${params.DEPLOY_ENV}
# 创建imagePullSecret
k create secret docker-registry regcred-130 \\
--docker-server=${REGISTRY_URL} \\
--docker-username=${REGISTRY_USER} \\
--docker-password=${REGISTRY_PASS} \\
--namespace=${params.DEPLOY_ENV} \\
--dry-run=client -o yaml | k apply -f -
# 替换镜像并部署
sed "s|image:.*python-app.*|image: ${fullImageWithTag}|g" k8s/deployment.yaml > /tmp/deployment-${params.DEPLOY_ENV}.yaml
k apply -f /tmp/deployment-${params.DEPLOY_ENV}.yaml -n ${params.DEPLOY_ENV}
# 确保使用imagePullSecret
k patch deployment python-app -n ${params.DEPLOY_ENV} \\
-p '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"regcred-130"}]}}}}' || true
# 重启并等待
k rollout restart deployment/python-app -n ${params.DEPLOY_ENV} 2>/dev/null || true
k rollout status deployment/python-app -n ${params.DEPLOY_ENV} --timeout=300s
"""
}
}
}
}
}
}
}
post {
always {
script {
sh """
docker logout ${REGISTRY_URL} || true
docker rmi ${FULL_IMAGE_NAME}:${env.IMAGE_TAG} || true
"""
}
cleanWs()
echo "构建结束。镜像标签: ${env.IMAGE_TAG}"
echo "完整镜像: ${FULL_IMAGE_NAME}:${env.IMAGE_TAG}"
echo "是否跳过构建: ${env.SKIP_BUILD}"
}
failure {
echo "构建失败,请检查日志"
}
}
}