一、ansible安装
ansible依赖于Python 2.6或更高的版本、paramiko、PyYAML及Jinja2。
1.1 编译安装
解决依赖关系
# yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
解压安装包
# tar xf ansible-1.5.4.tar.gz # cd ansible-1.5.4
编译安装
# python setup.py build # python setup.py install
拷贝配置文件
# mkdir /etc/ansible # cp -r examples/* /etc/ansible
1.2 rpm包安装
使用阿里云镜像源即可,这里为了方便使用,就直接使用yum安装了。
Fedora 用户可直接安装Ansible, 但RHEL或CentOS用户,需要 配置 EPEL # yum install -y epel-release # yum install -y ansible
注意:不同版本的ansible的功能差异可能较大。
二、配置
配置文件介绍:
配置文件:/etc/ansible/ansible.cfg
hostfile=/etc/ansible/hosts #指定默认hosts配置的位置 host_key_checking = False #不进行host_key检查,省去目标key发生变化时输入(yes/no)的步骤 ask_pass=True # 每次执行ansible命令是否询问ssh密码 ask_sudo_pass=True # 每次执行ansible命令时是否询问sudo密码
主机清单:/etc/ansible/hosts
主程序:ansible、ansible paly-book、ansible-doc
1.将要管理的主机纳入/etc/ansible/hosts配置文件中,可以填写IP或是主机名
[WebServers] 10.10.10.3 10.10.10.4
2.基于ssh的方式与被管理的主机进行通信,在管理的主机上(部署ansible的主机上)生成一对非对称密钥,将公钥发给被管理的主机。
(1)生成一对密钥:ssh-keygen -t rsa
[root@wlm yum.repos.d]# ssh-keygen -t rsa # 默认存放的地方为/root/.ssh目录下 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: e8:60:67:4d:29:90:d2:4d:7d:52:2f:c7:e4:87:a4:80 root@wlm The key's randomart p_w_picpath is: +--[ RSA 2048]----+ | ..+.o... o | | . o.E oo.B . | | . . ooo * . | | = o . | | o + S | | . = | | . | | | | | +-----------------+
(2)将公钥发给要管理的主机:ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected]
[root@wlm yum.repos.d]# ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] The authenticity of host '10.10.10.4 (10.10.10.4)' can't be established. RSA key fingerprint is 43:8a:cc:2c:6a:07:0e:16:17:04:b5:dd:2c:4a:9a:41. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys [email protected]'s password: Permission denied, please try again. [email protected]'s password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh '[email protected]'" and check to make sure that only the key(s) you wanted were added.
3.开始使用我们的第一条ansible命令,进行验证:
# ansible all -m ping
[root@wlm yum.repos.d]# ansible all -m ping 10.10.10.4 | SUCCESS => { "changed": false, "ping": "pong" } 10.10.10.3 | SUCCESS => { "changed": false, "ping": "pong" }
命令介绍:
简单实用格式:ansible[-m module_name] [-a args] [options] ansible all -m ping: all 代表所有被管理的主机都进行操作 -m ping 指定使用ping模块,ping通了返回的结果为pong
三、基本使用
1.常用命令
ansible-doc命令:获取模块列表,及模块使用格式; ansible-doc -l :获取列表 ansible-doc -s module_name :获取指定模块的使用信息
2.ansible 命令格式
ansible[-f forks] [-m module_name] [-a args]
指明管控主机,以模式形式表示或者直接给定 IP ,必须事先定义在文件中; all 设置所有 |
|
[-f forks] |
指明每批管控多少主机,默认为 5 个主机一批次 |
[-m module_name] |
使用何种模块管理操作,所有的操作都需要通过模块来指定 |
[-a args] |
指明模块专用参数; args 一般为 key=value 格式 注意:command模块的参数非为kv格式,而是直接给出要执行的命令即可; |
注意:
-iPATH, --inventory=PATH:指明使用的host inventory文件路径;
3.常用模块介绍(module_name)
1)command模块:远程主机上运行命令
例如:
ansible WebServers -m command -a "ls /tmp"
command模块可以省略,此命令可以直接写为:
ansible WebServers -a "ls /tmp"
[root@wlm yum.repos.d]# ansible WebServers -m command -a "ls /tmp" # WebServers组里的所有主机执行ls /tmp操作 10.10.10.4 | SUCCESS | rc=0 >> ansible_1DyyqF keyring-e9DiYC keyring-teKcdb orbit-gdm pulse-bcZcwuv9QjKR pulse-qnyrpnncnwcb 10.10.10.3 | SUCCESS | rc=0 >> ansible_itWaHf systemd-private-6d81b379511c48219f27f97e16064052-colord.service-RK8yfy systemd-private-6d81b379511c48219f27f97e16064052-cups.service-wm4x9x systemd-private-6d81b379511c48219f27f97e16064052-httpd.service-UXyj9P systemd-private-6d81b379511c48219f27f97e16064052-named.service-Nw7Sew systemd-private-6d81b379511c48219f27f97e16064052-rtkit-daemon.service-QM4tRC systemd-private-6d81b379511c48219f27f97e16064052-vmtoolsd.service-p58UCc
给远程主机添加用户,并设置密码:
ansible WebServers -a "useradd ansible1" ansible WebServers -a "echo dtsdts | passwd --stdin ansible1" # 直接这样使用不会成功,不支持管道,下面介绍shell模块
[root@wlm yum.repos.d]# ansible WebServers -a "useradd ansible1" 10.10.10.4 | SUCCESS | rc=0 >> 10.10.10.3 | SUCCESS | rc=0 >> [root@wlm yum.repos.d]# ansible WebServers -a "echo dtsdts | passwd --stdin ansible1" 10.10.10.4 | SUCCESS | rc=0 >> dtsdts | passwd -stdin ansible1 # 只显示了“dtsdts | passwd --stdin ansible1”内容 10.10.10.3 | SUCCESS | rc=0 >> dtsdts | passwd -stdin ansible1
2)shell模块:远程主机在shell进程下运行命令,支持shell特性,当然也支持管道
给用户添加密码:
ansible WebServers -m shell -a "echo dtsdts | passwd --stdin ansible1"
[root@wlm yum.repos.d]# ansible WebServers -m shell -a "echo dtsdts | passwd --stdin ansible1" 10.10.10.4 | SUCCESS | rc=0 >> 更改用户 ansible1 的密码 。 passwd: 所有的身份验证令牌已经成功更新。 10.10.10.3 | SUCCESS | rc=0 >> 更改用户 ansible1 的密码 。 passwd:所有的身份验证令牌已经成功更新。
3) copy模块:把当前主机文件复制到远程主机位置,可以指定mode(权限)、own(所属主)、group(所属组)
ansible all -m copy -a "src=/tmp/abc.txt dest=/root/ mode=644 owner=ansible1 group=root" # src="本地主机文件" dest="远程主机文件"
[root@wlm yum.repos.d]# ansible all -m copy -a "src=/tmp/abc.txt dest=/root/" 10.10.10.4 | SUCCESS => { "changed": true, "checksum": "325287cee456533bf76025312e5d05e842cb43a9", "dest": "/root/abc.txt", "gid": 0, "group": "root", "md5sum": "1c6d47c6e4d59c630751b47fff140b89", "mode": "0644", "owner": "root", "size": 15, "src": "/root/.ansible/tmp/ansible-tmp-1484639082.19-114656107854348/source", "state": "file", "uid": 0 } 10.10.10.3 | SUCCESS => { "changed": true, "checksum": "325287cee456533bf76025312e5d05e842cb43a9", "dest": "/root/abc.txt", "gid": 0, "group": "root", "md5sum": "1c6d47c6e4d59c630751b47fff140b89", "mode": "0644", "owner": "root", "size": 15, "src": "/root/.ansible/tmp/ansible-tmp-1484639082.46-26533455703361/source", "state": "file", "uid": 0 }
4)cron模块:在远程主机制定crontab周期性计划任务
minute= hour= day= month= weekday= job= name=(必须填写) state= 例如: ansible all -m cron -a "minute=*/10 job='/sbin/ntpdate 10.10.10.10 &> /dev/null' name=Synctime"
在被管理的主机上使用crontab -l查看
[root@WebServer ~]# crontab -l #Ansible: Synctime */10 * * * * /sbin/ntpdate 10.10.10.10 &> /dev/null
在管理(ansible)的主机上,可以删除制定的计划任务
ansible all -m cron -a "state=absent name=Synctime" # name="name"
[root@wlm yum.repos.d]# ansible all -m cron -a "state=absent name=Synctime" 10.10.10.4 | SUCCESS => { "changed": true, "envs": [], "jobs": [] } 10.10.10.3 | SUCCESS => { "changed": true, "envs": [], "jobs": [] }
5)fetch模块:和copy相反,从远程主机拷贝文件到本地主机
ansible WebServers -m fetch -a “src=/root/abc.txt dest=/root/kel/ flat=yes” src="远程主机文件" dest="本地主机" 可以不要flat=yes参数 flat=yes作用: 当dest=/root/kel/,abc.txt会保存在/root/kel/目录下 当dest=/root/kel,会拷贝abc.txt文件,并命名为kel
6)file模块:file模块它包含了文件、文件夹、超级链接类的创立、拷贝、移动、删除操作
ansible WebServers -m file -a # 修改文件的所有组、人、权限。 path=/etc/foo.conf owner=foo group=foo mode=0644 # 操作链接的案例 src=/file/to/link/to dest=/path/to/symlink owner=foo group=foo state=link #参数化案例 src=/tmp/{{ item.path }} dest={{ item.dest }} state=link with_items: - { path: 'x', dest: 'y' } - { path: 'z', dest: 'k' } # 使用touch来创建一个空文件并定义权限 path=/etc/foo.conf state=touch mode="u=rw,g=r,o=r" # touch一个空文件,并且修改权限 path=/etc/foo.conf state=touch mode="u+rw,g-wx,o-rwx"
7)yum模块:用于yum安装包安装和卸载等操作
# ansible WebServers -m yum -a “name=httpd” # 在远程主机上使用yum安装htpd服务
8)service模块:服务管理,就是service命令
ansible all -m service -a "" # 不管当前什么情况,启动apache name=httpd state=started # 不管当前什么情况,停止apache name=httpd state=stopped # 不管当前什么情况,重启apache name=httpd state=restarted # 系统重启后,启动apache name=httpd enabled=yes
9) user/group模块:user模块,用于管理用户;group模块,用于管理group
# ansible all -m user -a "name=test01 group=root" # 添加一个test01用户,所属组为root # ansible all -m user -a "name=test01 state=absent remove=yes" # 删除test01用户 # ansible all -m group -a "name=testgrp01" # 添加一个testgrp01的组 # ansible all -m group -a "name=testgrp01 state=absent" # 删除组testgrp01
四、Playbooks 剧本
playbooks 是 ansible 更强大的配置管理组件,实现基于文本文件编排执行的多个任务,且多次重复执行。playbook 组织格式为使用YAML 语言来进行编写。
playbook是由一个或多个”play”组成的列表。play的主要功能在于将事先归为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个paly组织在一个playbook中,即可以让他们联通起来按事先编排的机制同唱一台大戏。
YAML是用来写配置文件的,接下来的配置文件都是以yaml为后缀。
1.先来一个playbook的例子:
在ansible主机上的/root/下创建httpd目录,将本机的httpd.conf文件拷贝该目录下,修改配置文件里的监听的端口为8081
# vim web.yaml # 注意:文件一般以yaml为后缀 - hosts: WebServers # 运行指定任务的目标主机 remote_user: root # 在远程主机上执行任务的用户 tasks: # 任务列表 - name: install httpd package # 设置任务名称,非必要 yum: name=httpd state=present # 使用yum模块安装httpd - name: install configure file copy: src=/root/httpd/httpd.conf dest=/etc/httpd/conf/ # 使用copy模块 - name: start httpd service service: name=httpd state=started # 使用service模块,start服务
测试:
ansible-playbook --check playbook:只检测可能会发生的改变,但不真正执行操作;
ansible-playbook playbook:直接执行
ansible-playbook --list-hosts:列出运行任务的主机;
[root@wlm httpd]# ansible-playbook --check web.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.3] ok: [10.10.10.11] TASK [install httpd package] *************************************************** ok: [10.10.10.3] ok: [10.10.10.11] TASK [install configure file] ************************************************** changed: [10.10.10.11] ok: [10.10.10.3] TASK [start httpd service] ***************************************************** ok: [10.10.10.3] ok: [10.10.10.11] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=4 changed=1 unreachable=0 failed=0 10.10.10.3 : ok=4 changed=0 unreachable=0 failed=0 [root@wlm httpd]# ansible-playbook web.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.3] ok: [10.10.10.11] TASK [install httpd package] *************************************************** ok: [10.10.10.3] ok: [10.10.10.11] TASK [install configure file] ************************************************** ok: [10.10.10.3] ok: [10.10.10.11] TASK [start httpd service] ***************************************************** changed: [10.10.10.11] changed: [10.10.10.3] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=4 changed=1 unreachable=0 failed=0 10.10.10.3 : ok=4 changed=1 unreachable=0 failed=0
2.通过这个事例的使用,下面来概括一下介绍playbook
playbook的基础组件:
Hosts:运行指定任务的目标主机
remoute_user:在远程主机上执行任务的用户
sudo_user:
task:任务列表
格式:
(1)action:module arguments
(2) module:arguments
注意:shell和command模块后面直接跟命令,而非key=valume类的参数列表
设置在特定条件下触发:
(1)某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
handlers:
任务,在特定条件下触发;
接收到其他任务的通知是被触发;
(2)任务可以通过“tags”打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
运行playbook的方式:
(1)测试
ansible-playbook --check
只检测可能会发生的改变,但不真正执行操作;
ansible-playbook --list-hosts
列出运行任务的主机;
(2)运行
ansible-playbook
3.上面的脚本里,改变了配置文件之后会启动服务,但是不会重启服务,如果以后又改变配置文件,只有restart才会生效,那怎么实现了?
下面介绍handlers。
在特定条件下触发;接收到其他任务的通知时被触发。Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler。Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了。我改了配置文件要重启吧。
某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
handlers:
任务,在特定条件下触发;
接收到其他任务的通知是被触发;
事例脚本如下:
- hosts: WebServers remote_user: root tasks: - name: install httpd package yum: name=httpd state=present - name: install configure file copy: src=/root/httpd/httpd.conf dest=/etc/httpd/conf/ notify: restart httpd # 加notify标签,如果copy的执行结果为change,就会触发下面handlers里name: restart httpd的操作 - name: start httpd service service: name=httpd state=started handlers: - name: restart httpd # 这里的名称和notify是一致的 service: name=httpd state=restarted # restart httpd服务
测试(配置文件没有变动):
[root@wlm httpd]# ansible-playbook --check web_handlers.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.3] ok: [10.10.10.11] TASK [install httpd package] *************************************************** ok: [10.10.10.3] ok: [10.10.10.11] TASK [install configure file] ************************************************** ok: [10.10.10.11] ok: [10.10.10.3] TASK [start httpd service] ***************************************************** ok: [10.10.10.3] ok: [10.10.10.11] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=4 changed=0 unreachable=0 failed=0 10.10.10.3 : ok=4 changed=0 unreachable=0 failed=0
执行:
[root@wlm httpd]# ansible-playbook web_handlers.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.3] ok: [10.10.10.11] TASK [install httpd package] *************************************************** ok: [10.10.10.11] ok: [10.10.10.3] TASK [install configure file] ************************************************** ok: [10.10.10.3] ok: [10.10.10.11] TASK [start httpd service] ***************************************************** ok: [10.10.10.11] ok: [10.10.10.3] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=4 changed=0 unreachable=0 failed=0 10.10.10.3 : ok=4 changed=0 unreachable=0 failed=0 修改了被管理主机上10.10.10.3上的配置文件后再执行: [root@wlm httpd]# ansible-playbook web_handlers.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.11] ok: [10.10.10.3] TASK [install httpd package] *************************************************** ok: [10.10.10.11] ok: [10.10.10.3] TASK [install configure file] ************************************************** ok: [10.10.10.11] changed: [10.10.10.3] TASK [start httpd service] ***************************************************** ok: [10.10.10.11] ok: [10.10.10.3] RUNNING HANDLER [restart httpd] ************************************************ changed: [10.10.10.3] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=4 changed=0 unreachable=0 failed=0 10.10.10.3 : ok=5 changed=2 unreachable=0 failed=0
4.指定执行哪些name内的操作,添加tags标签
任务可以通过“tags”打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
在上一个脚本的基础上,添加tags标签操作,样例脚本如下:
- hosts: WebServers remote_user: root tasks: - name: install httpd package yum: name=httpd state=present tags: insthttpd # 添加tags标签,名称为insthttpd - name: install configure file copy: src=/root/httpd/httpd.conf dest=/etc/httpd/conf/ notify: restart httpd tags: instconf # 添加tags标签,名称为instconf - name: start httpd service service: name=httpd state=started tags: starthttpd # 添加tags标签,名称为starthttpd handlers: - name: restart httpd service: name=httpd state=restarted
执行:
在ansible-playbook命令上使用-t指定进行调用
[root@wlm httpd]# ansible-playbook -t starthttpd web_handlers.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.3] ok: [10.10.10.11] TASK [start httpd service] ***************************************************** ok: [10.10.10.11] ok: [10.10.10.3] # 只执行了start httpd service PLAY RECAP ********************************************************************* 10.10.10.11 : ok=2 changed=0 unreachable=0 failed=0 10.10.10.3 : ok=2 changed=0 unreachable=0 failed=0 [root@wlm httpd]# ansible-playbook -t instconf web_handlers.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.11] ok: [10.10.10.3] TASK [install configure file] ************************************************** ok: [10.10.10.11] ok: [10.10.10.3] # 值执行了install configure file PLAY RECAP ********************************************************************* 10.10.10.11 : ok=2 changed=0 unreachable=0 failed=0 10.10.10.3 : ok=2 changed=0 unreachable=0 failed=0
5.在playbook中使用变量
1)主机的系统变量(facts)
ansible会通过module setup来收集主机的系统信息,这些收集到的系统信息叫做facts,这些facts信息可以直接以变量的形式使用。
哪些facts变量可以引用呢?在命令行上通过调用setup module命令可以查看
$ ansible all -m setup -u root
怎样在playbook中使用facts变量呢,答案是直接使用:
--- - hosts: all user: root tasks: - name: echo system shell: echo {{ ansible_os_family }} - name install ntp on Debian linux apt: name=git state=installed when: ansible_os_family == "Debian" - name install ntp on redhat linux yum: name=git state=present when: ansible_os_family == "RedHat"
2)ansible-playbook命令行中的自定义变量;
-e VARS, --extra-vars=VARS
使用事例:
vim name.yaml - hosts: WebServers remote_user: root vars: - pkgname: memcached # 在playbook内部定义变量,变量名称为pkgname,值为memcached tasks: - name: install a package yum: name={{ pkgname }} state=present # 使用name={{ pkgname }}调用变量的值
测试:
[root@wlm ~]# ansible-playbook --syntax-check name.yaml # 语法检测 playbook: name.yaml [root@wlm ~]# ansible-playbook --check name.yaml # 测试使用 PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.11] ok: [10.10.10.3] TASK [install a package] ******************************************************* changed: [10.10.10.11] changed: [10.10.10.3] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=2 changed=1 unreachable=0 failed=0 10.10.10.3 : ok=2 changed=1 unreachable=0 failed=0
手动指定变量(-e VARS):在执行脚本时,指定变量的值
[root@wlm ~]# ansible-playbook -e pkgname=httpd --check name.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.11] ok: [10.10.10.3] TASK [install a package] ******************************************************* changed: [10.10.10.11] changed: [10.10.10.3] PLAY RECAP ********************************************************************* 10.10.10.11 : ok=2 changed=1 unreachable=0 failed=0 10.10.10.3 : ok=2 changed=1 unreachable=0 failed=0 [root@wlm ~]# ansible-playbook -e pkgname=httpd name.yaml PLAY [WebServers] ************************************************************** TASK [setup] ******************************************************************* ok: [10.10.10.11] ok: [10.10.10.3] TASK [install a package] *******************************************************
3) 通过roles传递变量;
4) Host Inventory
在/etc/ansible/hosts 文件里面编写
(a)向不同的主机传递不同的变量;
IP/HOSTNAME varalable=value var2=value2
(b)向组中的主机传递相同的变量;
[groupname:vars]
variable=value
invertory参数:
用于定义ansible远程连接目标主机是使用的参数,而非传递给playbook的变量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass