Ansible详解(二)

一、YAML语法简介

YAML介绍:

YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、

Python、Perl以及电子邮件格式RFC2822等。

Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者

YAML特性:

  • YAML的可读性好

  • YAML和脚本语言的交互性好

  • YAML使用实现语言的数据类型

  • YAML有一个一致的信息模型

  • YAML易于实现

  • YAML可以基于流来处理

  • YAML表达能力强,扩展性好

更多的内容及规范参见YAML的官方网站:http://www.yaml.org

YAML语法格式:

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

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

  3. 使用#号注释代码

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

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

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

  7. k/v的值可同行写也可换行写。同行使用:分隔

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

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

  10. 一个name只能包括一个task

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

YAML语法简介:

[列表]

List:列表,其所有元素均使用“-”打头

示例:

# A list of tasty fruits

– Apple

– Orange

– Strawberry

– Mango

[字典]

Dictionary:字典,通常由多个key与value构成

示例:

---
# An employee record

    name: Example Developer

    job: Developer

    skill: Elite

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

示例:

---
# An employee record

    { name: Example Developer, job: Developer, skill: Elite }

二、Ansible中的剧本Playbook用法

Playbook核心元素:

  • Hosts:执行的远程主机列表
  • Tasks:任务列表
  • remote_user:远程登录用户名,作用于host和task
  • Varniables:内置变量或自定义变量在playbook中调用
  • Templates:模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • Handlers:和notify结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags:标签,指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性。
    因此会自动跳过没有变化的部分。此时,如果确信其没有变化,就可以通过tags跳过此些代码片段
实例:
---
- hosts: websrvs               # 主机分组
  remote_user: root            # 远程访问登录的用户名

  tasks:        # 执行任务列表
    - name: install httpd   # 执行任务名
      yum: name=httpd       # 执行任务ansible命令
    - name: copy config file
      copy: src=/app/httpd.conf dest=/ect/httpd/conf/ backup=yes
      tags: start_httpd     # 任务执行指定标签

      notify: restart httpd # 触发特性条件,跳过以下命令,执行指定handlers任务

    - name: start httpd
      tags: start_httpd     # 任务标签名
      service: name=httpd state=started enabled=yes

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

三、Playbook中变量的使用

变量名:仅能由字母、数字和下划线组成,且只能以字母开头

变量来源

  1. ansible all -m setup 远程主机的所有变量都可直接调用

  2. 在/etc/ansible/hosts中定义

    普通变量:主机组中主机单独定义,优先级高于公共变量

    host分组变量:针对主机组中所有主机定义统一变量

  3. 通过命令行指定变量,优先级最高

    例如:ansible-playbook –e varname=value
    
  4. 在playbook中定义

    vars:
    
      – var1: value1
    
      – var2: value2
  5. 在role中定义

    变量定义:key=value

    示例:http_port=80

变量调用方式

通过{{ variable_name }} 调用变量,且变量名前后必须有空格,

有时用”{{ variable_name }}”才生效

变量调用优先级

命令行-e > playbook定义 > hosts普通变量 > host分组变量

实例
1:命令行变量赋值

    vim var2.yml

        —--
        – hosts: websrvs
          remote_user: root

          tasks:
            – name: install package
              yum: name={{ pkname }}

            – name: start service
              service: name={{ pkname }} state=started enabled=yes

    ansible-playbook -e ‘pkname=vsftpd’ var2.yml     

2:playbook中赋值变量

vim var1.yml
    ---
    – hosts: websrvs
      remote_user: root
      vars:
        – pkname1: httpd
        – pkname2: vsftpd

      tasks:
        – name: install package
          yum: name={{ pkname1 }}
        – name: install package
          yum: name={{ pkname2 }}

ansible-playbook var1.yml

3:hosts文件中定义普通变量

vim /etc/ansible/hosts

    192.168.30.11 httpd_port=81

    192.168.30.12 httpd_port=82


vim hostname.yml
    ---
    – hosts: websrvs
      remote_user: root

      tasks:
        – name: set hostname
          hostname: name=web-{{ httpd_port }}

    ansible-playbook -C hostname.yml

4:hosts文件中定义分组变量

vim /etc/ansible/hosts

    [websrv:vars]   
    nodename=www
    domainname=wxlinux.com

vim hostname2.yml
    ---
    – hosts: websrvs
      remote_user: root

      tasks:
        – name: set hostname
          hostname: name={{nodename}}{{http_port}}.{{domainname}}

ansible-playbook hostname.yml

5:引用系统自带变量


ansible all -m setup |grep  ansible_fqdn     查看系统自带变量

vim var.yml
    ---
    – hosts: websrvs
      remote_user: root

      tasks:
        – name: create log file
          file: name=/data/{{ ansible_fqdn }}.log state=touch

ansible-playbook  var.yml

6:定义变量到一个文件中

vim vars.yml
    var1: httpd
    var2: vsftpd

vim testvar.yml
    ---
    – hosts: websrvs
      remote_user: root
      vars_files:
        – vars.yml

      tasks:
        – name: install package
          yum: name={{ var1 }}
        – name: create file
          file: name=/data/{{ var2 }}.log state=touch

ansible-playbook testvar.yml

四、Playbook中模板的用法

templates模板简介:

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

使用方法:

  1. templates文件必须存放在templates目录下,且以.j2为后缀

  2. templates模块只能被playbook调用

  3. yam文件需和templates目录平级,目录结构如下:

    ./
    
    ├── temnginx.yml
    
    └── templates
    
    └── nginx.conf.j2
    

templates使用形式:

字符串:使用单引号或双引号

数字:整数,浮点数

列表:[item1, item2, …]

元组:(item1, item2, …)

字典:{key1:value1, key2:value2, …}

布尔型:true/false

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

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

逻辑运算:and, or, not

流表达式:For If When

实例:

1:使用template传输配置文件

cp /etc/nginx/nginx.conf  templates/nginx.conf.j2

vim testtemplate.yml
    ---
    – hosts: os6
      remote_user: root

      tasks:
        – name: install package
          yum: name=nginx
        – name: copy template
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
        – name: start service
          service: name=nginx state=started enabled=yes

ansible-playbook testtemplate.yml

执行结果:运行playbook后,我们发现work process进程数量与虚拟机cpu内核数量是一致的,

接下来我们将把配置模板中的work process进程数量与系统自带变量结合起来引用。
 
2:template引用系统变量

ansible websrvs -m setup |grep ‘cpu’

vim templates/nginx.conf.j2
    worker_processes {{ ansible_processor_vcpus+2 }};

vim testtemplate.yml
    ---
    – hosts:os6
      remote_user: root

      tasks:
        – name: install package
          yum: name=nginx
        – name: copy template
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
          notify: restart service
        – name: start service
          service: name=nginx state=started enabled=yes

      handlers:
        – name: restart service
          service:name=nginx state=restarted

ansible-playbook  testtemplate.yml

执行结果:再次运行playbook后,我们发现worker process进程数量等于cpu核心数量加2,这样template

就能帮我们实现根据不同主机性能定制相应的配置。
 
3:hosts文件普通变量修改nginx服务端口

vim /etc/ansible/hosts

192.168.30.101 httpd_port=81

192.168.30.102 httpd_port=82

vim templates/nginx.conf.j2

 server {
       listen       {{ http_port }} default server
       listen       [::]:{{ http_prot }} default server
  }

五、Playbook中逻辑语句的用法

When:

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与

否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法

  
  
查看发行版本系统变量:

ansible srv -m setup filter=”*distribution”

1: 使用when匹配系统版本

vim testtemplate.yml
---
– hosts: all
  remote_user: root

  tasks:
    – name: install package
      yum: name=nginx
    – name: copy template for centos7
      template: src=nginx.conf7.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == “7”
      notify: restart service

    – name: copy template for centos6
      template: src=nginx.conf6.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: restart service
      service:name=nginx state=restarted

 执行结果:当when语句不匹配时,将skipping直接跳过,仅执行与when语句匹配的语句内容,

 最终CentOS6,7根据不同的版本号生成对应的配置并启动服务。

2:使用迭代创建组

vim testitem2.yml
    ---
    – hosts: all
      remote_user: root

      tasks:
        – name: create some groups
          group: name={{ item }}

          when: ansible_distribution_major_version == “7”
          with_items:
            – g1
            – g2
            – g3

  执行结果:当系统版本为CentOS7时,创建g1,g2,g3组
 
3:使用迭代配合字典创建用户与组

vim testitem2.yml
---
– hosts: all
  remote_user: root

  tasks:
    – name: create some groups
      group: name={{ item }}
      with_items:
        – g1
        – g2
        – g3

    – name: create some users
      user: name={{ item.name }} group={{ item.group }}
      with_items:
        – { name: ‘user1’,group: ‘g1’ }
        – { name: ‘user2’,group: ‘g2’ }
        – { name: ‘user3’,group: ‘g3’ }

  执行结果:所有主机上创建user1,user2,user3用户,且主组为g1,g2,g3
 

