不需要安装客户端,通过sshd去通信
基于模块工作,模块可以由任何语言开发
不仅支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读
安装十分简单,centos上可直接yum安装
有提供UI(浏览器图形化),收费的 www.ansible.com/tower
官方文档 http://docs.ansible.com/ansible/latest/index.html
ansible已经被redhat公司收购,它在github上是一个非常受欢迎的开源软件,github地址 https://github.com/ansible/ansible
一本不错的入门电子书 https://ansible-book.gitbooks.io/ansible-first-book/
192.168.157.132 zyj-01 既做服务端
192.168.157.133 zyj-02 做客户端
192.168.157.134 zyj-03 做客户端
安装步骤
root@zyj-01 ~]# yum list |grep ansible
ansible.noarch 2.7.8-1.el7 epel
ansible-doc.noarch 2.7.8-1.el7 epel
ansible-doc是absible的文档工具
[root@zyj-01 ~]# yum install -y ansible ansible-doc
在zyj-01上执行
[root@zyj-01 ~]#ssh-keygen
将生成的公钥放到客户机上
[root@zyj-02 ~]#mkdir .ssh
[root@zyj-02 ~]#touch .ssh/authorized_keys
[root@zyj-02 ~]# vim .ssh/authorized_keys
[root@zyj-03 ~]#mkdir .ssh
[root@zyj-03 ~]#touch .ssh/authorized_keys
[root@zyj-03 ~]# vim .ssh/authorized_keys
vim /etc/hosts
内容如下:
192.168.157.132 zyj-01
192.168.157.133 zyj-02
192.168.157.134 zyj-03
vim /etc/ansible/hosts
内容如下
[testhost]
192.168.157.133
192.168.157.134
testhost为主机组名字,自定义的,下面两个ip为组内的机器ip,可以写主机名也可以写IP地址 把zyj-01和zyj-02机器归纳到testhost组里面来
格式:ansible 主机名/主机组名 -m command -a "命令"
[root@zyj-01 ~]# ansible testhost -m command -a "pwd"
192.168.157.133 | CHANGED | rc=0 >>
/root
192.168.157.134 | CHANGED | rc=0 >>
/root
hostname
为主机组名,-m
后边是模块名字,-a
后面是命令。
当然我们也可以直接写一个ip/主机名
,针对某一台机器来执行命令
shell
模块同样也可以实现,shell
模块用于批量处理脚本[root@zyj-01 ~]# ansible testhost -m shell -a 'hostname'
192.168.157.133 | CHANGED | rc=0 >>
zyj-02
192.168.157.134 | CHANGED | rc=0 >>
zyj-03
格式:ansible 主机名/主机组名 -m copy -a "src=源目录 dest=目标目录"
[root@zyj-01 ~]# ansible 192.168.157.133 -m copy -a "src=/root/test dest=/tmp/ owner=root group=root mode=755"
192.168.157.133 | SUCCESS => {
"changed": false,
"dest": "/tmp/",
"src": "/root/test"
}
owner=root group=root mode=755 指定目标目录的属组属主和权限
源目录会放到目标目录下面去,如果目标指定的目录不存在,它会自动创建。
格式:ansible 主机名/主机组名 -m copy -a 'src=源文件 dest=目标文件'
[root@zyj-01 ~]# ansible 192.168.157.133 -m copy -a "src=/root/1.txt dest=/tmp/1.txt owner=root group=root mode=777"
192.168.157.133 | SUCCESS => {
"changed": false,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/tmp/1.txt",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"path": "/tmp/1.txt",
"size": 0,
"state": "file",
"uid": 0
}
如果拷贝的是文件,dest指定的名字和源如果不同,并且它不是已经存在的目录,相当于拷贝过去后又重命名。但相反,如果desc是目标机器上已经存在的目录,则会直接把文件拷贝到该目录下面。
saltstack会直接拷贝脚本到远程并执行,ansible要分两步
格式:ansible 主机名/主机组名 -m shell -a "目标机器脚本路径"
[root@zyj-01 ~]# vim 1.sh ##把当前时间写到time.txt文件中
#!/bin/bash
echo `date` >> /tmp/time.txt
[root@zyj-01 ~]# ansible 192.168.57.133 -m copy -a "src=/root/1.sh dest=/tmp mode=755"
[root@zyj-01 ~]# ansible 192.168.157.1134 -m shell -a "/tmp/1.sh"
192.168.80.102 | SUCCESS | rc=0 >>
[root@zyj-02 ~]# cat /tmp/time.txt
2018年 09月 11日 星期二 20:54:37 CST
shell
模块比command
模块强 它支持远程执行命令并且带管道
格式:ansible 主机名/主机组名 -m cron -a "name='名字' job='内容'
[root@zyj-01 ~]# ansible 192.168.157.133 -m cron -a "name='test cron' job='/bin/bash touch /tmp/aaa.txt' weekday=6
分钟 minute
小时 hour
日期 day
月份month
周 weekday
在zyj-02上
[root@zyj-02 ~]# crontab -l ##添加了任务计划
#Ansible: test cron
* * * * 6 /bin/bash touch /tmp/aaa.txt
格式:ansible 主机名/主机组名 -m cron -a "name=名字' state=absent"
[root@zyj-01 ~]# ansible 192.168.157.133 -m cron -a "name='test cron' state=absent"
在zyj-02上
[root@zyj-02 ~]# crontab -l
格式:ansible 主机名/主机组 -m yum -a "name=软件名 state=installed"
[root@zyj-01 ~]# ansible testhost -m yum -a "name=httpd state=installed"
在zyj-02上
[root@zyj-02 ~]# rpm -qa httpd ##已经安装了httpd
httpd-2.4.6-80.el7.centos.1.x86_64
格式:ansible 主机名/主机组 -m yum -a "name=软件名 state=removed"
[root@zyj-01 ~]# ansible testhost -m yum -a "name=httpd state=removed"
在zyj-02上
[root@zyj-02 ~]# rpm -qa httpd ##没有显示任何包已安装
格式:ansible 主机名/主机组 -m service -a "name=服务名 state=started enabled=yes"
[root@zyj-01 ~]# ansible testhost -m service -a "name=httpd state=started enabled=yes"
格式:ansible-doc -l
[root@kun02 ~]# ansible-doc -l
格式:ansible-doc 模块名
[root@zyj-01 ~]# ansible-doc copy
playbook是把模块写入到一起的配置文件。方便管理,playbook文件已yml结尾,类似shell脚本
[root@zyj-01 ~]# cd /etc/ansible/
[root@zyj-01 ansible]# vim test.yml
---
- hosts: zyj-02
user: root
tasks:
- name: test_playbook
shell: touch /tmp/zyj.txt
第一行
需要有三个杠
,hosts
参数指定了对哪些主机进行参作,如果是多台机器可以用逗号
作为分隔,也可以使用主机组
,在/etc/ansible/hosts
里定义;
user
参数指定了使用什么用户登录远程主机操作;
tasks
指定了一个任务,其下面的name参数同样是对任务的描述,在执行过程中会打印出来;
shell
是ansible模块名字
格式:ansible-playbook yml名
[root@zyj-01 ansible]# ansible-playbook test.yml
-在zyj-02上查看
[root@zyj-02 ~]# ls -l /tmp/zyj.txt
-rw------- 1 root root 4 9月 12 21:22 /tmp/zyj.txt
[root@zyj-01 ansible]# vim create_user.yml
---
- name: create_user
hosts: 192.168.157.133
user: root
gather_facts: false
vars:
- user: "test"
tasks:
- name: create user
user: name="{{ user }}"
name
参数对该playbook实现的功能做一个概述,后面执行过程中,会打印 name变量的值 ,可以省略;
gather_facts
参数指定了在以下任务部分执行前,是否先执行setup模块获取主机相关信息,这在后面的task会使用到setup获取的信息时用到;
vars
参数,指定了变量,这里指变量名是user,其值为test ,需要注意的是,变量值一定要用引号引住;
最后一个user指调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。引用变量用 {{变量名}}
[root@zyj-01 ansible]# ansible-playbook create_user.yml
PLAY [create_user] **********************************************************************************************
TASK [create user] **********************************************************************************************
changed: [192.168.157.133]
PLAY RECAP ******************************************************************************************************
192.168.157.133 : ok=1 changed=1 unreachable=0 failed=0
[root@zyj-02 ~]# id test
uid=1003(zyj1) gid=1003(zyj1) 组=1003(zyj1)
[root@zyj-01 ansible]# vim while.yml
---
- name: change mode for file
hosts: 192.168.157.133
user: root
gather_facts: false
tasks:
- name: change mode for file
file: path=/tmp/{{ item }} state=touch mode=600
with_items:
- 1.txt
- 2.txt
- 3.txt
with_items
指定循环的对象 state=touch
为了创建文件
[root@zyj-01 ansible]# ansible-playbook while.yml
PLAY [change mode for file] *************************************************************************************
TASK [change mode for file] *************************************************************************************
changed: [192.168.157.133] => (item=1.txt)
changed: [192.168.157.133] => (item=2.txt)
changed: [192.168.157.133] => (item=3.txt)
PLAY RECAP ******************************************************************************************************
192.168.157.133 : ok=1 changed=1 unreachable=0 failed=0
[root@zyj-02 ~]# ll /tmp/*.txt ##创建文件 权限是600
-rw------- 1 root root 0 9月 12 22:47 /tmp/1.txt
-rw------- 1 root root 0 9月 12 22:47 /tmp/2.txt
-rw------- 1 root root 0 9月 12 22:47 /tmp/3.txt
[root@zyj-01 ansible]# vim when.yml
---
- name: use when
hosts: testhost
tasks:
- name: use when
shell: touch /tmp/when.txt
when: ansible_ens33.ipv4.address=="192.168.80.101"
when
就是if判断 当gather fact中的ansible_ens33的.ipv4的address等于192.168.80.101就会执行shell模块
[root@zyj-01 ansible]# ansible-playbook when.yml
PLAY [use when] *************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************
ok: [192.168.157.133]
ok: [127.0.0.1]
TASK [use when] *************************************************************************************************
skipping: [192.168.157.133]
[WARNING]: Consider using file module with state=touch rather than running touch
changed: [127.0.0.1]
PLAY RECAP ******************************************************************************************************
127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
192.168.157.133 : ok=1 changed=0 unreachable=0 failed=0
gather fact用于收集主机的信息
格式:ansible 主机名/主机组 -m setup
[root@zyj-01 ansible]# ansible testhost -m setup
handlers
类似&&
当前一个模块执行成功后就会执行handlers模块 前模块要notify
来指定执行哪个handlers模块。一般在服务器发生变化之后要执行的一些操作,比如我们修改了配置文件后,需要重启一下服务的时候
都会使用handlers
[root@zyj-01 ansible]# vim handlers.yml
---
- name: use handlers
hosts: 192.168.157.133
gather_facts: false
user: root
tasks:
- name: copy file
copy: src=/etc/passwd dest=/tmp/handlers.txt
notify: test handlers
handlers:
- name: test handlers
shell: echo "11111" >> /tmp/handlers.txt
只有copy模块真正执行后,才会去调用下面的handlers相关的操作。当copy不成功,并不会去执行handlers里面的shell相关命令。 这种比较适合配置文件发生更改后,重启服务的操作
。
[root@zyj-01 ansible]# ansible-playbook handlers.yml
PLAY [use handlers] *********************************************************************************************
TASK [copy file] ************************************************************************************************
changed: [192.168.157.133]
RUNNING HANDLER [test handlers] *********************************************************************************
changed: [192.168.157.133]
PLAY RECAP ******************************************************************************************************
192.168.157.133 : ok=2 changed=2 unreachable=0 failed=0
[root@zyj-02 ~]# tail -1 /tmp/handlers.txt
11111
1.创建相应的目录框架
[root@zyj-01 ~]# cd /etc/ansible/
[root@zyj-01 ansible]# mkdir nginx_install ##总目录
[root@zyj-01 ansible]# cd nginx_install
[root@zyj-01 nginx_install]# mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}
这里是在总目录下创建roles
目录并在其目录下再创建common
和install
目录,又在他们两个各自目录下创建handlers
,files
,meta
,tasks
,templates
,vars
目录
roles
目录下有两个角色,common
为一些准备操作,install
为安装nginx
的操作。每个角色下面又有几个目录。
handlers
下面是当发生改变时要执行的操作,通常用在配置文件发生改变,重启服务
files
为安装时用到的一些文件
meta
为说明信息,说明角色依赖等信息
tasks
里面是核心的配置文件
templates
通常存一些配置文件,启动脚本等模板文件
vars
下为定义的变量
[root@zyj-01 nginx_install]# cd /usr/local/
[root@zyj-01 local]# tar zcvf nginx.tar.gz --exclude "nginx.conf" nginx/ ##除了nginx.conf其他文件打包
install/files/
[root@zyj-01 local]# mv nginx.tar.gz /etc/ansible/nginx_install/roles/install/files/
[root@kun01 local]# cp /etc/init.d/nginx /etc/ansible/nginx_install/roles/install/templates/
[root@kun01 local]# cp /usr/local/nginx/conf/nginx.conf /etc/ansible/nginx_install/roles/install/templates/
[root@zyj-01 roles]# vim common/tasks/main.yml
- name: Install initializtion require software
yum: name={{ item }} state=installed
with_items:
- gcc
- zlib-devel
- pcre-devel
[root@zyj-01 roles]# vim install/vars/main.yml
nginx_user: www
nginx_port: 80
nginx_basedir: /usr/local/nginx
[root@zyj-01 roles]# vim install/tasks/copy.yml
- name: Copy Nginx Software
copy: src=nginx.tar.gz dest=/tmp/nginx.tar.gz owner=root group=root
- name: Uncompression Nginx Software
shell: tar zxf /tmp/nginx.tar.gz -C /usr/local/
- name: Copy Nginx Start Script
template: src=nginx dest=/etc/init.d/nginx owner=root group=root mode=0755
- name: Copy Nginx Config
template: src=nginx.conf dest={{ nginx_basedir }}/conf/ owner=root group=root mode=0644
copy
模块会自动到file目录中在源文件 template
模块会自动到template目录下找文件
[root@zyj-01 roles]# vim install/tasks/install.yml
- name: Create Nginx User
user: name={{ nginx_user }} state=present createhome=no shell=/sbin/nologin
- name: Start Nginx Service
shell: /etc/init.d/nginx start
- name: Add Boot Start Nginx Service
shell: chkconfig --level 345 nginx on
- name: Delete Nginx compression files
shell: rm -rf /tmp/nginx.tar.gz
[root@zyj-01 roles]# vim install/tasks/main.yml
- include: copy.yml
- include: install.yml
include
调用当前目录下的其他文件
[root@zyj-01 roles]# cd ..
[root@zyj-01 nginx_install]# vim install.yml
---
- hosts: 192.168.157.133
gather_facts: false
user: root
roles:
- common
- install
[root@zyj-01 nginx_install]# ansible-playbook install.yml
在zyj-02上查看
[root@zyj-02 ~]# ps aux |grep nginx
[root@zyj-02 ~]# netstat -lntp |grep 80
[root@zyj-01 nginx_install]# tree .
.
├── install.yml ##总入口
└── roles
├── common
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ │ └── main.yml ##安装依赖包
│ ├── templates
│ └── vars
└── install
├── files
│ └── nginx.tar.gz ##压缩包
├── handlers
├── meta
├── tasks
│ ├── copy.yml ##拷贝文件
│ ├── install.yml ##解压文件和启动服务
│ └── main.yml ##调用copy和install
├── templates
│ ├── nginx ##服务脚本
│ └── nginx.conf ##配置文件
└── vars
└── main.yml ##定义变量
写一个管理Nginx配置文件的playbook,当有配置文件更新了可以远程管理其他机器的配置文件
创建对应的目录框架
[root@zyj-01 ~]# cd /etc/ansible/
[root@zyj-01 ansible]# mkdir -p nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
new
为更新目录,old
为回滚目录,说白了就一个备份目录,files
目录下放配置文件nginx.conf和vhosts,handlers
目录用于重启nginx服务
[root@zyj-01 ~]# cd /usr/local/nginx/conf/
[root@zyj-01 conf]# cp -r vhost/ nginx.conf /etc/ansible/nginx_config/roles/new/files/
[root@zyj-01 roles]# cd /etc/ansible/nginx_config/roles/new/ ##回去new目录下
[root@zyj-01 new]# vim vars/main.yml
nginx_basedir: /usr/local/nginx
[root@zyj-01 new]# vim handlers/main.yml
- name: restart nginx
shell: /etc/init.d/nginx reload
[root@zyj-01 new]# vim tasks/main.yml
- name: copy conf file
copy: src={{ item.src }} dest={{ nginx_basedir }}/{{ item.dest }} backup=yes owner=root group=root mode=0644
with_items:
- { src: nginx.conf, dest: conf/nginx.conf }
- { src: vhost, dest: conf/ }
notify: restart nginx
{{ item.src }} 表示循环体里面的src
{{ item.dest }} 表示循环体里面的dest
{{ nginx_basedir }} 表示变量 指/usr/local/nginx
[root@zyj-01 new]# cd ../..
[root@zyj-01 nginx_config]# vim update.yml
---
- hosts: 192.168.157.133
user: root
gather_facts: false
roles:
- new
[root@zyj-01 nginx_config]# ansible-playbook update.yml
一般每次把配置文件更新完后都要把最新的配置文件拷贝一份到old目录下的files中,用于回滚
[root@zyj-01 roles]# rsync -av new/ old/
此操作每次都要在更新配置文件后做
[root@zyj-01 nginx_config]# vim rollback.yml
---
- hosts: 192.168.157.133
user: root
gather_facts: false
roles:
- old
执行回滚yml
[root@zyj-01 nginx_config]# ansible-playbook rollback.yml
[root@zyj-01 nginx_config]# tree
.
├── roles
│ ├── new ##更新
│ │ ├── files ##存放配置文件
│ │ │ ├── nginx.conf
│ │ │ └── vhost
│ │ │ └── test.com.conf
│ │ ├── handlers ##重新加载Nginx服务
│ │ │ └── main.yml
│ │ ├── tasks ##拷贝配置文件到远程机器
│ │ │ └── main.yml
│ │ └── vars ##定义变量
│ │ └── main.yml
│ └── old ##备份new目录 用于回滚
│ ├── files
│ │ ├── nginx.conf
│ │ └── vhost
│ │ └── test.com.conf
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── vars
│ └── main.yml
├── rollback.yml ##回滚总入口
└── update.yml ##更新总入口