
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
remote_user: root
tasks:
- name: test connection
ping:
remote_user: test
sudo: yes #默认sudo为root
sudo_user:test2 #sudo为test2
action: module arguments #示例: action: shell wall hello
module: arguments #建议使用 #示例: shell: wall hello
[root@ansible ansible]#cat hello.yaml
---
# first yaml file
- hosts: websrvs
remote_user: root
gather_facts: no #不收集系统信息,提高执行效率,如果需要收集系统信息,可以不添加。
tasks:
- name: test network connection
ping:
- name: excute command
command: wall "hello world!"
范例
---
- 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
#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
#Playbook实现
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
--syntax-check #语法检查,可缩写成--syntax, 相当于bash -n
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-i INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的
name
-v -vv -vvv #显示过程
范例:
[root@ansible ansible]#cat hello.yml
---
- hosts: websrvs
tasks:
- name: hello
command: echo "hello ansible"
[root@ansible ansible]#ansible-playbook hello.yml
[root@ansible ansible]#ansible-playbook -v hello.yml
ansible-playbook file.yml --check #只检测
ansible-playbook file.yml
ansible-playbook file.yml --limit websrvs
---
- hosts: dbsrvs
remote_user: root
gather_facts: no
tasks:
- {name: create group, group: name=mysql system=yes gid=306}
- name: create user
user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=306
home=/data/mysql create_home=no
利用 playbook 安装 nginx
---
# install nginx
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: add group nginx
group: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: web page
copy: src=files/index.html dest=/usr/share/nginx/html/index.html
- name: Start Nginx
service: name=nginx state=started enabled=yes
利用 playbook 安装和卸载 httpd
---
#install httpd
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: Instal1 httpd
yum: name=httpd
- name: Modify config list port
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen'
line: 'Listen 8080'
- name: Modify config data1
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^DocumentRoot "/var/www/html"'
line: 'DocumentRoot "/data/html"'
- name: Modify config data2
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^<Directory "/var/www/html">'
line: '<Directory "/data/html">'
- name: Mkdir website dir
file: path=/data/html state=directory
- name: Web html
copy: src=files/index.html dest=/data/html/
- name: Start service
service: name=httpd state=started enabled=yes
# ansible-playbook install_httpd.yml --limit 10.0.0.8
#remove_httpd.yml
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: remove httpd package
yum: name=httpd state=absent
- name: remove apache user
user: name=apache state=absent
- name: remove config file
file: name=/etc/httpd state=absent
- name: remove web html
file: name=/data/html/ state=absent
利用 playbook 安装 MySQL 5.6
[root@ansible ~]#ls -l /data/ansible/files/mysql-5.6.46-linux-glibc2.12-
x86_64.tar.gz
-rw-r--r-- 1 root root 403177622 Dec 4 13:05 /data/ansible/files/mysql-5.6.46-
linux-glibc2.12-x86_64.tar.gz
[root@ansible ~]#cat /data/ansible/files/my.cnf
[mysqld]
socket=/tmp/mysql.sock
user=mysql
symbolic-links=0
datadir=/data/mysql
innodb_file_per_table=1
log-bin
pid-file=/data/mysql/mysqld.pid
[client]
port=3306
socket=/tmp/mysql.sock
[mysqld_safe]
log-error=/var/log/mysqld.log
[root@ansible ~]#cat /data/ansible/files/secure_mysql.sh
#!/bin/bash
/usr/local/mysql/bin/mysql_secure_installation <<EOF
y
test
test
yyyy
EOF
[root@ansible ~]#tree /data/ansible/files/
/data/ansible/files/
├── my.cnf
├── mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
└── secure_mysql.sh
0 directories, 3 files
[root@ansible ~]#cat /data/ansible/install_mysql.yml
---
# install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: dbsrvs
remote_user: root
gather_facts: no
tasks:
- name: install packages
yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
- name: create mysql group
group: name=mysql gid=306
- name: create mysql user
user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes
create_home=no home=/data/mysql
- name: copy tar to remote host and file mode
unarchive: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.12-
x86_64.tar.gz dest=/usr/local/ owner=root group=root
- name: create linkfile /usr/local/mysql
file: src=/usr/local/mysql-5.6.46-linux-glibc2.12-x86_64
dest=/usr/local/mysql state=link
- name: data dir
shell: chdir=/usr/local/mysql/ ./scripts/mysql_install_db --
datadir=/data/mysql --user=mysql
tags: data
- name: config my.cnf
copy: src=/data/ansible/files/my.cnf dest=/etc/my.cnf
- name: service script
shell: /bin/cp /usr/local/mysql/support-files/mysql.server
/etc/init.d/mysqld
- name: enable service
shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
tags: service
- name: PATH variable
copy: content='PATH=/usr/local/mysql/bin:$PATH'
dest=/etc/profile.d/mysql.sh
- name: secure script
script: /data/ansible/files/secure_mysql.sh
tags: script
Playbook中使用handlers和notify
Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
注意:
如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳
过执行,可以使用force_handlers: yes 强制执行handler
案例1:
---
- 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/
notify:
- restart httpd
- wall
- name: ensure apache is running
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd state=restarted
- name: wall
command: wall "The config file is changed"
案例2:
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: add group nginx
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify: ["Restart Nginx","Check Nginx Process"] #或者下面格式
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx &> /tmp/nginx.log
案例3:强制调用handlers
- hosts: websrvs
force_handlers: yes #无论task中的任何一个task失败,仍强制调用handlers
tasks:
- name: config file
copy: src=nginx.conf dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: install package
yum: name=no_exist_package
handlers:
- name: restart nginx
service: name=nginx state=restarted
Playbook中使用tags组件
在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件。
可以一个task对应多个tag,也可以多个task对应一个tag。
还有另外3个特殊关键字用于标签, tagged, untagged 和 all,它们分别是仅运行已标记,只有未标记和所有任务。
vim httpd.yml
---
# tags example
- 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,file ] #写在一行
- conf #写成多行
- file
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
[root@ansible ~]#ansible-playbook --list-tags httpd.yml
[root@ansible ~]#ansible-playbook -t conf,service httpd.yml
[root@ansible ~]#ansible-playbook --skip-tags conf httpd.yml
[root@ansible ~]#ansible-playbook httpd.yml --skip-tags untagged
使用 setup 模块中变量
本模块自动在playbook调用,不要用ansible命令调用,生成的系统状态信息, 并存放在facts变量中
facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等
facts 变量的实际使用场景案例
通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件
变量的优先级从高到低如下:
-e 选项定义变量(ansible命令传入变量) -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名
文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组
变量
ansible 10.0.0.101 -m setup -a 'filter="ansible_default_ipv4"'
10.0.0.101 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "10.0.0.101",
"alias": "eth0",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "eth0",
"macaddress": "00:0c:29:e8:c7:9b",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
}
},
"changed": false
}
[root@centos8 ~]#ansible 10.0.0.8 -m setup -a "filter=ansible_nodename"
10.0.0.8 | SUCCESS => {
"ansible_facts": {
"ansible_nodename": "centos8",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
---
#var1.yml
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: create log file
file: name=/data/{{ ansible_nodename }}.log state=touch owner=test
mode=600
[root@ansible ~]#ansible-playbook var.yml
[root@ansible ansible]#cat show_ip.yml
- hosts: websrvs
tasks:
- name: show eth0 ip address {{ ansible_facts["eth0"]["ipv4"]["address"] }}
debug:
msg: IP address {{ ansible_eth0.ipv4.address }}
#msg: IP address {{ ansible_facts["eth0"]["ipv4"]["address"] }}
#msg: IP address {{ ansible_facts.eth0.ipv4.address }}
范例:
4.9.2 在playbook 命令行中定义变量
范例:
范例:
#msg: IP address {{ ansible_default_ipv4.address }}
#msg: IP address {{ ansible_eth0.ipv4.address }}
#msg: IP address {{ ansible_eth0.ipv4.address.split('.')[-1] }} #取IP中的
最后一个数字
[root@ansible ansible]#ansible-playbook -v show_ip.yml
[root@centos8 ~]#cat test.yml
---
- hosts: websrvs
tasks:
- name: test var
file: path=/data/{{ ansible_facts["eth0"]["ipv4"]["address"] }}.log
state=touch
#file: path=/data/{{ ansible_eth0.ipv4.address }}.log state=touch #和上面效
果一样
[root@centos8 ~]#ansible-playbook test.yml
[root@centos8 ~]#ll /data/10.0.0.8.log
-rw-r--r-- 1 root root 0 Oct 16 18:22 /data/10.0.0.8.log
在playbook命令行中定义变量。
vim var2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
[root@ansible ~]#ansible-playbook -e pkname=httpd var2.yml
在文件中定义变量:
#也可以将多个变量放在一个文件中
[root@ansible ~]#cat vars
pkname1: memcached
pkname2: vsftpd
[root@ansible ~]#vim var2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package {{ pkname1 }
yum: name={{ pkname1 }} state=present
- name: install package {{ pkname2 }
yum: name={{ pkname2 }} state=present
[root@ansible ~]#ansible-playbook -e '@vars' var2.yml