ansible笔记汇总

写作时间:2022年2月 系统:centos 7.9 ansible版本:2.9.27

推荐ansible使用方法

1.不要只用一组秘钥对,多主机按模块用几组ssh秘钥对(保障安全)

2.ssh秘钥对的key进行加密,不同的key设置不同的密码,防止别人登录ansible主机能操作所有服务器

可参考下面的链接做配置。在满足上面推荐的使用方法下,能像所有主机只用一个秘钥对而且key不加密一样方便。

利用ssh-agent提升ansible使用的方便及安全性_sinat_24354307的博客-CSDN博客

一.配置文件ansible.cfg

1.1 ansible.cfg文件的位置及顺序

1)ANSIBLE_CONFIG:首先,Ansible命令会检查环境变量指定的位置(export ANSIBLE_CONFIG=/etc/ansible.cfg)
2)./ansible.cfg:其次,将会检查当前目录下的ansible.cfg配置文件
3)~/.ansible.cfg:再次,将会检查当前用户home目录下的.ansible.cfg配置文件
4)/etc/ansible/ansible.cfg:最后,将会检查在用软件包管理工具安装Ansible时自动产生的配置文件

1.2 ansible.cfg 常用配置项举例(用#表示注释)
inventory = /etc/ansible/hosts		#这个参数表示资源清单inventory文件的位置
forks = 5		#并发连接数,默认为5
sudo_user = root		#设置默认执行命令的用户
remote_port = 22		#指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
host_key_checking = False		#设置是否检查SSH主机的密钥,值为True/False。关闭后第一次连接不会提示配置实例
timeout = 60		#设置SSH连接的超时时间,单位为秒
roles_path  = /root/roles  #设置roles的目录
log_path = /var/log/ansible.log		#指定一个存储ansible日志的文件(默认不记录日志)
1.3 默认的ansible.cfg文件
[defaults]
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
1.4 查看生效的配置文件路径

请看下面的第三行

[root@vm10 ~]# ansible --version
ansible 2.9.27
  config file = /root/a.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Oct 14 2020, 14:45:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
[root@vm10 ~]#
1.5 最佳实践配置文件

修改了hosts文件路径并添加了ansible的日志,其他配置可以按需修改

说明日志信息==终端输出的信息+时间+用户。结合命令行的history带时间,来看效果更好。

[defaults]
inventory = /tmp/hosts
log_path = /var/log/ansible.log
roles_path = /root/roles  #设置roles的目录,按需配置,切莫创造需求
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]

二.hosts文件和主机选择

2.1 默认hosts文件路径
/etc/ansible/hosts  # 小编是用yum安装的ansible
2.2配置文件(ansible.cfg)指定hosts文件路径

举例指定hosts文件路径为/tmp/hosts,此时ansible.cfg完整的配置文件如下(默认的基础上新增了第二行)

[defaults]
inventory = /tmp/hosts
[inventory]
...
2.3 执行命令时手动指定用哪个hosts文件
ansible -i /etc/ansible/hosts  ....
2.4 列出某个组都有哪些主机
[root@vm10 ~]# ansible  --list-hosts  all
  hosts (2):
    192.168.9.16
    192.168.9.17
[root@vm10 ~]# ansible  --list-hosts  test1
  hosts (2):
    192.168.9.16
    192.168.9.17
[root@vm10 ~]#
2.5 hosts文件常用配置技巧

也支持主机名,本文没涉及,可自行实验

一个IP可以放到多个组里面

实例的hosts文件为

[test1]
192.168.9.16
192.168.9.17

[test1:children]  # 组嵌套,下面的组也属于test1
test2

[test2]
1.1.1.[1:5:2]   #支持范围,从1到5间隔为2,结果是1 3 5
1.1.2.1  ansible_connection=local  #指定是本地主机不用ssh
1.1.2.2  ansible_connection=ssh ansible_port=222 ansible_user=manage ansible_password=123456  #指定特定的连接信息

三.常用模块举例

3.1 ping模块测试主机连通性
[root@server ~]# ansible web -m ping
192.168.37.122 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
3.2 command模块

