• 72209

    文章

  • 658

    评论

  • 17

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

自动化运维—ansible

撸了今年阿里、腾讯和美团的面试,我有一个重要发现.......>>

自动化运维—ansible

一、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安装和远程执行命令

查看ansible 的yum清单,安装ansible ansible-doc

[root@ying01 salt]# yum list | grep ansible
ansible.noarch                            2.6.3-1.el7                  epel     
ansible-doc.noarch                        2.6.3-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    

[root@ying01 salt]# yum -y install ansible  ansible-doc

查看ying01 主机上是否有公钥存在,若不存在则要生成,生成秘钥命令: ssh-keygen

[root@ying01 ~]# ls /root/.ssh/
authorized_keys  id_rsa  id_rsa.pub  known_hosts
[root@ying01 ~]# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+X/2tfggcYIe/3qp98blHj4ySD0GbVmP5QfU7tXXMbE/+FnktHOA3l9+noxXxNXFpaDjc4k+R9TV1R4yG8U0+bx8zucaVTSQWgFCiwDlKhY4pUgfQePtNX+AVUo7yf0+ysz7P3cyUTIInHORB2R/DoKzcxMEM9AHkb//G/UtLaRBhLLWhNGz/R8S5ZhdsC3+X+yKKDVffua8RWkAqevntf4lWz6KEYbuTjxzM7cOXOrHx0/w3/qtvD/Vee+I7vZHkCdqwMfQxn9pTh6c3RwBwcx9jzbJJ7YLV5KmOx0QqSK8qHylgjuO2ZS1wF1+eTdO1D2zP2aEykF6dDNhzQRb5 root@ying01

把此公钥分别 存放在ying01、ying02、ying03机器 的authorized_keys 文件下;

#ansible
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+X/2tfggcYIe/3qp98blHj4ySD0GbVmP5QfU7tXXMbE/+FnktHOA3l9+noxXxNXFpaDjc4k+R9TV1R4yG8U0+bx8zucaVTSQWgFCiwDlKhY4pUgfQePtNX+AVUo7yf0+ysz7P3cyUTIInHORB2R/DoKzcxMEM9AHkb//G/UtLaRBhLLWhNGz/R8S5ZhdsC3+X+yKKDVffua8RWkAqevntf4lWz6KEYbuTjxzM7cOXOrHx0/w3/qtvD/Vee+I7vZHkCdqwMfQxn9pTh6c3RwBwcx9jzbJJ7YLV5KmOx0QqSK8qHylgjuO2ZS1wF1+eTdO1D2zP2aEykF6dDNhzQRb5 root@ying01

编辑/etc/ansible/hosts文件,添加以下语句

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

[testhost]                //主机名称
127.0.0.1                 //主机IP
ying01                    //主机的ID
ying02
ying03

以上写IP也可以,要是写ID,就需要在 /etc/hosts 里面定义;因为之前已经定义ID

