(一)架构
Ansible Core
Modules
Core Modules(核心模块)
Customed Modules(自定义模块)
Host Inventory(主机清单,定义需要被管理的主机)
Files
CMDB
配置管理数据库??
PlayBooks(YAML格式的"剧本"即要执行的具体任务描述文件)
Hosts
roles
Connection Plugins
并发连接插件
(二)Ansible概念与特性
Configuration、Command and Control
Ansible is a radically simple model-driven configuration management,
multi-node deployment, and remote task execution system. Ansible works
over SSH and does not require any software or daemons to be installed
on remote nodes. Extension modules can be written in any language and
are transferred to managed machines automatically.
运维工具的分类:
agent:基于专用的agent程序完成管理功能,puppet, func, zabbix, ...
agentless:基于ssh服务完成管理,无须在客户端安装额外软件,ansible, fabric, ...
ansible特性
①学习曲线比较平滑
②模块化:调用特定的模块,完成特定的任务;
③基于Python语言研发,由Paramiko, PyYAML和Jinja2三个核心库实现;
④部署简单:agentless;
⑤支持自定义模块,使用任意编程语言;
⑥强大的playbook机制;
⑦幂等性, 即其任意多次执行所产生的影响均与一次执行的影响相同。这里主要指的是playbook具有该特性.
(三)ansible的安装与使用
3.1.1安装及程序环境
yum -y install ansible
#epel源,目前最新版本是2.2
程序
ansible # 主程序
ansible-playbook # 执行playbook的程序
ansible-doc # 查看文档
3.1.2各配置文件
主配置文件
/etc/ansible/ansible.cfg
主机清单:
/etc/ansible/hosts
角色目录:
/etc/ansible/roles
插件目录:
/usr/share/ansible_plugins/
3.2基本使用入门
3.2.1 ansible命令
ansible <host-pattern> [options]
host-pattern: 主机清单(host inventory)文件里的组名/通配符名或者某远程主机ip或者all
(表示所有的主机清单组)等
options:
-m MOD_NAME
#指明模块 ansible-doc -l
可以获取到模块名
-a MOD_ARGS
#指明模块参数
3.2.2 配置Host Inventory
[group_id]
HOST_PATTERN1
HOST_PATTERN2 ```
![在/etc/ansible/hosts里设置主机清单](http://upload-images.jianshu.io/upload_images/2057465-e74001d3135425a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**3.3 ansible常用的模块说明**
**模块:**处理各种任务的库
获取模块列表:**`ansible-doc -l`**
获取指定模块的使用帮助:**`ansible-doc -s MOD_NAME`**
![生成与远程主机通信所需的公私钥](http://upload-images.jianshu.io/upload_images/2057465-d2f246d325bdda7b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![与远程主机建立基于密钥的连接](http://upload-images.jianshu.io/upload_images/2057465-a945ee71d317416a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
|模块名|作用与参数|
|:----:|:------|
|**ping**|探测目标主机是否存活,无参数,如下图|
![ping模块](http://upload-images.jianshu.io/upload_images/2057465-125f262a9a838845.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
|模块名|作用与参数|
|:----:|:------|
|**command**|**默认的模块**在远程主机执行命令,注意参数不支持管道等特殊字符.示例:ansible websrvs -m command -a "ifconfig"|
|**shell**|在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等.**注意:command和shell模块的核心参数直接为命令本身;而其它模块的参数通常为“key=value”格式**.示例:|
|**copy**| 拷贝文件到远程主机用法|
(1) 复制文件-a "src= dest= "
(2) 给定内容生成件content:直接编写内容 -a "content= dest= "
(3) dest:目标文件地址
(4) mode, owner, group, ...
|模块名|作用与参数|
|:----:|:------|
|**file**|设置文件属性,可以创建目录 创建链接文件 删除文件等用法|
(1) 创建目录: -a "path= state=directory"
(2) 创建链接文件: -a "path= src= state=link"
(3) 删除文件: -a "path= state=absent"
(4) owner: -a "path= owner= .."
(5) mode: -a "path= mode=064 ..."
|模块名|作用与参数|
|:----:|:------|
|**fetch**|从远程主机拉取文件,比较少用因为有scp|
|**cron**|管理定时任务|
minute= # 指定分钟
hour= # 指定小时
day= # 指定日期
month= # 指定月份
weekday= # 指定星期几
job= # 定时任务的命令
name= # 对定时任务的描述
user= # 指定修改哪个用户的crontab文件
state={present|absent} # 控制定时任务,absent会将定时任务清除.
|模块名|作用与参数|
|:----:|:------|
|**hostname**|管理主机名 示例: `ansible all -m hostname -a "name=IBM"`|
|**yum**|管理软件包 **注意:YUM仓库须事先配置好**示例: `ansible all -m yum -a "name=httpd state=present enabled=true"`|
|**service**|管理服务,示例:`ansible all -m service -a "name=httpd state=started"`|
参数
name=
state={started|stopped|restarted}
enabled={true|false}
runlevel= #在哪些级别下可以开机自启动
|模块名|作用与参数|
|:----:|:------|
|**group**|添加或删除组gid # Optional `GID' to set for the group.
name= # Name of the group to manage.
state # Whether the group should be present or not on the remote host.
system # If `yes', indicates that the group created is a system group.
|模块名|作用与参数|
|:----:|:------|
|**user**|管理用户帐号. 示例:|
|***setup***|**以json的格式收集远程主机的各个由ansible对其设定的变量参数即ansible_facts 这项非常重要**示例: `ansible all -m setup` |
** 3.4YAML语言(ansible的playbook文件就是用的这种格式)**
**YAML**(英语发音:
[/](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99)[ˈ](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99#.E7.AC.A6.E8.99.9F)[j](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99#.E7.AC.A6.E8.99.9F)[æ](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99#.E7.AC.A6.E8.99.9F)[m](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99#.E7.AC.A6.E8.99.9F)[əl](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99#.E7.AC.A6.E8.99.9F)[/](https://zh.wikipedia.org/wiki/Wikipedia:%E8%8B%B1%E8%AA%9E%E5%9C%8B%E9%9A%9B%E9%9F%B3%E6%A8%99),尾音类似*camel*骆驼)是一个可读性高,用来表达资料序列的格式。YAML参考了其他多种语言,包括:[C语言](https://zh.wikipedia.org/wiki/C%E8%AA%9E%E8%A8%80)、[Python](https://zh.wikipedia.org/wiki/Python)、[Perl](https://zh.wikipedia.org/wiki/Perl),并从[XML](https://zh.wikipedia.org/wiki/XML)、电子邮件的数据格式(RFC [2822](http://www.rfc-editor.org/rfc/rfc2822.txt))中获得灵感。Clark Evans在2001年首次发表了这种语言[[1]](https://zh.wikipedia.org/wiki/YAML#cite_note-1)
,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者[[2]](https://zh.wikipedia.org/wiki/YAML#cite_note-2)
。目前已经有数种编程语言或脚本语言支援(或者说解析)这种语言。
*YAML*是"YAML Ain't a Markup Language"(YAML不是一种[标记语言](https://zh.wikipedia.org/wiki/%E6%A0%87%E8%AE%B0%E8%AF%AD%E8%A8%80))的[递回缩写](https://zh.wikipedia.org/wiki/%E9%81%9E%E8%BF%B4%E7%B8%AE%E5%AF%AB)。在开发的这种语言时,*YAML* 的意思其实是:"Yet Another Markup Language"(仍是一种[标记语言](https://zh.wikipedia.org/wiki/%E6%A0%87%E8%AE%B0%E8%AF%AD%E8%A8%80))[[3]](https://zh.wikipedia.org/wiki/YAML#cite_note-YAML_spec_2001_08_01-3)
,但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重新命名。
**常用数据结构**
- 清单([阵列](https://zh.wikipedia.org/wiki/%E9%99%A3%E5%88%97))[[编辑](https://zh.wikipedia.org/w/index.php?title=YAML&action=edit§ion=6)]
习惯上清单比较常用区块格式(block format)表示,也就是用短杠+空白字元作为起始。
--- # 最喜愛的電影
- Casablanca
- North by Northwest
- Notorious
--- # 購物清單
[milk, pumpkin pie, eggs, juice]
- 字典
{name:jerry, age:21}
{name: John Smith, age: 33}
**PlayBook的基本格式**
```python
核心元素:
hosts: 运行指定任务的目标主机;
remote_user:在远程主机以哪个用户身份执行;
tasks: 任务,由模块定义的操作的列表;
Templates: 模板,即使用了模板语法的文本文件;
Variables: 变量
handlers: 由特定条件触发的Tasks;
Roles: 角色,由多个自包含的任务 变量 templates handlers等组成的操作的集合.
playbook的基础组件:
hosts: 运行指定任务的目标主机
remote_user: 在远程主机以哪个用户身份执行;
sudo_user:非管理员需要拥有sudo权限;
tasks:任务列表
模块,模块参数,格式有如下两种:
(1) action: module arguments
(2) module: arguments
示例1:
- hosts: all
remote_user: root
tasks:
- name: install a group
group: name=mygrp system=true
- name: install a user
user: name=user1 group=mygrp system=true
示例2:
- hosts: websrvs
remote_user:
tasks:
- name: install httpd package
yum: name=httpd
- name: start httpd service
service: name=httpd state=started
执行playbook文件
运行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
handlers的用法
handlers:由特定条件触发的Tasks;
调用及定义方式:
tasks:
- name: TASK_NAME
module: arguments
notify: HANDLER_NAME
handlers:
- name: HANDLER_NAME
module: arguments
示例:
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install conf file
copy: src=/root/httpd.conf 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
tags的用法
tags: 给指定的任务定义(打)一个调用标识,以便可以选择性地执行或跳过执行这些任务,多个标签想要同时调用的话用","分隔开即可。在playbook文件中的写法如下:
- name: NAME
module: arguments
tags: TAG_ID
与tags相关的执行方法:**ansible-playbook [-t, TAGS, --tags=TAGS] | [--skip-tags=SKIP_TAGS] | [--list-tags] PLAYBOOKFILE.yaml
**
Variables,变量,即向playbook传递相关变量使得playbook功能更强大(跟真正的脚本语言一样了)
类型:
内建变量:
(1) facts # 还记得ansible 10.1.1.78 -m setup setup模块吗?
自定义变量的几种形式:
(1) 命令行传递;
ansible-playbook -e VAR=VALUE
(2) 在hosts Inventory(/etc/ansible/hosts文件)中为每个主机定义专用变量值;
(a) 向不同的主机传递不同的变量 ;
IP/HOSTNAME variable_name=value
(b) 向组内的所有主机传递相同的变量 ;
[groupname:vars] # 这个vars是固定写法
variable_name=value
(3) 在playbook中定义 # 优先级低于(1),所以同名变量(1)可以覆盖(3)
vars: # 这个不能少
- var_name: value # 示例 - pkgname: httpd
- 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, ...}
变量调用,如下图中的playbook文件中定义:
{{ var_name }}
Templates:模板,ansible中的模板功能由jinja2模块支持,模板化一个文件到远程主机
文本文件,内部嵌套有模板语言脚本(使用模板语言编写)
Jinja2 is a template engine written in pure Python. It provides a Django inspired non-XML syntax but supports inline expressions and an optional sandboxed environment.
语法:与Python一致
字面量:
字符串:使用单引号或双引号;
数字:整数、浮点数;
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:
+, -, *, /, //, %, **
比较操作:
==, !=, >, <, >=, <=
逻辑运算:and, or, not
执行模板文件中的脚本,并生成结果数据流,需要使用template模块且此模块仅支持在playbook中使用
backup # Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.
dest= # Location to render the template to on the remote machine.
follow # This flag indicates that filesystem links, if they exist, should be followed.
group # name of the group that should own the file/directory, as would be fed to `chown'
mode # mode the file or directory should be, such as 0644 as would be fed to `chmod'. As of version 1.8, the mode may be specified as a symbolic mode (for example, `u+rwx' or `u=rw,g=r,o=r').
owner # name of the user that should own the file/directory, as would be fed to `chown'
selevel # level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the `range'. `_default' feature works as for `seuser'.
serole # role part of SELinux file context, `_default' feature works as for `seuser'.
setype # type part of SELinux file context, `_default' feature works as for `seuser'.
seuser # user part of SELinux file context. Will default to system policy, if applicable. If set to `_default', it will use the `user' portion of the policy if available
src= # Path of a Jinja2 formatted template on the local server. This can be a relative or absolute path.
validate # The validation command to run before copying into place. The path to the file to validate is passed in via '%s' which must be present as in the visudo example below. validation to run before copying into place. T
~
注意:此模板不能在命令行使用,而只能用于playbook;
一个完整的playbook示例文件:
- hosts: ngxsrvs
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=latest
- name: install conf file
template: src=/root/nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: ngxconf
notify: reload nginx service
- name: start nginx service
service: name=nginx state=started enabled=true
handlers:
- name: reload nginx service
shell: /usr/sbin/nginx -s reload
playbook中的条件测试语句之when(可以使得playbook功能更灵活)
when:在tasks中使用,Jinja2的语法格式
- hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=latest
- name: start nginx service on CentOS6
shell: service nginx start
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
#这里的ansible_distribution、ansible_distribution_major_version都是内置变量,可用下图方式获得
- name: start nginx service
shell: systemctl start nginx.service
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
playbook中的循环测试语句之with_items
循环:迭代,需要重复执行的任务对迭代项的引用,固定变量名为"item”,使用with_item属性给定要迭代的元素
元素:列表
字符串
字典
基于字符串列表给出元素的playbook示例:
- hosts: websrvs
remote_user: root
tasks:
- name: install packages
yum: name={{ item }} state=latest # 注意这里循环的用法 item是固定的名称
with_items:
- httpd # 以- 开头的每一行内容都会被认为是一个item,下面的基于字典也如此
- php
- php-mysql
- php-mbstring
- php-gd
基于字典列表给元素的playbook示例
- hosts: all
remote_user: root
tasks:
- name: create groups
group: name={{ item }} state=present
with_items:
- groupx1
- groupx2
- groupx3
- name: create users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- {name: 'userx1', group: 'groupx1'}
- {name: 'userx2', group: 'groupx2'}
- {name: 'userx3', group: 'groupx3'}
角色: roles,以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等。/etc/ansible/roles/目录为默认的角色目录
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的文件,用于设定默认变量
下面截图部分为使用角色的一个小实例:
最后
在playbook中调用角色的方法,编辑一个调用role的yaml文件:ansible-playbook nginx.yml
- hosts: webservers
remote_user: root
roles:
- nginx # 这里即可调用上面截图部分创建的nginx角色了
- ROLE2 # 另一种方法,传递变量给role
- { role: nginx, nginxport: 8080, ...}
- { role: ROLE4, when: CONDITION }
实战作业:
(1) 主/备模型的keepalived+nginx;
(2) httpd+php+php-mysql;
(3) mysql-server或mariadb-server;
拥有testdb库,并允许testuser对其拥有所有权限;