ansible自动化运维工具

Ansible
ansible架构图

(一)架构

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&section=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
                ...
Inventory参数
    (5) 在角色调用时传递
        roles:
        - { role: ROLE_NAME, var: value, ...}               
变量调用,如下图中的playbook文件中定义:
    {{ var_name }}
ansible-playbook -e pkgname=httpd PB.yaml即可传递变量到playbook文件中

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;

Paste_Image.png

一个完整的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都是内置变量,可用下图方式获得
ansible内置变量
  - 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的文件,用于设定默认变量

下面截图部分为使用角色的一个小实例:


创建角色相关目录
nginx/tasks/main.yml
编辑nginx/handlers/main.yml
将本地nginx主配置文件编辑后放在模板目录中
nginx/templates/nginx.conf.j2
将本地nginx的默认配置文件放入到角色模板目录
nginx/templates/default.conf.j2
nginx/vars/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对其拥有所有权限;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容