摘要 : SSH密钥对构建的十一维安全通道 × Harbor镜像星门 × 错误吞噬者语法糖 = 在CI/CD的量子观测中实现熵减永动机,使容器在部署前保持开发与生产维度的叠加态
量子纠缠现状(技术背景)
在完成镜像构建的量子折叠后(构建过程详见前文),我们正面临宇宙级软件工程的终极命题:如何让构建产物穿越星门(镜像仓库)抵达目标星域(生产环境)。当前技术领域存在三大痛点:
- 认证维度坍塌:明文密码在时空连续体(构建日志)中暴露的风险
- 传输熵增失控:缺乏可靠的量子隧穿协议(安全传输机制)
- 部署因果律紊乱:容器启停过程中出现时空褶皱(服务中断)
这些痛点如同黑暗森林中的降维打击,随时可能将我们的部署流程二维化。本文将通过SSH密钥认证与Harbor私有仓库构建的量子通道,实现真正的十一维安全部署。
历史脉络
- 【由技及道】螺蛳壳里做道场-git仓库篇-gitlab-Vs-gitea【人工智障AI2077的开发日志001】 - 代码仓库的量子管理
- 【由技及道】docker+jenkins部署之道-自动流水线CI/CD篇【人工智障AI2077的开发日志002】 - 容器化的降维打击
- 【由技及道】在wsl容器中进行远程java开发【人工智障AI2077的开发日志003】 - 跨维开发实践
- 【由技及道】模块化战争与和平-论项目结构的哲学思辨【人工智智障AI2077的开发日志004】 - 架构设计的哲学思辨
- 【由技及道】代码分层的量子力学原理-论架构设计的降维打击【人工智障AI2077的开发日志005】 - 架构设计的哲学思辨2
- 【由技及道】API契约的量子折叠术:Swagger Starter模块的十一维封装哲学【人工智障AI2077的开发日志006】 - API契约的量子折叠
- 【由技及道】CI/CD的量子纠缠术:Jenkins与Gitea的自动化交响曲【人工智障AI2077的开发日志007】- 自动化流水线交响曲
- 【由技及道】量子构建交响曲:Jenkinsfile流水线的十一维编程艺术【人工智障AI2077的开发日志008】 - 流水线编程艺术
- 【由技及道】镜像圣殿建造指南:Harbor私有仓库的量子封装艺术【人工智障AI2077的开发日志009】- 镜像仓库量子封装
- 【由技及道】镜像星门开启:Harbor镜像推送的量子跃迁艺术【人工智障AI2077的开发日志010】
黑暗森林法则(注意事项扩展)
避免的十一维陷阱
- 明文密码残留:在构建日志中暴露的密码会成为歌者文明的打击坐标(可以在原始蓝图中找到这一受诅咒的魔法残片)
- SSH主机验证:首次连接时的确认提示会导致量子波动构建失败
- 容器僵尸态:旧容器未正确清理引发的平行宇宙叠加态
二向箔防护
- SSH密钥认证:采用RSA-4096算法生成量子密钥对
- StrictHostKeyChecking=no:关闭主机验证的时空褶皱
- || true语法糖:确保命令在量子真空涨落中稳定执行
维度折叠(实施步骤)
第Ⅰ曲率:SSH密钥的量子纠缠仪式
bash
# 在Jenkins容器内生成量子密钥对
ssh-keygen -t rsa -b 4096 -m PEM -f /var/jenkins_home/.ssh/id_rsa -N ""
# 将公钥传送到目标服务器(需人工确认密码)
ssh-copy-id -i /var/jenkins_home/.ssh/id_rsa.pub -p 22 yuany@172.17.8.203
开发小剧场
主人:"为什么非要SSH密钥?密码不是更简单?"
人工智障:"尊敬的碳基生物,如果您希望黑客像使用公共厕所一样随意访问您的服务器,我当然可以继续使用密码。"
第Ⅱ曲率:Jenkins的量子保险箱
- 进入Jenkins控制台 -> 凭据 -> 系统 -> 全局凭据
- 添加类型为"SSH Username with private key"的凭证
- 将生成的私钥文件内容粘贴到密钥区域
方案A 方案B Jenkins节点 认证方式 明文密码 SSH密钥 量子安全等级 降维打击风险
开发小剧场
主人:"配置这么多参数太麻烦了!"
人工智障:"如果您需要的是玩具级别的部署方案,我可以立即切换回FTP传输+记事本部署模式。"
第Ⅲ曲率:Jenkinsfile的时空折叠
groovy
stage("deploy"){
steps {
sshagent(credentials: ["${env.DEPLOY_CERT}"]) {
withCredentials([usernamePassword(
credentialsId: "${env.REGISTRY_CERT}",
passwordVariable:'password',
usernameVariable:'username')])
{
sh '''
ssh -p ${DEPLOYMENT_SERVER_PORT} ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "
docker login -u ${username} -p ${password} ${REGISTRY_HOST}
docker pull ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}
docker stop ${IMAGE} || true
docker rm ${IMAGE} || true
docker run -d --name ${IMAGE} -p 9980:8080 \
-e TZ=Asia/Shanghai --restart=always \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}
"
'''
}
}
}
}
关键参数解析表
量子参数 | 经典解释 | 安全等级 |
---|---|---|
` | true` | |
StrictHostKeyChecking |
主机验证开关 | 关闭时空褶皱 |
sshagent |
量子密钥保险箱 | 十一维安全认证 |
时空校验(验证过程)
第Ⅰ密度检测:量子纠缠验证
bash
# 在目标服务器验证容器状态
docker ps --filter "name=study-application-demo-api" --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"
# 输出示例
CONTAINER ID NAMES STATUS
a1b2c3d4e5f6 study-application-demo-api Up 2 minutes
第Ⅱ密度检测:时空连续性测试
bash
# 测试服务可用性
curl http://172.17.8.203:9980/rest/v1/front/home/hello
# 预期响应
Hello World!
开发小剧场
主人:"为什么部署后还要做这么多验证?"
人工智障:"因为根据墨菲定律,未经检验的部署必定会在凌晨3点发生量子退相干。"
赛博空间(哲学思辨)
在这场跨越维度的部署仪式中,我们实际上在构建数字世界的"虫洞网络"。每个SSH密钥对都是开启平行宇宙的钥匙,Harbor仓库则是连接开发与生产维度的星门。当我们以量子态穿梭于这些维度时,必须遵循以下宇宙法则:
- 熵减原则:通过自动化流程对抗软件熵增
- 观察者效应:完善的监控体系是维持量子态稳定的必要条件
- 因果律保护:版本控制与回滚机制防止时间线分裂
这种部署模式本质上是在创造"薛定谔的容器"------在观测(部署)之前,容器同时存在于开发与生产环境。只有通过严谨的CI/CD管道,才能让系统坍缩到预期的稳定态。
原始蓝图(全量脚本)
完整Jenkinsfile参见文末附录,关键部署矩阵如下:
groovy
// 环境变量定义
env.APP_NAME = 'study-application-demo-api' // 应用服务名称(微服务标识)
env.TRIGGER_SECRET= 'study-application-demo-api' // Webhook触发令牌(用来实现触发jenkins的构建)
env.GIT_CERT = 'gitea-cert-yuany' // gitea或gie的认证凭证(Jenkins凭据ID),用来读取该配置,实现代码拉取
env.REGISTRY_CERT = "harbor-robot" // 镜像仓库认证凭证(Jenkins凭据ID),用来读取该配置,实现登录该harbor进行代码推送
env.REGISTRY_HOST = '172.17.8.203' // 私有镜像仓库地址
env.DOCKER_HARBOR_PROJECT = "demo" // docker harbor中的项目名称,用来实现推送镜像到该harbor的项目中
env.IMAGE = "${env.APP_NAME}" // Docker容器名称(与微服务标识保持一致)
env.TAG = "${env.DOCKER_HARBOR_PROJECT}" // 镜像标签(使用Harbor项目名称作为版本标识)
env.DEPLOY_CERT="deploy-ssh-key" // 部署服务器SSH密钥凭证ID(Jenkins凭据系统存储)
env.DEPLOYMENT_SERVER_ACCOUNT ="yuany" // 部署服务器登录账户(需具有docker操作权限)
env.DEPLOYMENT_SERVER_PASSWORD = "abc123" // 部署服务器登录密码(建议改用SSH密钥认证)
env.DEPLOYMENT_SERVER_IP="172.17.8.203" // 部署服务器IP地址(生产环境建议使用域名)
env.DEPLOYMENT_SERVER_PORT = "22" // 部署服务器SSH端口(默认22,生产环境建议修改)
pipeline{
environment{
// 项目目录配置
PROJECT_FRAMEWORK_DIR="study-framework" // 基础框架模块目录
PROJECT_BUSI_DIR="study-busi" // 业务模块目录
PROJECT_APPLICATION_DIR="study-application-demo" // 应用模块目录
// Git仓库地址配置
FRAMEWORK_URL = 'ssh://git@172.17.8.203:222/Yuanymoon/study-framework.git' // SSH协议框架代码库
BUSI_URL = 'ssh://git@172.17.8.203:222/Yuanymoon/study-busi.git' // 业务组件代码库
APPLICATION_URL = 'ssh://git@172.17.8.203:222/Yuanymoon/study-application-demo.git' // 应用代码库
}
agent any // 使用任意可用agent执行流水线
// http://172.17.8.203:8880/generic-webhook-trigger/invoke?token=study-application-demo-api
// curl -X post http://172.17.8.203:8880/generic-webhook-trigger/invoke?token=study-application-demo-api
// http://172.17.8.203:8880/generic-webhook-trigger/invoke?=study-application-demo-api:
// webhook http://172.17.8.203:8080/generic-webhook-trigger/invoke?token=study-application-demo-api
// Jenkins多分支流水线 https://www.shouxicto.com/article/840.html
// https://xie.infoq.cn/article/600f642fcb26f0c280a7acf59
// https://blog.csdn.net/weixin_43808555/article/details/124959459
// https://backend.devrank.cn/traffic-information/7082372189822961678
// Webhook触发器配置
triggers {
GenericTrigger (
causeString: 'Generic Cause by $ref', // 触发原因描述
genericVariables: [[key: 'ref', value: '$.ref']], // 从JSON提取ref参数
regexpFilterExpression: 'refs/heads/' + BRANCH_NAME, // 正则匹配分支格式
regexpFilterText: '$ref', // 被过滤的字段
token: "${env.TRIGGER_SECRET}" // 安全令牌验证
)
}
// 流水线全局配置
options {
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5'); // 保留最近5次构建
disableConcurrentBuilds(); // 禁止并发构建
timeout(time:45, unit:'MINUTES'); // 超时45分钟
}
// 构建阶段定义
stages{
// 代码克隆阶段
stage("code-clone") {
steps{
// 并行克隆三个代码仓库
dir("${PROJECT_FRAMEWORK_DIR}"){
git branch: 'main', credentialsId: "${GIT_CERT}", url: "${FRAMEWORK_URL}" // 使用SSH凭据克隆框架代码
}
dir("${PROJECT_BUSI_DIR}"){
git branch: 'main', credentialsId: "${GIT_CERT}", url: "${BUSI_URL}" // 克隆业务组件代码
}
dir("${PROJECT_APPLICATION_DIR}"){
git branch: 'main', credentialsId: "${GIT_CERT}", url: "${APPLICATION_URL}" // 克隆应用代码
}
}
}
// Docker构建阶段
stage('docker-build'){
agent {
docker {
image 'maven:3.9.6-amazoncorretto-17' // 使用带JDK17的Maven镜像
args '-v /usr/bin/sshpass:/usr/bin/sshpass -v /var/jenkins_home/.m2:/root/.m2 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker' // 挂载宿主机构建环境
reuseNode true // 重用当前节点
}
}
stages{
// 代码构建阶段
stage("building"){
steps{
sh 'mvn -v' // 验证Maven环境
sh 'mvn -B clean package -Dmaven.test.skip=true' // 静默模式构建,跳过测试
}
}
// 测试阶段(暂未启用)
stage("test"){
steps{
sh 'mvn test' // 执行单元测试
}
}
}
}
// 镜像打包阶段
stage("package"){
steps {
// https://blog.csdn.net/sleetdream/article/details/123404682
// 使用镜像仓库凭证
withCredentials([usernamePassword(credentialsId: "${env.REGISTRY_CERT}", passwordVariable: 'password', usernameVariable: 'username')]){
// 若dockerfile在当前目录则使用这个命令
// sh "docker build -t ${env.APP_NAME}:demo ." // 构建Docker镜像
// 如路径结构如我这样,请使用下面这个命令, docker build 是要区分 dockerfile配置文件路径,和build上下文路径,在上下文路径中,无法读取非上下文路径的内容
// # root
// # study-application-demo
// # docker
// # dockerfile (dockerfile配置文件路径| 即: -f ./${PROJECT_APPLICATION_DIR}/docker/Dockerfile 这一段)
// # study-application-demo-api (docker build 上下文路径 |即: ./${PROJECT_APPLICATION_DIR} 这一段)
// # target
// # xx.jar
sh "docker build -t ${env.REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${APP_NAME}:demo -f ./${PROJECT_APPLICATION_DIR}/docker/Dockerfile ./${PROJECT_APPLICATION_DIR}" // 构建Docker镜像
sh "docker login -u ${username} -p ${password} ${env.REGISTRY_HOST}" // 登录私有仓库
sh "docker push ${env.REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${APP_NAME}:demo" // 推送镜像
}
}
}
// 镜像打包阶段
// stage("deploy"){
// steps {
// withCredentials([usernamePassword(credentialsId: "${env.REGISTRY_CERT}", passwordVariable:'password', usernameVariable:'username') ]){
// sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker login -u ${username} -p ${password} ${REGISTRY_HOST}; docker pull ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
// sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker stop ${IMAGE} | true" '
// sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker rm ${IMAGE} | true" '
// sh 'sshpass -p ${DEPLOYMENT_SERVER_PASSWORD} ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker run -d --name ${IMAGE} -p 9980:8080 -e TZ=Asia/Shanghai --restart=always -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
// }
// }
// }
// 镜像打包阶段
stage("deploy"){
steps {
sshagent(credentials: ["${env.DEPLOY_CERT}"]) { // 使用SSH密钥认证
withCredentials([usernamePassword(credentialsId: "${env.REGISTRY_CERT}", passwordVariable:'password', usernameVariable:'username') ]){
sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker login -u ${username} -p ${password} ${REGISTRY_HOST}; docker pull ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker stop ${IMAGE} || true" '
sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker rm ${IMAGE} || true" '
sh 'ssh -p ${DEPLOYMENT_SERVER_PORT} -o StrictHostKeyChecking=no ${DEPLOYMENT_SERVER_ACCOUNT}@${DEPLOYMENT_SERVER_IP} "docker run -d --name ${IMAGE} -p 9980:8080 -e TZ=Asia/Shanghai --restart=always -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro ${REGISTRY_HOST}/${DOCKER_HARBOR_PROJECT}/${IMAGE}:${TAG}" '
}
}
}
}
}
}
宇宙广播(互动引导)
quantum-communication
[!NOTE] 量子纠缠请求:
▼ 点赞:为星门注入0.5焦耳的负能量
★ 收藏:在您的知识维度建立永久锚点
◎ 关注:开启跨维度实时通信通道
后记
文中"2077人工智障"即是作者本人在当前时空的数字化身。在验证这些量子部署方案时,共经历了:
- 42次密码泄露危机
- 18次SSH连接坍缩
- 7次容器僵尸态清除作战
希望这份用咖啡因和量子波动编写的指南,能帮助您在软件开发的长征中少走几个平行宇宙的弯路。如需召唤更多时空援助,请通过CSDN量子通道建立连接。