ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
1.连接插件connection plugins:负责和被监控端实现通信;
2.host inventory:指定操作的主机,定义 Ansible 管理主机的清单;
3.Modules : 包括 Ansible 自带的核心模块及自定义模块
4.Plugins : 完成模块功能的补充,包括连接插件、邮件插件等
5.playbook:剧本,定义 Ansible 多任务配置文件,由Ansible 自动执行
6.Ansible : 核心
作为ansible的默认模块,可以允许远程主机范围内的所有shell命令。
注意: 在command的命令中含有像`$ HOME'这样的变量和像``<“',`”>“,
`“”“”,“”;“”和“”&“'将无法正常工作(如果需要这些功能,请使用[shell]模块)
执行远程主机的shell脚本文件
实现主控端向目标主机copy文件。
#src 主控端文件位置
#dest 被控端目标位置
#owner 文件复制过去后的所有者
#group 文件复制过去后的所属组
#mode 文件的权限设定,执行a+x这种方式
安装软件包。
#name 包名
#state (Choices: present, installed, latest, absent, removed)[Default: present]
#disable_gpg_check:禁止gpg检查
#enablerepo:只启动指定的repo
服务管理
基于模板方式生成一个文件复制到远程主机(template使用Jinjia2格式作为文件模版,进行文档内变量的替换的模块。它的每次使用都会被ansible标记为”changed”状态。)
– backup: 如果原目标文件存在,则先备份目标文件
– src:在ansible控制器上的Jinja2格式化模板的路径。 这可以是相对或绝对的路径。
– dest:将模板渲染到远程机器上的位置。
force:是否强制覆盖,默认为yes
– owner:目标文件属主
– group:目标文件属组
– mode:目标文件的权限
file模块主要用于远程主机上的文件操作,file模块包含如下选项:
– force:需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
– group:定义文件/目录的属组
– mode:定义文件/目录的权限
– owner:定义文件/目录的属主
– path:必选项,定义文件/目录的路径
– recurse:递归的设置文件的属性,只对目录有效
– src:要被链接的源文件的路径,只应用于state=link的情况
– dest:被链接到的路径,只应用于state=link的情况
– state:
directory:如果目录不存在,创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
远程主机的用户管理
[root@server1 ansible]# ls
ansible
ansible-2.7.8-1.el7.noarch.rpm
ansible-tower-setup-bundle-3.4.2-1.el7.tar.gz
libtomcrypt-1.17-25.el7.x86_64.rpm
libtommath-0.42.0-5.el7.x86_64.rpm
python2-crypto-2.6.1-13.el7.x86_64.rpm
python2-jmespath-0.9.0-1.el7.noarch.rpm
python-httplib2-0.9.2-0.1.el7.noarch.rpm
python-keyczar-0.71c-2.el7.noarch.rpm
python-paramiko-2.1.1-0.9.el7.noarch.rpm
roles
sshpass-1.06-1.el7.x86_64.rpm
[root@server1 ansible]# yum install -y ansible-2.7.8-1.el7.noarch.rpm python* sshpass-1.06-1.el7.x86_64.rpm libtom*
添加执行用户 配置文件
[root@server1 ~]# useradd devops
[root@server1 ~]# su - devops
[devops@server1 ~]$ mkdir ansible
[devops@server1 ansible]$ vim /etc/ansible/ansible.cfg
[devops@server1 ansible]$ vim ansible.cfg
[defaults]
inventory = inventory
[devops@server1 ansible]$ ls
ansible.cfg
[devops@server1 ansible]$ vim inventory
[test]
server2
[db]
server3
[webservers:children]
test
db
[root@server2 ~]# useradd devops
[root@server2 ~]# passwd devops
[root@server3 ~]# useradd devops
[root@server3 ~]# passwd devops
[devops@server1 .ssh]$ ssh-copy-id server2
[devops@server1 .ssh]$ ssh-copy-id server3
[devops@server1 ~]$ cd ansible/
[devops@server1 ansible]$ ansible all --list-hosts
hosts (2):
server3
server2
ansible 命令
[devops@server1 ansible]$ ansible all -m ping #-m 执行shell
server2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
server3 | SUCCESS => {
"changed": false,
"ping": "pong"
}
[devops@server1 ansible]$ ansible test -a 'df -h'
server2 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 17G 1.1G 16G 6% /
devtmpfs 910M 0 910M 0% /dev
tmpfs 920M 0 920M 0% /dev/shm
tmpfs 920M 17M 904M 2% /run
tmpfs 920M 0 920M 0% /sys/fs/cgroup
/dev/sda1 1014M 139M 876M 14% /boot
tmpfs 184M 0 184M 0% /run/user/0
tmpfs 184M 0 184M 0% /run/user/1001
[devops@server1 ansible]$ ansible test -m copy -a 'src=/etc/passwd dest=/tmp/passwd'
server2 | CHANGED => {
"changed": true,
"checksum": "69570ab641c80fc0a03ca0a5b701a1558db456b2",
"dest": "/tmp/passwd",
"gid": 1001,
"group": "devops",
"md5sum": "12354193e30943fde4d8249ade14100a",
"mode": "0664",
"owner": "devops",
"size": 1096,
"src": "/home/devops/.ansible/tmp/ansible-tmp-1559876278.72-133885602576760/source",
"state": "file",
"uid": 1001
}
[devops@server1 ansible]$ ansible test -a 'ls /tmp/passwd'
server2 | CHANGED | rc=0 >>
/tmp/passwd
#设置文件权限
[devops@server1 ansible]$ ansible test -m file -a 'dest=/tmp/passwd mode=600'
server2 | CHANGED => {
"changed": true,
"gid": 1001,
"group": "devops",
"mode": "0600",
"owner": "devops",
"path": "/tmp/passwd",
"size": 1096,
"state": "file",
"uid": 1001
}
[root@server2 ~]# vim /etc/sudoers
devops ALL=(ALL) NOPASSWD: ALL
[root@server3 ~]# vim /etc/sudoers
devops ALL=(ALL) NOPASSWD: ALL
#设置默认root执行
[devops@server1 ansible]$ vim ansible.cfg
[defaults]
inventory = inventory
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
安装服务
[devops@server1 ansible]$ ansible test -m yum -a 'name=httpd state=present'
[devops@server1 ansible]$ ansible webservers -m yum -a 'name=httpd state=present'
启动服务
[devops@server1 ansible]$ ansible db -m service -a 'name=httpd state=started'
配置http主页信息
[devops@server1 ansible]$ ansible db -m copy -a 'content="www.westos.org\n" dest=/var/www/html/index.html'
server3 | CHANGED => {
"changed": true,
"checksum": "7565f2132a25e2fa5e4966739d800a5ba145a233",
"dest": "/var/www/html/index.html",
"gid": 0,
"group": "root",
"md5sum": "67d266ad6f2d939b89f20d32d81c85a8",
"mode": "0644",
"owner": "root",
"size": 15,
"src": "/home/devops/.ansible/tmp/ansible-tmp-1559877213.24-191713534984413/source",
"state": "file",
"uid": 0
}
[devops@server1 ansible]$ curl server3
www.westos.org
[devops@server1 ansible]$ ansible db -m service -a 'name=firewalld state=started'
设置防火墙 允许服务http 立即生效
[devops@server1 ansible]$ ansible db -m firewalld -a 'service=http state=enabled permanent=yes immediate=yes'
server3 | CHANGED => {
"changed": true,
"msg": "Permanent and Non-Permanent(immediate) operation, Changed service http to enabled"
}
scp [email protected]:/etc/httpd/conf/httpd.conf .
[devops@server1 ansible]$ vim playbook.yml
---
# deploy apache
- hosts: webservers
tasks:
- name: install httpd
yum:
name: httpd
state: latest
- name: create index.html
copy:
content: "www.westos.org\n"
dest: /var/www/html/index.html
- name: configure httpd
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: 644
notify: restart httpd
- name: start httpd
service:
name: httpd
state: started
enabled: true
- name: start firewalld
service:
name: firewalld
state: started
enabled: true
- name: configure firewalld
firewalld:
service: http
state: enabled
permanent: yes
immediate: yes
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
检测语法
[devops@server1 ansible]$ ansible-playbook playbook.yml --syntax-check
playbook: playbook.yml
执行
[devops@server1 ansible]$ ansible-playbook playbook.yml
使用jinja语句设置变量
[devops@server1 ansible]$ vim playbook.yml
- name: create index.html
copy:
content: "{{ ansible_facts['hostname'] }}\n"
dest: /var/www/html/index.html
[devops@server1 ansible]$ ansible-playbook playbook.yml
[devops@server1 ansible]$ curl 172.25.76.2
server2
[devops@server1 ansible]$ curl 172.25.76.3
server3
添加主机ip
[devops@server1 ansible]$ vim playbook.yml
- name: create index.html
copy:
content: "{{ ansible_facts['hostname'] }} {{ ansible_facts['default_ipv4']['address'] }}\n"
dest: /var/www/html/index.html
[devops@server1 ansible]$ ansible-playbook playbook.yml
[devops@server1 ansible]$ curl 172.25.76.2
server2 172.25.76.2
[devops@server1 ansible]$ curl 172.25.76.3
server3 172.25.76.3
[devops@server1 ansible]$ vim playbook.yml
---
# deploy apache
- hosts: webservers
vars: ##添加vars
http_port: 8080
tasks:
- name: install httpd
yum:
name: httpd
state: latest
- name: create index.html
copy:
content: "{{ ansible_facts['hostname'] }} {{ ansible_facts['default_ipv4']['address'] }}\n"
dest: /var/www/html/index.html
tags: one
- name: configure httpd
template: ##改为template
src: files/httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
owner: root
group: root
mode: 644
notify: restart httpd
[devops@server1 files]$ vim httpd.conf.j2
Listen {{ http_port }}
[devops@server1 ansible]$ ansible-playbook playbook.yml -t one ##根据tags名执行某部分
[devops@server1 ansible]$ ansible-playbook playbook.yml
查看主机信息
[devops@server1 ansible]$ ansible test -m setup
[devops@server1 ansible]$ vim hostinfo.yml
---
- hosts: webservers
tasks:
- name: create infofile
template:
src: templates/info.j2
dest: /mnt/info
[devops@server1 ansible]$ mkdir templates
[devops@server1 ansible]$ cd templates/
[devops@server1 templates]$ vim info.j2
主机名:{{ ansible_facts['hostname'] }}
主机IP地址:{{ ansible_facts['default_ipv4']['address'] }}
跟分区大小:{{ ansible_facts['devices']['dm-0']['size'] }}
系统内核:{{ ansible_facts['kernel'] }}
[devops@server1 ansible]$ ansible-playbook hostinfo.yml
[devops@server1 ansible]$ ansible all -a 'ls -l /mnt/info
> '
server3 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 113 Jun 7 03:02 /mnt/info
server2 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 113 Jun 7 03:02 /mnt/info
[devops@server1 ansible]$ ansible all -a 'cat /mnt/info'
server3 | CHANGED | rc=0 >>
主机名:server3
主机IP地址:172.25.76.3
跟分区大小:17.00 GB
系统内核:3.10.0-514.el7.x86_64
server2 | CHANGED | rc=0 >>
主机名:server2
主机IP地址:172.25.76.2
跟分区大小:17.00 GB
系统内核:3.10.0-514.el7.x86_64
不同主机下载不同服务
[devops@server1 ansible]$ cat install.yml
---
- hosts: all
tasks:
- name: install httpd
yum:
name: httpd
state: present
when: ansible_facts['hostname'] == 'server2'
- name: install mariadb
yum:
name: mariadb
state: present
when: ansible_facts['hostname'] == 'server3'
[devops@server1 ansible]$ ansible-playbook install.yml
使用循环 下载多个服务
[devops@server1 ansible]$ cat install.yml
---
- hosts: all
tasks:
- name: install httpd
yum:
name: "{{ item }}"
state: present
when: ansible_facts['hostname'] == 'server2'
loop:
- httpd
- mariadb
- php
- php-mysql
- name: install mariadb
yum:
name: mariadb
state: present
when: ansible_facts['hostname'] == 'server3'
[devops@server1 ansible]$ ansible-playbook install.yml
给多个主机设置hosts文件
[devops@server1 ansible]$ cat hostinfo.yml
---
- hosts: webservers
tasks:
- name: create infofile
template:
src: templates/info.j2
dest: /mnt/info
- name: create hosts
template:
src: templates/hosts.j2
dest: /etc/hosts
owner: root
group: root
mode: 0644
[devops@server1 ansible]$ cd templates/
[devops@server1 templates]$ cat
hosts.j2 info.j2
[devops@server1 templates]$ cat hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['webservers'] %}
{{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}
批量添加用户
[devops@server1 ansible]$ vim adduser.yml
---
- hosts: all
tasks:
- name: create users
user:
name: "{{ item }}"
state: present
password: westos
loop:
- user1
- user2
- user3
- user4
state中present和installed,absent和removed通过源码可知是一样的
源码:
if state in ['installed', 'present']:
if disable_gpg_check:
yum_basecmd.append('--nogpgcheck')
res = install(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos)
elif state in ['removed', 'absent']:
res = remove(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos)
elif state == 'latest':
if disable_gpg_check:
yum_basecmd.append('--nogpgcheck')
res = latest(module, pkgs, repoq, yum_basecmd, conf_file, en_repos, dis_repos)
else:
# should be caught by AnsibleModule argument_spec
module.fail_json(msg="we should never get here unless this all"
" failed", changed=False, results='', errors='unexpected state')
return res
[devops@server1 ansible]$ ansible-playbook adduser.yml
加密用户信息
[devops@server1 ansible]$ mkdir vars
[devops@server1 ansible]$ cd vars/
[devops@server1 vars]$ vim userlist.yml
---
userlist:
- user: user1
pass: westos
- user: user2
pass: redhat
[devops@server1 vars]$ ansible-vault encrypt userlist.yml
New Vault password:
Confirm New Vault password:
Encryption successful
[devops@server1 vars]$ cat userlist.yml
$ANSIBLE_VAULT;1.1;AES256
61363834376637346561323063623134386433396537393934326531653662313136316336323133
6139393436376230356231613661626239633966663731320a393866636363353162626161306262
31643937336164666237373165633338386131663333326432353437633365643164626234366662
3466373061333433310a653631356361393836313633393165376539303739616638653838373537
63613663666630636463326439356533663131376433653438646265336237356665346266346663
63376233303664636437333261383162313936373738323532383533623934613462313636353164
32346561613738343432663735643535623434306330343836363136396164633562656434356332
39636563333039613062336634356165643265363031393031393864396234396430643031306631
3866
[devops@server1 vars]$ ansible-vault view userlist.yml
Vault password:
---
userlist:
- user: user1
pass: westos
- user: user2
pass: redhat
删除用户
[devops@server1 ansible]$ cat adduser.yml
---
- hosts: all
vars_files:
- vars/userlist.yml
tasks:
- name: create users
user:
name: "{{ item }}"
state: absent
password: westos
loop: "{{ userlist }}"
[devops@server1 ansible]$ ansible-playbook adduser.yml --ask-vault-pass
Vault password: