zoukankan      html  css  js  c++  java
  • Ansible 免密登录与主机清单配置

    Ansible 通过 SSH 协议免密登录远程主机

    安装好 ansible 后,第一件事当然是连接上远程主机。

    1. 批量扫描主机指纹

    ansible 使用 ssh 协议登录远程主机进行操作,我想用过 ssh user@host 命令的都知道,首次登录远程主机时都会有如下提示:

    ryan@RYAN-MI-DESKTOP:~$ ssh user@github.com
    The authenticity of host 'github.com (13.250.177.223)' can't be established.
    RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
    Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
    Warning: Permanently added 'github.com,13.250.177.223' (RSA) to the list of known hosts.
    

    这里会要求你输入 yes 将主机指纹保存到本地,是一种安全措施,防止在遇到 DNS 污染或 IP 冲突等异常情况时,目标主机被冒名顶替。

    Ansible 默认情况下也会使用这个指纹对主机进行验证,因此我们希望能够快速地扫描出所有主机的指纹,这里使用 ssh-keyscan 命令:

    echo "
    192.168.58.131
    192.168.58.132
    192.168.58.133
    " > my-hosts
    ssh-keyscan -f my-hosts >> ~/.ssh/known_hosts
    # 或者添加 -H 参数,只保存主机 IP/域名的 hash 值,更安全
    ssh-keyscan -H -f my-hosts >> ~/.ssh/known_hosts
    

    2. 设置免密登录

    大量的远程主机都使用同一个密码提供 ssh 远程登录是很不安全的,一般都建议所有主机都只开启私钥登录,禁用密码登录。相关配置在主机的 /etc/ssh/sshd_config 中,详细配置方法请自行搜索。

    首先你需要在本地通过 ssh-keygen 命令生成好公私钥,默认使用 rsa 算法。

    如果你是使用的虚拟机,可以基于同一个 ova 镜像创建所有虚拟机,一开始就把运维账号(如 ops)和公钥打包在 ova 中。

    或者你可以在安装所有主机时,给所有远程主机都打开密码登录,然后通过 ansible 来批量添加 ssh 公钥到所有主机上,流程如下:

    首先编写一个名叫 add-sshkey.yml 的 playbook(playbook 将在后面详细介绍):

    ---
    - hosts: all  # 使用 inventory 中的所有主机
      gather_facts: false
      remote_user: root  # 使用这个账号登录远程主机
    
      tasks:
      - name: install ssh key
        authorized_key:  # 查看该 module 的文档:`ansible-doc authorized_key`
          user: root   # 给远程主机上的这个用户添加公钥。建议不要直接使用 root 账号(可以用 ops)
          key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"  # 也可以使用 url,这样公钥可以直接放 nginx 上挂着,更方便。
          state: present
    

    然后用如下命令运行这个 playbook,输入密码,就能在所有远程主机上添加好 ssh 公钥:

    # --inventory 指定主机清单,就用我们之前进行 ssh-keyscan 时用的那个文件就行
    # --ask-pass 可以让我们交互式地输入主机密码(所有主机的密码必须相同)
    ansible-playbook --inventory my-hosts --ask-pass ssh-addkey.yml 
    

    ansible 使用 /etc/ansible/hosts 文件作为它的默认 inventory 主机清单,但是我比较追求「基础设施即代码」,
    为了将这个 hosts 文档和相关代码/文档放在一起,提交到 git 仓库保存,我推荐每次都使用 -i [hosts_file] 的方式指定 inventory 主机清单。

    如果各主机的 ssh 端口、密码等参数不一致,就需要在 my-hosts 中设定更详细的参数,详见 Ansible Docs - intro_inventory

    3. 开始愉快地玩耍

    OK,现在免密登录就配好了,可以愉快地用 Ansible 玩耍了。
    简单地进行下测试:

    # ansible [pattern] -m [module] -u [remote user] -a "[module options]"
    # -u root     # 使用 root 账户登录远程主机,这个对应前面 playbook 中的 remote_user
    # all         # [pattern],all 表示选中 my-hosts 中的所有主机
    # -m [module] # 指定使用的 ansible 模块,默认使用 `command`,即在远程主机上执行 -a 参数中的命令 
    # -a "ls -al"    # 指定 module 的参数,这里是提供给 `command` 模块的参数。
    ansible -u root -i my-hosts all -a "ls -al"
    
    # 或者使用 ansible-console 交互式执行命令,更适合愉快地游玩hhh
    ansible-console -i my-hosts all -u root
    

    4. inventory 主机清单

    前面给出的 inventory 只是非常简单的 IP 地址列表。
    可如果我们不同的主机有不同的 ssh 端口号、ssh 密钥,或者不同的用户等等,那这样一个简单的 IP 列表就不够用了。

    为了解决这个问题,我们需要使用更高级的 inventory 语法,以对主机进行分类,对不同类别的主机配置不同的参数。

    ini 格式的配置举例如下:

    # 给服务器分组,组名只能用 [a-zA-Z0-9_]
    [databases]
    # 指定一个数字范围
    192.168.1.1[01:50]
    
    [k8s_cluster]
    # 指定一个字母表范围
    worker[01:30].k8s.local
    worker-[a:h].k8s.local
    
    # k8s-cluster 组的公用参数
    [k8s_cluster:vars]
    ntp_server=ntp.local
    proxy=proxy.local
    
    [app]
    # 给服务器指定别名(git),通过关键字参数指定其他参数
    git ansible_host=git.local ansible_port=225  ansible_ssh_private_key_file=<path/to/git-server-ssh>
    
    # 使用指定的账号密码(危险!)
    tester ansible_host=tester.local ansible_user=root ansible_password=xxx
    

    另外也可以使用 yaml 格式配置 inventory 主机清单,上面的 ini 配置写成 yaml 格式是这样的:

    ---
    databases:
      hosts: 192.168.1.1[01:50]
    
    k8s_cluster:
      hosts: # 没有别名的服务器
        worker[01:30].k8s.local:
        worker-[a:h].k8s.local:
      vars:  # 公共的参数
        ntp_server: ntp.local
        proxy: proxy.local
    app:
      hosts:
        git:  # 服务器别名
          ansible_host: git.local  # 如果未定义这个,默认以「别名」为 host。(在这里就是 git)
          ansible_port: 225
          ansible_ssh_private_key_file: <path/to/git-server-ssh>
        tester:
            ansible_host: tester.local
            ansible_user: root
            ansible_password: xxx  # 危险!尽量不要写明文密码
    

    写好配置后,可以通过如下命令验证并查看你的配置:

    ansible-inventory -i xxx.yml --list --yaml
    

    该命令会提示出你错误的配置,并且打印出最终得到的 yaml 配置内容。

    批量扫描主机指纹

    验证通过后,就可以通过 ansible/ansible-playbook/ansible-console 愉快地玩耍了么?很遗憾的是——不行。

    我们在前面使用不带任何参数的文档作为 inventory 时,因为 ssh-keyscan 也能解析它,所以我们很方便地就完成了主机指纹的批量扫描。

    但是现在我们的 inventory 变得很复杂了,ssh-keyscan 解析不了它了,该如何去批量扫描主机指纹呢?难道几十上百台服务器的指纹,我必须得手动一个个去添加?!

    答案是可以批量加,最简单有效的方法,是使用如下命令:

    # 使用环境变量 ANSIBLE_HOST_KEY_CHECKING 临时关闭主机指纹检查 
    ANSIBLE_HOST_KEY_CHECKING=false ansible -i inventory.yaml all -m ping
    

    经测试,不论成功与否,ping 模块都会自动将所有主机的指纹添加到 known_hosts 中。
    但是在 ping 的文档里没有讲到这个功能,这算是未定义行为。

    其他方法:

    1. 网上有很多文档会教你修改 /etc/ansible/ansible.cfg 以关闭指纹的验证,但是这是很危险的操作!你可能会连接到了黑客伪造的主机!
    2. 参考中有个问答,里面有人提供了一个 playbook 批量添加指纹,但是该方法不支持「主机别名」
      • 该 playbook 会将别名当作 host 解析,根本不理会 ansible_host 参数。
      • 另外测试发现它用到了 ansbile 的 local 连接,而这种用法在 wsl1(ubuntu) 上无法使用,会报权限错误。。
    3. 自己写个小脚本读取 ansible-inventory -i xxx.yml --list 输出的 json,将它转换成 ssh-keyscan 可读的文本。

    参考

  • 相关阅读:
    js中的this
    js中的call和apply
    自定义ListView无法响应点击事件
    Listview滑动超出显示区域时getChildAt(arg2)异常错误
    cocos2d-x在eclipse上搭建开发环境
    阿里云服务器CentOS 5.7(64位)安装配置LAMP服务器(Apache+PHP5+MySQL)
    如何在eclipse模拟器上运行下载好的apk程序
    百度RSS整理
    vtigercrm学习(二)
    Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果
  • 原文地址:https://www.cnblogs.com/kirito-c/p/12878009.html
Copyright © 2011-2022 走看看