暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

这就是ansible系列之三(adhoc模式入门实践)

埋头过坎 2020-11-20
748

    前面ansible系列的内容介绍了基础信息, 而番外篇则介绍了定位准备ansible环境过程中如何定位SSH带来的问题的全过程, 本文开始笔者将从实践的角度介绍ansible。

    

如图所示, ansible有两种常用的使用方式,分别是ad-hoc和palybook, 其中playbook又包含基本的playbook及复杂的使用roles组织的形式。 本文先介绍ad-hoc模式, 其它的放到后续的文章介绍。

    ad-hoc模式(http://ansible.com.cn/docs/intro_adhoc.html), 顾名思义,ad-hoc有单次的意思, 就是说通过命令行方式单次执行单个命令的一种使用模式。 它适用于用来快速地验证环境或者做一些比较简单的模式等场景。

    我们先来看下ansible支持的命令行, 采用的ansible版本信息如下:(约定, 主机/用户名等敏感信息约定进行脱敏, 采用<host-xx>、<user-xx>等形式来替代)

    (base) bash-4.1$ ansible --version
    ansible 2.9.6
    config file = /home/<user-xx>/.ansible.cfg
    configured module search path = ['/home/<user-xx>/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
    ansible python module location = home/<user-xx>/anaconda3/lib/python3.7/site-packages/ansible
    executable location = home/<user-xx>/anaconda3/bin/ansible
    python version = 3.7.4 (default, Aug 13 2019, 20:35:49) [GCC 7.3.0]

    ansible提供的命令如下:

      (base) bash-4.1$ ansible -h
      usage: ansible
        [-h# 帮助信息
        [--version# 版本信息
        [-v# 同--version
        [-b#以提权后的用户执行命令
        [--become-method BECOME_METHOD# 提权方法,通常是sudo
        [--become-user BECOME_USER# 切换帐户
        [-K# 请求sudo时密码
        [-i INVENTORY] # 指定主机文件路径
        [--list-hosts] # 列出主机清单
        [-l SUBSET# 指定一种模式, 用于过滤出有效主机
        [-P POLL_INTERVAL# 定期POLL_INTERVAL秒返回后台任务进度
        [-B SECONDS# 超过SECONDS秒后杀死后台执行命令
        [-o# 标准输出到一行
        [-t TREE# 输出信息到TREE目录下
        [-k] # 请求ssh密码
        [--private-key PRIVATE_KEY_FILE] # 私有密钥路径
        [-u REMOTE_USER# 登录远程被管节点的帐户
        [-c CONNECTION# 指定连接方式, 包括ssh、 pramiko等
        [-T TIMEOUT# SSH连接超时
        [--ssh-common-args SSH_COMMON_ARGS] # ssh通用参数
        [--sftp-extra-args SFTP_EXTRA_ARGS] # sftp额外参数
        [--scp-extra-args SCP_EXTRA_ARGS] # scp额外参数
        [--ssh-extra-args SSH_EXTRA_ARGS] # ssh额外参数
        [-C# 模拟执行但不会真正执行
        [--syntax-check# 语法检查,通用是playbook
        [-D# 比较文件、模板的区别
        [-e EXTRA_VARS]  # 额外变量
        [--vault-id VAULT_IDS# 用于加密的保险库ID?
        [--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES] 用于加密的保险库密码?
        [-f FORKS# 进程并发数量
        [-M MODULE_PATH] # 使用的模块的路径
        [--playbook-dir BASEDIR] # playbook的根路径
        [-a MODULE_ARGS# 模块参数 
        [-m MODULE_NAME# 选用模块
        pattern #与哪台主机进行交互


      先来看一下用于确认基础环境是否OK的常用的ping和command模块,如下:

        (base) bash-4.1$ ansible host_02 -m ping
        <host-xx> | SUCCESS => {
        "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": false,
        "ping": "pong"
        }
        (base) bash-4.1$ ansible host_02 -m command -a uptime
        <host-xx> | CHANGED | rc=0 >>
        22:38:09 up 11 days, 6:25, 1 user, load average: 1.79, 1.88, 1.75
        (base) bash-4.1$

        命令的基本格式是 ansible <主机信息> -m 模块信息 -a 模块参数

        第一条命令是使用ping模块测试连通性, 第二个命令是使用command模块(缺省模块,可以不显示指出来)执行uptime命令获取开机时间。

        ad-hoc模式的使用方式就是类似上面这样简单方便, 在特定的场景下起着重要的作用。

            之前定位SSH问题时, 曾经加上了-vvv  (3个v就够了, 4个更详细)来调试具体的交互过程, 同样地我们可以来看一下ad-hoc模式下, 整个过程大概都做了哪些事情,还是以上面ping命令为例子, 如下:

          (base) bash-4.1$ ansible host_02 -m ping -vvv
          #获取并显示当前ansible版本、模块等基础信息
          ansible 2.9.6
          config file = home/<user-xx>/.ansible.cfg
          configured module search path = ['/home/<user-xx>/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
          ansible python module location = home/<user-xx>/anaconda3/lib/python3.7/site-packages/ansible
          executable location = home/<user-xx>/anaconda3/bin/ansible
          python version = 3.7.4 (default, Aug 13 2019, 20:35:49) [GCC 7.3.0]
          # 读取配置文件
          Using home/<user-xx>/.ansible.cfg as config file
          host_list declined parsing home/<user-xx>/.ansible/hosts as it did not pass its verify_file() method
          script declined parsing home/<user-xx>/.ansible/hosts as it did not pass its verify_file() method
          auto declined parsing home/<user-xx>/.ansible/hosts as it did not pass its verify_file() method
          Parsed /home/<user-xx>/.ansible/hosts inventory source with ini plugin
          META: ran handlers
          # 与被管节点建立连接, 获取使用的帐户的home目录
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          ## 具体执行命令
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 <host-xx> '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
          ## 返回的结果
          <host-xx> (0, b'/home/<user-xx>\n', b'')
          # 在被管节点的home目录下建立tmp目录并创建本次会话需要的临时文件
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 <host-xx> '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425 `" && echo ansible-tmp-1605883636.6817505-49446542390425="` echo /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425 `" ) && sleep 0'"'"''
          <host-xx> (0, b'ansible-tmp-1605883636.6817505-49446542390425=/home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425\n', b'')
          <host-xx> Attempting python interpreter discovery
          # 查找被管节点的python执行环境信息
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 <host-xx> '/bin/sh -c '"'"'echo PLATFORM; uname; echo FOUND; command -v '"'"'"'"'"'"'"'"'/usr/bin/python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.5'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python2.6'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/libexec/platform-python'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/bin/python3'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python'"'"'"'"'"'"'"'"'; echo ENDFOUND && sleep 0'"'"''
          <host-xx> (0, b'PLATFORM\nLinux\nFOUND\n/usr/bin/python\n/usr/bin/python2.7\n/usr/bin/python\nENDFOUND\n', b'')
          # 查询被管节点的系统信息
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 <host-xx> '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
          <host-xx> (0, b'{"osrelease_content": "NAME=\\"CentOS Linux\\"\\nVERSION=\\"7 (Core)\\"\\nID=\\"centos\\"\\nID_LIKE=\\"rhel fedora\\"\\nVERSION_ID=\\"7\\"\\nPRETTY_NAME=\\"CentOS Linux 7 (Core)\\"\\nANSI_COLOR=\\"0;31\\"\\nCPE_NAME=\\"cpe:/o:centos:centos:7\\"\\nHOME_URL=\\"https://www.centos.org/\\"\\nBUG_REPORT_URL=\\"https://bugs.centos.org/\\"\\n\\nCENTOS_MANTISBT_PROJECT=\\"CentOS-7\\"\\nCENTOS_MANTISBT_PROJECT_VERSION=\\"7\\"\\nREDHAT_SUPPORT_PRODUCT=\\"centos\\"\\nREDHAT_SUPPORT_PRODUCT_VERSION=\\"7\\"\\n\\n", "platform_dist_result": ["centos", "7.5.1804", "Core"]}\n', b'')
          Using module file /home/<user-xx>/anaconda3/lib/python3.7/site-packages/ansible/modules/system/ping.py
          # 将要执行的任务放到临时目录, 并通过 sftp上传到被管节点
          <host-xx> PUT /home/<user-xx>/.ansible/tmp/ansible-local-32382jry0hz_b/tmp4uuzwwg7 TO /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425/AnsiballZ_ping.py
          <host-xx> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 '[<host-xx> ]'
          <host-xx> (0, b'sftp> put /home/<user-xx>/.ansible/tmp/ansible-local-32382jry0hz_b/tmp4uuzwwg7 /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425/AnsiballZ_ping.py\n', b'')
          # 给被管节点的任务文件添加执行权限
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 <host-xx> '/bin/sh -c '"'"'chmod u+x /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425/ /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425/AnsiballZ_ping.py && sleep 0'"'"''
          <host-xx> (0, b'', b'')
          # 在被管节点执行任务, 这里是ping
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 -tt <host-xx> '/bin/sh -c '"'"'/usr/bin/python /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425/AnsiballZ_ping.py && sleep 0'"'"''
          <host-xx> (0b'\r\n{"invocation": {"module_args": {"data": "pong"}}, "ping": "pong"}\r\n'b'Shared connection to <host-xx> closed.\r\n')
          # 删除被管节点的临时文件
          <host-xx> ESTABLISH SSH CONNECTION FOR USER: None
          <host-xx> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/disk3/<user-xx>/.ansible/cp/472fc29db8 <host-xx> '/bin/sh -c '"'"'rm -f -r /home/<user-xx>/.ansible/tmp/ansible-tmp-1605883636.6817505-49446542390425/ > /dev/null 2>&1 && sleep 0'"'"''
          <host-xx> (0, b'', b'')
          <host-xx> | SUCCESS => {
          "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": false,
          "invocation": {
          "module_args": {
          "data": "pong"
          }
          },
          "ping": "pong"
          }
          META: ran handlers
          META: ran handlers
          (base) bash-4.1$

          经历的步骤大概如下:

          a. 获取并显示当前ansible版本、模块等基础信息

          b. 读取配置文件

          c. 与被管节点建立连接, 获取使用的帐户的home目录

          d. 在被管节点的home目录下建立tmp目录并创建本次会话需要的临时文件

          e. 查询被管节点的python执行环境信息

          f.  查询被管节点的系统信息

          g. 将要执行的任务放到临时目录, 并通过 sftp上传到被管节点

          h. 给被管节点的任务文件添加执行权限

          i.  在被管节点执行任务, 这里是ping

          j.  删除被管节点的临时文件


              可以看到看起来一个简单的命令, 实际上发生了多次交互, 同时也看到缺省模式需要多次建立远程的ssh连接, 效率会相对比较低。可以通过SSH的长链接属性来减少SSH本身的消耗,另外可以通过pipelining配置来将多条命令压缩在一个SSH去执行。 

              总的来说, ad-hoc模式对用户来说还是非常方便的, 且在一些场景下很管用, 值得好好学习一下常用的命令。

          文章转载自埋头过坎,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论