• 自动化运维之ansible


    第三十九课 自动化运维之ansible

    目录

    十五、 ansible介绍
    十六、 ansible安装
    十七、 ansible远程执行命令
    十八、 ansible拷贝文件或目录
    十九、 ansible远程执行脚本
    二十、 ansible管理任务计划
    二十一、 ansible安装包和管理服务
    二十二、 使用ansible playbook
    二十三、 playbook里的变量
    二十四、 playbook里的循环
    二十五、 playbook里的条件判断
    二十六、 playbook中的handlers
    二十七、 playbook安装nginx
    二十八、 playbook管理配置文件


    十五、 ansible介绍

    Ansilbe是一个部署一群远程主机的工具。远程的主机可以是远程虚拟机或物理机, 也可以是本地主机。

    Ansilbe通过SSH协议实现远程节点和管理节点之间的通信,不需要安装客户端。

    Ansible基于模块工作,模块可以由任何语言开发

    Ansible不仅支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读

    Ansible的安装十分简单,centos上可直接通过yum安装。

    Ansible有提供命令行版本,免费。也有提供UI(浏览器图形化)版本,网址: www.ansible.com/tower,但是收费的。

    官方文档: http://docs.ansible.com/ansible/latest/index.html

    Ansible已经被redhat公司收购,它在github上是一个非常受欢迎的开源软件,github地址https://github.com/ansible/ansible

    一本不错的入门电子书 https://ansible-book.gitbooks.io/ansible-first-book/


    十六、 ansible安装

    环境:

    ansiblemanager 192.168.1.51 CentOS Linux release 7.5.1804 (Core)

    ansiblemanaged01 192.168.1.52 CentOS Linux release 7.5.1804 (Core)

    ansiblemanaged02 192.168.1.53 CentOS Linux release 7.5.1804 (Core)

    为三台主机配置hosts文件

    [root@ansiblemanager ~]# vim /etc/hosts
    // 添加如下内容
    192.168.1.51 ansiblemanager
    192.168.1.52 ansiblemanaged01
    192.168.1.53 ansiblemanaged02
    

    1.在ansiblemanager上安装ansible

    // 查看源里自带的ansible版本
    [root@ansiblemanager ~]# yum list | grep ansible
    Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
    ansible.noarch                            2.6.2-1.el7                  epel     
    ansible-doc.noarch                        2.6.2-1.el7                  epel     
    ansible-inventory-grapher.noarch          2.4.4-1.el7                  epel     
    ansible-lint.noarch                       3.4.21-1.el7                 epel     
    ansible-openstack-modules.noarch          0-20140902git79d751a.el7     epel     
    ansible-review.noarch                     0.13.4-1.el7                 epel     
    kubernetes-ansible.noarch                 0.6.0-0.1.gitd65ebd5.el7     epel     
    python2-ansible-runner.noarch             1.0.1-1.el7                  epel     
    python2-ansible-tower-cli.noarch          3.3.0-2.el7                  epel   
    // 安装ansible
    [root@ansiblemanager ~]# yum -y install ansible  ansible-doc.noarch
    

    2.在ansiblemanager上生成密钥

    [root@ansiblemanager ~]# 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:SelwQ1T30hy8SQxvHWlQ/0YmDvm0VNYvAR9qrVdqFb8 root@ansiblemanager
    The key's randomart image is:
    +---[RSA 2048]----+
    |       .o.. +*=+=|
    |       . . . X=O*|
    |      . =   *.&+X|
    |       = o . X+O+|
    |        S   . BEo|
    |             o . |
    |                 |
    |                 |
    |                 |
    +----[SHA256]-----+
    [root@ansiblemanager ~]# ssh-copy-id 192.168.1.52
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    The authenticity of host '192.168.1.52 (192.168.1.52)' can't be established.
    ECDSA key fingerprint is SHA256:F7bJ5VTokx6I6FGONg5glMgIm7xggOdBnDfnOz1WAm4.
    ECDSA key fingerprint is MD5:d3:c0:12:84:40:a4:89:27:3f:bd:1a:2b:e5:2e:cc:27.
    Are you sure you want to continue connecting (yes/no)? yes
    /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.1.52's password: 
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh '192.168.1.52'"
    and check to make sure that only the key(s) you wanted were added.
    
    [root@ansiblemanager ~]# ssh 192.168.1.52
    Last login: Wed Sep  5 17:31:52 2018 from ansiblemanaged01
    [root@ansiblemanaged01 ~]# logout
    Connection to 192.168.1.52 closed.
    [root@ansiblemanager ~]# ssh-copy-id 192.168.1.53
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    The authenticity of host '192.168.1.53 (192.168.1.53)' can't be established.
    ECDSA key fingerprint is SHA256:F7bJ5VTokx6I6FGONg5glMgIm7xggOdBnDfnOz1WAm4.
    ECDSA key fingerprint is MD5:d3:c0:12:84:40:a4:89:27:3f:bd:1a:2b:e5:2e:cc:27.
    Are you sure you want to continue connecting (yes/no)? yes
    /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.1.53's password: 
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh '192.168.1.53'"
    and check to make sure that only the key(s) you wanted were added.
    
    [root@ansiblemanager ~]# ssh 192.168.1.53
    Last login: Wed Sep  5 17:32:23 2018 from ansiblemanaged01
    [root@ansiblemanaged02 ~]# logout
    Connection to 192.168.1.53 closed.
    
    

    3.新建配置被管理主机清单文件/etc/ansible/hosts

    [root@ansiblemanager ~]# vim /etc/ansible/hosts
    // 添加以下内容
    [testhosts]
    192.168.1.52
    192.168.1.53
    

    十七、 ansible远程执行命令

    ansible命令的格式是:

    ansible <host-pattern> [options]
    

    演示:

    // 批量执行命令,-m后面接调用module的名字, -a后面接调用module的参数
    [root@ansiblemanager ~]# ansible  testhosts -m command -a 'w' 
    192.168.1.52 | SUCCESS | rc=0 >>
     17:49:21 up 59 min,  3 users,  load average: 0.00, 0.01, 0.03
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     tty1                      16:52   56:01   0.02s  0.02s -bash
    root     pts/0    192.168.1.9      16:52    3:13   0.32s  0.32s -bash
    root     pts/1    ansiblemanager   17:49    0.00s  0.11s  0.00s w
    
    192.168.1.53 | SUCCESS | rc=0 >>
     17:49:22 up 58 min,  3 users,  load average: 0.00, 0.01, 0.05
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     tty1                      16:53   55:46   0.01s  0.01s -bash
    root     pts/0    192.168.1.9      16:53    3:14   0.31s  0.31s -bash
    root     pts/1    ansiblemanager   17:49    1.00s  0.08s  0.00s w
    
    // 也可以针对单主机执行命令
    [root@ansiblemanager ~]# ansible 192.168.1.52 -m command -a 'uptime'
    192.168.1.52 | SUCCESS | rc=0 >>
     10:24:44 up 54 min,  2 users,  load average: 0.00, 0.01, 0.03
     
    // shell模块也可以执行命令
    [root@ansiblemanager ~]# ansible  testhosts -m shell -a 'w'
    192.168.1.52 | SUCCESS | rc=0 >>
     10:26:16 up 55 min,  2 users,  load average: 0.00, 0.01, 0.03
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     pts/0    192.168.1.9      09:31    3:52   0.01s  0.01s -bash
    root     pts/1    ansiblemanager   10:26    0.00s  0.05s  0.00s w
    
    192.168.1.53 | SUCCESS | rc=0 >>
     10:26:16 up 55 min,  2 users,  load average: 0.00, 0.01, 0.02
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     pts/0    192.168.1.9      09:31   55:08   0.01s  0.01s -bash
    root     pts/1    ansiblemanager   10:26    0.00s  0.08s  0.00s w
    
    

    错误: "msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"

    解决: yum install -y libselinux-python


    十八、 ansible拷贝文件或目录

    1.拷贝目录

    // 源目录会放到目标目录下面去,如果目标指定的目录不存在,它会自动创建。
    // 如果拷贝的是文件,dest指定的名字和源如果不同,并且它不是已经存在的目录,
    // 相当于拷贝过去后又重命名。但相反,如果desc是目标机器上已经存在的目录,
    // 则会直接把文件拷贝到该目录下面。
    [root@ansiblemanager ~]# ansible 192.168.1.52 -m copy -a "src=/etc/ansible dest=/tmp owner=root group=root mode=755"
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "dest": "/tmp/", 
        "src": "/etc/ansible"
    }
    // 在192.168.1.52上查看
    [root@ansiblemanaged01 ~]# ls -l /tmp/
    total 0
    drwxr-xr-x 3 root root 51 Sep  6 10:39 ansible
    drwx------ 2 root root  6 Sep  6 09:14 vmware-root
    [root@ansiblemanaged01 ~]# 
    

    2.拷贝文件

    // 拷贝的行为类似于copy命令
    [root@ansiblemanager ~]# ansible 192.168.1.52 -m copy -a "src=/etc/inittab dest=/tmp"                                       
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "checksum": "e285e50c4dd88d8a2f644dd1750f60400ca60f94", 
        "dest": "/tmp/inittab", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "66a88d6c4d693170753ea3382f8bc150", 
        "mode": "0644", 
        "owner": "root", 
        "size": 511, 
        "src": "/root/.ansible/tmp/ansible-tmp-1536201763.72-216741204056791/source", 
        "state": "file", 
        "uid": 0
    }
    // 在192.168.1.52上查看
    [root@ansiblemanaged01 ~]# ls -l /tmp/
    total 4
    drwxr-xr-x 3 root root  51 Sep  6 10:39 ansible
    -rw-r--r-- 1 root root 511 Sep  6 10:42 inittab
    drwx------ 2 root root   6 Sep  6 09:14 vmware-root
    

    十九、 ansible远程执行脚本

    1.在AnsibkeManager端建立脚本文件

    [root@ansiblemanaged01 sh]# vim who.sh
    #!/bin/bash
    
    echo $HOSTNAME
    

    2.分发脚本到被管理机器

    [root@ansiblemanager ~]# ansible testhosts -m copy -a "src=/root/script/sh/who.sh dest=/tmp mode=755"
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "checksum": "71b7b8522c1f41a69ce8f1e6671b028fdf849752", 
        "dest": "/tmp/who.sh", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "2896d6645133ac0c98022eb61a5737cb", 
        "mode": "0755", 
        "owner": "root", 
        "size": 28, 
        "src": "/root/.ansible/tmp/ansible-tmp-1536202718.33-277007092121833/source", 
        "state": "file", 
        "uid": 0
    }
    192.168.1.53 | SUCCESS => {
        "changed": true, 
        "checksum": "71b7b8522c1f41a69ce8f1e6671b028fdf849752", 
        "dest": "/tmp/who.sh", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "2896d6645133ac0c98022eb61a5737cb", 
        "mode": "0755", 
        "owner": "root", 
        "size": 28, 
        "src": "/root/.ansible/tmp/ansible-tmp-1536202718.34-129515903004432/source", 
        "state": "file", 
        "uid": 0
    }
    

    3.批量执行脚本

    [root@ansiblemanager ~]# ansible testhosts -m shell -a '/tmp/who.sh'
    192.168.1.52 | SUCCESS | rc=0 >>
    ansiblemanaged01
    
    192.168.1.53 | SUCCESS | rc=0 >>
    ansiblemanaged02
    
    // shell模块与command模块的区别: shell模块,还支持远程执行命令并且带管道
    [root@ansiblemanager ~]# ansible testhosts -m command -a 'who | grep root'     
    192.168.1.52 | FAILED | rc=1 >>
    who: extra operand ‘root’
    Try 'who --help' for more information.non-zero return code
    
    192.168.1.53 | FAILED | rc=1 >>
    who: extra operand ‘root’
    Try 'who --help' for more information.non-zero return code
    
    
    [root@ansiblemanager ~]# ansible testhosts -m shell -a 'who | grep root'
    192.168.1.52 | SUCCESS | rc=0 >>
    root     pts/0        2018-09-06 09:31 (192.168.1.9)
    root     pts/1        2018-09-06 11:01 (ansiblemanager)
    
    192.168.1.53 | SUCCESS | rc=0 >>
    root     pts/0        2018-09-06 09:31 (192.168.1.9)
    root     pts/1        2018-09-06 11:01 (ansiblemanager)
    

    二十、 ansible管理任务计划

    1.新建任务计划

    // 其他的时间表示:分钟 minute 小时 hour 日期 day 月份 month
    [root@ansiblemanager ~]# ansible testhosts -m cron -a "name='test cron' job='/bin/echo $(date +%F)>>/tmp/dd.txt'  weekday=6"
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "envs": [], 
        "jobs": [
            "test cron"
        ]
    }
    192.168.1.53 | SUCCESS => {
        "changed": true, 
        "envs": [], 
        "jobs": [
            "test cron"
        ]
    }
    // 在被管理端检查计划任务是否建立
    [root@ansiblemanaged01 ~]# crontab -l
    #Ansible: test cron
    * * * * 6 /bin/echo 2018-09-06>>/tmp/dd.txt
    // 由ansible管理的计划任务,请不要手动修改,否则会导致ansible无法再管理相应的计划任务
    

    2.删除计划任务

    [root@ansiblemanager ~]# ansible 192.168.1.52 -m cron -a "name='test cron' state=absent"                                      
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "envs": [], 
        "jobs": []
    }
    // 验证
    [root@ansiblemanager ~]# ansible testhosts -m command -a "crontab -l"                                   
    192.168.1.52 | SUCCESS | rc=0 >>
    
    
    192.168.1.53 | SUCCESS | rc=0 >>
    #Ansible: test cron
    * * * * 6 /bin/echo 2018-09-06>>/tmp/dd.txt
    

    二十一、 ansible安装包和管理服务

    1.通过yum模块安装包

    // 在name后面还可以加上state=installed/removed来管理软件包
    [root@ansiblemanager ~]# ansible testhosts -m yum -a "name=httpd"          
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
     * base: mirrors.cn99.com
     * epel: mirrors.aliyun.com
     * extras: mirrors.cn99.com
     * updates: mirrors.163.com
    Resolving Dependencies
    --> Running transaction check
    ---> Package httpd.x86_64 0:2.4.6-80.el7.centos.1 will be installed
    --> Processing Dependency: httpd-tools = 2.4.6-80.el7.centos.1 for package: httpd-2.4.6-80.el7.centos.1.x86_64
    --> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-80.el7.centos.1.x86_64
    --> Running transaction check
    ---> Package httpd-tools.x86_64 0:2.4.6-80.el7.centos.1 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-80.el7.centos.1       updates       2.7 M
    Installing for dependencies:
     httpd-tools       x86_64       2.4.6-80.el7.centos.1       updates        90 k
     mailcap           noarch       2.1.41-2.el7                base           31 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+2 Dependent packages)
    
    Total download size: 2.8 M
    Installed size: 9.6 M
    Downloading packages:
    --------------------------------------------------------------------------------
    Total                                              3.8 MB/s | 2.8 MB  00:00     
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     1/3 
      Installing : mailcap-2.1.41-2.el7.noarch                                  2/3 
      Installing : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 
      Verifying  : mailcap-2.1.41-2.el7.noarch                                  1/3 
      Verifying  : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     2/3 
      Verifying  : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 
    
    Installed:
      httpd.x86_64 0:2.4.6-80.el7.centos.1                                          
    
    Dependency Installed:
      httpd-tools.x86_64 0:2.4.6-80.el7.centos.1    mailcap.noarch 0:2.1.41-2.el7   
    
    Complete!
    "
        ]
    }
    192.168.1.53 | SUCCESS => {
        "changed": true, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
     * base: mirrors.163.com
     * epel: mirrors.aliyun.com
     * extras: mirrors.163.com
     * updates: mirrors.163.com
    Resolving Dependencies
    --> Running transaction check
    ---> Package httpd.x86_64 0:2.4.6-80.el7.centos.1 will be installed
    --> Processing Dependency: httpd-tools = 2.4.6-80.el7.centos.1 for package: httpd-2.4.6-80.el7.centos.1.x86_64
    --> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-80.el7.centos.1.x86_64
    --> Running transaction check
    ---> Package httpd-tools.x86_64 0:2.4.6-80.el7.centos.1 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-80.el7.centos.1       updates       2.7 M
    Installing for dependencies:
     httpd-tools       x86_64       2.4.6-80.el7.centos.1       updates        90 k
     mailcap           noarch       2.1.41-2.el7                base           31 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+2 Dependent packages)
    
    Total download size: 2.8 M
    Installed size: 9.6 M
    Downloading packages:
    --------------------------------------------------------------------------------
    Total                                              3.1 MB/s | 2.8 MB  00:00     
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     1/3 
      Installing : mailcap-2.1.41-2.el7.noarch                                  2/3 
      Installing : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 
      Verifying  : mailcap-2.1.41-2.el7.noarch                                  1/3 
      Verifying  : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     2/3 
      Verifying  : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 
    
    Installed:
      httpd.x86_64 0:2.4.6-80.el7.centos.1                                          
    
    Dependency Installed:
      httpd-tools.x86_64 0:2.4.6-80.el7.centos.1    mailcap.noarch 0:2.1.41-2.el7   
    
    Complete!
    "
        ]
    }
    

    2.服务管理

    [root@ansiblemanager ~]# ansible testhosts -m service -a "name=httpd state=started enabled=yes" 
    192.168.1.52 | SUCCESS => {
        "changed": true, 
        "enabled": true, 
        "name": "httpd", 
        "state": "started", 
        "status": {
            "ActiveEnterTimestampMonotonic": "0", 
            "ActiveExitTimestampMonotonic": "0", 
            "ActiveState": "inactive", 
            "After": "systemd-journald.socket -.mount tmp.mount nss-lookup.target system.slice basic.target network.target remote-fs.target", 
            "AllowIsolate": "no", 
            "AmbientCapabilities": "0", 
            "AssertResult": "no", 
            "AssertTimestampMonotonic": "0", 
            "Before": "shutdown.target", 
            "BlockIOAccounting": "no", 
            "BlockIOWeight": "18446744073709551615", 
            "CPUAccounting": "no", 
            "CPUQuotaPerSecUSec": "infinity", 
            "CPUSchedulingPolicy": "0", 
            "CPUSchedulingPriority": "0", 
            "CPUSchedulingResetOnFork": "no", 
            "CPUShares": "18446744073709551615", 
            "CanIsolate": "no", 
            "CanReload": "yes", 
            "CanStart": "yes", 
            "CanStop": "yes", 
            "CapabilityBoundingSet": "18446744073709551615", 
            "ConditionResult": "no", 
            "ConditionTimestampMonotonic": "0", 
            "Conflicts": "shutdown.target", 
            "ControlPID": "0", 
            "DefaultDependencies": "yes", 
            "Delegate": "no", 
            "Description": "The Apache HTTP Server", 
            "DevicePolicy": "auto", 
            "Documentation": "man:httpd(8) man:apachectl(8)", 
            "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
            "ExecMainCode": "0", 
            "ExecMainExitTimestampMonotonic": "0", 
            "ExecMainPID": "0", 
            "ExecMainStartTimestampMonotonic": "0", 
            "ExecMainStatus": "0", 
            "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "FailureAction": "none", 
            "FileDescriptorStoreMax": "0", 
            "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
            "GuessMainPID": "yes", 
            "IOScheduling": "0", 
            "Id": "httpd.service", 
            "IgnoreOnIsolate": "no", 
            "IgnoreOnSnapshot": "no", 
            "IgnoreSIGPIPE": "yes", 
            "InactiveEnterTimestampMonotonic": "0", 
            "InactiveExitTimestampMonotonic": "0", 
            "JobTimeoutAction": "none", 
            "JobTimeoutUSec": "0", 
            "KillMode": "control-group", 
            "KillSignal": "18", 
            "LimitAS": "18446744073709551615", 
            "LimitCORE": "18446744073709551615", 
            "LimitCPU": "18446744073709551615", 
            "LimitDATA": "18446744073709551615", 
            "LimitFSIZE": "18446744073709551615", 
            "LimitLOCKS": "18446744073709551615", 
            "LimitMEMLOCK": "65536", 
            "LimitMSGQUEUE": "819200", 
            "LimitNICE": "0", 
            "LimitNOFILE": "4096", 
            "LimitNPROC": "1796", 
            "LimitRSS": "18446744073709551615", 
            "LimitRTPRIO": "0", 
            "LimitRTTIME": "18446744073709551615", 
            "LimitSIGPENDING": "1796", 
            "LimitSTACK": "18446744073709551615", 
            "LoadState": "loaded", 
            "MainPID": "0", 
            "MemoryAccounting": "no", 
            "MemoryCurrent": "18446744073709551615", 
            "MemoryLimit": "18446744073709551615", 
            "MountFlags": "0", 
            "Names": "httpd.service", 
            "NeedDaemonReload": "no", 
            "Nice": "0", 
            "NoNewPrivileges": "no", 
            "NonBlocking": "no", 
            "NotifyAccess": "main", 
            "OOMScoreAdjust": "0", 
            "OnFailureJobMode": "replace", 
            "PermissionsStartOnly": "no", 
            "PrivateDevices": "no", 
            "PrivateNetwork": "no", 
            "PrivateTmp": "yes", 
            "ProtectHome": "no", 
            "ProtectSystem": "no", 
            "RefuseManualStart": "no", 
            "RefuseManualStop": "no", 
            "RemainAfterExit": "no", 
            "Requires": "basic.target -.mount", 
            "RequiresMountsFor": "/var/tmp", 
            "Restart": "no", 
            "RestartUSec": "100ms", 
            "Result": "success", 
            "RootDirectoryStartOnly": "no", 
            "RuntimeDirectoryMode": "0755", 
            "SameProcessGroup": "no", 
            "SecureBits": "0", 
            "SendSIGHUP": "no", 
            "SendSIGKILL": "yes", 
            "Slice": "system.slice", 
            "StandardError": "inherit", 
            "StandardInput": "null", 
            "StandardOutput": "journal", 
            "StartLimitAction": "none", 
            "StartLimitBurst": "5", 
            "StartLimitInterval": "10000000", 
            "StartupBlockIOWeight": "18446744073709551615", 
            "StartupCPUShares": "18446744073709551615", 
            "StatusErrno": "0", 
            "StopWhenUnneeded": "no", 
            "SubState": "dead", 
            "SyslogLevelPrefix": "yes", 
            "SyslogPriority": "30", 
            "SystemCallErrorNumber": "0", 
            "TTYReset": "no", 
            "TTYVHangup": "no", 
            "TTYVTDisallocate": "no", 
            "TasksAccounting": "no", 
            "TasksCurrent": "18446744073709551615", 
            "TasksMax": "18446744073709551615", 
            "TimeoutStartUSec": "1min 30s", 
            "TimeoutStopUSec": "1min 30s", 
            "TimerSlackNSec": "50000", 
            "Transient": "no", 
            "Type": "notify", 
            "UMask": "0022", 
            "UnitFilePreset": "disabled", 
            "UnitFileState": "disabled", 
            "Wants": "system.slice", 
            "WatchdogTimestampMonotonic": "0", 
            "WatchdogUSec": "0"
        }
    }
    192.168.1.53 | SUCCESS => {
        "changed": true, 
        "enabled": true, 
        "name": "httpd", 
        "state": "started", 
        "status": {
            "ActiveEnterTimestampMonotonic": "0", 
            "ActiveExitTimestampMonotonic": "0", 
            "ActiveState": "inactive", 
            "After": "remote-fs.target nss-lookup.target tmp.mount network.target systemd-journald.socket system.slice -.mount basic.target", 
            "AllowIsolate": "no", 
            "AmbientCapabilities": "0", 
            "AssertResult": "no", 
            "AssertTimestampMonotonic": "0", 
            "Before": "shutdown.target", 
            "BlockIOAccounting": "no", 
            "BlockIOWeight": "18446744073709551615", 
            "CPUAccounting": "no", 
            "CPUQuotaPerSecUSec": "infinity", 
            "CPUSchedulingPolicy": "0", 
            "CPUSchedulingPriority": "0", 
            "CPUSchedulingResetOnFork": "no", 
            "CPUShares": "18446744073709551615", 
            "CanIsolate": "no", 
            "CanReload": "yes", 
            "CanStart": "yes", 
            "CanStop": "yes", 
            "CapabilityBoundingSet": "18446744073709551615", 
            "ConditionResult": "no", 
            "ConditionTimestampMonotonic": "0", 
            "Conflicts": "shutdown.target", 
            "ControlPID": "0", 
            "DefaultDependencies": "yes", 
            "Delegate": "no", 
            "Description": "The Apache HTTP Server", 
            "DevicePolicy": "auto", 
            "Documentation": "man:httpd(8) man:apachectl(8)", 
            "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
            "ExecMainCode": "0", 
            "ExecMainExitTimestampMonotonic": "0", 
            "ExecMainPID": "0", 
            "ExecMainStartTimestampMonotonic": "0", 
            "ExecMainStatus": "0", 
            "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "FailureAction": "none", 
            "FileDescriptorStoreMax": "0", 
            "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
            "GuessMainPID": "yes", 
            "IOScheduling": "0", 
            "Id": "httpd.service", 
            "IgnoreOnIsolate": "no", 
            "IgnoreOnSnapshot": "no", 
            "IgnoreSIGPIPE": "yes", 
            "InactiveEnterTimestampMonotonic": "0", 
            "InactiveExitTimestampMonotonic": "0", 
            "JobTimeoutAction": "none", 
            "JobTimeoutUSec": "0", 
            "KillMode": "control-group", 
            "KillSignal": "18", 
            "LimitAS": "18446744073709551615", 
            "LimitCORE": "18446744073709551615", 
            "LimitCPU": "18446744073709551615", 
            "LimitDATA": "18446744073709551615", 
            "LimitFSIZE": "18446744073709551615", 
            "LimitLOCKS": "18446744073709551615", 
            "LimitMEMLOCK": "65536", 
            "LimitMSGQUEUE": "819200", 
            "LimitNICE": "0", 
            "LimitNOFILE": "4096", 
            "LimitNPROC": "1796", 
            "LimitRSS": "18446744073709551615", 
            "LimitRTPRIO": "0", 
            "LimitRTTIME": "18446744073709551615", 
            "LimitSIGPENDING": "1796", 
            "LimitSTACK": "18446744073709551615", 
            "LoadState": "loaded", 
            "MainPID": "0", 
            "MemoryAccounting": "no", 
            "MemoryCurrent": "18446744073709551615", 
            "MemoryLimit": "18446744073709551615", 
            "MountFlags": "0", 
            "Names": "httpd.service", 
            "NeedDaemonReload": "no", 
            "Nice": "0", 
            "NoNewPrivileges": "no", 
            "NonBlocking": "no", 
            "NotifyAccess": "main", 
            "OOMScoreAdjust": "0", 
            "OnFailureJobMode": "replace", 
            "PermissionsStartOnly": "no", 
            "PrivateDevices": "no", 
            "PrivateNetwork": "no", 
            "PrivateTmp": "yes", 
            "ProtectHome": "no", 
            "ProtectSystem": "no", 
            "RefuseManualStart": "no", 
            "RefuseManualStop": "no", 
            "RemainAfterExit": "no", 
            "Requires": "basic.target -.mount", 
            "RequiresMountsFor": "/var/tmp", 
            "Restart": "no", 
            "RestartUSec": "100ms", 
            "Result": "success", 
            "RootDirectoryStartOnly": "no", 
            "RuntimeDirectoryMode": "0755", 
            "SameProcessGroup": "no", 
            "SecureBits": "0", 
            "SendSIGHUP": "no", 
            "SendSIGKILL": "yes", 
            "Slice": "system.slice", 
            "StandardError": "inherit", 
            "StandardInput": "null", 
            "StandardOutput": "journal", 
            "StartLimitAction": "none", 
            "StartLimitBurst": "5", 
            "StartLimitInterval": "10000000", 
            "StartupBlockIOWeight": "18446744073709551615", 
            "StartupCPUShares": "18446744073709551615", 
            "StatusErrno": "0", 
            "StopWhenUnneeded": "no", 
            "SubState": "dead", 
            "SyslogLevelPrefix": "yes", 
            "SyslogPriority": "30", 
            "SystemCallErrorNumber": "0", 
            "TTYReset": "no", 
            "TTYVHangup": "no", 
            "TTYVTDisallocate": "no", 
            "TasksAccounting": "no", 
            "TasksCurrent": "18446744073709551615", 
            "TasksMax": "18446744073709551615", 
            "TimeoutStartUSec": "1min 30s", 
            "TimeoutStopUSec": "1min 30s", 
            "TimerSlackNSec": "50000", 
            "Transient": "no", 
            "Type": "notify", 
            "UMask": "0022", 
            "UnitFilePreset": "disabled", 
            "UnitFileState": "disabled", 
            "Wants": "system.slice", 
            "WatchdogTimestampMonotonic": "0", 
            "WatchdogUSec": "0"
        }
    }
    
    // 被管理端检查
    [root@ansiblemanager ~]# ansible testhosts -m shell -a "netstat -nltp | grep :80"
    192.168.1.52 | SUCCESS | rc=0 >>
    tcp6       0      0 :::80                   :::*                    LISTEN      2542/httpd          
    
    192.168.1.53 | SUCCESS | rc=0 >>
    tcp6       0      0 :::80                   :::*                    LISTEN      2015/httpd          
    
    

    3.Ansible文档的使用

    // 列出所有的模块
    
    [root@ansiblemanager ~]# ansible-doc -l 
    a10_server                                           Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server objec...
    a10_server_axapi3                                    Manage A10 Networks AX/SoftAX/Thunder/vThunder devices              
    a10_service_group                                    Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service grou...
    a10_virtual_server                                   Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual serv...
    accelerate                                           Enable accelerated mode on remote node                              
    aci_aaa_user                                         Manage AAA users (aaa:User)                                         
    aci_aaa_user_certificate                             Manage AAA user certificates (aaa:UserCert)                         
    aci_access_port_to_interface_policy_leaf_profile     Manage Fabric interface policy leaf profile interface selectors (inf...
    aci_aep                                              Manage attachable Access Entity Profile (AEP) objects (infra:AttEnti...
    aci_aep_to_domain                                    Bind AEPs to Physical or Virtual Domains (infra:RsDomP)             
    aci_ap                                               Manage top level Application Profile (AP) objects (fv:Ap
    ...下略...
    
    // 查看指定模块的文档
    [root@ansiblemanager ~]# ansible-doc a10_server 
    > A10_SERVER    (/usr/lib/python2.7/site-packages/ansible/modules/network/a10/a10_server.py)
    
            Manage SLB (Server Load Balancer) server objects on A10 Networks devices via aXAPIv2.
    
    OPTIONS (= is mandatory):
    
    - client_cert
            PEM formatted certificate chain file to be used for SSL client authentication. This file can
            also include the key as well, and if the key is included, `client_key' is not required.
            [Default: (null)]
    
    - client_key
            PEM formatted file that contains your private key to be used for SSL client authentication.
            If `client_cert' contains both the certificate and key, this option is not required.
            [Default: (null)]
    
    - force
            If `yes' do not get a cached copy.
            (Aliases: thirsty)[Default: False]
            type: bool
    ...下略...
    

    二十二、 使用ansible playbook

    Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.

    如果 Ansible 模块你是工作室中的工具,那么 playbooks 就是你设置的方案计划.

    Playbooks 的格式是YAML。

    第一个playbook

    // 编写playbook文件
    // 第一行需要有三个杠,hosts参数指定了对哪些主机进行参作,
    // 如果是多台机器可以用逗号作为分隔,也可以使用主机组,在/etc/ansible/hosts里定义
    // user参数指定了使用什么用户登录远程主机操作
    // tasks指定了一个任务,其下面的name参数同样是对任务的描述,在执行过程中会打印出来,shell是ansible模块名字
    
    [root@ansiblemanager ~]#  vim  /etc/ansible/test.yml
    ---
    - hosts: ansiblemanaged01
      remote_user: root
      tasks:
        - name: test_playbook
          shell: echo $HOSTNAME >>/tmp/playbook_Test.txt
    
    // 执行
    [root@ansiblemanager ansible]# ansible-playbook test.yml
    
    PLAY [testhosts] *************************************************************************************************************
    
    TASK [Gathering Facts] *******************************************************************************************************
    ok: [192.168.1.53]
    ok: [192.168.1.52]
    
    TASK [test playbook] *********************************************************************************************************
    changed: [192.168.1.53]
    changed: [192.168.1.52]
    
    PLAY RECAP *******************************************************************************************************************
    192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
    192.168.1.53               : ok=2    changed=1    unreachable=0    failed=0   
    
    [root@ansiblemanager ansible]# ansible all -m shell -a "cat /tmp/playboogtest.txt" 
    192.168.1.53 | SUCCESS | rc=0 >>
    ansiblemanaged02
    
    192.168.1.52 | SUCCESS | rc=0 >>
    ansiblemanaged01
    
    

    二十三、 playbook里的变量

    演示

    // 创建playbook文件
    [root@ansiblemanager ansible]# vim create_user.yml
    ---
    - name: create user
      hosts: testhosts
      user: root
      gather_facts: false
      vars:
       - user: "nico"
      tasks:
       - name: create user
         user: name="{{ user }}"
    // 执行
    [root@ansiblemanager ansible]# ansible-playbook create_user.yml 
    
    PLAY [create user] ***********************************************************************************************************
    
    TASK [create user] ***********************************************************************************************************
    changed: [192.168.1.53]
    changed: [192.168.1.52]
    
    PLAY RECAP *******************************************************************************************************************
    192.168.1.52               : ok=1    changed=1    unreachable=0    failed=0   
    192.168.1.53               : ok=1    changed=1    unreachable=0    failed=0   
    // 验证
    [root@ansiblemanager ansible]# ansible all -m shell -a "grep nico /etc/passwd" 
    192.168.1.52 | SUCCESS | rc=0 >>
    nico:x:5001:5001::/home/nico:/bin/bash
    
    192.168.1.53 | SUCCESS | rc=0 >>
    nico:x:5001:5001::/home/nico:/bin/bash
    
    // name参数对该playbook实现的功能做一个概述,后面执行过程中,会打印name变量的值,
    // 可以省略;gather_facts参数指定了在以下任务部分执行前,是否先执行setup模块获取主机相关
    // 信息,如果后面的task会使用到setup获取的信息时会用到;vars参数,指定了变量,
    // 这里指字一个user变量,其值为nico,需要注意的是,变量值一定要用引号引住;
    // user指定了调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。
    

    二十四、 playbook里的循环

    演示

    // 创建playbook文件
    // with_items为循环的对象
    [root@ansiblemanager ansible]# vim loop.yml              
    ---
    - hosts: 192.168.1.52
      user: root
      tasks:
       - name: change mode for files
         file: path=/tmp/{{ item }} state=touch mode=600
         with_items:
          - 1.txt
          - 2.txt
          - 3.txt
    // 执行
    [root@ansiblemanager ansible]# ansible-playbook loop.yml 
    
    PLAY [192.168.1.52] **********************************************************************************************************
    
    TASK [Gathering Facts] *******************************************************************************************************
    ok: [192.168.1.52]
    
    TASK [change mode for files] *************************************************************************************************
    changed: [192.168.1.52] => (item=1.txt)
    changed: [192.168.1.52] => (item=2.txt)
    changed: [192.168.1.52] => (item=3.txt)
    
    PLAY RECAP *******************************************************************************************************************
    192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
    

    二十五、 playbook里的条件判断

    演示:

    // 新建playbook文件
    [root@ansiblemanager ansible]# vim when.yml              
    ---
    - hosts: testhosts
      user: root
      gather_facts: True
      tasks:
       - name: use when
         shell: echo $HOSTNAME >>/tmp/tt.txt
         when: ansible_ens32.ipv4.address=="192.168.1.52"
    // 执行
    [root@ansiblemanager ansible]# ansible-playbook when.yml 
    
    PLAY [testhosts] ***************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [192.168.1.52]
    ok: [192.168.1.53]
    
    TASK [use when] ****************************************************************
    skipping: [192.168.1.53]
    changed: [192.168.1.52]
    
    PLAY RECAP *********************************************************************
    192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
    192.168.1.53               : ok=1    changed=0    unreachable=0    failed=0   
    // 验证
    [root@ansiblemanager ansible]# ansible all -m command -a 'cat /tmp/tt.txt'    
    192.168.1.53 | FAILED | rc=1 >>
    cat: /tmp/tt.txt: No such file or directorynon-zero return code
    
    192.168.1.52 | SUCCESS | rc=0 >>
    ansiblemanaged01
    
    // 当注释when这一句,则会对192.168.1.53
    
    [root@ansiblemanager ansible]# vim when.yml                               
    ---
    - hosts: testhosts
      user: root
      gather_facts: True
      tasks:
       - name: use when
         shell: echo $HOSTNAME >>/tmp/tt.txt
         #when: ansible_ens32.ipv4.address=="192.168.1.52"
    // 执行
    [root@ansiblemanager ansible]# ansible-playbook when.yml 
    
    PLAY [testhosts] *************************************************************************************************************
    
    TASK [Gathering Facts] *******************************************************************************************************
    ok: [192.168.1.52]
    ok: [192.168.1.53]
    
    TASK [use when] **************************************************************************************************************
    changed: [192.168.1.53]
    changed: [192.168.1.52]
    
    PLAY RECAP *******************************************************************************************************************
    192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
    192.168.1.53               : ok=2    changed=1    unreachable=0    failed=0   
    
    [root@ansiblemanager ansible]# ansible all -m command -a 'cat /tmp/tt.txt'
    192.168.1.52 | SUCCESS | rc=0 >>
    ansiblemanaged01
    ansiblemanaged01
    
    192.168.1.53 | SUCCESS | rc=0 >>
    ansiblemanaged02
    
    //所有的facter信息可以通过 "ansible aming-02 -m setup" 查看
    

    二十六、 playbook中的handlers

    Ansible playbook中的handlers可实现类似逻辑与的功能。

    演示

    // 新建playbook文件
    // 只有copy模块真正执行后,才会去调用下面的handlers相关的操作。
    // 也就是说如果1.txt和2.txt内容是一样的,并不会去执行handlers里面的shell相关命令。 // 这种比较适合配置文件发生更改后,重启服务的操作。
    [root@ansiblemanager ansible]# vim handlers.yml                       
    ---
    - name: handlers test
      hosts: testhosts
      user: root
      tasks:
        - name: copy file
          copy: src=/etc/inittab dest=/tmp/1.txt
          notify: test handlers
      handlers:
        - name: test handlers
          shell: echo "new line" >> /tmp/1.txt
    // 执行
    [root@ansiblemanager ansible]# ansible-playbook handlers.yml
    
    PLAY [handlers test] *********************************************************************************************************
    
    TASK [Gathering Facts] *******************************************************************************************************
    ok: [192.168.1.52]
    ok: [192.168.1.53]
    
    TASK [copy file] *************************************************************************************************************
    changed: [192.168.1.52]
    changed: [192.168.1.53]
    
    RUNNING HANDLER [test handlers] **********************************************************************************************
    changed: [192.168.1.52]
    changed: [192.168.1.53]
    
    PLAY RECAP *******************************************************************************************************************
    192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0   
    192.168.1.53               : ok=3    changed=2    unreachable=0    failed=0   
    // 检查
    [root@ansiblemanager ansible]# ansible all -m command -a "tail -n 2 /tmp/1.txt"
    192.168.1.52 | SUCCESS | rc=0 >>
    #
    new line
    
    192.168.1.53 | SUCCESS | rc=0 >>
    #
    new line
    

    二十七、 playbook安装nginx

    思路:先在一台机器上编译安装好nginx、打包,然后再用ansible去下发

    1.分发主机进入ansible配置文件目录

    [root@ansiblemanager ~]# cd /etc/ansible/
    

    2.为方便管理,创建一个nginx_install的目录

    [root@ansiblemanager ansible]# mkdir  nginx_install
    [root@ansiblemanager ansible]# ls -ld !$
    ls -ld nginx_install
    drwxr-xr-x 2 root root 6 Sep 10 15:03 nginx_install
    [root@ansiblemanager ansible]# cd !$
    cd nginx_install
    

    3.创建playbook目录结构

    [root@ansiblemanager nginx_install]# mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}
    [root@ansiblemanager nginx_install]# tree
    .
    └── roles
        ├── common
        │   ├── files
        │   ├── handlers
        │   ├── meta
        │   ├── tasks
        │   ├── templates
        │   └── vars
        └── install
            ├── files
            ├── handlers
            ├── meta
            ├── tasks
            ├── templates
            └── vars
    // roles目录下有两个角色,common为一些准备操作,install为安装nginx的操作。
    // 每个角色下面又有几个目录,handlers下面是当发生改变时要执行的操作,
    // 通常用在配置文件发生改变,重启服务。files为安装时用到的一些文件,
    // meta为说明信息,说明角色依赖等信息,tasks里面是核心的配置文件,
    // templates通常存一些配置文件,启动脚本等模板文件,vars下为定义的变量
    

    4.在模板机安装nginx并打包

    [root@lanquark sh]# cd /usr/local/
    [root@lanquark local]# tar zcvf nginx.tar.gz nginx/ --exclude nginx.conf 
    // 打包好以后同步到分发主机
    

    5.将打包的nginx文件,配置文件,启动脚本拷贝到相应的目录

    [root@ansiblemanager nginx_install]# mv /usr/local/src/nginx.tar.gz roles/install/files/
    [root@ansiblemanager nginx_install]# mv /usr/local/src/nginx.conf roles/install/templates/
    [root@ansiblemanager nginx_install]# mv /usr/local/src/nginx roles/install/templates/
    

    6.定义普通的tasks

    [root@ansiblemanager nginx_install]# vim roles/common/tasks/main.yml
    - name: Install initializtion require software
      yum: name={{ item }} state=installed
      with_items:
        - zlib-devel
        - pcre-devel
    

    7.定义变量

    [root@ansiblemanager nginx_install]# vim roles/install/vars/main.yml
    nginx_user: nginx
    nginx_port: 80
    nginx_basedir: /usr/local/nginx 
    

    8.定义文件拷贝配置

    [root@ansiblemanager nginx_install]# vim roles/install/tasks/copy.yml
    - name: Copy Nginx Software
      copy: src=nginx.tar.gz dest=/tmp/nginx.tar.gz owner=root group=root
    - name: Uncompression Nginx Software
      shell: tar zxf /tmp/nginx.tar.gz -C /usr/local/
    - name: Copy Nginx Start Script
      template: src=nginx dest=/etc/init.d/nginx owner=root group=root mode=0755
    - name: Copy Nginx Config
      template: src=nginx.conf dest={{ nginx_basedir }}/conf/ owner=root group=root mode=0644
    

    9.建立用户、启动服务。删除安装包

    [root@ansiblemanager nginx_install]# vim roles/install/tasks/install.yml
    
    - name: Create Nginx User
      user: name={{ nginx_user }} state=present createhome=no shell=/sbin/nologin
    - name: Start Nginx Service
      shell: /etc/init.d/nginx start
    - name: Add Boot Start Nginx Service
      shell: chkconfig --level 345 nginx on
    - name: Delete Nginx compression files
      shell: rm -rf /tmp/nginx.tar.gz
    

    10.创建main.yml,调用copy和install

    [root@ansiblemanager nginx_install]# vim roles/install/tasks/main.yml
    - include: copy.yml
    - include: install.yml
    

    11.创建入口文件

    [root@ansiblemanager nginx_install]# vim install.yml 
    ---
    - hosts: 192.168.1.52
      remote_user: root
      gather_facts: True
      roles:
        - common
        - install
    

    12.执行

    [root@ansiblemanager nginx_install]# ansible-playbook install.yml 
    
    PLAY [192.168.1.52] **********************************************************************************************************
    
    TASK [Gathering Facts] *******************************************************************************************************
    ok: [192.168.1.52]
    
    TASK [common : Install initializtion require software] ***********************************************************************
    ok: [192.168.1.52] => (item=[u'zlib-devel', u'pcre-devel'])
    
    TASK [install : Copy Nginx Software] *****************************************************************************************
    ok: [192.168.1.52]
    
    TASK [install : Uncompression Nginx Software] ********************************************************************************
     [WARNING]: Consider using the unarchive module rather than running tar.  If you need to use command because unarchive 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.
    
    changed: [192.168.1.52]
    
    TASK [install : Copy Nginx Start Script] *************************************************************************************
    ok: [192.168.1.52]
    
    TASK [install : Copy Nginx Config] *******************************************************************************************
    changed: [192.168.1.52]
    
    TASK [install : Create Nginx User] *******************************************************************************************
    changed: [192.168.1.52]
    
    TASK [install : Start Nginx Service] *****************************************************************************************
    changed: [192.168.1.52]
    
    TASK [install : Add Boot Start Nginx Service] ********************************************************************************
    changed: [192.168.1.52]
    
    TASK [install : Delete Nginx compression files] ******************************************************************************
     [WARNING]: Consider using the file module with state=absent rather than running rm.  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.
    
    changed: [192.168.1.52]
    
    PLAY RECAP *******************************************************************************************************************
    192.168.1.52               : ok=10   changed=6    unreachable=0    failed=0   
    

    13.客户端检查

    [root@ansiblemanaged01 ~]# lsof -i :80
    COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    nginx   14441  root    6u  IPv4 510103      0t0  TCP *:http (LISTEN)
    nginx   14442 nginx    6u  IPv4 510103      0t0  TCP *:http (LISTEN)
    

    二十八、 playbook管理配置文件

    生产环境中安装软件包只是在初始化环境的时候用一下,大多时候是需要管理配置文件的,下面我们来写个管理nginx配置文件的playbook

    1.创建playbook配置目录结构

    [root@ansiblemanager nginx_install]# mkdir  -p /etc/ansible/nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
    [root@ansiblemanager nginx_install]# cd ../
    [root@ansiblemanager ansible]# tree nginx_config/
    nginx_config/
    └── roles
        ├── new
        │   ├── files
        │   ├── handlers
        │   ├── tasks
        │   └── vars
        └── old
            ├── files
            ├── handlers
            ├── tasks
            └── vars
    
    11 directories, 0 files
    // 其中new为更新时用到的,old为回滚时用到的,files下面为nginx.conf和vhosts
    // 目录,handlers为重启nginx服务的task
    // 关于回滚,需要在执行playbook之前先备份一下旧的配置,所以对于老配置文件的管
    // 理一定要严格,千万不能随便去修改线上机器的配置,并且要保证new/files下面的
    // 配置和线上的配置一致
    

    2.把当前线上的文件放到new/files下

    11 directories, 0 files
    [root@ansiblemanager ansible]# cp /usr/local/src/nginx.conf nginx_config/roles/new/files/
    [root@ansiblemanager ansible]# ls -l !$
    ls -l nginx_config/roles/new/files/
    total 4
    -rw-r--r-- 1 root root 2903 Sep 10 16:53 nginx.conf
    

    3.定义变量

    [root@ansiblemanager ansible]#  vim /etc/ansible/nginx_config/roles/new/vars/main.yml
    nx_basedir: /usr/local/nginx
    

    4.定义重新加载nginx服务

    [root@ansiblemanager ansible]# vim /etc/ansible/nginx_config/roles/new/handlers/main.yml  
    - name: restart nginx
      shell: /etc/init.d/nginx reload
    

    5.定义主配置文件

    [root@ansiblemanager ansible]#  vim /etc/ansible/nginx_config/roles/new/tasks/main.yml 
    - name: copy conf file
      copy: src={{ item.src }} dest={{ nginx_basedir }}/{{ item.dest }} backup=yes owner=root group=root mode=0644
      with_items:
        - { src: nginx.conf, dest: conf/nginx.conf }
        - { src: vhosts, dest: conf/ }
      notify: restart nginx
    
    1. 定义入口文件
    ---
    - hosts: 192.168.1.52
      user: root
      roles:
      - new
    

    7.执行更新

    // 修改了默认的配置文件,新建了vhosts文件夹,并在vhosts文件夹里添加了几个配置文件
    -rw-r--r-- 1 root root 56 Sep 10 20:22 update.yml
    [root@ansiblemanager nginx_config]# ansible-playbook update.yml 
    
    PLAY [192.168.1.52] *****************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************
    ok: [192.168.1.52]
    
    TASK [new : copy conf file] *********************************************************************************************************************************************
    ok: [192.168.1.52] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
    changed: [192.168.1.52] => (item={u'dest': u'conf/', u'src': u'vhosts'})
    
    RUNNING HANDLER [new : restart nginx] ***********************************************************************************************************************************
    changed: [192.168.1.52]
    
    PLAY RECAP **************************************************************************************************************************************************************
    192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0 
    
    // 在192.168.1.52上检查,已经更新,不再是默认的那个配置文件了
    [root@ansiblemanager nginx_config]# ansible 192.168.1.52 -m command -a "tail -n 5 /usr/local/nginx/conf/nginx.conf"  
    192.168.1.52 | SUCCESS | rc=0 >>
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            }    
        }
    }
    
    

    8.回滚操作

    // 更新前一定要备份new下files中的内容,再行更新
    // 同步new的内容到old,也相当于备份了一次
    [root@ansiblemanager nginx_config]# rsync -av roles/new/ roles/old/
    sending incremental file list
    files/
    files/nginx.conf
    files/vhosts/
    files/vhosts/bbs.yuankeedu.conf
    files/vhosts/www.yuankeedu.conf
    handlers/
    handlers/main.yml
    tasks/
    tasks/main.yml
    vars/
    vars/main.yml
    
    sent 3,910 bytes  received 150 bytes  8,120.00 bytes/sec
    total size is 3,270  speedup is 0.81
    [root@ansiblemanager nginx_config]# tree
    .
    ├── roles
    │   ├── new
    │   │   ├── files
    │   │   │   ├── nginx.conf
    │   │   │   └── vhosts
    │   │   │       ├── bbs.yuankeedu.conf
    │   │   │       └── www.yuankeedu.conf
    │   │   ├── handlers
    │   │   │   └── main.yml
    │   │   ├── tasks
    │   │   │   └── main.yml
    │   │   └── vars
    │   │       └── main.yml
    │   └── old
    │       ├── files
    │       │   ├── nginx.conf
    │       │   └── vhosts
    │       │       ├── bbs.yuankeedu.conf
    │       │       └── www.yuankeedu.conf
    │       ├── handlers
    │       │   └── main.yml
    │       ├── tasks
    │       │   └── main.yml
    │       └── vars
    │           └── main.yml
    ├── update.retry
    └── update.yml
    
    13 directories, 14 files
    // 对配置文件进行变更,注释掉对vhosts引用
    #    include vhost/*.conf;
    //更新
    [root@ansiblemanager nginx_config]# ansible-playbook update.yml 
    
    PLAY [192.168.1.52] *****************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************
    ok: [192.168.1.52]
    
    TASK [new : copy conf file] *********************************************************************************************************************************************
    changed: [192.168.1.52] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
    ok: [192.168.1.52] => (item={u'dest': u'conf/', u'src': u'vhosts'})
    
    RUNNING HANDLER [new : restart nginx] ***********************************************************************************************************************************
    changed: [192.168.1.52]
    
    PLAY RECAP **************************************************************************************************************************************************************
    192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0   
    
    [root@ansiblemanager nginx_config]# 
    // 检查是否更新
    
    [root@ansiblemanager nginx_config]# ansible 192.168.1.52 -m command -a "grep ^# /usr/local/nginx/conf/nginx.conf"
    192.168.1.52 | SUCCESS | rc=0 >>
    #    include vhost/*.conf;
    
    // 回滚
    // 建立回滚入口文件
    [root@ansiblemanager nginx_config]# vim rollback.yml 
    ---
    - hosts: 192.168.1.52
      user: root
      roles:
      - old
    
    //执行回滚
    "rollback.yml" 5L, 56C written                                                                                                                         
    [root@ansiblemanager nginx_config]# ansible-playbook rollback.yml 
    
    PLAY [192.168.1.52] *****************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************
    ok: [192.168.1.52]
    
    TASK [old : copy conf file] *********************************************************************************************************************************************
    changed: [192.168.1.52] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
    ok: [192.168.1.52] => (item={u'dest': u'conf/', u'src': u'vhosts'})
    
    RUNNING HANDLER [old : restart nginx] ***********************************************************************************************************************************
    changed: [192.168.1.52]
    
    PLAY RECAP **************************************************************************************************************************************************************
    192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0   
    
    // 检查, 回滚成功
    
    [root@ansiblemanager nginx_config]# ansible 192.168.1.52 -m command -a "grep vhost /usr/local/nginx/conf/nginx.conf"
    192.168.1.52 | SUCCESS | rc=0 >>
        include vhost/*.conf;
    
  • 相关阅读:
    LINUX操作系统VIM的安装和配置
    Ubuntu 14.04 LTS中怎样安装fcitx中文输入法
    Ubuntu 速配指南:开启3D桌面特效
    在U盘上安装Windows 7的详细步骤
    设置ip地址、掩码、网关、DNS
    U盘安装电脑系统教程
    取消word中所有超链接
    dos命令批处理发送文字到剪贴板
    Word2007:如何在竖版(纵向)页面中间插入横版(横向)页面
    ubuntu12.04 alternate win7 双系统安装
  • 原文地址:https://www.cnblogs.com/minn/p/9623252.html
Copyright © 2020-2023  润新知