ansible

ansible

一、基础介绍

运维工具的分类

根据控制端与被控制端进行交互的方式分为两类,一类需要被控制端启用功能,另一类中被控制端无须具备代理功能,控制端直接通过ssh协议以系统用户的身份与被控制端进行连接
agent:puppet, func, ...
agentless(ssh,):ansible, fabric

特性:

模块化:调用特定的模块,完成特定任务;
基于Python语言实现,由Paramiko, PyYAML和Jinja2三个关键模块;
部署简单:agentless;
支持自定义模块;
支持playbook;
幂等性;

安装:

依赖epel源,包名为 ansible

配置文件

主配置文件:/etc/ansible/ansible.cfg
主机清单:/etc/ansible/hosts

主程序:
ansible
ansible-playbook
ansible-doc

ansible的简单使用格式

ansible HOST-PATTERN -m MOD_NAME -a MOD_ARGS -f FORKS -C -u USERNAME -c CONNECTION

二、常用模块

(1)command模块

command模块:在远程主机运行命令;
chdir:执行命令前切换工作目录的指定位置
creates:/path/to/somefile 创建该目录前判断该目录是否存在
removes:/path/to/somefile 如果给定的文件或者目录不存在,则不执行命令
command模块为ansible的默认模块,可以不指定直接使用-a

[root@CentOS6 ~]#ansible all -m command -a 'date'
172.18.45.7 | SUCCESS | rc=0 >>
Tue Nov 21 10:47:55 CST 2017
...
#all:指明匹配的主机,可以是特定IP可以是host定义的组名,all表示全部主机
#-m 指定模块名
#-a 模块参数

(2)cron 模块

Manage cron.d and crontab entries.
minute=
day=
month=
weekday=
hour=
job=
*name=
state=
present:创建
absent:删除
示例:

[root@CentOS6 ~]#ansible webserv -m cron -a 'minute="*/10" job="/bin/echo hello" name="test cron job"'
172.18.45.8 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}
172.18.45.11 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}
#默认state=present,如果要删除该计划任务则添加state=absent
[root@CentOS6 ~]#ansible webserv -a 'crontab -l'
172.18.45.11 | SUCCESS | rc=0 >>
#Ansible: test cron job
*/10 * * * * /bin/echo hello
172.18.45.8 | SUCCESS | rc=0 >>
#Ansible: test cron job
*/10 * * * * /bin/echo hello

(3)user模块

管理用户账号
*name= #指定用户名
system=
uid=
shell=
group=
groups=
comment=
home=
generate_ssh_key= [true|false]
local=
默认state=present,如果要删除该用户则添加state=absent

(4)copy模块

Copies files to remote locations.
用法:
(1) src= #源路径 dest=#目标路径
(2) content= #取代src,直接生成目标文件 dest=
owner, group, mode
示例:

[root@CentOS6 ~]#ansible all -m copy -a 'src=/etc/fstab dest=/root/fstab.ansible owner=root mode=600'
#此处src可用content=“string...”代替

(5)file模块

Sets attributes of files定义文件属性
用法:
(1) 创建链接文件:*path= src= state=link
(2) 修改属性:path= owner= mode= group=
(3) 创建目录:path= state=directory
注意:sate属性的可用值
file,directory,link,hard,tuoch,absent

[root@CentOS6 ~]#ansible all -m file -a 'path=/root/ansible.link src=/root/fstab.ansible state=link'

(6)ping模块

测试指定主机是否能连接

(7)service模块

管理服务
*name= #服务名称
state=
started
stopped
restarted
enabled= #是否启用开机启动取值为“true or false”
runlevel=
示例:

[root@CentOS6 ~]#ansible websrvs -m service -a "name=nginx enabled=true state=started"
#enabled=true 设置开机自动启动

(8)shell模块

在远程主机在shell进程下运行命令,支持shell特性,如管道等;

(9)script模块

在远程主机运行一个本地的脚本
仅支持相对路径
ansible all -m script -a "script.sh"

(10)yum模块

yum模块:Manages packages with the '’yum' package manager
name=:程序包名称,可以带版本号;
state=
present(安装), latest(安装最新版本)
absent(卸载)
示例:

[root@CentOS6 ~]#ansible websrvs -m yum -a "name=nginx state=latest"

(11)setup模块

收集远程和主机的facts
可以用于剧本调用,作为变量为每台主机灵活定制配置参数

(12)git模块

Deploy software (or files) from git checkouts
repo=
dest=
version=

(13)deploy_helper模块

Manages some of the steps common in deploying projects.

(14)haproxy模块

Enable, disable, and set weights for HAProxy backend servers using socket commands.
backend=
host=
state=
weight=