[root@ying01 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
113.108.182.52  www.hao123.com www.baidu.com
127.0.0.1  ying.com
192.168.112.136 ying01
192.168.112.138 ying02
192.168.112.139 ying03

测试以下127.0.0.1主机是否联通

[root@ying01 ~]# ssh 127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:ZQlXi+kieRwi2t64Yc5vUhPPWkMub8f0CBjnYRlX2Iw.
ECDSA key fingerprint is MD5:ff:9f:37:87:81:89:fc:ed:af:c6:62:c6:32:53:7a:ad.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
Last login: Tue Sep 11 11:49:11 2018 from 192.168.112.1
[root@ying01 ~]# w
 13:30:28 up 13:31,  2 users,  load average: 0.12, 0.09, 0.07
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    11:49    4.00s  0.45s  0.01s ssh 127.0.0.1
root     pts/1    127.0.0.1        13:30    4.00s  0.06s  0.00s w
[root@ying01 ~]# logout
Connection to 127.0.0.1 closed.

在行testhost主机上,执行命令


[root@ying01 ~]# ansible testhost -m command -a 'wc -l /etc/passwd'
ying03 | SUCCESS | rc=0 >>
25 /etc/passwd

ying02 | SUCCESS | rc=0 >>
30 /etc/passwd

127.0.0.1 | SUCCESS | rc=0 >>
53 /etc/passwd

ying01 | SUCCESS | rc=0 >>
53 /etc/passwd

[root@ying01 ~]# ansible 127.0.0.1 -m command -a 'wc -l /etc/passwd'   //可以针对IP
127.0.0.1 | SUCCESS | rc=0 >>
53 /etc/passwd

[root@ying01 ~]# ansible 'ying03' -m command -a 'wc -l /etc/passwd'   //可以针对单个定义ID
ying03 | SUCCESS | rc=0 >>
25 /etc/passwd

语句释义:ansible 批量执行命令,testhost 是主机的集合,-m后面接调用module的名字, -a后面接调用module的参数

shell模块也可以执行命令

[root@ying01 ~]# ansible  testhost -m shell -a 'wc -l /etc/passwd'
127.0.0.1 | SUCCESS | rc=0 >>
53 /etc/passwd

ying03 | SUCCESS | rc=0 >>
25 /etc/passwd

ying02 | SUCCESS | rc=0 >>
30 /etc/passwd

ying01 | SUCCESS | rc=0 >>
53 /etc/passwd

[root@ying01 ~]# ansible  testhost -m shell -a 'hostname'
ying01 | SUCCESS | rc=0 >>
ying01

127.0.0.1 | SUCCESS | rc=0 >>
ying01

ying03 | SUCCESS | rc=0 >>
ying03

ying02 | SUCCESS | rc=0 >>
ying02

[root@ying01 ~]# ansible 'ying01' -m shell -a 'wc -l /etc/passwd'
ying01 | SUCCESS | rc=0 >>
53 /etc/passwd

[root@ying01 ~]# ansible 127.0.0.1 -m shell -a 'wc -l /etc/passwd'
127.0.0.1 | SUCCESS | rc=0 >>
53 /etc/passwd

错误解决

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

解决: yum install -y libselinux-python

三、 ansible拷贝文件或目录

ansible ying02 -m copy -a "src=/etc/ansible dest=/tmp/ansibletest owner=root group=root mode=0755"

  • ying02 : 指定认证主机,可以是testhost集合,也可以是ying03、127.0.0.1等;
  • copy -a "定义内容" :复制定义的内容
  • src=/etc/ansible :定义复制的源目录及文件
  • dest=/tmp/ansibletest :定义要复制到的位置
  • owner=root :定义uid为root
  • group=root :组为root
  • mode=0755 :权限为755

整个语句意思为:把master机器的/etc/ansible目录复制到远程机器ying02上的/tmp/ansibletest目录,并指定所有者、所有组及其权限;

[root@ying01 ~]# ansible ying02 -m copy -a "src=/etc/ansible  dest=/tmp/ansibletest owner=root group=root mode=0755"
ying02 | SUCCESS => {
    "changed": true, 
    "dest": "/tmp/ansibletest/", 
    "src": "/etc/ansible"
}

在ying02上,查看复制结果

[root@ying02 ~]# ls -la /tmp/ansibletest
总用量 4
drwxr-xr-x   3 root root   21 9月  11 17:35 .
drwxrwxrwt. 17 root root 4096 9月  11 17:35 ..
drwxr-xr-x   3 root root   51 9月  11 17:35 ansible
[root@ying02 ~]# tree /tmp/ansibletest
/tmp/ansibletest
└── ansible
    ├── ansible.cfg
    ├── hosts
    └── roles

2 directories, 2 files

ying02上未指定目录,会自动创建目录

[root@ying01 ~]# ansible ying02 -m copy -a "src=/etc/ansible  dest=/tmp/  owner=root group=root mode=0755"
ying02 | SUCCESS => {
    "changed": true, 
    "dest": "/tmp/", 
    "src": "/etc/ansible"
}

在ying02上,查看复制结果

[root@ying02 ~]# ls -ld /tmp/ansible
drwxr-xr-x 3 root root 51 9月  11 17:40 /tmp/ansible

[root@ying02 ~]# tree /tmp/ansible
/tmp/ansible
├── ansible.cfg
├── hosts
└── roles

1 directory, 2 files

注意:

  • 源目录会放到目标目录下面去,
  • 如果目标指定的目录不存在,它会自动创建。
  • 如果拷贝的是文件,dest指定的名字和源如果不同,并且它不是已经存在的目录,相当于拷贝过去后又重命
  • 但相反,如果desc是目标机器上已经存在的目录,则会直接把文件拷贝到该目录下面。

四、 ansible远程执行脚本

创建test.sh脚本

[root@ying01 ~]# vim /tmp/test.sh 

#!/bin/bash
 echo `date` > /tmp/ansible_test.txt   //创建ansible_test.txt文件 

把此脚本复制到ying03主机上,并改名为test1.sh

[root@ying01 ~]# ansible ying03 -m copy -a "src=/tmp/test.sh  dest=/tmp/test1.sh  owner=root group=root mode=0755"
ying03 | SUCCESS => {
    "changed": true, 
    "checksum": "1a6e4af02dba1bda6fc8e23031d4447efeba0ade", 
    "dest": "/tmp/test1.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "edfaa4371316af8c5ba354e708fe8a97", 
    "mode": "0755", 
    "owner": "root", 
    "size": 48, 
    "src": "/root/.ansible/tmp/ansible-tmp-1536660710.3-139886566503496/source", 
    "state": "file", 
    "uid": 0
}
[root@ying01 ~]# ansible ying03 -m shell -a "/tmp/test1.sh"  //远程执行test1.sh脚本
ying03 | SUCCESS | rc=0 >>

查看ansible_test.txt内容及相关情况

[root@ying03 ~]# cat /tmp/ansible_test.txt
2018年 09月 11日 星期二 18:12:56 CST
[root@ying03 ~]# ls -l  /tmp/ansible_test.txt
-rw-r--r-- 1 root root 43 9月  11 18:12 /tmp/ansible_test.txt

注意:-m command 不支持管道符,而-m shell 支持管道

-m command 不支持管道

[root@ying01 ~]# ansible testhost  -m command -a 'cat /etc/passwd |wc -l'
ying03 | FAILED | rc=1 >>
cat:无效选项 -- l
Try 'cat --help' for more information.non-zero return code

ying02 | FAILED | rc=1 >>
cat:无效选项 -- l
Try 'cat --help' for more information.non-zero return code

ying01 | FAILED | rc=1 >>
cat:无效选项 -- l
Try 'cat --help' for more information.non-zero return code

127.0.0.1 | FAILED | rc=1 >>
cat:无效选项 -- l
Try 'cat --help' for more information.non-zero return code

-m shell 支持管道


[root@ying01 ~]# ansible testhost  -m shell -a 'cat /etc/passwd |wc -l'
ying02 | SUCCESS | rc=0 >>
30

ying03 | SUCCESS | rc=0 >>
25

127.0.0.1 | SUCCESS | rc=0 >>
53

ying01 | SUCCESS | rc=0 >>
53


五、ansible管理任务计划

  • 新建管理任务计划

给ying02机器,创建名为test cron 的管理认为计划

[root@ying01 ~]# ansible ying02 -m cron -a "name='test cron' job='/bin/touch /tmp/1212.txt' weekday=6"
ying02 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron"
    ]

