GitLab CI作业中ssh-keyscan无法获取EC2实例公钥问题
问题背景
- 搭建面向AWS EC2实例部署Docker容器的GitLab CI/CD流水线时,参考SSH部署方案实现流程,作业执行
ssh-keyscan <目标地址>步骤异常失败,报错为ERROR: Job failed: exit code 1。 - 已验证本地环境执行
ssh-keyscan <目标EC2的IPv4 DNS或IP>可正常返回结果,但在独立的Ubuntu EC2实例上执行相同命令无任何输出。
现有配置
流水线配置片段
... deploy-to-staging: image: docker:20.10.14 stage: deploy to staging needs: ["docker-stuff"] before_script: - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )' - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - - mkdir -p ~/.ssh - chmod 700 ~/.ssh - ssh-keyscan $EC2_IP >> ~/.ssh/known_hosts - chmod 644 ~/.ssh/known_hosts ...
GitLab CI已配置变量
SSH_PRIVATE_KEY:.pem格式的EC2密钥对私钥EC2_IP:EC2实例的公网IPv4 DNS地址
排查思路与解决方案
ssh-keyscan无输出直接返回退出码1,本质是无法和目标地址的22端口建立TCP连接,按以下优先级排查即可:
优先排查网络访问控制配置(90%以上的同类问题都是这个原因)
本地能正常执行ssh-keyscan,仅EC2环境、GitLab Runner环境执行失败,核心原因是访问源IP不在目标EC2的白名单里:- 检查目标EC2绑定的安全组入站规则,确认GitLab Runner的公网出口IP、做测试的Ubuntu EC2的IP,已经被加入22端口的允许列表;如果暂时查不到Runner出口IP,可以临时加0.0.0.0/0的22端口入站规则做连通性测试,验证通过后再收紧规则。
- 如果GitLab Runner部署在AWS私有子网,确认子网关联了NAT网关具备公网访问能力,或存在到目标EC2的可达路由。
- 登录目标EC2检查本地防火墙规则,Ubuntu默认的ufw如果处于开启状态,需要确认22端口已放通,可执行
ufw status查看规则,未放通则执行ufw allow 22添加规则。
增加调试参数定位具体错误
替换流水线中原有的ssh-keyscan行,增加调试日志和超时时间,拿到明确的错误信息:# 替换原有ssh-keyscan行,-v打印调试日志,-T设置10秒连接超时 - ssh-keyscan -v -T 10 $EC2_IP >> ~/.ssh/known_hosts若日志显示
Connection timed out仍为网络连通性问题;若显示Connection refused,则是目标EC2的sshd服务未启动、或SSH服务未监听默认22端口。检查目标EC2的SSH服务状态
登录目标EC2执行以下命令校验服务状态:# 检查sshd服务运行状态 systemctl status sshd # 检查SSH服务端口监听情况 ss -tulpn | grep sshd如果SSH服务自定义了非22的端口,需要给
ssh-keyscan增加-p <自定义端口号>参数指定端口。临时绕过主机密钥校验(仅用于测试环境快速验证,不推荐生产长期使用)
如果需要先跑通流水线流程,可以暂时跳过主机密钥校验步骤,注释掉原有ssh-keyscan和known_hosts权限配置行,添加以下配置:- echo -e "Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null" > ~/.ssh/config - chmod 600 ~/.ssh/config流程跑通后建议恢复主机密钥校验逻辑,避免遭遇中间人攻击的安全风险。
内容的提问来源于stack exchange,提问作者jeldzinski
相关产品推荐
相关产品推荐

