ansible

1、ansible

ansible的配置文件

/etc/ansible/ansible.cfg     主配置文件,配置ansible工作特性,也可以在项目的目录中创建此文件,当前目录下如果也有ansible.cfg,则此文件优先生效,建议每个项目目录下,创建独有的ansible.cfg文件
/etc/ansible/hosts           主机清单
/etc/ansible/roles/          存放角色的目录

1.1 Ansible 的默认配置文件/etc/ansible/ansible.cfg,其中大部分的配置内容无需进行修改

[defaults]
#inventory ? ? = /etc/ansible/hosts     #主机列表配置文件
#library = /usr/share/my_modules/       #库文件存放目录
#remote_tmp = $HOME/.ansible/tmp        #临时py命令文件存放在远程主机目录
#local_tmp ? ? = $HOME/.ansible/tmp     #本机的临时命令执行目录
#forks ? ? ? ? = 5 ?                    #默认并发数
#sudo_user ? ? = root                   #默认sudo 用户
#ask_sudo_pass = True                   #每次执行ansible命令是否询问ssh密码
#ask_pass ? ? = True
#remote_port ? = 22
#host_key_checking = False ? ?          #检查对应服务器的host_key,建议取消此行注释,实现第一次连接自动信任目标主机
#log_path=/var/log/ansible.log          #日志文件,建议启用
#module_name = command ?                #默认模块,可以修改为shell模块

[privilege_escalation]                  #普通用户提权配置
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False

1.2 inventory 主机清单文件

默认的inventory file为/etc/ansible/hosts
inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成

注意: 生产建议在每个项目目录下创建项目独立的hosts文件

官方文档:

https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html

Inventory 参数说明

ansible_ssh_host                #将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port                #ssh端口号.如果不是默认的端口号,通过此变量设置.这种可以使用 ip:端口 192.168.1.100:2222
ansible_ssh_user                #默认的 ssh 用户名
ansible_ssh_pass                #ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass               #sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)    #sudo 命令路径(适用于1.8及以上版本)
ansible_connection              #与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 ‘smart‘,‘smart‘ 方式会根据是否支持 ControlPersist, 来判断‘ssh‘ 方式是否可行
ansible_ssh_private_key_file    #ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type              #目标系统的shell类型.默认情况下,命令的执行使用 ‘sh‘ 语法,可设置为 ‘csh‘ 或 ‘fish‘.
ansible_python_interpreter      #目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python 不是 2.X 版本的 Python.之所以不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....

1.3 ansible相关工具

#查看帮助工具
ansible-doc [options] [module...]
#列出所有模块
ansible-doc -l ?
#查看指定模块帮助用法
ansible-doc ping ?
#查看指定模块帮助用法
ansible-doc -s ?ping 

#ansible执行工具
ansible <host-pattern> [-m module_name] [-a args]

#剧本执行工具
ansible-playbook

#命令行工具连接 https://galaxy.ansible.com 
ansible-galaxy

#加密解密yml文件
ansible-vault [create|decrypt|edit|encrypt|rekey|view]

#交互执行命令,支持tab,ansible 2.0+新增
ansible-console

2、ansible常用模块

2.1 Command模块

功能:在远程主机执行命令,此为默认模块,可忽略-m选项
注意:次命令不支持$VARNAME < > | ; & 等,可能用shell模块实现
注意:模块不具备幂等性
范例:

[root@ansible ~]#ansible web -m command -a ‘chdir=/etc cat centos-release‘
10.0.0.133 | CHANGED | rc=0 >>
CentOS Linux release 8.3.2011
10.0.0.126 | CHANGED | rc=0 >>
CentOS Linux release 8.3.2011

[root@ansible ~]#ansible web -m command -a ‘echo magedu |passwd --stdin wang‘
10.0.0.133 | CHANGED | rc=0 >>
magedu |passwd --stdin wang
10.0.0.126 | CHANGED | rc=0 >>
magedu |passwd --stdin wang

2.2 shell模块

功能:和command相似,用shell执行命令,支持各种符号,比如:*,$, >
注意:此模块不具有幂等性
范例:

[root@ansible ~]#ansible web -m shell -a ‘echo $HOSTNAME‘
10.0.0.133 | CHANGED | rc=0 >>
client
10.0.0.126 | CHANGED | rc=0 >>
mycat
[root@ansible ~]#ansible web -m shell -a "echo $HOSTNAME"
10.0.0.133 | CHANGED | rc=0 >>
ansible
10.0.0.126 | CHANGED | rc=0 >>
ansible

[root@ansible ~]#ansible web -m shell -a ‘echo Centos | passwd --stdin wang‘
10.0.0.126 | CHANGED | rc=0 >>
Changing password for user wang.
passwd: all authentication tokens updated successfully.
10.0.0.133 | CHANGED | rc=0 >>
Changing password for user wang.
passwd: all authentication tokens updated successfully.
[root@ansible ~]#ansible web -m shell -a ‘ls -l /etc/shadow‘
10.0.0.133 | CHANGED | rc=0 >>
---------- 1 root root 806 Jul 21 09:33 /etc/shadow
10.0.0.126 | CHANGED | rc=0 >>
----------. 1 root root 785 Jul 21 09:33 /etc/shadow
[root@ansible ~]#ansible web -m shell -a ‘echo hello >/data/hello.log‘
10.0.0.133 | CHANGED | rc=0 >>

10.0.0.126 | CHANGED | rc=0 >>

[root@ansible ~]#ansible web -m shell -a ‘cat /data/hello.log‘
10.0.0.133 | CHANGED | rc=0 >>
hello
10.0.0.126 | CHANGED | rc=0 >>
hello

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

[root@ansible ~]#vim /etc/ansible/ansible.cfg
#修改下面一行
module_name = shell

2.3 Script模块

功能:在远程主机上运行ansible服务器上的脚本(无需执行权限)
注意:此模块不具有幂等性
范例:

ansible web -m script -a /data/test.sh

2.4 Copy模块

功能:从ansible服务器主控端复制文件到远程主机
注意: src=file 如果是没指明路径,则为当前目录或当前目录下的files目录下的file文件
范例:

#如目标存在,默认覆盖,此处指定先备份
[root@ansible ~]#ansible web -m copy -a "src=/root/ssh_key.sh dest=/tmp/test.sh owner=wang mode=600 backup=yes"
#指定内容,直接生成目标文件 
[root@ansible ~]#ansible web -m copy -a "content=‘test line1\ntest line2\n‘ dest=/tmp/test.txt"
[root@ansible ~]#ansible web -a ‘cat /tmp/test.txt‘
10.0.0.133 | CHANGED | rc=0 >>
test line1
test line2
10.0.0.126 | CHANGED | rc=0 >>
test line1
test line2

#复制/etc目录自身,注意/etc/后面没有/
ansible web -m copy -a "src=/etc dest=/backup"
#复制/etc/下的文件,不包括/etc/目录自身,注意/etc/后面有/
ansible web -m copy -a "src=/etc/ dest=/backup"

2.5 Get_url模块

功能: 用于将文件从http、https或ftp下载到被管理机节点上
常用参数如下:

url              下载文件的URL,支持HTTP,HTTPS或FTP协议
dest             下载到目标路径(绝对路径),如果目标是一个目录,就用服务器上面文件的名称,如果目标设置了名称就用目标设置的名称
owner            指定属主
group            指定属组
mode             指定权限
force            如果yes,dest不是目录,将每次下载文件,如果内容改变,替换文件。如果否,则只有在目标不存在时才会下载该文件
checksum         对目标文件在下载后计算摘要,以确保其完整性
    示例: checksum="sha256:D98291AC[...]B6DC7B97",
    checksum="sha256:http://example.com/path/sha256sum.txt"
url_username     用于HTTP基本认证的用户名。 对于允许空密码的站点,此参数可以不使用`url_password‘
url_password     用于HTTP基本认证的密码。 如果未指定`url_username‘参数,则不会使用`url_password‘参数
validate_certs   如果“no”,SSL证书将不会被验证。 适用于自签名证书在私有网站上使用timeout: URL请求的超时时间,秒为单位

范例:

[root@ansible ~]#ansible web -m get_url -a ‘url=http://nginx.org/download/nginx-1.18.0.tar.gz dest=/usr/local/src/nginx.tar.gz checksum="md5:b2d33d24d89b8b1f87ff5d251aa27eb8"‘

2.6 Fetch模块

功能:从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录
范例:

[root@ansible ~]#ansible web -m fetch -a ‘src=/etc/redhat-release dest=/data/os‘
[root@ansible ~]#tree /data/os/
/data/os/
├── 10.0.0.126
│?? └── etc
│??     └── redhat-release
└── 10.0.0.133
    └── etc
        └── redhat-release

4 directories, 2 files

2.7 File模块

功能:设置文件属性,创建软链接等
范例:

#创建文件
[root@ansible ~]#ansible all -m file -a ‘path=/data/test.txt state=touch‘
[root@ansible ~]#ansible all -m file -a ‘path=/data/test.txt state=absent‘
[root@ansible ~]#ansible all -m file -a ‘path=/root/test.sh owner=wang mode=755 state=touch‘
#创建目录
[root@ansible ~]#ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
#创建软链接,src在当前ansible要存在
[root@ansible ~]#ansible all -m file -a ‘src=/data/testfile path=/data/testfile-link state=link‘
#递归修改目录属性,但不递归至子目录
[root@ansible ~]#ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
#递归修改目录及子目录的属性
[root@ansible ~]#ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes"

2.8 stat模块

功能:检查文件或文件系统的状态
注意:对于Windows目标,请改用win_stat模块
选项:

path      文件/对象的完整路径(必须)

常用的返回值判断:

exists    判断是否存在
isuid     调用用户的ID与所有者ID是否匹配

范例:

[root@ansible ~]#ansible 127.0.0.1 -m stat -a ‘path=/etc/passwd‘
127.0.0.1 | SUCCESS => {
    "changed": false,
    "stat": {
        "atime": 1626783161.0525913,
        "attr_flags": "",
        "attributes": [],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "e4017c7406a7f0e7e52be462ba51fc0f6d4c3e78",
        "ctime": 1625395551.69196,
        "dev": 2049,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 134699518,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1625395551.69196,
        "nlink": 1,
        "path": "/etc/passwd",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 1106,
        "uid": 0,
        "version": "2221273259",
        "wgrp": false,
        "woth": false,
        "writeable": true,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}

经典案例:

[root@ansible ~]#cat stat.yml
- hosts: web
  tasks:
    - name: check file
      stat: path=/data/mysql
      register: st
    - name: debug
      debug: 
        msg: "/data/mysql is not exits"
      when: not st.stat.exits
[root@ansible ~]#ansible-playbool stat.yml

2.9 unarchive模块

功能:解包解压缩
实现有两种用法:
1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes,此为默认值,可省略
2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
常见参数:

copy           默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,会在远程主机上寻找src源文件
remote_src     和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible主机上
src            源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果是远程主机上的路径,则需要设置copy=no
dest           远程主机上的目标路径
mode           设置解压缩后的文件权限

范例:

[root@ansible ~]#ansible all -m unarchive -a ‘src=/data/foo.tgz dest=/var/lib/foo owner=wang group=bin‘
[root@ansible ~]#ansible all -m unarchive -a ‘src=/tmp/foo.zip dest=/data copy=no mode=0777‘
[root@ansible ~]#ansible all -m unarchive -a ‘src=https://example.com/example.zip dest=/data copy=no‘
[root@ansible ~]#ansible web -m unarchive -a ‘src=https://releases.ansible.com/ansible/ansible-2.1.6.0-0.1.rc1.tar.gz dest=/data/ ? owner=root remote_src=yes‘
[root@ansible ~]#ansible web -m unarchive -a ‘src=http://nginx.org/download/nginx-1.18.0.tar.gz dest=/usr/local/src/ copy=no‘

2.10 Archive 模块

功能:打包压缩保存在被管理节点
范例:

[root@ansible ~]#ansible web -m archive ?-a ‘path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=wang mode=0600‘

2.11 Hostname模块

功能:管理主机名
范例:
```[root@ansible ~]#ansible web -m shell -a ‘echo $HOSTNAME‘
10.0.0.133 | CHANGED | rc=0 >>
client
10.0.0.126 | CHANGED | rc=0 >>
mycat
[root@ansible ~]#ansible 10.0.0.133 -m hostname -a "name=websrv"
[root@ansible ~]#ansible web -m shell -a ‘echo $HOSTNAME‘
10.0.0.133 | CHANGED | rc=0 >>
websrv
10.0.0.126 | CHANGED | rc=0 >>
mycat

#### 2.12 Cron模块
功能:计划任务
支持时间:minute,hour,day,month,weekday
范例:

#备份数据库脚本
[root@ansible ~]#cat /root/mysqlbackup.sh
#!/bin/bash
mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql
date +%F_%T.sql.gz

#创建任务
[root@ansible ~]#ansible 10.0.0.8 -m cron -a ‘hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh‘
[root@ansible ~]#ansible web -m cron -a "minute=*/5 job=‘/usr/sbin/ntpdate ntp.aliyun.com &>/dev/null‘ name=Synctime"

#禁用计划任务
[root@ansible ~]#ansible web -m cron -a "minute=*/5 job=‘/usr/sbin/ntpdate 172.20.0.1 &>/dev/null‘ name=Synctime disabled=yes"

#启用计划任务
[root@ansible ~]#ansible web -m cron -a "minute=*/5 job=‘/usr/sbin/ntpdate 172.20.0.1 &>/dev/null‘ name=Synctime disabled=no"

#删除任务
ansible web -m cron -a "name=‘backup mysql‘ state=absent"
ansible web -m cron -a ‘state=absent name=Synctime‘

#### 2.13 Yum和Apt模块
功能:yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本
apt 模块管理 Debian 相关版本的软件包
范例:

#安装
[root@ansible ~]#ansible web -m yum -a ‘name=httpd state=present‘
#启用epel源进行安装
[root@ansible ~]#ansible web -m yum -a ‘name=nginx state=present enablerepo=epel‘
#升级除kernel和foo开头以外的所有包
[root@ansible ~]#ansible websrvs -m yum -a ‘name= state=lastest exclude=kernel,foo*‘
#删除
[root@ansible ~]#ansible websrvs -m yum -a ‘name=httpd state=absent‘

范例:

[root@ansible ~]#ansible web -m yum -a "name=https://mirror.tuna.tsinghua.edu.cn/zabbix/zabbix/5.2/rhel/7/x86_64/zabbix-agent-5.2.5-1.el7.x86_64.rpm"
[root@ubuntu ~]#ansible web -m apt -a ‘name=rsync,psmisc state=absent‘

查看包

[root@ansible ~]#ansible localhost -m yum -a "list=tree"
localhost | SUCCESS => {
"ansible_facts": {
"pkg_mgr": "dnf"
},
"changed": false,
"msg": "",
"results": [
{
"arch": "x86_64",
"epoch": "0",
"name": "tree",
"nevra": "0:tree-1.7.0-15.el8.x86_64",
"release": "15.el8",
"repo": "@System",
"version": "1.7.0",
"yumstate": "installed"
},
{
"arch": "x86_64",
"epoch": "0",
"name": "tree",
"nevra": "0:tree-1.7.0-15.el8.x86_64",
"release": "15.el8",
"repo": "base",
"version": "1.7.0",
"yumstate": "available"
}
]
}

#### 2.14 yum_repository模块

[root@ansible ~]#cat remove_yum_repo.yml

  • hosts: web
    tasks:
    • name: remove repo
      yum_repository:
      name: test
      file: external_repos
      state: absent
      #### 2.15 Service模块
      功能:管理服务
      范例:

      [root@ansible ~]#ansible all -m service -a "name=httpd state=started enabled=yes"
      [root@ansible ~]#ansible all -m service -a ‘name=httpd state=stopped‘
      [root@ansible ~]#ansible all -m service -a ‘name=httpd state=reloaded‘
      [root@ansible ~]#ansible all -m shell -a "sed -i ‘s/^Listen 80/Listen 8080/‘ /etc/httpd/conf/httpd.conf"
      [root@ansible ~]#ansible all -m service -a ‘name=httpd state=restarted‘

      #### 2.16 User模块
      功能:管理用户
      范例:

      #创建用户
      [root@ansible ~]#ansible all -m user -a ‘name=user1 comment="test user" uid=2048 home=/app/user1 group=root‘
      [root@ansible ~]#ansible all -m user -a ‘name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes‘

#remove=yes表示删除用户及家目录等数据,默认remove=no
[root@ansible ~]#ansible all -m user -a ‘name=nginx state=absent remove=yes‘

#生成123456加密的密码

#创建用户test,并生成4096bit的私钥
[root@ansible ~]#ansible web -m user -a ‘name=test generate_ssh_key=yes ssh_key_bits=4096 ssh_key_file=.ssh/id_rsa‘

#### 2.17 Group模块
功能:管理组
范例:

#创建组
[root@ansible ~]#ansible web -m group ?-a ‘name=nginx gid=88 system=yes‘
#删除组
[root@ansible ~]#ansible web -m group -a "name=nginx state=absent"

#### 2.18 Lineinfile模块
一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块
如果想进行多行匹配进行替换需要使用replace模块
这两个都支持正则表达式
功能:相当于sed,可以修改文件内容
范例:

[root@ansible ~]#ansible web -m lineinfile -a "path=/etc/httpd/conf/httpd.conf regexp=‘^Listen‘ line=‘Listen 80‘"
[root@ansible ~]#ansible all -m ? lineinfile -a "path=/etc/selinux/config regexp=‘^SELINUX=‘ line=‘SELINUX=disabled‘"
[root@ansible ~]#ansible all -m lineinfile ?-a ‘dest=/etc/fstab state=absent regexp="^#"‘

#### 2.19 Replace 模块
该模块有点类似于sed命令,主要也是基于正则进行匹配和替换,建议使用
范例:

[root@ansible ~]#ansible all -m replace -a "path=/etc/fstab regexp=‘^(UUID.)‘ replace=‘#\1‘"
[root@ansible ~]#ansible all -m replace -a "path=/etc/fstab regexp=‘^#(UUID.
)‘ replace=‘\1‘"

#### 2.20 SELinux模块
该模块管理 SELInux 策略
范例:

[root@ansible ~]#ansible 10.0.0.133 -m selinux -a ‘state=disabled‘

#### 2.21 reboot模块
[root@ansible ~]#ansible web -m reboot 
#### 2.22 mount挂载和卸载
功能: 挂载和卸载文件系统
范例:

#临时挂载
[root@ansible ~]#mount websrvs -m mount -a ‘src=UUID="bb4f92fa-6073-4f84-9266-6b87e79e6104" path=/home fstype=xfs opts=noatime state=present‘

#临时取消挂载
[root@ansible ~]#mount web -m mount -a ‘path=/home fstype=xfs opts=noatime state=unmounted‘

#永久挂载
[root@ansible ~]#ansible web -m mount -a ‘src=10.0.0.133:/data/wordpress path=/var/www/html/wp-content/uploads opts="_netdev" state=mounted‘

#永久卸载
[root@ansible ~]#ansible web -m mount -a ‘src=10.0.0.133:/data/wordpress path=/var/www/html/wp-content/uploads state=absent‘

#### 2.23 Setup模块
功能: setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度
可以使用gather_facts: no 来禁止 Ansible 收集 facts 信息
范例:

[root@ansible ~]#ansible all -m setup
[root@ansible ~]#ansible all -m setup -a "filter=ansible_nodename"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_hostname"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_domain"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_memtotal_mb"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_memory_mb"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_memfree_mb"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_os_family"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_distribution_major_version"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_distribution_version"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_processor_vcpus"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_all_ipv4_addresses"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_architecture"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_uptime_seconds"
[root@ansible ~]#ansible all -m setup -a "filter=ansible_processor*"
[root@ansible ~]#ansible all -m setup -a ‘filter=ansible_env‘

范例:

