☞Ansible

Ansible


ansible简介

ansible playbooks

ansible部署{keepalived+nginx{httpd, mysql, php}}


ansible简介

Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine. 
Ansible是一款轻量级自动化运维工具,由Python语言开发,结合了多种自动化运维工具的特性,实现了批量系统配置、批量应用部署、批量命令执行等功能;ansible是基于模块化实现批量操作的。

ansible特点: 
模块化、部署简单、工作于agentless模式、默认使用ssh协议、支持自定义模块、支持Palybook等 

ansiblestruct.png

  • Ansible: 核心程序;

  • Modules: 包括 Ansible 自带的核心模块及自定义模块;

  • Plugins: 完成模块功能的补充,包括连接插件、邮件插件等;

  • Playbooks: 网上很多翻译为剧本,个人觉得理解为编排更为合理;定义 Ansible 多任务配置文件,有 Ansible 自动执行;

  • Host Inventory: 定义 Ansible 管理主机的清单,ansible只能管理Inventory中定义的主机

使用Paramiko,PyYAML和Jinja2三个Python的核心库实现 
部署简单:agentless; 
支持自定义模块,使用任意语言编写

问题:不同环境的目标系统如何对相同服务定制不同配置 
如让httpd侦听在不同的端口之上。

安装ansible

解决依赖关系

ansible程序包被Fedora-epel所收入,因此安装前需配置好epel仓库的yum源;

使用ansible前提条件

ansible基于SSH连接至host,因此有必要让ansible通过ssh-key连接主机。为了避免Ansible下发指令时输入目标主机密码,通过证书签名达到SSH无密码是一个好的方案,推荐使用ssh-keygen与ssh- copy-id来实现快速证书的生成和公钥下发,其中ssh-keygen生成一对密钥,使用ssh-copy-id来下发生成的公钥。具体操作如下:

  • 生成 SSH公玥和私钥文件 
    ssh-kengen -t rsa -P ' '

  • 拷贝公玥文件到目标主机的ssh认证文件中 
    ssh-copy-id -i ~/.ssh/id_rsa.pub root@HostIP

  • 连接测试 
    ssh root@HostIP

注意: 如果不配置主机免密钥登录,可以在/etc/ansible/hosts中定义用户和密码,主机ip地址,和ssh端口,这样也可以进行免密码访问,但是这个/hosts文件要保护好。

主要文件

程序:/usr/bin/ansible/usr/bin/ansible-playbook/usr/bin/ansible-doc 
配置文件:/etc/ansible/ansible.cfg 
主机清单:/etc/ansible/hosts 
插件目录:/usr/share/ansible_plugins

配置文件

Host Inventory

Inventory是一个简单的从外部资源寻找主机,主机组的成员,和变量信息的程序 – 可以是个 SQL 数据库,一个 CMDB 解决方案,或者是 LDAP。这个概念来自 Puppet (叫”External Nodes Classifier”),工作方式也是类似的。

Ansible 通过读取默认的主机清单配置/etc/ansible/hosts,可以同时连接到多个远程主机上执行任务,默认路径可以通过修改 ansible.cfg 的 hostfile 参数指定路径。

在主机清单文件中定义host组,便于执行命令时指定在哪些主机使用,也可在palybook文件调用这些定义好的主机名称。

1, ansible_ssh_host : 
指定主机别名对应的真实 IP,如:100 ansible_ssh_host=192.168.1.100,随后连接该主机无须指定完整 IP,只需指定 100 即可 
2, ansible_ssh_port : 
指定连接到这个主机的 ssh 端口,默认 22 
3, ansible_ssh_user: 
连接到该主机的 ssh 用户 
4, ansible_ssh_pass: 
连接到该主机的 ssh 密码(连-k 选项都省了),安全考虑还是建议使用私钥或在命令行指定-k 选项输入 
5, ansible_sudo_pass: sudo 密码 
6, ansible_sudo_exe: sudo 命令路径 
7, ansible_connection : 
连接类型,可以是 local、ssh 或 paramiko,ansible1.2 之前默认为 paramiko 
8, ansible_ssh_private_key_file : 私钥文件路径 
9, ansible_shell_type : 
目标系统的 shell 类型,默认为 sh,如果设置 csh/fish,那么命令需要遵循它们语法 
10, ansible_python_interpreter : 
python 解释器路径,默认是/usr/bin/python,但是如要要连BSD系统的话,就需要该指令修改 python 路径 
11, ansible__interpreter : 
这里的”*”可以是 ruby 或 perl 或其他语言的解释器,作用和 ansible_python_interpreter 类似

ansible.cfg

默认的forks=5,即一次fork 5个ansible进程与目标主机通信,fact缓存路径等 
如:

命令使用

ansible

ansible-doc

Show Ansible module documentation

ansible-playbook

