Ansible应用介绍

Ansible

简介

ansible是个什么东西呢?官方的title是“Ansible is Simple IT Automation”——简单的自动化IT工具。这个工具的目标有这么几项:自动化部署APP;自动化管理配置项;自动化的持续交互;自动化的(AWS)云服务管理。所有的这几个目标从本质上来说都是在一个台或者几台服务器上,执行一系列的命令而已。通俗的说就是批量的在远程服务器上执行命令 。当然,最主要的是它是基于 paramiko 开发的。这个paramiko是什么呢?它是一个纯Python实现的ssh协议库。因此fabric和ansible还有一个共同点就是不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。简单归纳一下:

Ansible

—基于 Python paramiko 开发,分布式,无需客户端,轻量级,配置语法使用 YMAL 及 Jinja2模板语言,更强的远程命令执行操作

类似的自动化运维工具有很多常用的还有:

Puppet

—基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱

SaltStack

—基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YMAL,使得配置脚本更简单

Ansible工作机制

Ansible 在管理节点将 Ansible 模块通过 SSH 协议(或者 Kerberos、LDAP)推送到被管理端执行,执行完之后自动删除,可以使用 SVN 等来管理自定义模块及编排

ansible.png

由上面的图可以看到 Ansible 的组成由 5 个部分组成:

Ansible:            核心

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

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

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

Inventory:         定义 Ansible 管理主机的清单

Ansible安装

使用软件仓库安装

主要的Linux发行版都有自己的软件包管理系统,能帮你自动解决软件包的依赖关系。比如:

Fedora、RHEL、CentOS以及兼容的发行版:

$ sudo yum -y install ansible

Ubuntu、Debian,以及兼容发行版:

$ apt-get install ansible

注意:Fedora、RHEL、CentOS要配置epel源仓库

使用源码安装

最时尚的玩法是使用源码安装了。你会拿到最新版,但并非稳定版。所以,使用源码安装时要留意Bug,积极关注社区和版本更新。请从Github上获取最新代码,安装过程如下:

$ git clone git://github.com/ansible/ansible.git

$ cd ansible && sudo make&&make install

使用pip安装Ansible

Pip是专门用来管理Python模块的工具,Ansible会将每次正式发布都更新到pip仓库中。所以通过pip安装或更新Ansible,会比较稳妥的拿到最新稳定版。

值得注意的是升级操作系统时,并不会同时升级Ansible。另外,升级操作系统有可能损坏Ansible环境,毕竟它依赖Python。还有如果你已经基于Ansible开发大量模块,你最好一直使用对应版本。此时不建议你升级到最新版本,以免由于不兼容等问题导致模块功能异常。Pip的安装指令为:

$ pip install ansible

Ansible的升级

利用pip升级ansible

$pip install –upgrade ansible

尝试ansible

配置主机Hosts

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

vi /etc/ansible/hosts

[web]

192.168.1.100

192.168.1.101

配置免密钥登陆

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

ssh-keygen -t rsa -P ''

ssh-copy-id -i .ssh/id_rsa.pub deploy@192.168.1.100

ssh-copy-id -i .ssh/id_rsa.pub deploy@192.168.1.101

注意:在首次连接或者重装系统之后会出现检查 keys 的提示

The authenticity of host '192.168.0.5 (192.168.0.5)' can't be established.

ECDSA key fingerprint is 05:51:e5:c4:d4:66:9b:af:5b:c9:ba:e9:e6:a4:2b:fe.

Are you sure you want to continue connecting (yes/no)?

解决办法:

vim /etc/ansible/ansible.cfg 或者 ~/.ansible.cfg

[defaults]

host_key_checking = False

也可以通过设置系统环境变量来禁止这样的提示

export ANSIBLE_HOST_KEY_CHECKING=False

测试ping

ansible web -m ping

192.168.1.101 | success >> {

    "changed": false,

    "ping": "pong"

}

 

192.168.1.100 | success >> {

    "changed": false,

    "ping": "pong"

}

Ansible命令参数介绍