不能用管道符,直接用shell模块更通用些。此模块不做具体说明。可查看下方参考链接获取具体用法。

3.3 shell模块

跟在电脑上执行shell一样,可以使用管道符等,不做说明。

3.4 copy模块

这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。其相关选项如下:

src    #被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于"rsync"
content   #用于替换"src",可以直接指定文件的值
dest     #必选项,将源文件复制到的远程主机的绝对路径
backup   #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
directory_mode   #递归设定目录的权限,默认为系统默认权限
force     #当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;设为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"
others     #所有的 file 模块中的选项可以在这里使用

用法举例如下:

1.复制文件
ansible web -m copy -a 'src=~/hello dest=/data/hello'

2.给定内容生成文件,并制定权限
ansible web -m copy -a 'content="I am keer\n" dest=/data/name mode=666'

3.backup的用法,覆盖的时候要不要备份,下面的备份旧文件的选项
ansible web -m copy -a 'content="I am keerya\n" backup=yes dest=/data/name mode=666'

4.force的用法,因目标主机有a.cfg而且跟src的不一样,所以本次copy不做任何操作
[root@vm10 ~]# ansible z -m copy -a "src=a.cfg dest=/tmp/a.cfg  force=no"
192.168.9.16 | SUCCESS => {
    "changed": false,
    "dest": "/tmp/a.cfg",
    "src": "/root/a.cfg"
}
192.168.9.17 | SUCCESS => {
    "changed": false,
    "dest": "/tmp/a.cfg",
    "src": "/root/a.cfg"
}
3.5 file模块

该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。下面是一些常见的命令:

force   #需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group   #定义文件/目录的属组。后面可以加上mode:定义文件/目录的权限
owner   #定义文件/目录的属主。后面必须跟上path:定义文件/目录的路径
recurse  #递归设置文件的属性,只对目录有效,后面跟上src:被链接的源文件路径,只应用于state=link的情况
dest   #被链接到的路径,只应用于state=link的情况
state   #状态,有以下选项:

directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件

用法举例如下:

1.创建目录
ansible web -m file -a 'path=/data/app state=directory'

2.创建软链接
ansible web -m file -a 'path=/data/bbb.jpg src=aaa.jpg state=link'

结果为:
-rw-r--r-- 1 root     root     5649 Dec  4 14:44 aaa.jpg
lrwxrwxrwx 1 root     root        7 Dec  5 10:25 bbb.jpg -> aaa.jpg

3.删除文件
ansible web -m file -a 'path=/data/a state=absent'
3.6 fetch模块

该模块用于从远程某主机获取(复制)文件到本地。有两个选项:

dest:用来存放文件的目录
src:在远程拉取的文件,并且必须是一个file,不能是目录

用法举例:

ansible web -m fetch -a 'src=/data/hello dest=/data'

结果查看:
要注意,文件保存的路径是我们设置的接收目录下的被管制主机ip目录下
[root@server ~]# cd /data/
[root@server data]# ls
1  192.168.37.122  192.168.37.133  fastdfs  web
[root@server data]# cd 192.168.37.122
[root@server 192.168.37.122]# ls
data
[root@server 192.168.37.122]# cd data/
[root@server data]# ls
hello
[root@server data]# pwd
/data/192.168.37.122/data
3.7 cron模块

该模块适用于管理cron计划任务的。
其使用的语法跟我们的crontab文件中的语法一致,同时,可以指定以下选项:

day= #日应该运行的工作( 1-31, *, */2, )
hour= # 小时 ( 0-23, *, */2, )
minute= #分钟( 0-59, *, */2, )
month= # 月( 1-12, *, /2, )
weekday= # 周 ( 0-6 for Sunday-Saturday, )
job= #指明运行的命令是什么
name= #定时任务描述
reboot # 任务在重启时运行,不建议使用,建议使用special_time
special_time #特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state #指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务
user # 以哪个用户的身份执行

举例如下:

1.添加周期任务
ansible web -m cron -a 'name="ntp update every 5 min" minute=*/5 job="/sbin/ntpdate 172.17.0.1 &> /dev/null"'

