HOME
BLOG
TIME
FRIENDS
SAY TO ME
MOOD
TRAVELING
自动化运维第一步——Ansible 使用教程
2020/08/16 6.9k 29 分钟 点击

Ansible是一种非常优秀的自动化运维工具,基于SSH协议开发的,并且更适合模块化工作,Ansible是一种集成IT系统的配置管理、应用部署、执行特定任务的开源平台,它是基于python,Agentless语言,由Paramiko和PyYAML两个关键模块构建。集合了众多运维工具的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。Ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是Ansible所运行的模块,Ansible只是提供一种框架。Ansible不需要在远程主机上安装代理工具,因为它们是基于SSH来和远程主机通讯的。这也与Saltstack有所不同,但是Saltstack的执行效率更高,不过需要部署代理agent。
Ansible适用于在中小型企业中使用,而对于更大型,重型的环境,Puppet更适合。

Ansible特性

  • 模块化:调用特定的模块,完成特定任务
  • 有Paramiko , PyYAML ,jinja2 (模板语言)三个关键模块
  • 支持自定义模块
  • 基于Python语言实现
  • 部署简单,基于python和SSH(默认已安装),agentless
  • 安全,基于OpenSSH
  • 支持playbook编排任务
  • 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
  • 无需代理不依赖PKI (无需ssl )
  • 可使用任何编程语言写模块
  • YAML格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案

    Ansible主要组成部分

  • ANSIBLE PLAYBOOKS :任务剧本(任务集),编排定义Ansible任务集的配置文件,甶Ansible顺序依次执行,通常是JSON格式的YML文件
  • INVENTORY : Ansible管理主机的清单 /etc/ansible/hosts
  • MODULES : Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
  • PlUGINS :模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插 件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口
  • ANSIBLE :组合INVENTORY、API、MODULES、PUJGINS的绿框,可以理解 为是ansible命令工具,其为核心执行工具

Ansible命令执行来源:

  • USER ,普通用户,即SYSTEM ADMINISTRATOR

  • CMDB (配置管理数据库)API调用

  • PUBLIC/PRIVATE CLOUD API调用

  • USER-> Ansible Playbook -> Ansibile

    利用Ansible实现管理的方式:

  • Ad-Hoc即ansible命令,主要用于临时命令使用场景

  • Ansible-playbook主要用于长期规划好的,大型项目的场景,需要有前提的规划

Ansible-playbook (剧本)执行过程:

  • 将已有编排好的任务集写入Ansible-Playbook
  • 通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行

Ansible主要操作对象:

  • HOSTS主机
  • NETWORKING网络设备

Ansible注意事项

  • 执行ansible的主机一般称为主控端,中控,master或堡垒机
  • 主控端Python版本需要2.6或以上
  • 被控端Python版本小于2.4,需要安装python-simplejson
  • 被控端如开启SELinux需要安装libselinux-python
  • windows不能做为主控端

Ansible的安装

rpm包安装:EPEL源
yum install ansible