-v,–verbose                                   详细模式,如果命令执行成功,输出详细的结果(-vv –vvv -vvvv)

  -i PATH,–inventory=PATH                       指定host文件的路径,默认是在/etc/ansible/hosts

  -f NUM,–forks=NUM                             NUM是指定一个整数,默认是5,指定fork开启同步进程的个数。

  -m NAME,–module-name=NAME                     指定使用的module名称,默认是command

  -m DIRECTORY,–module-path=DIRECTORY           指定module的目录来加载module,默认是/usr/share/ansible,

  -a,MODULE_ARGS                                 指定module模块的参数

  -k,–ask-pass                                  提示输入ssh的密码,而不是使用基于ssh的密钥认证

  –sudo                                         指定使用sudo获得root权限

  -K,–ask-sudo-pass                             提示输入sudo密码,与–sudo一起使用

  -u USERNAME,–user=USERNAME                    指定移动端的执行用户

  -C,–check                                     测试此命令执行会改变什么内容,不会真正的去执行

主机清单Hosts介绍

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

/etc/ansible/hosts 主机清单配置格式如下

[dbservers]                                                     []表示主机的分组名,可以按照功能、系统等进行分类,便于对某些主机或者某一组功能相同的主机进行操作

192.168.1.12

one.example.com

badwolf.example.com:5309                                        支持指定 SSH 端口 5309

jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50     设置主机别名为 jumper

www[01:50].example.com                                         支持通配符匹配 www01 www02 …www50

[databases]

db-[a:f].example.com                                             支持字母匹配 a b c…f

为某主机指定连接类型和连接用户

[zhao]

Localhost  ansible_connection=local

other1.example.com ansible_connection=ssh ansible_ssh_user=deploy

other2.example.com ansible_connection=ssh ansible_ssh_user=deploy

hosts 文件支持一些特定指令,上面已经使用了其中几个,所有支持的指令如下:

ansible_ssh_host                       指定主机别名对应的真实 IP,如:100 ansible_ssh_host=192.168.1.100,随后连接该主机无须指定完整 IP,只需指定 251 就行

ansible_ssh_port                       指定连接到这个主机的 ssh 端口,默认 22

ansible_ssh_user                       连接到该主机的 ssh 用户

ansible_ssh_pass                       连接到该主机的 ssh 密码(连-k 选项都省了),安全考虑还是建议使用私钥或在命令行指定-k 选项输入

ansible_sudo_pass                      sudo 密码

ansible_sudo_exe                       sudo 命令路径

ansible_connection                     连接类型,可以是 localssh paramikoansible1.2 之前默认为 paramiko

ansible_ssh_private_key_file           私钥文件路径

ansible_shell_type                     目标系统的 shell 类型,默认为 sh,如果设置 csh/fish,那么命令需要遵循它们语法

ansible_python_interpreter             python 解释器路径,默认是/usr/bin/python,但是如要要连*BSD系统的话,就需要该指令修改 python 路径

ansible_*_interpreter                  这里的"*"可以是 ruby perl 或其他语言的解释器,作用和 ansible_python_interpreter 类似

清单通配模式介绍

在Ansible中,清单一位着要管理哪些机器,在playbook中,意味着哪些主机需要应用特定的配置或者过程。

比如我们的主机列表配置为:

192.168.1.10

[web]

192.168.1.100

192.168.1.101

[db]

192.168.1.102

 

ansible web -m yum -a "name=nginx state=present"

模式通常用主机组来表示,上面的命令就代表web组的所有主机

简单介绍一下其他的匹配方式:

通配所有主机

all

*

通配具有规则特征的主机或者主机名

one.example.com

*.example.com

192.168.1.100

192.168.1.*

通配两个组的所有主机,组名之间通过冒号隔开,表示OR的意思

web

web:db

非模式匹配:表示在 web组不在db组的主机

web:!db

交集匹配:表示同时都在 web 和db组的主机

web:&db

匹配一个组的特定编号的主机(先后顺序 0 到…)

匹配 web组的第 1 个主机

web[0]

匹配 web组的第 1 个到第 25 个主机

web [0-25]                                                  官网文档是”:”表示范围,测试发现应该使用”,注意不要和匹配多个主机组混淆

组合匹配:在 web或者 db组中,必须还存在于test1组中,但是不在test2组中

web:db:&test1:!test2

ansible几个常用模块介绍

shell模块