结果:
#Ansible: ntp update every 5 min
*/5 * * * * /sbin/ntpdate 172.17.0.1 &> /dev/null

2.删除周期任务(只需要名字就行)
ansible web -m cron -a 'name="ntp update every 5 min"  state=absent'

3.设置重启的时候执行
ansible z -m cron -a 'name="test1" special_time=reboot  job="/usr/bin/date  >> /root/a.txt"'

结果:
#Ansible: test1
@reboot /usr/bin/date  >> /root/a.txt

crontab说明

@reboot    :    Run once after reboot.      重启时执行一次
@yearly    :    Run once a year, ie.  "0 0 1 1 *".  一年执行一次,1月1号0点0分执行
@annually  :    Run once a year, ie.  "0 0 1 1 *". 一年执行一次,1月1号0点0分执行
@monthly   :    Run once a month, ie. "0 0 1 * *". 一月执行一次,每月1号0点0分执行
@weekly    :    Run once a week, ie.  "0 0 * * 0". 一周执行一次
@daily     :    Run once a day, ie.   "0 0 * * *".  一天执行一次
@hourly    :    Run once an hour, ie. "0 * * * *".  一小时执行一次
3.8 yum模块

其选项如下:

name=   #所安装的包的名称
state=   #present—>安装, latest—>安装最新的, absent—> 卸载软件。
update_cache   #强制更新yum的缓存
conf_file   #指定远程yum安装时所依赖的配置文件(安装本地已有的包)。
disable_pgp_check  #是否禁止GPG checking,只用于presentor latest
disablerepo   #临时禁止使用yum库。 只用于安装或更新时。
enablerepo   #临时使用的yum库。只用于安装或更新时。

用法举例:

安装httpd
ansible web -m yum -a 'name=httpd state=present'
3.9 service模块

该模块用于服务程序的管理。其主要选项如下:

arguments #命令行提供额外的参数
enabled #设置开机启动。
name= #服务名称
runlevel #开机启动的级别,一般不用指定。
sleep #在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。(定义在剧本中。)
state #有四种状态,分别为:started—>启动服务, stopped—>停止服务, restarted—>重启服务, reloaded—>重载配置

示例:

1.启动服务并设置开机自启动
ansible web -m service -a 'name=nginx state=started enabled=true'

2.停止服务
ansible web -m service -a 'name=nginx state=stopped'
3.10 user模块

该模块主要是用来管理用户账号。其主要选项如下:

comment  # 用户的描述信息
createhome  # 是否创建家目录
force  # 在使用state=absent时, 行为与userdel –force一致.
group  # 指定基本组
groups  # 指定附加组,如果指定为(groups=)表示删除所有组
home  # 指定用户家目录
move_home  # 如果设置为home=时, 试图将用户主目录移动到指定的目录
name  # 指定用户名
non_unique  # 该选项允许改变非唯一的用户ID值
password  # 指定用户密码
remove  # 在使用state=absent时, 行为是与userdel –remove一致
shell  # 指定默认shell
state  # 设置帐号状态,不指定为创建,指定值为absent表示删除
system  # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid  # 指定用户的uid

示例:

1.添加用户并指定uid
ansible web -m user -a 'name=keer uid=11111'

2.添加用户并不创建家目录
ansible web -m user -a 'name=keer  create_home=false'

3.删除用户(不会删除家目录,需要删除的话请用shell模块删除家目录)
ansible web -m user -a 'name=keer state=absent'
3.11 group模块

该模块主要用于添加或删除组。常用的选项如下:

gid=  #设置组的GID号
name=  #指定组的名称
state=  #指定组的状态,默认为创建,设置值为absent为删除
system=  #设置值为yes,表示创建为系统组

举例如下:

1.创建组
ansible web -m group -a 'name=sanguo gid=12222'

2.删除组
ansible web -m group -a 'name=sanguo state=absent'
3.12 script模块

该模块用于将本机的脚本在被管理端的机器上运行。
首先,我们写一个脚本,并给其加上执行权限(测试不加也能成功),然后执行ansible命令