编译安装:
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir/etc/ansible
cp -r examples/* /etc/ansible

GitHub方式:
git clone git://github.com/ansible/^nsible.git –recursive
cd ./ansible
source ./hacking/env-setup

pip安装:pip是安装Python包的管理器,类似yum
yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install —upgrade pip
pip install ansible —upgrade

确认安装: ansible –version

Ansible相关文件

  • 配置文件
    /etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性
    /etc/ansible/hosts 主机清单
    /etc/ansible/roles/存放角色的目录
  • 程序
    /usr/bin/ansible主程序,临时命令执行工具
    /usr/bin/ansible-doc查看配置文档,模块功能查看工具
    /usr/bin/ansible-galaxy下载/上传优秀代码或Roles模块的官网平台
    /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
    /usr/bin/ansible-pull 远程执行命令的工具
    /usr/bin/ansible-vault 文件加密工具
    /usr/bin/ansible-console基于Console界面与用户交互的执行工具

主机清单inventory

  • Inventory主机清单
    ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名
  • 默认的inventory file为/etc/ansible/hosts
  • inventory file可以有多个,且也可以通过Dynamic inventory来动态生成

/etc/ansible/hosts文件的格式

  • inventory文件遵循INI文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明
    示例:
    ntp.yangyang.host
    [webservers]
    www1.yangyang.host:2222
    www2.yangyang.host
    [dbservers]
    dbl.yangyang.host
    db2.yangyang.host
    db3.yangyang.host
    • 如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机
      示例:
      [websrvs]
      www[01:100].yangyang.com
      [dbsrvs]
      db-[a:f].yangyang.com

Ansible配置文件

  • Ansible 配置文件 /etc/ansible/ansible.cfg (―般保持默认)
  • [defaults]
    inventory = /etc/ansible/hosts # 主机列表配置文件
    #library = /usr/share/my_modules/ # 库文件存放目录
    #remoteJ:mp = $H〇ME/.ansible/tmp #临时py命令文件存放在远程主机目录
    #local_tmp = $H〇ME/.ansible/tmp # i机的临时命令执行目录
    #forks =5 #默认并发数
    #sudo_user = root # 默认sudo 用户
    #askjudo_pass = True #每次执行ansible命令是否询问ssh密码
    #ask_pass = True
    #remote_port =22
    #host_key_checking = False #检查对应服务器的host_key ,建议取消注释
    #log_path=/var/log/ansible.log #日志文件

Ansible系列命令

  • ansible
  • ansible-doc
    • ansible-playbook
    • ansible-vault
  • ansible-console
  • ansible-galaxy
  • ansible-pull

ansible-doc:显示模块帮助
ansible-doc [options] [module]
-a: 显示所有模块的文档
-l,-list: 列出可用模块
-s,–snippet显示指定模块的 playbook片段
示例
ansible-doc-列出所有模块
ansible- doc ping查看指定模块帮助用法
ansible-doc - s ping查看指定模块帮助用法

ansible通过ssh实现配置管理、应用部署、任务执行等功能,建议配置 ansible端能基于密钥认证的方式联系各被管理节点
ansible [-m module_name ][-a args ]
-version显示版本
-m module指定模块,默认为 command
-v 详细过程,vvv更详细
-list-hosts 显示主机列表,可简写-|ist
-k,-ask-pass 提示输入ssh连接密码,默认Key验证
-K,-ask-become-pass 提示输入sudo时的口令
-C,-check 检查,并不执行
-T,- timeout=TIMEOUT 执行命令的超时时间,默认105
-u,–user= REMOTE_USER 执行远程执行的用户
-b,–become 代替旧版的sudo切换

Ansible的 Host-pattern

  • ansible的Host- pattern 匹配主机的列表
    all: 表示所有 Inventory中的所有主机
    ansible all -m ping
  • *: 通配符
    ansible “*“ -m ping
    ansible 192.168.1.-m ping
    ansible “\
    srvs”- m ping
  • 或关系
    ansible “websrvs: appsrvs”-m ping
    ansible “1921681.10:192.1681.20” m ping
  • 逻辑与
    ansible “websrvs: &dbsrvs”-m ping
    在 websrvs组并且在 dbsrvs组中的主机
  • 逻辑非
    ansible ‘websrvs:!dbsrvs’ -m ping
    在 websrvs组,但不在 dbsrvs组中的主机
    注意:此处为单引号,因为有!
  • 综合逻辑
    ansible ‘websrvs:dbsrvs:&appsrvs:!ftpsrvs’ -m ping
  • 正则表达式
    ansible “websrvs: &dbsrvs”-m ping
    ansible “~(web|db).*.yangyang.host” -m ping

Ansible命令执行过程

  • 1.加载自己的配置文件默认/etc/ansible/ansible.cfg
  • 2.加载自己对应的模块文件,如command
  • 3.通过 ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ ansible-tmp-数字/xxx.PY文件
  • 4给文件+x执行权限
  • 5.执行并返回结果
  • 6.删除临时py文件, sleep o退出

执行状态

  • 绿色:执行成功并且不需要做改变的操作
    • 黄色:执行成功并且对目标主机做变更
    • 红色:执行失败

Ansible使用示例

示例:
以yang用户执行ping存活检测
ansible all -m ping -u yang -k
以yang sudo至root执行ping存活检测
ansible all -m ping -u yang -b -k
以yang sudo至pp用户执行ping存活检测
ansible all -m ping -u yang -b -k –become-user pp
以yang sudo至root用户执行
ansible all -m command -u yang -become-user=root -a ‘ls /root’-b -k -K

Ansible常用模块

  • Command: 在远程主机执行命令,默认模块,可忽略-m选项
    • ansible srvs -m command -a ‘service vsftpd start’
    • ansible srvs -m command -a ‘echo 123 | passwd –stdin yang’ 不成功
      • 此命令不支持 $VARNAME < > | ; &等操作符,如果用到需要用shell模块实现
  • Shell: 和command相似,用shell执行命令
    • ansible srv -m shell -a ‘echo 123 I passwd –stdin yang’
    • 调用bash执行命令类似 cat/tmp/stanley.md I awk -F ‘|’ ‘{print $1,$2}’ &> /tmp/ example.txt 这些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器
  • script: 运行脚本
    • -a “/PATH/TO/SCRIPT_FILE”
    • sensible websrvs -m script -a f1.sh
  • copy: 从服务器复制文件到客户端
    • ansible srv -m copy -a “src=/root/f1.sh dest=/tmp/f2.sh owner=yang mode=600 backup=yes”
      如目标存在,默认覆盖,此处指定先备份
    • ansible srv -m copy -a “content=test content\n’ dest=/tmp/f1.txt”利用内容,直接生成目标文件
  • fetch: 从客户端取文件至服务器端,copy相反,目录可先tar
    • ansible srv -m fetch -a ‘src=/root/a.sh dest=/data/scripts’
  • file: 设置文件属性
    • ansible srv -m file -a “path=/root/1.sh owner=yang mode=755”
    • ansible web -m file -a “src=/app/testfile dest=/app/testfile-link state=link”
  • hostname: 管理主机名
    • ansible node1 -m hostname -a “name=websrvs”
  • cron: 计划任务
    支持时间: minute,hour,day,month,weekday
    • ansible srv -m cron -a “minute=*/5 job=/usr/ sbin/ntpdate 172.16.0. 1 &>/dev/null name= Synctime” 创建任务
      • ansible srv -m cron -a ‘state=absent name= Synctime’ 删除任务
  • yum: 管理包
    • ansible srv -m yum -a ‘name=httpd state=latest’ 安装
    • ansible srv -m yum -a ‘name=httpd state=absent’ 删除
  • service: 管理服务
    • ansible srv -m service -a ‘name=httpd state=stopped’
      • ansible srv -m service -a ‘name=httpd state=started’
      • ansible srv -m service -a ‘name=httpd state=reloaded’
      • ansible srv -m service -a ‘name=httpd state=restarted’
  • user: 管理用户
    • ansible srv -m user -a ‘name=user1 comment=”test user” uid=2048 home=/app/userl group=root’
      • ansible srv -m user -a’name=sysuserl system=yes home=/app/sysuser1’
      • ansible sry -m user -a ‘ name= user1 state= absent remove=yes’ 删除用户及家目录等数据
  • group: 管理组
    • ansible srv -m group -a” name=testgroup system=yes”
      • ansible srv -m group -a “name=testgroup state=absent”

        Ansible系列命令

  • ansible-galaxy
    连接htts://galaxy.ansible.com下载相应的roles
    • 列出所有已安装的 galaxy
      ansible-galaxy list
    • 安装 galaxy
      ansible-galaxy install geerlingguy redis
    • 删除 galaxy
      ansible-galaxy remove geerlingguy redIs
  • ansible-pull
    推送命令至远程,效率无限提升,对运维要求较高
  • ansible-playbook
    ansible-playbook hello.yml 这便是剧本