默认情况下,ansible使用的module 是 command,这个模块并不支持 shell 变量和管道等,若想使用shell 来执行模块,请使用-m 参数指定 shell 模块,但是值得注意的是普通的命令执行模块是通过python的ssh执行。

使用shell模块在远程主机上执行命令:

ansible web -m shell -a ‘echo $TERM’

raw模块

Raw也是命令执行模块,而raw模块则是直接用ssh模块进行执行,通常用在客户机还没有python的环境的时候。

使用raw模块在远程主机上执行命令:

ansible web -m raw -a ‘echo $TERM’

copy模块

实现主控端向目标主机拷贝文件,类似于scp的功能

拷贝本地的/etc/hosts 文件到 web主机组所有主机的/tmp/hosts(空目录除外)

ansible web -m copy -a "src=/etc/hosts dest=/tmp/hosts"

file模块

file模块称之为文件属性模块,可以做的操作如下:

使用 file 模块创建文件

ansible web -m file -a "dest=/tmp/zhao/a.txt state=touch"

file 模块允许更改文件的用户及权限

ansible web -m file -a "dest=/tmp/zhao/a.txt mode=600"

ansible web -m file -a "dest=/tmp/zhao/b.txt mode=600 owner=deploy group=root"

使用 file 模块创建目录,类似 mkdir -p

ansible web -m file -a "dest=/tmp/yong mode=755 owner=deploy group=sa state=directory"

使用 file 模块删除文件或者目录

ansible web -m file -a "dest=/tmp/yong state=absent"

注:state的其他选项:link(链接)hard(硬链接)

template模块

根据官方的翻译是:template使用了Jinjia2格式作为文件模板,进行文档内变量的替换的模块。他的每次使用都会被ansible标记为changed状态。

stat模块

获取远程文件状态信息,包含atime、ctime、mtime、md5、uid、gid等

ansible web -m stat -a "path=/tmp/zhao/a.txt"

管理软件模块

apt、yum模块分别用于管理ubuntu系列和redhat系列系统软件包

安装nginx软件包

ansible web -m yum -a "name=nginx state=present"

ansible web -m apt -a "name=nginx state=present"

安装包到一个特定的版本

ansible web -m yum -a "name=nginx-1.6.2 state=present"

ansible web -m apt -a "name=nginx-1.6.2 state=present"

指定某个源仓库安装某软件包

ansible web -m yum -a "name=php55w enablerepo= remi state=present"

更新一个软件包是最新版本

ansible web -m yum -a "name=nginx state=latest"

ansible web -m apt -a "name=nginx state=latest"

卸载一个软件

ansible web -m yum -a "name=nginx state=absent"

ansible web –m apt -a "name=nginx state=absent"

Ansible 支持很多操作系统的软件包管理,使用时 -m 指定相应的软件包管理工具模块,如果没有这样的模块,可以自己定义类似的模块或者使用 command 模块来安装软件包。

User模块

使用 user 模块对于创建新用户和更改、删除已存在用户非常方便

创建一个zhao用户并更新密码(密码必须为加密过的字符串)

ansible all -m user -a "name=zhao password= $6$YyF5qLN8$edF1l.d/xcd9kv4ZQD/VVq5g2Uavlwoo/l.W4YVIQgsNghN4CbJKSEdZ5ihxztkYJ.bZV2PCP6MnGOioSLqUK."

删除zhao用户

ansible all -m user -a "name=zhao state=absent"

service模块

启动web 组所有主机的 httpd服务

ansible web -m service -a "name=httpd state=started"

重启 web 组所有主机的 httpd服务

ansible web -m service -a "name=httpd state=restarted"

关闭web组所有主机的 httpd服务

ansible web -m service -a "name=httpd state=stopped"

playbook解析

Playbooks 是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。基本的YMAL语法请参考http://docs.ansible.com/YAMLSyntax.html

Playbook组成

Target section               定义将要执行 playbook 的远程主机组

Variable section             定义 playbook 运行时需要使用的变量

Task section                定义将要在远程主机上执行的任务列表

Handler section             定义 task 执行完成以后需要调用的任务

 

通过下面这个例子我们来简单了解一下:

– hosts: web

vars:

worker_processes: 4

max_open_file: 65535

remote_user: deploy

tasks:

– name: ensure nginx is at the latest version

