This commit is contained in:
dxin
2025-11-13 11:59:04 +08:00
parent 1298fdd1e8
commit a7c7be8452
17 changed files with 1856 additions and 235 deletions

305
SCM/s1_flymoon_admin.groovy Normal file
View File

@@ -0,0 +1,305 @@
pipeline {
agent any
tools{
maven 'mvn3.8.8'
jdk 'jdk21'
}
parameters {
gitParameter(
branchFilter: 'origin/(.*)',
defaultValue: 'dxin',
name: 'Code_branch',
type: 'PT_BRANCH_TAG',
selectedValue: 'DEFAULT',
sortMode: 'NONE',
description: '选择代码分支: ',
quickFilterEnabled: true,
tagFilter: '*',
listSize: "1"
)
choice(
name: 'NAME_SPACES',
choices: ['sit', 'test', 'prod'],
description: '选择存放镜像的仓库命名空间:'
)
string(
name: 'CUSTOM_TAG',
defaultValue: '',
description: '可选:自定义镜像 Tag (字母、数字、点、下划线、短横线), 留空则自动生成 “ v+构建次数_分支名_短哈希_构建时间 ”'
)
booleanParam(
name: 'DEPLOY_AFTER_BUILD',
defaultValue: true,
description: '是否构建完镜像后部署?'
)
}
environment {
KUBECONFIG = credentials('k8s-test-config-admin') // k8s 凭证 ID, Jenkins 中配置的凭证名称
REGISTRY = "uswccr.ccs.tencentyun.com" // 镜像仓库地址
NAMESPACE = "lessie${params.NAME_SPACES}" // 命名空间根据choices的选择拼接
IMAGE_NAME = "flymoon-admin" // 镜像名(固定前缀)
CREDENTIALS_ID = "dxin_img_hub_auth" // 容器仓库凭证ID
Deployment_name = "s1-flymoon-admin-deployment" // 工作负载名
Pod_container_name = "s1-flymoon-admin" // pod内运行的容器名
K8s_namespace = "sit" // 这是k8s集群的命名空间
}
stages {
stage('拉取代码') {
steps {
git branch: "${params.Code_branch}", credentialsId: 'fly_gitlab_auth', url: 'http://106.53.194.199/root/fly_moon_admin.git'
}
}
stage('获取信息') {
steps {
script {
// 获取最近一次提交的哈希值短格式前8位
env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD',returnStdout: true).trim()
// 获取最近一次提交的作者
env.GIT_AUTHOR = sh(script: 'git log -1 --pretty=format:%an',returnStdout: true).trim()
// 获取最近一次提交的时间(格式化)
env.GIT_COMMIT_TIME = sh(
script: 'git log -1 --pretty=format:%ct | xargs -I {} date -d @{} +%Y%m%d-%H%M%S',
returnStdout: true
).trim()
// 获取最近一次提交的备注信息(转义特殊字符,避免构建失败)
env.GIT_COMMIT_MSG = sh(script: 'git log -1 --pretty=format:%s | sed -e \'s/"/\\"/g\'', returnStdout: true).trim()
// Jenkins构建次数
def buildNumber = env.BUILD_NUMBER // Jenkins内置变量直接获取当前Job的构建序号
// 当前分支名(处理/为-如feature/docker_1015 → feature-docker_1015
def branchName = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
def formattedBranch = branchName.replace('/', '-').replace('_', '-') // 替换分支名中的/和_为-
// 构建时间格式202510181215年-月-日-时-分,无分隔符)
def buildTime = sh(script: 'date +%Y%m%d%H%M', returnStdout: true).trim()
def defaultTag = "v${buildNumber}_${formattedBranch}_${GIT_COMMIT_SHORT}_${buildTime}"
def customTag = params.CUSTOM_TAG?.trim()
def tagPattern = ~/^[a-zA-Z0-9._-]+$/
// 判断最终Tag
if (customTag && customTag ==~ tagPattern) {
echo "✅ 使用自定义镜像 Tag: ${customTag}"
env.IMAGE_TAG = customTag
} else if (customTag) {
echo "⚠️ 自定义 Tag '${customTag}' 不符合规范,将使用默认生成的 Tag: ${defaultTag}"
def confirmed = true
timeout(time: 1, unit: 'MINUTES') {
try {
input(
message: """⚠️ Tag 命名不规范:
${customTag}
将使用自动生成的 Tag
${defaultTag}
是否继续构建?""",
ok: '确认'
)
} catch (err) {
// 用户点击“取消”或中断
echo "🚫 用户取消构建"
confirmed = false
}
}
if (confirmed) {
echo "✅ 用户确认使用自动生成的 Tag${defaultTag}"
env.IMAGE_TAG = defaultTag
} else {
error("流水线已终止。")
}
} else {
env.IMAGE_TAG = defaultTag
echo "未输入自定义 Tag, 使用自动生成规则: ${env.IMAGE_TAG}"
}
}
}
}
stage('Maven 编译') {
steps {
sh "cd ${WORKSPACE}/ && mvn clean install -Dmaven.test.skip=true"
}
}
stage('登录容器仓库') {
steps {
withCredentials([usernamePassword(
credentialsId: env.CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PWD'
)]) {
sh '''
echo "$REGISTRY_PWD" | docker login ${REGISTRY} -u ${REGISTRY_USER} --password-stdin
'''
}
}
}
stage('构建容器镜像') {
steps {
script {
// 构建镜像,添加标签信息
sh """
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} \
--label "git-branch='${params.Code_branch}'" \
--label "git-commit='${GIT_COMMIT_SHORT}'" \
--label "git-author='${GIT_AUTHOR}'" \
--label "git-message='${GIT_COMMIT_MSG}'" \
--label "build-time='${GIT_COMMIT_TIME}'" \
.
"""
}
}
}
stage('推送镜像到仓库') {
steps {
script {
// 推送主镜像(带唯一 Tag
sh "docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "推送镜像成功:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
}
}
}
stage('部署到K8S') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
sh """
echo "=== 更新 Deployment 镜像 ==="
kubectl set image deployment/${Deployment_name} ${Pod_container_name}=${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} -n ${K8s_namespace}
echo "=== 添加注解 ==="
kubectl annotate deployment/${Deployment_name} kubernetes.io/change-cause="${GIT_COMMIT_MSG}" --overwrite -n ${K8s_namespace}
echo "=== 查看历史版本 ==="
kubectl rollout history deployment/${Deployment_name} -n ${K8s_namespace}
echo "=== 查看所使用的镜像 ==="
kubectl get deployment ${Deployment_name} -n ${K8s_namespace} -o=jsonpath='{.spec.template.spec.containers[*].image}'
"""
}
}
stage('检查部署情况') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
echo "检测部署状态并验证新版本运行情况"
sh """
echo "=== 检查 Deployment 滚动更新状态 ==="
kubectl rollout status deployment/${Deployment_name} -n ${K8s_namespace} --timeout=180s
if [ \$? -ne 0 ]; then
echo "❌ 部署超时或失败,开始收集诊断信息..."
echo "=== 查看当前 Pods 状态 ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 查看最近的事件 ==="
kubectl get events -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp | tail -n 20
echo "=== 查看最近一个失败 Pod 的详细描述 ==="
FAILED_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --field-selector=status.phase!=Running -o jsonpath='{.items[0].metadata.name}')
if [ ! -z "\$FAILED_POD" ]; then
kubectl describe pod \$FAILED_POD -n ${K8s_namespace} || true
kubectl logs \$FAILED_POD -n ${K8s_namespace} --tail=50 || true
fi
echo "=== 回滚到上一个版本 ==="
kubectl rollout undo deployment/${Deployment_name} -n ${K8s_namespace}
exit 1
fi
echo "=== 检查 Pods 是否全部 Ready ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 获取最新 Pod 名称 ==="
NEW_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')
echo "=== 新 Pod 启动日志(最近20行) ==="
kubectl logs \$NEW_POD -n ${K8s_namespace} --tail=20 || true
echo "✅ 部署成功:\$NEW_POD 已正常运行"
"""
}
}
}
post {
always {
script {
def keepCount = 2
echo "开始清理本地旧镜像,仅保留最近 ${keepCount} 个构建版本"
def imagePrefix = "${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}"
// 获取所有镜像(按创建时间排序,越新的越前)
// 格式Repository:Tag ImageID CreatedAt
def allImagesRaw = sh(script: "docker images ${imagePrefix} --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.CreatedAt}}' | sort -rk3", returnStdout: true).trim()
if (!allImagesRaw) {
echo "未找到任何镜像,无需清理"
return
}
def allImages = allImagesRaw.split('\n')
if (allImages.size() <= keepCount) {
echo "当前镜像数未超过 ${keepCount} 个,无需清理"
return
}
def oldImages = allImages.drop(keepCount)
echo "发现 ${oldImages.size()} 个旧镜像需要清理"
oldImages.each { line ->
echo " ${line}"
}
oldImages.each { line ->
def parts = line.split(' ')
def imageTag = parts[0]
def imageId = parts.size() > 1 ? parts[1] : ""
// 对于标签为<none>的无效镜像使用镜像ID删除
if (imageTag.contains("<none>") && imageId) {
echo "删除无效镜像: ${imageId}"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else if (imageId) {
// 对于有标签的有效镜像优先使用镜像ID删除
echo "删除旧镜像: ${imageTag} (${imageId})"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else {
// 兜底方案,使用标签删除
echo "删除旧镜像: ${imageTag}"
sh(returnStatus: true, script: "docker rmi -f ${imageTag} || true")
}
}
echo "清理完成,当前镜像状态:"
sh """
docker images ${imagePrefix} --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.CreatedAt}}\\t{{.Size}}'
"""
sh "docker logout ${REGISTRY}"
echo "容器仓库已登出,本地凭证已清理"
}
}
success {
// 输出构建结果
echo "成功!"
echo "镜像地址:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "对应代码提交:${GIT_COMMIT_SHORT}${GIT_COMMIT_MSG}"
}
failure {
// 输出构建结果
echo "有步骤失败,请检查!"
}
}
}

303
SCM/s1_flymoon_agent.groovy Normal file
View File

@@ -0,0 +1,303 @@
pipeline {
agent any
tools{
maven 'mvn3.8.8'
jdk 'jdk21'
}
parameters {
gitParameter(
branchFilter: 'origin/(.*)',
defaultValue: 'dxin',
name: 'Code_branch',
type: 'PT_BRANCH_TAG',
selectedValue: 'DEFAULT',
sortMode: 'NONE',
description: '选择代码分支: ',
quickFilterEnabled: true,
tagFilter: '*',
listSize: "1"
)
choice(
name: 'NAME_SPACES',
choices: ['sit', 'test', 'prod'],
description: '选择存放镜像的仓库命名空间:'
)
string(
name: 'CUSTOM_TAG',
defaultValue: '',
description: '可选:自定义镜像 Tag (字母、数字、点、下划线、短横线), 留空则自动生成 “ v+构建次数_分支名_短哈希_构建时间 ”'
)
booleanParam(
name: 'DEPLOY_AFTER_BUILD',
defaultValue: true,
description: '是否构建完镜像后部署?'
)
}
environment {
KUBECONFIG = credentials('k8s-test-config-admin') // k8s 凭证 ID, Jenkins 中配置的凭证名称
REGISTRY = "uswccr.ccs.tencentyun.com" // 镜像仓库地址
NAMESPACE = "lessie${params.NAME_SPACES}" // 命名空间根据choices的选择拼接
IMAGE_NAME = "flymoon-agent" // 镜像名(固定前缀)
CREDENTIALS_ID = "dxin_img_hub_auth" // 容器仓库凭证ID
Deployment_name = "s1-flymoon-agent-deployment" // 工作负载名
Pod_container_name = "s1-flymoon-agent" // pod内运行的容器名
K8s_namespace = "sit" // 这是k8s集群的命名空间
}
stages {
stage('拉取代码') {
steps {
git branch: "${params.Code_branch}",
credentialsId: 'fly_gitlab_auth',
url: 'http://106.53.194.199/root/fly_moon_agent.git'
}
}
stage('获取信息') {
steps {
script {
// 获取最近一次提交的哈希值短格式前8位
env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD',returnStdout: true).trim()
// 获取最近一次提交的作者
env.GIT_AUTHOR = sh(script: 'git log -1 --pretty=format:%an',returnStdout: true).trim()
// 获取最近一次提交的时间(格式化)
env.GIT_COMMIT_TIME = sh(
script: 'git log -1 --pretty=format:%ct | xargs -I {} date -d @{} +%Y%m%d-%H%M%S',
returnStdout: true
).trim()
// 获取最近一次提交的备注信息(转义特殊字符,避免构建失败)
env.GIT_COMMIT_MSG = sh(script: 'git log -1 --pretty=format:%s | sed -e \'s/"/\\"/g\'', returnStdout: true).trim()
// Jenkins构建次数
def buildNumber = env.BUILD_NUMBER // Jenkins内置变量直接获取当前Job的构建序号
// 当前分支名(处理/为-如feature/docker_1015 → feature-docker_1015
def branchName = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
def formattedBranch = branchName.replace('/', '-').replace('_', '-') // 替换分支名中的/和_为-
// 构建时间格式202510181215年-月-日-时-分,无分隔符)
def buildTime = sh(script: 'date +%Y%m%d%H%M', returnStdout: true).trim()
def defaultTag = "v${buildNumber}_${formattedBranch}_${GIT_COMMIT_SHORT}_${buildTime}"
def customTag = params.CUSTOM_TAG?.trim()
def tagPattern = ~/^[a-zA-Z0-9._-]+$/
// 判断最终Tag
if (customTag && customTag ==~ tagPattern) {
echo "✅ 使用自定义镜像 Tag: ${customTag}"
env.IMAGE_TAG = customTag
} else if (customTag) {
echo "⚠️ 自定义 Tag '${customTag}' 不符合规范,将使用默认生成的 Tag: ${defaultTag}"
def confirmed = true
timeout(time: 1, unit: 'MINUTES') {
try {
input(
message: """⚠️ Tag 命名不规范:
${customTag}
将使用自动生成的 Tag
${defaultTag}
是否继续构建?""",
ok: '确认'
)
} catch (err) {
// 用户点击“取消”或中断
echo "🚫 用户取消构建"
confirmed = false
}
}
if (confirmed) {
echo "✅ 用户确认使用自动生成的 Tag${defaultTag}"
env.IMAGE_TAG = defaultTag
} else {
error("流水线已终止。")
}
} else {
env.IMAGE_TAG = defaultTag
echo "未输入自定义 Tag, 使用自动生成规则: ${env.IMAGE_TAG}"
}
}
}
}
stage('Maven 编译') {
steps {
sh "cd ${WORKSPACE}/ && mvn clean install -Dmaven.test.skip=true"
}
}
stage('登录容器仓库') {
steps {
withCredentials([usernamePassword(
credentialsId: env.CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PWD'
)]) {
sh '''
echo "$REGISTRY_PWD" | docker login ${REGISTRY} -u ${REGISTRY_USER} --password-stdin
'''
}
}
}
stage('构建容器镜像') {
steps {
script {
// 构建镜像,添加标签信息
sh """
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} \
--label "git-branch='${params.Code_branch}'" \
--label "git-commit='${GIT_COMMIT_SHORT}'" \
--label "git-author='${GIT_AUTHOR}'" \
--label "git-message='${GIT_COMMIT_MSG}'" \
--label "build-time='${GIT_COMMIT_TIME}'" \
.
"""
}
}
}
stage('推送镜像到仓库') {
steps {
script {
sh "docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "推送镜像成功:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
}
}
}
stage('部署到K8S') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
sh """
echo "=== 更新 Deployment 镜像 ==="
kubectl set image deployment/${Deployment_name} ${Pod_container_name}=${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} -n ${K8s_namespace}
echo "=== 添加注解 ==="
kubectl annotate deployment/${Deployment_name} kubernetes.io/change-cause="${GIT_COMMIT_MSG}" --overwrite -n ${K8s_namespace}
echo "=== 查看历史版本 ==="
kubectl rollout history deployment/${Deployment_name} -n ${K8s_namespace}
echo "=== 查看所使用的镜像 ==="
kubectl get deployment ${Deployment_name} -n ${K8s_namespace} -o=jsonpath='{.spec.template.spec.containers[*].image}'
"""
}
}
stage('检查部署情况') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
echo "检测部署状态并验证新版本运行情况"
sh """
echo "=== 检查 Deployment 滚动更新状态 ==="
kubectl rollout status deployment/${Deployment_name} -n ${K8s_namespace} --timeout=180s
if [ \$? -ne 0 ]; then
echo "❌ 部署超时或失败,开始收集诊断信息..."
echo "=== 查看当前 Pods 状态 ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 查看最近的事件 ==="
kubectl get events -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp | tail -n 20
echo "=== 查看最近一个失败 Pod 的详细描述 ==="
FAILED_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --field-selector=status.phase!=Running -o jsonpath='{.items[0].metadata.name}')
if [ ! -z "\$FAILED_POD" ]; then
kubectl describe pod \$FAILED_POD -n ${K8s_namespace} || true
kubectl logs \$FAILED_POD -n ${K8s_namespace} --tail=50 || true
fi
echo "=== 回滚到上一个版本 ==="
kubectl rollout undo deployment/${Deployment_name} -n ${K8s_namespace}
exit 1
fi
echo "=== 检查 Pods 是否全部 Ready ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 获取最新 Pod 名称 ==="
NEW_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')
echo "=== 新 Pod 启动日志(最近20行) ==="
kubectl logs \$NEW_POD -n ${K8s_namespace} --tail=20 || true
echo "✅ 部署成功:\$NEW_POD 已正常运行"
"""
}
}
}
post {
always {
script {
def keepCount = 2
echo "开始清理本地旧镜像,仅保留最近 ${keepCount} 个构建版本"
def imagePrefix = "${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}"
// 获取所有镜像(按创建时间排序,越新的越前)
// 格式Repository:Tag ImageID CreatedAt
def allImagesRaw = sh(script: "docker images ${imagePrefix} --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.CreatedAt}}' | sort -rk3", returnStdout: true).trim()
if (!allImagesRaw) {
echo "未找到任何镜像,无需清理"
return
}
def allImages = allImagesRaw.split('\n')
if (allImages.size() <= keepCount) {
echo "当前镜像数未超过 ${keepCount} 个,无需清理"
return
}
def oldImages = allImages.drop(keepCount)
echo "发现 ${oldImages.size()} 个旧镜像需要清理"
oldImages.each { line ->
echo " ${line}"
}
oldImages.each { line ->
def parts = line.split(' ')
def imageTag = parts[0]
def imageId = parts.size() > 1 ? parts[1] : ""
// 对于标签为<none>的无效镜像使用镜像ID删除
if (imageTag.contains("<none>") && imageId) {
echo "删除无效镜像: ${imageId}"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else if (imageId) {
// 对于有标签的有效镜像优先使用镜像ID删除
echo "删除旧镜像: ${imageTag} (${imageId})"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else {
// 兜底方案,使用标签删除
echo "删除旧镜像: ${imageTag}"
sh(returnStatus: true, script: "docker rmi -f ${imageTag} || true")
}
}
echo "清理完成,当前镜像状态:"
sh """
docker images ${imagePrefix} --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.CreatedAt}}\\t{{.Size}}'
"""
sh "docker logout ${REGISTRY}"
echo "容器仓库已登出,本地凭证已清理"
}
}
success {
// 输出构建结果
echo "镜像构建成功!"
echo "镜像地址:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "对应代码提交:${GIT_COMMIT_SHORT}${GIT_COMMIT_MSG}"
}
failure {
// 输出构建结果
echo "有步骤出错!"
}
}
}

View File

@@ -0,0 +1,301 @@
pipeline {
agent any
tools{
maven 'mvn3.8.8'
jdk 'jdk21'
}
parameters {
gitParameter(
branchFilter: 'origin/(.*)',
defaultValue: 'dxin',
name: 'Code_branch',
type: 'PT_BRANCH_TAG',
selectedValue: 'DEFAULT',
sortMode: 'NONE',
description: '选择代码分支: ',
quickFilterEnabled: true,
tagFilter: '*',
listSize: "1"
)
choice(
name: 'NAME_SPACES',
choices: ['sit', 'test', 'prod'],
description: '选择存放镜像的仓库命名空间:'
)
string(
name: 'CUSTOM_TAG',
defaultValue: '',
description: '可选:自定义镜像 Tag (字母、数字、点、下划线、短横线), 留空则自动生成 “ v+构建次数_分支名_短哈希_构建时间 ”'
)
booleanParam(
name: 'DEPLOY_AFTER_BUILD',
defaultValue: true,
description: '是否构建完镜像后部署?'
)
}
environment {
KUBECONFIG = credentials('k8s-test-config-admin') // k8s 凭证 ID, Jenkins 中配置的凭证名称
REGISTRY = "uswccr.ccs.tencentyun.com" // 镜像仓库地址
NAMESPACE = "lessie${params.NAME_SPACES}" // 命名空间根据choices的选择拼接
IMAGE_NAME = "flymoon-payment" // 镜像名(固定前缀)
CREDENTIALS_ID = "dxin_img_hub_auth" // 容器仓库凭证ID
Deployment_name = "s1-flymoon-payment-deployment" // 工作负载名
Pod_container_name = "s1-flymoon-payment" // pod内运行的容器名
K8s_namespace = "sit" // 这是k8s集群的命名空间
}
stages {
stage('拉取代码') {
steps {
git branch: "${params.Code_branch}", credentialsId: 'fly_gitlab_auth', url: 'http://106.53.194.199/root/fly_moon_payment.git'
}
}
stage('获取信息') {
steps {
script {
// 获取最近一次提交的哈希值短格式前8位
env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD',returnStdout: true).trim()
// 获取最近一次提交的作者
env.GIT_AUTHOR = sh(script: 'git log -1 --pretty=format:%an',returnStdout: true).trim()
// 获取最近一次提交的时间(格式化)
env.GIT_COMMIT_TIME = sh(
script: 'git log -1 --pretty=format:%ct | xargs -I {} date -d @{} +%Y%m%d-%H%M%S',
returnStdout: true
).trim()
// 获取最近一次提交的备注信息(转义特殊字符,避免构建失败)
env.GIT_COMMIT_MSG = sh(script: 'git log -1 --pretty=format:%s | sed -e \'s/"/\\"/g\'', returnStdout: true).trim()
// Jenkins构建次数
def buildNumber = env.BUILD_NUMBER // Jenkins内置变量直接获取当前Job的构建序号
// 当前分支名(处理/为-如feature/docker_1015 → feature-docker_1015
def branchName = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
def formattedBranch = branchName.replace('/', '-').replace('_', '-') // 替换分支名中的/和_为-
// 构建时间格式202510181215年-月-日-时-分,无分隔符)
def buildTime = sh(script: 'date +%Y%m%d%H%M', returnStdout: true).trim()
def defaultTag = "v${buildNumber}_${formattedBranch}_${GIT_COMMIT_SHORT}_${buildTime}"
def customTag = params.CUSTOM_TAG?.trim()
def tagPattern = ~/^[a-zA-Z0-9._-]+$/
// 最终Tag
if (customTag && customTag ==~ tagPattern) {
echo "✅ 使用自定义镜像 Tag: ${customTag}"
env.IMAGE_TAG = customTag
} else if (customTag) {
echo "⚠️ 自定义 Tag '${customTag}' 不符合规范,将使用默认生成的 Tag: ${defaultTag}"
def confirmed = true
timeout(time: 1, unit: 'MINUTES') {
try {
input(
message: """⚠️ Tag 命名不规范:
${customTag}
将使用自动生成的 Tag
${defaultTag}
是否继续构建?""",
ok: '确认'
)
} catch (err) {
// 用户点击“取消”或中断
echo "🚫 用户取消构建"
confirmed = false
}
}
if (confirmed) {
echo "✅ 用户确认使用自动生成的 Tag${defaultTag}"
env.IMAGE_TAG = defaultTag
} else {
error("流水线已终止。")
}
} else {
env.IMAGE_TAG = defaultTag
echo "未输入自定义 Tag, 使用自动生成规则: ${env.IMAGE_TAG}"
}
}
}
}
stage('Maven 编译') {
steps {
sh "cd ${WORKSPACE}/ && mvn clean install -Dmaven.test.skip=true"
}
}
stage('登录容器仓库') {
steps {
withCredentials([usernamePassword(
credentialsId: env.CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PWD'
)]) {
sh '''
echo "$REGISTRY_PWD" | docker login ${REGISTRY} -u ${REGISTRY_USER} --password-stdin
'''
}
}
}
stage('构建容器镜像') {
steps {
script {
// 构建镜像,添加标签信息
sh """
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} \
--label "git-branch='${params.Code_branch}'" \
--label "git-commit='${GIT_COMMIT_SHORT}'" \
--label "git-author='${GIT_AUTHOR}'" \
--label "git-message='${GIT_COMMIT_MSG}'" \
--label "build-time='${GIT_COMMIT_TIME}'" \
.
"""
}
}
}
stage('推送镜像到仓库') {
steps {
script {
sh "docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "推送镜像成功:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
}
}
}
stage('部署到K8S') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
sh """
echo "=== 更新 Deployment 镜像 ==="
kubectl set image deployment/${Deployment_name} ${Pod_container_name}=${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} -n ${K8s_namespace}
echo "=== 添加注解 ==="
kubectl annotate deployment/${Deployment_name} kubernetes.io/change-cause="${GIT_COMMIT_MSG}" --overwrite -n ${K8s_namespace}
echo "=== 查看历史版本 ==="
kubectl rollout history deployment/${Deployment_name} -n ${K8s_namespace}
echo "=== 查看所使用的镜像 ==="
kubectl get deployment ${Deployment_name} -n ${K8s_namespace} -o=jsonpath='{.spec.template.spec.containers[*].image}'
"""
}
}
stage('检查部署情况') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
echo "检测部署状态并验证新版本运行情况"
sh """
echo "=== 检查 Deployment 滚动更新状态 ==="
kubectl rollout status deployment/${Deployment_name} -n ${K8s_namespace} --timeout=180s
if [ \$? -ne 0 ]; then
echo "❌ 部署超时或失败,开始收集诊断信息..."
echo "=== 查看当前 Pods 状态 ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 查看最近的事件 ==="
kubectl get events -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp | tail -n 20
echo "=== 查看最近一个失败 Pod 的详细描述 ==="
FAILED_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --field-selector=status.phase!=Running -o jsonpath='{.items[0].metadata.name}')
if [ ! -z "\$FAILED_POD" ]; then
kubectl describe pod \$FAILED_POD -n ${K8s_namespace} || true
kubectl logs \$FAILED_POD -n ${K8s_namespace} --tail=50 || true
fi
echo "=== 回滚到上一个版本 ==="
kubectl rollout undo deployment/${Deployment_name} -n ${K8s_namespace}
exit 1
fi
echo "=== 检查 Pods 是否全部 Ready ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 获取最新 Pod 名称 ==="
NEW_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')
echo "=== 新 Pod 启动日志(最近20行) ==="
kubectl logs \$NEW_POD -n ${K8s_namespace} --tail=20 || true
echo "✅ 部署成功:\$NEW_POD 已正常运行"
"""
}
}
}
post {
always {
script {
def keepCount = 2
echo "开始清理本地旧镜像,仅保留最近 ${keepCount} 个构建版本"
def imagePrefix = "${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}"
// 获取所有镜像(按创建时间排序,越新的越前)
// 格式Repository:Tag ImageID CreatedAt
def allImagesRaw = sh(script: "docker images ${imagePrefix} --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.CreatedAt}}' | sort -rk3", returnStdout: true).trim()
if (!allImagesRaw) {
echo "未找到任何镜像,无需清理"
return
}
def allImages = allImagesRaw.split('\n')
if (allImages.size() <= keepCount) {
echo "当前镜像数未超过 ${keepCount} 个,无需清理"
return
}
def oldImages = allImages.drop(keepCount)
echo "发现 ${oldImages.size()} 个旧镜像需要清理"
oldImages.each { line ->
echo " ${line}"
}
oldImages.each { line ->
def parts = line.split(' ')
def imageTag = parts[0]
def imageId = parts.size() > 1 ? parts[1] : ""
// 对于标签为<none>的无效镜像使用镜像ID删除
if (imageTag.contains("<none>") && imageId) {
echo "删除无效镜像: ${imageId}"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else if (imageId) {
// 对于有标签的有效镜像优先使用镜像ID删除
echo "删除旧镜像: ${imageTag} (${imageId})"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else {
// 兜底方案,使用标签删除
echo "删除旧镜像: ${imageTag}"
sh(returnStatus: true, script: "docker rmi -f ${imageTag} || true")
}
}
echo "清理完成,当前镜像状态:"
sh """
docker images ${imagePrefix} --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.CreatedAt}}\\t{{.Size}}'
"""
sh "docker logout ${REGISTRY}"
echo "容器仓库已登出,本地凭证已清理"
}
}
success {
// 输出构建结果
echo "镜像构建成功!"
echo "镜像地址:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "对应代码提交:${GIT_COMMIT_SHORT}${GIT_COMMIT_MSG}"
}
failure {
// 输出构建结果
echo "有片段失败!"
}
}
}

View File

@@ -40,7 +40,7 @@ pipeline {
IMAGE_NAME = "go_lessie-sourcing-api" // 镜像名(固定前缀,这里是指构建后的镜像名)
CREDENTIALS_ID = "dxin_img_hub_auth" // 容器仓库凭证ID
Deployment_name = "s1-lessie-go-api-deployment" // 工作负载资源清单文件
Deployment_name = "s1-lessie-go-api-deployment" // 工作负载名
Pod_container_name = "s1-lessie-go-api" // pod内运行的容器名
K8s_namespace = "sit" // 这是k8s集群的命名空间

314
SCM/s1_lessie_ai_web.groovy Normal file
View File

@@ -0,0 +1,314 @@
pipeline {
agent any
parameters {
gitParameter(
branchFilter: 'origin/(.*)',
defaultValue: 'dxin',
name: 'Code_branch',
type: 'PT_BRANCH_TAG',
selectedValue: 'DEFAULT',
sortMode: 'NONE',
description: '选择代码分支: ',
quickFilterEnabled: true,
tagFilter: '*',
listSize: "1"
)
choice(
name: 'NAME_SPACES',
choices: ['sit', 'test', 'prod'],
description: '选择存放镜像的仓库命名空间:'
)
choice(
name: 'BUILD_ENV',
choices: ['im', 's2', 'prod'],
description: '选择构建的环境配置, 默认为 pnpm build:im 构建'
)
string(
name: 'CUSTOM_TAG',
defaultValue: '',
description: '可选:自定义镜像 Tag (字母、数字、点、下划线、短横线), 如 v0.0.1, 留空则自动生成 “ v+构建次数_分支名_短哈希_构建时间 ”'
)
booleanParam(
name: 'DEPLOY_AFTER_BUILD',
defaultValue: true,
description: '是否构建完镜像后部署?'
)
}
environment {
KUBECONFIG = credentials('k8s-test-config-admin') // k8s 凭证 ID, Jenkins 中配置的凭证名称
REGISTRY = "uswccr.ccs.tencentyun.com" // 镜像仓库地址
NAMESPACE = "lessie${params.NAME_SPACES}" // 命名空间根据choices的选择拼接
IMAGE_NAME = "lessie-ai-web" // 镜像名(固定前缀)
CREDENTIALS_ID = "dxin_img_hub_auth" // 容器仓库凭证ID
Deployment_name = "s1-lessie-ai-web-deployment" // 工作负载名
Pod_container_name = "s1-lessie-ai-web" // pod内运行的容器名
K8s_namespace = "sit" // 这是k8s集群的命名空间
}
stages {
stage('拉取代码') {
steps {
git branch: "${params.Code_branch}",
credentialsId: 'fly_gitlab_auth',
url: 'http://106.53.194.199/web/jennie.git'
}
}
stage('获取信息') {
steps {
script {
// 获取最近一次提交的哈希值短格式前8位
env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD',returnStdout: true).trim()
// 获取最近一次提交的作者
env.GIT_AUTHOR = sh(script: 'git log -1 --pretty=format:%an',returnStdout: true).trim()
// 获取最近一次提交的时间(格式化)
env.GIT_COMMIT_TIME = sh(
script: 'git log -1 --pretty=format:%ct | xargs -I {} date -d @{} +%Y%m%d-%H%M%S',
returnStdout: true
).trim()
// 获取最近一次提交的备注信息(转义特殊字符,避免构建失败)
env.GIT_COMMIT_MSG = sh(script: 'git log -1 --pretty=format:%s | sed -e \'s/"/\\"/g\'', returnStdout: true).trim()
// Jenkins构建次数
def buildNumber = env.BUILD_NUMBER // Jenkins内置变量直接获取当前Job的构建序号
// 当前分支名(处理/为-如feature/docker_1015 → feature-docker_1015
def branchName = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
def formattedBranch = branchName.replace('/', '-').replace('_', '-') // 替换分支名中的/和_为-
// 构建时间格式202510181215年-月-日-时-分,无分隔符)
def buildTime = sh(script: 'date +%Y%m%d%H%M', returnStdout: true).trim()
def defaultTag = "v${buildNumber}_${formattedBranch}_${GIT_COMMIT_SHORT}_${buildTime}"
def customTag = params.CUSTOM_TAG?.trim()
def tagPattern = ~/^[a-zA-Z0-9._-]+$/
// 判断最终Tag
if (customTag && customTag ==~ tagPattern) {
echo "✅ 使用自定义镜像 Tag: ${customTag}"
env.IMAGE_TAG = customTag
} else if (customTag) {
echo "⚠️ 自定义 Tag '${customTag}' 不符合规范,将使用默认生成的 Tag: ${defaultTag}"
def confirmed = true
timeout(time: 1, unit: 'MINUTES') {
try {
input(
message: """⚠️ Tag 命名不规范:
${customTag}
将使用自动生成的 Tag
${defaultTag}
是否继续构建?""",
ok: '确认'
)
} catch (err) {
// 用户点击“取消”或中断
echo "🚫 用户取消构建"
confirmed = false
}
}
if (confirmed) {
echo "✅ 用户确认使用自动生成的 Tag${defaultTag}"
env.IMAGE_TAG = defaultTag
} else {
error("流水线已终止。")
}
} else {
env.IMAGE_TAG = defaultTag
echo "未输入自定义 Tag, 使用自动生成规则: ${env.IMAGE_TAG}"
}
}
}
}
stage('pnpm i&b') {
steps {
script {
def buildEnv = params.BUILD_ENV // 获取参数
sh """
export PATH="/data/nvm/versions/node/v20.15.0/bin:$PATH"
echo "开始安装依赖包"
cd ${WORKSPACE}/ && rm -rf node_modules && pnpm install
echo "开始构建"
pnpm build:${buildEnv}
mv dist/main/index.html dist/
chmod -R 755 dist/
"""
}
}
}
stage('登录容器仓库') {
steps {
withCredentials([usernamePassword(
credentialsId: env.CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PWD'
)]) {
sh '''
echo "$REGISTRY_PWD" | docker login ${REGISTRY} -u ${REGISTRY_USER} --password-stdin
'''
}
}
}
stage('构建容器镜像') {
steps {
script {
// 构建镜像,添加标签信息
sh """
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} \
--label "git-branch='${params.Code_branch}'" \
--label "git-commit='${GIT_COMMIT_SHORT}'" \
--label "git-author='${GIT_AUTHOR}'" \
--label "git-message='${GIT_COMMIT_MSG}'" \
--label "build-time='${GIT_COMMIT_TIME}'" \
.
"""
}
}
}
stage('推送镜像到仓库') {
steps {
script {
sh "docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "推送镜像成功:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
}
}
}
stage('部署到K8S') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
sh """
echo "=== 更新 Deployment 镜像 ==="
kubectl set image deployment/${Deployment_name} ${Pod_container_name}=${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} -n ${K8s_namespace}
echo "=== 添加注解 ==="
kubectl annotate deployment/${Deployment_name} kubernetes.io/change-cause="${GIT_COMMIT_MSG}" --overwrite -n ${K8s_namespace}
echo "=== 查看历史版本 ==="
kubectl rollout history deployment/${Deployment_name} -n ${K8s_namespace}
echo "=== 查看所使用的镜像 ==="
kubectl get deployment ${Deployment_name} -n ${K8s_namespace} -o=jsonpath='{.spec.template.spec.containers[*].image}'
"""
}
}
stage('检查部署情况') {
when {
expression { return params.DEPLOY_AFTER_BUILD }
}
steps {
echo "检测部署状态并验证新版本运行情况"
sh """
echo "=== 检查 Deployment 滚动更新状态 ==="
kubectl rollout status deployment/${Deployment_name} -n ${K8s_namespace} --timeout=180s
if [ \$? -ne 0 ]; then
echo "❌ 部署超时或失败,开始收集诊断信息..."
echo "=== 查看当前 Pods 状态 ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 查看最近的事件 ==="
kubectl get events -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp | tail -n 20
echo "=== 查看最近一个失败 Pod 的详细描述 ==="
FAILED_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --field-selector=status.phase!=Running -o jsonpath='{.items[0].metadata.name}')
if [ ! -z "\$FAILED_POD" ]; then
kubectl describe pod \$FAILED_POD -n ${K8s_namespace} || true
kubectl logs \$FAILED_POD -n ${K8s_namespace} --tail=50 || true
fi
echo "=== 回滚到上一个版本 ==="
kubectl rollout undo deployment/${Deployment_name} -n ${K8s_namespace}
exit 1
fi
echo "=== 检查 Pods 是否全部 Ready ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
echo "=== 获取最新 Pod 名称 ==="
NEW_POD=\$(kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')
echo "=== 新 Pod 启动日志(最近20行) ==="
kubectl logs \$NEW_POD -n ${K8s_namespace} --tail=20 || true
echo "✅ 部署成功:\$NEW_POD 已正常运行"
"""
}
}
}
post {
always {
script {
def keepCount = 2
echo "开始清理本地旧镜像,仅保留最近 ${keepCount} 个构建版本"
def imagePrefix = "${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}"
// 获取所有镜像(按创建时间排序,越新的越前)
// 格式Repository:Tag ImageID CreatedAt
def allImagesRaw = sh(script: "docker images ${imagePrefix} --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.CreatedAt}}' | sort -rk3", returnStdout: true).trim()
if (!allImagesRaw) {
echo "未找到任何镜像,无需清理"
return
}
def allImages = allImagesRaw.split('\n')
if (allImages.size() <= keepCount) {
echo "当前镜像数未超过 ${keepCount} 个,无需清理"
return
}
def oldImages = allImages.drop(keepCount)
echo "发现 ${oldImages.size()} 个旧镜像需要清理"
oldImages.each { line ->
echo " ${line}"
}
oldImages.each { line ->
def parts = line.split(' ')
def imageTag = parts[0]
def imageId = parts.size() > 1 ? parts[1] : ""
// 对于标签为<none>的无效镜像使用镜像ID删除
if (imageTag.contains("<none>") && imageId) {
echo "删除无效镜像: ${imageId}"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else if (imageId) {
// 对于有标签的有效镜像优先使用镜像ID删除
echo "删除旧镜像: ${imageTag} (${imageId})"
sh(returnStatus: true, script: "docker rmi -f ${imageId} || true")
} else {
// 兜底方案,使用标签删除
echo "删除旧镜像: ${imageTag}"
sh(returnStatus: true, script: "docker rmi -f ${imageTag} || true")
}
}
echo "清理完成,当前镜像状态:"
sh """
docker images ${imagePrefix} --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.CreatedAt}}\\t{{.Size}}'
"""
sh "docker logout ${REGISTRY}"
echo "容器仓库已登出,本地凭证已清理"
}
}
success {
// 输出构建结果
echo "镜像构建成功!"
echo "镜像地址:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "对应代码提交:${GIT_COMMIT_SHORT}${GIT_COMMIT_MSG}"
}
failure {
// 输出构建结果
echo "部署有错误,请检查!"
}
}
}

View File

@@ -175,10 +175,13 @@ pipeline {
steps {
echo "检测部署状态并验证新版本运行情况"
sh """
set +e
echo "=== 检查 Deployment 滚动更新状态 ==="
kubectl rollout status deployment/${Deployment_name} -n ${K8s_namespace} --timeout=180s
ROLLOUT_RESULT=\$?
if [ \$? -ne 0 ]; then
if [ \$ROLLOUT_RESULT -ne 0 ]; then
echo "❌ 部署超时或失败,开始收集诊断信息..."
echo "=== 查看当前 Pods 状态 ==="
kubectl get pods -l app=${Pod_container_name} -n ${K8s_namespace} -o wide
@@ -272,7 +275,7 @@ pipeline {
}
success {
// 输出构建结果
echo "镜像构建成功!"
echo "部署成功!"
echo "镜像地址:${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}"
echo "对应代码提交:${GIT_COMMIT_SHORT}${GIT_COMMIT_MSG}"
}

View File

@@ -1,7 +1,24 @@
map $msec $sample_200 {
default 0;
"~00$" 1; # 每 200 次大约打印 1 次
}
map $http_user_agent $loggable {
default 1;
"clb-healthcheck" $sample_200;
}
log_format custom_main '$remote_addr - $remote_user [$time_local+0800] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" rt=$request_time ua="$upstream_addr" '
'us="$upstream_status" ut="$upstream_response_time"';
server {
listen 80;
server_name _;
access_log /var/log/nginx/access.log custom_main if=$loggable;
# 前端静态文件
location / {
root /usr/share/nginx/html;
@@ -9,6 +26,7 @@ server {
try_files $uri $uri/ /index.html;
}
# 精确匹配 index.html禁用缓存
location = /index.html {
root /usr/share/nginx/html;

View File

@@ -0,0 +1,44 @@
apiVersion: cloud.tencent.com/v1alpha1
kind: TkeServiceConfig
metadata:
name: jetty-ingress-config
namespace: sit
spec:
loadBalancer:
l7Listeners:
- protocol: HTTP
port: 80
snatEnable: false # 监听器透传客户端源 IP非 snat 白名单用户,请勿声明该字段)。当 snatEnable 为 true 时,关闭透传客户端源 IP 选项。当 snatEnable 为 false 时,打开透传客户端源 IP 选项。当设置 keepaliveEnable 为 1 时snatEnable 不能为 false。
domains:
- domain: "" # domain为空表示使用VIP作为域名
rules:
- url: "/health"
forwardType: HTTP # 指定后端协议为 HTTP目前支持 HTTP/HTTPS/GRPC。
healthCheck:
enable: false
- protocol: HTTPS
port: 443
defaultServer: "sample.tencent.com" # 默认域名
keepaliveEnable: 1 # 监听器开启长连接(非 keepalive 白名单用户,请勿声明该字段)
domains:
- domain: "sample.tencent.com"
http2: true # 启用 HTTP 2.0
rules:
- url: "/"
forwardType: HTTPS # 指定后端协议为 HTTPS目前支持 HTTP/HTTPS/GRPC。
session:
enable: true
sessionExpireTime: 3600
healthCheck:
enable: true
intervalTime: 10 # intervalTime 要大于 timeout否则会出错
timeout: 5 # timeout 要小于 intervalTime否则会出错
healthNum: 2
unHealthNum: 2
httpCheckPath: "/checkHealth"
httpCheckDomain: "sample.tencent.com" #注意:健康检查必须使用固定域名进行探测,如果您在.spec.loadBalancer.l7Listeners.protocol.domains.domain 里填写的是泛域名,一定要使用 httpCheckDomain 字段明确具体需要健康检查的域名,否则泛域名不支持健康检查。
httpCheckMethod: HEAD
httpCode: 31 # 可选值1~31默认 31。 1 表示探测后返回值 1xx 代表健康2 表示返回 2xx 代表健康4 表示返回 3xx 代表健康8 表示返回 4xx 代表健康16 表示返回 5xx 代表健康。若希望多种返回码都可代表健康,则将相应的值相加。
sourceIpType: 0 # 可选值0或1设定健康检查源ip。0 表示负载均衡VIP1 表示 100.64.0.0/10 网段ip。对于域名化clb默认值为1且只能为1对于非域名化的clb默认值不一定可在clb控制台配置页面看能否看到VIP探测方式如能看到默认值为0否则为1更多详情查看 https://cloud.tencent.com/document/product/214/86666。
checkType: "HTTPS" # 可选值HTTPHTTPSTCP 或 GRPC默认 HTTP。2024.06之后新建的集群支持改字段,存量集群如有需要可提工单升级后台组件来支持。当 forwardType 为 HTTPS 时checkType 只能为 TCP 或 HTTPS。当 forwardType 为 GRPC 时checkType 只能为 TCP 或 GRPC。
scheduler: WRR # 可选值WRR、LEAST_CONN、IP_HASH

View File

@@ -2,7 +2,7 @@ apiVersion: v1
kind: Pod
metadata:
name: network-test-pod
namespace: lessie-sit
namespace: sit
labels:
app: network-test
spec:
@@ -25,7 +25,7 @@ apiVersion: v1
kind: Service
metadata:
name: network-test-pod-svc
namespace: test-lessie
namespace: sit
labels:
app: network-test
spec:

View File

@@ -5,7 +5,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: s1-flymoon-admin-deployment
namespace: test-lessie
namespace: sit
labels:
app: s1-flymoon-admin
environment: s1
@@ -38,7 +38,7 @@ spec:
type: DirectoryOrCreate
containers:
- name: s1-flymoon-admin # 容器名称
image: uswccr.ccs.tencentyun.com/lessiesit/flymoon-admin:v0.0.1 # 容器镜像
image: uswccr.ccs.tencentyun.com/lessiesit/flymoon-admin:v1_dxin_467169b_202511101605 # 容器镜像
imagePullPolicy: Always # 镜像拉取策略 拉
env:
- name: POD_NAME
@@ -60,25 +60,48 @@ spec:
- name: flymoon-admin-logs-volume
mountPath: /app/logs/
subPathExpr: flymoon-admin-log-$(POD_NAME)
startupProbe: # 启动探针,用于判断容器是否已启动完成
httpGet:
path: /sit-api/health
port: 8080
initialDelaySeconds: 10 #容器启动后等待多少秒才开始第一次探测
periodSeconds: 10 # 启动探测的间隔秒数,每隔多少秒执行一次探测
failureThreshold: 30
readinessProbe: # 就绪探针,用于判断容器是否已准备好接收流量
httpGet:
path: /sit-api/health
port: 8080
initialDelaySeconds: 20 # 就绪探测在容器启动后等待多少秒才开始第一次探测(避免应用启动未完成即被判为不就绪)
periodSeconds: 10 # 就绪探测的间隔秒数,每隔多少秒执行一次探测
timeoutSeconds: 5 # 单次就绪探测的超时时间(秒),超过则该次探测视为失败
failureThreshold: 3 # 连续失败多少次后认为就绪探测失败Pod 不再被视为就绪)
livenessProbe: # 存活探针,用于判断容器是否仍然健康,失败会触发重启
httpGet:
path: /sit-api/health
port: 8080
initialDelaySeconds: 10 # 存活探测在容器启动后等待多少秒才开始第一次探测
periodSeconds: 30 # 存活探测的间隔秒数
timeoutSeconds: 5 # 单次存活探测的超时时间(秒)
failureThreshold: 3 # 连续失败多少次后认为容器不健康并触发重启
---
# ----------------------------
# Service
# 集群内部http://s1-flymoon-admin-svc.s1-lessie.svc.cluster.local:8080
# 集群外部http://<Node-IP>:30808
# 集群内部http://s1-flymoon-admin-svc.sit.svc.cluster.local:8080
# ----------------------------
apiVersion: v1
kind: Service
metadata:
name: s1-flymoon-admin-svc
namespace: test-lessie
namespace: sit
labels:
app: s1-flymoon-admin
environment: s1
project: flymoon
spec:
type: NodePort
type: ClusterIP
selector: # 必须匹配 Deployment 的 labels 才能关联 Pod
app: s1-flymoon-admin
environment: s1
@@ -87,5 +110,4 @@ spec:
- name: http
port: 8080 # ClusterIP 内部端口
targetPort: 8080 # 容器端口
nodePort: 30808 # 节点对外端口(30000-32767)

View File

@@ -4,18 +4,18 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-flymoon-agent-deployment
namespace: test-lessie
name: s1-flymoon-agent-deployment
namespace: sit
labels:
app: test-flymoon-agent
environment: test
app: s1-flymoon-agent
environment: s1
project: flymoon
spec:
replicas: 1
selector:
matchLabels:
app: test-flymoon-agent
environment: test
app: s1-flymoon-agent
environment: s1
project: flymoon
strategy:
type: RollingUpdate # 滚动更新策略
@@ -25,8 +25,8 @@ spec:
template:
metadata:
labels:
app: test-flymoon-agent
environment: test
app: s1-flymoon-agent
environment: s1
project: flymoon
spec:
imagePullSecrets:
@@ -37,8 +37,8 @@ spec:
path: /data/logs/flymoon-agent/
type: DirectoryOrCreate
containers:
- name: test-flymoon-agent # 容器名称
image: uswccr.ccs.tencentyun.com/lessietest/flymoon-agent:v0.0.5 # 容器镜像
- name: s1-flymoon-agent # 容器名称
image: uswccr.ccs.tencentyun.com/lessiesit/flymoon-agent:v0.0.5 # 容器镜像
imagePullPolicy: Always # 镜像拉取策略,拉
env:
- name: POD_NAME
@@ -55,37 +55,52 @@ spec:
memory: "1Gi" # 容器请求分配1Gi内存这会实际预留
limits:
cpu: "1" # 最多可以使用1个CPU核心
memory: "3Gi" # 容器最多可以使用3Gi内存
memory: "4Gi" # 容器最多可以使用3Gi内存
volumeMounts:
- name: flymoon-agent-logs-volume
mountPath: /app/logs/
subPathExpr: flymoon-agent-log-$(POD_NAME)
readinessProbe: # 就绪探针,用于判断容器是否已准备好接收流量
httpGet:
path: /sit-api/health
port: 8070
initialDelaySeconds: 20 # 就绪探测在容器启动后等待多少秒才开始第一次探测(避免应用启动未完成即被判为不就绪)
periodSeconds: 10 # 就绪探测的间隔秒数,每隔多少秒执行一次探测
timeoutSeconds: 5 # 单次就绪探测的超时时间(秒),超过则该次探测视为失败
failureThreshold: 3 # 连续失败多少次后认为就绪探测失败Pod 不再被视为就绪)
livenessProbe: # 存活探针,用于判断容器是否仍然健康,失败会触发重启
httpGet:
path: /sit-api/health
port: 8070
initialDelaySeconds: 10 # 存活探测在容器启动后等待多少秒才开始第一次探测
periodSeconds: 30 # 存活探测的间隔秒数
timeoutSeconds: 5 # 单次存活探测的超时时间(秒)
failureThreshold: 3 # 连续失败多少次后认为容器不健康并触发重启
---
# ----------------------------
# Service
# 集群内部http://test-flymoon-agent-svc.test-lessie.svc.cluster.local:8070
# 集群外部http://<Node-IP>:30807
# 集群内部http://s1-flymoon-agent-svc.sit.svc.cluster.local:8070
# ----------------------------
apiVersion: v1
kind: Service
metadata:
name: test-flymoon-agent-svc
namespace: test-lessie
name: s1-flymoon-agent-svc
namespace: sit
labels:
app: test-flymoon-agent
environment: test
app: s1-flymoon-agent
environment: s1
project: flymoon
spec:
type: NodePort
type: ClusterIP
selector: # 必须匹配 Deployment 的 labels 才能关联 Pod
app: test-flymoon-agent
environment: test
app: s1-flymoon-agent
environment: s1
project: flymoon
ports:
- name: http
port: 8070 # ClusterIP 内部端口
targetPort: 8070 # 容器端口
nodePort: 30807 # 节点对外端口(30000-32767)

View File

@@ -0,0 +1,113 @@
# ----------------------------
# Deployment
# ----------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: s1-flymoon-payment-deployment
namespace: sit
labels:
app: s1-flymoon-payment
environment: s1
project: flymoon
spec:
replicas: 1
selector:
matchLabels:
app: s1-flymoon-payment
environment: s1
project: flymoon
strategy:
type: RollingUpdate # 滚动更新策略
rollingUpdate:
maxSurge: 1 # 最大新增副本数
maxUnavailable: 0 # 最大不可用副本数
template:
metadata:
labels:
app: s1-flymoon-payment
environment: s1
project: flymoon
spec:
imagePullSecrets:
- name: dxin-image-repository # 镜像仓库凭证Secret
volumes:
- name: flymoon-payment-logs-volume
hostPath:
path: /data/logs/flymoon-payment/
type: DirectoryOrCreate
containers:
- name: s1-flymoon-payment # 容器名称
image: uswccr.ccs.tencentyun.com/lessiesit/flymoon-payment:v2_dxin_d408919_202511121501 # 容器镜像
imagePullPolicy: Always # 镜像拉取策略,总是拉取
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: SPRING_PROFILES_ACTIVE
value: "s1"
ports:
- containerPort: 8090 # 容器暴露的端口
resources:
requests:
cpu: "100m" # 容器请求分配0.1个CPU核心这不是实际占用但调度会以这里进行参考
memory: "1Gi" # 容器请求分配1Gi内存这会实际预留
limits:
cpu: "1" # 最多可以使用1个CPU核心
memory: "3Gi" # 容器最多可以使用3Gi内存
volumeMounts:
- name: flymoon-payment-logs-volume
mountPath: /app/logs/
subPathExpr: flymoon-payment-log-$(POD_NAME)
startupProbe: # 启动探针,用于判断容器是否已启动完成
httpGet:
path: /health
port: 8090
initialDelaySeconds: 10 #容器启动后等待多少秒才开始第一次探测
periodSeconds: 10 # 启动探测的间隔秒数,每隔多少秒执行一次探测
failureThreshold: 30
readinessProbe: # 就绪探针,用于判断容器是否已准备好接收流量
httpGet:
path: /health
port: 8090
initialDelaySeconds: 20 # 就绪探测在容器启动后等待多少秒才开始第一次探测(避免应用启动未完成即被判为不就绪)
periodSeconds: 10 # 就绪探测的间隔秒数,每隔多少秒执行一次探测
timeoutSeconds: 5 # 单次就绪探测的超时时间(秒),超过则该次探测视为失败
failureThreshold: 3 # 连续失败多少次后认为就绪探测失败Pod 不再被视为就绪)
livenessProbe: # 存活探针,用于判断容器是否仍然健康,失败会触发重启
httpGet:
path: /health
port: 8090
initialDelaySeconds: 10 # 存活探测在容器启动后等待多少秒才开始第一次探测
periodSeconds: 30 # 存活探测的间隔秒数
timeoutSeconds: 5 # 单次存活探测的超时时间(秒)
failureThreshold: 3 # 连续失败多少次后认为容器不健康并触发重启
---
# ----------------------------
# Service
# 集群内部http://s1-flymoon-payment-svc.sit.svc.cluster.local:8090
# 集群外部http://<Node-IP>:30809
# ----------------------------
apiVersion: v1
kind: Service
metadata:
name: s1-flymoon-payment-svc
namespace: sit
labels:
app: s1-flymoon-payment
environment: s1
project: flymoon
spec:
type: ClusterIP
selector: # 必须匹配 Deployment 的 labels 才能关联 Pod
app: s1-flymoon-payment
environment: s1
project: flymoon
ports:
- name: http
port: 8090 # ClusterIP 内部端口
targetPort: 8090 # 容器端口

View File

@@ -4,18 +4,18 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-lessie-ai-web-deployment
namespace: test-lessie
name: s1-lessie-ai-web-deployment
namespace: sit
labels:
app: test-lessie-ai-web
environment: test
app: s1-lessie-ai-web
environment: s1
project: lessie
spec:
replicas: 1
selector:
matchLabels:
app: test-lessie-ai-web
environment: test
app: s1-lessie-ai-web
environment: s1
project: lessie
strategy:
type: RollingUpdate # 滚动更新策略
@@ -25,18 +25,18 @@ spec:
template:
metadata:
labels:
app: test-lessie-ai-web
environment: test
app: s1-lessie-ai-web
environment: s1
project: lessie
spec:
imagePullSecrets:
- name: dxin-image-repository
volumes:
- name: test-default-conf-volume
- name: s1-default-conf-volume
configMap:
name: test-default-conf
name: default-conf
containers:
- name: test-lessie-ai-web
- name: s1-lessie-ai-web
image: uswccr.ccs.tencentyun.com/lessiesit/lessie-ai-web:latest
imagePullPolicy: Always
ports:
@@ -49,33 +49,31 @@ spec:
cpu: "500m" # 最多可以使用0.5个CPU核心
memory: "512Mi" # 容器最多可以使用8Gi内存
volumeMounts:
- name: test-default-conf-volume
- name: s1-default-conf-volume
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
---
# ----------------------------
# Service
# 集群内部http://test-lessie-ai-web-svc.test-lessie.svc.cluster.local:8000
# 集群外部http://<Node_IP>:30080
# 集群内部http://s1-lessie-ai-web-svc.sit.svc.cluster.local:8000
# ----------------------------
apiVersion: v1
kind: Service
metadata:
name: test-lessie-ai-web-svc
namespace: test-lessie
name: s1-lessie-ai-web-svc
namespace: sit
labels:
app: test-lessie-ai-web
environment: test
app: s1-lessie-ai-web
environment: s1
project: lessie
spec:
type: NodePort
type: ClusterIP
selector:
app: test-lessie-ai-web
environment: test
app: s1-lessie-ai-web
environment: s1
project: lessie
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30080

View File

@@ -0,0 +1,185 @@
apiVersion: cloud.tencent.com/v1alpha1
kind: TkeServiceConfig
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"cloud.tencent.com/v1alpha1","kind":"TkeServiceConfig","metadata":{"annotations":{},"creationTimestamp":"2025-11-10T10:30:17Z","generation":4,"name":"sit-ingress-auto-ingress-config","namespace":"sit","resourceVersion":"2206754346","uid":"a64d0729-c7b3-416d-8eab-921eaa9c6c9d"},"spec":{"loadBalancer":{"l7Listeners":[{"defaultServer":"test.jennie.im","domains":[{"domain":"test.jennie.im","http2":true,"rules":[{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"GET","httpCheckPath":"/health","httpCode":31,"intervalTime":10,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/api/"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/api/chat"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/api/conversation"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/api/searches"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/api/shares"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/api/showcases"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/prod-api/agent/"},{"forwardType":"HTTP","healthCheck":{"checkType":"HTTP","enable":true,"extendedCode":"","healthNum":3,"httpCheckDomain":"test.jennie.im","httpCheckMethod":"HEAD","httpCheckPath":"/","httpCode":31,"intervalTime":5,"sourceIpType":1,"timeout":2,"unHealthNum":3},"scheduler":"WRR","session":{"enable":false},"url":"/prod-api/system"}]}],"keepaliveEnable":0,"port":443,"protocol":"HTTPS"}]}}}
creationTimestamp: "2025-11-10T10:30:17Z"
generation: 5
name: sit-ingress-auto-ingress-config
namespace: sit
resourceVersion: "2206893793"
uid: a64d0729-c7b3-416d-8eab-921eaa9c6c9d
spec:
loadBalancer:
l7Listeners:
- defaultServer: test.jennie.im
domains:
- domain: test.jennie.im
http2: true
rules:
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: HEAD
httpCheckPath: /
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /health
httpCode: 31
intervalTime: 10
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /api/
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /api/chat
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /api/conversation
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /api/searches
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /api/shares
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /api/showcases
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /sit-api/health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /prod-api/agent/
- forwardType: HTTP
healthCheck:
checkType: HTTP
enable: true
extendedCode: ""
healthNum: 3
httpCheckDomain: test.jennie.im
httpCheckMethod: GET
httpCheckPath: /sit-api/health
httpCode: 31
intervalTime: 5
sourceIpType: 1
timeout: 2
unHealthNum: 3
scheduler: WRR
session:
enable: false
url: /prod-api/system
keepaliveEnable: 0
port: 443
protocol: HTTPS

View File

@@ -0,0 +1,179 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
ingress.cloud.tencent.com/client-token: dc603203-6dcd-4f15-8357-a9bf648c70a3
ingress.cloud.tencent.com/direct-access: "true"
ingress.cloud.tencent.com/status.conditions: '[{"type":"Ready","status":"True","lastTransitionTime":"2025-11-12T07:56:00Z","reason":"Success","message":""}]'
ingress.cloud.tencent.com/tke-service-config-auto: "true"
kubernetes.io/ingress.class: qcloud
kubernetes.io/ingress.extensiveParameters: '{"AddressIPVersion":"IPV4","InternetAccessible":{"InternetChargeType":"TRAFFIC_POSTPAID_BY_HOUR","InternetMaxBandwidthOut":100}}'
kubernetes.io/ingress.http-rules: "null"
kubernetes.io/ingress.https-rules: '[{"host":"test.jennie.im","path":"/","backend":{"serviceName":"s1-lessie-ai-web-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/api/chat","backend":{"serviceName":"s1-lessie-go-api-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/api/conversation","backend":{"serviceName":"s1-lessie-go-api-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/api/shares","backend":{"serviceName":"s1-lessie-go-api-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/api/showcases","backend":{"serviceName":"s1-lessie-go-api-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/api/searches","backend":{"serviceName":"s1-lessie-go-api-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/api/","backend":{"serviceName":"s1-lessie-agents-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/prod-api/agent/","backend":{"serviceName":"s1-flymoon-agent-svc","servicePort":"http"}},{"host":"test.jennie.im","path":"/prod-api/system","backend":{"serviceName":"s1-flymoon-agent-svc","servicePort":"http"}}]'
kubernetes.io/ingress.qcloud-loadbalance-id: lb-2ro8hoe0
kubernetes.io/ingress.rule-mix: "true"
creationTimestamp: "2025-11-10T10:28:54Z"
finalizers:
- ingress.k8s.tencent/resources
generation: 2
labels:
ingress.cloud.tencent.com/loadbalance-type: OPEN
managedFields:
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:status:
f:loadBalancer:
f:ingress: {}
manager: service-controller
operation: Update
subresource: status
time: "2025-11-10T10:29:12Z"
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:ingress.cloud.tencent.com/tke-service-config-auto: {}
manager: tke-cloud-gw
operation: Update
time: "2025-11-10T10:30:16Z"
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:ingress.cloud.tencent.com/direct-access: {}
f:kubernetes.io/ingress.class: {}
f:kubernetes.io/ingress.extensiveParameters: {}
f:kubernetes.io/ingress.http-rules: {}
f:kubernetes.io/ingress.https-rules: {}
f:kubernetes.io/ingress.rule-mix: {}
f:spec:
f:rules: {}
f:tls: {}
manager: tke-platform-api
operation: Update
time: "2025-11-10T11:20:12Z"
- apiVersion: networking.k8s.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
f:ingress.cloud.tencent.com/client-token: {}
f:ingress.cloud.tencent.com/status.conditions: {}
f:kubernetes.io/ingress.qcloud-loadbalance-id: {}
f:finalizers:
.: {}
v:"ingress.k8s.tencent/resources": {}
f:labels:
.: {}
f:ingress.cloud.tencent.com/loadbalance-type: {}
manager: service-controller
operation: Update
time: "2025-11-12T07:56:00Z"
name: sit-ingress
namespace: sit
resourceVersion: "2234515988"
uid: ec5b21d8-4386-495d-a5c2-998ae6258f1a
spec:
rules:
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-ai-web-svc
port:
name: http
path: /
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-go-api-svc
port:
name: http
path: /api/chat
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-go-api-svc
port:
name: http
path: /api/conversation
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-go-api-svc
port:
name: http
path: /api/shares
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-go-api-svc
port:
name: http
path: /api/showcases
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-go-api-svc
port:
name: http
path: /api/searches
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-lessie-agents-svc
port:
name: http
path: /api/
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-flymoon-agent-svc
port:
name: http
path: /prod-api/agent/
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: s1-flymoon-agent-svc
port:
name: http
path: /prod-api/system
pathType: ImplementationSpecific
tls:
- hosts:
- test.jennie.im
secretName: jennie-im-sbydostx
status:
loadBalancer:
ingress:
- hostname: lb-2ro8hoe0-iadyek218pl4vqn0.clb.usw-tencentclb.cloud

View File

@@ -1,90 +0,0 @@
# ----------------------------
# Deployment
# ----------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-flymoon-payment-deployment
namespace: test-lessie
labels:
app: test-flymoon-payment
environment: test
project: flymoon
spec:
replicas: 1
selector:
matchLabels:
app: test-flymoon-payment
environment: test
project: flymoon
strategy:
type: RollingUpdate # 滚动更新策略
rollingUpdate:
maxSurge: 1 # 最大新增副本数
maxUnavailable: 0 # 最大不可用副本数
template:
metadata:
labels:
app: test-flymoon-payment
environment: test
project: flymoon
spec:
imagePullSecrets:
- name: dxin-image-repository # 镜像仓库凭证Secret
volumes:
- name: flymoon-payment-logs-volume
hostPath:
path: /data/logs/flymoon-payment/
type: DirectoryOrCreate
containers:
- name: test-flymoon-payment # 容器名称
image: uswccr.ccs.tencentyun.com/lessietest/flymoon-payment:v0.0.7 # 容器镜像
imagePullPolicy: Always # 镜像拉取策略,总是拉取
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: SPRING_PROFILES_ACTIVE
value: "s1"
ports:
- containerPort: 8090 # 容器暴露的端口
resources:
requests:
cpu: "100m" # 容器请求分配0.1个CPU核心这不是实际占用但调度会以这里进行参考
memory: "1Gi" # 容器请求分配1Gi内存这会实际预留
limits:
cpu: "1" # 最多可以使用1个CPU核心
memory: "3Gi" # 容器最多可以使用3Gi内存
volumeMounts:
- name: flymoon-payment-logs-volume
mountPath: /app/logs/
subPathExpr: flymoon-payment-log-$(POD_NAME)
---
# ----------------------------
# Service
# 集群内部http://test-flymoon-payment-svc.test-lessie.svc.cluster.local:8090
# 集群外部http://<Node-IP>:30809
# ----------------------------
apiVersion: v1
kind: Service
metadata:
name: test-flymoon-payment-svc
namespace: test-lessie
labels:
app: test-flymoon-payment
environment: test
project: flymoon
spec:
type: NodePort
selector: # 必须匹配 Deployment 的 labels 才能关联 Pod
app: test-flymoon-payment
environment: test
project: flymoon
ports:
- name: http
port: 8090 # ClusterIP 内部端口
targetPort: 8090 # 容器端口
nodePort: 30809 # 节点对外端口(30000-32767)

View File

@@ -1,89 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
ingress.cloud.tencent.com/auto-rewrite: "false"
ingress.cloud.tencent.com/client-token: 454eb954-4094-43fc-9cff-05f3f7f307c7
ingress.cloud.tencent.com/healthcheck-interval: "5"
ingress.cloud.tencent.com/healthcheck-method: GET
ingress.cloud.tencent.com/healthcheck-path: /health
ingress.cloud.tencent.com/healthcheck-timeout: "3"
ingress.cloud.tencent.com/healthy-threshold: "2"
ingress.cloud.tencent.com/status.conditions: '[{"type":"Ready","status":"True","lastTransitionTime":"2025-11-05T09:47:06Z","reason":"Success","message":""}]'
ingress.cloud.tencent.com/unhealthy-threshold: "3"
kubernetes.io/ingress.class: qcloud
kubernetes.io/ingress.extensiveParameters: '{"AddressIPVersion":"IPV4","InternetAccessible":{"InternetChargeType":"TRAFFIC_POSTPAID_BY_HOUR","InternetMaxBandwidthOut":100}}'
kubernetes.io/ingress.http-rules: "null"
kubernetes.io/ingress.https-rules: '[{"host":"test.jennie.im","path":"/","backend":{"serviceName":"test-lessie-ai-web-svc","servicePort":"80"}},{"host":"test.jennie.im","path":"/payment/webhook","backend":{"serviceName":"test-flymoon-payment-svc","servicePort":"8090"}},{"host":"test.jennie.im","path":"/sit-api/agent/","backend":{"serviceName":"test-flymoon-agent-svc","servicePort":"8070"}},{"host":"test.jennie.im","path":"/sit-api/system/","backend":{"serviceName":"test-flymoon-agent-svc","servicePort":"8070"}},{"host":"test.jennie.im","path":"/api/chat","backend":{"serviceName":"test-lessie-go-api-svc","servicePort":"8100"}}]'
kubernetes.io/ingress.qcloud-loadbalance-id: lb-ifri829c
kubernetes.io/ingress.rule-mix: "true"
creationTimestamp: "2025-10-31T06:28:10Z"
finalizers:
- ingress.k8s.tencent/resources
generation: 14
labels:
ingress.cloud.tencent.com/loadbalance-type: OPEN
name: test-lessie-ingress
namespace: test-lessie
resourceVersion: "2052378552"
uid: d196795e-711d-4b08-a5f7-22613becfc13
spec:
rules:
- host: test.jennie.im
http:
paths:
- backend:
service:
name: test-lessie-ai-web-svc
port:
number: 80
path: /
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: test-flymoon-payment-svc
port:
number: 8090
path: /payment/webhook
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: test-flymoon-agent-svc
port:
number: 8070
path: /sit-api/agent/
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: test-flymoon-agent-svc
port:
number: 8070
path: /sit-api/system/
pathType: ImplementationSpecific
- host: test.jennie.im
http:
paths:
- backend:
service:
name: test-lessie-go-api-svc
port:
number: 8100
path: /api/chat
pathType: ImplementationSpecific
tls:
- hosts:
- test.jennie.im
secretName: jennie-im-sbydostx
status:
loadBalancer:
ingress:
- hostname: lb-ifri829c-6dku12mwxpf5ivcs.clb.usw-tencentclb.cloud