for 与 if

示例1:template,for

vim for1.conf.j2
    {% for port in ports %}

    server{
             listen {{ port }}
    }

    {% endfor %}

vim testfor.yml
    ---
    – hosts: websrvs
      remote_user: root
      vars:
        ports:
          – 818283

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

 执行结果:每台主机生成for1.conf文件,内容如下

示例2:template,for,引用字典

vim for2.conf.j2

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

cp testfor.yml testfor2.yml

vim testfor2.yml
    ---
    – hosts: websrvs
      remote_user: root
      vars:
        ports:
          – listen_port: 81
          – listen_port: 82
          – listen_port: 83

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

 执行结果:每台主机生成for2.conf文件,内容如下
 
示例3:for循环中调用字典

vim for3.conf.j2

    {% for p in ports %}
    server{
             listen {{ p.port }}
             servername {{ p.name }}
        documentroot {{ p.rootdir }}
    }
    {% endfor %}

cp testfor2.yml testfor3.yml

vim testfor3.yml
    ---
    – hosts: websrvs
      remote_user: root
      vars:
        ports:
          – web1:
            port: 81
            name: web1.magedu.com
            rootdir: /data/website1
          – web2:
            port: 82
            name: web2.magedu.com
            rootdir: /data/website2
          – web3:
            port: 83
            name: web3.magedu.com
            rootdir: /data/website3

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

 执行结果:每台主机生成for3.conf文件,内容如下

示例4:for循环中调用if

vim for4.conf.j2
    {% for p in ports %}
    server{
             listen {{ p.port }}
    {% if p.name is defined %}
             servername {{ p.name }}
    {% endif %}
            documentroot {{ p.rootdir }}
    }
    {% endfor %}

cp testfor3.yml testfor4.yml

vim testfor4.yml
    ---
    – hosts: websrvs
      remote_user: root
      vars:
        ports:
          – web1:
            port: 81
            #name: web1.magedu.com
             rootdir: /data/website1
          – web2:
            port: 82
            name: web2.magedu.com
             rootdir: /data/website1
          – web3:
            port: 83
            #name: web3.magedu.com
             rootdir: /data/website1

      tasks:
        – name: copy conf
          template:src=for4.conf.j2  dest/data/for4.conf

  执行结果:每台主机生成for3.conf文件,内容如下,
  web1与web3的name没赋值,所有跳过,web2的name被赋值,文件中输出结果
   

六、Roles角色详解

角色(roles):角色集合

roles
|-- filecopy
|-- httpd
|-- memcached
|-- mysql
`-- nginx

/roles/project/ :项目名称,有以下子目录

nginx
|-- files
|-- tasks
|-- templates
|-- handlers
|-- meta
`-- vars



files/ :存放由copy或script模块等调用的文件

templates/:template模块查找所需要模板文件的目录

tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;
    其它的文件需要在此文件中通过include进行包含

handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过
    include进行包含

vars/:定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件
    中通过include进行包含

meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,
    其它文件需在此文件中通过include进行包含

default/:设定默认变量时使用此目录中的main.yml文件

 建议:roles创建在ansible目录
 如:

mkdir roles

mkdir roles/{httpd,mysql,memcache,nginx} -pv

实例

1:定义nginx角色

niginx

1.group:nginx

2.user:nginx

3.yum:nginx

4.template:nigin.conf.j2

5.service:nginx

目录结构如下:

Ansible详解(二)_第1张图片

cd nginx

mkdir tasks templates

cd tasks

vim group.yml
    – name: create group
      group: name=nginx gid=80

vim user.yml
    – name: create user
      user: name=nginx group=nginx uid=80 shell=/sbin/noligin

vim yum.yml
    – name: install package
      yum: name=nginx

vim start.yml
    – name: start service
      service: name=nginx state=started enabled=yes

vim restart.yml
    – name: restart service
      service: name=nginx state=restarted 

cp /etc/nginx/nginx.conf  template/nginx.conf.j2

vim template/nginx.conf.j2

worker_processes {{ ansible_processes_vcpus+2 }};

vim templ.yml
    – name: copy conf
    template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

vim main.yml
    – include: group.yml
    – include: user.yml
    – include: yum.yml
    – include: templ.yml
    – include: start.yml

调用角色的剧本要和roles目录在同一文件夹

vim nginx_roles.yml
    – hosts: websrvs
      romete_user: root
      roles:
        – role: nginx

ansible-playbook -C nginx_role.yml

2:增加httpd角色

结构目录如下:
Ansible详解(二)_第2张图片

cd httpd/
mkdir tasks

cd tasks/
vim user.yml
    – name: create user
      user: name=apache system=yes shell=/sbin/nologin

cd httpd/

mkdir files

cp httpd.conf   files/

cd /tasks/

vim copyfile.yml
    – name: copy files
      copy: src=httpd.conf dest=/data/ own=apache

vim main.yml
    – incluse: user.yml
    – incluse: copyfile.yml

vim httpd_role.yml
    – hosts: websrvs
      romete_user: root
      roles:
        – role: httpd

示例3:同时调用两个roles角色

目录结构:
Ansible详解(二)_第3张图片

cp niginx_role.yml some_role.yml

vim some_role.yml
    – hosts: websrvs
      romete_user: root

      roles:
        – role: httpd
        – role: nginx

示例4:一个roles角色调用另一个roles角色的task任务

目标:nginx调用httpd的copyfile

vim main.yml

– include: group.yml

– include: user.yml

– include: yum.yml

– include: templ.yml

– include: start.yml

– inclide: roles/httpd/tasks/copyfile.yml

示例5:roles playbook tags

目录结构如下:

Ansible详解(二)_第4张图片

cp -r nginx/ app/     首先虚构一个app的role

vim some_role2.yml
    – hosts: websrvs
      romete_user: root
      roles:
        – { role: httpd,tags:[‘web’,’httpd’]}
        – { role: nginx,tags:[‘web’,’nginx’]}
        – { role: app,tags:’app’}

ansible-playbook -t web some_role.yml

执行结果:只执行标签为web的role
 

示例6:roles playbook tags when

cp -r nginx/ app/     虚构一个role

vim some_role3.yml
    – hosts: all
      romete_user: root

      roles:
       – { role: httpd,tags:[‘web’,’httpd’]}
       – { role: nginx,tags:[‘web’,’nginx’]
           when: ansible_distribution_major_version==”7″}
       – { role: app,tags:’app’}

ansible-playbook -t web some_role.yml

 执行结果:至执行tags标签为web的roles,当主版本号为7时,才执行nginx的role
  

示例7:综合演示

结构目录:

Ansible详解(二)_第5张图片

rm -rf /app

mkdir app

cd app

mkdir tasks templates vars handlers files

cd tasks/

vim group.yml
    – name: create group
      group: name=app system=yes gid=123

vim user.yml
    – name: create user
      user: name=app group=app system=yes shell=/sbin/nologin uid=123

vim yum.yml
    – name: install package
       yum: name=httpd

cp /etc/httpd/conf/httpd.conf /templates/httpd.conf.j2

vim temlates/httpd.conf.j2
    Listen {{ ansible_processor_vcpus*10 }}
    User {{ username }}
    Group {{ groupname }}

vim /vars/main.yml
    username: app
    groupname: app

vim templ.yml
    – name: copy conf
      temlplate: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
      notify: restart service

vim start.yml
    – name: start service
       service: name=httpd state=started enabled=yes

vim handlers/main.yml
    – name: restart service
       service: name=httpd state=restarted

touch files/vhosts.conf 

vim copyfile.yml
    – name: copy config
      copy: src=vhosts.conf  dest=/ect/httpd/conf.d/

vim main.yml
    – include: group.yml
    – include: user.yml
    – include: yum.yml
    – include: templ.yml
    – include: copyfile.yml
    – include: start.yml

cd ansible/

vim app_role.yml
    – hosts: websrvs
      remote_user: root
      roles:
        – role: app

示例8:部署memcached,占用内存为物理内存1/4

yum install memcached

目录结构:
Ansible详解(二)_第6张图片

cp /etc/sysconfig/memcached templates/memcached.j2

vim memcached.j2

CACHESIZE=”{{ ansible_memtotal_mb//4 }}”

vim tasks/yum.yml
    – name: install package
       yum: name=memcached

vim templ.yum
    – name: copy conf
       template: src=memcached.j2 dest=/etc/sysconfig/memcached

vim start.yml
    – name: start service
      service: name=memcached state=started enabled=yes

vim main.yml
    – include: yum.yml
    – include: templ.yml
    – inculde: start.yml

vim memcached_role.yml
    – hosts: os6
       remote_user: root
       roles:
         – role: memcached

ansible-playbook memcached_role.yml

远程查看配置文件,确认生效:

ansible os6 -a 'cat /etc/sysconfig/memcached'

你可能感兴趣的:(linux)