Test yaml

  • hosts: websvrs
    remote_user: root

    tasks:

    • name: hello
      command: hostname
      ==需要注意 yaml语法格式对缩进要求严格,必须统一对其,空格和Tab不难混用==
  • ansible-vault
    功能:管理加密解密ym文件
    • ansible-vault [create|decrypt|edit|encrypt|rekey|view]
    • ansible-vault encrypt hello.yml加密
    • ansible-vault decrypt hello.yml解密
    • ansible-vault view hello.yml查看
    • ansible-vault edit hello.yml编辑加密文件
    • ansible-vault rekey hello. yml修改口令
    • ansible-vault create new.yml创建新文件
  • ansible-console:
    2.0+新增,可交互执行命令,支持tab
    root@test (2) [f:10] $
    含义:
    执行用户@当前操作的主机组 (当前组的主机数量) [f:并发数] $
  • 设置并发数: forks n 例如: forks 10
  • 切换组:cd主机组例如: cd web
  • 列出当前组主机列表: list
  • 列出所有的内置命令: ?或help
  • 示例
    root@all (2) [f:5] $ list
    root@all (2) [f:5] $ cd appsrvs
    root@appsrvs (2) [f: 5] $ list
    root@appsrvs (2) [f:5] $ yum name=httpd state=present
    root@appsrvs (2) [f:5] $ service name=httpd state=started