常用模块

  1. ping:探测目标主机是否存活;

  2. command:在远程主机执行命令;默认的module 
    ansible all -m command -a "hostname "

  3. shell:在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等 ; 
    ansible all -m shell -a "cat /etc/passwd| grep root " 
    注意:command和shell模块的核心参数直接为命令本身;而其它模块的参数通常为“key=action”格式;

  4. copy: C o p i e s f i l e s t o r e m o t e l o c a t i o n s . 
    用法: 
    (1) 复制文件:-a “src= dest= ” 
    (2) 给定内容生成文件:-a “content= dest= ” 
    其它参数:mode, owner, group, …

  5. file:S e t s a t t r i b u t e s o f f i l e s 
    用法: 
    (1) 创建目录:-a “path= state=directory” 
    (2) 创建链接文件:-a “path= src= state=link” 
    (3) 删除文件:-a “path= state=absent“

  6. fetch:F e t c h e s a f i l e f r o m r e m o t e n o d e s

  7. cron:M a n a g e c r o n . d a n d c r o n t a b e n t r i e s . 
    -a ” ” 
    minute= 
    hour= 
    day= 
    month= 
    weekday= 
    job= 
    name= 
    user= 
    state={present|absent}

  8. hostname:M a n a g e h o s t n a m e 
    name=

  9. yum:M a n a g e s p a c k a g e s w i t h t h e I ( y u m ) p a c k a g e m a n a g e r 
    (1) name= state={present|latest} 
    (2) name= state=absent

  10. service:M a n a g e s e r v i c e s . 
    name= 
    state={started|restarted|stoped|reloaded} 
    started 
    stopped 
    restarted 
    enabled= 
    runlevel=

  11. group: A d d o r r e m o v e g r o u p s 
    name= 
    state= 
    system= 
    gid= 
    state={present|absent} 
    ansible db -m group -a 'name=test gid=1000'

  12. user:M a n a g e u s e r a c c o u n t s 
    name= 
    group= 
    groups= 
    comment= 
    uid= 
    system= 
    shell= 
    expires= 
    home= 
    state={present|absent} 
    ansible all -m user -a 'name=DBA uid=505 home=/Data/dba shell=/sbin/nologin' 
    ansible db -m user -a 'name=budongshu uid=506 state=absent'

  13. setup:G a t h e r s f a c t s a b o u t r e m o t e h o s t s 
    收集系统信息,作为可用的变量: 
    “device”: “eno16777736” 
    “address”: “10.1.22.106” 
    “ansible_distribution”: “CentOS” 
    “ansible_distribution_major_version”: “7” 
    “ansible_fqdn”: “localhost.localdomain”, 
    “ansible_hostname”: “cent6”, 
    “ansible_interfaces”: [ 
    “lo”, 
    “eth1”, 
    “eth0” 
    ], 
    …… 
    结构体类型的fact引用: 
    {{ ansible_eth0.ipv4.address }} 
    {{ ansible_eth0[“ipv4”][“address”] }} 
    {{ ansible_all_ipv4_addresses[0] }}

  14. template 
    template使用了Jinjia2格式作为文件模板,进行文档内变量的替换的模块。他的每次使用都会被ansible标记为changed状态。

  15. script:自动复制脚本到远程节点,并运行 
    ansible all -m script -a 'ansible_test.sh'

ansible各模块简单示例

ansible playbooks

playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的任务一项一项执行,一项task可能指定了多个host,且默认并行执行5个fork进程。

playbook内容组成

  • 核心元素: 

    1. tasks:任务,有模块定义的操作列表

    2. vas:变量

    3. tempaltes:模板,使用了Jinjia2格式作为文件模板

    4. handlers:由特定条件触发的Tasks;

    5. roles:角色

  • 基本组件 

    1. Hosts:指定目标主机

    2. remote_user:在远程主机上以哪个用户身份执行; 
      sudo_user:非管理员需要用于sudo权限

    3. tasks:任务列表 
      模块:模块参数 
      格式: 
      (1)action: module arguments 
      如: name、tags、with_items、notify、when、…… 
      (2)module: arguments 
      如: yum、copy、template、service、command、shell、……

host、user

playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户,如

remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。

vars

和 Facts 相反, 变量是一些值,或字典,列表的名称(可以是标量值–整数,布尔型,或字符串,字典,列表),然后变量可以应用在模板和剧本里面。他们是声明的东西,不是获取远程系统的当前状态或性质(这是Facts)

