1、保证网的连通,有repo源,环境:centos7
2、安装依赖:
[root@localhost ~]# yum -y install yum-plugin-priorities
# set [priority=1] to official repository
[root@localhost ~]# sed -i -e "s/\]$/\]\npriority=1/g" /etc/yum.repos.d/CentOS-Base.repo
# install from EPEL
[root@localhost ~]# yum -y install epel-release
3、安装Ansible
[root@localhost ~]# yum --enablerepo=epel -y install ansible openssh-clients
# cat version
[root@localhost ~]# ansible --version
ansible 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
4、设置master主机和目标服务主机
[root@localhost ~]# vi /etc/ansible/ansible.cfg
# line 39: uncomment (not check host key)
host_key_checking = False
[root@localhost ~]# mv /etc/ansible/hosts /etc/ansible/hosts.org
[root@localhost ~]# vi /etc/ansible/hosts
# write clients you manage
192.168.1.124
# possible to group
# define any group name you like
[target_servers]
# write clients to be grouped
192.168.1.123
192.168.1.122
# show all defined hosts
[root@localhost ~]# ansible all --list-host
hosts (3):
192.168.1.124
192.168.1.123
192.168.1.122
# show specific hosts in a group
[root@localhost ~]# ansible target_servers --list-hosts
hosts (2):
192.168.1.123
192.168.1.122
1、将master主机上的密钥对发送到目标服务主机
[root@localhost ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:hGBOReFB6031aykx9qn+gZ6N/58BH99xe55QIN8MufM [email protected]
The key's randomart image is:
+---[RSA 2048]----+
| ++*. . |
| + o + . . . |
| . + o +..+ |
| . + . +o+* |
| . S . *= *.|
| = * B|
| o .. E+|
| o + ...=|
| =o+..+o|
+----[SHA256]-----+
[root@localhost ~]# scp -r /root/.ssh/id_rsa.pub 192.168.1.122:/root/.ssh/authorized_keys
[email protected]'s password:
scp: /root/.ssh/authorized_keys: No such file or directory
# creat .ssh directory,eg:mkdir .ssh/
[root@localhost ~]# scp -r /root/.ssh/id_rsa.pub 192.168.1.122:/root/.ssh/authorized_keys
[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:
id_rsa.pub 100% 408 339.7KB/s 00:00
[root@localhost ~]# scp -r /root/.ssh/id_rsa.pub 192.168.1.123:/root/.ssh/authorized_keys
[email protected]'s password:
id_rsa.pub 100% 408 501.3KB/s 00:00
2、执行ping到目标服务器组
[root@localhost ~]# ansible target_servers -m ping
192.168.1.122 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.123 | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@localhost ~]# ansible target_servers -k -m command -a "uptime"
SSH password:
192.168.1.123 | SUCCESS | rc=0 >>
00:16:12 up 21 min, 3 users, load average: 0.00, 0.00, 0.00
192.168.1.122 | SUCCESS | rc=0 >>
00:16:12 up 18 min, 3 users, load average: 0.00, 0.03, 0.02
[root@localhost ~]# ansible target_servers -k -m command -a "cat /etc/shadow" -b --ask-become-pass
SSH password:
SUDO password[defaults to SSH password]:
192.168.1.123 | SUCCESS | rc=0 >>
root:$6$48ZMF9FizOdf4NfQ$9A.y63BDtbIbLOKfur7KKwq5VXmXU7hHU16WBzOOQL3KVPbdPpf2azuXiGpQ/EhKPMImq/F1IQ4iKipHbsjGk1::0:99999:7:::
bin:*:17110:0:99999:7:::
daemon:*:17110:0:99999:7:::
adm:*:17110:0:99999:7:::
lp:*:17110:0:99999:7:::
sync:*:17110:0:99999:7:::
shutdown:*:17110:0:99999:7:::
halt:*:17110:0:99999:7:::
mail:*:17110:0:99999:7:::
operator:*:17110:0:99999:7:::
games:*:17110:0:99999:7:::
ftp:*:17110:0:99999:7:::
nobody:*:17110:0:99999:7:::
systemd-network:!!:17655::::::
dbus:!!:17655::::::
polkitd:!!:17655::::::
postfix:!!:17655::::::
sshd:!!:17655::::::
nice:$6$ZIbd4kXHFtv5TZBj$LO.KlRrLUVt5CSrhUaHo4O/lpoWThdb6JwkAulxoaf8g1VGrehB.FeUiBoYqnNq22Af2jJkbAxSrpMjgToIHx1::0:99999:7:::
192.168.1.122 | SUCCESS | rc=0 >>
root:$6$.3Or/V3DVSEpiQGe$w3M7sf1NPKZaV263UbRdeMM2oLqp7pobHtqT9HQg4O0B3yLMm/03Wx6RnSnRrlR2W0EQXSFfRmpbYtCb14tC3.::0:99999:7:::
bin:*:17110:0:99999:7:::
daemon:*:17110:0:99999:7:::
adm:*:17110:0:99999:7:::
lp:*:17110:0:99999:7:::
sync:*:17110:0:99999:7:::
shutdown:*:17110:0:99999:7:::
halt:*:17110:0:99999:7:::
mail:*:17110:0:99999:7:::
operator:*:17110:0:99999:7:::
games:*:17110:0:99999:7:::
ftp:*:17110:0:99999:7:::
nobody:*:17110:0:99999:7:::
systemd-network:!!:17655::::::
dbus:!!:17655::::::
polkitd:!!:17655::::::
postfix:!!:17655::::::
sshd:!!:17655::::::
nice:$6$VR5HAGXfMcZR0BXe$skusoEq06akncAh1bM.D6d0iunvUqiSLF.SvW3PHHDQWJjk4j3NyNYZYwpYuvE6n.1KxxRjKOoF9ci3CAds5e.::0:99999:7:::
3、基本用法说明
官方网站:http://docs.ansible.com/ansible/latest/modules/modules_by_category.html
主要用法分两种ansible——ad-hoc和ansible——playbook。
ansible Target Hosts [Option] -m [Module] -a [Arguments] -k [passwd]
you’d like to use another user’s priviledge except root, specify the option “–become-user=xxx”. If you’d like to use another way to use priviledge except sudo (su | pbrun | pfexec | runas), specify the option “–become-method=xxx”.
name|use
–|--
ansible_ad-hoc|类比shell命令,直接执行
ansible_playbook|类比shell scripts命令,适合于复杂应用的部署,可同步或异步的发起任务
1、file模块
作用:完成对文件的基本操作,eg:文件或目录的创建、删除、修改权限等
# 在target_servers主机上创建一个名为testfile的文件,如果testfile文件已经存在,则会更新文件的时间戳,与touch命令的作用相同。
ansible arget_servers -m file -a "path=/testdir/testfile state=touch"
# 在target_servers主机上创建一个名为testfile的文件,如果testfile文件已经存在,则不会进行任何操作
ansible arget_servers -m file -a "path=/testdir/testdir state=directory"
#在target_servers主机上为testfile文件创建软链接文件,软链接名为linkfile,执行下面命令的时候,testfile已经存在
ansible arget_servers -m file -a "path=/testdir/linkfile state=link src=/testdir/testfile"
#在target_servers主机上为testfile文件创建硬链接文件,硬链接名为linkfile,执行下面命令的时候,testfile已经存在
ansible arget_servers -m file -a "path=/testdir/hardfile state=hard src=/testdir/testfile"
#在创建链接文件时,如果源文件不存在,或者链接文件与其他文件同名,强制覆盖同名或者创建链接文件
ansible arget_servers -m file -a "path=/testdir/linkfile state=link src=sourcefile force=yes"
删除远程机器上的指定文件或目录
ansible arget_servers -m file -a "path=/testdir/testdir state=absent"
在创建文件或目录的时候指定属主,或者修改远程主机上的文件或目录的属主。
ansible arget_servers -m file -a "path=/testdir/abc state=touch owner=zsy"
ansible arget_servers -m file -a "path=/testdir/abc owner=zsy"
ansible arget_servers -m file -a "path=/testdir/abc state=directory owner=zsy"
# 在创建文件或目录的时候指定属组,或者修改远程主机上的文件或目录的属组。
ansible arget_servers -m file -a "path=/testdir/abb state=touch group=zsy"
ansible arget_servers -m file -a "path=/testdir/abb group=zsy"
ansible arget_servers -m file -a "path=/testdir/abb state=directory group=zsy"
# 在创建文件或目录的时候指定权限,或者修改远程主机上的文件或目录的权限。
ansible arget_servers -m file -a "path=/testdir/abb state=touch mode=0644"
ansible arget_servers -m file -a "path=/testdir/abb mode=0644"
ansible arget_servers -m file -a "path=/testdir/binfile mode=4700"
ansible arget_servers -m file -a "path=/testdir/abb state=directory mode=0644"
#当操作远程主机中的目录时,同时递归的将目录中的文件的属主属组都设置为rainbowzj
ansible arget_servers -m file -a "path=/testdir/abd state=directory owner=rainbowzj group=rainbowzj recurse=rainbowzj"
2、copy模块
作用:拷贝文件
# 将ansible主机中/testdir/copytest文件复制到远程主机的/opt目录下,注意,如果copytest文件已经存在于远程主机的/opt目录中,并且远程主机中的copytest与ansible主机中copytest文件内容不同,那么使用如下命令时,远程主机中的copytest文件将被覆盖。
ansible target_servers -m copy -a "src=/copytest dest=/opt/"
#在远程主机的/opt目录下生成文件test,test文件中有两行文本,第一行文本为aaa,第二行为bbb,当使用content指定文件内容时,dest参数对应的值必须是一个文件,而不能是一个路径。
ansible target_servers -m copy -a 'content="aaa\nbbb\n" dest=/opt/test'
#将ansible主机中//testdir/copytest文件复制到远程主机的/opt目录中时,如果copytest文件已经存在/opt/copytest文件,并且远程主机中的copytest与ansible主机中copytest文件内容不一致,则不执行拷贝操作,远程主机中的/opt/copytest文件内容不会改变。
ansible target_servers -m copy -a "src=/testdir/copytest dest=/opt/ force=no"
#将ansible主机中//testdir/copytest文件复制到远程主机的/opt目录中时,如果远程主机已经存在/opt/copytest文件,并且远程主机中的copytest与ansible主机中copytest文件内容不一致,会执行拷贝操作,但在执行拷贝操作之前,会将远程主机中的原文件重命名,一座备份,然后在进行拷贝操作。
ansible target_servers -m copy -a "src=/testdir/copytest dest=/opt/ backup=yes"
# 拷贝文件时,指定文件的属主,需要注意,远程主机上必须存在对应的用户。
ansible target_servers -m copy -a "src=/testdir/copytest dest=/opt/ owner=rainbowzj"
# 拷贝文件时,指定文件的属组,需要注意,远程主机上必须存在对应的组。
ansible target_servers -m copy -a "src=/testdir/copytest dest=/opt/ group=rainbowzj"
# 拷贝文件时,指定文件的权限
ansible target_servers -m copy -a "src=/testdir/copytest dest=/opt/ mode=0640"
3、将服务器的信息输入到一个文档中并以‘====’分割
ansible-doc:ansible target_servers -m blockinfile -a 'path=/root/a.txt block="========" '
将CPU信息与是否为固态硬盘的信息放入a.txt中,且中间以’----‘分割。
- hosts: target_servers
tasks:
- shell: cat /proc/cpuinfo > a.txt
- blockinfile: path=/root/a.txt block="------------"
- shell: cat /sys/block/*/queue/rotational >> a.txt
# - shell: fdisk -l > c.txt
# - shell: dmidecode > d.txt
# - shell: free -m > e.txt
# - shell: dd if=/dev/zero of=test bs=8k count=256k conv=fdatasync > f.txt
将所有需要的放入a.txt中。可以通过设置的关键字进行查找对应的位置;
- hosts: target_servers
tasks:
- shell: cat /proc/cpuinfo > a.txt
- blockinfile: path=/root/a.txt block="------------" marker="#{mark} I am fengefu"
- shell: cat /sys/block/*/queue/rotational >> a.txt
- blockinfile: path=/root/a.txt block="============" marker="#{mark} memory"
- shell: fdisk -l >> a.txt
- blockinfile: path=/root/a.txt block="============" marker="#{mark} IOspeed"
- shell: dd if=/dev/zero of=test bs=8k count=256k conv=fdatasync >> a.txt
- blockinfile: path=/root/a.txt block="============" marker="#{mark} present memory"
- shell: free -m >> a.txt
- blockinfile: path=/root/a.txt block="============" marker="#{mark} zhubanxinxi"
- shell: dmidecode -t 16 >> a.txt
发现执行dd语句的结果不能得到返回
1、例:创建文本
[root@localhost ~]# vi playbook_sample.yml
- hosts: target_servers
# define tasks
tasks:
# task name (any name you like)
- name: Test Task
# use file module to set the file state
file: path=/home/test.conf state=touch owner=root mode=0600
# run Playbook
[root@localhost ~]# ansible-playbook playbook_sample.yml
PLAY [target_servers] **************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.1.123]
ok: [192.168.1.122]
TASK [Test Task] *******************************************************************
changed: [192.168.1.123]
changed: [192.168.1.122]
PLAY RECAP *************************************************************************
192.168.1.122 : ok=2 changed=1 unreachable=0 failed=0
192.168.1.123 : ok=2 changed=1 unreachable=0 failed=0
# confirm settings
[root@localhost ~]# ansible target_servers -m command -a "ls -l /home"
192.168.1.122 | SUCCESS | rc=0 >>
total 0
drwx------. 2 nice nice 62 May 4 23:52 nice
-rw-------. 1 root root 0 May 5 00:57 test.conf
192.168.1.123 | SUCCESS | rc=0 >>
total 0
drwx------. 2 nice nice 62 May 4 23:51 nice
-rw-------. 1 root root 0 May 5 00:57 test.conf
2、例:安装httpd服务
[root@localhost ~]# vi 2.yml
- hosts: target_servers
# use priviledge (default : root)
become: yes
# the way to use priviledge
become_method: sudo
# define tasks
tasks:
- name: httpd is installed
yum: name=httpd state=installed
- name: httpd is running and enabled
service: name=httpd state=started enabled=yes
[root@localhost ~]# ansible-playbook 2.yml --ask-become-pass
SUDO password:
PLAY [target_servers] **************************************************************
TASK [Gathering Facts] *************************************************************
ok: [192.168.1.123]
ok: [192.168.1.122]
TASK [httpd is installed] **********************************************************
changed: [192.168.1.122]
changed: [192.168.1.123]
TASK [httpd is running and enabled] ************************************************
changed: [192.168.1.123]
changed: [192.168.1.122]
PLAY RECAP *************************************************************************
192.168.1.122 : ok=3 changed=2 unreachable=0 failed=0
192.168.1.123 : ok=3 changed=2 unreachable=0 failed=0
[root@localhost ~]# ansible target_servers -m shell -a "/bin/systemctl status httpd |head -3" -b --ask-become-pass
SUDO password:
192.168.1.122 | SUCCESS | rc=0 >>
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2018-05-05 00:44:51 CST; 3min 7s ago
192.168.1.123 | SUCCESS | rc=0 >>
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2018-05-05 00:44:52 CST; 3min 7s ago
3、例:使用变量安装包
[root@localhost ~]# vi 3.yml
- hosts: target_servers
become: yes
become_method: sudo
tasks:
- name: General packages are installed
yum: name={{ item }} state=installed
with_items:
- vim-enhanced
- wget
- unzip
tags: General_Packages
[root@localhost ~]# ansible-playbook 3.yml --ask-become-pass
SUDO password:
PLAY [target_servers] *********************************************************************
TASK [Gathering Facts] ********************************************************************
ok: [192.168.1.123]
ok: [192.168.1.122]
TASK [General packages are installed] *****************************************************
changed: [192.168.1.123] => (item=[u'vim-enhanced', u'wget', u'unzip'])
changed: [192.168.1.122] => (item=[u'vim-enhanced', u'wget', u'unzip'])
PLAY RECAP ********************************************************************************
192.168.1.122 : ok=2 changed=1 unreachable=0 failed=0
192.168.1.123 : ok=2 changed=1 unreachable=0 failed=0
[root@localhost ~]# ansible target_servers -m shell -a "rpm -qa | grep -E 'vim-enhanced|wget|unzip'" --ask-become-pass
SUDO password:
[WARNING]: Consider using yum, dnf or zypper module rather than running rpm
192.168.1.122 | SUCCESS | rc=0 >>
wget-1.14-15.el7_4.1.x86_64
vim-enhanced-7.4.160-2.el7.x86_64
unzip-6.0-16.el7.x86_64
192.168.1.123 | SUCCESS | rc=0 >>
wget-1.14-15.el7_4.1.x86_64
vim-enhanced-7.4.160-2.el7.x86_64
unzip-6.0-16.el7.x86_64
4、显示内容格式变换
[root@localhost ~]# ansible 192.168.1.122 -m setup
192.168.1.122 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.1.122"
],
"ansible_all_ipv6_addresses": [
"fe80::8568:bca8:555d:6f"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "05/19/2017",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64",
"LANG": "en_US.UTF-8",
"crashkernel": "auto",
"quiet": true,
"rd.lvm.lv": "centos/swap",
"rhgb": true,
"ro": true,
"root": "/dev/mapper/centos-root"
},
······
[root@localhost ~]# vi 4.yml
- hosts: target_servers
tasks:
- name: Refer to Gathering Facts
command: echo "{{ ansible_distribution }} {{ ansible_distribution_version }}"
register: dist
- debug: msg="{{ dist.stdout }}"
[root@localhost ~]# ansible-playbook 4.yml
PLAY [target_servers] *********************************************************************
TASK [Gathering Facts] ********************************************************************
ok: [192.168.1.122]
ok: [192.168.1.123]
TASK [Refer to Gathering Facts] ***********************************************************
changed: [192.168.1.122]
changed: [192.168.1.123]
TASK [debug] ******************************************************************************
ok: [192.168.1.123] => {
"msg": "CentOS 7.4.1708"
}
ok: [192.168.1.122] => {
"msg": "CentOS 7.4.1708"
}
PLAY RECAP ********************************************************************************
192.168.1.122 : ok=3 changed=1 unreachable=0 failed=0
192.168.1.123 : ok=3 changed=1 unreachable=0 failed=0
5、
[root@localhost ~]# vi 5.yml
# set boolean with failed_when
# To use "when", "failed_when", it's possible to write branch condition in Ansible Playbook.
# create "index.html" if result of boolean is "1"
- hosts: target_servers
become: yes
become_method: sudo
tasks:
- name: index file exists or not
shell: test -f /var/www/html/index.html
ignore_errors: true
register: file_exists
failed_when: file_exists.rc not in [0, 1]
- name: put index.html
shell: echo "httpd index" > /var/www/html/index.html
when: file_exists.rc == 1
[root@localhost ~]# ansible-playbook 3.yml --ask-become-pass
SUDO password:
PLAY [target_servers] ***************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.1.123]
ok: [192.168.1.122]
TASK [General packages are installed] ***********************************************************************************************
ok: [192.168.1.123] => (item=[u'vim-enhanced', u'wget', u'unzip'])
ok: [192.168.1.122] => (item=[u'vim-enhanced', u'wget', u'unzip'])
PLAY RECAP **************************************************************************************************************************
192.168.1.122 : ok=2 changed=0 unreachable=0 failed=0
192.168.1.123 : ok=2 changed=0 unreachable=0 failed=0
[root@localhost ~]# ansible-playbook 5.yml --ask-become-pass
SUDO password:
PLAY [target_servers] ***************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.1.123]
ok: [192.168.1.122]
TASK [index file exists or not] *****************************************************************************************************
changed: [192.168.1.123]
changed: [192.168.1.122]
TASK [put index.html] ***************************************************************************************************************
changed: [192.168.1.123]
changed: [192.168.1.122]
PLAY RECAP **************************************************************************************************************************
192.168.1.122 : ok=3 changed=2 unreachable=0 failed=0
192.168.1.123 : ok=3 changed=2 unreachable=0 failed=0
6、
[root@localhost ~]# vi 6.yml
# To use "notify", "handlers", it's possible to execute a task which is defined in "handlers" after a task completed which has "notify" method.
- hosts: target_servers
become: yes
become_method: sudo
handlers:
- name: restart sshd
service: name=sshd state=restarted
tasks:
- name: edit sshd_config
lineinfile: >
dest=/etc/ssh/sshd_config
regexp="{{ item.regexp }}"
line="{{ item.line }}"
with_items:
- { regexp: '^#PermitRootLogin', line: 'PermitRootLogin no' }
notify: restart sshd
tags: Edit_sshd_config
[root@localhost ~]# ansible-playbook 6.yml --ask-become-pass
SUDO password:
PLAY [target_servers] ***************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.1.123]
ok: [192.168.1.122]
TASK [edit sshd_config] *************************************************************************************************************
changed: [192.168.1.123] => (item={u'regexp': u'^#PermitRootLogin', u'line': u'PermitRootLogin no'})
changed: [192.168.1.122] => (item={u'regexp': u'^#PermitRootLogin', u'line': u'PermitRootLogin no'})
RUNNING HANDLER [restart sshd] ******************************************************************************************************
changed: [192.168.1.122]
changed: [192.168.1.123]
PLAY RECAP **************************************************************************************************************************
192.168.1.122 : ok=3 changed=2 unreachable=0 failed=0
192.168.1.123 : ok=3 changed=2 unreachable=0 failed=0
eg:
ad-hoc:
ansible target_servers -m file -a "path=/testdir/testfile state=touch mode=0700"
playbook:
tasks:
- name: make testfile
file:
path: /testdir/testfile
state: touch
mode: 0700
export HADOOP_HOME=/usr/local/hadoop-2.8.3
export CLASSPATH=.:$HADOOP_HOME/lib:$CLASSPATH
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_ROOT_LOGGER=INFO,console
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib"