优秀的编程知识分享平台

网站首页 > 技术文章 正文

自动化运维工具:ansible(二)(ansible 自动化运维)

nanyue 2024-08-16 00:38:09 技术文章 42 ℃


接(上篇)自动化运维工具:ansible(一)

13、ansible系列命令

1>ansible-galaxy  

连接https://galaxy.ansible.com下载相应的roles(角色)  

列出所有已安装的galaxy    

  • ansible-galaxy list  

安装galaxy    

  • ansible-galaxy install geerlingguy.redis  

删除galaxy    

  • ansible-galaxy remove geerlingguy.redis

2>ansible-pull  推送命令至远程,效率无限提升,对运维要求较高

3>Ansible-playbook

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

(2)YAML是一个个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、 Perl以及电子邮件格式RFC2822等。    YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language" (仍是一种标记语言)    

特性:      

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

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

(3)在单一档案中,可用连续三个连字号(一)区分多个档案。另外,还有选择性的连续三个点号(...)用来表示档案结尾次行开始正常写Playbook的内容,一般建议写明该Playbook的功能    使用#号注释代码    

  • 缩进必须是统一的,不能空格和tab混用    
  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的    
  • YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感    
  • k/v的值可同行写也可换行写。同行使用:分隔    
  • v可是个字符串,也可是另一个列表    
  • 一个完整的代码块功能需最少元素需包括name: task    
  • 一个name只能包括一个task    
  • YAML文件扩展名通常为yml或yaml

(4)List:列表,其所有元素均使用"-"打头

示例:
[root@ansible ansible]#cat file.yml 
---
- hosts: webserver    #一个hosts列表,定义针对的列表主机
  remote_user: root

  tasks:              #任务
    - name: create new file    #任务列表1
      file: name=/root/newfile state=touch
    - name: create new user    #任务列表2
      user: name=test system=yes shell=/sbin/nologin

(5)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}

(6)Hosts:执行的远程主机列表    

playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中。    

可以是如下形式:    

  • one.example.com    
  • one.example.com:two.example.com    
  • 192.168.100.10    
  • 192.168.100.*    
  • webserver:dbserver 两个组的并集    
  • webserver:&dbserver 两个组的交集    
  • webservers:!dbserver 在webserver组,但不在dbserver组
  • all /etc/ansible/hosts主机清单中的所有主机
---
- hosts: all    #主机清单中的所有主机
  remote_user: root

  tasks:              #任务
  ......

(7)task列表和action    

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

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

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

tasks:任务列表    

格式:       

  • action: module arguments      
  • module: arguments #建议使用    

?注意:shell和command模块后面跟命令,而非key=value    

某任务的状态在运行后为changed时,可通过"notify"通知给相应的 handlers


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

#编辑httpd.yml,实现httpd的安装,配置文件更改,服务启动
#问题:第一次启动后,更改httpd的配置文件,第二次再执行,会因为之前启动了,而无法重启服务
#解决:通过设置"notify",当某任务的状态在运行后为changed时,通知给相应的 handlers ,触发相应的命令
[root@ansible ansible]#vim httpd.yml 
---
- hosts: all
  remote_user: root

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

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

?任务可以通过"tags"打标签,而后可在ansible-playbook命令上使用-t指定进行调用

[root@ansible ansible]#ansible all -m yum -a 'name=httpd state=absent'
[root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
to get rid of this message.
192.168.100.20 | FAILED | rc=1 >>
未安装软件包 httpd non-zero return code
192.168.100.10 | FAILED | rc=1 >>
未安装软件包 httpd non-zero return code

通过ansible卸载httpd,在通过tags标签指定只下载httpd

[root@ansible ansible]#ansible-playbook -t install -C httpd.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [install httpd package] *******************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible-playbook -t install httpd.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [install httpd package] *******************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
to get rid of this message.
192.168.100.20 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
192.168.100.10 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
[root@ansible ansible]#ansible all -m shell -a 'ss -ntl | grep 80'
192.168.100.20 | FAILED | rc=1 >>
non-zero return code
192.168.100.10 | FAILED | rc=1 >>
non-zero return code

(8)运行playbook

如果命令或脚本的退出码不为零,可以使用如下方式替代

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

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

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

运行playbook的方式    

ansible-playbook <filename.yml> ... [options]    

常见选项:      

--check只检测可能会发生的改变,但不真正执行操作      

--list-hosts 列出运行任务的主机      

--limit主机列表只针对主机列表中的主机执行      

-v显示过程-vv -vvv 更详细

示例:
ansible-playbook file.yml --check #只检测
ansible-playbook file.yml #执行
ansible-playbook file.yml --limit webserver

(9)ansible-playbook支持变量:

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

变量来源:      

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

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

  • 普通变量:主机组中主机单独定义,优先级高于公共变量        
  • 公共(组)变量:针对主机组中所有主机定义统一变量

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

  • ansible-playbook -e varname=value      

4.在playbook中定义

[root@ansible ansible]#vim apps.yml 
---
- hosts: all
  remote_user: root

  tasks:
    - name: install package
      yum: name={{ pkname }}    #定义变量
    - name: start service
      service: name={{ pkname }} state=started enabled=yes
[root@ansible ansible]#ansible-playbook -e 'pkname=vsftpd' -C apps.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [install package] *************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

TASK [start service] ***************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible-playbook -e 'pkname=vsftpd' apps.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.10]
ok: [192.168.100.20]

