微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

 

问题描述:

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

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

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

@H_404_22@

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

ssh [email protected]

就会出现 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 [email protected]

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

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

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

 

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

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

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

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

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

 


 

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

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

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