用crontab -l查看此管理计划

[root@ying02 ~]# crontab -l
# Lines below here are managed by Salt, do not edit
#Ansible: test cron
* * * * 6 /bin/touch /tmp/1212.txt
  • 管理计划任务

state=absent 定义状态为无,即可删除此计划任务

[root@ying01 ~]# ansible ying02 -m cron -a "name='test cron' state=absent"
ying02 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}

在ying02上验证,此时已经无任务计划,说明删除成功

[root@ying02 ~]# crontab -l
# Lines below here are managed by Salt, do not edit

注意:由ansible管理的计划任务 (crontab -e),请不要手动修改,否则会导致ansible无法再管理相应的计划任务

六、ansible安装包和管理服务

删除httpd模块

[root@ying01 ~]# ansible ying02 -m yum -a "name=httpd state=removed" 
ying02 | SUCCESS => {
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-80.el7.centos.1 将被 删除\n--> 正在处理依赖关系 httpd = 2.4.6-80.el7.centos.1,它被软件包 httpd-devel-2.4.6-80.el7.centos.1.x86_64 需要\n--> 正在检查事务\n---> 软件包 httpd-devel.x86_64.0.2.4.6-80.el7.centos.1 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package          架构        版本                          源             大小\n================================================================================\n正在删除:\n httpd            x86_64      2.4.6-80.el7.centos.1         @updates      9.4 M\n为依赖而移除:\n httpd-devel      x86_64      2.4.6-80.el7.centos.1         @updates      749 k\n\n事务概要\n================================================================================\n移除  1 软件包 (+1 依赖软件包)\n\n安装大小:10 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  正在删除    : httpd-devel-2.4.6-80.el7.centos.1.x86_64                    1/2 \n  正在删除    : httpd-2.4.6-80.el7.centos.1.x86_64                          2/2 \n  验证中      : httpd-devel-2.4.6-80.el7.centos.1.x86_64                    1/2 \n  验证中      : httpd-2.4.6-80.el7.centos.1.x86_64                          2/2 \n\n删除:\n  httpd.x86_64 0:2.4.6-80.el7.centos.1                                          \n\n作为依赖被删除:\n  httpd-devel.x86_64 0:2.4.6-80.el7.centos.1                                    \n\n完毕!\n"
    ]
}

在ying02机器上,查看httpd是否删除

[root@ying02 ~]# rpm -qa httpd                   
[root@ying02 ~]# netstat -lnpt |grep httpd 

安装httpd

[root@ying01 ~]# ansible ying02 -m yum -a "name=httpd" 
ying02 | SUCCESS => {
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * epel: mirrors.aliyun.com\n * extras: mirrors.aliyun.com\n * updates: centos.ustc.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-80.el7.centos.1 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package      Arch          Version                        Repository      Size\n================================================================================\nInstalling:\n httpd        x86_64        2.4.6-80.el7.centos.1          updates        2.7 M\n\nTransaction Summary\n================================================================================\nInstall  1 Package\n\nTotal download size: 2.7 M\nInstalled size: 9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : httpd-2.4.6-80.el7.centos.1.x86_64                           1/1 \n  Verifying  : httpd-2.4.6-80.el7.centos.1.x86_64                           1/1 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-80.el7.centos.1                                          \n\nComplete!\n"
    ]
}

启动httpd