TASK [install package] *************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

TASK [start service] ***************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible all -m shell -a 'ss -ntl|grep 21'
192.168.100.20 | CHANGED | rc=0 >>
LISTEN     0      32          :::21                      :::*                  
192.168.100.10 | CHANGED | rc=0 >>
LISTEN     0      32          :::21                      :::*      

也可以在playbook中,定义vars

也可以使用变量文件:

[root@ansible ansible]#vim vars.yml 
var1: httpd
var2: vsftpd
[root@ansible ansible]#vim testvar.yml 
---
- hosts: all
  remote_user: root
  vars_files:
    - vars.yml

  tasks:
    - name: install package
      yum: name={{ var1 }}
    - name: create file
      file: name=/root/{{ var2 }}.log state=touch
[root@ansible ansible]#ansible-playbook -C testvar.yml 
......
[root@ansible ansible]#ansible-playbook testvar.yml
...... 
[root@ansible ansible]#ansible all -a 'ls /root'
192.168.100.20 | CHANGED | rc=0 >>
......
vsftpd.log
192.168.100.10 | CHANGED | rc=0 >>
......
vsftpd.log
[root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg
to get rid of this message.
192.168.100.20 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
192.168.100.10 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64

5 在role中定义    

变量定义:key=value    

示例:http_port=80    

变量调用方式:      

  • 通过{{ variable_name }}调用变量,且变量名前后必须有空格,有时用"{{ variable_ name}}" 才生效      
  • ansible playbook -e选项指定

4>Ansible-vault  

功能:管理加密解密yml文件

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       创建新文件

5>Ansible-console:2.0+新增,可交互执行命令,支持tab  

root@test (2)[f:10] $  

执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]$    

?设置并发数:forksn 例如:forks 10    

?切换组:cd主机组 例如:cd web    

?列出当前组主机列表:list    

?列出所有的内置命令:?或help    

?示例:

[root@ansible ~]#ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (2)[f:5]$ cd webserver
root@webserver (1)[f:5]$ forks 10
root@webserver (1)[f:10]$ command hostname
192.168.100.10 | CHANGED | rc=0 >>
node1
root@webserver (1)[f:10]$ shell ls /root
192.168.100.10 | CHANGED | rc=0 >>
anaconda-ks.cfg
hello.sh
hello.sh.4604.2020-03-17@21:14:22~

14、模板templates  

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

Jinja2语言,使用字面量,有下面形式    

  • 字符串:使用单引号或双引号    
  • 数字:整数,浮点数    
  • 列表: [item1, item2, ...]    
  • 元组: (item1, item2, ...)    
  • 字典: {key1:value1, key2:value2, ...}    
  • 布尔型: true/false    
  • 算术运算: +,-, *,/.// %,**    
  • 比较操作: ==,!=,>,>=, <, <=    
  • 逻辑运算: and, or, not    
  • 流表达式: For If When

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

templates文件必须存放于templates目录下,且命名为.j2结尾  

yamI/yml文件需和templates目录平级,目录结构如下:

├── ansible  

└── templates

