Ansible
什么是Ansible
Ansible是基于python语言开发的,由paramiko和pyYAML两个关键模块构建。playbook是Ansible的核心,是ansible的配置、部署、编排语言,基于YAML语言来编写。
可以做的事:
配置管理
服务及时开通
应用部署
流程编排
监控告警
日志记录
Ansible优点和特性
无代理(采用openssh进行管理)、去中心化、模块化
Ansible tower是ansible的web管理界面
Ansible架构
Ansible安装
rpm包安装
#安装epel源
yum install epel-release
#安装ansible
yum install -y ansible
编译安装
wget ansible-*
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar zxf ansible-*
cd ansible
pip安装
#安装epel源
yum install epel-release
yum install python-pip python-devel
yum install gcc glibc-devel zlib-level rpm-build openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
Ansible使用
ansible配置文件
/etc/ansible/ansible.cfg 主配置文件
#配置项
host_key_checking = False 不检查指纹key
/etc/ansible/hosts 主机清单
/etc/ansible/roles/ 存放角色的目录
#脚本
基于ssh-key的免密登陆
ansible实现管理的主要方式
Ad-Hoc:即利用ansible命令,主要用于临时命令的使用场景
Ansible-playbook:主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
ansible主要工具
ansible-doc
ansible-doc用来显示模块帮助
#格式
ansible-doc [option] [module...]
#option
-l, --list 列出可用模块
-s, --snippet 显示指定模块的playbook片段
#例
ansible-doc -l
ansible-doc -s ping
ansible
#格式
ansible [-m module_name] [-a args]
#host-pattern,用于匹配被控制的主机列表
all 表示inventory主机清单中的所有主机
#选项
-m module 指定模块,默认command
-v 详细过程
--list-hosts 显示主机列表,可简写--list
-k, --ask-pass 提示输入ssh链接密码,默认key验证
-C, --check 检查,并不执行
-T, --timeout=num 执行命令的超时时间,默认10s
-u, --user=username 执行远程执行的用户,被控端的用户
-b, --become 代替旧版的sudo切换
--becom-user=username 指定sudo的用户,默认为root
-k, --ask-become-pass 提示输入sudo时的口令/密码
#通配符*
#例
ansible "*" -m module ping
ansible "10.1.1.*" -m module ping
#或关系
#10.1.1.1主机或者10.1.1.10主机
ansible "10.1.1.1:10.1.1.10" -m module ping
#逻辑与
#在webservers组并在dbservers组的主机
ansible "webservers:$dbservers" -m module ping
#逻辑非
#在webservers组,但不在dbservers组中的主机
#逻辑非中主机用单引号''引起来
ansible 'webservers:!dbservers' -m module ping
#正则表达式
ansible执行过程
- 加载自己的配置文件,默认/etc/ansible/ansible.cfg
- 加载自己对应的模块文件,如command
- 通过ansible将模块或者命令生成对应的py临时文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-NUM/xxx.py文件
- 给文件+x权限
- 执行并返回结果
- 删除临时py文件,退出
ansible-galaxy
此工具会下载相应的角色roles,网站:https://galaxy.ansible.com
#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy-redis
ansible-pull
此工具会推送ansible的命令至远程,效率无限提升,对运维要求较高
ansible-playbook
此工具用于执行以编写好的playbook任务
#例
ansible-playbook hello.yml
ansible-vault
此工具用于加解密yml文件
#格式
ansible-vault [create|decrypt|edit|encrypt|rekey|view] 文件名
#例
ansible-vault encrypt hello.yml 加密文件
ansible-vault decrypt hello.yml 解密文件
ansible-vault view hello.yml 查看文件
ansible-vault edit hello.yml 编辑文件
ansible-vault rekey hello.yml 修改口令
ansible-vault create hello.yml 创建新文件
ansible-console
此工具可交互执行命令,支持tab,ansible2.0+新增
#格式
执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$
#常用子命令
设置并发数: forks n 例如:forks 10
切换组: cd 主机组 例如:cd webappservers
列出当前主机组列表: list
列出所有内置命令: ?或help
#例
root@all (2)[f:5]$ list
root@all (2)[f:5]$ cd appservers
root@appservers (2)[f:5]$ yum name=httpd state=present
root@appservers (2)[f:5]$ service name=httpd state=started
ansible常用模块
command模块
在远程主机执行命令,此为默认模块,可忽略-m选项
此模块不支持变量 < > | ; &等
#例
ansible webservers -a 'echo hello > /data/hello.txt'
ansible webservers -m command -a 'echo hello world!'
shell模块
shell模块和command相似,用shell执行命令,此模块支持变量 < > | ; & *等各种符号,比command更强大
可以在ansible.cfg中更改默认command为shell模块
#例
ansible webservers -m shell -a 'echo $HOSTNAME'
script模块
在远程主机运行ansible服务器上的脚本,此模块会把脚本复制到远程主机,执行完毕后删除
ansible webservers -m script -a /data/test.sh
copy模块
从ansible服务器复制到远程主机
#如果目标存在,默认覆盖,先指定备份
#例1
ansible webservers -m copy -a "src=/root/test.sh dest=/tmp/test.sh owner=wang mode=600 backup=yes"
#解释
src ansible服务器文件位置
dest 远程主机文件位置
owner 属主
mode 权限
backup 是否备份
#将文本内容直接复制到远程主机
#例2
ansible webservers -m copy -a "content='test line1\ntest line2' dest=/tmp/test.txt"
#解释
content= 输入文本内容
\n 为换行
dest 远程主机位置
fetch模块
从远程主机提取文件至ansible主控端,与copy相反,目前不支持目录
#例
ansible webservers -m fetch -a "src=/root/test.sh dest=/data/scripts"
file模块
设置文件属性,创建空文件
#创建空文件
#例
ansible webservers -m file -a "path=/date/test.txt state=touch"
#删除空文件
ansible webservers -m file -a "path=/date/test.txt state=absent"
#设置属性
ansible webservers -m file -a "path=/date/test.txt owner=wang mode=644"
#创建目录
ansible webservers -m file -a "path=/data/mysql state=directory owner=wang group=mysql"
#创建软连接
ansible webservers -m file -a "src=/data/link1 dest=/tmp/link1 state=link"
unarchive模块
解压缩包
实现的两种用法:
1.将ansible主机的压缩包传到远程主机解压缩至特定目录,设置copy=yes
2.将远程主机上的某个压缩包解压到指定路径下,设置copy=no
copy:默认为yes,当copy=yes时,拷贝的文件是从ansible主机复制到远程主机上,如果设置copy=no时,会在远程主机上寻找src原文件
remote_src:和copy功能一样互斥,yes表示在远程主机,不再ansible主机,no表示文件在ansible主机上
src:源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是让远程主机上的路径,则需要设置copy=no
dest:远程主机上的目标路径
mode:设置解压缩后的文件权限
#例
ansible webservers -m unarchive -a "src=/tmp/etc.tar.gz dest=/tmp/test/"
archive模块
打包、压缩
ansible webservers -m archive -a "path=/tmp/test/etc dest=/tmp/file1.tar.bz2 format=bz2 owner=wang mode=600"
hostname模块
管理主机名
ansible 10.1.1.1 -m hostname -a "name=mysql_server"
cron模块
计划任务
支持的时间:分钟minute,小时hour,天day,月month,周weekday
#例
#创建计划任务
ansible 10.1.1.1 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
#解释
job 远程主机上的文件路径
disabled=yes 禁用计划任务
disabled=no 启用计划任务
#删除计划任务
ansible webservers -m cron -a "name='backup mysql' state=absent"
yum模块
管理软件包,只支持RHEL系列OS,不支持Ubuntu等OS
yum默认安装最新版本
#安装
ansible webservers -m yum -a "name=httpd state=prsent"
#卸载
ansible webservers -m yum -a "name=httpd state=absent"
service模块
服务的管理
#启动服务
ansible webservers -m service -a "name=httpd state=started"
#停止服务
ansible webservers -m service -a "name=httpd state=stopped"
#参数
enable 开启启动yes或no
state started、stopped、restarted
user模块
用户管理
#创建用户
ansible webservers -m user -a 'name=user1 comment="test user" uid=608 home=/app/user1 group=class shell=/sbin/nologin'
#删除用户及家目录
ansible webservers -m user -a "name=user1 state=absent remove=yes"
group模块
用户组管理
#创建组
ansible webservers -m group -a "name=group1 gid=999"
#删除组
ansible webservers -m group -a "name=group1 state=absent"
lineinfile模块
相当于sed,可以修改文件内容,在ansible使用sed时会遇到特殊符号替换的问题
ansible webservers -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=enforcing'"
#解释
path 需要修改的文件
regexp 过滤条件
line 修改的内容
replance模块
类似sed命令,主要基于正则表达式进行匹配和替换
#注释UUID开头的行
ansible webserver -m replance -a "path=/etc/fstab regexp=^(UUID.*) replance='#\1'"
setup模块
收集主机的系统信息,这些facts信息可以直接以变量的形式使用,但是如果有多台主机,会影响执行速度,可以使用gather_facts=no来禁止ansible手机facts信息
ansible webservers -m setup -a "filter=..."
filter 过滤字段
playbook
playbook介绍
playbook是由一个或多个play组成的列表
playbook主要功能是将定义的一组主机,装扮成事先通过ansible中的task定义好的角色。tast实际是调用ansible的一个module,将多个play组织在一个playbook中,即让它们联合起来,按事先编排的机制执行预定义的动作
playbook文件是采用YAML语言编写的
YAML语言
一种标记语言,可读性高
语言特性
- YAML可读性好
- YAML和脚本语言的交互性好
- YAML使用实现语言的数据类型
- YAML有一个一致的信息模型
- YAML易于实现
- YAML可以基于流来处理
- YAML表达能力强,扩展性好
格式
在单一文件第一行,用连续三个”-“开始,还有选择性的连续三个点“...”用来表示文件的结尾
第二行开始写正常的playbook内容,一般建议写该playbook的功能
使用#注释代码
缩进必须是统一的,不能空格和tab混用
缩进的级别也必须是统一的,同样的缩进代表同样的级别,程序判断配置的级别是通过缩进结合换行来实现的,YAML文件内容是区分大小写的,key/value的值均需大小写
多个k/v可同行写也可换行写,同行使用,分隔
v可以是字符串,也可以是另一个列表/数组
一个完整的代码块功能需最少元素包括name和task
一个name只能包括一个task
YAML文件扩展名通常为yml或yaml
YAML常见的数据结构
list列表
列表由多个元素组成,且所有元素前均使用“-”开头
#例
#a list of tasty fruits
- Apple
- Orange
- strawberry
[Apple,Orange,strawberry]
dictionary字典
字典通常由多个key与value构成
#例
#an employee record
name: example developer
job: developer
skill: elite
{name: "example developer",job: "developer",skill: "elite"}
playbook核心元素
hosts
执行的远程主机列表
#例
- hosts: webservers:appservers 或
remote_user
可用于hosts和task中,指定通过sudo切换到某个用户的方式在远程主机执行任务
#例
- hosts: webservers
remote_user: root
task:
- name: test connection
ping:
remote_user: jack
sudo: yes
sudo_user: wang #默认sudo为root,修改sudo为wang
task和action
主要为task list,可以有多个task list
task两种格式:
1.action:module arguments
2.module:arguments (建议使用)
shell和command模块后面跟命令,不是key/value
#例
- hosts: webservers
remote_user: root
task:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enable=yes
其他组件
playbook命令
#格式
ansible-playbook ... [option]
#常见选项
-C --check 只检测可能会发生的改变,但不真正执行操作
--list-hosts 列出运行任务的主机
--list-tags 列出tag
--list-tasks 列出task
--limit 主机列表 只针对主机列表中的主机执行
-v -vv -vvv 显示过程
#playbook文件范例
#创建mysql用户和组
---
# create mysql user and group
- hosts: dbservers
remote_user: root
tasks:
- name: create mysql group
group: name=mysql system=yes gid=330
- name: "create mysql user"
user: name=mysql system=yes group=mysql shell=/sbin/nologin create_home=no home=/data/mysql uid=330
#group、user都是模块
#name: 动作名称
#name= key/value
#检查是否有错误,执行playbook
ansible-playbook /etc/ansible/playbook/install_mysql.yml -C
ansible-playbook /etc/ansible/playbook/install_mysql.yml
#查看是否成功
ansible dbservers -m shell -a "getent passwd mysql"
ansible dbservers -m shell -a "id mysql"
handlers和notify
类似mysql中的触发器触发的动作行为
handlers触发行为,notify触发器
#例yml文件
---
- hosts: webservers
remote_user: root
task:
- name: install httpd
yum: name=httpd state=present
- name: copy configure file
copy: src=file/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd #notify与handlers中name内容必须一致,相当于一个函数,在此调用函数
- name: start httpd service
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd #notify与handlers中name内容必须一致,相当于一个函数,在此调用函数
service: name=httpd stated=restarted
#notify出发多个动作
#例
notify:
- restart httpd
- check httpd process
handlers:
- name: restart httpd
service: name=httpd state=restarted enabled=yes
- name: check httpd process
shell: killall -0 httpd &> /tmp/httpd.log
#killall -0 (数字0,检查进程是否存在)
playbook中的变量
变量名只能以字母开头,字母、数字和下划线组成,
```` yml
#变量定义
variable_name=value
#例
http_prot=80
#调用方式
通过{{ variable_name }}调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才能生效
#变量来源
1.ansible的setup facts远程主机的所有变量都可以直接调用,在playbook中调用,命令行不可调用
2.通过命令行指定变量,优先级最高
#例
ansible-playbook -e "variable_name=value"
3.在playbook文件中定义变量
#例
- hosts: webservers
remote_user: root
vars: #定义多个变量variable: value- username: user1
- groupname: group1
#调用变量
task:- name: create group
group: name={{ groupname }} state=present - name: create user
user: name={{ username }} state=present
- name: create group
4.使用变量文件
#建立一个独立的playbook文件用来定义文件
#例
vim vars.yml
#variables file
username: user1
groupname: group1
...
#在另一文件中调用变量
- hosts: webservers
remote_user: root
vars_files: #调用变量文件- /etc/ansible/variable/vars.yml #文件名路径
task:- name: create group
group: name={{ groupname }} state=present - name: create user
user: name={{ username }} state=present
- name: create group
- /etc/ansible/variable/vars.yml #文件名路径
5.主机清单文件中定义变量
#例
#定义主机变量
[webservers]
172.16.99.144 http_port=80
#定义主机组变量
[webservers:vars]
ntp_server=ntp.server1.com
http_port=80
#### template模版
> ansible的一个模块
>
> 模版是一个文本文件,可以作为生成文件的模版,并且模版文件中还可以嵌套jinja语法
**jinja2语言**
> jinja2语言使用字面量,有下面形式:
>
> 字符串:使用单引号或双引号
>
> 数字:整数,浮点数
>
> 列表:[item1,item2,...]
>
> 元组:[item1,item2,...]
>
> 字典:{key1:value,key2:value,...}
>
> 布尔型:true/false
>
> 算术运算:+,-,*,/,//,%,**
>
> 比较操作:==,!=,>,<,>=,<=
>
> 逻辑运算:and,or,not
>
> 流表达式:for, if,when
>
> 字面量:表示字符串和数值
**template**
> 功能:可以根据和参考模块文件,动态生成相类似的配置文件
>
> template文件见必须放在template目录下,命名为*.j2结尾
>
> yaml文件和templates目录平级
````shell
#利用template同步nginx配置文件
#准备templates/nginx.conf.j2
vim temnginx.yml
---
- hosts: webservers
remote_user: root
task:
- name: template config to remote hosts
template: src=nginx.conf dest=/etc/nginx/nginx.conf
ansible-playbook temnginx.yml
##template替换,相当于cp
mkdir templates
cp nginx.conf /etc/ansible/templates/nginx.conf.j2
vim /etc/ansible/templates/nginx.conf.j2
#添加下面一行,工作进程
worker_processes {{ ansible_processor_vcpus }};
#修改temnginx2.yml文件
vim temnginx2.yml
---
- hosts: webservers
remote_user: root
task:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
ansible-playbook temnginx2.yml
#算数运算
worker_processes {{ ansible_processor_vcpus**2 }};
#template文件中的流程控制if和for,在*.j2文件中编辑好后,在yml文件中调用此文件
定义nginx_vhost列表
{% for vhost(变量名) in nginx_vhosts(列表) %}
server {
listen {{ vhost.listen }}
}
{% endfor %}
#when语句条件测试,在yml文件使用when,j2文件使用if
task:
- name: "shutdown"
when: ansible_os_family == "RedHat"
command: /sbin/shutdown -h now
#playbook文件中迭代with_items
#重复性执行任务,固定变量名item
task:
- name: add users
user: name={{ item }} state=present group=wheel
with_item:
- testuser1
- testuser2
roles角色
role是ansible1.2版本引入,用于层次性、结构化的组织playbook。role能够根据层次结构自动装载变量文件、task以及handlers等。要使用roles只需在playbook中使用include指令即可
运维复杂的场景建议使用roles,代码复用度高
roles:多个角色的集合,可以将多个role,分别放至目录roles下的独立自目录中
roles目录结构
playbook.yml
roles/
project/ 项目名称
tasks/ 任务,至少包含一个名为main.yml的文件,include调用
files/ copy或script等文件
vars/ 变量
templates/ 模版,至少包含一个名为main.yml的文件,include调用
handlers/ 变量,至少包含一个名为main.yml的文件,include调用
default/ 默认变量,优先级比vars低
meta/ 元数据,至少包含一个名为main.yml的文件,include调用
...
main.yml文件中定义了yml的执行顺序
#调用角色方法一
---
- hosts: webservers
remote_user: root
roles:
- mysql
- nginx
#调用角色方法二
#传递变量给角色
---
- hosts: webservers
remote_user: root
roles:
- mysql
- { role: nginx, username: nginx }
#调用角色方法三
#条件测试
---
- hosts: webservers
remote_user: root
roles:
- mysql
- { role: nginx, username: nginx, when: ansible_distribution_major_version == "7" }
#调用角色方法四
#使用tag标签