SSH / 文件传输 / 制品仓库
概述
本文档涵盖从远程服务器连接到自动化部署的完整工具链:SSH 安全配置与隧道技术、文件传输与同步方案、制品仓库管理(Nexus / Artifactory),以及部署流程的最佳实践。
一、SSH 配置
1.1 密钥生成
使用 ssh-keygen 生成 RSA 或 Ed25519 密钥对:
# 生成 Ed25519 密钥(推荐,更高安全性)
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519
# 生成 RSA 密钥(兼容旧系统)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/id_rsa参数说明:
| 参数 | 含义 |
|---|---|
-t | 密钥类型(ed25519 / rsa / ecdsa) |
-b | 密钥长度(RSA 至少 4096 位) |
-C | 注释,通常填写邮箱 |
-f | 输出文件路径 |
1.2 authorized_keys
将客户端公钥添加到服务器端:
# 方法一:手动追加
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# 方法二:ssh-copy-id(推荐)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ipauthorized_keys 支持精细化的访问控制:
# 限制来源 IP 和命令
from="192.168.1.0/24",command="/usr/bin/validate.sh",no-agent-forwarding,no-port-forwarding ssh-ed25519 AAA... user@host
# 仅允许特定用户
restrict,command="/usr/bin/git-shell" ssh-ed25519 AAA... git-user@host常用选项:
| 选项 | 含义 |
|---|---|
from="..." | 限制允许的客户端来源 IP |
command="..." | 强制执行的命令(忽略客户端请求的命令) |
no-agent-forwarding | 禁止代理转发 |
no-port-forwarding | 禁止端口转发 |
no-pty | 禁止分配 TTY |
restrict | 启用所有限制(OpenSSH 7.2+) |
1.3 sshd_config 安全加固
# /etc/ssh/sshd_config
# 禁用密码认证(核心安全措施)
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
# 修改默认端口(避开自动化扫描)
Port 2222
# 仅允许特定用户登录
AllowUsers deployer admin
# 禁止 root 直接登录
PermitRootLogin no
# 密钥相关配置
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# 协议与加密
Protocol 2
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
# 会话控制
MaxAuthTries 3
MaxSessions 10
ClientAliveInterval 300
ClientAliveCountMax 2
# 日志
LogLevel VERBOSE应用配置后重启服务:
# 验证配置
sshd -t
# 重启服务
systemctl restart sshd
# 务必保持当前会话不退出,另开终端验证新配置可正常登录后再关闭旧会话1.4 跳板机 ProxyJump
通过跳板机(堡垒机)访问内网服务器:
# ~/.ssh/config 配置
Host bastion
HostName bastion.example.com
User jumpuser
Port 22
IdentityFile ~/.ssh/id_ed25519
Host internal-server
HostName 10.0.1.100
User appuser
Port 2222
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519
# 简化连接
ssh internal-server多层跳板机:
# 链式跳转(OpenSSH 7.3+)
ssh -J user1@jump1:22,user2@jump2:22 target-host
# 等同于
ssh -o ProxyJump=user1@jump1:22,user2@jump2:22 target-host本地端口转发与远程端口转发:
# 本地转发:将本地 8080 转发到远程内网的 80 端口
ssh -L 8080:internal-web:80 bastion
# 远程转发:将远程端口转发到本地服务(内网穿透)
ssh -R 9000:localhost:3000 bastion
# 动态转发(SOCKS 代理)
ssh -D 1080 bastion二、文件传输
2.1 SCP 命令详解
# 上传文件
scp -P 2222 local-file.txt user@server:/remote/path/
# 下载文件
scp -P 2222 user@server:/remote/path/file.txt ./
# 上传目录(递归)
scp -r -P 2222 ./dist/ user@server:/opt/app/
# 通过跳板机传输
scp -o ProxyJump=bastion file.txt internal-server:/tmp/
# 限制带宽(单位 Kbit/s,128 Kbit/s = 16 KB/s)
scp -l 128 large-file.zip user@server:/tmp/SCP 局限性:
- 不支持增量传输,每次全量拷贝
- 传输中断后无法断点续传
- 大目录传输效率较低
2.2 rsync 增量同步
rsync 是更推荐的文件同步工具,支持增量传输、压缩、断点续传。
本地同步:
# 基本语法
rsync -avh --delete source/ destination/
# 参数说明
# -a 归档模式(保留权限、时间戳、符号链接等)
# -v 详细输出
# -h 人类可读格式
# --delete 删除目标端多余文件
# --dry-run 预览模式(不实际执行)远程同步(通过 SSH):
# 推送到远程
rsync -avhz --progress -e "ssh -p 2222" ./build/ user@server:/opt/app/
# 从远程拉取
rsync -avhz --progress -e "ssh -p 2222" user@server:/opt/app/backup/ ./
# 通过跳板机
rsync -avhz -e "ssh -o ProxyJump=bastion" ./dist/ internal-server:/opt/app/
# 排除文件
rsync -avh --exclude='node_modules' --exclude='.git' --exclude='*.log' ./project/ user@server:/opt/project/高级用法:
# 断点续传(部分传输的文件)
rsync -avhP --partial-dir=.rsync-partial huge-file.tar.gz user@server:/tmp/
# 限速传输(避免占满带宽)
rsync -avh --bwlimit=5000 ./data/ user@server:/data/
# 基于快照的增量备份(硬链接)
rsync -avh --delete --link-dest=/backup/yesterday/ /data/ /backup/today/2.3 FTP vs SFTP 对比
| 特性 | FTP | SFTP (SSH File Transfer Protocol) |
|---|---|---|
| 传输层 | TCP 21(控制)+ 20(数据) | SSH (TCP 22) |
| 加密 | 明文传输(FTPS 可选) | 继承 SSH 加密 |
| 认证方式 | 用户名/密码 | 密码或密钥对 |
| 防火墙友好度 | 较差(需要动态端口) | 好(仅需一个端口) |
| 断点续传 | 支持 | 支持 |
| 目录列表 | 支持 | 支持 |
| 性能 | 大文件略优 | 加密开销略高 |
| 安全性 | 低(建议避免) | 高 |
结论: 新系统应统一使用 SFTP。FTP 仅在遗留系统中出现,且应尽快迁移。
2.4 lftp 批量传输
lftp 是强大的命令行文件传输工具,支持多种协议和批量操作:
# 交互式 SFTP 会话
lftp -u user sftp://server
# 非交互式批量下载
lftp -c "open -u user,password sftp://server; mget -c /remote/path/*.log /local/path/"
# 镜像同步(类似 rsync)
lftp -c "open -u user sftp://server; mirror --verbose --delete --parallel=4 /remote/dir /local/dir"
# 批量上传
lftp -c "open -u user sftp://server; mput /local/path/*.tar.gz /remote/path/"
# 使用镜像实现增量同步
lftp -c "
open -u deploy, sftp://192.168.1.100 -p 2222
mirror --reverse \
--verbose \
--delete \
--exclude node_modules/ \
--exclude .git/ \
--exclude '*.log' \
--parallel=4 \
/local/build/ /opt/app/
"lftp 优势:
- 支持 FTP、SFTP、HTTP、HTTPS 等多种协议
mirror命令类似 rsync 的镜像同步--parallel并发传输提升吞吐- 支持断点续传(
-c参数)
三、自动化部署脚本示例
以下是一个完整的自动化部署脚本,涵盖从代码拉取到服务重启的全流程:
#!/bin/bash
# ============================================
# deploy.sh — 自动化部署脚本
# 用法: ./deploy.sh [env] [branch]
# env: dev | staging | production (默认 dev)
# branch: Git 分支名 (默认 main)
# ============================================
set -euo pipefail
# ---------- 配置区 ----------
APP_NAME="my-service"
DEPLOY_USER="deployer"
DEPLOY_HOST="192.168.1.100"
DEPLOY_PORT="2222"
REMOTE_DIR="/opt/${APP_NAME}"
BACKUP_DIR="/opt/backup/${APP_NAME}"
JAR_NAME="${APP_NAME}.jar"
SSH_KEY="~/.ssh/deploy_key"
# 环境相关配置
declare -A PORTS=(
[dev]="8080"
[staging]="8081"
[production]="8080"
)
declare -A PROFILES=(
[dev]="dev"
[staging]="staging"
[production]="prod"
)
# ---------- 参数解析 ----------
ENV="${1:-dev}"
BRANCH="${2:-main}"
PORT="${PORTS[$ENV]}"
PROFILE="${PROFILES[$ENV]}"
echo "=== 部署开始: ${APP_NAME} | 环境: ${ENV} | 分支: ${BRANCH} ==="
# ---------- 1. 代码拉取与构建 ----------
echo "[1/5] 拉取代码并构建..."
cd /home/jenkins/workspace/${APP_NAME}
git checkout ${BRANCH}
git pull origin ${BRANCH}
# Maven 构建(跳过测试以加速部署流程)
./mvnw clean package -DskipTests -P${PROFILE}
# 检查构建产物
if [ ! -f "target/${JAR_NAME}" ]; then
echo "错误: 构建产物不存在"
exit 1
fi
# ---------- 2. 备份远程旧版本 ----------
echo "[2/5] 备份远程旧版本..."
BACKUP_FILE="${BACKUP_DIR}/${APP_NAME}-$(date +%Y%m%d_%H%M%S).jar"
ssh -p ${DEPORT_PORT} -i ${SSH_KEY} ${DEPLOY_USER}@${DEPLOY_HOST} \
"mkdir -p ${BACKUP_DIR} && \
cp ${REMOTE_DIR}/${JAR_NAME} ${BACKUP_FILE} && \
echo '备份完成: ${BACKUP_FILE}'"
# 保留最近 30 天备份,清理旧备份
ssh -p ${DEPLOY_PORT} -i ${SSH_KEY} ${DEPLOY_USER}@${DEPLOY_HOST} \
"find ${BACKUP_DIR} -name '*.jar' -mtime +30 -delete"
# ---------- 3. 传输新版本 ----------
echo "[3/5] 传输新版本到服务器..."
rsync -avhz --progress \
-e "ssh -p ${DEPLOY_PORT} -i ${SSH_KEY}" \
target/${JAR_NAME} \
${DEPLOY_USER}@${DEPLOY_HOST}:${REMOTE_DIR}/${JAR_NAME}.new
# ---------- 4. 停止旧服务 ----------
echo "[4/5] 停止旧服务..."
ssh -p ${DEPLOY_PORT} -i ${SSH_KEY} ${DEPLOY_USER}@${DEPLOY_HOST} \
"sudo systemctl stop ${APP_NAME} || true"
# 等待进程完全退出
sleep 3
# ---------- 5. 替换并启动新服务 ----------
echo "[5/5] 启动新服务..."
ssh -p ${DEPLOY_PORT} -i ${SSH_KEY} ${DEPLOY_USER}@${DEPLOY_HOST} \
"mv ${REMOTE_DIR}/${JAR_NAME}.new ${REMOTE_DIR}/${JAR_NAME} && \
sudo systemctl start ${APP_NAME}"
# 等待应用启动并健康检查
echo "等待应用启动..."
for i in $(seq 1 30); do
sleep 2
STATUS=$(ssh -p ${DEPLOY_PORT} -i ${SSH_KEY} ${DEPLOY_USER}@${DEPLOY_HOST} \
"curl -s -o /dev/null -w '%{http_code}' http://localhost:${PORT}/actuator/health" || echo "000")
if [ "${STATUS}" = "200" ]; then
echo "健康检查通过 (HTTP 200)"
break
fi
echo "等待中... (第 ${i} 次尝试, 状态码: ${STATUS})"
done
if [ "${STATUS}" != "200" ]; then
echo "警告: 健康检查未通过,请手动检查服务状态"
echo "回滚命令: ./rollback.sh ${ENV} $(basename ${BACKUP_FILE})"
exit 1
fi
echo "=== 部署成功: ${APP_NAME} (${ENV}) ==="
echo "部署时间: $(date '+%Y-%m-%d %H:%M:%S')"回滚脚本示例:
#!/bin/bash
# rollback.sh — 快速回滚
set -euo pipefail
ENV="${1:-dev}"
BACKUP_FILE="${2:-}"
DEPLOY_USER="deployer"
DEPLOY_HOST="192.168.1.100"
DEPLOY_PORT="2222"
REMOTE_DIR="/opt/my-service"
BACKUP_DIR="/opt/backup/my-service"
if [ -z "${BACKUP_FILE}" ]; then
# 自动获取最新备份
BACKUP_FILE=$(ssh -p ${DEPLOY_PORT} ${DEPLOY_USER}@${DEPLOY_HOST} \
"ls -t ${BACKUP_DIR}/*.jar | head -1")
fi
echo "回滚到: ${BACKUP_FILE}"
ssh -p ${DEPLOY_PORT} ${DEPLOY_USER}@${DEPLOY_HOST} \
"sudo systemctl stop my-service && \
cp ${BACKUP_DIR}/${BACKUP_FILE} ${REMOTE_DIR}/my-service.jar && \
sudo systemctl start my-service"
echo "回滚完成"四、制品仓库 Nexus
4.1 Docker 安装 Nexus
# docker-compose.yml
version: '3.8'
services:
nexus:
image: sonatype/nexus3:latest
container_name: nexus
restart: always
ports:
- "8081:8081" # Nexus Web UI
- "8082:8082" # Docker (hosted)
- "8083:8083" # Docker (proxy/group)
- "8084:8084" # Raw / Maven / npm
volumes:
- nexus-data:/nexus-data
environment:
- INSTALL4J_ADD_VM_PARAMS=-Xms2g -Xmx2g -XX:MaxDirectMemorySize=2g
ulimits:
nofile:
soft: 65536
hard: 65536
volumes:
nexus-data:
driver: local启动并初始化:
# 启动
docker-compose up -d
# 查看初始管理员密码
docker exec nexus cat /nexus-data/admin.password
# 访问 http://localhost:8081
# 默认管理员: admin4.2 Maven 私服配置
在 Nexus 中创建仓库:
| 仓库类型 | 用途 | 示例名称 |
|---|---|---|
| maven2 (hosted) | 私有 release 制品 | maven-releases |
| maven2 (hosted) | 私有 snapshot 制品 | maven-snapshots |
| maven2 (proxy) | 代理中央仓库/阿里云 | maven-central-proxy |
| maven2 (group) | 聚合上述仓库 | maven-public |
Maven settings.xml 配置:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>nexus-releases</id>
<username>deployer</username>
<password>your-password</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>deployer</username>
<password>your-password</password>
</server>
</servers>
<mirrors>
<mirror>
<id>nexus-public</id>
<mirrorOf>*</mirrorOf>
<url>http://nexus:8084/repository/maven-public/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>nexus-public</id>
<url>http://nexus:8084/repository/maven-public/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
</profile>
</profiles>
</settings>项目 pom.xml 配置发布地址:
<distributionManagement>
<repository>
<id>nexus-releases</id>
<name>Nexus Release Repository</name>
<url>http://nexus:8084/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<name>Nexus Snapshot Repository</name>
<url>http://nexus:8084/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement># 发布到 Nexus
mvn deploy
# SNAPSHOT 版本自动发布到 snapshot 仓库
# RELEASE 版本自动发布到 release 仓库4.3 npm 仓库配置
创建 npm 仓库:
| 仓库类型 | 用途 | 示例名称 |
|---|---|---|
| npm (hosted) | 私有 npm 包 | npm-private |
| npm (proxy) | 代理 npmjs.org / 淘宝镜像 | npm-proxy |
| npm (group) | 聚合上述仓库 | npm-public |
客户端配置:
# 设置 npm 仓库地址
npm config set registry http://nexus:8084/repository/npm-public/
# 登录私有仓库发布包
npm login --registry=http://nexus:8084/repository/npm-private/
# 发布 npm 包
npm publish --registry=http://nexus:8084/repository/npm-private/
# 配合 .npmrc 使用
echo "registry=http://nexus:8084/repository/npm-public/" > .npmrc4.4 Docker 镜像代理
创建 Docker 代理仓库:
| 仓库类型 | 用途 | 端口 |
|---|---|---|
| docker (proxy) | 代理 Docker Hub | 8083 |
| docker (hosted) | 私有镜像仓库 | 8082 |
| docker (group) | 聚合代理+私有 | - |
客户端配置:
# 登录 Nexus Docker 仓库
docker login nexus.example.com:8082
# 拉取镜像(通过代理)
docker pull nexus.example.com:8083/nginx:latest
# 实际会从 Docker Hub 缓存到 Nexus
# 推送私有镜像
docker tag my-app:latest nexus.example.com:8082/my-app:1.0.0
docker push nexus.example.com:8082/my-app:1.0.0Nexus 配置 Docker Bearer Token Realm:
- 登录 Nexus Web UI (http://localhost:8081)
- 进入 Administration > Realms
- 将 "Docker Bearer Token Realm" 激活
- 配置 HTTP 连接器支持 Docker 协议
五、Artifactory
5.1 通用制品仓库
Artifactory(JFrog)是功能更全面的制品仓库管理平台,支持通用二进制存储和丰富的元数据管理。
Docker 安装:
# docker-compose.yml
version: '3.8'
services:
artifactory:
image: docker.bintray.io/jfrog/artifactory-oss:latest
container_name: artifactory
restart: always
ports:
- "8081:8081" # Web UI
- "8082:8082" # Router (Artifactory 7+)
volumes:
- artifactory-data:/var/opt/jfrog/artifactory
environment:
- JF_SHARED_NODE_ID=artifactory-01
ulimits:
nofile:
soft: 32000
hard: 40000
volumes:
artifactory-data:
driver: local核心特性:
- 通用制品管理:Maven、npm、Docker、PyPI、Go、Helm 等任意包格式
- Checksum 存储:基于 SHA-256 的二进制存储,相同内容自动去重
- 丰富的元数据:自定义属性、标签、注释
- AQL 查询语言:Artifactory Query Language 实现高级搜索
- Xray 集成:二进制漏洞扫描(需商业许可)
- 高可用架构:支持多节点集群和异地复制
5.2 Nexus vs Artifactory 对比
| 维度 | Nexus (Sonatype) | Artifactory (JFrog) |
|---|---|---|
| 开源版本 | Nexus Repository OSS | Artifactory OSS(功能有限) |
| 包格式支持 | Maven、npm、Docker、Raw、Yum、PyPI、Go | 全格式支持 + Conan、Helm、Conda 等 |
| 元数据管理 | 基础属性 | 完善的元数据系统和 AQL |
| 二进制去重 | 不支持 | 基于 Checksum 自动去重 |
| 安全扫描 | Sonatype IQ(商业) | JFrog Xray(商业) |
| 高可用 | 基础集群(商业) | 原生多节点集群 |
| 性能 | 轻量,资源占用较低 | 功能丰富,资源开销较高 |
| 学习曲线 | 较低 | 中等 |
| 常用场景 | 中小团队 Maven/npm 私服 | 大型企业全流程制品管理 |
| CI/CD 集成 | Jenkins、GitLab CI 基础集成 | 完善的 REST API 和平台集成 |
选型建议:
- 中小团队、仅需 Maven/npm 私服:选择 Nexus(OSS 即可满足)
- 大型团队、多语言多格式制品管理、需要安全扫描:选择 Artifactory
- 已有 Jenkins/GitLab 流水线但与 JFrog 平台深度集成需求:选择 Artifactory
六、部署流程最佳实践
6.1 版本管理
语义化版本规范(SemVer):
MAJOR.MINOR.PATCH
1. 2. 3- MAJOR:不兼容的 API 变更
- MINOR:向下兼容的功能新增
- PATCH:向下兼容的问题修复
版本号在制品仓库中的管理策略:
# Release 版本(Maven 示例)
1.0.0 — 首次正式发布
1.1.0 — 新增功能
1.1.1 — Bug 修复
2.0.0 — 重大重构
# Snapshot 版本(开发阶段)
1.0.0-SNAPSHOT
1.1.0-SNAPSHOTGit Tag 与制品版本对齐:
# 创建版本 Tag
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin v1.2.0
# 生成对应版本的制品
mvn versions:set -DnewVersion=1.2.0
mvn clean deploy变更日志管理(keep a changelog 规范):
# Changelog
## [1.2.0] - 2026-07-01
### Added
- 新增用户权限管理模块
### Changed
- 优化数据库查询性能
### Fixed
- 修复登录会话超时问题6.2 回滚策略
回滚的三种层级:
| 层级 | 操作 | 速度 | 适用场景 |
|---|---|---|---|
| 应用层 | 替换二进制包重启 | 1-2 分钟 | 代码级 Bug |
| 环境层 | 回退容器镜像版本 | 2-5 分钟 | 配置/依赖问题 |
| 数据层 | 数据库回滚迁移脚本 | 5-30 分钟 | Schema 变更导致的问题 |
实现可靠回滚的关键点:
- 保留历史版本:制品仓库中保留至少 30 天的历史版本
- 数据库向前兼容:数据库迁移脚本必须支持回滚操作
- 自动化回滚脚本:部署脚本必须配套回滚脚本(见第三节示例)
- 回滚测试:定期演练回滚流程,确保其可用
- 回滚通知:回滚操作需通知到相关团队并记录原因
回滚决策流程:
发现生产问题
|
├─ 问题影响面小 → 热修复(Hotfix)分支修复后正常部署
|
└─ 问题影响面大 → 立即回滚到上一个稳定版本
|
├─ 前端:CDN 切回旧版本静态资源
├─ 后端服务:执行回滚脚本,替换二进制并重启
└─ 数据库:执行回滚迁移脚本(如有)6.3 灰度发布
灰度发布(金丝雀发布)是降低发布风险的常用策略,详见 灰度发布与蓝绿部署。
基于网关的灰度方案:
# Nginx 灰度配置示例
upstream backend {
server 10.0.1.10:8080 weight=90; # 稳定版(90% 流量)
server 10.0.1.11:8080 weight=10; # 新版本(10% 流量)
}
# 基于 Header 的灰度(内部测试)
server {
if ($http_x_canary = "true") {
set $backend "10.0.1.11:8080";
}
proxy_pass http://$backend;
}灰度发布流程:
1. 新版本部署到少量实例(金丝雀组,5-10% 流量)
2. 监控关键指标(错误率、响应时间、业务转化率)
3. 稳定运行观察期(建议 30-60 分钟)
4. 逐步扩大流量比例(25% → 50% → 75% → 100%)
5. 全量发布完成,旧版本保留 N 个实例作为回滚后备灰度发布检查清单:
- [ ] 监控指标:错误率、P99 延迟、CPU/内存、GC 情况
- [ ] 业务指标:接口调用量、订单转化率、用户活跃度
- [ ] 日志告警:应用日志错误级别告警
- [ ] 数据库连接池使用率
- [ ] 第三方依赖可用性
- [ ] 回滚按钮/脚本就绪
6.4 持续交付流水线集成
推荐的部署流水线阶段:
代码提交 → 静态分析 → 单元测试 → 构建打包 →
制品上传(Nexus/Artifactory) → 部署到测试环境 →
集成测试 → 部署到预发布环境 → 冒烟测试 →
灰度发布 → 全量上线关键实践总结:
- 不可变制品:每次构建生成唯一版本号,构建后不再修改二进制
- 环境一致性:开发、测试、生产环境使用相同的基础镜像和配置模板
- 配置外部化:环境差异通过环境变量或配置中心注入
- 健康检查:每个部署步骤后执行自动化健康检查
- 可观测性:完善的日志、指标和链路追踪体系
- 部署原子性:单次部署要么全部成功,要么全部回滚
- 制品签名:对制品进行签名验证,防止篡改
- 权限最小化:部署账号仅授予部署所需的必要权限