一、ansible介绍
1.ansible
ansible是新出现的自动化运维工具,基于Python研发。糅合了众多老牌运维工具的优点实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。仅需在管理工作站上安装ansible程序配置被管控主机的IP信息,被管控的主机无客户端。ansible应用程序存在于epel(第三方社区)源,依赖于很多python组件。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
2.ansible特性
模块化设计,调用特定的模块来完成特定任务,本身是核心组件,短小精悍;
基于Python语言实现,由Paramiko(python的一个可并发连接ssh主机功能库), PyYAML和Jinja2(模板化)三个关键模块实现;
部署简单,agentless无客户端工具;
主从模式工作;
支持自定义模块功能;
支持playbook剧本,连续任务按先后设置顺序完成;
期望每个命令具有幂等性:
3.ansible架构
ansible core:ansible自身核心模块
host inventory:主机库,定义可管控的主机列表
connection plugins:连接插件,一般默认基于ssh协议连接
modules:core modules(自带模块)、custom modules(自定义模块)
playbooks:剧本,按照所设定编排的顺序执行完成安排任务
4.配置文件:
(1)ansible应用程序的主配置文件:/etc/ansible/ansible.cfg
(2) Host Inventory定义管控主机:/etc/ansible/hosts
二、ansible安装
1.配置时间同步
2.关闭防火墙
3.关闭selinux
4.配置DNS
5.下载yum源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
6.安装epel
yum -y install epel-release
7.安装ansible
yum -y install ansible
执行完第七步如果没有报错ansible安装完成
8.配置ssh
ssh-keygen
ssh-copy-id 192.168.31.55 #192.168.31.55为客户端IP
9.把客户端IP写到/etc/ansible/hosts里
若遇报错,则需paramiko模块安装
https://pypi.python.org/packages/source/e/ecdsa/ecdsa-0.11.tar.gz
# tar xvzf ecdsa-0.11.tar.gz
# cd ecdsa-0.11
# python setup.py install
https://pypi.python.org/packages/source/p/paramiko/paramiko-1.15.1.tar.gz
# tar xvzf paramiko-1.15.1.tar.gz
# cd paramiko-1.15.1
# python setup.py install
二、ansible特性
(1)模块化:调用特定的模块,完成特定任务;
(2)基于python语言实现,由paramiko,PYYAML和JINJa2三个关键模块组成
(3)部署简单:agentless,被红帽收购,故备收入epel源
(4)支持自定义模块
(5)支持playbook(剧本)
三、ansible组成+部署
部署:yum -y install ansible
配置文件:/etc/ansible/ansible.cfg
主机清单:/etc/ansible/hosts
主程序:ansible、ansible paly-book、ansible-doc
ansible命令参数介绍
-m:要执行的模块,默认为command
-a:模块的参数
-u:ssh连接的用户名,默认用root,ansible.cfg中可以配置
-k:提示输入ssh登录密码。当使用密码验证的时候用
-s:sudo运行
-U:sudo到那个用户,默认为root
-K:提示输入sudo密码,当不是NOPASSWD模式时使用
-C:只是测试一下会改变什么内容,不会真正去执行
-c:连接类型(default=smart)
-f:fork多少个进程并发处理,默认为5个
-i:指定hosts文件路径,默认default=/etc/ansible/hosts
-I 指定pattern,对<host_pattern>已匹配的主机中再过滤一次
--list-hosts:只打印有哪些主机会执行这个playbook文件,不是实际执行
-M:要执行的模块路径,默认为/usr/share/ansible
-o:压缩输出,摘要输出
--private-key 私钥路径
-T: ssh连接超时时间,默认10秒
-t:日志输出到该目录,日志文件名以主机名命名
-v:verbost
字段名 参考值 含义
ansible_architecture x86_64 受控节点系统框架
ansible_distribution CentOS 受控节点的操作系统发行版
ansible_distribution_version 6.3 受控节点发行版本的版本号
ansible_domain kisops.org 受控节点的主域名
ansible_fqdn site01.kisops.org 受控节点的完整机器名
ansible_interfaces [“lo”,”eth0”] 列出受控节点所有的网卡
ansible_kernel 2.6.32-431.5.1.el6.x86_64 受控节点的内核版本号
ansible_memtotal_mb 30099 受控节点总内存大小(兆)
ansible_processor_count 24 受控节点的CPU核心
ansible_virualization_role guest 受控节点的身份:host为宿主机,guest为虚拟机
ansible_virtualization_type kvm 受控节点的虚拟化类型
#普通用户使用sudo
$ ansible all --sudo -m copy -a 'src=/tmp/zabbix_agentd.conf dest=/usr/local/zabbix/etc/ owner=ody group=root mode=0644'
三、ansible基本命令的使用
1.语法
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
-f forks:启动的并发数
-m module_name:使用的模块
-args:模块特有参数
[root@yunwei ~]# ansible web -m ping
192.168.31.114 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.31.113 | SUCCESS => {
"changed": false,
"ping": "pong"
}
2.command模块
使用command模块执行date指令,ansible 默认模块,不支持变量传递。
[root@yunwei ~]# ansible web -m command -a 'date'
192.168.31.114 | SUCCESS | rc=0 >>
2017年 03月 24日 星期五 17:09:53 CST
192.168.31.113 | SUCCESS | rc=0 >>
2017年 03月 24日 星期五 17:09:54 CST
[root@yunwei ~]# ansible web -a 'date'
192.168.31.113 | SUCCESS | rc=0 >>
2017年 03月 24日 星期五 17:11:02 CST
192.168.31.114 | SUCCESS | rc=0 >>
2017年 03月 24日 星期五 17:11:02 CST
3.copy模块
把本地/root/aaa 考到目标主机/tmp/aaa
[root@yunwei ~]# ansible web -m copy -a 'src=/root/aaa dest=/tmp/aaa owner=root group=root mode=0644'
192.168.31.114 | SUCCESS => {
"changed": false,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/tmp/aaa",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/tmp/aaa",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 0,
"state": "file",
"uid": 0
[root@yunwei ~]# ansible web -a 'ls -l /tmp/aaa'
192.168.31.114 | SUCCESS | rc=0 >>
-rw-r--r--. 1 root root 0 3月 24 17:23 /tmp/aaa
-
ansible安装以及配置认证
ansible也是有Python开发的。
ansible特点:
不需要安装客户端,通过sshd去通信
基于模块工作,模块可以由任何语言开发
不仅支持命令行使用模块,也支持编写yaml格式的playbook
支持sudo
又提供UI(浏览器图形化)www.ansible.com/tower 10台主机以内免费
开源UI http://github.com/alaxli/ansible_ui
文档http://download.csdn.net/detail/liyang23456/7741185
ansible安装:
两台机器:
服务端:192.168.147.137
客户端:192.168.147.138
在两台机器的/etc/hosts文件里加入:
192.168.147.137 server
192.168.147.138 client
只需要在服务端上安装ansible即可
服务端:
yum install -y epel-release
yum install -y ansible
ansible配置密钥:
服务端:
生成秘钥对(默认放在/root/.ssh/目录下,也可以自定义):
ssh-keygen -t rsa
直接回车即可,不用设置秘钥密码
把公钥(id_rsa.pub)内容放到客户端(192.168.147.138)的/root/.ssh/authorized_keys里面:scp /root/.ssh/id_rsa.pub 192.168.147.138:/root/.ssh/authorized_keys
也在服务端上的/root/.ssh/authorized_keys里面复制一份公钥,后面要用本机做一个客户端,即127.0.0.1:scp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys
客户端:
更改文件权限:
chmod 600 /root/.ssh/authorized_keys
关闭selinux:
setenforce 0
测试服务端连接客户端:
ssh client
如果ssh命令不存在,安装一下:
yum insall -y openssh-clients
2.ansible远程执行命令
服务端:
定义一个主机组:
vim /etc/ansible/hosts
添加一个主机组:
[testhost]
127.0.0.1
192.168.147.138
说明:testhost为主机组名字,自定义的。下面两个IP为组内的机器IP,也可以写主机名,前提是能解析为IP。
对这组主机执行w命令:
ansible testhost -m command -a 'w'
这样就可以批量执行命令了。这里的testhost为主机组名,-m后边是模块名字,-a后面是命令。当然我们也可以直接写一个IP,针对某一台机器来执行命令。
ansible 127.0.0.1 -m command -a 'hostname'
错误:“msg”:"Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
解决:yum install -y libselinux-python
还有一个模块就是shell同样也可以实现,支持管道:
ansible testhost -m shell -a 'cat /etc/passwd | grep root'
shell功能比command功能多。
3.ansible拷贝目录或者文件
ansible testhost -m copy -a "src=/etc/ansible dest=/tmp/ansibletest owner=root group=root mode=0755"
注意:源目录会放到目标目录下面去,如果目标指定的目录不存在,它会自动创建。如果拷贝的是文件,dest指定的名字和源如果不同,并且它不是已经存在的目录,相当于拷贝过去后又重命名。但相反,如果dest是目标机器上已经存在的目录,则会直接把文件拷贝到该目录下面,例如:
ansible testhost -m copy -a "src=/etc/passwd dest=/tmp/123"
这里的/tmp/123和源机器上的/etc/passwd是一致的,但如果目标机器上已经有/tmp/123目录,则会在/tmp/123/目录下建立passwd文件。
4.ansible远程执行脚本
首先创建一个shell脚本:
vim /tmp/test.sh
#!/bin/bash
echo `date` > /tmp/ansible_test.txt
然后把该脚本分发到各个机器上
ansible testhost -m copy -a "src=/tmp/test.sh dest=/tmp/test.sh mode=0755"
最后是批量执行该shell脚本
ansible testhost -m shell -a "/tmp/test.sh"
shell模块,还支持远程执行命令并且带管道:
ansible testhost -m shell -a "cat /etc/passwd | wc -l"
5.ansible实现任务计划
服务端:
创建一个任务计划:
ansible testhost -m cron -a "name='test cron' job='/bin/touch /tmp/1212.txt' weekday=6"
如果删除该cron只需要加一个字段state=absent
ansible testhost -m cron -a "name='test cron' state=absent"
其他的时间表示:
分:minute
时:hour
日:day
月:month
周:weekday
客户端:
查看任务计划:
crontab -l
6.ansible安装rpm包和管理服务
安装httpd:
ansible testhost -m yum -a "name=httpd"
在name后面还可以加上state=installed,默认不加也可以安装
开启httpd服务,并设为开机启动:
ansible testhost -m service -a "name=httpd state=started enabled=yes"
这里的name是centos系统里的服务名,可以通过chkconfig --list查看。
ansible文档的使用:
ansible-doc -l 查看所有的模块
ansible-doc cron 查看指定的模块
7.ansible playbook介绍
类似于shell脚本,相当于把命令写入到文件里,例如:
vim /etc/ansible/test.yml
---
- hosts: testhost
remote_user: root
tasks:
- name: test_playbook
shell: touch /tmp/test.txt
说明:hosts参数制定了对哪些主机进行操作;
user参数制定了使用什么用户登录远程主机操作;
tasks制定了一个任务,其下面的name参数同样是对任务的描述,在执行过程中会打印出来。
执行:ansible-playbook /etc/ansible/test.yml
再来一个创建用户的例子:
vim /etc/ansible/create_user.yml
---
- name: create_user
hosts: testhost
user: root
gather_facts: false
vars:
- user: "test"
tasks:
- name: create user
user: name="` user `"
执行:ansible-playbook /etc/ansible/create_user.yml
说明:name参数对该playbook实现的功能做一个概述,后面执行过程中,会打印name变量的值,可以省略;gather_facts参数制定了在以下任务执行前,是否先执行setup模块获取相关信息,这在后面的task或使用到setup获取的信息时用到;
vars参数制定了变量,这里指一个user变量,其值为test,需要注意的是,变量值一定要引号括起来;
user制定了调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。
收集客户端的信息:
ansible client -m setup
8.ansible playbook循环
修改testhost组下主机的/tmp/目录下的1.txt,2.txt,3.txt(首先保证这些文件存在)的权限修改为600,属主改为root,属组改为root:
编辑一个loop.yml脚本:
vim /etc/ansible/loop.yml
---
- hosts: testhost
user: root
tasks:
- name: change mode for file
file: path=/tmp/` item ` mode=600 owner=root group=root
with_items:
- 1.txt
- 2.txt
- 3.txt
执行:
ansible-playbook /etc/ansible/loop.yml
9.ansible playbook判断
当满足条件ansible_hostname == "client"时执行命令:
touch /tmp/when.txt:
编辑一个when.yml脚本:
vim /etc/ansible/when.yml
---
- hosts: testhost
remote_user: root
gather_facts: True
tasks:
- name: use when
shell: touch /tmp/when.txt
when: ansible_hostname == "client"
执行:ansible-playbook /etc/ansible/when.yml
10.ansible playbook 中的 handlers
在执行task之后,服务器发生变化之后要执行的一些操作,比如我们修改了一些配置问价后,需要重启一下服务:
vim /etc/ansinle/handlers.yml
---
- name: handlers test
hosts: testhost
user: root
tasks:
- name: copy file
copy: src=/etc/passwd dest=/tmp/aaa.txt
notify: test handlers
handlers:
- name: test handlers
shell: echo "111111" >> /tmp/aaa.txt
说明:只有copy模块执行成功后,才会去调用下面的handlers相关的操作。也就是说如果passwd和aaa.txt内容是一样的,并不会去执行handlers里面的shell相关命令。这种比较适合配置文件发生更改后,重启服务的操作。
执行:ansible-playbook /etc/ansinle/handlers.yml
11.ansible实例-安装Nginx
思路:先在一台机器上编译安装好Nginx、打包,然后再用ansible去下发
进入ansible配置文件目录:cd /etc/ansible
创建一个nginx_install目录,方便管理:mkdir nginx_install
进入该目录:cd nginx_install
mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}
说明:roles目录下有两个角色,commen为一些准备操作,install为安装nginx的操作。每个角色下面又有几个目录,handlers下面是当发生改变时要执行的操作,通常用在配置文件发生改变,重启服务。files为安装时用到的一些文件,meta为说明信息,说明角色依赖等信息,tasks里面是核心的配置文件,templates通常存一些配置文件,启动脚本等模块文件,vars下为定义的变量。
详细步骤:
1.编译安装Nginx可以参考LNMP部分
2.安装完Nginx后可以看到安装目录下的内容:ls /usr/local/nginx/
3.切换目录:cd /usr/local/
4.打包压缩Nginx安装目录:tar czf nginx.tar.gz nginx
5.切换到ansible配置文件目录:cd /etc/ansible
6.创建nginx_install目录:mkdir nginx_install
7.进入该目录:cd nginx_install
8.创建子目录:mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}
9.将相关文件拷贝到指定目录下:
cp /usr/local/nginx.tar.gz /etc/ansible/nginx_install/roles/install/files/
cp /usr/local/nginx/conf/nginx.conf /etc/ansible/nginx_install/roles/install/templates/
cp /etc/init.d/nginx /etc/ansible/nginx_install/roles/install/templates/
10.编写common/tasks的总入口配置文件:
vim /etc/ansible/nginx_install/roles/common/tasks/main.yml
- name: Install initialization require software
yum: name=` item ` state=installed
with_items:
- zlib-devel
- pcre-devel
- openssl-devel
11.编写install/vars的总入口配置文件:
vim /etc/ansible/nginx_install/roles/install/vars/main.yml
nginx_user: www
nginx_basedir: /usr/local/nginx
12.编写install/tasks的copy配置文件:
vim /etc/ansible/nginx_install/roles/install/tasks/copy.yml
- name: Copy Nginx Sofrware
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
13.编写install/tasks的install配置文件:
vim /etc/ansible/nginx_install/roles/install/tasks/install.yml
- name: Create Nginx User
user: name=` nginx_user ` state=present createhome=no shell=/sbin/nologin
- name: Start Nginx Service
service: name=nginx state=started
- name: Add Boot Start Nginx Service
shell: chkconfig --level 345 nginx on
- name: Delete Nginx compression files
shell: rm -rf /tmp/nginx.tar.gz
14.编写install/tasks的总入口配置文件:
vim /etc/ansible/nginx_install/roles/install/tasks/main.yml
- include: copy.yml
- include: install.yml
15.编写整个程序的总入口配置文件:
vim /etc/ansible/nginx_install/install.yml
---
- hosts: 192.168.147.138
remote_user: root
gather_facts: True
roles:
- common
- install
16.执行:ansible-playbook /etc/ansible/nginx_install/install.yml
客户端:
查看上述三个包是否已经安装成功:rpm -qa | egrep 'pcre|openssl|zlib'
查看Nginx是否安装成功:ls /usr/local/nginx/
查看服务是否启动成功:ps aux | grep nginx
查看加入服务列表是否成功:chkconfig --list nginx
11.ansible实例-管理Nginx配置文件
生产环境中大多时候是需要管理配置文件的,安装软件包只是在初始化环境的时候用一下。下面我们来写个管理Nginx配置文件的playbook
mkdir -p /etc/ansible/nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
其中new为更新时用到的,old为回滚时用到的,files下面为nginx.conf和vhosts目录,handlers为重启Nginx服务的命令
关于回滚,需要在执行playbook之前备份一下旧的配置,所以对于老配置文件的管理一定要严格,千万不要随便去修改线上机器的配置,并且要保证new/files下面的配置和线上的配置一致
先把nginx.conf和vhosts目录放到files目录下面
cd /usr/local/nginx/conf/
cp -r nginx.conf vhosts /etc/ansible/nginx_config/roles/new/files
详细步骤:
-
级联创建所需要的目录:
mkdir -p /etc/ansible/nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
2.将Nginx的配置文件拷贝到指定目录:
cp /usr/local/nginx/conf/nginx.conf /etc/ansible/nginx_config/roles/new/files/
cp -r /usr/local/nginx/conf/vhosts /etc/ansible/nginx_config/roles/new/files/
3.定义vars:
vim /etc/ansible/nginx_config/roles/new/vars/main.yml
nginx_basedir: /usr/local/nginx
4.定义handlers:
vim /etc/ansible/nginx_config/roles/new/handlers/main.yml
- name: restart nginx
shell: /etc/init.d/nginx reload
5.定义tasks:
vim /etc/ansible/nginx_config/roles/new/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: vhosts, dest: conf/ }
notify: restart nginx
6.定义一个update程序的入口文件:
vim /etc/ansible/nginx_config/update.yml
---
- hosts: 192.168.147.138
user: root
roles:
- new
7.执行更新:ansible-playbook /etc/ansible/nginx_config/update.yml
上面实现了更新,即在服务端修改配置文件,执行playbook即可同步到客户端。
回滚的实现更简单:在每次更新之前,先将new/目录下的配置文件备份到old/目录下,定义一个rollback程序的入口文件:
vim /etc/ansible/nginx_config/rollback.yml
---
- hosts: 192.168.147.138
user: root
roles:
- old
如果更新失败,可以执行回滚:ansible-playbook /etc/ansible/nginx_config/rollback.yml
ansible样例库:
git clone git://github.com/dl528888/ansible-examples.git
git命令需要yum安装一下:yum install -y git
五、ansible的常用模块(用ansible-doc -l可以显示)
(1)command模块:远程主机上运行命令
例如:ansible webservers -m command -a "ls /var"
ansible webservers -a "useradd user1",command模块可以省
ansible webservers -a "echo magedu |passwd –stdin user1" ,不成功,不支持管道
(2)shell模块:(管道可以用)远程主机在shell进程下运行命令,支持shell特性
例如:ansible webservers -m shell -a "echo cwj1111|passwd –stdin user1"
(3)copy模块:把文件复制到远程位置
例如:ansible all -m copy -a "src=/etc/fstab dest=/tmp/fstab" 可以指明mode(权限),group(组),owner(主)。
(4)cron:管理任务计划的
minute=,day=,month=,weekday=,hour=,job=,name=(必须要给),state=
例如:ansible all -m cron -a "minute=*/5 job='/sbin/ntpdate 192.168.1.109 &> /dev/null' name=Synctime "
在被管理主机上使用crontab -l便可以看到
ansible all -m cron -a "state=absent name=Synctime" 就可以删除
(5)fetch模块:拉取文件的(从远程主机上拉取文件到本地)
ansible-doc -s fetch 查看
(6)file模块:设定文件属性(属组,属主)
例如:ansible all -m file -a "src=/tmp/fstab path=/tmp/fstab.link state=link"
修改属性:path= ,owner= ,mode= ,group=
创建目录:ansible all -m file -a "path=/tmp/tmpdir state=directory "
(7)pip模块:管理python的模块
(8)yum模块:用yum包管理,管理包
例如:ansible all -m yum -a "name=httpd state=present"
上面显示的是我已经装过了,就没有改变,现在我们卸载了看看:ansible all -m yum -a "name=httpd state=absent"
在使用rpm看一下就没有了
(9)service模块:管理服务
name=,state=, started(启动),stopped(停止),restarted(重启), enabled=,runlevel=
例如:先查看两台主机的80端口,再启动
ansible all -m shell -a "ss -tnl |grep :80 "
ansible all -m service -a "name=httpd state=started"
启动之后:
(10)user模块:管理用户,账号,组
name=,system=,uid=,shell=,group=,groups=,home=,passwd=,remove=(state=absent,同时删除家目录)
例如:ansible all -m user -a "name=user2 system=yes state=present uid=306 "
(11)setup模块,收集变量
六、ansible-playbook
ansible使用YAML语法描述配置文件,YAML语法以简洁明了、结构清晰著称。ansible的任务配置文件被称为playbook,就是剧本,每个剧本里面包含一系列的任务,每个任务在ansible中又被称为“戏剧”(play)。
(1)YAML语法格式
数据结构可以用类似大纲的缩排方式呈现,结构通过通过缩进来表示,连续的项目可以通过减号“-”来表示,map结构里面的key/value对用冒号“:”来分隔。如下:
(2)例子
先创建一个working文件夹,再cd到working里面,把yaml文件移到里面,创建一个files目录,把配置好的httpd.conf移到里面去,改一下监听端口,改成8080
ansible-playbook –check web.yaml
测试一下:
启动:ansible all -m service -a "name=httpd state=restarted"
ansible all -m shell -a "ss -tnl |grep :8080"
(3)上面的有一个缺陷,我改动那个配置文件了怎么办,这个时候就要用handlers了
在特定条件下触发;接收到其他任务的通知时被触发。Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler。Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了。我改了配置文件要重启吧。
(4)指定哪一出独唱用tags
我只想运行playbook的某一步,其他的不运行
(5)variables变量
1、facts:可以直接调用
2、ansible-playbook命令的命令行中可以自定义变量:-e 使用变量
ansible-playbook -e pkname=memcached –check web2.yaml
3、通过roles传递变量
4、Host Inventory
(6)模版templates:是一个文本文件内容嵌套脚本,是使用模版编程语言编程。
Jinja2:
template模块:基于模版方式生成一个文件复制到远程主机
例子,
(1)首先:ansible all -m setup | grep ansibleprocessorvcpus
(2)在working/files/ 下,编辑一个epel源,这里我们直接wget 阿里的好了:wget -O working/files/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
(3)复制过去:ansible all -m copy -a "src=files/epel.repo dest=/etc/yum.repos.d "
(4)装上nginx:ansible all -m yum -a "name=nginx state=present "
(5)创建模版文件:cp /etc/nginx/nginx.conf files/nginx.conf.j2
vim files/nginx.conf.j2
workerprocesses ` ansibleprocessor_vcpus `;
(6)使用template将模版复制过去:
好了,现在做的结果是让worker_processes跟cpu的内核数相等。它比copy更厉害的是,它配置的是模版文件,就像作文模版一样,可以根据你的需要配置吻合不同机器一个模版文件,而copy的文件是固定不变的。
(7)条件判断,when语句,在task中使用,支持jinja2的语法格式
(8)循环,迭代,我一下装好几个包
YAML简介
YAML是一个可读性高的用来表达资料序列的格式。
YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。
Clark Evans在2001年在首次发表了这种语言,另外Ingy dt Net与Oren Ben-Kiki也是这语言的共同设计者。
YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。
其特性包括:
YAML的可读性好
YAML和脚本语言的交互性好
YAML使用实现语言的数据类型
YAML有一个一致的信息模型
YAML易于实现
YAML可以基于流来处理
YAML表达能力强,扩展性好
YAML语法
YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。
其结构(Structure)通过空格来展示,
序列(Sequence)里的项用"-"来代;
Map里的键值对用":"分隔。
YAML文件扩展名通常为.yaml或者.yml。
下面是一个示例。
name: John Smith
age: 41gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age 13
gender: Female
YAML 2 个重要的结构组成部分list和directory
################################# list
列表的所有元素均使用“-”打头例如
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
##############################dictionary
字典通过key与valuef进行标识例如
---
# An employee record
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置于{}中进行表示例如
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
多个映射关系组成一个字典一个列表可以包含多个字典。
ymal中的变量
################################## 变量命名
变量名仅能由字母、数字和下划线组成且只能以字母开头。
################################## facts
facts是由正在通信的远程目标主机发回的信息这些信息被保存在ansible变量中。要获取指定的远程主机所支持的所有facts可使用如下命令进行
# ansible hostname -m setup 这个命令可以获得被监控端主机的各种信息将这些信息得到后保存到变量中。
################################ 自定义变量
在 yaml 中可以使用vars关键字来定义变量
vars:
var_name: value
############################# 变量的引用
` var_name `
########################### 特殊的变量迭代
当有需要重复性执行的任务时可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用并通过with_items语句来指明迭代的元素列表即可。
#######################################示例
例如在被控端添加 2 个用户
方式1一般做法
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
方式2使用变量方式
- name: add several users
vars:
user1: testuser1
user2: testuser2
user: name=` user1 ` state=present groups=wheel
user: name=` user2 ` state=present groups=wheel
方式3使用迭代方式
- name: add several users
user: name=` item ` state=present groups=wheel
with_items:
- testuser1
- testuser2
事实上with_items中可以使用元素还可为hashes例如
- name: add several users
user: name=` item`.`name ` state=present groups=` item`.`groups `
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
3、Inentory文件的格式
inventory文件遵循INI文件风格中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中
此外当如若目标主机使用了非默认的SSH端口还可以在主机名称之后使用冒号加端口号来标明。
[webservers]
www1.magedu.com:2222
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com
如果主机名称遵循相似的命名模式还可以使用列表的方式标识各主机例如
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
#################### 主机变量
可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用。例如
[webservers]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=303 maxRequestsPerChild=909
################### 组变量
组变量是指赋予给指定组内所有主机上的在playbook中可用的变量。例如
[webservers]
www1.magedu.com
www2.magedu.com
[webservers:vars]
ntpntp_server=ntp.magedu.com
nfsnfs_server=nfs.magedu.com
################## 组嵌套
inventory中组还可以包含其它的组并且也可以向组中的主机指定变量。
不过这些变量只能在ansible-playbook中使用而ansible不支持。例如
[apache]
httpd1.magedu.com
httpd2.magedu.com
[nginx]
ngx1.magedu.com
ngx2.magedu.com
[webservers:children]
apache
nginx
[webservers:vars]
ntpntp_server=ntp.magedu.com
######################### inventory参数
ansible基于ssh连接inventory中指定的远程主机时还可以通过参数指定其交互方式常用的参数如下所示
ansible_ssh_host # 要连接的主机名
ansible_ssh_port # 端口号默认是22
ansible_ssh_user # ssh连接时默认使用的用户名
ansible_ssh_pass # ssh连接时的密码
ansible_sudo_pass # 使用sudo连接用户是的密码
ansible_ssh_private_key_file # 秘钥文件如果不想使用ssh-agent管理时可以使用此选项
ansible_shell_type # shell的类型默认sh
#########################################################################################
4、playbooks
playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。
从根本上来讲所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中即可以让它们联同起来按事先编排的机制同唱一台大戏。
###########################playbook基础组件
1、Hosts和Users
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。
hosts用于指定要执行指定任务的主机其可以是一个或多个由冒号分隔主机组。
remote_user则用于指定远程主机上的执行任务的用户。
不过remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务其可用于play全局或某任务。
此外甚至可以在sudo时使用sudo_user指定sudo时切换的用户。
- hosts: webnodes
remote_user: mageedu
tasks:
- name: test connection ping:
remote_user: mageedu sudo: yes
2、任务列表和action
play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行即在所有主机上完成第一个任务后再开始第二个。
在运行自下而下某playbook时如果中途发生错误所有已执行任务都将回滚因此在更正playbook后重新执行一次即可。
task的目的是使用指定的参数执行模块而在模块参数中可以使用变量。模块执行是幂等的这意味着多次执行是安全的因为其结果均一致。
每个task都应该有其name用于playbook的执行结果输出建议其内容尽可能清晰地描述任务执行步骤。如果未提供name则action的结果将用于输出。
定义task的可以使用“action: module options”或“module: options”的格式推荐使用后者以实现向后兼容。
如果action一行的内容过多也中使用在行首使用几个空白字符进行换行。
tasks:
- name: make sure apache is running
service: name=httpd state=running
在众多模块中只有command和shell模块仅需要给定一个列表而无需使用“key=value”
格式例如
tasks:
- name: disable selinux
command: /sbin/setenforce 0如果命令或脚本的退出码不为零可以使用如下方式替代
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors来忽略错误信息
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
3、handlers
用于当关注的资源发生变化时采取一定的操作。
“notify”这个action可用于在每个play的最后被触发这样可以避免多次有改变发生时每次都执行指定的操作取而代之仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler也即notify中调用handler中定义的操作。
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handler是task列表这些task与前述的task并没有本质上的不同。
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
5、tags
tags用于让用户选择运行或路过playbook中的部分代码。ansible具有幂等性因此会自动跳过没有变化的部分即便如此有些代码为测试其确实没有发生变化的时间依然会非常地长。此时如果确信其没有变化就可以通过tags跳过此些代码片断。
示例基于playbooks实现web服务的部署
1、提供好Inventory文件
# /etc/ansible/hosts基于秘钥认证
[webhosts]
172.16.10.22
172.16.10.33
2、编辑 palybooks 剧本
# vim /root/web.yaml
- name: web service
remote_user: root
hosts: webhosts
vars:
packages: httpd
tasks:
- name: install httpd yum: name=` packages ` state=present
tags: install
- name: configuration httpd
copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
tags: conf
notify:
- restart httpd
- name: service httpd start
service: name=httpd enabled=no state=started
tags: start
- name: add centos and hadoop user
user: name=` item ` state=absent
tags: adduser
with_items:
- centos
- hadoop
handlers:
- name: restart httpd
service: name=httpd state=restarted
3、准备好配置文件
将web的配置放到指定目录 src=/root/httpd.conf
4、开始部署
ansible-playbooks /root/web.yml
yum的epel源,
配置文件:/etc/ansible/ansible.cfg
主机清单:/etc/ansible/hosts
主程序:
ansible
ansible-playbook
ansible-doc
ansible的简单使用格式:
ansible HOST-PATTERN -m MOD_NAME -a MOD_ARGS
ansible-doc -s MOD_name
ansible的常用模块:
获取模块列表:
ansible-doc -l
command模块:在远程主机运行命令,不支持“|”
ansible websrvs -m command -a "useradd user1"
shell模块:远程主机在shell进程中中运行
ansible websrvs -m shell - a "echo magedu | password --stdin user1"
copy模块:复制文件至远程主机;
用法:(1)src=\'#\'" /etc/fstab dest=/tmp/fstab"
(2)content= dest= //直接把内容作为数据流传输至文件;
ansible all -m copy -a "content='hello world\n' dest=/tmp/testfile"
owner,group,mode
cron模块:manage cron.d and crontab entries
minute=
hour=
day=
weekday=
job=
*name= //必须有此参数 state=
present //默认为添加
absent //删除crontab
ansible all -m cron -a "minute=*/5 job='/sbin/ntpdate 172.16.0.1 &> /dev/null' name=Synctime"
fetch模块:从远程主机拉去文件至当前机器;
file模块:修改文件属性;
*path= //必须有此参数
用法:(1)创建连接文件
ansible all -m file -a "src=/tmp/fstab path=/tmp/fstab.link state=link"
(2)修改属性:path= owner= mode= group=
(3)创建目录:path= state=directory
ansible all -m file -a "path=/tmp/tmpdir state=directory"
hostname模块:manage hostname
name=
ping模块:
pip模块:用来管理Python的依赖模块;
yum模块:用yum来管理程序包
*name=:指明程序包名称,可以带版本号 //必须有此参数 state=
present,latest(安装),absent(卸载);
ansible all -m yum -a "name=httpd state=latest"
service模块:管理服务
*name= //必须有此参数 state=
started,stopped,restarted;
enabled= 1|0 //开机自启动;
runlevel=
ansible all -m service -a "name=httpd state=started"
uri模块:uri的访问管理 user模块:管理用户账户;
*name
system= yes|no //yes是系统账户
uid=
shell= group=
groups=
comment=
home=
move_home=
remove= //当state=agent是删除家目录
ansible all -m user -a "name=user3 system=yes state=present uid=306"
setup模块:用于获取facts; group模块:添加或删除组
*name= //必须给的参数 state
system
gid=
scipt模块:把本地脚本传递到远程主机后进行执行;
ansible -m script -a "/path/to/script_file"
YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。
其结构(structure)通过空格来展示,序列(Sequence)里的项用“-”来代表,Map里的键值对用“:”分隔。
Playbook:
Playbook的核心元素:
Hosts:主机
Tasks:任务
variables:
Templates:包含了模板的文本文件;
Handlers:由特定条件出发任务;
Roles:
playbook的基础组件
Hosts:运行指定任务的目标主机;
remoute_user:在远程主机上执行任务的用户;
sudu_user:
tasks:任务列表
模块,模块参数;
格式:
(1)action:module arguments
(2)module:arguments
handlers:
任务,在特定条件下触发;
接收到其他任务的通知时被触发;
variables:
(1)facts:可直接调用;
(2)ansible-playbook命令行中的自定义变量;
-e VARS,--extra-vars=VARS
(3)通过role传递变量;
(4)Host Inventory
(1)向不同的主机传递不同的变量;
ip/hostname varaiable=value var2=value2
(2)向组中主机传递相同的变量
[groupname:vars]
variable=value
invertory参数:
用于定义ansible远程连接目标主机时的参数,而非传递给playbook的变量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
....
**注意:shell和command模块后直接跟命令即可**
**某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;**
**任务可以通过“tags”打标签,而后可在ansible-playbook命令上使用-t指定进行调用;**
playbook的使用方法:
ansible-playbook在执行命令时,第一个任务执行完成后执行第二个任务,第二个执行完成后,执行第三个任务;
ansible-playbook
--list-host //显示执行的主机列表;
--check //在目标主机进行检测可能会发生改变,但并不执行;
-t tags //指明任务
ansible-palybook -t instconf web.yml //进行标签为instconf的项目;
playbook示例1:编写sample.yaml
- hosts: remote_user:root
tasks:
- name: create a user user3
user: name=user3 system=true uid=307
- name: creare a user user4
user: name=user4 system=true uid=308
playbook示例2:编写web.yml
- hosts: websrvs remote_user: root
tasks:
- name: install httpd package yum: name=httpd state=present
- name: install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/ //src为相对路径
tags: instconf
notify: restart httpd
- name: start httpd.service
serivce: name=httpd state=started
-name: execute ss command
shell: ss -tnl | grep 8080
- handlers:
- name: restart httpd
service: name=httpd state=restarted
一.ansible 说明
ansible 是一款自动化工具,可以完成配置系统、软件发布、高级任务的编排、编排更高级的任务,比如连续部署或零停机时间滚动更新。
二.anisble 安装
2.1这里希望通过yum方式安装,需要安装EPEL
下载地址:
https://admin.fedoraproject.org/mirrormanager/mirrors/EPEL
2.2.安装epel:
rpm -ivh epel-release-latest-7.noarch.rpm
2.3.安装ansible,自动解决依赖关系
yum install ansible
2.4.安装列表如下:
ansible、PyYAML、libtomcrypt、libtommath、libyaml、python-babel、python-backports 、python-backports-ssl_match_hostname 、python-httplib2 python-jinja2、python-keyczar、python-markupsafe、python-setuptools、python2-crypto、python2-ecdsa、python2-paramiko、python2-pyasn1、sshpass
2.5.查看ansible版本:
# rpm -qa | grep ansible
ansible-2.2.0.0-4.el7.noarch
spacer.gif
2.6.结构说明
/etc/ansible/ansible.cfg #主配置文件
/etc/ansible/hosts #认证主机列表
/etc/ansible/roles #角色配置路径
/usr/bin/ansible #主命令
/usr/bin/ansible-console
/usr/bin/ansible-doc #ansible帮助文档
/usr/bin/ansible-galaxy
/usr/bin/ansible-playbook #playbook命令
/usr/bin/ansible-pull
/usr/bin/ansible-vault
ansible主配文件解析
[defaults]
# some basic default values...
#inventory = /etc/ansible/hosts #这个事默认库文件位置,脚本,或者存放可通信主机的目录
#library = /usr/share/my_modules/ #这个事Ansible默认搜寻模块的位置
#module_utils = /usr/share/my_module_utils/
#remote_tmp = ~/.ansible/tmp
#local_tmp = ~/.ansible/tmp
#forks = 5 #连接主机的并发数
#poll_interval = 15 #对于Ansible中的异步任务(详见 异步操作和轮询), 这个是设置定义,当具体的poll interval 没有定义时,多少时间回查一下这些任务的状态, 默认值是一个折中选择15秒钟.这个时间是个回查频率和任务完成叫回频率和当任务完成时的回转频率的这种:
#sudo_user = root
#ask_sudo_pass = True #ask_pass,用来控制Ansible playbook 在执行sudo之前是否询问sudo密码.默认为no
#ask_pass = True #个可以控制,Ansible 剧本playbook 是否会自动默认弹出弹出密码.默认为no
#transport = smart
#remote_port = 22 #ssh连接端口
#module_lang = C #这是默认模块和系统之间通信的计算机语言,默认为’C’语言.
#module_set_locale = False
#gathering = implicit #控制默认facts收集(远程系统变量). 默认值为’implicit’, 每一次play,facts都会被收集
#gather_subset = all
# gather_timeout = 10
#roles_path = /etc/ansible/roles #roles 路径指的是’roles/’下的额外目录,用于playbook搜索Ansible roles
#host_key_checking = False #检查主机密钥
# change the default callback
#stdout_callback = skippy
# enable additional callbacks
#callback_whitelist = timer, mail
#task_includes_static = True
#handler_includes_static = True
#error_on_missing_handler = True
#sudo_exe = sudo #如果在其他远程主机上使用另一种方式执行sudo草做, sudo程序的路径可以用这个参数更换,使用命令行标签来拟合标准
#sudo_flags = -H -S -n #当使用sudo支持的时候,传递给sudo而外的标签. 默认值为”-H”, 意思是保留原用户的环境.在有些场景下也许需要添加或者删除 标签,大多数用户不需要修改
#timeout = 10 #SSH超时时间
#remote_user = root #使用/usr/bin/ansible-playbook链接的默认用户名,如果不指定,会使用当前登录的用户名
#log_path = /var/log/ansible.log # 日志文件存放路径
#module_name = command #ansible命令执行默认的模块
#executable = /bin/sh #在sudo环境下产生一个shell交互接口. 用户只在/bin/bash的或者sudo限制的一些场景中需要修改
#hash_behaviour = replace # 特定的优先级覆盖变量
#private_role_vars = yes
#jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n #允许开启Jinja2拓展模块
#private_key_file = /path/to/file #如果你是用pem密钥文件而不是SSH 客户端或秘密啊认证的话,你可以设置这里的默认值,来避免每一次提醒设置密钥文件位置
#vault_password_file = /path/to/vault_password_file
#ansible_managed = Ansible managed #这个设置可以告知用户,Ansible修改了一个文件,并且手动写入的内容可能已经被覆盖.
#display_skipped_hosts = True # 显示任何跳过任务的状态 ,默认是显示
#display_args_to_stdout = False #显示任何跳过任务的状态 ,默认是显示
#error_on_undefined_vars = False #如果所引用的变量名称错误的话, 将会导致ansible在执行步骤上失败
#system_warnings = True #允许禁用系统运行ansible相关的潜在问题警告
#deprecation_warnings = True #允许在ansible-playbook输出结果中禁用“不建议使用”警告
# command_warnings = False #当shell和命令行模块被默认模块简化的时,Ansible 将默认发出警告
#action_plugins = /usr/share/ansible/plugins/action #“行为”是 ansible中的一段代码,用来激活一些事件,例如执行一个模块,一个模版,等等;这是一个以开发者为中心的特性,使得一些底层模块可以从外部不同地方加载
#cache_plugins = /usr/share/ansible/plugins/cache
#callback_plugins = /usr/share/ansible/plugins/callback
#connection_plugins = /usr/share/ansible/plugins/connection
#lookup_plugins = /usr/share/ansible/plugins/lookup
#inventory_plugins = /usr/share/ansible/plugins/inventory
#vars_plugins = /usr/share/ansible/plugins/vars
#filter_plugins = /usr/share/ansible/plugins/filter
#test_plugins = /usr/share/ansible/plugins/test
#strategy_plugins = /usr/share/ansible/plugins/strategy
#strategy = free
#bin_ansible_callbacks = False #用来控制callback插件是否在运行 /usr/bin/ansible 的时候被加载. 这个模块将用于命令行的日志系统,发出通知等特性
#nocows = 1 #默认ansible可以调用一些cowsay的特性 开启/禁用:0/1
#cow_selection = default
#cow_selection = random
#nocolor = 1 #输出带上颜色区别, 开启/关闭:0/1
#fact_caching = memory
#retry_files_enabled = False
#retry_files_save_path = ~/.ansible-retry
#no_log = False
#no_target_syslog = False
#allow_world_readable_tmpfiles = False
#var_compression_level = 9
#module_compression = 'ZIP_DEFLATED'
#max_diff_size = 1048576
#merge_multiple_cli_flags = False
# Controls showing custom stats at the end, off by default
#show_custom_stats = True
#inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo
[privilege_escalation]
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False
[paramiko_connection]
#record_host_keys=False
#pty=False
[ssh_connection]
#ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
# control_path_dir = /tmp/.ansible/cp
#control_path_dir = ~/.ansible/cp
# control_path = %(directory)s/%%h-%%r
#control_path =
#pipelining = False
# Control the mechanism for transferring files (old)
# * smart = try sftp and then try scp [default]
# * True = use scp only
# * False = use sftp only
#scp_if_ssh = smart
#transfer_method = smart
#sftp_batch_mode = False
[accelerate]
#accelerate_port = 5099 #在急速模式下使用的端口
#accelerate_timeout = 30
#accelerate_connect_timeout = 5.0
# The daemon timeout is measured in minutes. This time is measured
# from the last activity to the accelerate daemon.
#accelerate_daemon_timeout = 30
#accelerate_multi_key = yes
[selinux]
#libvirt_lxc_noseclabel = yes
[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyan
[diff]
# Always print diff when running ( same as always running with -D/--diff )
# always = no
# Set how many context lines to show in diff
# context = 3
三.ansible 认证及基本使用
3.1.实验环境说明:
172.16.110.39 ansible
172.16.110.47 client1
3.2.anisble基于ssh认证,这里通过添加主机key认证的方式来进行认证。
服务端
#ssh-keygen -t rsa -P ''
#scp /root/.ssh/id_rsa.pub root@172.16.110.47:/data
#
客户端
#cd /data/
#cat id_rsa.pub >> /root/.ssh/authorized_keys
#chmod 600 /root/.ssh/authorized_keys
#
3.3.运行说明
# ansible -h
Usage: ansible <host-pattern> [options]
3.3.1.运行简单的ping测试
# ansible all -m ping
[WARNING]: provided hosts list is empty, only localhost is available
[WARNING]: No hosts matched, nothing to do
提示,没有提供服务器列表,所以添加列表
主机列表可以ip、域名、分组、正则匹配等方式运行
3.3.2.主机ip列表方式:
# vim /etc/ansible/hosts
[webservers]
10.237.154.25
spacer.gif
ansible all -m ping
spacer.gif
SUCCESS:表示成功
false:表示未进行改变
pong:返回值,表示成功
3.3.3.分组方式运行命令:
vim /etc/ansible/hosts
[webserver]
172.16.110.47
# ansible webserver -a "ls /root"
172.16.110.47 | SUCCESS | rc=0 >>
anaconda-ks.cfg
spacer.gif
出现以上问题说明ssh认证有问题,重新弄一遍。
3.3.5.使用正则列表:
vim /etc/ansible/hosts
[webserver]
172.16.110.4[7:8]
# ansible webserver -a "/sbin/ifconfig ens33 | grep netmask"
172.16.110.48 | FAILED | rc=1 >>
|: Unknown host
ifconfig: `--help' gives usage information.
172.16.110.47 | FAILED | rc=1 >>
|: Unknown host
ifconfig: `--help' gives usage information.
这里增加了管道,ansible增加管道必须使用shell的模块运行
# ansible webserver -m shell -a "/sbin/ifconfig ens33 | grep netmask"
172.16.110.47 | SUCCESS | rc=0 >>
inet 172.16.110.47 netmask 255.255.255.0 broadcast 172.16.110.255
172.16.110.48 | SUCCESS | rc=0 >>
inet 172.16.110.48 netmask 255.255.255.0 broadcast 172.16.110.255
3.4.Inventory 参数的说明,摘自网上
ansible_ssh_host
将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port
ssh端口号.如果不是默认的端口号,通过此变量设置.
ansible_ssh_user
默认的 ssh 用户名
ansible_ssh_pass
ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass
sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)
sudo 命令路径(适用于1.8及以上版本)
ansible_connection
与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.
ansible_ssh_private_key_file
ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type
目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter
目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我们
不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
示例说明:
some_host ansible_ssh_port=2222 ansible_ssh_user=manager
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
ansible模块目录结构
$ tree roles/
roles/
└── base
├── defaults
├── files
│ ├── puppet.conf
│ ├── yum65.repo
│ ├── yum67.repo
│ └── yum.repo
├── handlers
│ └── main.yml
├── meta
├── tasks
│ ├── chkconfig.yml
│ ├── hostname.yml
│ ├── main.yml
│ ├── ntpd.yml
│ ├── puppet.yml
│ ├── repo.yml
│ └── route.yml
├── templates
│ ├── hosts.j2
│ └── static-routes.j2
└── vars
└── main.yml
8 directories, 16 files
入口文件的site.yml
$ more site.yml
---
- hosts: all
remote_user: test
become: yes
become_method: sudo
roles:
- base
模版文件template
修改主机名
$ more base/templates/hosts.j2
127.0.0.1 ` ansible_fqdn ` localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 ` ansible_fqdn ` localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.1 puppet.server
添加静态路由,需要重启网络
$ more base/templates/static-routes.j2
any net 10.0.0.0/8 gw ` gateway `
any net 172.0.0.0/8 gw ` gateway `
any net 192.168.1.0/24 gw ` gateway `
可以在base/vars/main.yml中定义变量,由于环境特殊,我在命令行中使用变量。
yml中定义使用变量的格式如下
name:value
task中的入口文件
$ more base/tasks/main.yml
---
- include: ntpd.yml
- include: repo.yml
- include: route.yml
- include: hostname.yml
- include: chkconfig.yml
- include: puppet.yml
时间同步
$ more base/tasks/ntpd.yml
---
- name: sync datatime
command: /usr/sbin/ntpdate 202.120.2.101
- name: sync hwclock
command: /sbin/hwclock -w
更具不同系统版本配置yum源
$ more base/tasks/repo.yml
---
- name: configure RedHat5 yum repo
copy: force=yes src=yum.repo dest=/etc/yum.repos.d/rhel-debuginfo.repo owner=root group=root mode=0644
when: ansible_distribution_major_version == '5'
- name: configure RedHat6.5 yum repo
copy: force=yes src=yum65.repo dest=/etc/yum.repos.d/rhel-debuginfo.repo owner=root group=root mode=0644
when: ansible_distribution_version == '6.5'
- name: configure RedHat6.7 yum repo
copy: force=yes src=yum67.repo dest=/etc/yum.repos.d/rhel-debuginfo.repo owner=root group=root mode=0644
when: ansible_distribution_version == '6.7'
配置路由
$ more base/tasks/route.yml
- name: config static route
template: force=yes src=static-routes.j2 dest=/etc/sysconfig/static-routes owner=root group=root mode=0644
notify: restart network
批量配置服务器的hostname(动态inventory脚本实现)
$ more base/tasks/hostname.yml
---
- name: install facter
yum: name=facter state=latest
- name: install rubygem-json
yum: name=rubygem-json state=latest
- hostname: name=` hostname `
- name : gather facts again
setup :
- name: config hosts
template: force=yes src=hosts.j2 dest=/etc/hosts owner=root group=root mode=0644
关闭iptables,sendmail和selinux
$ more base/tasks/chkconfig.yml
- name: chkconfig off iptables
shell: /sbin/chkconfig iptables off
- name: stop iptables
service: name=iptables state=stopped
- name: chkconfig off sendmail
shell: /sbin/chkconfig sendmail off
- name: stop sendmail
service: name=sendmail state=stopped
- name: stop selinux
command: /sbin/setenforce 0
初始化节点的puppet
$ more base/tasks/puppet.yml
---
- name: install puppet
yum: name=puppet state=latest
register: result
ignore_errors: True
- name: puppet config file
copy: force=yes src=puppet.conf dest=/etc/puppet/puppet.conf owner=root group=root mode=0644
when: result.rc==0
- name: run puppet
shell: /usr/bin/puppet agent -t
所需要的rpm包
ansible-2.2.1.0-1.el6.noarch.rpm
libyaml-0.1.3-4.el6_6.x86_64.rpm
python-argparse-1.2.1-2.1.el6.noarch.rpm
python-crypto2.6-2.6.1-2.el6.x86_64.rpm
python-httplib2-0.7.7-1.el6.noarch.rpm
python-jinja2-26-2.6-3.el6.noarch.rpm
python-keyczar-0.71c-1.el6.noarch.rpm
python-six-1.9.0-2.el6.noarch.rpm
PyYAML-3.10-3.1.el6.x86_64.rpm
sshpass-1.05-1.el6.x86_64.rpm
python-crypto2.6-2.6.1-2.el6.x86_64
服务器如果可以出公网可以使用pip或者yum安装ansible
1.安装ansible
yum install ansible -y
2.配置ansible,优化配置,提高ansible性能【/etc/ansible/ansible.cfg】
[defaults]
forks = 150
transport = paramiko
#使用facter缓存,默认使用内存,支持redis
gathering = implicit
fact_caching_timeout = 86400
fact_caching = jsonfile
fact_caching_connection = /etc/ansible/facts/cache
host_key_checking = False
remote_user = test
deprecation_warnings = False
callback_plugins = /etc/ansible/callback_plugins
retry_files_enabled = False
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[paramiko_connection]
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
pipelining = True
[accelerate]
[selinux]
[colors]
优化ssh,提高ansible性能
$ more ~/.ssh/config
Host *
Compression yes
ServerAliveInterval 60
ServerAliveCountMax 5
ControlMaster auto
ControlPath ~/.ssh/%r@%h-%p
ControlPersist 4h
3.启用ansible的callback_plugins 显示ansible-playbook的执行时间
$ more callback_plugins/profile_tasks.py
import datetime
import os
import time
from ansible.plugins.callback import CallbackBase
class CallbackModule(CallbackBase):
"""
A plugin for timing tasks
"""
def __init__(self):
super(CallbackModule, self).__init__()
self.stats = {}
self.current = None
def playbook_on_task_start(self, name, is_conditional):
"""
Logs the start of each task
"""
if os.getenv("ANSIBLE_PROFILE_DISABLE") is not None:
return
if self.current is not None:
# Record the running time of the last executed task
self.stats[self.current] = time.time() - self.stats[self.current]
# Record the start time of the current task
self.current = name
self.stats[self.current] = time.time()
def playbook_on_stats(self, stats):
"""
Prints the timings
"""
if os.getenv("ANSIBLE_PROFILE_DISABLE") is not None:
return
# Record the timing of the very last task
if self.current is not None:
self.stats[self.current] = time.time() - self.stats[self.current]
# Sort the tasks by their running time
results = sorted(
self.stats.items(),
key=lambda value: value[1],
reverse=True,
)
# Just keep the top 10
results = results[:10]
# Print the timings
for name, elapsed in results:
print(
"{0:-<70}{1:->9}".format(
'{0} '.format(name),
' {0:.02f}s'.format(elapsed),
)
)
total_seconds = sum([x[1] for x in self.stats.items()])
print("\nPlaybook finished: {0}, {1} total tasks. {2} elapsed. \n".format(
time.asctime(),
len(self.stats.items()),
datetime.timedelta(seconds=(int(total_seconds)))
)
)
执行的效果如下
test connection --------------------------------------------------------- 1.17s
Playbook finished: Wed Feb 15 13:09:06 2017, 1 total tasks. 0:00:01 elapsed.
4.编写ansible的动态inventory脚本
$ more inventory.py
#!/usr/bin/env python
import argparse
import sys
try:
import json
except ImportError:
import simplejson as json
def RFile():
with open('hostlist.txt', 'r+') as f:
result=[]
for line in f.readlines():
host = line.strip().split()
if host:
result.append(host)
return result
host_list = RFile()
def groupList():
group_list = []
for host in host_list:
group_list.append(host[1])
print (json.dumps({"all":group_list},indent=4))
def hostList(key):
host_dict = {}
for host in host_list:
host_dict[host[1]] = {"ansible_ssh_host": host[1],"ansible_ssh_port":9999, "ansible_ssh_user":"test","ansible_ssh_pass":
"test","hostname":host[0]}
print (json.dumps(host_dict[key], indent=4))
if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
groupList()
elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
hostList(sys.argv[2])
else:
print "Usage: %s --list or --host <hostname>" % sys.argv[0]
sys.exit(1)
主机列表如下
more hostlist.txt
backup01.cn 10.44.245.85
测试playbook:test.yml
$ more test.yml
- hosts: all
remote_user: test
gather_facts: no
become: yes
become_method: sudo
tasks:
- name: test connection
ping:
执行结果如下:
$ ansible-playbook -i inventory.py test.yml
PLAY [all] *********************************************************************
TASK [test connection] *********************************************************
ok: [10.44.245.85]
PLAY RECAP *********************************************************************
10.44.245.85 : ok=1 changed=0 unreachable=0 failed=0
test connection --------------------------------------------------------- 1.17s
Playbook finished: Wed Feb 15 13:20:09 2017, 1 total tasks. 0:00:01 elapsed.
ansible几个常用模块及参数的简单演示
file模块使用示例
[root@node1 ~]# ansible-doc -l | grep "^\<file\>"
file Sets attributes of files
[root@node1 ~]# ansible-doc -s file --> 查看模块特有的参数
[root@node1 ~]# ansible all -m file -a "path=/tmp/testansible state=directory"
--> 在目标主机的/tmp目录下创建testansible目
copy模块使用示例
[root@node1 ~]# ansible all -m copy -a "src=/etc/issue dest=/tmp/testansible"
--> 将/etc/issue 文件复制到 /tmp/testansible 目录下,文件名和源文件名同名
[root@node1 ~]# ansible all -m copy -a "content='hello world' dest=/tmp/testansible/first"
--> 给定内容生成文件 即 /tmp/testansible/first 的文件内容为 "hello world"
yum模块使用示例
[root@node1 ~]# ansible all -m yum -a "name=httpd state=absent"
--> 卸载httpd程序包
[root@node1 ~]# ansible all -m yum -a "name=httpd state=present"
--> 安装httpd程序包
service模块使用示例
[root@node1 ~]# ansible all -m service -a "name=httpd state=started"
-->启动httpd服务
[root@node1 ~]# ansible all -m service -a "name=httpd state=stopped"
--> 停止httpd服务
获取目标主机上的facts变量(在使用yaml模板语言时,可直接进行引用)
[root@node1 ~]# ansible all -m setup
其他模块及其参数的使用方式和上述的类似
读者可自行查看帮助即可
查看命令帮助的方法:
# ansible-doc -l
# ansible-doc -s
简单使用示例
node1:192.168.0.106 centos7.2
node2:192.168.0.110 centos7.2
[root@node1 ~]# yum -y install ansible --> 采用yum 安装ansible
[root@node1 ~]# rpm -q ansible
ansible-2.2.0.0-3.el7.noarch --> 版本为ansible-2.2
[root@node1 ~]# rpm -ql ansible --> 简单查看生成的文件列表
/etc/ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
/etc/ansible/roles
/usr/bin/ansible
/usr/bin/ansible-doc
/usr/bin/ansible-playbook
[root@node1 ~]# vim /etc/ansible/hosts --> 定义host inventory
[all]
192.168.0.106
192.168.0.110
[root@node1 ~]# ansible all -m ping --> 测试管理主机是否OK
192.168.0.106 | SUCCESS => {
"changed": false,
"ping": "pong" --> 代表正常
}
192.168.0.110 | SUCCESS => {
"changed": false,
"ping": "pong" --> 代表正常
}
简单的命令使用帮助
# ansible <host-pattern> [-f fork] [-m module_name] [-a args]
# ansible-doc -l 查看所支持的所有模块 即 -m 后面的参数
# ansible-doc -s <模块名> 查看指定模块的参数 即 -a 后面的参数
ansible之playbook介绍
核心元素:
Tasks:任务,由模块定义的操作的列表;
Variables:变量
Templates:模板,即使用了模板语法的文本文件;
Handlers:由特定条件触发的Tasks;
Roles:角色;
playbook的基础组件
hosts:运行指定任务的目标主机
remote_user:在远程主机上已哪个用户身份执行
tasks:任务列表
运行playbook,使用ansible-playbook命令
(1) 检测语法
# ansible-playbook --syntax-check /path/to/playbook.yaml
(2) 测试运行
# ansible-playbook -C /path/to/playbook.yaml
--list-hosts
--list-tasks
--list-tags
(3) 运行
# ansible-playbook /path/to/playbook.yaml
-t TAGS, --tags=TAGS
--skip-tags=SKIP_TAGS
--start-at-task=START_AT
(4)查看帮助
# ansible-playbook -h
playbook核心元素之 --> tasks 介绍
[root@ansible ~]# vim test1.yaml
- hosts: centos6
remote_user: root
tasks:
- name: add a group
group: name=ansgroup1 system=false
- name: add a user
user: name=ansuser1 group=ansgroup1 system=false
- name: restart httpd service
service: name=httpd state=restarted
[root@ansible ~]# ansible-playbook --syntax-check test1.yaml --> 语法测试
[root@ansible ~]# ansible-playbook -C test1.yaml --> 测试执行
[root@ansible ~]# ansible-playbook test1.yaml --> 执行
playbook核心元素之 --> handlers 介绍
Handlers:由特定条件触发的Tasks;
[root@ansible ~]# vim test2.yaml
- hosts: centos7
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: copy config file
copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd service --> 和notify配合使用即可
- name: start httpd service
service: name=httpd state=started
handlers:
- name: restart httpd service
service: name=httpd state=restarted
playbook核心元素之 --> variables 介绍
Variables:基本用法
类型:
内建:(1) facts
自定义:
(1) 命令行传递;
-e VAR=VALUE
(2) 在hosts Inventory中为每个主机定义专用变量值;
(a) 向不同的主机传递不同的变量;
IP/HOSTNAME variable_name=value
(b) 向组内的所有主机传递相同的变量 ;
[groupname:vars]
variable_name=value
(3) 在playbook中定义
vars:
- var_name: value
- var_name: value
(4) Inventory还可以使用参数:
用于定义ansible远程连接目标主机时使用的属性,而非传递给playbook的变量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
...
(5) 在角色调用时传递
roles:
- { role: ROLE_NAME, var: value, ...}
变量调用:
` var_name `
实例示范
[root@ansible ~]# vim test3.yaml
- hosts: centos6
remote_user: root
vars:
- first: hello
tasks:
- name: first test
shell: echo ` first ` > /tmp/first.test
- name: second test
shell: echo ` second ` > /tmp/second.test
- name: facts
shell: echo ` ansible_product_serial ` > /tmp/third.test
playbook核心元素之 --> 模板template 介绍
templates:文件文件,内部嵌套有模板语言脚本(使用模板语言编写)
[root@ansible ~]# ansible-doc -l | grep "^\<template\>" --> template是一个模块
template Templates a file out to a remote server.
[root@node1 ~]# ansible-doc -s template --> 查看 template模块的参数
src=
dest=
mode=
onwer=
group=
...
注意:此模拟不能在命令行使用,而只能用于playbook
实际使用范例
[root@ansible ~]# vim test4.yaml
- hosts: centos7
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: copy config file
template: src=/root/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: restart httpd service
- name: start httpd service
service: name=httpd state=started
handlers:
- name: restart httpd service
service: name=httpd state=restarted
yaml语法之 条件测试,循环,tags 介绍
条件测试
when语句:在tasks中使用。
[root@ansible ~]# vim test5.yaml
- hosts: centos6-7
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: start centos6 httpd
shell: service httpd start
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" --> facts变量
- name: start centos7 httpd
shell: systemctl start httpd.service
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
循环:迭代,需要重复执行的任务
对迭代项的引用,固定变量名为 "item",使用with_item属性给定要迭代的元素;
[root@ansible ~]# vim test6.yaml
- hosts: centos7
remote_user: root
tasks:
- name: create groups
group: name=` item ` state=present
with_items:
- groupx1
- groupx2
- name: create users
user: name=` item`.`name ` group=` item`.`group ` state=present
with_items:
- {name: 'userx1', group: 'groupx1'}
- {name: 'userx2', group: 'groupx2'}
tags:给指定的任务定义一个调用标识
[root@ansible ~]# vim test7.yaml
- hosts: centos7
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: copy config file
copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
tags: httpdconf
- name: start httpd service
service: name=httpd state=started
- name: print date
shell: /usr/bin/date
tags: showdate
playbook核心元素之 --> 角色role
角色:
以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等;
role_name/
files/:存储由copy或script等模块调用的文件;
tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;
其它的文件需要由main.yml进行"包含"调用;
handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;
其它的文件需要由main.yml进行"包含"调用;
vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;
其它的文件需要由main.yml进行“包含”调用;
templates/:存储由template模块调用的模板文本;
meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关
系;其它的文件需要由main.yml进行"包含"调用;
default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
实例
[root@ansible roles]# pwd
/etc/ansible/roles --> 配置文件中定义的默认路径
[root@ansible roles]# mkdir nginx
[root@ansible roles]# tree nginx
nginx
├── default
├── files
├── handlers
│ └── main.yml
├── meta
├── tasks
│ └── main.yml
├── templates
│ └── nginx.conf.j2
└── vars
└── main.yml
[root@ansible roles]# vim nginx/tasks/main.yml
- name: install nginx
yum: name=nginx state=present
tags: insngx
- name: install conf file
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: ngxconf
notify: reload nginx service
- name: start nginx service
service: name=nginx enabled=true state=started
[root@ansible roles]# vim nginx/templates/nginx.conf.j2
//可以简单修改端口号测试
//在配置文件中引用一个变量
[root@ansible roles]# vim nginx/handlers/main.yml
- name: reload nginx service
service: name=nginx state=restarted
[root@ansible roles]# vim nginx/vars/main.yml
ngxport: "8090" --> 修改nginx监听的端口测试
编写playbook调用角色
[root@ansible roles]# vim nginx.yml
--> 配置文件中定义的位置(/etc/ansible/ansible.cfg )
- hosts: centos7
remote_user: root
roles:
- nginx
测试
[root@ansible roles]# ansible-playbook nginx.yml