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模块
功能:管理主机名 范例:
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/mysql_backup.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模块
- name: Add multiple repositories into the same file (1/2)
yum_repository:
name: epel
description: EPEL YUM repo
file: external_repos
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
gpgcheck: nogpgcheck: no
- name: Add multiple repositories into the same file (2/2)
yum_repository:
name: rpmforge
description: RPMforge YUM repo
file: external_repos
baseurl: http://apt.sw.be/redhat/el7/en/$basearch/rpmforge
mirrorlist: http://mirrorlist.repoforge.org/el7/mirrors-rpmforge
enabled: no
- name: Remove repository from a specific repo file
yum_repository:
name: epel
file: external_repos
state: absent
范例:创建和删除仓库
[root@ansible ~]#cat yum_repo.yml
- hosts: web
tasks:
- name: Add multiple repositories into the same file
yum_repository:
name: test
description: EPEL YUM repo
file: external_repos
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
gpgcheck: no
[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