Ansible之Playbook

  • playbook是由一个或多个”play”组成的列表
  • play的主要功能在于将事先归并为一组的主机装扮成事先通过 ansible中的task 定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。
    将多个pay组织在一个playboyαk中,即可以让它们联同起来按事先编排的机制,同唱一台大戏
  • Playbook采用YAML语言编写

YAML介绍

  • YAML是一个可读性高的用来表达资料序列的格式。
  • YAML参考了其他多种语言,包括:XML、
    C语言、 Python、Per以及电子邮件格式RFC2822等。 Clark Evans在2001年在首次发表了这种语言,另外 Ingy dot 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语法简介

  • 在单一档案中,可用连续三个连字号(——)区分多个档案。另外,还有选择性的连续三个点号(…)用来表示档案结尾

  • 次行开始正常写 Playbook的内容,一般建议写明该 Playbook的功能

  • 使用#号注释代码

  • 缩进必须是统一的,不能空格和tab混用

  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的

  • YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感

  • k/V的值可同行写也可换行写。同行使用:分隔

  • v可是个字符串,也可是另一个列表

  • 一个完整的代码块功能需最少元素需包括name:task

  • 一个name只能包括一个task

  • YAML文件扩展名通常为yml或yaml

  • list:列表,其所有元素均使用“-”打头
    示例

# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
  • dictionary:字典,通常由多个key与vaue构成
    示例
---
An employee record
name: Example Developer
job: Developer
skill: Elite

也可以将 key:value放置于{}中进行表示,用分隔多个 key:value
示例

---
# An employee record
`{% raw %}{name: Example Developer, job: Developer, skil Elite}{% raw %}
```

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

```yaml
name: John Smith
age: 41
gender: Male
spouse:
    name: Jane Smith
    age: 37
    gender: Female
children:
   - name: Jimmy Smith
     age: 17
     gender: Male
   - name: Jenny Smith
     age: 13
     gender: Female
```


## Playbook核心元素

* Hosts执行的远程主机列表
* Tasks任务集
* Variables内置变量或自定义变量在 playbook中调用
* Templates模板,可替换模板文件中的变量并实现-些简单逻辑的文件
* Handlers和notify结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
* tags标签指定某条任务执行,用于选择运行 playbook中的部分代码。 ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
ansible-playbook -t tagsname useradd.yml

## playbook基础组件

* Hosts
   * playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。 hosts用于指定要执行指定任务的主机,须事先定义在主机清单中
  * 可以是如下形式
one.yangyang.host
one.yangyang.host:two.yangyang.host
192.168.1.50
192.168.1.*
   * websrys:dbsrys两个组的并集
   * websrys:&dbsrys两个组的交集
   * webservers:!phoeni在 websrvss组,但不在 dbsrys组
    示例 -hosts: websrys: dbsrys
* remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于pay全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户

```yaml
- hosts: websrvs
  remote_user: root

  tasks:
  - name: test connection
    ping:
    remote_user: yang
    sudo: yes      #默认sudo为root
    sudo_user: pp   #sudo为pp
```

* task列表和action
    * play的主体部分是 task list. task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而下某 playbook时,如果中途发生错误,所有已执行任务都将回滚,因此在更正 playbook后重新执行一次即可
    * task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
    * 每个task都应该有其name,用于 playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供ηame,则 action的结果将用于输出

* tasks:任务列表
    * 格式:
      (1)action: module arguments
      (2)module: arguments   建议使用
==注意:shell和command模块后面跟命令,而非key=vaue==
    * 某任务的状态在运行后为 changed时,可通过"notify"通知给相应的handlers
    * 任务可以通过"tags"打标签,而后可在 ansible-playbook命令上使用-t指定进行调用
示例:

```yaml
tasks:
  - name: disable selinux
    command: /sbin/setenforce 0
```
   * 如果命令或脚本的退出码不为零,可以使用如下方式替代

