用于将服务器从Google Cloud添加到config ssh的脚本

注解。 一篇关于非常简单的脚本的文章,该脚本从服务器列表中构成ssh Linux的配置。 在Ubuntu 18上测试,使用Goodle Cloud SDK,Python 2.7,Bash。


在我必须使用的服务器数量急剧增加之后,我意识到密码存储和CMDB不再提供像那些我只记得所有IP和详细信息的日子那样的操作访问权限。 也许是因为我们尚未掌握CMDB。 尽管如此,还是有必要解决通过SSH快速访问大量服务器的问题。


下一步-从Linux终端的角度来看(在Ubuntu 18上执行)。 也许它可以在其他发行版中运行,并且可能甚至在Windows上也有类似产品-我没有看过。


主要要求:


  • 容易重复。 几位管理员
    并且您需要能够为所有人配置相同的功能。 此外,我们允许远程工作-至少每台笔记本电脑都会有这种情况,但是碰巧您不在通常的“经过长期调试和调试”的计算机上工作。
  • 添加,删除,更改服务器的地址。 应该考虑这一点。

为此,我决定在ssh设置中使用别名主机,通过gcloud cli GCP客户端获取服务器列表,并使用Python 2.7自动化所有这些操作(因为它在Ubuntu中是默认设置,因此我决定研究它以处理数据)。 脚本本身带有下切的描述。


问题陈述


这个想法是这样的:以这样一种方式保留别名服务器及其当前地址的连接列表:仅使用名称即可建立连接。 同时,API会定期从GCP更新列表本身。


结果,有几个任务:


  1. 通过仅键入一个容易记住的名称来连接到主机(我们通常根据严格的规则来形成名称,因此只要知道客户端和系统就可以肯定地猜出服务器名称就足够了)。 名称可以是真实的(如果服务器是完全由我们创建的),也可以是cmdb中的别名(如果服务器是由客户端创建的,并且名称是根据客户端的规则分配的)。 无论如何,记住一个名字比住一个地址容易。 地址也会更改。
  2. 获取具有有效地址的当前主机列表。 因为 主要平台是GCP,而90%的服务器都在那儿,那么这个问题将通过它们的API来解决,而不是通过监视工具来解决。
  3. 按主机名搜索。 尽管它们更容易记住,但数量却在增加,并且内存不是无限的:)是的,新管理员更容易。
  4. 更新别名包-仅在地址更改时才地址。 为了放弃对所有捆绑包的完全重写,这是必需的。 这样不仅可以存储GCP服务器的捆绑软件。 到目前为止,这个问题尚未解决:(

解决方案说明


连接别名


这里的一切都很简单,不是我自己决定的。 Linux ssh实用程序在配置文件中支持别名配置。


文件位置:〜/ .ssh / config


我们使用的文件格式非常平庸,但实际上存在的可能性要大得多:


HOST alias_ HostName ip__- 

您可以在此处官方文档中阅读有关配置选项的更多信息。


进一步的步骤


  1. 使用不同的密钥连接到不同的主机组。 在安全方面有点偏执不会造成伤害。
  2. 提供此文件的备份,以防止意外更改和更新脚本错误。

搜索主机名


在这里,这个决定根本不属于我,而是属于本·洛博Ben Lobaugh,他的文章对此进行了描述。
简短地说,我使用sed,为了便于启动(参数中的很长规则),它通过别名缩写:


 alias sshhosts="sed -rn 's/^\s*HOST\s+(.*)\s*/\1/ip' ~/.ssh/config" 

如果您需要通过名称部分查找主机,那么该脚本将由grep实用程序完美地补充,因此结果如下所示:


 sshhost | grep '---' 

例如,还有其他选项,如此处所述。


主机名自动完成


感谢onix74的解决方案!
将行添加到〜/ .bash_completion:


 complete -W "$(grep "^HOST " ~/.ssh/config | grep -v "\*" | sed 's/[^ ]* *\(.*\)/\1/')" ssh 

对于ssh命令,自动完成将根据别名服务器列表运行。 即 您可以使用ssh代替ssh服务器的名称。 它在bash中工作。

进一步的步骤


我计划将主机分成几组,以便您可以选择特定客户端或特定应用程序的所有服务器。 对于批量脚本执行和Ansible连接而言,此功能似乎很有趣。 以及为不同的组创建不同的连接详细信息。 但是它到底有多有意义仍然有待观察。


从GCP获取主机列表


在此步骤中,除了参数设置外,其他一切都非常简单(尽管这里只是经验问题)。 我决定使用GCloud SDK来获取数据,因为 尽管我很少使用它,但是我想这将使我越来越少地使用图形界面,从而大大简化了管理程序。 因此,主要论据是获得经验。
可能可以使用curl和GCP REST API进行相同的操作,然后该解决方案将变得更加通用(因为GCloud SDK需要单独的安装和初始化,虽然并不需要那么复杂,但是仍然需要)。


为了获得必要的信息,我必须使用json格式。 尽管这大大简化了对收到答案的进一步处理,但它使人们对在SDK中设置格式设置参数有所考虑。
结果,我收到以下命令:


 gcloud compute instances list --filter="status:running" --format="json(name, status, networkInterfaces[].accessConfigs[])" 

它仅返回当前活动的服务器(连接其他服务器没有意义),并提供有关其名称和网络接口的信息。 到目前为止,每台服务器仅使用一个外部接口。


最终结果到达json:


 [ ---...---- { "name": "-", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "ip-", "networkTier": "PREMIUM", "type": "ONE_TO_ONE_NAT" } ] } ], "status": "RUNNING" }, ----...--- ] 

进一步的步骤


找到一种格式,其输出将最小化甚至消除后续处理。


基于GCP数据创建别名列表的脚本


该脚本是用python 2.7编写的,其原因有两个:


  1. 我决定研究它以处理数据。
  2. 在大多数运行linux的系统上,默认情况下python 2.7是-在其他地方使用它不会有问题。 鉴于即使现在赢了,也允许您放置第二个系统并使用Ubuntu作为终端。

算法如下:


  1. 我们使用SDK从Google Cloud获取服务器列表,并从python启动控制台中的命令执行。
  2. 我们将结果JSON解析为python友好类型。
  3. 我们以设置ssh所需的格式提供输出(如果需要,脚本输出将重定向到〜/ .ssh / config或某些中间文件)。

查看脚本
 #!/usr/bin/python import commands import json sComputeListOutput = commands.getoutput('gcloud compute instances list --filter="status:running" --format="json(name, status, networkInterfaces[].accessConfigs[])" ') s = json.loads(sComputeListOutput) for server in s: print 'HOST ',server['name'] print ' HostName ',server['networkInterfaces'][0]['accessConfigs'][0]['natIP'] 

仅更新修改的数据


此任务仍在进行中。 我计划在同一脚本中读取ssh / config文件,将其与接收到的值进行比较,然后将整个结果写回。 或者单独生成一个新文件,并使用某种差异进行比较-这将使您可以手动确认所有更改。

Source: https://habr.com/ru/post/zh-CN484500/


All Articles