三、playbook

(1)语法YAML

YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。目前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

YAML是"YAML Ain't a Markup Language"(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言),但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。

YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印除错内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。

(2)YAML特点:

可读性好;
和脚本的交互性好;
有一个一致的信息模型;
易于实现;
可以基于流量来处理;
表达能力强,扩展性好

(3)Playbook的核心组件

Hosts:主机
Tasks:任务列表
Variables:变量
Templates:包含了模板语法的文本文件;
Handlers:由特定条件触发的任务;

(4)Hosts

运行指定任务的目标主机;

(5)remoute_user

在远程主机上执行任务的用户;

(6)sudo_user

用户身份切换

(7)tasks

任务列表
模块,模块参数;
格式:
(1) action: module arguments
(2) module: arguments

注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;
(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
(2) 任务可以通过"tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
blaybook中通过hosts组件实现执行任务的目标主机或者主机群灵活调用,而tasks组件下的tags元素则实现了各项任务的单独调用。

(8)notify

触发器
notify作为触发器被定义在tasks之下,当标记有notify触发器的任务被执行时会触发下文中handlers中定义的任务。
主要用于配置文件修改时触发服务重新启动,或者重读配置文件。

(9)handlers

处理器
handles定义了一个任务,与tasks不同的是handles定义的任务是条件式触发的,当标记触发器notify的任务被执行时才会触发handles定义的任务。

示例:

[root@CentOS6 ~]#vim nginx.yml 
- hosts: websrvs
  remote_user: root
  tasks:
  - name: install nginx pachkage
    yum: name=nginx state=latest
  - name: start nginx service
    service: name=nginx enabled=true state=started

- hosts: dbsrvs
  remote_user: root
  tasks:
  - name: install redis package
    yum: name=redis state=latest
  - name: install conf file
    copy: src=/root/redis.conf dest=/etc/redis.conf owner=redis group=root mode=644
    tags: instconf
    notify: restart redis service	#触发器
  - name: start redis service
    service: name=redis state=started
  handlers:	#处理器
  - name: restart redis service
    service: name=redis state=restart

四、运行playbook的方式

(1) 测试
ansible-playbook --check #只检测可能会发生的改变,但不真正执行操作;
ansible-playbook --list-hosts #列出运行任务的主机;
ansible-playbook --list-tasks #列出要运行的任务列表
ansible-playbook --syntax-check #语法检查

(2) 运行handlers:
任务,在特定条件下触发;
接收到其它任务的通知时被触发;
notify: HANDLER TASK NAME

variables

(1) facts:可直接调用;
注意:可使用setup模块直接获取目标主机的facters;

(2) 用户自定义变量:
(a) ansible-playbook命令的命令行中的
-e VARS, --extra-vars=VARS
(b) 在playbook中定义变量的方法:
vars:
- var1: value1
- var2: value2

变量引用:{{ variable }}
示例:

[root@CentOS6 ~]#vim instpkg.yml 
- hosts: websrvs
  remote_user: root
  vars:
  - pkgname: tree	#定义变量
  tasks:
  - name: install {{ pkgname }}
    yum: name={{ pkgname }} state=latest #调用变量
#name 同样支持变量调用

(3) 通过roles传递变量;

(4) Host Inventory
(a) 用户自定义变量
(i) 向不同的主机传递不同的变量;
IP/HOSTNAME varaiable=value var2=value2
(ii) 向组中的主机传递相同的变量;
[groupname:vars]
variable=value
(b) invertory参数
用于定义ansible远程连接目标主机时使用的参数,而非传递给

playbook的变量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansbile_sudo_pass
...

操作

说明:
该试验实现简单的ansible-playbook功能,通过一台控制端配置三台web服务器安装nginx,配置两台数据库服务安装redis同时同一部署redis的配置文件,简单的将redis的监听端口改为0.0.0.0意为监听本机所有IP地址。
(一)配置host文件

[root@CentOS6 ~]#vim /etc/ansible/hosts
[webserv]
172.18.45.11
172.18.45.8
172.18.45.13
[dbserv]
172.18.45.7
172.18.45.12

(二)密钥验证
同步时间:ntpdate 172.18.0.1
生成私钥:

[root@CentOS6 ~]#ssh-keygen -t rsa

复制密钥给各个host:

ssh-copy-id -i /root/.ssh/id_rsa.pub root@172.18.45.11
ssh-copy-id -i /root/.ssh/id_rsa.pub root@172.18.45.12
...

查看ansible支持的所有模块:

[root@CentOS6 ~]#ansible-doc -l
a10_server                         Manage A10 Networks AX/SoftAX/Thunder/vThu...
a10_server_axapi3                  Manage A10 Networks AX/SoftAX/Thunder/vThu...
...

查看特定模块用法:

[root@CentOS6 ~]#ansible-doc -s MODULE_NAME

(三)编辑playbook

[root@CentOS6 ~]#vim nginx.yml		#要求以.yml结尾
- hosts: websrvs
  remote_user: root			#远程登录用户身份
  tasks:
  - name: install nginx pachkage
    yum: name=nginx state=latest
  - name: start nginx service
    service: name=nginx enabled=true state=started
#使用yum安装nginx启动服务,并设置开机自动启动
- hosts: dbsrvs
  remote_user: root
  tasks:
  - name: install redis package
    yum: name=redis state=latest
  - name: install conf file
    copy: src=/root/redis.conf dest=/etc/redis.conf owner=redis group=root mode=644
    #统一部署配置文件,指定配置文件源路径,目标路径,属主,属组,以及权限
  - name: start redis service
    service: name=redis state=started

(四)的配置文件
在ansible srv端安装redis,将redis的配置文件复制到playbook中指定的位置既/root目录之下,并修改监听端口将bind 127.0.0.1改为bind 0.0.0.0。
(五)测试
检查配置文件语法错误:

[root@CentOS6 ~]#ansible-playbook --syntax-check nginx.yml 
playbook: nginx.yml		#无误

模拟运行:

[root@CentOS6 ~]#ansible-playbook -C nginx.yml

(六)运行
在测试没有错误的情况下即可运行剧本

五、补充模块

setup模块

template模块

基于模板方式生成一个文件复制到远程主机
*src=
*dest=
owner=
group=
mode=

                <html>
                    <title></title>
                    <head></head>
                    <body>
                        ...
                        <?php
                            phpinfo();
                        ?>
                    </body>
                </html>

模板:templates
文本文件,嵌套有脚本(使用模板编程语言编写)
Jinja2:
字面量:
字符串:使用单引号或双引号;
数字:整数,浮点数;
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false

算术运算

+, -, *, /, //, %,**
比较操作:
==, !=, >, >=, <, <=

逻辑运算

and, or, not
示例:

- hosts: websrvs
  remote_user: root
  tasks:
    - name: install nginx
    yum: name=nginx state=present
    - name: install conf file
    template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    notify: restart nginx
    tags: instconf
    - name: start nginx service
    service: name=nginx state=started
    handlers:
    - name: restart nginx
    service: name=nginx state=restarted					

模板配置文件 :nginx.conf.j2

worker_processes {{ ansible_processor_vcpus - 1 }};
listen {{ http_port }};
server_name 

条件测试

when语句:在task中使用,jinja2的语法格式

tasks: 
- name: install conf file to centos7
  template: src=files/nginx.conf.c7.j2
  when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
  template: src=files/nginx.conf.c6.j2
  when: ansible_distribution_major_version == "6"				

循环:迭代,需要重复执行的任务;
对迭代项的引用,固定变量名为”item“
而后,要在task中使用with_items给定要迭代的元素列表;

列表方法:
字符串
字典

- name: install some packages
  yum: name={{ item }} state=present
  with_items:
  - nginx
  - memcached
  - php-fpm
- name: add some groups
  group: name={{ item }} state=present
  with_items:
  - group11
  - group12
  - group13
- name: add some users
  user: name={{ item.name }} group={{ item.group }} state=present
  with_items:
  - { name: 'user11', group: 'group11' }
  - { name: 'user12', group: 'group12' }
  - { name: 'user13', group: 'group13' }

六、角色(roles)

角色集合:
roles/
mysql/
httpd/
nginx/
memcached/

每个角色,以特定的层级目录结构进行组织:

mysql/
	files/ :存放由copy或script模块等调用的文件;
	templates/:template模块查找所需要模板文件的目录;
	tasks/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
	handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
	vars/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
	meta/:至少应该包含一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要在此文件中通过include进行包含;
	default/:设定默认变量时使用此目录中的main.yml文件;

在playbook调用角色方法1:

- hosts: websrvs
  remote_user: root
  roles:
  - mysql
  - memcached
  - nginx

在playbook调用角色方法2:传递变量给角色

- hosts: 
  remote_user:
  roles:
  - { role: nginx, username: nginx }
#键role用于指定角色名称;后续的k/v用于传递变量给角色;
#还可以基于条件测试实现角色调用;
roles:
- { role: nginx, when: "ansible_distribution_major_version == '7' " }

更多开源模块示例可参考:
https://github.com/ansible/ansible-examples

原文地址:https://www.cnblogs.com/qige2017/p/7906374.html