ansible web -m script -a '/tmp/df.sh'
3.13 setup模块

该模块主要用于收集信息,是通过调用facts组件来实现的。
facts组件是Ansible用于采集被管机器设备信息的一个功能,我们可以使用setup模块查机器的所有facts信息,可以使用filter来查看指定信息。整个facts信息被包装在一个JSON格式的数据结构中,ansible_facts是最上层的值。
facts就是变量,内建变量 。每个主机的各种信息,cpu颗数、内存大小等。会存在facts中的某个变量中。调用后返回很多对应主机的信息,在后面的操作中可以根据不同的信息来做不同的操作。如redhat系列用yum安装,而debian系列用apt来安装软件。

filter常用汇总:

ansible_all_ipv4_addresses # ipv4的所有地址
ansible_all_ipv6_addresses # ipv6的所有地址
ansible_date_time # 获取到控制节点时间
ansible_default_ipv4 # 默认的ipv4地址
ansible_distribution # 系统
ansible_distribution_major_version # 系统的大版本
ansible_distribution_version # 系统的版本号
ansible_domain #系统所在的域
ansible_env #系统的环境变量
ansible_hostname #系统的主机名
ansible_fqdn #系统的全名
ansible_machine #系统的架构
ansible_memory_mb #系统的内存信息
ansible_os_family # 系统的家族
ansible_pkg_mgr # 系统的包管理工具
ansible_processor_cores #系统的cpu的核数(每颗)
ansible_processor_count #系统cpu的颗数
ansible_processor_vcpus #系统cpu的总个数=cpu的颗数*CPU的核数
ansible_python # 系统上的python

filter="*关键词*"  #用来搜索关键词  

示例:

1.查看主机所有setup信息(内容很多)
ansible web -m setup

2.过滤内存信息
ansible web -m setup -a 'filter="*mem*"'


3.保存过滤的信息到文件,每个主机占一个文件
ansible web -m setup -a 'filter="*mem*"' --tree /tmp/facts

结果如下:
[root@vm10 ~]# tree /tmp/facts/
/tmp/facts/
├── 192.168.9.16
└── 192.168.9.17