yum: pkg=nginx state=latest

– name: write the nginx config file

template: src=/data/ansible/template/nginx.j2 dest=/etc/nginx.conf

notify:

– restart nginx

– name: ensure nginx is running

service: name=nginx state=started

handlers:

– name: restart nginx

service: name=nginx state=restarted

主机和用户

在playbook中的每一个play都可以选择在哪些机器和以什么用户完成,hosts一行可以是一个主机组或者主机或者主机也可以是多个,中间以冒号分隔,可以参考前面提到的清单通配模式:其中remote_user表示执行的用户账号

– hosts: web

remote_user: root

每个任务都可以定义自己的用户

– hosts: web

remote_user: root

tasks:

– name: test connection

ping:

remote_user: yourname

在 playbook中使用sudo

– hosts: web

remote_user: yourname

sudo: yes

在一个任务中使用sudo

– hosts: web

remote_user: yourname

tasks:

– service: name=nginx state=started

sudo: yes

登陆后 sudo 到其他用户执行

– hosts: web

remote_user: yourname

sudo: yes

sudo_user: postgres

注释:在使用 sudo_user 切换到非 root 用户时,Ansible 会将模块参数(非密码选项参数)记录到/tmp 下的一个临时随机文件,命令执行完后会删除;当 sudo 到 root 或者普通用户登陆时并不记录

任务列表

所有定义的任务列表(tasks list),playbook将按照定义的配置文件自上而下的顺序执行,定义的主机都将得到相同的任务,但是执行的返回结果不一定保存一致,取决于主机的环境及程序包状态。建议每个任务事件都要定义一个name标签,好处是增强可读性,也便于观察结果输出时了解运行的位置。下面就一service模块为例来定义一个任务,service: key=value参数,具体请参考模块的详细介绍

tasks:

– name: ensure nginx is running

service: name=nginx state=started

command 和 shell 模块不需要增加 key

tasks:

– name: disable selinux

command: setenforce 0

command和shell模块关注命令或者脚本执行后返回值,如果命令成功执行返回结果不是0的情况下可以使用以下方法:

tasks:

– name: disable selinux

command: setenforce 0

     ignore_errors: True

如果在任务中参数过长可以回车使用空格缩进

tasks:

– name: Copy ansible inventory file to client

copy: src=/etc/ansible/hosts dest=/tmp/hosts

owner=root group=root mode=0644

变量的使用

如何创建一个有效的变量名

变量名应该由字母、数组和下划线组成,以字母开头。例如:foo_port、foo5 就是很好的变量名,而 foo-port、foo port、foo.port、12 都是无效的变量名

在 在 playbook  中如何定义变量

– hosts: webservers

vars:

http_port: 80

变量这一块就不多提了,针对这一块了解甚微,如有需要请自行查找,这里简单介绍一下jinja2过滤器中的register关键字,register关键字的作用是将命令执行的结果保存为变量,结果会因为模块不同而不同,在运行ansible-playbook时增加-v参数就可以看到results可能的值。比如:

– hosts: local

  remote_user: root

  tasks:

    – name: Get server Time

      shell: date +%Y-%m-%d_%H_%M

      register: Time

      ignore_errors: True

    – name: Create a file

      shell: touch /tmp/zhao{{Time.stdout}}.txt

执行结果如下:

$ ansible-playbook 2.yml -v

 

PLAY [local] ******************************************************************

 

GATHERING FACTS ***************************************************************

ok: [192.168.1.52]

 

TASK: [Get server Time] *******************************************************

changed: [192.168.1.52] => {"changed": true, "cmd": "date +%Y-%m-%d_%H_%M", "delta": "0:00:00.002363", "end": "2015-06-19 11:06:12.359652", "rc": 0, "start": "2015-06-19 11:06:12.357289", "stderr": "", "stdout": "2015-06-19_11_06", "warnings": []}

 

TASK: [Create a file] *********************************************************

changed: [192.168.1.52] => {"changed": true, "cmd": "touch /tmp/zhao2015-06-19_11_06.txt", "delta": "0:00:00.002386", "end": "2015-06-19 11:06:12.631204", "rc": 0, "start": "2015-06-19 11:06:12.628818", "stderr": "", "stdout": "", "warnings": ["Consider using file module with state=touch rather than running touch"]}

 

