ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

大事记 - Jenkins 脚本部署报错 “Host key verification failed”

2022-08-02 09:31:48  阅读:227  来源: 互联网

标签:公钥 keys failed Host 报错 ssh Jenkins 服务器 应用服务器


// 这本是一个不应该出现的问题...

 

问题描述:

有一台用来部署项目的 Jenkins 服务器,然后新开了一台应用服务器,需要通过 Jenkins 将打包后的代码部署到应用服务器

但由于权限控制,我不知道两边服务器的密码,应用服务器(记为 dev.server)也只能通过跳板机访问

而 Jenkins 服务器(记为 jenkins.server)我没有任何办法访问,只能访问搭建好的 Jenkins 页面

在这样的背景下, 如果在 Jenkins 脚本中通过 ssh 直连应用服务器

ssh deploy@dev.server

就会出现 Host key verification failed 错误

 

 

分析原因:

其实原因很简单,通过 ssh 访问服务器是需要携带认证信息的,比如用户和密码,或者通过公钥免密登录

但这两个方案都不适用,因为我既不知道应用服务器的密码,也无法拿到 Jenkins 服务器的公钥

 

 

解决方案:

于是一次迂回大作战打响了

 

第一回合:Jenkinsfile 携带私钥

由于问题的本质是认证失败,我便打算通过 Jenkins credentials 来处理

首先在 Jenkins 中创建一个类型为 SSH Username with private key 的全局凭据

并将应用服务器的私钥粘贴进去

cat /root/.ssh/id_rsa

// 完整流程可以参考《Jenkins----凭据管理之配置ssh私钥》

然后需要调整 Jenkinsfile 脚本,用 withCredentials 方法将需要凭据的部分给包起来

比如我原本的脚本是:

stages {
  stage('Init ssh server'){
    steps {
      sh "ssh ${env._HOST_NAME} 'mkdir -p ${env._DEPLOY_PATH}'"
    }
  }
}

加入凭据之后就是:

stages {
  stage('Init ssh server'){
    steps {
      withCredentials(bindings: [
        sshUserPrivateKey(credentialsId: 'jenkins-ssh-key-xxxx', keyFileVariable: 'SSH_KEY_XXX')
      ]) {
        sh "ssh ${env._HOST_NAME} 'mkdir -p ${env._DEPLOY_PATH}'"
      }
    }
  }
}

// 建议使用 Jenkins 的片段生成器

配置好之后,我再次回放脚本

在我期待的目光下,Console Output 又抛出那个熟悉错误 Host key verification failed

 

第二回合:尝试配置免密登录

withCredentials 的方案失败之后,我再次梳理了一下整个流程,还是决定配置免密登录

我先用自己的电脑来测试,获取到本地的公钥 

cat ~/.ssh/id_rsa.pub

然后通过跳板机进入应用服务器,打开 authorized_keys 文件(若无则创建)

vi ~/.ssh/authorized_keys

然后将本地公钥粘贴到应用服务器 authorized_keys 的末尾


如果知道应用服务器的密码,上述过程还可以简化为一行命令:

ssh-copy-id user@hostname

运行之后需要输入对应用户的密码,然后就会把本地的公钥追加到 authorized_keys


此外还需要调整 ssh 的配置文件以及访问权限,详细配置可以参考《服务器配置免密码密钥登录》

不过运维已经完成了应用服务器的基本配置,在修改了 authorized_keys 之后,我就能在本地链接应用服务器了

 

眼见本地连接成功,我急忙腆着脸去找 Jenkins 服务器的管理员,费了好多口舌,他终于把 Jenkins 服务器的公钥给我了

随后我将 Jenkins 服务器的公钥也配到应用服务器的 authorized_keys 中,再次回放脚本

然而,结果依然是 Host key verification failed

同样的配置,为什么本地能正常访问,Jenkins 服务器却无法访问呢?

 

决战:本地直连 Jenkins 服务器

我想了许久,也没有想通本地与 Jenkins 服务器的差异

最后把心一横,决定想办法连上 Jenkins 服务器看看

可运维始终不肯开放跳板机权限,在我束手无措的时候,突然想到 Jenkinsfile 本身就是在 Jenkins 服务器上跑脚本

那么... 我岂不是可以通过 Jenkins 脚本,将我本地的公钥添加到 Jenkins 服务器的 authorized_keys 中,实现本地到 Jenkins 服务器的免密登录?

 

于是我在 Jenkins 脚本中添加了这一行命令:

sh "echo 'ssh-rsa xxxxxx' >> ~/.ssh/authorized_keys"

其中的 'ssh-rsa xxxxxx' 就是我本地公钥 id_rsa.pub

脚本跑完之后,我在本地使用 ssh 访问 Jenkins 服务器:

ssh root@jenkins.server

没有让我输入密码,这说明免密登录配置成功了。但有以下提示:

这个提示并不陌生, 首次连接服务器时都会有这个确认信息

确认之后,这个远程服务器的信息就会记录到本地的  ~/.ssh/known_hosts 中

 

我突然想到,Jenkins 服务器也是第一次访问应用服务器,会不会也有这个确认过程?而在脚本中无法确认,所以就会报错

此时我已经连上了 Jenkins 服务器,并且在应用服务器的 authorized_keys 中添加了 Jenkins 服务器的公钥

接着我在 Jenkins 服务器上,再次尝试通过 ssh 访问应用服务器,果然出现了上面的确认提示!

我双手颤抖着输入 yes,随后回到 Jenkins 部署页面,回放脚本

这次一路畅通,没有出现任何报错。看到脚本执行成功的绿色标记,我长舒了一口气

 


 

再来回溯整个问题,其实就是 known_hosts 导致的。如果解决了 known_hosts 的问题,使用 withCredentials 也是可以的

最后补充一篇《SSH之known_hosts文件》作为参考~

 

标签:公钥,keys,failed,Host,报错,ssh,Jenkins,服务器,应用服务器
来源: https://www.cnblogs.com/wisewrong/p/16539155.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有