zoukankan      html  css  js  c++  java
  • 自动化运维工具:ansible

    1、运维自动化发展历程及技术应用
      本地部署:On-Premises
      基础设施即服务:IaaS(Infrastructure as a Service)
      平台即服务:PaaS(Platform as a Service)
      软件即服务:SaaS(Software as a Service)

    2、自动化运维应用场景
      1>文件传输
      2>命令执行
        应用部署
        配置管理
        任务流编排
      3>程序发布
        预发布:新版本的代码先发布到服务器(跟线上环境完全相同,只是未接入调度器)
        程序发布:不能导致系统故障或造成系统完全不可用;不能影响用户体验
        灰度发布:先发布1/10的服务器,面向少量精准用户,在逐渐增多
        发布路径:
          /nginx1.1
          nginx(软链接)
          /nginx1.2
          在调度机上将一台real-server置为down,停止旧版本的服务,删除旧的软链接,启动新的服务,创建新的软链接,在调度器启用这一批服务器
        自动化灰度发布:脚本、发布平台

    3、ansible特性
      1>模块化,有Paramiko,PyYAML,jinja2(模块语言)三个关键模块,支持自定义模块
      2>基于Python语言实现,部署简单,基于python和ssh(默认安装),安全、agentless(无代理,不需要配置代理,主控端直接控制被控端)
      3>支持playbook编排任务
      4>幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
      5>无需代理不依赖PKI(无需ssl)
      6>可使用任何编程语言写模块
      7>YAML格式,编排任务,支持丰富的数据结构
      8>较强大的多层解决方案(角色)

    4、ansible架构及工作原理

     

    5、ansible主要组成部分
      ansible playbook:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
      inventory:Ansible管理主机的清单/etc/anaible/hosts
      modules:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
      plugins:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
      API:供第三方程序调用的应用程序编程接口
      ANSIBLE:组合INVENTORY、API、 MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具

    6、Ansible命令执行来源:
      USER,普通用户,即SYSTEM ADMINISTRATOR
      CMDB (配置管理数据库) API 调用
      PUBLIC/PRIVATE CLOUD API调用
      USER → Ansible Playbook → Ansibile

    7、利用ansible实现管理的方式:
      Ad-Hoc即ansible命令,主要用于临时命令使用场景
      Ansible-playbook主要用于长期规划好的,大型项目的场景,需要有前提的规划
      Ansible-playbook (剧本) 执行过程:
        将已有编排好的任务集写入Ansible-Playbook
        通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行
      Ansible主要操作对象:
        HOSTS主机
        NETWORKING网络设备
      注意事项:
      ➢执行ansible的主机一般称为主控端,中控,master或堡垒机
      ➢主控端Python版本需要2.6或以上
      ➢被控端Python版本小于2.4需要安装python-simplejson
      ➢被控端如开启SELinux需要安装libselinux-python
      ➢windows不能做为主控端

    8、安装(本机采用rpm安装,实验)
      1>rpm包安装:EPEL源

    yum install ansible -y

      2>编译安装:

    yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
    tar xf ansible-1.5.4.tar.gz
    cd ansible-1.5.4
    python setup.py build
    python setup.py install
    mkdir /etc/ansible
    cp -r examples/* /etc/ansible

      3>Git方式:

    git clone git://github.com/ansible/ansible.git --recursive
    cd ./ansible
    source ./hacking/env-setup

      4>pip安装:pip是安装Python包的管理器,类似yum

    yum install python-pip python-devel
    yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
    pip install --upgrade pip
    pip install ansible --upgrade

      5>确认安装: ansible --version

    9、相关文件
      1>配置文件
        /etc/ansible/ansible.cfg    主配置文件,配置ansible工作特性
        /etc/ansible/hosts             主机清单
        /etc/ansible/roles/             存放角色的目录
      2>程序
        /usr/bin/ansible                 主程序,临时命令执行工具
        /usr/bin/ansible-doc           查看配置文档,模块功能查看工具
        /usr/bin/ansible-galaxy      下载/上传优秀代码或Roles模块的官网平台
        /usr/bin/ansible-playbook  定制自动化任务,编排剧本工具/usr/bin/ansible-pull远程执行命令的工具
        /usr/bin/ansible-vault         文件加密工具
        /usr/bin/ansible-console    基于Console界面与用户交互的执行工具
      3>主机清单inventory
        Inventory主机清单
        ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名
        默认的inventory file为/etc/ansible/hosts
        inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成

      4>/etc/ansible/hosts文件格式
      inventory文件遵循INI文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明

    [root@ansible ~]#vim /etc/ansible/hosts

       也可以配置域名解析,使用域名代替ip,如果ssh默认端口号有改动不是22端口,则 ip/域名:端口

      Ansible配置文件
      Ansible配置文件/etc/ansible/ansible.cfg (一般保持默认)

    [defaults]
    #inventory = /etc/ansible/hosts     #主机列表配置文件
    #library = /usr/share/my_modules/   #库文件存放目录
    #remote_tmp = $HOME/.ansible/tmp    #临时py命令文件存放在远程主机目录
    #local_tmp = $HOME/.ansible/tmp     #本机的临时命令执行目录
    #forks = 5                          #默认并发数
    #sudo_user = root                   #默认sudo用户
    #ask_sudo_pass = True               #每次执行ansible命令是否询问ssh密码
    #ask_pass = True
    #remote_port = 22
    #host_key_checking = False          #检查对应服务器的host_key,建议取消注释,要不然得先建立连接(/root/.ssh/known_hosts)Ansible才能连接成功
    #log_path=/var/log/ansible.log      #日志文件

      Ansible配置文件保持默认,建议开启:host_key_checking = False,log_path=/var/log/ansible.log

    10、Ansible系列命令
      ansible ansible-doc ansible-playbook ansible-vault ansible-console ansible-galaxy ansible-pull
      ansible-doc 显示模块帮助
      ansible-doc [options] [module...]
        -a 显示所有模块的文档
        -l,--list 列出可用模块
        -s,--snippet显示指定模块的playbook片段
      示例:

    ansible-doc -l      列出所有模块
    ansible-doc ping    查看指定模块帮助用法
    ansible-doc -s ping 查看指定模块帮助用法(短帮助)

      ansible通过ssh实现配置管理、应用部署、任务执行等功能,建议配置ansible端能基于密钥认证的方式联系各被管理节点
      ansible <host-pattern> [-m module_name] [-a args]
        --version显示版本
        -m module指定模块,默认为command
        -v详细过程-vv -vvv更详细
        --list-hosts显示主机列表,可简写-list
        -k, --ask-pass提示输入ssh连接密码,默认Key验证
        -K, --ask-become-pass提示输入sudo时的口令
        -C, --check检查,并不执行
        -T, --timeout=TIMEOUT执行命令的超时时间,默认10s
        -u, --user=REMOTE_USER执行远程执行的用户
        -b, --become代替旧版的sudo切换

    [root@ansible ~]#ansible 192.168.100.10 -m ping -k    #-m:指定模块,-k:指定k口令验证
    SSH password: 
    192.168.100.10 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    
    [root@ansible ~]#ansible all --list    #列出主机列表
      hosts (2):
        192.168.100.10
        192.168.100.20
    [root@ansible ~]#ansible all -m ping -u yang -k    #以yang用户身份执行ping
    SSH password: 
    192.168.100.20 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    192.168.100.10 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    [root@ansible ~]#ansible all -k -u yang -b -K -m command -a 'ls /root'    #以yang用户身份执行ls /root,-b即sudo切换身份,-K输入sudo时的口令
    SSH password: 
    BECOME password[defaults to SSH password]: 
    192.168.100.20 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    jdk-8u221-linux-x64.tar.gz
    192.168.100.10 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    
    
    设置基于key验证:
    [root@ansible ~]#ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/root/.ssh/id_rsa):     #设置空,为了安全建议进行进一步设置
    Enter passphrase (empty for no passphrase):                  #设置空
    Enter same passphrase again:                                 #设置空
    Your identification has been saved in /root/.ssh/id_rsa.
    Your public key has been saved in /root/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:nHRFKqBQ/jceNpkOFfoVLKbE+hVchYw25FKG8m3eFeM root@ansible.localdomain
    The key's randomart image is:
    +---[RSA 2048]----+
    |  .....+==o++    |
    |   o..+*O.++o    |
    |    o=o==++. o   |
    |    ..o*+B  E    |
    |     .o+S. .     |
    |      .*.+.      |
    |        o        |
    |                 |
    |                 |
    +----[SHA256]-----+
    [root@ansible ~]#ssh-copy-id 192.168.100.10    #拷贝至192.168.100.10
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    root@192.168.100.10's password: 
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh '192.168.100.10'"
    and check to make sure that only the key(s) you wanted were added.
    
    [root@ansible ~]#ssh-copy-id 192.168.100.20    #拷贝至192.168.100.20
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    root@192.168.100.20's password: 
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh '192.168.100.20'"
    and check to make sure that only the key(s) you wanted were added.
    [root@ansible
    ~]#ansible all -m ping #基于key验证不需要在输入key口令 192.168.100.20 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 192.168.100.10 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" }


      ansible的Host-pattern
      匹配主机的列表
      All:表示所有Inventory中的所有主机

    [root@ansible ~]#ansible all --list
      hosts (2):
        192.168.100.10
        192.168.100.20

       *:通配符
      ansible "*" -m ping
      ansible 192.168.100.* -m ping
      ansible "*server" -m ping

    [root@ansible ~]#ansible *server -m ping
    192.168.100.20 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    192.168.100.10 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }

      或关系
      ansible "webserver:dbserver" -m ping
      ansible "192.168.100.10:192.168.100.20" -m ping

    [root@ansible ~]#ansible "webserver:dbserver" -m ping
    192.168.100.20 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }
    192.168.100.10 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "ping": "pong"
    }

      逻辑与
      ansible "webserver:&dbserver" -m ping
      在webserver组并且在dbserver组中的主机
      逻辑非
      ansible 'webserver:!dbserver' -m ping
      在webserver组,但不在dbserver组中的主机
      注意:此处为单引号
      综合逻辑
      ansible 'webserver:dbserver:&appserver:!ftpserver' -m ping
      正则表达式
      ansible "webserver:&dbserver" -m ping
      ansible“ ~(web|db).*.yang.com”-m ping

    11、Ansible命令执行过程
      1.加载自己的配置文件默认/etc/ansible/ansible.cfg
      2.加载自己对应的模块文件,如command
      3.通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
      4.给文件+x执行
      5.执行并返回结果
      6.删除临时py文件,sleep 0退出
      执行状态:
        绿色:执行成功并且不需要做改变的操作
        黄色:执行成功并且对目标主机做变更
        红色:执行失败

    12、Ansible常见模块

      各种模块的使用,可以ansible-doc -s service先查看帮助,再进行使用
      1>command模块:在远程主机执行命令,默认模块,可忽略-m选项

    [root@ansible ~]#ansible all -m command -a 'hostname'
    192.168.100.20 | CHANGED | rc=0 >>
    node-2
    192.168.100.10 | CHANGED | rc=0 >>
    node-1
    [root@ansible ~]#ansible all -m command -a 'echo yang | passwd --stdin yang'
    192.168.100.20 | CHANGED | rc=0 >>
    yang | passwd --stdin yang    #没有成功,当字符串打印出来了
    192.168.100.10 | CHANGED | rc=0 >>
    yang | passwd --stdin yang    #没有成功,当字符串打印出来了

      此命令不支持$VARNAME < > | ; & 等,需要使用shelI模块实现

      2>shell模块:和command相似,用shell执行命令

    [root@ansible ~]#ansible all -m shell -a 'echo yang | passwd --stdin yang'
    192.168.100.20 | CHANGED | rc=0 >>
    更改用户 yang 的密码 。
    passwd:所有的身份验证令牌已经成功更新。
    192.168.100.10 | CHANGED | rc=0 >>
    更改用户 yang 的密码 。
    passwd:所有的身份验证令牌已经成功更新。

      调用bash执行命令类似cat /tmp/stanley.md | awk -F'|' '{print $1,$2}' &>/tmp/example.txt 这些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本,copy到远程,执行,再把需要的结果拉回执行命令的机器

      3>script模块:运行脚本
      -a "/PATH/TO/SCRIPT_FILE"

    [root@ansible ~]#./hello.sh     #当前Ansible机器上的脚本:实现打印hello,输出主机名
    hello
    my hostname is ansible.localdomain
    [root@ansible ~]#ansible all -m script -a '/root/hello.sh'
    192.168.100.20 | CHANGED => {
        "changed": true, 
        "rc": 0, 
        "stderr": "Shared connection to 192.168.100.20 closed.
    ", 
        "stderr_lines": [
            "Shared connection to 192.168.100.20 closed."
        ], 
        "stdout": "hello
    my hostname is node2.localdomain
    ", 
        "stdout_lines": [
            "hello", 
            "my hostname is node2.localdomain"
        ]
    }
    192.168.100.10 | CHANGED => {
        "changed": true, 
        "rc": 0, 
        "stderr": "Shared connection to 192.168.100.10 closed.
    ", 
        "stderr_lines": [
            "Shared connection to 192.168.100.10 closed."
        ], 
        "stdout": "hello
    my hostname is node1.localdomain
    ", 
        "stdout_lines": [
            "hello", 
            "my hostname is node1.localdomain"
        ]
    }

      4>copy模块:从服务器复制文件到客户端

    [root@ansible ~]#ansible all -m copy -a 'src=/root/hello.sh dest=/root/'    #src:指定源文件  dest:指定目标文件存放目录
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00", 
        "dest": "/root/hello.sh", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "c426adca4193658a2183f59d726cc2dc", 
        "mode": "0644", 
        "owner": "root", 
        "size": 58, 
        "src": "/root/.ansible/tmp/ansible-tmp-1584450232.18-80008690840068/source", 
        "state": "file", 
        "uid": 0
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00", 
        "dest": "/root/hello.sh", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "c426adca4193658a2183f59d726cc2dc", 
        "mode": "0644", 
        "owner": "root", 
        "size": 58, 
        "src": "/root/.ansible/tmp/ansible-tmp-1584450232.14-44687748938829/source", 
        "state": "file", 
        "uid": 0
    }

    node1节点查看:
    [root@node1 ~]# ll
    total 8
    -rw-------. 1 root root 1557 Sep 28 22:49 anaconda-ks.cfg
    -rw-r--r--  1 root root   58 Mar 17 21:03 hello.sh

    删除node节点的hello.sh文件,重新创建个同名文件,再使用ansible复制,如目标存在,默认覆盖,此处backup=yes指定先备份(ansible有幂等性特点)
    [root@ansible ~]#ansible all -m copy -a 'src=/root/hello.sh dest=/root/ backup=yes mode=+x' #src:指定源文件 dest:指定目标文件存放目录 backup=yes:如果目标文件存在则进行备份
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00",
        "dest": "/root/hello.sh",
        "gid": 0,
        "group": "root",
        "mode": "0755",
        "owner": "root",
        "path": "/root/hello.sh",
        "size": 58,
        "state": "file",
        "uid": 0
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00",
        "dest": "/root/hello.sh",
        "gid": 0,
        "group": "root",
        "mode": "0755",
        "owner": "root",
        "path": "/root/hello.sh",
        "size": 58,
        "state": "file",
        "uid": 0
    }


    [root@ansible ~]#ansible all -a 'ls /root/'
    192.168.100.20 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    hello.sh
    hello.sh.4160.2020-03-17@21:14:23~ #原文件存在,被备份
    jdk-8u221-linux-x64.tar.gz
    192.168.100.10 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    hello.sh
    hello.sh.4604.2020-03-17@21:14:22~ #原文件存在,被备份

      5>Fetch模块:从客户端取文件至服务器端,copy相反,目录可先tar

    [root@ansible ~]#mkdir /data    #先创建一个/data目录,存放抓取过来的文件
    [root@ansible ~]#ansible all -m fetch -a 'src=/root/anaconda-ks.cfg dest=/data'
    192.168.100.10 | CHANGED => {
        "changed": true, 
        "checksum": "c324508ffa651d64f4fa6286fb74ec438e283b3b", 
        "dest": "/data/192.168.100.10/root/anaconda-ks.cfg", 
        "md5sum": "b1c0bd6a556fac4e120fddcc7d1124df", 
        "remote_checksum": "c324508ffa651d64f4fa6286fb74ec438e283b3b", 
        "remote_md5sum": null
    }
    192.168.100.20 | CHANGED => {
        "changed": true, 
        "checksum": "4a2e5b1e34c5496d9dcebbb9a1b7ece8b6b03950", 
        "dest": "/data/192.168.100.20/root/anaconda-ks.cfg", 
        "md5sum": "32435d070271e8018672e21ae7c2acbb", 
        "remote_checksum": "4a2e5b1e34c5496d9dcebbb9a1b7ece8b6b03950", 
        "remote_md5sum": null
    }
    [root@ansible ~]#tree /data/
    /data/
    ├── 192.168.100.10
    │   └── root
    │       └── anaconda-ks.cfg
    └── 192.168.100.20
        └── root
            └── anaconda-ks.cfg
    
    4 directories, 2 files

      6>File模块:设置文件属性

    [root@ansible ~]#ansible all -a 'ls /data'
    192.168.100.20 | FAILED | rc=2 >>
    ls: 无法访问/data: 没有那个文件或目录non-zero return code
    192.168.100.10 | FAILED | rc=2 >>
    ls: 无法访问/data: 没有那个文件或目录non-zero return code
    [root@ansible ~]#ansible all -m shell -a 'mkdir /data'    #可以看到我们使用shell,创建目录,建议我们使用file模块创建目录
    [WARNING]: Consider using the file module with state=directory rather than running
    'mkdir'.  If you need to use command because file is insufficient you can add
    'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
    to get rid of this message.
    192.168.100.10 | CHANGED | rc=0 >>
    
    192.168.100.20 | CHANGED | rc=0 >>
    
    [root@ansible ~]#ansible all -a 'ls /data'
    192.168.100.20 | CHANGED | rc=0 >>
    
    192.168.100.10 | CHANGED | rc=0 >>
    
    [root@ansible ~]#ansible all -m file -a 'name=/data/f1 state=touch'    #在创建的/data目录下,使用file模块创建文件,state=touch:状态=touch 创建
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "dest": "/data/f1", 
        "gid": 0, 
        "group": "root", 
        "mode": "0644", 
        "owner": "root", 
        "size": 0, 
        "state": "file", 
        "uid": 0
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "dest": "/data/f1", 
        "gid": 0, 
        "group": "root", 
        "mode": "0644", 
        "owner": "root", 
        "size": 0, 
        "state": "file", 
        "uid": 0
    }
    [root@ansible ~]#ansible all -a 'ls /data'
    192.168.100.20 | CHANGED | rc=0 >>
    f1
    192.168.100.10 | CHANGED | rc=0 >>
    f1
    [root@ansible ~]#ansible all -m file -a 'name=/data/f1 state=absent'    #absent删除文件
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "path": "/data/f1", 
        "state": "absent"
    }
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "path": "/data/f1", 
        "state": "absent"
    }
    [root@ansible ~]#ansible all -a 'ls /data'
    192.168.100.20 | CHANGED | rc=0 >>
    
    192.168.100.10 | CHANGED | rc=0 >>
    
    [root@ansible ~]#ansible all -m file -a 'name=/data/dir1 state=directory'    #directory创建目录
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 0, 
        "group": "root", 
        "mode": "0755", 
        "owner": "root", 
        "path": "/data/dir1", 
        "size": 6, 
        "state": "directory", 
        "uid": 0
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 0, 
        "group": "root", 
        "mode": "0755", 
        "owner": "root", 
        "path": "/data/dir1", 
        "size": 6, 
        "state": "directory", 
        "uid": 0
    }
    [root@ansible ~]#ansible all -a 'ls -l /data'
    192.168.100.20 | CHANGED | rc=0 >>
    总用量 0
    drwxr-xr-x 2 root root 6 3月  17 22:29 dir1
    192.168.100.10 | CHANGED | rc=0 >>
    总用量 0
    drwxr-xr-x 2 root root 6 3月  17 22:29 dir1
    [root@ansible ~]#ansible all -m file -a 'name=/data/dir1 state=absent'    #删除目录
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "path": "/data/dir1", 
        "state": "absent"
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "path": "/data/dir1", 
        "state": "absent"
    }
    [root@ansible ~]#ansible all -a 'ls /data'
    192.168.100.20 | CHANGED | rc=0 >>
    
    192.168.100.10 | CHANGED | rc=0 >>
    
    [root@ansible ~]#ansible all -m file -a 'src=/etc/fstab dest=/data/fstab.link state=link'    #src,dest指定源文件,目标文件,link:创建软链接
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "dest": "/data/fstab.link", 
        "gid": 0, 
        "group": "root", 
        "mode": "0777", 
        "owner": "root", 
        "size": 10, 
        "src": "/etc/fstab", 
        "state": "link", 
        "uid": 0
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "dest": "/data/fstab.link", 
        "gid": 0, 
        "group": "root", 
        "mode": "0777", 
        "owner": "root", 
        "size": 10, 
        "src": "/etc/fstab", 
        "state": "link", 
        "uid": 0
    }
    [root@ansible ~]#ansible all -a 'ls -l /data'
    192.168.100.20 | CHANGED | rc=0 >>
    总用量 0
    lrwxrwxrwx 1 root root 10 3月  17 22:31 fstab.link -> /etc/fstab
    192.168.100.10 | CHANGED | rc=0 >>
    总用量 0
    lrwxrwxrwx 1 root root 10 3月  17 22:31 fstab.link -> /etc/fstab
    [root@ansible ~]#ansible all -m file -a 'dest=/data/fstab.link state=absent'    #删除软链接
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "path": "/data/fstab.link", 
        "state": "absent"
    }
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "path": "/data/fstab.link", 
        "state": "absent"
    }
    [root@ansible ~]#ansible all -a 'ls -l /data'
    192.168.100.20 | CHANGED | rc=0 >>
    总用量 0
    192.168.100.10 | CHANGED | rc=0 >>
    总用量 0

      7>Hostname模块:管理主机名

    node-1节点先查看主机名:
    [root@node-1 ~]# hostname
    node-1
    
    [root@ansible ~]#ansible 192.168.100.10 -m hostname -a 'name=node1'
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "ansible_domain": "", 
            "ansible_fqdn": "node1", 
            "ansible_hostname": "node1", 
            "ansible_nodename": "node1", 
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "name": "node1"
    }
    
    node-1节点再查看主机名:exit退出生效
    [root@node-1 ~]# hostname
    node1

      8>Cron模块:计划任务
    支持时间:minute , hour , day , month , weekday:分钟,小时,日,月,周

    [root@ansible ~]#ansible all -m cron -a 'minute=* weekday=1,2,3 job="/usr/bin/wall FBI warning" name=warning'    #创建任务
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "warning"
        ]
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "warning"
        ]
    }

    node-1节点查看:node-2节点类似
    [root@node-1 ~]#
    Broadcast message from root@node-1 (Tue Mar 17 22:48:01 2020):

    FBI warning

    Broadcast message from root@node-1 (Tue Mar 17 22:49:01 2020):

    FBI warning

    [root@ansible ~]#ansible all -m cron -a 'disabled=true job="/usr/bin/wall FBI warning" name=warning' #disabled=true关闭任务
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "envs": [],
        "jobs": [
            "warning"
        ]
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "envs": [],
        "jobs": [
            "warning"
        ]
    }

    [root@ansible ~]#ansible all -m cron -a 'job="/usr/bin/wall FBI warning" name=warning state=absent' #absent删除任务
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "envs": [],
        "jobs": []
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "envs": [],
        "jobs": []
    }

      9>Yum:管理包
      ansible server -m yum -a 'name=httpd state=latest'安装
      ansible server -m yum -a 'name=httpd state=absent'删除

    [root@ansible ~]#ansible all -m yum -a 'name=httpd state=latest'    #latest:安装
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "changes": {
            "installed": [
                "httpd"
            ], 
            "updated": []
        }, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
    Resolving Dependencies
    --> Running transaction check
    ---> Package httpd.x86_64 0:2.4.6-67.el7.centos will be installed
    --> Processing Dependency: httpd-tools = 2.4.6-67.el7.centos for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Running transaction check
    ---> Package apr.x86_64 0:1.4.8-3.el7 will be installed
    ---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed
    ---> Package httpd-tools.x86_64 0:2.4.6-67.el7.centos will be installed
    ---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    ================================================================================
     Package            Arch          Version                     Repository   Size
    ================================================================================
    Installing:
     httpd              x86_64        2.4.6-67.el7.centos         base        2.7 M
    Installing for dependencies:
     apr                x86_64        1.4.8-3.el7                 base        103 k
     apr-util           x86_64        1.5.2-6.el7                 base         92 k
     httpd-tools        x86_64        2.4.6-67.el7.centos         base         87 k
     mailcap            noarch        2.1.41-2.el7                base         31 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+4 Dependent packages)
    
    Total download size: 3.0 M
    Installed size: 10 M
    Downloading packages:
    --------------------------------------------------------------------------------
    Total                                              8.4 MB/s | 3.0 MB  00:00     
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : apr-1.4.8-3.el7.x86_64                                       1/5 
      Installing : apr-util-1.5.2-6.el7.x86_64                                  2/5 
      Installing : httpd-tools-2.4.6-67.el7.centos.x86_64                       3/5 
      Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 
      Installing : httpd-2.4.6-67.el7.centos.x86_64                             5/5 
      Verifying  : httpd-2.4.6-67.el7.centos.x86_64                             1/5 
      Verifying  : mailcap-2.1.41-2.el7.noarch                                  2/5 
      Verifying  : apr-1.4.8-3.el7.x86_64                                       3/5 
      Verifying  : httpd-tools-2.4.6-67.el7.centos.x86_64                       4/5 
      Verifying  : apr-util-1.5.2-6.el7.x86_64                                  5/5 
    
    Installed:
      httpd.x86_64 0:2.4.6-67.el7.centos                                            
    
    Dependency Installed:
      apr.x86_64 0:1.4.8-3.el7                     apr-util.x86_64 0:1.5.2-6.el7    
      httpd-tools.x86_64 0:2.4.6-67.el7.centos     mailcap.noarch 0:2.1.41-2.el7    
    
    Complete!
    "
        ]
    }
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "changes": {
            "installed": [
                "httpd"
            ], 
            "updated": []
        }, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
    Resolving Dependencies
    --> Running transaction check
    ---> Package httpd.x86_64 0:2.4.6-67.el7.centos will be installed
    --> Processing Dependency: httpd-tools = 2.4.6-67.el7.centos for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64
    --> Running transaction check
    ---> Package apr.x86_64 0:1.4.8-3.el7 will be installed
    ---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed
    ---> Package httpd-tools.x86_64 0:2.4.6-67.el7.centos will be installed
    ---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    ================================================================================
     Package            Arch          Version                     Repository   Size
    ================================================================================
    Installing:
     httpd              x86_64        2.4.6-67.el7.centos         base        2.7 M
    Installing for dependencies:
     apr                x86_64        1.4.8-3.el7                 base        103 k
     apr-util           x86_64        1.5.2-6.el7                 base         92 k
     httpd-tools        x86_64        2.4.6-67.el7.centos         base         87 k
     mailcap            noarch        2.1.41-2.el7                base         31 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+4 Dependent packages)
    
    Total download size: 3.0 M
    Installed size: 10 M
    Downloading packages:
    --------------------------------------------------------------------------------
    Total                                              8.3 MB/s | 3.0 MB  00:00     
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : apr-1.4.8-3.el7.x86_64                                       1/5 
      Installing : apr-util-1.5.2-6.el7.x86_64                                  2/5 
      Installing : httpd-tools-2.4.6-67.el7.centos.x86_64                       3/5 
      Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 
      Installing : httpd-2.4.6-67.el7.centos.x86_64                             5/5 
      Verifying  : httpd-2.4.6-67.el7.centos.x86_64                             1/5 
      Verifying  : mailcap-2.1.41-2.el7.noarch                                  2/5 
      Verifying  : apr-1.4.8-3.el7.x86_64                                       3/5 
      Verifying  : httpd-tools-2.4.6-67.el7.centos.x86_64                       4/5 
      Verifying  : apr-util-1.5.2-6.el7.x86_64                                  5/5 
    
    Installed:
      httpd.x86_64 0:2.4.6-67.el7.centos                                            
    
    Dependency Installed:
      apr.x86_64 0:1.4.8-3.el7                     apr-util.x86_64 0:1.5.2-6.el7    
      httpd-tools.x86_64 0:2.4.6-67.el7.centos     mailcap.noarch 0:2.1.41-2.el7    
    
    Complete!
    "
        ]
    }
    [root@ansible ~]#ansible all -m shell -a 'rpm -q httpd'    #查看是否安装
    [WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
    If you need to use command because yum, dnf or zypper is insufficient you can add
    'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
    to get rid of this message.
    192.168.100.20 | CHANGED | rc=0 >>
    httpd-2.4.6-67.el7.centos.x86_64
    192.168.100.10 | CHANGED | rc=0 >>
    httpd-2.4.6-67.el7.centos.x86_64
    [root@ansible ~]#ansible all -m yum -a 'name=httpd state=absent'    #absent:卸载
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "changes": {
            "removed": [
                "httpd"
            ]
        }, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "已加载插件:fastestmirror
    正在解决依赖关系
    --> 正在检查事务
    ---> 软件包 httpd.x86_64.0.2.4.6-67.el7.centos 将被 删除
    --> 解决依赖关系完成
    
    依赖关系解决
    
    ================================================================================
     Package       架构           版本                          源             大小
    ================================================================================
    正在删除:
     httpd         x86_64         2.4.6-67.el7.centos           @base         9.4 M
    
    事务概要
    ================================================================================
    移除  1 软件包
    
    安装大小:9.4 M
    Downloading packages:
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      正在删除    : httpd-2.4.6-67.el7.centos.x86_64                            1/1 
      验证中      : httpd-2.4.6-67.el7.centos.x86_64                            1/1 
    
    删除:
      httpd.x86_64 0:2.4.6-67.el7.centos                                            
    
    完毕!
    "
        ]
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "changes": {
            "removed": [
                "httpd"
            ]
        }, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "已加载插件:fastestmirror
    正在解决依赖关系
    --> 正在检查事务
    ---> 软件包 httpd.x86_64.0.2.4.6-67.el7.centos 将被 删除
    --> 解决依赖关系完成
    
    依赖关系解决
    
    ================================================================================
     Package       架构           版本                          源             大小
    ================================================================================
    正在删除:
     httpd         x86_64         2.4.6-67.el7.centos           @base         9.4 M
    
    事务概要
    ================================================================================
    移除  1 软件包
    
    安装大小:9.4 M
    Downloading packages:
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      正在删除    : httpd-2.4.6-67.el7.centos.x86_64                            1/1 
      验证中      : httpd-2.4.6-67.el7.centos.x86_64                            1/1 
    
    删除:
      httpd.x86_64 0:2.4.6-67.el7.centos                                            
    
    完毕!
    "
        ]
    }
    [root@ansible ~]#ansible all -m shell -a 'rpm -q httpd'    #卸载后查看
    [WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
    If you need to use command because yum, dnf or zypper is insufficient you can add
    'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
    to get rid of this message.
    192.168.100.20 | FAILED | rc=1 >>
    未安装软件包 httpd non-zero return code
    192.168.100.10 | FAILED | rc=1 >>
    未安装软件包 httpd non-zero return code

      10>Service模块:管理服务
      ansible server -m service -a 'name=httpd state=stopped'
      ansible server -m service -a 'name=httpd state=started'
      ansible server -m service -a 'name=httpd state=reloaded'
      ansible server -m service -a 'name=httpd state=restarted'

    [root@ansible ~]#ansible all -m yum -a 'name=httpd state=latest'    #安装httpd
    [root@ansible ~]#ansible all -m shell -a 'ss -ntl'
    192.168.100.20 | CHANGED | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128         :::22                      :::*                  
    LISTEN     0      100        ::1:25                      :::*                  
    192.168.100.10 | CHANGED | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128         :::22                      :::*                  
    LISTEN     0      100        ::1:25                      :::*                  
    [root@ansible ~]#ansible all -m service -a 'name=httpd state=started enabled=yes'    #启动httpd,并设为开机自启动
    [root@ansible ~]#ansible all -m shell -a 'ss -ntl'
    192.168.100.20 | CHANGED | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128         :::80                      :::*                  
    LISTEN     0      128         :::22                      :::*                  
    LISTEN     0      100        ::1:25                      :::*                  
    192.168.100.10 | CHANGED | rc=0 >>
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128          *:22                       *:*                  
    LISTEN     0      100    127.0.0.1:25                       *:*                  
    LISTEN     0      128         :::80                      :::*                  
    LISTEN     0      128         :::22                      :::*                  
    LISTEN     0      100        ::1:25                      :::*[root@ansible ~]#ansible all -m service -a 'name=httpd state=stopped'    #关闭httpd
    

      11>User模块:管理用户

    [root@ansible ~]#ansible all -m user -a 'name=nginx shell=/sbin/nologin system=yes home=/var/nginx groups=root,bin uid=77 comment="nginx service"'    #创建用户指定shell类型,系统账号,家目录,附加组,uid,描述信息
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "comment": "nginx service", 
        "create_home": true, 
        "group": 77, 
        "groups": "root,bin", 
        "home": "/var/nginx", 
        "name": "nginx", 
        "shell": "/sbin/nologin", 
        "state": "present", 
        "system": true, 
        "uid": 77
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "comment": "nginx service", 
        "create_home": true, 
        "group": 77, 
        "groups": "root,bin", 
        "home": "/var/nginx", 
        "name": "nginx", 
        "shell": "/sbin/nologin", 
        "state": "present", 
        "system": true, 
        "uid": 77
    }
    [root@ansible ~]#ansible all -a 'getent passwd nginx'
    192.168.100.20 | CHANGED | rc=0 >>
    nginx:x:77:77:nginx service:/var/nginx:/sbin/nologin
    192.168.100.10 | CHANGED | rc=0 >>
    nginx:x:77:77:nginx service:/var/nginx:/sbin/nologin
    [root@ansible ~]#ansible all -m user -a 'name=nginx state=absent remove=yes'    #删除用户及其家目录信息
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "force": false, 
        "name": "nginx", 
        "remove": true, 
        "state": "absent", 
        "stderr": "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到
    ", 
        "stderr_lines": [
            "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到"
        ]
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "force": false, 
        "name": "nginx", 
        "remove": true, 
        "state": "absent", 
        "stderr": "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到
    ", 
        "stderr_lines": [
            "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到"
        ]
    }
    [root@ansible ~]#ansible all -a 'getent passwd nginx'
    192.168.100.20 | FAILED | rc=2 >>
    non-zero return code
    192.168.100.10 | FAILED | rc=2 >>
    non-zero return code

      12>Group:管理组

    [root@ansible ~]#ansible all -m group -a 'name=nginx system=yes gid=88'
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 88, 
        "name": "nginx", 
        "state": "present", 
        "system": true
    }
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 88, 
        "name": "nginx", 
        "state": "present", 
        "system": true
    }
    [root@ansible ~]#ansible all -a 'getent group nginx'
    192.168.100.20 | CHANGED | rc=0 >>
    nginx:x:88:
    192.168.100.10 | CHANGED | rc=0 >>
    nginx:x:88:
    [root@ansible ~]#ansible all -m group -a 'name=nginx state=absent'
    192.168.100.20 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "name": "nginx", 
        "state": "absent"
    }
    192.168.100.10 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "name": "nginx", 
        "state": "absent"
    }
    [root@ansible ~]#ansible all -a 'getent group nginx'
    192.168.100.20 | FAILED | rc=2 >>
    non-zero return code
    192.168.100.10 | FAILED | rc=2 >>
    non-zero return code

      模块用法不清楚可以查看帮助:

    [root@ansible ~]#ansible-doc -s cron    #例:查看cron模块

    13、ansible系列命令

      1>ansible-galaxy
      连接https://galaxy.ansible.com下载相应的roles(角色)
      列出所有已安装的galaxy
        ansible-galaxy list
      安装galaxy
        ansible-galaxy install geerlingguy.redis
      删除galaxy
        ansible-galaxy remove geerlingguy.redis

      2>ansible-pull
      推送命令至远程,效率无限提升,对运维要求较高

      3>Ansible-playbook

      (1)playbook是由一个或多个 "play" 组成的列表,采用YAML语言编写。
        play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏。

      (2)YAML是一一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、 Perl以及电子邮件格式RFC2822等。
        YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language" (仍是一种标记语言)
        特性:
          YAML的可读性好
          YAML和脚本语言的交互性好
          YAML使用实现语言的数据类型
          YAML有一个一致的信息模型
          YAML易于实现
          YAML可以基于流来处理
          YAML表达能力强,扩展性好
          更多的内容及规范参见http://www.yaml.org

      (3)在单一档案中,可用连续三个连字号(一)区分多个档案。另外,还有选择性的连续三个点号(...)用来表示档案结尾
    次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
        使用#号注释代码
        缩进必须是统一的,不能空格和tab混用
        缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
        YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感
        k/v的值可同行写也可换行写。同行使用:分隔
        v可是个字符串,也可是另一个列表
        一个完整的代码块功能需最少元素需包括name: task
        一个name只能包括一个task
        YAML文件扩展名通常为yml或yaml

      (4)List:列表,其所有元素均使用"-"打头

    示例:
    [root@ansible ansible]#cat file.yml 
    ---
    - hosts: webserver    #一个hosts列表,定义针对的列表主机
      remote_user: root
    
      tasks:              #任务
        - name: create new file    #任务列表1
          file: name=/root/newfile state=touch
        - name: create new user    #任务列表2
          user: name=test system=yes shell=/sbin/nologin

      (5)Dictionary:字典,通常由多个key与value构成

    示例:
    # An employee record
    name: Example Developer
    job: Developer
    skill: Elite

        也可以将key:value放置于{}中进行表示,用","分隔多个key:value

    # An employee record
    {name: Example Developer, job: Developer, skill: Elite}

      (6)Hosts:执行的远程主机列表
        playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中。
        可以是如下形式:
        one.example.com
        one.example.com:two.example.com
        192.168.100.10
        192.168.100.*
        webserver:dbserver 两个组的并集
        webserver:&dbserver 两个组的交集
        webservers:!dbserver 在webserver组,但不在dbserver组
                  all /etc/ansible/hosts主机清单中的所有主机

    ---
    - hosts: all    #主机清单中的所有主机
      remote_user: root
    
      tasks:              #任务
      ......

      (7)task列表和action
        ➢play的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
        ➢task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
        ➢每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤,如果未提供name,则action的结果将用于输出。
        tasks:任务列表
        格式:
          action: module arguments
          module: arguments    #建议使用
        ➢注意:shell和command模块后面跟命令,而非key=value
        某任务的状态在运行后为changed时,可通过"notify"通知给相应的 handlers

        handlers(触发器)和notify(通知)结合使用触发条件
    Handlers是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作
    Notify此action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。

    #编辑httpd.yml,实现httpd的安装,配置文件更改,服务启动
    #问题:第一次启动后,更改httpd的配置文件,第二次再执行,会因为之前启动了,而无法重启服务
    #解决:通过设置"notify",当某任务的状态在运行后为changed时,通知给相应的 handlers ,触发相应的命令
    [root@ansible ansible]#vim httpd.yml
    ---
    - hosts: all
      remote_user: root

      tasks:
        - name: install httpd package
          yum: name=httpd
        - name: copy conf file
          copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/ backup=yes
          notify: restart service
        - name: start service
          service: name=httpd state=started enabled=yes

      handlers:
        - name: restart service
          service: name=httpd state=restarted

      ➢任务可以通过"tags"打标签,而后可在ansible-playbook命令上使用-t指定进行调用

    [root@ansible ansible]#ansible all -m yum -a 'name=httpd state=absent'
    [root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
    [WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
    If you need to use command because yum, dnf or zypper is insufficient you can add
    'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
    to get rid of this message.
    192.168.100.20 | FAILED | rc=1 >>
    未安装软件包 httpd non-zero return code
    192.168.100.10 | FAILED | rc=1 >>
    未安装软件包 httpd non-zero return code

       通过ansible卸载httpd,在通过tags标签指定只下载httpd

    [root@ansible ansible]#ansible-playbook -t install -C httpd.yml
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.20]
    ok: [192.168.100.10]
    
    TASK [install httpd package] *******************************************************
    changed: [192.168.100.20]
    changed: [192.168.100.10]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@ansible ansible]#ansible-playbook -t install httpd.yml
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.20]
    ok: [192.168.100.10]
    
    TASK [install httpd package] *******************************************************
    changed: [192.168.100.10]
    changed: [192.168.100.20]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
    [WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
    If you need to use command because yum, dnf or zypper is insufficient you can add
    'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
    to get rid of this message.
    192.168.100.20 | CHANGED | rc=0 >>
    httpd-2.4.6-67.el7.centos.x86_64
    192.168.100.10 | CHANGED | rc=0 >>
    httpd-2.4.6-67.el7.centos.x86_64
    [root@ansible ansible]#ansible all -m shell -a 'ss -ntl | grep 80'
    192.168.100.20 | FAILED | rc=1 >>
    non-zero return code
    192.168.100.10 | FAILED | rc=1 >>
    non-zero return code

       (8)运行playbook

        如果命令或脚本的退出码不为零,可以使用如下方式替代

    tasks:
      - name: run this command and ignore the result
        shell: /usr/bin/somecommand || /bin/true

        或者使用ignore_errors来忽略错误信息:

    tasks:
      - name: run this command and ignore the result
        shell: /usr/bin/somecommand
        ignore_errors: True

        运行playbook的方式
        ansible-playbook <filename.yml> ... [options]
        常见选项:
          --check只检测可能会发生的改变,但不真正执行操作
          --list-hosts 列出运行任务的主机
          --limit主机列表只针对主机列表中的主机执行
          -v显示过程-vv -vvv 更详细

    示例:
    ansible-playbook file.yml --check #只检测
    ansible-playbook file.yml #执行
    ansible-playbook file.yml --limit webserver

      (9)ansible-playbook支持变量:

        变量名:仅能由字母、数字和下划线组成,且只能以字母开头
        变量来源:
          1 ansible setup facts远程主机的所有变量都可直接调用
          2 在/etc/ansible/hosts中定义
            普通变量:主机组中主机单独定义,优先级高于公共变量
            公共(组)变量:针对主机组中所有主机定义统一变量

          3 通过命令行指定变量,优先级最高
          ansible-playbook -e varname=value
          4 在playbook中定义

    [root@ansible ansible]#vim apps.yml 
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: install package
          yum: name={{ pkname }}    #定义变量
        - name: start service
          service: name={{ pkname }} state=started enabled=yes
    [root@ansible ansible]#ansible-playbook -e 'pkname=vsftpd' -C apps.yml
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.20]
    ok: [192.168.100.10]
    
    TASK [install package] *************************************************************
    changed: [192.168.100.20]
    changed: [192.168.100.10]
    
    TASK [start service] ***************************************************************
    changed: [192.168.100.10]
    changed: [192.168.100.20]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@ansible ansible]#ansible-playbook -e 'pkname=vsftpd' apps.yml
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.10]
    ok: [192.168.100.20]
    
    TASK [install package] *************************************************************
    changed: [192.168.100.20]
    changed: [192.168.100.10]
    
    TASK [start service] ***************************************************************
    changed: [192.168.100.10]
    changed: [192.168.100.20]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@ansible ansible]#ansible all -m shell -a 'ss -ntl|grep 21'
    192.168.100.20 | CHANGED | rc=0 >>
    LISTEN     0      32          :::21                      :::*                  
    192.168.100.10 | CHANGED | rc=0 >>
    LISTEN     0      32          :::21                      :::*      

      也可以在playbook中,定义vars

      也可以使用变量文件:

    [root@ansible ansible]#vim vars.yml 
    var1: httpd
    var2: vsftpd
    [root@ansible ansible]#vim testvar.yml 
    ---
    - hosts: all
      remote_user: root
      vars_files:
        - vars.yml
    
      tasks:
        - name: install package
          yum: name={{ var1 }}
        - name: create file
          file: name=/root/{{ var2 }}.log state=touch
    [root@ansible ansible]#ansible-playbook -C testvar.yml 
    ......
    [root@ansible ansible]#ansible-playbook testvar.yml
    ......
    [root@ansible ansible]#ansible all -a 'ls /root' 192.168.100.20 | CHANGED | rc=0 >> ...... vsftpd.log 192.168.100.10 | CHANGED | rc=0 >> ...... vsftpd.log [root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd' [WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'. If you need to use command because yum, dnf or zypper is insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message. 192.168.100.20 | CHANGED | rc=0 >> httpd-2.4.6-67.el7.centos.x86_64 192.168.100.10 | CHANGED | rc=0 >> httpd-2.4.6-67.el7.centos.x86_64

          5 在role中定义
        变量定义:key=value
        示例:http_port=80
        变量调用方式:
          通过{{ variable_name }}调用变量,且变量名前后必须有空格,有时用"{{ variable_ name}}" 才生效
          ansible playbook -e选项指定

      4>Ansible-vault
      功能:管理加密解密yml文件

    ansible-vault [create |decrypt| edit encrypt|rekey |view]
    ansible-vault encrypt hello.yml    加密
    ansible-vault decrypt hello.yml    解密
    ansible-vault view hello.yml       查看
    ansible-vault edit hello.yml       编辑加密文件
    ansible-vault rekey hello.yml      修改口令
    ansible-vault create new.yml       创建新文件

      5>Ansible-console:2.0+新增,可交互执行命令,支持tab
      root@test (2)[f:10] $
      执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]$
        ➢设置并发数:forksn 例如:forks 10
        ➢切换组:cd主机组 例如:cd web
        ➢列出当前组主机列表:list
        ➢列出所有的内置命令:?或help
        ➢示例:

    [root@ansible ~]#ansible-console
    Welcome to the ansible console.
    Type help or ? to list commands.
    
    root@all (2)[f:5]$ cd webserver
    root@webserver (1)[f:5]$ forks 10
    root@webserver (1)[f:10]$ command hostname
    192.168.100.10 | CHANGED | rc=0 >>
    node1
    root@webserver (1)[f:10]$ shell ls /root
    192.168.100.10 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    hello.sh
    hello.sh.4604.2020-03-17@21:14:22~

    14、模板templates
      文本文件,嵌套有脚本(使用模板编程语言编写)
      Jinja2语言,使用字面量,有下面形式
        字符串:使用单引号或双引号
        数字:整数,浮点数
        列表: [item1, item2, ...]
        元组: (item1, item2, ...)
        字典: {key1:value1, key2:value2, ...}
        布尔型: true/false
        算术运算: +,-, *,/.// %,**
        比较操作: ==,!=,>,>=, <, <=
        逻辑运算: and, or, not
        流表达式: For If When

      templates功能:根据模块文件动态生成对应的配置文件
      templates文件必须存放于templates目录下,且命名为.j2结尾
      yamI/yml文件需和templates目录平级,目录结构如下:

      .
      ├── ansible
          └── templates

    #实例:配置nginxtemplates模板文件,使不同主机的worker进程数量=CPU*2
    [root@ansible ~]#mkdir ansiable/templates
    [root@ansible ~]#tree -d
    .
    ├── ansible
    │   └── templates
    └── bin
    [root@ansible ansible]#ansible webserver -m setup | grep "processor"    #查看CPU变量名
            "ansible_processor": [
            "ansible_processor_cores": 1, 
            "ansible_processor_count": 1, 
            "ansible_processor_threads_per_core": 1, 
            "ansible_processor_vcpus": 1, 
    [root@ansible ansible]#cp /etc/nginx/nginx.conf ./templates/nginx.conf.j2
    [root@ansible ansible]#vim templates/nginx.conf.j2
    [root@ansible ansible]#vim testtempl.yml 
    ---
    - hosts: webserver
      remote_user: root

      tasks:
        - name: install paskage
          yum: name=nginx
        - name: copy template
          tempate: src=/root/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
        - name: start service
          service: name=nginx state=started enabled=yes
    [root@ansible ansible]#ansible-playbook testtempl.yml

      when语句:
      条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法
      格式:
      在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法

      对不同centos版本针对配置

    [root@ansible ansible]#ansible all -m setup -a 'filter="*distribution*"'
    192.168.100.20 | SUCCESS => {
        "ansible_facts": {
            "ansible_distribution": "CentOS", 
            "ansible_distribution_file_parsed": true, 
            "ansible_distribution_file_path": "/etc/redhat-release", 
            "ansible_distribution_file_variety": "RedHat", 
            "ansible_distribution_major_version": "7", 
            "ansible_distribution_release": "Core", 
            "ansible_distribution_version": "7.4", 
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false
    }
    192.168.100.10 | SUCCESS => {
        "ansible_facts": {
            "ansible_distribution": "CentOS", 
            "ansible_distribution_file_parsed": true, 
            "ansible_distribution_file_path": "/etc/redhat-release", 
            "ansible_distribution_file_variety": "RedHat", 
            "ansible_distribution_major_version": "7", 
            "ansible_distribution_release": "Core", 
            "ansible_distribution_version": "7.4", 
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false
    }

       迭代:当有需要重复性执行的任务时,可以使用迭代机制
        对迭代项的引用,固定变量名为"item"
        要在task中使用with_items给定要迭代的元素列表
        列表格式:
          字符串
          字典

       迭代嵌套子变量

    [root@ansible ansible]#cat testitem.yml 
    ---
    - hosts: all
      remote_user: root
    
      tasks:
        - name: create some groups
          group: name={{ item }}
          with_items:
            - g1
            - g2
            - g3
        - name: create some users
          user: name={{ item.name }} group={{ item.group }}
          with_items:
            - { name: 'user1', group: 'g1' }
            - { name: 'user2', group: 'g2' }
            - { name: 'user3', group: 'g3' }

      playbook中的template for if:

    [root@ansible ansible]#cat templates/for1.conf.j2 
    {% for port in ports %}
    server{
        listen {{ port }}
    }
    {% endfor %}
    [root@ansible ansible]#cat testfor.yml 
    ---
    - hosts: all
      remote_user: root
      vars:
        ports:
          - 81
          - 82
          - 83
      tasks:
        - name: copy conf
          template: src=/root/ansible/templates/for1.conf.j2 dest=/root/for1.conf
    [root@ansible ansible]#ansible-playbook -C testfor.yml 
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.20]
    ok: [192.168.100.10]
    
    TASK [copy conf] *******************************************************************
    changed: [192.168.100.10]
    changed: [192.168.100.20]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@ansible ansible]#ansible-playbook testfor.yml 
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.20]
    ok: [192.168.100.10]
    
    TASK [copy conf] *******************************************************************
    changed: [192.168.100.10]
    changed: [192.168.100.20]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 


    node1节点查看:
    [root@node1 ~]# cat for1.conf
    server{
        listen 81
    }
    server{
        listen 82
    }
    server{
        listen 83
    }
    [root@ansible ansible]#cat testfor2.yml 
    ---
    - hosts: all
      remote_user: root
      vars:
        ports:
            - listen_port: 80
            - listen_port: 82
            - listen_port: 83
      tasks:
        - name: copy conf
          template: src=/root/ansible/templates/for2.conf.j2 dest=/root/for2.conf
    [root@ansible ansible]#cat templates/for2.conf.j2 
    {% for port in ports %}
    server{
        listen {{ port.listen_port }}
    }
    {% endfor %}
    [root@ansible ansible]#ansible-playbook testfor2.yml 
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.20]
    ok: [192.168.100.10]
    
    TASK [copy conf] *******************************************************************
    changed: [192.168.100.10]
    changed: [192.168.100.20]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    node1节点查看:
    [root@node1 ~]# cat for2.conf 
    server{
        listen 80
    }
    server{
        listen 82
    }
    server{
        listen 83
    }
    
    
    [root@ansible ansible]#
    cat testfor3.yml --- - hosts: all remote_user: root vars: ports: - web1: port: 81 name: web1.yang.com rootdir: /root/website1 - web1: port: 82 name: web2.yang.com rootdir: /root/website2 - web1: port: 83 name: web3.yang.com rootdir: /root/website3 tasks: - name: copy conf template: src=/root/ansible/templates/for3.conf.j2 dest=/root/for3.conf [root@ansible ansible]#cat templates/for3.conf.j2 {% for p in ports %} server{ listen {{ p.port }} servername {{ p.name }} documentroot {{ p.rootdir }} } {% endfor %} [root@ansible ansible]#ansible-playbook testfor3.yml PLAY [all] ************************************************************************* TASK [Gathering Facts] ************************************************************* ok: [192.168.100.20] ok: [192.168.100.10] TASK [copy conf] ******************************************************************* changed: [192.168.100.20] changed: [192.168.100.10] PLAY RECAP ************************************************************************* 192.168.100.10 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.100.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 node1节点查看: [root@node1 ~]# cat for3.conf server{ listen 81 servername web1.yang.com documentroot /root/website1 } server{ listen 82 servername web2.yang.com documentroot /root/website2 } server{ listen 83 servername web3.yang.com documentroot /root/website3 }
    [root@ansible ansible]#cat testfor4.yml 
    ---
    - hosts: all
      remote_user: root
      vars:
        ports:
          - web1:
            port: 81
            #name: web1.yang.com
            rootdir: /root/website1
          - web1:
            port: 82
            name: web2.yang.com
            rootdir: /root/website2
          - web1:
            port: 83
            #name: web3.yang.com
            rootdir: /root/website3
      tasks:
        - name: copy conf
          template: src=/root/ansible/templates/for4.conf.j2 dest=/root/for4.conf
    [root@ansible ansible]#cat templates/for4.conf.j2 
    {% for p in ports %}
    server{
        listen {{ p.port }}
    {% if p.name is defined %}    #如果被定义了则生成,没有定义则不生成
        servername {{ p.name }}
    {% endif %}
        documentroot {{ p.rootdir }}
    }
    {% endfor %}
    [root@ansible ansible]#ansible-playbook testfor4.yml 
    
    PLAY [all] *************************************************************************
    
    TASK [Gathering Facts] *************************************************************
    ok: [192.168.100.10]
    ok: [192.168.100.20]
    
    TASK [copy conf] *******************************************************************
    changed: [192.168.100.20]
    changed: [192.168.100.10]
    
    PLAY RECAP *************************************************************************
    192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    
    node1节点查看:
    [root@node1 ~]# cat for4.conf 
    server{
        listen 81
        documentroot /root/website1
    }
    server{
        listen 82
        servername web2.yang.com
        documentroot /root/website2
    }
    server{
        listen 83
        documentroot /root/website3
    }

    15、roles
      1>定义:ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
      复杂场景:建议使用roles,代码复用度高
        变更指定主机或主机组
        如命名不规范维护和传承成本大
        某些功能需多个Playbook,通过Includes即可实现

      2>roles目录结构
      每个角色,以特定的层级目录结构进行组织

    playbook.yml
    roles/
        project/
            tasks/
            files/
            vars/         不常用
            default/      不常用
            templates/
            handlers/
            meta/         不常用

      /roles/project/:项目名称,有以下子目录
      files/ : 存放由copy或script模块等调用的文件
      templates/ : template模块查找所需要模板文件的目录
      tasks/ : 定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
      handlers/ : 至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
      vars/ : 定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
      meta/ : 定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.ymI的文件,其它文件需在此文件中通过include进行包含
      default/ : 设定默认变量时使用此目录中的main.yml文件

      3>使用:
      角色(roles):角色集合
      roles/(官方建议目录/etc/ansible/roles,不过也可以自定义)
        mysql/
        httpd/
        nginx/
        memcached/

    [root@ansible ansible]#tree    #构建目录结构,如果没有可以mkdir创建目录
    .
    └── roles
        ├── httpd
        ├── memcache
        ├── mysql
        └── nginx
    
    5 directories, 0 files
    [root@ansible ansible]#cd roles/nginx/
    [root@ansible nginx]#pwd
    /root/ansible/roles/nginx
    [root@ansible nginx]#mkdir tasks templates    #在roles/nginx创建一个任务目录和模板目录
    [root@ansible nginx]#ls
    tasks  templates
    [root@ansible nginx]#cd tasks/                #进入任务tasks目录
    [root@ansible tasks]#vim group.yml            #先创建组文件
    [root@ansible tasks]#cat group.yml
    - name: create group
      group: name=nginx gid=80
    [root@ansible tasks]#vim user.yml             #再创建用户文件
    [root@ansible tasks]#cat user.yml
    - name: create user
      user: name=nginx uid=80 group=nginx system=yes shell=/sbin/nologin
    [root@ansible tasks]#vim yum.yml              #再创建安装文件
    [root@ansible tasks]#cat yum.yml
    - name: install package
      yum: name=nginx
    [root@ansible tasks]#vim start.yml            #进而创建启动文件
    [root@ansible tasks]#cat start.yml
    - name: start service
      service: name=nginx state=started enabled=yes
    [root@ansible tasks]#cp start.yml restart.yml
    [root@ansible tasks]#vim restart.yml          #重启服务文件
    [root@ansible tasks]#cat restart.yml
    - name: restart service
      service: name=nginx state=restarted
    [root@ansible templates]#cd ../templates/     #进入模板templates目录
    [root@ansible templates]#cp /etc/nginx/nginx.conf nginx.conf.j2    #拷贝本机的nginx文件成为模板文件
    [root@ansible templates]#vim nginx.conf.j2
    

     

    
    
    [root@ansible templates]#cd ../tasks/
    [root@ansible tasks]#ls
    group.yml  restart.yml  start.yml  user.yml  yum.yml
    [root@ansible tasks]#vim templ.yml
    [root@ansible tasks]#cat templ.yml            #回到任务tasks目录,创建templ.yml文件
    - name: copy conf
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    [root@ansible tasks]#ls
    group.yml  restart.yml  start.yml  templ.yml  user.yml  yum.yml
    [root@ansible tasks]#vim main.yml             #创建全局文件,定义调用各个板块文件的顺序
    [root@ansible tasks]#cat main.yml
    - include: group.yml
    - include: user.yml
    - include: yum.yml
    - include: templ.yml
    - include: start.yml
    [root@ansible tasks]#cd ../../
    [root@ansible roles]#ls
    httpd  memcache  mysql  nginx
    [root@ansible roles]#cd ../
    [root@ansible ansible]#ls
    roles
    [root@ansible ansible]#vim nginx_role.yml     #创建nginx role文件,注意必须和roles同级
    [root@ansible ansible]#cat nginx_role.yml
    - hosts: all
      remote_user: root
      roles:
        - role: nginx
    [root@ansible ansible]#ansible-playbook -C nginx_role.yml    #检查语法
    [root@ansible ansible]#ansible-playbook nginx_role.yml       #执行
    
    
    总结:构建目录树结构如下 [root@ansible ansible]#tree . ├── nginx_role.yml └── roles ├── httpd ├── memcache ├── mysql └── nginx ├── tasks │ ├── group.yml │ ├── main.yml │ ├── restart.yml │ ├── start.yml │ ├── templ.yml │ ├── user.yml │ └──
    yum.yml └── templates └── nginx.conf.j2 7 directories, 9 files



  • 相关阅读:
    微信证书 javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    【转】ubunt 安装 yum出现 ubuntu 解决“无法获得锁 /var/lib/dpkg/lock -open (11:资源暂时不可用)”的方法
    HTTP Status 500
    idea导入项目报错:文档中根元素前面的标记必须格式正确
    redis 存取问题
    maven项目怎么引入另一个maven项目
    如何解决failed to push some refs to git
    idea配置maven后提示 commond not found
    JMS规范简介
    java消息中间件的使用与简介
  • 原文地址:https://www.cnblogs.com/zyybky/p/12514631.html
Copyright © 2011-2022 走看看