```yaml
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand /bin/true
```

* 或者使用 ignore_errors来忽略错误信息: 

```yaml
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True
```

## 运行Playbook
* 运行 playbook的方式
ansible-playbook ...[options]
* 常见选项
-\-check 只检测可能会发生的改变,但不真正执行操作
-\-list-hosts 列出运行任务的主机
-\-Iimit 主机列表只针对主机列表中的主机执行
-v 显示过程vvv更详细
* 示例
ansible-playbook file.yml --check只检测
ansible-playbook file yml
ansible-playbook file yml --limit websrvs

## Playbook VS ShellScripts
SHELL脚本

```powershell
#! /bin/bash
#安装 Apache
yum install --quiet -y httpd
#复制配置文件
cp/tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
#启动 Apache,并设置开机启动
service httpd start
chkconfig httpd on
```
Playbook定义

```yaml
---
- hosts: all
  remote_user: root
  tasks:
    - name: "安装 Apache"
      yum: name=httpd
    - name: "复制配置文件"
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
    - name: "复制配置文件"
      copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.cd/
    - name: "启动 Apache,并设置开机启动"
      service: name=httpd state=started enabled=yes
```

## Playbook:示例
示例: httpd.yml

```yaml
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name: install httpd package
      yum: name=httpd
      tags: inhttpd
    - name: copy configure
      copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
      notify: restart service
    - name: start service
      service: name=httpd state=started enabled=yes
      tags: rshttpd

  handlers:
    - name: restart service
      service: name=httpd state=restarted
```
## Handlers和notify结合使用触发条件
* handlers
是task列表,这些task与前述的task并没有本质上的不同用于当关注的资源发生变化时,才会采取一定的操作
* notify此action可用于在每个pay的最后被触发,这样可避免多次有改变发生时毎次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为 handler,也即 notify中调用 handler中定义的操作

## Playbook中tags使用
示例:httpd.yml
```yaml
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name: install httpd package
      yum: name=httpd
      tags: inhttpd
    - name: copy configure
      copy: src=files/httpd.conf dest=/etc/httpd/conf/ backup=yes
      notify: restart service
    - name: start service
      service: name=httpd state=started enabled=yes
      tags: rshttpd

  handlers:
    - name: restart service
      service: name=httpd state=restarted
```
## Playbook中变量使用
* 变量名:仅能由字母、数字和下划线组成,且只能以字母开头
* 变量来源
    * 1.ansible setup facts远程主机的所有变量都可直接调用
    * 2.在/etc/ansible/hosts中定义
         * 普通变量:主机组中主机单独定义,优先级高于公共变量
        * 公共(组)变量:针对主机组中所有主机定义统一变量
例子:
[websrvs]
192.168.218.101 nginx_port=8080
192.168.218.102 nginx_port=9090
    * 3.通过命令行指定变量,优先级最高
ansible-playbook -e varname=value
    * 4.在playbook中定义
           vars
    * 5.在role中定义
           例子
```yaml
var1: value1
var2: value2
```

* 变量命名
变量名仅能由字母、数字和下划线组成,且只能以字母开头
* 变量定义:key=value
示例:httpd_port=80
* 变量调用方式
通过{% raw %}{{ variable name }}{% endraw %} 调用变量,且变量名前后必须有空格,有时用{% raw %}{{ variable name }}{% endraw %}才生效
ansible-playbook -e 选项指定
ansible-playbook test.yml -e hosts=www user=yang

## 使用Setup变量
这是一个可以显示系统信息的变量
例子:

