CI/CD A 服务器(构建机)免密登录 B 服务器(目标部署机)完整操作

CI/CD A 服务器(构建机)免密登录 B 服务器(目标部署机)完整操作

原理:A 生成 ssh 密钥对,把公钥 放到 B 服务器~/.ssh/authorized_keys,A 用私钥登录 B,CI/CD 工具(Jenkins/GitLab CI 等)使用 A 上的私钥远程发布。 说明:A = 发起端,B = 目标服务器;操作全部在A 服务器执行,少量 B 端权限检查。

1. A 服务器:生成 SSH 密钥对(不要设置密码!CI/CD 自动化不能输密码)

复制代码
# 一路回车,不设置passphrase,直接生成密钥
ssh-keygen -t ed25519 -C "cicd-auto-deploy"
# 旧系统不支持ed25519就用rsa
# ssh-keygen -t rsa -b 4096 -C "cicd-auto-deploy"

生成文件默认路径:

  • 私钥:~/.ssh/id_ed25519(A 服务器保留,不能泄露,CI/CD 用这个)
  • 公钥:~/.ssh/id_ed25519.pub(复制这个内容到 B)

⚠️ 重点:密钥不要加密码,如果生成时输入了密码,CI 流水线执行 ssh/scp 会卡住等待手动输入密码。

2. A 服务器把公钥推送到 B 服务器(两种方式)

方式 1:ssh-copy-id(最简单,推荐)

复制代码
# B服务器用户名@B的IP
ssh-copy-id root@B服务器IP
# 非root用户示例:ssh-copy-id deploy@192.168.1.101

输入 B 服务器的登录密码,执行完成,公钥自动写入 B 的~/.ssh/authorized_keys。

方式 2:手动复制(服务器没有 ssh-copy-id 命令时用)

  1. 在 A 查看公钥内容:

    cat ~/.ssh/id_ed25519.pub

  2. 登录 B 服务器,创建 / 修改 ssh 目录:

    B服务器执行

    mkdir -p ~/.ssh
    chmod 700 ~/.ssh

    把上面A的公钥字符串追加到文件

    echo "粘贴A公钥全部内容" >> ~/.ssh/authorized_keys
    chmod 600 ~/.ssh/authorized_keys

权限非常关键:.ssh目录 700,authorized_keys 必须 600,权限过大 ssh 会拒绝免密登录。

3. 验证免密(A 服务器执行)

复制代码
ssh root@B服务器IP

✅ 成功:直接登录,不需要输入密码。 ❌ 失败:排查下面常见问题。

4. CI/CD 使用方案(两种常用)

方案 A:Jenkins Agent/CI 进程直接跑在 A 服务器

A 服务器上的 CI 进程使用当前用户下的私钥 ~/.ssh/id_ed25519,流水线脚本直接 ssh:

复制代码
# 流水线示例
ssh root@BIP "cd /data/app && git pull && restart app"

方案 B:CI 工具单独管理私钥(推荐,安全最佳实践)

不要把私钥明文放服务器文件,在 Jenkins/GitLab CI/ArgoCD 的密钥凭证 里,填入 A 服务器私钥(id_ed25519完整内容),流水线运行时动态加载私钥。

生产环境优先这种,避免私钥文件留在机器磁盘。

5. 常见失败排查清单

  1. B 服务器~/.ssh目录权限 >700 /authorized_keys 权限 > 600 → ssh 拒绝免密

  2. 公钥粘贴错误,有换行、空格多余字符

  3. B 服务器 sshd 配置禁止公钥登录: 登录 B,检查 sshd 配置 /etc/ssh/sshd_config

    PubkeyAuthentication yes
    AuthorizedKeysFile .ssh/authorized_keys

修改后重启 sshd:

复制代码
# centos
systemctl restart sshd
# ubuntu
systemctl restart ssh
  1. 防火墙:B 服务器 22 端口是否放行 A 服务器 IP

  2. SELinux 开启(CentOS/RHEL),会导致读取 authorized_keys 失败:

    临时关闭测试

    setenforce 0

相关推荐
坤坤子吖3 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
青瓦梦滋3 小时前
Redis主从复制
服务器·数据库·redis·缓存·bootstrap
Frankie_stand4 小时前
测试自动化实战指南:从脚本化、自动判据到 CI 集成的完整落地路径
android·ci/cd·自动化
沫璃染墨4 小时前
从零入门计算机网络系列(十八):TCP连接管理详解——从三次握手与四次挥手到TIME_WAIT机制
运维·服务器·网络·c++·网络协议·tcp/ip·tcp
Felven4 小时前
华为鲲鹏920s芯片serdestool工具使用说明
linux·运维·服务器·华为·鲲鹏920·serdestool
LabVIEW开发5 小时前
Omron PLC:接 LabVIEW 常踩的 5 个坑
服务器·网络·labview·labview知识·labview功能·labview程序
我是koten11 小时前
【运维杂谈】K8s遇到Terminating的名称空间删除不了怎么办?(解决方案亲测有效)
linux·运维·服务器·云原生·kubernetes·k8s·名称空间
爱吃奥利奥_wen1 天前
SQL Server 基础语法详解:从建库建表到约束与增删改查
服务器·数据库·oracle
Android系统攻城狮1 天前
Linux FFmpeg深度解析之avio_open调用流程与实战(三十八)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频
逐流人1 天前
手工建集群到全自动发布:k8s集群部署与DevOps流水线整合实战
ci/cd·云原生·kubernetes·云计算·devops