(1) 内置的facts变量通过 setup 模块获取; 
(2) 自定义变量:

  1. 命令行传递;

  1. Inventory还可以使用参数: 
    用于定义ansible远程连接目标主机时使用的属性,而非传递给playbook的变量;

  1. 在playbook中定义变量

  1. 在hosts Inventory中为每个主机定义专用变量值; 
    (a) 向不同的主机传递不同的变量 ; 
    IP/HOSTNAME variable_name=value 
    (b) 向组内的所有主机传递相同的变量 ; 
    [groupname:vars] 
    variable_name=value

  2. 在角色调用时传递

  • 调用方式: 
    {{ var_name }}

  • 结构体类型的fact变量引用: 
    {{ ansible_eth0.ipv4.address }} 
    {{ ansible_eth0[“ipv4”][“address”] }} 
    {{ ansible_all_ipv4_addresses[0] }}

  • 变量优先级总结: 
    命令行传递的外部变量优先级高;vars定义的变量优先级大于host Iventroy传递的变量,具体如下: 

    1. extra vars (在命令行中使用 -e)优先级最高

    2. 然后是在inventory中定义的连接变量(比如ansible_ssh_user)

    3. 接着是大多数的其它变量(命令行转换,play中的变量,included的变量,role中的变量等)

    4. 然后是在inventory定义的其它变量

    5. 然后是由系统发现的facts

    6. 然后是 “role默认变量”, 这个是最默认的值,很容易丧失优先权

命令行传递变量

playbook文件定义变量

hosts Inventory传递变量

Inventory组共用变量

用于定义ansible远程连接目标主机时使用的属性,而非传递给playbook的变量

调用role时传递变量

handlers

用于当关注的资源发生变化时采取一定的操作。“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。这意味着服务可以被反弹仅仅他们需要重启的时候。Handler 不仅仅可以用于重启服务,但是重启服务是最通用的用法。

tasks

play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。

task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。

每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。

Tags

Ansible 允许给playbook里面的资源通过自定义的关键字打上标签,然后只运行与关键字一致的部分代码。 例如,可能有个完成的 OS 配置,然后特定的步骤标记为 “ntp” ,然后运行 “ntp” 步骤来重新配置时间服务器信息。

template

Ansible 很容易的传输文件到远端系统上面,但是它经常需要替换一些变量在其它的文件里面。变量可以来自 清单文件,Host Vars, Group Vars,或者 Facts。Templates 使用 Jinja2 模板引擎同样可以包含逻辑控制像循环和 if 语句。

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.

Jinja2语法介绍:

  • 字面量: 
    字符串:使用单引号或双引号; 
    数字:整数、浮点数; 
    列表:[item1, item2, …] 
    元组:(item1, item2, …) 
    字典:{key1:value1, key2:value2, …} 
    布尔型:true/false

  • 算术运算: 
    +, -, , /, //, %, *

  • 比较操作: 
    ==, !=, >, <, >=, <=

  • 逻辑运算:and, or, not

执行模板文件中的脚本,并生成结果数据流,需要使用template模块;

此外,template模块只能在playbook文件中使用,不能在命令行调用 
【nothing】ansible websrvs -m copy -a “src=/root/nginx.conf dest=/tmp/nginx.conf” 
【error】ansible websrvs -m template -a “src=/root/nginx.conf dest=/tmp/nginx.conf”

例:在nginx配置文件中使用模板变量

when条件测试

一个可选的关键字来决定这个任务是不是应该指向,如果再 “when:” 关键字这里的表达式是是不正确的,这个任务会被忽略。When语句包含Jinja2表达式。

item循环

需要重复执行的任务,如同时安装一组程序或者重复一个轮询步骤直到收到某个特定结果。 
对迭代项的引用,固定变量名为”item”,使用with_item属性给定所有的元素列表:

  • 元素列表:字符串字典

(1)基于字符串的循环列表(行值)

(2) 基于字典的循环列表 
相当于给同一个action设定不同的值(列值)

PyYAML库

YAML is a data serialization format designed for human readability and interaction with scripting languages.

YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。

YAML Ain’t Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:”Yet Another Markup Language”(仍是一种标记语言)。其特性有:

YAML的可读性好 
YAML和脚本语言的交互性好 
YAML使用实现语言的数据类型 
YAML有一个一致的信息模型 
YAML易于实现 
YAML可以基于流来处理 
YAML表达能力强,扩展性好

更多的内容及规范参见:http://www.yaml.org

YAML语法

YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用”-“来代表,Map里的键值对用”:”分隔。下面是一个示例:

playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。

YAML文件扩展名通常为.yaml,如example.yaml或main.yml;

YAML坑

YAML语法要求如果值以{{ foo }}开头的话我们需要将整行用双引号包起来. 
错误:

正确:

palybook文件示例

(1)增加用户并指定组

(2)安装httpd程序

roles

一个 Role 可以包含特定的变量值,特定的任务,特定的触发器等东西。因为 Role 的文件结构,roles 可以是再次利用的单元,可以让你在其它 playbooks 中共享一些行为。