[root@ying01 ~]# ansible ying02 -m service -a "name=httpd state=started enabled=no" 
ying02 | SUCCESS => {
    "changed": true, 
    "enabled": false, 
    "name": "httpd", 
    "state": "started", 
    篇幅原因,省略

在ying02机器上,验证httpd是否启动

[root@ying02 ~]# netstat -lnpt |grep httpd
tcp6       0      0 :::80                   :::*                    LISTEN      31897/httpd         
[root@ying02 ~]# ps aux |grep httpd
root     31897  0.0  0.2 224020  4996 ?        Ss   20:53   0:00 /usr/sbin/httpd -DFOREGROUND
apache   31898  0.0  0.1 224020  2952 ?        S    20:53   0:00 /usr/sbin/httpd -DFOREGROUND
apache   31899  0.0  0.1 224020  2952 ?        S    20:53   0:00 /usr/sbin/httpd -DFOREGROUND
apache   31900  0.0  0.1 224020  2952 ?        S    20:53   0:00 /usr/sbin/httpd -DFOREGROUND
apache   31901  0.0  0.1 224020  2952 ?        S    20:53   0:00 /usr/sbin/httpd -DFOREGROUND
apache   31902  0.0  0.1 224020  2952 ?        S    20:53   0:00 /usr/sbin/httpd -DFOREGROUND
root     32086  0.0  0.0 112720   984 pts/0    S+   21:01   0:00 grep --color=auto httpd

注意:这里的name是centos系统里的服务名,可以通过chkconfig --list查到。

ansible-doc -l : 列出所有的模块

[root@ying01 ~]# ansible-doc -l|grep httpd
apache2_mod_proxy                                    Set and/or get members' attributes of an Apache httpd 2.4 mod_proxy balancer pool                  
bigip_device_httpd                                   Manage HTTPD related settings on BIG-IP          

ansible-doc cron :查看指定模块的文档

[root@ying01 ~]# ansible-doc cron 
> CRON    (/usr/lib/python2.7/site-packages/ansible/modules/system/cron.py)

        Use this module to manage crontab and environment variables entries. This module allows you to create environment
        variables and named crontab entries, update, or delete them. When crontab jobs are managed: the module includes one
        line with the description of the crontab entry `"#Ansible: <name>"' corresponding to the "name" passed to the module,
        which is used by future ansible/module calls to find/check the state. The "name" parameter should be unique, and
        changing the "name" value will result in a new cron task being created (or a different one being removed). When
        environment variables are managed: no comment line is added, but, when the module needs to find/check the state, it
        uses the "name" parameter to find the environment variable definition line. When using symbols such as %, they must
        be properly escaped.

OPTIONS (= is mandatory):

篇幅原因,下面内容省略

七、使用ansible playbook

  • Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.
  • 如果 Ansible 模块你是工作室中的工具,那么 playbooks 就是你设置的方案计划.
  • Playbooks 的格式是YAML。
[root@ying01 ~]# cd /etc/ansible/
[root@ying01 ansible]# ls
ansible.cfg  hosts  roles
[root@ying01 ansible]# vim test.yml

---
- hosts: ying02                      //针对ying02主机,若果多个主机,可以用逗号隔开
  remote_user: root                  //远程用户为root
  tasks:                             //任务
    - name: test_playbook            //任务名 test_playbook 
      shell: touch /tmp/qqq.txt      //用到shell模块

执行test.yml文件方案

[root@ying01 ansible]# ansible-playbook test.yml

PLAY [ying02] ***********************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying02]

TASK [test_playbook] ****************************************************************************************************************************************
 [WARNING]: Consider using the file module with state=touch rather than running touch.  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: [ying02]

PLAY RECAP **************************************************************************************************************************************************
ying02                     : ok=2    changed=1    unreachable=0    failed=0   

在ying02机器上验证

[root@ying02 ~]# ls -l /tmp/qqq.txt
-rw-r--r-- 1 root root 0 9月  11 21:24 /tmp/qqq.txt
[root@ying02 ~]# date
2018年 09月 11日 星期二 21:26:19 CST

八、playbook里的变量

创建create_user.yml文件

[root@ying01 ansible]# vim create_user.yml

---
- name: create_user
  hosts: ying02
  user: root
  gather_facts: false              //false 不收集主机相关信息;ture :与之相反
  vars:
    - user: "test"
  tasks:
    - name: create user
      user: name="{{ user }}"

create_user.yml文件语句释义:

  • name参数对该playbook实现的功能做一个概述,后面执行过程中,会打印name变量的值,可以省略;
  • gather_facts参数指定了在以下任务部分执行前,是否先执行setup模块获取主机相关 信息,如果后面的task会使用到setup获取的信息时会用到;
  • vars参数,指定了变量,这里指字一个user变量,其值为test,需要注意的是,变量值一定要用引号引住;
  • user指定了调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。

执行此文件

[root@ying01 ansible]# ansible-playbook create_user.yml 

PLAY [create_user] ******************************************************************************************************************************************

TASK [create user] ******************************************************************************************************************************************
changed: [ying02]

PLAY RECAP **************************************************************************************************************************************************
ying02                     : ok=1    changed=1    unreachable=0    failed=0   


在ying02上,测试执行结果

[root@ying02 ~]# id test
uid=1002(test) gid=1002(test) 组=1002(test)

九、playbook里的循环

创建while.yml文件

[root@ying01 ansible]# pwd
/etc/ansible
[root@ying01 ansible]# vim while.yml

---
- hosts: ying02                                       //针对ying02主机
  user: root                                          //用户为root
  tasks: 
    - name: change mode for files                      //任务名称属性   
      file: path=/tmp/{{ item }} state=touch mode=600  //定义变量item ,先创建,再给予权限
      with_items:                                      //item文本集合
        - 1.txt
        - 2.txt
        - 3.txt

执行 while.yml文件;Gathering Facts又出现,因为我们没有禁掉;

[root@ying01 ansible]# ansible-playbook while.yml 

PLAY [ying02] ***********************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying02]

TASK [change mode for files] ********************************************************************************************************************************
changed: [ying02] => (item=1.txt) 
changed: [ying02] => (item=2.txt)
changed: [ying02] => (item=3.txt)

PLAY RECAP **************************************************************************************************************************************************
ying02                     : ok=2    changed=1    unreachable=0    failed=0   

在ying02上,测试此循环试验成功,每个文件都创建,并授予600权限

[root@ying02 ~]# ls -l /tmp/?.txt
-rw------- 1 root root 0 9月  11 22:49 /tmp/1.txt
-rw------- 1 root root 0 9月  11 22:49 /tmp/2.txt
-rw------- 1 root root 0 9月  11 22:49 /tmp/3.txt

十、playbook里的条件判断

创建when.yml条件判断的yml文本

[root@ying01 ansible]# vim when.yml

---
- hosts: testhost
  user: root
  gather_facts: True
  tasks:
    - name: use when
      shell: touch /tmp/when.txt         //
      when: ansible_ens33.ipv4.address == "192.168.112.138"

when: ansible_ens33.ipv4.address == "192.168.112.138" 释义:

  • when: 为ansble模块
  • ansible_ens33 :为一个1级范围
  • ipv4:为ansible_ens33范围内的子集;
  • address:为ipv4的一个子集;
  • == "192.168.112.138" :匹配此IP

上面的when条件语句,就通过查看facter信息,来设置条件;

查看所有的facter信息: ansible ying02 -m setup

[root@ying01 ansible]# ansible ying02 -m setup

以下内容为节选,为了突出when条件

"ansible_ens33": {                                //此为1级条件
            "active": true, 
            "device": "ens33", 
            "features": {
                "busy_poll": "off [fixed]", 
                "fcoe_mtu": "off [fixed]", 
                "generic_receive_offload": "on", 
                "generic_segmentation_offload": "on", 
            
                "vlan_challenged": "off [fixed]"
            }, 
            "hw_timestamp_filters": [],  
            "ipv4": {                            //此为2级条件        
                "address": "192.168.112.138",    //此为3级条件
                "broadcast": "192.168.112.255", 
                "netmask": "255.255.255.0", 
                "network": "192.168.112.0"
            }, 
            "ipv6": [
                {
                    "address": "fe80::43bd:36bd:3f01:f8e8", 
                    "prefix": "64", 
                    "scope": "link"
                }

执行 when.yml方案

[root@ying01 ansible]# ansible-playbook when.yml 

PLAY [testhost] *********************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying02]
ok: [ying03]
ok: [ying01]
ok: [127.0.0.1]

TASK [use when] *********************************************************************************************************************************************
skipping: [127.0.0.1]
skipping: [ying01]
skipping: [ying03]
 [WARNING]: Consider using the file module with state=touch rather than running touch.  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: [ying02]

PLAY RECAP **************************************************************************************************************************************************
127.0.0.1                  : ok=1    changed=0    unreachable=0    failed=0   
ying01                     : ok=1    changed=0    unreachable=0    failed=0   
ying02                     : ok=2    changed=1    unreachable=0    failed=0   
ying03                     : ok=1    changed=0    unreachable=0    failed=0   

在ying02机器上,验证,有when.txt生成;因为只有ying02符合条件

[root@ying02 ~]# ls -l /tmp/when.txt
-rw-r--r-- 1 root root 0 9月  11 23:09 /tmp/when.txt

其他机器都没有,因为不符合when条件

[root@ying03 ~]# ls -l /tmp/when.txt
ls: 无法访问/tmp/when.txt: 没有那个文件或目录

十一、playbook中的handlers

Ansible playbook中的handlers可实现类似逻辑与的功能。(相当于shell中&&)

运用场景为:修改完配置文件后,重新加载配置文件;

创建handlers.yml文件

[root@ying01 ansible]# vim handlers.yml

---
- name: handlers test
  hosts: ying02
  user: root
  tasks:
    - name: copy file
      copy: src=/etc/passwd dest=/tmp/bbb.txt      //先复制
      notify: test handlers
  handlers:
    - name: test handlers
      shell: echo "111111" >> /tmp/bbb.txt        //再写入内容

说明:此处必要copy步骤成功,handlers才能够继续执行;逻辑并且

执行 handlers.yml文件

[root@ying01 ansible]# ansible-playbook handlers.yml 

PLAY [handlers test] ****************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying02]

TASK [copy file] ********************************************************************************************************************************************
changed: [ying02]

RUNNING HANDLER [test handlers] *****************************************************************************************************************************
changed: [ying02]

PLAY RECAP **************************************************************************************************************************************************
ying02                     : ok=3    changed=2    unreachable=0    failed=0   


在ying02机器上,测试bbb.txt文本有111111写入,试验成功

[root@ying02 ~]# tail /tmp/bbb.txt 
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
zabbix:x:997:994:Zabbix Monitoring System:/var/lib/zabbix:/sbin/nologin
memcached:x:996:993:Memcached daemon:/run/memcached:/sbin/nologin
mongod:x:995:992:mongod:/var/lib/mongo:/bin/false
gitlab-www:x:994:990::/var/opt/gitlab/nginx:/bin/false
git:x:993:989::/var/opt/gitlab:/bin/sh
gitlab-redis:x:992:988::/var/opt/gitlab/redis:/bin/false
gitlab-psql:x:991:987::/var/opt/gitlab/postgresql:/bin/sh
gitlab-prometheus:x:990:986::/var/opt/gitlab/prometheus:/bin/sh
111111

十二、 playbook安装nginx

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

第一步:创建/etc/ansible/nginx_install目录及其子目录

[root@ying01 ~]# cd /etc/ansible
[root@ying01 ansible]# cd nginx_install/
[root@ying01 nginx_install]# mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}
[root@ying01 nginx_install]# tree 
.
└── roles                    //install      此目录为安装nginx操作
    ├── common               //此目录为一些准备操作
    │   ├── files               //此目录存放一些安装nginx时用到的文件
    │   ├── handlers            //当发生改变时要执行的操作,比如配置文件发生改变了,就要重启nginx服务
    │   ├── meta                //此目录存放说明信息
    │   ├── tasks               //存放核心的配置文件
    │   ├── templates           //存放一些配置文件,启动脚本等模块文件
    │   └── vars                //自定义变量
    └── install             //此目录为安装nginx操作
        ├── files
        ├── handlers
        ├── meta
        ├── tasks
        ├── templates
        └── vars

第二步:确定需要打包的nginx目录文件

[root@ying01 nginx_install]# pwd
/etc/ansible/nginx_install
您在 /var/spool/mail/root 中有新邮件
[root@ying01 nginx_install]# ls /usr/local/nginx/
client_body_temp  conf  fastcgi_temp  html  logs  proxy_temp  sbin  scgi_temp  uwsgi_temp
[root@ying01 nginx_install]# ls /etc/init.d/nginx 
/etc/init.d/nginx
[root@ying01 nginx_install]# ls /usr/local/nginx/conf/nginx.conf
/usr/local/nginx/conf/nginx.conf

第三步:打包nginx目录下,除vhost的所有有关nginxd文件;把nginx配置文件、启动脚本复制到roles/install/templates/下;

[root@ying01 nginx_install]# cd /usr/local/
[root@ying01 local]# tar czf nginx.tar.gz --exclude "nginx.conf" --exclude "vost"
[root@ying01 local]# tar czf nginx.tar.gz --exclude "nginx.conf" --exclude "vhost" nginx/
[root@ying01 local]# mv nginx.tar.gz /etc/ansible/nginx_install/roles/install/files/
[root@ying01 local]# cp nginx/conf/nginx.conf /etc/ansible/nginx_install/roles/install/templates/
[root@ying01 local]# cp /etc/init.d/nginx /etc/ansible/nginx_install/roles/install/templates

[root@ying01 local]# cd /etc/ansible/nginx_install/roles/
[root@ying01 roles]# tree         //查看已复制到位的文件
.
├── common
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
└── install
    ├── files
    │   └── nginx.tar.gz
    ├── handlers
    ├── meta
    ├── tasks
    ├── templates
    │   ├── nginx
    │   └── nginx.conf
    └── vars

14 directories, 3 files


第四步:定义普通的tasks,创建main.yml文件

[root@ying01 roles]# cd common/
[root@ying01 common]# vim tasks/main.yml

- name: Install initializtion require software
  yum: name={{ item }} state=installed   //循环安装所需包
  with_items:
    - zlib-devel
    - pcre-devel

第五步:定义变量,创建/install/vars/main.yml 文件

[root@ying01 common]# vim /etc/ansible/nginx_install/roles/install/vars/main.yml 

nginx_user: www                         //用户
nginx_port: 800                         //端口
nginx_basedir: /usr/local/nginx         //nginx目录

第六步:定义文件拷贝配置文件

[root@ying01 common]# vim /etc/ansible/nginx_install/roles/install/tasks/copy.yml

- name: Copy Nginx Software                 //把nginx包复制到指定目录
  copy: src=nginx.tar.gz dest=/tmp/nginx.tar.gz owner=root group=root  
- name: Uncompression Nginx Software         //用shell模块远程解压到/usr/local下
  shell: tar zxf /tmp/nginx.tar.gz -C /usr/local/                      
- name: Copy Nginx Start Script              //复制启动nginx脚本                     
  template: src=nginx dest=/etc/init.d/nginx owner=root group=root mode=0755  
- name: Copy Nginx Config                    //复制nginx配置文件,通过变量,即/usr/local/nginx下
  template: src=nginx.conf dest={{ nginx_basedir }}/conf/ owner=root group=root mode=0644

第七步:建立用户、启动服务。删除安装包

[root@ying01 ~]# vim  /etc/ansible/nginx_install/roles/install/tasks/install.yml 

- name: Create Nginx User                   //创建用户信息等
  user: name={{ nginx_user }} state=present createhome=no shell=/sbin/nologin
- name: Start Nginx Service                 //远程启动nginx
  shell: /etc/init.d/nginx start
- name: Add Boot Start Nginx Service        //增加nginx服务,到启动项
  shell: chkconfig --level 345 nginx on
- name: Delete Nginx compression files        //删除nginx.tar.gz包
  shell: rm -rf /tmp/nginx.tar.gz

第八步:创建main.yml,调用copy和install

[root@ying01 ~]# vim /etc/ansible/nginx_install/roles/install/tasks/main.yml 

- include: copy.yml
- include: install.yml

第九步:创建入口文件

[root@ying01 ~]# vim /etc/ansible/nginx_install/install.yml

---
- hosts: ying03
  remote_user: root
  gather_facts: True
  roles:
    - common
    - install

在认证主机ying03上,因为之前安装有nginx,因此把设计nginx改为nginx1,防止试验干涉;

[root@ying03 ~]# cd /usr/local/
[root@ying03 local]# mv nginx nginx1
[root@ying03 local]# ls
bin  etc  games  include  lib  lib64  libexec  mysql  nginx1  sbin  share  src
[root@ying03 local]# ls /etc/init.d/
functions  mysqld  netconsole  network  nginx  README
[root@ying03 local]# cd /etc/init.d/
[root@ying03 init.d]# ls
functions  mysqld  netconsole  network  nginx  README
[root@ying03 init.d]# mv nginx nginx1

在ying01上,开始执行总入口的install.yml文件

[root@ying01 ~]# ansible-playbook /etc/ansible/nginx_install/install.yml

PLAY [ying03] ***********************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying03]

TASK [common : Install initializtion require software] ******************************************************************************************************
ok: [ying03] => (item=[u'zlib-devel', u'pcre-devel'])

TASK [install : Copy Nginx Software] ************************************************************************************************************************
changed: [ying03]

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: [ying03]

TASK [install : Copy Nginx Start Script] ********************************************************************************************************************
changed: [ying03]

TASK [install : Copy Nginx Config] **************************************************************************************************************************
changed: [ying03]

TASK [install : Create Nginx User] **************************************************************************************************************************
changed: [ying03]

TASK [install : Start Nginx Service] ************************************************************************************************************************
changed: [ying03]

TASK [install : Add Boot Start Nginx Service] ***************************************************************************************************************
changed: [ying03]

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: [ying03]

PLAY RECAP **************************************************************************************************************************************************
ying03                     : ok=10   changed=8    unreachable=0    failed=0   


到ying03机器上测试,有nginx的进程,说明是试验成功

[root@ying03 init.d]# ps aux |grep nginx
root      8748  0.0  0.1  45576  1076 ?        Ss   01:01   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody    8749  0.0  0.3  47928  3704 ?        S    01:01   0:00 nginx: worker process
nobody    8750  0.0  0.3  47928  3704 ?        S    01:01   0:00 nginx: worker process
root      8887  0.0  0.0 112720   980 pts/0    S+   01:02   0:00 grep --color=auto nginx

十三、 playbook管理配置文件

生产环境中安装软件包只是在初始化环境的时候用一下,大多时候是需要管理配置文件的。此时可以用playbook功能。

创建playbook配置目录结构

[root@ying01 ~]#  mkdir  -p /etc/ansible/nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
[root@ying01 ~]# cd /etc/ansible/nginx_config/
[root@ying01 nginx_config]# tree
/etc/ansible/nginx_config/
└── roles
    ├── new
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   └── vars
    └── old
        ├── files
        ├── handlers
        ├── tasks
        └── vars

11 directories, 0 files

把nginx虚拟主机,复制到nginx_config/roles/new/files/目录下

[root@ying01 nginx_config]#  cd /usr/local/nginx/conf/
[root@ying01 conf]# cp -r nginx.conf vhost  /etc/ansible/nginx_config/roles/new/files/
[root@ying01 conf]# cd -
/etc/ansible/nginx_config
[root@ying01 nginx_config]# tree
.
└── roles
    ├── new
    │   ├── files
    │   │   ├── nginx.conf
    │   │   └── vhost
    │   │       ├── aaa.com.conf
    │   │       ├── load.conf
    │   │       ├── proxy.conf
    │   │       ├── ssl.conf
    │   │       └── test.com.conf
    │   ├── handlers
    │   ├── tasks
    │   └── vars
    └── old
        ├── files
        ├── handlers
        ├── tasks
        └── vars

12 directories, 6 files

定义变量文件

[root@ying01 nginx_config]#  vim /etc/ansible/nginx_config/roles/new/vars/main.yml

nginx_basedir: /usr/local/nginx

定义nginx重新加载配置

[root@ying01 nginx_config]# vim /etc/ansible/nginx_config/roles/new/handlers/main.yml  

- name: restart nginx
  shell: /etc/init.d/nginx reload

定义主配置文件

[root@ying01 nginx_config]# 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

定义总入口配置,创建update.yml文件

[root@ying01 nginx_config]# vim /etc/ansible/nginx_config/update.yml 

---
- hosts: ying03
  user: root
  roles:
  - new

执行update.yml文件

[root@ying01 nginx_config]# ansible-playbook /etc/ansible/nginx_config/update.yml

PLAY [ying03] ***********************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying03]

TASK [new : copy conf file] *********************************************************************************************************************************
ok: [ying03] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
changed: [ying03] => (item={u'dest': u'conf/', u'src': u'vhost'})

RUNNING HANDLER [new : restart nginx] ***********************************************************************************************************************
changed: [ying03]

PLAY RECAP **************************************************************************************************************************************************
ying03                     : ok=3    changed=2    unreachable=0    failed=0   


在客户端ying03测试,nginx服务重新加载

[root@ying03 ~]# ps aux |grep nginx
root      8945  0.0  0.2  45856  2900 ?        Ss   01:07   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody   10713  0.0  0.3  48208  3964 ?        S    02:11   0:00 nginx: worker process
nobody   10714  0.0  0.3  48208  3964 ?        S    02:11   0:00 nginx: worker process
root     10724  0.0  0.0 112720   984 pts/0    R+   02:12   0:00 grep --color=auto nginx

[root@ying03 ~]# ls /usr/local/nginx/conf/vhost/          //vhost也被复制到指定目录
aaa.com.conf  load.conf  proxy.conf  ssl.conf  test.com.conf

文件的回滚测试

在ying01机器上,把new文件夹备份到old文件夹

[root@ying01 nginx_config]# rsync -av roles/new/ roles/old/
sending incremental file list
files/
files/nginx.conf
files/vhost/
files/vhost/aaa.com.conf
files/vhost/load.conf
files/vhost/proxy.conf
files/vhost/ssl.conf
files/vhost/test.com.conf
handlers/
handlers/main.yml
tasks/
tasks/main.yml
vars/
vars/main.yml

sent 4,919 bytes  received 207 bytes  10,252.00 bytes/sec
total size is 4,105  speedup is 0.80
[root@ying01 nginx_config]# tree
.
├── roles
│   ├── new
│   │   ├── files
│   │   │   ├── nginx.conf
│   │   │   └── vhost
│   │   │       ├── aaa.com.conf
│   │   │       ├── load.conf
│   │   │       ├── proxy.conf
│   │   │       ├── ssl.conf
│   │   │       └── test.com.conf
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   └── old
│       ├── files
│       │   ├── nginx.conf
│       │   └── vhost
│       │       ├── aaa.com.conf
│       │       ├── load.conf
│       │       ├── proxy.conf
│       │       ├── ssl.conf
│       │       └── test.com.conf
│       ├── handlers
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
├── update.retry
└── update.yml

13 directories, 20 files

创建rollback.yml 文件

[root@ying01 nginx_config]# vim /etc/ansible/nginx_config/rollback.yml 

---
- hosts: ying03
  user: root
  roles:
  - old 

在ying上,配置文件nginx.conf,在include前面加上#号

[root@ying01 nginx_config]# vim /etc/ansible/nginx_config/roles/new/files/nginx.conf

 # include vhost/*.conf;

在ying02上测试,发现include前面有#号

[root@ying03 ~]# tail -5 /usr/local/nginx/conf/nginx.conf
    gzip_http_version 1.1;
    gzip_types text/plain application/x-javascript text/css text/htm 
    application/xml;
  # include vhost/*.conf;

执行rollback.yml 文件

[root@ying01 nginx_config]# ansible-playbook /etc/ansible/nginx_config/rollback.yml 

PLAY [ying03] ***********************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [ying03]

TASK [old : copy conf file] *********************************************************************************************************************************
ok: [ying03] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
ok: [ying03] => (item={u'dest': u'conf/', u'src': u'vhost'})

PLAY RECAP **************************************************************************************************************************************************
ying03                     : ok=2    changed=0    unreachable=0    failed=0   


在ying02上测试,发现include的#消失了,试验成功

[root@ying03 ~]# tail -5 /usr/local/nginx/conf/nginx.conf
    gzip_http_version 1.1;
    gzip_types text/plain application/x-javascript text/css text/htm 
    application/xml;
    include vhost/*.conf;
}


695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

欢迎来到梁钟霖个人博客网站。本个人博客网站提供最新的站长新闻,各种互联网资讯。 还提供个人博客模板,最新最全的java教程,java面试题。在此我将尽我最大所能将此个人博客网站做的最好! 谢谢大家,愿大家一起进步!

转载原创文章请注明出处,转载至: 梁钟霖个人博客www.liangzl.com

0条评论

Loading...


发表评论

电子邮件地址不会被公开。 必填项已用*标注

自定义皮肤
注册梁钟霖个人博客