#实例:配置nginxtemplates模板文件,使不同主机的worker进程数量=CPU*2
[root@ansible ~]#mkdir ansiable/templates
[root@ansible ~]#tree -d
.
├── ansible
│   └── templates
└── bin
[root@ansible ansible]#ansible webserver -m setup | grep "processor"    #查看CPU变量名
        "ansible_processor": [
        "ansible_processor_cores": 1, 
        "ansible_processor_count": 1, 
        "ansible_processor_threads_per_core": 1, 
        "ansible_processor_vcpus": 1, 
[root@ansible ansible]#cp /etc/nginx/nginx.conf ./templates/nginx.conf.j2
[root@ansible ansible]#vim templates/nginx.conf.j2
[root@ansible ansible]#vim testtempl.yml 
---
- hosts: webserver
  remote_user: root

  tasks:
    - name: install paskage
      yum: name=nginx
    - name: copy template
      tempate: src=/root/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: start service
      service: name=nginx state=started enabled=yes
[root@ansible ansible]#ansible-playbook testtempl.yml

when语句:  

条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法  

格式:  

  • 在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
  • 对不同centos版本针对配置
[root@ansible ansible]#ansible all -m setup -a 'filter="*distribution*"'
192.168.100.20 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "CentOS", 
        "ansible_distribution_file_parsed": true, 
        "ansible_distribution_file_path": "/etc/redhat-release", 
        "ansible_distribution_file_variety": "RedHat", 
        "ansible_distribution_major_version": "7", 
        "ansible_distribution_release": "Core", 
        "ansible_distribution_version": "7.4", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
192.168.100.10 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "CentOS", 
        "ansible_distribution_file_parsed": true, 
        "ansible_distribution_file_path": "/etc/redhat-release", 
        "ansible_distribution_file_variety": "RedHat", 
        "ansible_distribution_major_version": "7", 
        "ansible_distribution_release": "Core", 
        "ansible_distribution_version": "7.4", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

迭代:当有需要重复性执行的任务时,可以使用迭代机制    

对迭代项的引用,固定变量名为"item"    

要在task中使用with_items给定要迭代的元素列表    

列表格式:      

  • 字符串      
  • 字典

迭代嵌套子变量

[root@ansible ansible]#cat testitem.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' }


  playbook中的template for if:

[root@ansible ansible]#cat templates/for1.conf.j2 
{% for port in ports %}
server{
    listen {{ port }}
}
{% endfor %}
[root@ansible ansible]#cat testfor.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
      - 81
      - 82
      - 83
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for1.conf.j2 dest=/root/for1.conf
[root@ansible ansible]#ansible-playbook -C testfor.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible-playbook testfor.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 


node1节点查看:
[root@node1 ~]# cat for1.conf 
server{
    listen 81
}
server{
    listen 82
}
server{
    listen 83
}
[root@ansible ansible]#cat testfor2.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
        - listen_port: 80
        - listen_port: 82
        - listen_port: 83
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for2.conf.j2 dest=/root/for2.conf
[root@ansible ansible]#cat templates/for2.conf.j2 
{% for port in ports %}
server{
    listen {{ port.listen_port }}
}
{% endfor %}
[root@ansible ansible]#ansible-playbook testfor2.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

node1节点查看:
[root@node1 ~]# cat for2.conf 
server{
    listen 80
}
server{
    listen 82
}
server{
    listen 83
}



[root@ansible ansible]#cat testfor3.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
      - web1:
        port: 81
        name: web1.yang.com
        rootdir: /root/website1
      - web1:
        port: 82
        name: web2.yang.com
        rootdir: /root/website2
      - web1:
        port: 83
        name: web3.yang.com
        rootdir: /root/website3
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for3.conf.j2 dest=/root/for3.conf
[root@ansible ansible]#cat templates/for3.conf.j2 
{% for p in ports %}
server{
    listen {{ p.port }}
    servername {{ p.name }}
    documentroot {{ p.rootdir }}
}
{% endfor %}
[root@ansible ansible]#ansible-playbook testfor3.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

node1节点查看:
[root@node1 ~]# cat for3.conf 
server{
    listen 81
    servername web1.yang.com
    documentroot /root/website1
}
server{
    listen 82
    servername web2.yang.com
    documentroot /root/website2
}
server{
    listen 83
    servername web3.yang.com
    documentroot /root/website3
}
[root@ansible ansible]#cat testfor4.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
      - web1:
        port: 81
        #name: web1.yang.com
        rootdir: /root/website1
      - web1:
        port: 82
        name: web2.yang.com
        rootdir: /root/website2
      - web1:
        port: 83
        #name: web3.yang.com
        rootdir: /root/website3
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for4.conf.j2 dest=/root/for4.conf
[root@ansible ansible]#cat templates/for4.conf.j2 
{% for p in ports %}
server{
    listen {{ p.port }}
{% if p.name is defined %}    #如果被定义了则生成,没有定义则不生成
    servername {{ p.name }}
{% endif %}
    documentroot {{ p.rootdir }}
}
{% endfor %}
[root@ansible ansible]#ansible-playbook testfor4.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.10]
ok: [192.168.100.20]

TASK [copy conf] *******************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


node1节点查看:
[root@node1 ~]# cat for4.conf 
server{
    listen 81
    documentroot /root/website1
}
server{
    listen 82
    servername web2.yang.com
    documentroot /root/website2
}
server{
    listen 83
    documentroot /root/website3
}

15、roles  

1>定义:ansilbe自1.2版本引入的新特性,用于层次性、结构化的组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。  

复杂场景:建议使用roles,代码复用度高    

  • 变更指定主机或主机组    
  • 如命名不规范维护和传承成本大    
  • 某些功能需多个Playbook,通过Includes即可实现  

2>roles目录结构  

每个角色,以特定的层级目录结构进行组织

playbook.yml
roles/
    project/
        tasks/
        files/
        vars/         不常用
        default/      不常用
        templates/
        handlers/
        meta/         不常用

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

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

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

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

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

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

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

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

3>使用:  

角色(roles):角色集合  

roles/(官方建议目录/etc/ansible/roles,不过也可以自定义)    

  • mysql/    
  • httpd/    
  • nginx/    
  • memcached/
[root@ansible ansible]#tree    #构建目录结构,如果没有可以mkdir创建目录
.
└── roles
    ├── httpd
    ├── memcache
    ├── mysql
    └── nginx

5 directories, 0 files
[root@ansible ansible]#cd roles/nginx/
[root@ansible nginx]#pwd
/root/ansible/roles/nginx
[root@ansible nginx]#mkdir tasks templates    #在roles/nginx创建一个任务目录和模板目录
[root@ansible nginx]#ls
tasks  templates
[root@ansible nginx]#cd tasks/                #进入任务tasks目录
[root@ansible tasks]#vim group.yml            #先创建组文件
[root@ansible tasks]#cat group.yml
- name: create group
  group: name=nginx gid=80
[root@ansible tasks]#vim user.yml             #再创建用户文件
[root@ansible tasks]#cat user.yml
- name: create user
  user: name=nginx uid=80 group=nginx system=yes shell=/sbin/nologin
[root@ansible tasks]#vim yum.yml              #再创建安装文件
[root@ansible tasks]#cat yum.yml
- name: install package
  yum: name=nginx
[root@ansible tasks]#vim start.yml            #进而创建启动文件
[root@ansible tasks]#cat start.yml
- name: start service
  service: name=nginx state=started enabled=yes
[root@ansible tasks]#cp start.yml restart.yml
[root@ansible tasks]#vim restart.yml          #重启服务文件
[root@ansible tasks]#cat restart.yml
- name: restart service
  service: name=nginx state=restarted
[root@ansible templates]#cd ../templates/     #进入模板templates目录
[root@ansible templates]#cp /etc/nginx/nginx.conf nginx.conf.j2    #拷贝本机的nginx文件成为模板文件
[root@ansible templates]#vim nginx.conf.j2

[root@ansible templates]#cd ../tasks/
[root@ansible tasks]#ls
group.yml  restart.yml  start.yml  user.yml  yum.yml
[root@ansible tasks]#vim templ.yml
[root@ansible tasks]#cat templ.yml            #回到任务tasks目录,创建templ.yml文件
- name: copy conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[root@ansible tasks]#ls
group.yml  restart.yml  start.yml  templ.yml  user.yml  yum.yml
[root@ansible tasks]#vim main.yml             #创建全局文件,定义调用各个板块文件的顺序
[root@ansible tasks]#cat main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: start.yml
[root@ansible tasks]#cd ../../
[root@ansible roles]#ls
httpd  memcache  mysql  nginx
[root@ansible roles]#cd ../
[root@ansible ansible]#ls
roles
[root@ansible ansible]#vim nginx_role.yml     #创建nginx role文件,注意必须和roles同级
[root@ansible ansible]#cat nginx_role.yml
- hosts: all
  remote_user: root
  roles:
    - role: nginx
[root@ansible ansible]#ansible-playbook -C nginx_role.yml    #检查语法
[root@ansible ansible]#ansible-playbook nginx_role.yml       #执行


总结:构建目录树结构如下
[root@ansible ansible]#tree
.
├── nginx_role.yml
└── roles
    ├── httpd
    ├── memcache
    ├── mysql
    └── nginx
        ├── tasks
        │   ├── group.yml
        │   ├── main.yml
        │   ├── restart.yml
        │   ├── start.yml
        │   ├── templ.yml
        │   ├── user.yml
        │   └── yum.yml
        └── templates
            └── nginx.conf.j2

7 directories, 9 files

感谢作者:我听过

出处:http://dwz.date/bYGu

最近发表
标签列表