```yaml
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name: create log file
      file: name=/data/{% raw %}{{ ansible_fqdn }}{% endraw %}.log state=touch mode=600 owner=yang

同时他也是一个模块,可以使用ansible-doc setup来查看使用方法

模板Templates

  • 文本文件,嵌套有脚本(使用模板编程语言编写)

  • Jinja2语言,使用字面量,有下面形式
    字符串:使用单引号或双引号
    数字:整数,浮点数
    列表:[item1,item2,
    元组:(tem1,item2,
    字典:{key1 value1,key2 value2,}
    布尔型:true/ false

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

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

  • 逻辑运算:and,or,not

  • 流表达式: for if when

  • templates功能:根据模块文件动态生成对应的配置文件

    • templates文件必须存放于templates目录下,且命名为.j2结尾
    • yaml/yml文件需和templates目录平级,目录结构如下
      .
      ├── templates
      │ ├── for1.conf.j2
      │ ├── for2.conf.j2
      │ ├── for3.conf.j2
      │ ├── if.conf.j2
      │ └── nginx.conf.j2
      ├── testfor.yml

      Playbook中template变更替换

  • 修改文件 nginx.conf j2下面行为
    worker_processes {{ ansible_processor_vcpus }}

  • cat temnginx2.yml

---
- hosts: websrvs
  remote_user: root
  vers:
    - nginx_port: 88
  tasks:
    - name: install wget
      yum: name=wget
    - name: install aliyun.epel.repo
      shell: "wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo"
    - name: install nginx
      yum: name=nginx
      notify: stop http service
    - name: copy template for centos6
      template: src=nginx.conf6.j2 dest=/etc/nginx/nginx.conf
      when:  ansible_distribution_major_version == "7"
      notify: restart service
    - name: copy template for centos7
      template: src=nginx.conf7.j2 dest=/etc/nginx/nginx.conf
      when:  ansible_distribution_major_version == "6"
      notify: restart service
    - name: start service
      service: name=nginx state=started enabled=yes

  handlers:
    - name: stop http service
      service: name=httpd state=stopped
    - name: restart service
      service: name=nginx state=restarted

Playbook中template算术运算

  • 算法运算
  • 示例
    vim nginx.conf.j2
worker_processes {% raw %}{{ ansible_processor_vcpus**2 }}{% endraw %}
worker_processes {% raw %}{{ ansible_processor_vcpus+2 }}{% endraw %}

When的使用

  • 条件测试如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试通过when语句实现,在task中使用,jinja2的语法
    格式
  • When语句
  • 在task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法
  • 示例
  • tasks:
- name: shutdown redhat flavored systems
  command: /sbin/shutdown -h now
  when: ansible_os_family=="RedHat"
---
- hosts: all
  remote_user: root

  tasks:
    - name: create some files
      file: name=/data/{% raw %}{{ item }}{% endraw %} state=touch
      when: ansible_distribution_major_version == "7"
      with_items:
        - file1
        - file2
        - file3
    - name: install package
      yum: name={% raw %}{{ item }}{% endraw %}
      with_items:
        - htop
        - sl
        - hping3

迭代: with_items

  • 迭代:当有需要重复性执行的任务时,可以使用迭代机制对迭代项的引用,固定变量名为”item”
    • 要在task中使用 with_items:给定要迭代的元素列表
    • 列表格式
      • 字符串
      • 字典
        例子:
---
- hosts: all
  remote_user: root

  tasks:
    - name: create some files
      file: name=/data/{% raw %}{{ item }}{% endraw %} state=touch
      when: ansible_distribution_major_version == "7"
      with_items:
        - file1
        - file2
        - file3
    - name: install package
      yum: name={% raw %}{{ item }}{% endraw %}
      with_items:
        - htop
        - sl
        - hping3
---
- hosts: all
  remote_user: root

  tasks:
    - name: create group
      group: name={% raw %}{{ item }}{% endraw %}
      with_items:
        - g1
        - g2
        - g3

迭代嵌套子变量

例子:

---
- hosts: all
  remote_user: root

  tasks:
    - name: create group
      group: name={% raw %}{{ item }}{% endraw %}
      with_items:
        - g1
        - g2
        - g3
    - name: create user
      user: name={% raw %}{{ item.name }}{% endraw %} group={% raw %}{{ item.group }}{% endraw %}
      with_items:
        - { name: 'user1' , group: 'g1' }
        - { name: 'user2' , group: 'g2' }
        - { name: 'user3' , group: 'g3' }

Playbook中template for if

第一种:

---
- hosts: websrvs
  remote_user: root
  vars:
    ports:
      - 80
      - 81
      - 82

  tasks:
    - name: copy conf
      template: src=for1.conf.j2 dest=/data/for1.conf

cat for1.conf.j2

{% raw %}{% for port in ports %}{% endraw %}
server{
    listen {% raw %}{{ port }}{% endraw %}
}
{% raw %}{% endfor %}{% endraw %}

第二种:

---
- hosts: websrvs
  remote_user: root
  vars:
    ports:
      - listen_port: 80
      - listen_port: 81
      - listen_port: 82

  tasks:
    - name: copy conf
      template: src=for2.conf.j2 dest=/data/for1.conf

cat for2.conf.j2

{% raw %}{% for port in ports %}{% raw %}
server{
	listen {% raw %}{{ port.listen_port }}{% endraw %}
}
{% raw %}{% endfor %}{% endraw %}

第三种:

---
- hosts: websrvs
  remote_user: root
  vars:
    list:
      - web1:
        port: 81
        name: web1.yangyang.host
        rootdir: /data/website1
      - web2:
        port: 82
        name: web2.yangyang.host
        rootdir: /data/website2
      - web3:
        port: 83
        name: web3.yangyang.host
        rootdir: /data/website3

  tasks:
    - name: copy conf
      template: src=for3.conf.j2 dest=/data/for3.conf

cat for3.conf.j2

{% raw %}{% for p in list %}{% endraw %}
server{
    listen {% raw %}{{ p.port }}{% endraw %}
        servername {% raw %}{{ p.name }}{% endraw %}
        documentroot {% raw %}{{ p.rootdir }}{% endraw %}
}
{% raw %}{% endfor %}{% endraw %}

==上诉的.conf.j2代码均在与playbook同级的templates目录下==

Roles 角色

  • roles
    ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织 playbook。 roles能够根据层次型结构自动装载变量文件、 tasks以及 handlers等。要使用 roles只需要在 playbook中使用 include指令即可。简单来讲, roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地 include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
  • 复杂场景:建议使用 roles,代码复用度高
    • 变更指定主机或主机组
    • 如命名不规范维护和传承成本大
    • 某些功能需多个 Playbook,通过includes即可实现

      Ansible Roles目录编排

      Roles目录结构

  • 每个角色,以特定的层级目录结构进行组织
  • Roles目录结构
    playbook.yml
    roles/
    project/
    tasks/
    file/
    vars/不常用
    default/不常用
    templates/
    handlers/
    meta/不常用

Roes各目录作用

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

实例

结构
.
├── app_role.yml
└── roles
└── app
├── files
│ └── vhosts.conf
├── handlers
│ └── main.yml
├── tasks
│ ├── copyfile.yml
│ ├── group.yml
│ ├── main.yml
│ ├── start.yml
│ ├── templ.yml
│ ├── user.yml
│ └── yum.yml
├── templates
│ └── httpd.conf.j2
└── vars
└── main.yml
cat /root/ansible/app_role.yml

---
- hosts: websrvs
  remote_user: root

  roles:
    - app

cat /root/ansible/roles/app/handlers/main.yml

- name: restart service
  service: name=httpd state=restarted

cat /root/ansible/roles/app/tasks/copyfile.yml

- name: copy files
  copy: src=vhosts.conf dest=/etc/httpd/conf.d/  owner=app

cat /root/ansible/roles/app/tasks/group.yml

- name: create group
  group: name=app system=yes gid=123

cat /root/ansible/roles/app/tasks/start.yml

- name: start service
  service: name=httpd state=started enabled=yes

cat /root/ansible/roles/app/tasks/templ.yml

- name: copy configure
  template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  notify: restart service

cat /root/ansible/roles/app/tasks/user.yml

- name: create user
  user: name=app group=app system=yes shell=/sbin/nologin uid=123

cat /root/ansible/roles/app/tasks/yum.yml

- name: install package
  yum: name=httpd

cat /root/ansible/roles/app/tasks/main.yml

- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: copyfile.yml
- include: start.yml

cat /root/ansible/roles/app/templates/httpd.conf.j2

Listen {% raw %}{{ ansible_processor_vcpus*10 }}{% endraw %}

cat /root/ansible/roles/app/vars/main.yml

user_name: app
group_name: app

Roles playbook tags使用

  • roles playbook tags使用
    ansible-playbook –tags=”nginx,httpdmysql” nginx-role.yml
    // nginx-role.yml
---
- hosts: testweb
  remote_user: root

  roles:
  - { role: nginx,tags: ['nginx','web'],when: ansible_distribution_major_version=="6 }
  - { role: httpd,tags: ['httpd','web'] }
  - { role: mysql,tags: ['mysqI','db'] }
  - { role: marridb,tags: ['mysq','db'] }
  - { role: php }
运维自动化