PLAY RECAP ********************************************************************

192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0  

通过上面这个例子我们可以看到task的执行输出和facts一样的,我们可以通过jinja2模板获取变量值:{{Time.stdout}}{{Time.cmd}}等等

NotifyHandles

用于当关注的资源发生变化时采取一定的操作。

“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

角色定义使用

Roles在Ansible1.2+版本中所被支持,主要是为了更好的组织playbooks。

举例说明:

site.yml

webservers.yml

fooservers.yml

roles/

common/

files/

templates/

tasks/

handlers/

vars/

defaults/

meta/

webservers/

files/

templates/

tasks/

handlers/

vars/

defaults/

meta/

在 playbook 中可以这样使用 roles

– hosts: webservers

roles:

– common

– webservers

roles 目录结构说明:

taskshandlersvars(只对当前 role 有效)、meta(定义 role 间的直接依赖关系)目录内存在

main.yml 文件时会将对应的任务、处理、变量和 meta 添加到 play

files 存放文件,ansible 默认会从这里找文件,对应 task 里面的 copyscript 模块

template 存放模板,对应 task 里面的 template 模块

tasks 存放任务,include 默认读取这里的任务

defaults 默认的变量存放位置,使用/devaults/main.yml,相对其他参数变量设置的优先级最低

注释:Ansible1.4+以后的版本,可以通过 roles_path 参数配置 roles 路径,多路径使用冒号分隔,可以将常见角色集中存放,指定 roles 路径,这样多个 playbook 可以共用

运行Playbook

查看模块执行成功与否的详细信息

$ansible-playbook playbook.yml –v

查看一个 playbook 中都会对哪些主机产生影响

$ansible-playbook playbook.yml –list-hosts

查看都有哪些任务要执行

$ansible-playbook playbook.yml –list-tasks

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

(1)
ZhaoYongZhaoYong
上一篇 2015-07-03
下一篇 2015-07-03

相关推荐

  • N28第五周

    1、简述rpm与yum命令的常见选项,并举例
    2、自建yum仓库,分别为网络源和本地源
    3、简述at和crontab命令,制定 每周三凌晨三、五点10分执行某个脚本,输出当前时间,时间格式为 2017-12-28 10:00:00
    4、简述sed常用操作命令,并举例

    Linux干货 2018-01-03
  • 磁盘和文件系统管理述

        我们知道一块磁盘是可以被分区成多个分区的(partition),以Windows的观点来看,你可能会有一颗磁盘并且将他分区成为C:, D:, E:盘,那个C, D,E就是分区。Linux的设备都是以文件的型态存在,磁盘设备接口的不同也早就了磁盘文件名的不同。即IDE接口的磁盘设备文件名都是/dev/hd[a-z…

    Linux干货 2016-08-29
  • linux获取”命令帮助“

    一、相关术语:         外部命令:一个可执行程序,位于文件系统某目录下;是系统为了完善各种功能而加入的程序。         内部命令:系统shell程序的部分程序。内部命令执行速度非常快,其…

    Linux干货 2016-06-09
  • 马哥教育网络班20期+第3周课程练习

     1、列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。 法一: who | cut -d ‘ ‘ -f 1 | tail -u 法二: who | cut -d ’’-f&…

    Linux干货 2016-06-26
  • 文件查找命令find

      在文件系统上常常需要根据文件的各种属性去查找符合条件的文件。在Linux下也有相当优异的查找命令。今天只要将find和locate。find通常不常用,因为速度慢!通常我们先使用locate来进行模糊查找,如果真找不到了,才以find来查找。为什么呢?因为locate是利用数据库来查找数据,所以速度非常快,而且并没有实际查询硬盘比较省时间。 l…

    Linux干货 2016-08-22
  • Linux终端类型

    Linux系统的终端主要包括控制台终端、控制终端、串口终端、伪终端、虚拟终端。 1、控制台终端(/dev/console)    在Unix系统中,计算机显示器通常被称为控制台终端。Console与虚拟终端相关联,内核将信息送到控制台终端上(/dev/console), 通过与console相关联的虚拟终端将信息显示到屏幕上。不管当前正在…

    Linux干货 2016-10-19