[root@ansible ~]#ansible all -m setup -a ‘filter=ansible_python_version‘
10.0.0.135 | SUCCESS => {
"ansible_facts": {
"ansible_python_version": "3.6.8",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
10.0.0.133 | SUCCESS => {
"ansible_facts": {
"ansible_python_version": "3.6.8",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
10.0.0.134 | SUCCESS => {
"ansible_facts": {
"ansible_python_version": "3.6.8",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
10.0.0.126 | SUCCESS => {
"ansible_facts": {
"ansible_python_version": "3.6.8",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

范例:取IP地址

#取所有IP
[root@ansible ~]#ansible 10.0.0.133 -m setup -a ‘filter=ansible_all_ipv4_addresses‘
10.0.0.133 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.0.0.133"
],
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

#取默认IP
[root@ansible ~]#ansible all -m setup -a ‘filter="ansible_default_ipv4"‘
10.0.0.135 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "10.0.0.135",
"alias": "eth0",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "eth0",
"macaddress": "00:0c:29:a7:b0:c1",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
},
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
10.0.0.126 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "10.0.0.126",
"alias": "ens33",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "ens33",
"macaddress": "00:0c:29:29:82:48",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
},
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
10.0.0.134 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "10.0.0.134",
"alias": "eth0",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "eth0",
"macaddress": "00:0c:29:8b:00:8c",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
},
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
10.0.0.133 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "10.0.0.133",
"alias": "eth0",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "eth0",
"macaddress": "00:0c:29:09:26:9f",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
},
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

#### 2.24 debug模块
此模块可以用于输出信息,并且通过 msg 定制输出的信息内容
注意: msg后面的变量有时需要加 " " 引起来
范例: debug 模块默认输出Hello world

[root@ansible ~]#ansible 10.0.0.133 -m debug
10.0.0.133 | SUCCESS => {
"msg": "Hello world!"
}

[root@ansible ~]#cat debug.yml

  • hosts: web

    tasks:

    • name: output Hello world
      debug:
      #默认没有指定msg,默认输出"Hello world!"
      [root@ansible ~]#ansible-playbook debug.yml

PLAY [web] ***

TASK [Gathering Facts] ***
ok: [10.0.0.126]
ok: [10.0.0.133]

TASK [output Hello world] ****
ok: [10.0.0.126] => {
"msg": "Hello world!"
}
ok: [10.0.0.133] => {
"msg": "Hello world!"
}

PLAY RECAP ***
10.0.0.126 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.133 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

范例:利用debug模块输出变量

[root@ansible ~]#cat debug.yml

  • hosts: web

    tasks:

    • name: output variables
      debug:
      msg: Host "{{ ansible_nodename }}" Ip "{{ ansible_default_ipv4.address }}"
      [root@ansible ~]#ansible-playbook debug.yml

PLAY [web] ***

TASK [Gathering Facts] ***
ok: [10.0.0.133]
ok: [10.0.0.126]

TASK [output variables] **
ok: [10.0.0.126] => {
"msg": "Host \"mycat\" Ip \"10.0.0.126\""
}
ok: [10.0.0.133] => {
"msg": "Host \"client\" Ip \"10.0.0.133\""
}

PLAY RECAP ***
10.0.0.126 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.133 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

范例:显示字符串特定字符

[root@ansible ~]#cat debug.yml

  • hosts: all
    gather_facts: no
    vars:
    a: "12345"

    tasks:

    • debug:
      msg: "{{a[2]}}"
      #定义了一个字符串变量a,如果想要获取a字符串的第3个字符,则可以使用”a[2]”获取,索引从0开始,执行上例playbook,debug的输出信息如下:
      [root@ansible ~]#ansible-playbook debug.yml

PLAY [all] ***

TASK [debug] *****
ok: [10.0.0.134] => {
"msg": "3"
}
ok: [10.0.0.126] => {
"msg": "3"
}
ok: [10.0.0.133] => {
"msg": "3"
}
ok: [10.0.0.135] => {
"msg": "3"
}

PLAY RECAP ***
10.0.0.126 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.133 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.134 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.135 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

### 3、ansible-playbook
#### playbook核心组件
官方文档

https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywords

一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:

Hosts 执行的远程主机列表
Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
Variables 内置变量或自定义变量在playbook中调用
Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

#### hosts 组件
Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中

one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs ? ? #或者,两个组的并集
Websrvs:&dbsrvs ? #与,两个组的交集
webservers:!dbsrvs ? #在websrvs组,但不在dbsrvs组

案例:
  • hosts: websrvs:appsrvs
    #### remote_user 组件
    remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
  • hosts: websrvs
    remote_user: root

    tasks:

    • name: test connection
      ping:
      remote_user: magedu
      sudo: yes #默认sudo为root
      sudo_user:wang ? ? #sudo为wang
      #### task列表和action组件
      play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
      task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
      每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出
      task两种格式:

      action: module arguments
      module: arguments ? #建议使用

      注意:shell和command模块后面跟命令,而非key=value
      范例:
  • hosts: websrvs
    remote_user: root
    gather_facts: no

    tasks:

    • name: install httpd
      yum: name=httpd
    • name: start httpd
      service: name=httpd state=started enabled=yes
      #### 其它组件
      某任务的状态在运行后为changed时,可通过"notify"通知给相应的handlers任务可以通过"tags"打标签,可在ansible-playbook命令上使用-t指定进行调用
      #### Playbook中使用handlers和notify
      Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
      案例:
  • hosts: web
    remote_user: root
    gather_facts: no
    tasks:

    • name: Install httpd
      yum: name=httpd state=present
    • name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd
    • name: ensure apache is running
      service: name=httpd state=started enabled=yes

    handlers:

    • name: restart httpd
      service: name=httpd state=restarted
      #### Playbook中使用tags组件
      在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件
      案例:
  • hosts: websrvs
    remote_user: root
    gather_facts: no

    tasks:

    • name: Install httpd
      yum: name=httpd state=present
    • name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: conf
    • name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes
      #### Playbook中使用变量
      ##### 使用 setup 模块中变量
      本模块自动在playbook调用,不要用ansible命令调用
      案例:使用setup变量

      [root@ansible ~]#ansible 10.0.0.126 -m setup -a ‘filter="ansible_default_ipv4"‘
      10.0.0.126 | SUCCESS => {
      "ansible_facts": {
      "ansible_default_ipv4": {
      "address": "10.0.0.126",
      "alias": "ens33",
      "broadcast": "10.0.0.255",
      "gateway": "10.0.0.2",
      "interface": "ens33",
      "macaddress": "00:0c:29:29:82:48",
      "mtu": 1500,
      "netmask": "255.255.255.0",
      "network": "10.0.0.0",
      "type": "ether"
      },
      "discovered_interpreter_python": "/usr/libexec/platform-python"
      },
      "changed": false
      }

[root@ansible ~]#ansible 10.0.0.126 -m setup -a ‘filter=ansible_nodename‘
10.0.0.126 | SUCCESS => {
"ansible_facts": {
"ansible_nodename": "mycat",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}

范例: 
  • hosts: all
    remote_user: root
    gather_facts: yes

    tasks:

    • name: create log file
      file: name=/data/{{ ansible_nodename }}.log state=touch owner=wang mode=600
      ##### 在playbook 命令行中定义变量
      范例:
  • hosts: web
    remote_user: root
    tasks:
    • name: install package
      yum: name={{ pkname }} state=present

[root@ansible ~]#ansible-playbook -e pkname=httpd var2.yml

##### 在playbook文件中定义变量
范例:
  • hosts: web
    remote_user: root

    vars:
    username: user1
    groupname: group1

    tasks:

    • name: create group
      group: name={{ groupname }} state=present
    • name: create user
      user: name={{ username }} group={{ groupname }} state=present

[root@ansible ~]#ansible-playbook -e "username=user2 groupname=group2" var3.yml

范例:
  • hosts: web
    remote_user: root
    vars:
    collect_info: "/data/test/{{ansible_default_ipv4[‘address‘]}}/"

    tasks:

    • name: create IP directory
      file: name="{{collect_info}}" state=directory

#执行结果
[root@client ~]#tree /data/test/
/data/test/
└── 10.0.0.133

1 directory, 0 files

##### 使用变量文件
可以在一个独立的playbook文件中定义变量,在另一个playbook文件中引用变量文件中的变量,比playbook中定义的变量优化级高
范例:

[root@ansible ~]#cat vars.yml
#variables file
package_name: mariadb-server
service_name: mariadb

[root@ansible ~]#cat var5.yml
#install package and start service

  • hosts: db
    remote_user: root
    vars_files:

    • vars.yml

    tasks:

    • name: install package
      yum: name={{ package_name }}
      tags: install
    • name: start service
      service: name={{ service_name }} state=started enabled=yes
      范例2:

      [root@ansible ~]#cat vars2.yml
      var1: httpd
      var2: nginx

[root@ansible ~]#cat var6.yml

  • hosts: web
    remote_user: root
    vars_files:

    • vars2.yml

    tasks:

    • name: create httpd log
      file: name=/app/{{ var1 }}.log state=touch
    • name: create nginx log
      file: name=/app/{{ var2 }}.log state=touch
      ##### 主机清单文件中定义变量
      在inventory 主机清单文件中为指定的主机定义变量以便于在playbook中使用
      范例:

      [web]
      www1.jiangfeng.com http_port=80 maxRequestsPerChild=808
      www2.jiangfeng.com http_port=8080 maxRequestsPerChild=909

      在inventory 主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优先级低于主机变量
      范例:

      [web]
      www1.jiangfeng.com http_port=8080
      www2.jiangfeng.com

[web:vars]
http_port=80
ntp_server=ntp.jiangfeng.com
nfs_server=nfs.jiangfeng.com

范例:

[root@ansible ~]#vim /etc/ansible/hosts
[web]
10.0.0.126 hname=www1 domain=jiangfeng.com
10.0.0.133 hname=www2

[web:vars]
mark="-"
domain=jiangfeng.org

[root@ansible ~]#ansible web -m hostname -a ‘name={{ hname }}{{ mark }}{{ domain }}‘
10.0.0.126 | CHANGED => {
"ansible_facts": {
"ansible_domain": "com.com",
"ansible_fqdn": "www1-jiangfeng.com",
"ansible_hostname": "www1-jiangfeng",
"ansible_nodename": "www1-jiangfeng.com",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"name": "www1-jiangfeng.com"
}
10.0.0.133 | CHANGED => {
"ansible_facts": {
"ansible_domain": "org",
"ansible_fqdn": "www2-jiangfeng.org",
"ansible_hostname": "www2-jiangfeng",
"ansible_nodename": "www2-jiangfeng.org",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"name": "www2-jiangfeng.org"
}

#命令行指定变量
10.0.0.126 | CHANGED => {
"ansible_facts": {
"ansible_domain": "cn",
"ansible_fqdn": "ec2-54-153-56-183.us-west-1.compute.amazonaws.com",
"ansible_hostname": "www1-jiangfeng",
"ansible_nodename": "www1-jiangfeng.cn",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"name": "www1-jiangfeng.cn"
}
10.0.0.133 | CHANGED => {
"ansible_facts": {
"ansible_domain": "cn",
"ansible_fqdn": "www2-jiangfeng.cn",
"ansible_hostname": "www2-jiangfeng",
"ansible_nodename": "www2-jiangfeng.cn",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"name": "www2-jiangfeng.cn"
}

范例:k8s的ansible变量文件

[etcd]
10.0.0.104 NODE_NAME=etcd1
10.0.0.105 NODE_NAME=etcd2
10.0.0.106 NODE_NAME=etcd3

[kube-master]
10.0.0.103 NEW_MASTER=yes
10.0.0.101
10.0.0.102

[kube-node]
10.0.0.109 NEW_NODE=yes
10.0.0.107
10.0.0.108

[harbor]

[ex-lb]
10.0.0.111 LB_ROLE=master EX_APISERVER_VIP=10.0.0.100 EX_APISERVER_PORT=8443
10.0.0.112 LB_ROLE=backup EX_APISERVER_VIP=10.0.0.100 EX_APISERVER_PORT=8443

[chrony]

[all:vars]
CONTAINER_RUNTIME="docker"
CLUSTER_NETWORK="calico"
PROXY_MODE="ipvs"
SERVICE_CIDR="192.168.0.0/16"
CLUSTER_CIDR="172.16.0.0/16"
NODE_PORT_RANGE="20000-60000"
CLUSTER_DNS_DOMAIN="magedu.local."
bin_dir="/usr/bin"
ca_dir="/etc/kubernetes/ssl"
base_dir="/etc/ansible"

#### template 模板
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法
template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件必须存放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件需和templates目录平级,目录结构如下示例:
 ./ 
   ├── temnginx.yml 
   └── templates 
        └── nginx.conf.j2
范例:利用template 同步nginx配置文件

#准备templates/nginx.conf.j2文件
[root@ansible ~]#vim temnginx.yml

  • hosts: web
    remote_user: root

    tasks:

    • name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

    [root@ansible ~]#ansible-playbook temnginx.yml

    ##### template算术运算

    vim nginx.conf.j2
    worker_processes {{ ansible_processor_vcpus**2 }};
    worker_processes {{ ansible_processor_vcpus+2 }};

    #### template中使用流程控制 for 和 if
    template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能
    范例:

    #temlnginx2.yml

  • hosts: websrvs
    remote_user: root
    vars:
    nginx_vhosts:
    • 81
    • 82
    • 83
      tasks:
      • name: template config
        template: src=nginx.conf2.j2 dest=/data/nginx.conf

#templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}

ansible-playbook -C templnginx2.yml --limit 10.0.0.126

#生成的结果:
server {
? listen 81
}
server {
? listen 82
}
server {
? listen 83
}

在模版文件中还可以使用 if条件判断,决定是否生成相关的配置信息
范例:

#templnginx5.yml

  • hosts: web
    remote_user: root
    vars:
    nginx_vhosts:
    • web1:
      listen: 8080
      root: "/var/www/nginx/web1/"
    • web2:
      listen: 8080
      server_name: "web2.jiangfeng.com"
      root: "/var/www/nginx/web2/"
    • web3:
      listen: 8080
      server_name: "web3.jiangfeng.com"
      root: "/var/www/nginx/web3/"
      tasks:
      • name: template config to
        template: src=nginx.conf5.j2 dest=/data/nginx5.conf

#templates/nginx.conf5.j2
{% for vhost in nginx_vhosts %}
server {
? listen {{ vhost.listen }}
? {% if vhost.server_name is defined %}
server_name {{ vhost.server_name }} ? #注意缩进
? {% endif %}
root ?{{ vhost.root }} ? ? ? ? ? ? ? ?#注意缩进
}
{% endfor %}

#生成的结果
server {
? listen 8080
? root /var/www/nginx/web1/
}
server {
? listen 8080
? server_name web2.jiangfeng.com
? root /var/www/nginx/web2/
}
server {
? listen 8080
? server_name web3.jiangfeng.com
? root /var/www/nginx/web3/
}

#### playbook使用 when
when语句,可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用条件测试,jinja2的语法格式
范例:
  • hosts: websrvs
    remote_user: root
    tasks:
    • name: "shutdown RedHat flavored systems"
      command: /sbin/shutdown -h now
      when: ansible_os_family == "RedHat"
      范例:
  • hosts: websrvs
    remote_user: root
    tasks:
    ? - name: "shut down CentOS 6 and Debian 7 systems"
    ? command: /sbin/shutdown -t now
    when: (ansible_facts[‘distribution‘] == "CentOS" and ansible_facts[‘distribution_major_version‘] == "6") or (ansible_facts[‘distribution‘] == "Debian" and ansible_facts[‘distribution_major_version‘] == "7")
    
    #### playbook 使用迭代 with_items(loop)
    迭代:当有需要重复性执行的任务时,可以使用迭代机制
    对迭代项的引用,固定内置变量名为"item"
    要在task中使用with_items给定要迭代的元素列表
    注意: ansible2.5版本后,可以用loop代替with_items
    ##### 列表元素格式:
  • 字符串
  • 字典
    范例:
  • hosts: web
    remote_user: root

    tasks:

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

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

  • name: add several users
    user: name=testuser1 state=present groups=wheel
  • name: add several users
    user: name=testuser2 state=present groups=wheel
  • name: add several users
    user: name=testuser3 state=present groups=wheel

    范例:卸载 mariadb 

    #remove mariadb server

    • hosts: app:!10.0.0.126
      remote_user: root

    tasks:

  • name: stop service
    shell: /etc/init.d/mysqld stop
  • name: delete files and dir
    file: path={{item}} state=absent
    with_items:
    • /usr/local/mysql
    • /usr/local/mariadb-10.2.27-linux-x86_64
    • /etc/init.d/mysqld
    • /etc/profile.d/mysql.sh
    • /etc/my.cnf
    • /data/mysql
  • name: delete user
    user: name=mysql state=absent remove=yes
    迭代嵌套子变量:在迭代中,还可以嵌套子变量,关联多个变量在一起使用
    示例:
    • hosts: websrvs
      remote_user: root
      tasks:
  • name: add some groups
    group: name={{ item }} state=present
    with_items:
    • nginx
    • mysql
    • apache
  • name: add some users
    user: name={{ item.name }} group={{ item.group }} state=present
    with_items:

    • { name: ‘nginx‘, group: ‘nginx‘ }
    • { name: ‘mysql‘, group: ‘mysql‘ }
    • { name: ‘apache‘, group: ‘apache‘ }
      #### 管理节点过多导致的超时问题解决方法
      默认情况下,Ansible将尝试并行管理playbook中所有的机器。对于滚动更新用例,可以使用serial关键字定义Ansible一次应管理多少主机,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例
      范例:

      #vim test_serial.yml

      • hosts: all
        serial: 2 ?#每次只同时处理2个主机,将所有task执行完成后,再选下2个主机再执行所有task,直至所有主机
        gather_facts: False

    ...

    范例:
    • name: test serail
      hosts: all
      serial: "20%" ? #每次只同时处理20%的主机
      ### 4、 roles 角色
      运维复杂的场景:建议使用 roles,代码复用度高
      roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例

      roles/
      mysql/
      nginx/
      tomcat/
      redis/

      默认roles存放路径

      /root/.ansible/roles
      /usr/share/ansible/roles
      /etc/ansible/roles

      #### 5.1  Ansible Roles目录编排
      ##### roles目录结构:

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

      ##### Roles各目录作用
      roles/project/ :项目名称,有以下子目录

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

      #### 5.2 创建 role
      创建role的步骤

      1 创建以roles命名的目录
      2 在roles目录中分别创建以各角色名称命名的目录,如mysql等
      3 在每个角色命名的目录中分别创建files、handlers、tasks、templates和vars等目录;用不到的目录可以创建为空目录,也可以不创建
      4 在每个角色相关的子目录中创建相应的文件,如 tasks/main.yml,templates/nginx.conf.j2
      5 在playbook文件中,调用需要的角色

      针对大型项目使用Roles进行编排
      范例:roles的目录结构

      nginx-role.yml
      roles/
      └── nginx
      ? ? ├── files
      ? ? │ ? └── main.yml
      ? ? ├── tasks
      ? ? │ ? ├── groupadd.yml
      ? ? │ ? ├── install.yml
      ? ? │ ? ├── main.yml
      ? ? │ ? ├── restart.yml
      ? ? │ ? └── useradd.yml
      ? ? └── vars
      ? ? ? ? └── main.yml

      #### 5.3 playbook 调用角色
      调用角色方法1:
    • hosts: websrvs
      remote_user: root
      roles:
  • mysql
  • memcached
  • nginx
    调用角色方法2:
    键role用于指定角色名称,后续的k/v用于传递变量给角色
    • hosts: all
      remote_user: root
      roles:
  • mysql
  • { role: nginx, username: nginx }

    调用角色方法3:
    还可基于条件测试实现角色调用
    • hosts: all
      remote_user: root
      roles:
  • { role: nginx, username: nginx, when: ansible_distribution_major_version == ‘7‘ }
    #### 5.4 roles 中 tags 使用

    [root@ansible ~]#vim app-role.yml

    • hosts: app
      remote_user: root
      roles:
  • { role: nginx ,tags: [ ‘nginx‘, ‘web‘ ] ,when: ansible_distribution_major_version == "6" }
  • { role: httpd ,tags: [ ‘httpd‘, ‘web‘ ] }
  • { role: mysql ,tags: [ ‘mysql‘, ‘db‘ ] }
  • { role: mariadb ,tags: [ ‘mariadb‘, ‘db‘ ] }

[root@ansible ~]#ansible-playbook --tags="nginx,httpd,mysql" app-role.yml

#### 5.5 实战案例
##### 实现 httpd 角色

#创建角色相关的目录
[root@ansible ~]#mkdir -pv /data/ansible/roles/httpd/{tasks,handlers,files}

#创建角色相关的文件
[root@ansible ~]#cd /data/ansible/roles/httpd/

#main.yml 是task的入口文件
[root@ansible httpd]#vim tasks/main.yml

  • include: group.yml
  • include: user.yml
  • include: install.yml
  • include: config.yml
  • include: index.yml
  • include: service.yml

[root@ansible httpd]#vim tasks/group.yml

  • name: create apache group
    group: name=apache system=yes gid=80

[root@ansible httpd]#vim tasks/user.yml

  • name: create apache user
    user: name=apache system=yes shell=/sbin/nologin home=/var/www/ uid=80 group=apache

[root@ansible httpd]#vim tasks/install.yml

  • name: install httpd package
    yum: name=httpd

[root@ansible httpd]#vim tasks/config.yml

  • name: config file
    copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes
    notify: restart

[root@ansible httpd]#vim tasks/index.yml

  • name: index.html
    copy: src=index.html dest=/var/www/html/

[root@ansible httpd]#vim tasks/service.yml

  • name: start service
    service: name=httpd state=started enabled=yes

[root@ansible httpd]#vim handlers/main.yml

  • name: restart
    service: name=httpd state=restarted

#在files目录下准备两个文件
[root@ansible httpd]#ls files/
httpd.conf index.html

[root@ansible httpd]#tree /data/ansible/roles/httpd/
/data/ansible/roles/httpd/
├── files
│?? ├── httpd.conf
│?? └── index.yml
├── handlers
│?? └── main.yml
└── tasks
├── config.yml
├── group.yml
├── index.yml
├── install.yml
├── main.yml
├── service.yml
└── user.yml

3 directories, 10 files

#在playbook中调用角色
[root@ansible httpd]#vim /data/ansible/role_httpd.yml

httpd role

  • hosts: web
    remote_user: root

    roles:

    • httpd

#运行playbook
[root@ansible httpd]#ansible-playbook /data/ansible/role_httpd.yml

### 3、ansible-playbook批量安装httpd,按主机名提供不同的index.html(如node1的index.html欢迎页面为welcome node1)

#我这个方法解题思路是利用模板
[root@ansible ~]#vim install_httpd.yml

  • hosts: app
    remote_user: root
    gather_facts: yes

    tasks:

    • name: Install httpd
      yum: name=httpd state=present
    • name: modify config
      lineinfile: path=/etc/httpd/conf/httpd.conf regexp=‘^Listen‘ line=‘Listen 8080‘
    • name: template html to remote hosts
      template: src=index.html.j2 dest=/var/www/html/index.html
    • name: start service
      service: name=httpd state=started enabled=yes

[root@ansible ~]#vim templates/index.html.j2
welcome {{ ansible_hostname }}

[root@ansible ~]#tree
.
├── templates
│?? └── index.html.j2
├── install_httpd.yml

[root@ansible ~]#ansible-playbook install_httpd.yml

#测试
[root@ansible ~]#ansible app -m shell -a ‘curl 127.0.0.1:8080‘
[WARNING]: Consider using the get_url or uri module rather than running ‘curl‘. If you need to use command because get_url or uri 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.
10.0.0.134 | CHANGED | rc=0 >>
welcome ansible % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 16 100 16 0 0 16000 0 --:--:-- --:--:-- --:--:-- 16000
10.0.0.135 | CHANGED | rc=0 >>
welcome 10 % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 11 100 11 0 0 11000 0 --:--:-- --:--:-- --:--:-- 11000
10.0.0.126 | CHANGED | rc=0 >>
welcome www1-jiangfeng % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 23 100 23 0 0 23000 0 --:--:-- --:--:-- --:--:-- 23000

上一篇:postman提取token


下一篇:Win7 环境weblogic用户名和密码忘记解决方法