一个完整的role以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等;
role_struct: 
files/:存放有copy或script等模块调用的文件; 
tasks/:至少有一个main.yml用于定义主task,其他文件应被main.yml包含调用; 
handlers/:至少有一个main.yml用于定义主handler,其他文件应被main.yml包含调用; 
templates/:存放有template模块调用的模板文件; 
meta/:至少有一个main.yml用于定义当前role的特殊设定及依赖关系,其他文件应被main.yml包含调用 
default/:至少有一个main.yml用于定义默认的变量;

简单的role示例

  • 创建roles目录结构 
    mkdri -p /etc/ansible/roles/{nginx,mysql,httpd}/{files,tasks,handlers,vars,templates,meta,default}

  • 编辑任务文件:vi /nginx/tasks/main.yml

  • 编辑关联任务:vi /nginx/handlers/main.yml

  • 编辑playbook变量:vi vars/main.yml

  • 编辑模板文件:vi nginx.conf.j2 default.conf.j2 
    cp /etc/nginx/nginx.conf roles/nginx/templates/nginx.conf.j2 
    cp /etc/nginx/conf.d/default.conf roles/nginx/templates/default.conf.j2

  • 编辑role调用文件:vi palynginx.yml

  • 检查整个role语法、测试执行 
    ansible-playbook --syntax-check playnginx.yml 
    ansible-playbook -C playnginx.yml

  • 调用执行playbook文件 
    ansible-playbook playnginx.yml

总结

    ansible作为运维工具中远程命令执行工具,能够实现:批量部署应用程序、系统配置、批量命令执行等功能,是一款较轻量化的Python程序。ansible经过不断的发展,具有模块化、部署简单、工作于agentless模式、使用ssh协议、支持自定义模块、支持Palybook等特点。 
    Playbooks 可用于收集主机配置信息,更强大的地方在于 playbooks 中可以编排有序的任务执行过程,甚至于做到在多组机器间来回有序的执行指定步骤任务,且可以同步或异步的发起任务。

更多信息:http://www.ansible.com.cn/docs/

ansible部署{keepalived+nginx+{httpd, mysql, php}}

架构图.jpg

ansible部署AMP环境

同时兼容CentOS 6 与Cent OS 7系统

目录结构

tasks/main.yml

  1. 使用yum模块安装httpd、php、php-mysql

  2. 根据DBName变量安装mysql程序

  3. 根据HttpConf变量并使用模板向httpd.conf文件传递变量,同时触发重载httpd服务

  4. 启动httpd服务(省略php.ini文件的复制)

  5. 根据DBService变量启动mysql服务

  6. 根据fact变量定制每台web服务器的index.html

  7. 创建测试数据库,授权LocalIP变量,即ansible主机的变量

handlers/main.yml

vars/main.yml

templates/

  1. vi httpd-2.2.conf.j2

  1. vi httpd-2.4.conf.j2

host iventory

/etc/ansible/hosts

roles调用

ngxproxy.yml

play and check

执行playbook 

play.jpg

 
访问we1和web2 

test.jpg

 
访问测试数据库 

TEST2.jpg

ansible部署nginx反代服务器

同时兼容 CentOS 6 与 CentOS 7 系统

目录结构

tasks/main.yml

  1. 根据rpmName变量复制nginx程序包到目标主机

  2. 根据rpmName安装nginx程序包

  3. 基于模板复制nginx.conf和default.conf文件到目标主机,并触发重载nginx服务,且已经配置好upstrem server

  4. 启动nginx服务

handlers/main.yml

vars/main.yml

templates/

  1. vi default.conf.j2

  1. vi nginx.conf.j2

files/

  1. nginx-1.10.0-1.el7.ngx.x86_64.rpm

  2. nginx-1.10.2-1.el6.ngx.x86_64.rpm

host iventory

/etc/ansible/hosts

roles调用

ngxproxy.yml

play and check

执行playbook 

play.jpg

 
访问两台代理服务器均能轮询web1、web2 

test.jpg

ansible部署keepalived

同时兼容 CentOS 6 与 CentOS 7 系统,采用双主模型的keepalived配置高可用nginx代理服务器。

目录结构

tasks/main.yml

  1. 使用yum安装keepalivcd

  2. 基于模板复制keepalived.conf和notify.sh脚本到目标主机,并触发重载keepalived服务,且已经配置好了双主模型的keepalived

  3. 启动keepalived服务

handlers/main.yml

templates/

  1. vi keepalived.conf.j2

  1. vi notify.sh

host iventory

/etc/ansible/hosts

roles调用

ngxproxy.yml

play and check

执行playbook 

play.jpg

 
访问VIP1与VIP2均能轮询web1、web2 

test.jpg

合并调用roles的palybook

hosts

keneweb.yml

原创文章,作者:helloc,如若转载,请注明出处:http://www.178linux.com/58041

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1823388528@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班