0 directories, 2 files
[root@vm10 ~]# cat /tmp/facts/192.168.9.16 | python -m json.tool
{
    "ansible_facts": {
        "ansible_memfree_mb": 781,
        "ansible_memory_mb": {
            "nocache": {
                "free": 862,
                "used": 128
            },
            "real": {
                "free": 781,
                "total": 990,
                "used": 209
            },
            "swap": {
                "cached": 0,
                "free": 2047,
                "total": 2047,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 990,
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

3.14 lineinfile模块

修改文件专用的模块,非常好用。支持正则

参数:

  • backup: 是否备份原文件,默认为no
  • backrefs:
    • 当backrefs为no时,如果regex没有匹配到行,则添加一行,如果Regx匹配到行,则修改该行
    • 当backrefs为yes时,如果regex没有匹配到行,则保持原文件不变,如果regex匹配到行,则修改该行
    • backrefs默认为no,所以上面那个示例中,我们没有配置backrefs,而默认没有匹配,则修改。

用法举例:

1.在匹配到的行前添加一行或多行内容(一次只改一行,改了之后因已经添加过了,所以执行第二次无效)
把带有"nd1"字段的行后面插入"befor1\nbefor2"因为有\n所以是2行内容
ansible 192.168.9.12 -m lineinfile -a 'dest=/tmp/a.txt  insertbefore="nd1" line="befor1\nbefor2"'

2.在匹配到的行后添加一行或多行内容(一次只改一行,改了之后因已经添加过了,所以执行第二次无效)
把带有"hand1"字段的行后面插入"after1\nafter2"因为有\n所以是2行内容
ansible 192.168.9.12 -m lineinfile -a 'dest=/tmp/a.txt  insertafter="hand1" line="after1\nafter2"'

3.替换匹配到的行的内容并修改文件权限(一次只改一行)
把带有"befor"的行替换为"前面" 并设置文件权限
ansible 192.168.9.12 -m lineinfile -a 'dest=/tmp/a.txt  regex="befor" line="前面" owner=root group=root mode=0777'

4.删除匹配到的行(自动一次删除匹配到的所有行)
删除所有带"befor"字符的行
ansible 192.168.9.12 -m lineinfile -a 'dest=/tmp/a.txt  regex="befor" state=absent'

5.如果该文件存在,且文件中没有跟line中一模一样的行,则添加一行;文件不存在不做操作;文件中有跟line一模一样的行也不做操作
ansible 192.168.9.12 -m lineinfile -a 'dest=/tmp/a.txt line="step5"'

四.playbook

4.1.列出playbook中的主机
[root@vm10 ansible_playbook]# ansible-playbook --list-hosts 01-install_and_start_httpd.yml

playbook: 01-install_and_start_httpd.yml

  play #1 (192.168.9.12): 192.168.9.12  TAGS: []
    pattern: [u'192.168.9.12']
    hosts (1):
      192.168.9.12
4.2.列出playbook中的tasks
[root@vm10 ansible_playbook]# ansible-playbook --list-tasks 01-install_and_start_httpd.yml

playbook: 01-install_and_start_httpd.yml

  play #1 (192.168.9.12): 192.168.9.12  TAGS: []
    tasks:
      install httpd     TAGS: []
      start httpd       TAGS: []
4.3.列出playbook中的tags
[root@vm10 ansible_playbook]# ansible-playbook --list-tags 01-install_and_start_httpd.yml

playbook: 01-install_and_start_httpd.yml

  play #1 (192.168.9.12): 192.168.9.12  TAGS: []
      TASK TAGS: []
4.4.ansible-playbook中shell的用法,不需要用Key=value的形式
---
- hosts: z
  remote_user: root
  tasks:
    - shell: 这里直接输命令即可
4.5.notify和handlers的用法

只有notify对应的task执行了,才会执行对应的handler。比如task用lineinfile模块修改配置文件的,如果文件没有在task中做变动,则对应的handler是不执行的。

---
- hosts: z
  remote_user: root
  tasks:
    - name: step 1 shell
      shell: echo step1  > /tmp/a.txt;sleep 2
      notify: handlers2
    - name: step 2 shell
      shell: echo step2  >> /tmp/a.txt;sleep 2
      notify: 
       - handlers1
       - handlers0
       
  handlers:
      - name: handlers0
        shell: echo hand0 >> /tmp/a.txt;sleep 2
      - name: handlers1
        shell: echo hand1 >> /tmp/a.txt;sleep 2
      - name: handlers2
        shell: echo hand2 >> /tmp/a.txt;sleep 2
      - name: hand3 #没有被notify所以不执行
        shell: echo hand3 >> /tmp/a.txt
# 执行结果的顺序为 step1  -> step2 -> handler0 -> handler1 -> handler2
# handler执行的顺序与handler在playbook中定义的顺序是相同的,与”handler被notify”的顺序无关。
# 先执行task再执行handler
4.6.tags的用法

每个task可以设置tags,可以用ansible-playbook *.yml -t tags1 来执行需要执行的tags1对应的task

- hosts: z
  remote_user: root
  tasks:
   - name: shell1
     shell: echo shell1
     tags:  shell1
   - name: shell2
     shell: shell2
     tags: shell2
     
#举例yml文件如上,如果单独想执行shell1标签的task,执行下面的命令
#ansible-playbook  05-tag.yml  -t shell1
4.7.变量-命令行直接传

注意:检查语法的时候也要加上变量的值,如:

ansible-playbook -C 06-vars-in-shell.yml -e service=httpd -e service2=httpd2  # 多个变量就多个-e即可

全文如下

- hosts: z
  remote_user: root
  tasks:
    - name: 'task1:  {{ service }}'
      shell: echo  {{ service }}
    - name: task2 start {{ service2 }}
      service: name={{ service2 }} state=started

# 执行任务时,输入:
# ansible-playbook  06-vars-in-shell.yml -e service=httpd  -e service2=httpd2
4.8.变量-写到playbook中

注意:vars部分也可以写到tasks部分下面

- hosts: z
  remote_user: root
  vars:  #看这里
    - service: http
    - service2: http2
  tasks:
    - name: 'task1:  {{ service }}'
      shell: echo  {{ service }}
    - name: task2 start {{ service2 }}
      service: name={{ service2 }} state=started
4.9.hosts文件中设定主机变量

分配变量给主机,只需要将变量定义在主机的host之后,就可在 playbooks 中使用。如:

[atlanta]
host1 http_port=80   maxRequestsPerChild=808
host2 http_port=303  maxRequestsPerChild=909
4.10.hosts文件中设定组变量
[atlanta]
host1
host2

[atlanta:vars]  #给atlanta组设定变量
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
4.11.文件定义 Host 和 Group 变量

在 inventory 主文件中保存所有的变量并不是最佳的方式。还可以保存在独立的文件中,这些独立文件与 inventory 文件保持关联。

假设在inventory文件中有一个主机名为 ‘foosball,主机同时属于两个组,一个是 ‘raleigh’,另一个是 ‘webservers’:

[raleigh]
foosball

[webservers]
foosball

那么以下配置文件(YAML 格式)中的变量可以为 ‘foosball’ 主机所用。依次为 ‘raleigh’ 的组变量,’webservers’ 的组变量,’foosball’ 的主机变量:

/etc/ansible/group_vars/raleigh                #注意看路径  group_vars
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball                #注意看路径  host_vars

优先级最高的是host_vars中定义的变量,其次组的变量是根据组的名字排序来进行优先级排序的,组名称靠后的优先级高。

实例:

yaml文件为

- hosts: z
  remote_user: root
  tasks:
    - name: 'task1:  {{ service }}'
      shell: echo  {{ service }}
    - name: task2 start {{ service2 }}
      service: name={{ service2 }} state=started

/etc/ansible/group_vars/z 文件为

service:
  - http3

执行命令(service变量从变量文件读了)

ansible-playbook -C 06-vars-in-shell.yml  -e service2=http2
4.12.动态获取主机列表

Dynamic Inventory指通过外部脚本获取主机列表,并按照ansible 所要求的格式返回给ansilbe命令的。

这部分一般会结合CMDB资管系统、zabbix 监控系统、crobble安装系统、云计算平台等获取主机信息。由于主机资源一般会动态的进行增减,而这些系统一般会智能更新。我们可以通过这些工具提供的API 或者接入库查询等方式返回主机列表。

由于Ansible在接受脚本动态获取主机信息时支持的是json格式,这里直接通过一段代码打印一个段json格式的主机信息:

a.py内容如下,并设置a.py有可执行的权限

#!/usr/bin/env python
# coding=utf-8
# 脚本中一定要加上解释器,如 #!/usr/bin/python
import json
host1ip = ['10.212.52.252', '10.212.52.14']
host2ip = ['10.212.52.16']
group1 = 'test1'
group2 = 'test2'
hostdata = {group1: {"hosts": host1ip},
            group2: {"hosts": host2ip}
            }
print json.dumps(hostdata, indent=4)

a.py的输出为

{
  "test1": {
    "hosts": [
      "10.212.52.252",
      "10.212.52.14"
    ]
  },
  "test2": {
    "hosts": [
      "10.212.52.16"
    ]
  }
}

执行ansible命令

ansible -i a.py test1 -m ping  #即可动态获取test1组的主机清单。不一定非得是python,其它语言也行,输出是json即可。
4.13.循环迭代

当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可。例如:

- name: add several users
  user: name={{ item }} state=present groups=wheel
  with_items:
        - testuser1
        - testuser2

上面语句的功能等同于下面的语句:

- name: add user testuser1
  user: name=testuser1 state=present groups=wheel
- name: add user testuser2
  user: name=testuser2 state=present groups=wheel

另外,with_items中使用的元素还可以是hashes,例如:

- name: add several users
  user: name={{ item.name }} state=present groups={{ item.groups }}
  with_items:
        - { name: 'testuser1', groups: 'wheel'}
        - { name: 'testuser2', groups: 'root'}

【注意】:item是固定变量名。

4.14.条件判断

when语句:在task中使用,jinja2的语法格式。
举例如下:

tasks:
- name: install conf file to centos7
  template: src=files/nginx.conf.c7.j2
  when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
  template: src=files/nginx.conf.c6.j2
  when: ansible_distribution_major_version == "6"
4.15.模板

ansible会根据"模板"文件,为每一台主机生成对应的配置文件(如setup中的变量)。使用Ansible的jinja2模板也就是使用template模块,该模块和copy模块一样,都是讲文件复制到远端主机上去,但是区别在于,template模块可以获取到文件中的变量,而copy则是原封不动的把文件内容复制过去。

实例1:简单举例

模板文件:motd.j2

Welcome to {{ ansible_hostname }}
This system total mem is : {{ ansible_memtotal_mb }} MB
This system free mem is: {{ ansible_memfree_mb }} MB

yaml文件

- hosts: z
  remote_user: root
  tasks:
   - name: muban
     template:  src=./motd.j2  dest=/tmp/motd1
实例2:循环,从0-20

模板文件:xunhuan.j2

{% for n in range(21) %}
        server 172.16.1.{{ n }}
{% endfor %}

yaml文件

- hosts: z
  remote_user: root
  tasks:
    - name: 循环
      template: src=xunhuan.j2 dest=/tmp/xunhuan.txt

输出

        server 172.16.1.0
        server 172.16.1.1
.....省略
        server 172.16.1.20
实例3:判断

模板文件panduan.j2

{% if ansible_hostname == 'vm12' %} #注意vm12要加引号,因为是字符串,不加引号会以为是变量,导致报错
echo {{ ansible_hostname }} yes > /tmp/a.txt
{% elif ansible_hostname == 'vm13' %}

echo {{ ansible_hostname }} yes > /tmp/a.txt
echo {{ ansible_hostname }} yes > /tmp/a.txt
{% endif %}

yaml文件

- hosts: z
  remote_user: root
  tasks:
    - name: 判断
      template: src=panduan.j2 dest=/tmp/panduan.txt

输出(模板是空行输出也是空行)

192.168.9.13 | CHANGED | rc=0 >>

echo vm13 yes > /tmp/a.txt
echo vm13 yes > /tmp/a.txt
192.168.9.12 | CHANGED | rc=0 >>
echo vm12 yes > /tmp/a.txt
实例4:变量默认值

使用default()默认值,当我们定义了变量的值时,采用变量的值,当我们没有定义变量的值时,那么使用默认给定的值.

模板文件中默认值语法如下

Listen: {{ server_port|default(80) }}
4.16.角色

卸载某个角色的话,也需要单独整个roles的目录

1.roles的目录配置

默认目录为:/etc/ansible/roles

可修改配置文件:ansible.cfg

...
[defaults]
roles_path    = /root/roles
....
2.角色各个目录的含义

tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml,当调用角色时,默认会执行main.yml文件中的任务,你也可以将其他需要执行的任务文件通过include的方式包含在tasks/main.yml文件中。
handlers目录:当角色需要调用handlers时,默认会在此目录中的main.yml文件中查找对应的handler
defaults目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,通常,defaults/main.yml文件中的变量都用于设置默认值,以便在你没有设置对应变量值时,变量有默认的值可以使用,定义在defaults/main.yml文件中的变量的优先级是最低的。
vars目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,看到这里你肯定会有疑问,vars/main.yml文件和defaults/main.yml文件的区别在哪里呢?区别就是,defaults/main.yml文件中的变量的优先级是最低的,而vars/main.yml文件中的变量的优先级非常高,如果你只是想提供一个默认的配置,那么你可以把对应的变量定义在defaults/main.yml中,如果你想要确保别人在调用角色时,使用的值就是你指定的值,则可以将变量定义在vars/main.yml中,因为定义在vars/main.yml文件中的变量的优先级非常高,所以其值比较难以覆盖。
meta目录:如果你想要赋予这个角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如 作者信息、角色主要作用等等,你也可以在meta/main.yml文件中定义这个角色依赖于哪些其他角色,或者改变角色的默认调用设定,在之后会有一些实际的示例,此处不用纠结。
templates目录: 角色相关的模板文件可以放置在此目录中,当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件。
files目录:角色可能会用到的一些其他文件可以放置在此目录中,比如,当你定义nginx角色时,需要配置https,那么相关的证书文件即可放置在此目录中。
当然,上述目录并不全是必须的,也就是说,如果你的角色并没有相关的模板文件,那么角色目录中并不用包含templates目录,同理,其他目录也一样,一般情况下,都至少会有一个tasks目录。

3.实例

3.1 在roles目录下生成对应的目录结构

[root@server ansible]# cd roles/
[root@server roles]# ls
[root@server roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
[root@server roles]# tree
.
├── httpd
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
├── mysql
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
└── nginx
    ├── default
    ├── files
    ├── handlers
    ├── meta
    ├── tasks
    ├── templates
    └── vars

3.2 定义配置文件

我们需要修改的配置文件为/tasks/main.yml,下面,我们就来修改一下:

[root@server roles]# vim nginx/tasks/main.yml
- name: cp
  copy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
- name: install
  yum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
- name: conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  tags: nginxconf
  notify: new conf to reload
- name: start service
  service: name=nginx state=started enabled=true

3.3放置我们所需要的文件到指定目录
因为我们定义的角色已经有了新的组成方式,所以我们需要把文件都放到指定的位置,这样,才能让配置文件找到这些并进行加载。
rpm包放在files目录下,模板放在templates目录下:

[root@server nginx]# cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm ./files/
[root@server nginx]# cp /tmp/nginx.conf.j2 ./templates/
[root@server nginx]# tree
.
├── default
├── files
│   └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
├── handlers
├── meta
├── tasks
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars

3.4 修改变量文件

我们在模板中定义的变量,也要去配置文件中加上:

[root@server nginx]# vim vars/main.yml
nginxprot: 9999

3.5定义handler文件

我们在配置文件中定义了notify,所以我么也需要定义handlers,我们来修改配置文件:

[root@server nginx]# vim handlers/main.yml
- name: new conf to reload
  service: name=nginx state=restarted

3.6 定义playbook文件

接下来,我们就来定义剧本文件,由于大部分设置我们都单独配置在了roles里面,所以,接下来剧本就只需要写一点点内容即可:

[root@server ansible]# vim roles.yml 
- hosts: web
  remote_user: root
  roles:
    - nginx

3.7 启动服务

剧本定义完成以后,我们就可以来启动服务了:

[root@server ansible]# ansible-playbook roles.yml

PLAY [web] *********************************************************************

TASK [setup] *******************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]

TASK [nginx : cp] **************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]

TASK [nginx : install] *********************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]

TASK [nginx : conf] ************************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]

TASK [nginx : start service] ***************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]

RUNNING HANDLER [nginx : new conf to reload] ***********************************
changed: [192.168.37.122]
changed: [192.168.37.133]

PLAY RECAP *********************************************************************
192.168.37.122             : ok=6    changed=4    unreachable=0    failed=0   
192.168.37.133             : ok=6    changed=4    unreachable=0    failed=0   
4.卸载角色

请在roles角色里面建一个新的角色"uninstall_角色",然后使用该角色即可

参考链接

自动化运维工具——ansible详解(一) - 珂儿吖 - 博客园 (cnblogs.com)

自动化运维工具——ansible详解(二) - 珂儿吖 - 博客园 (cnblogs.com)

Ansible 1.2.2:Ansible 主机清单文件 hosts_学渣角鹿白的博客-CSDN博客_ansible host文件

Ansible lineinfile模块详解 - breezey - 博客园 (cnblogs.com)

Ansible(三十)-- ansible 中的模板 template模块 jinja2模板引擎(一)_CL82的博客-CSDN博客_ansible template模块

你可能感兴趣的:(ssh,服务器,运维)