Ansible 使用基础 ( 二 )------ Playbook   基本使用

YAML 基本语法规则:

  •     YAML文件内同区分大小写,其中的key/valye的值均大小写敏感
  •     使用缩进表示层级关系,缩进的空格数目不重要,只要相同层级的元素左侧对齐即可【空格和tab不能混用】
  •     多个key/value 可以分行也可以写在一行,以 , 分开
  •     value 可以是一个字符串,也可以是一个列表
  •     一个完整的代码功能最少需要包含 name 和 task 元素
  •     一个 name 只能包括一个 task
  •     YAML 文件扩展名通常为 yml 或 yaml
  •     # 表示注释,从这个字符一直到行尾,都会被解析器忽略。

YAML 支持的数据结构有:

字典,写法如下:

{name: 'eeeeee',jog: 'kkkk',skill: 'ddddd'}
  name: eeeeeee
  job: kkkkkk
  skill: ddddd

列表,写法如下:

[A,B,C,D]
   - A 
   - B 
   - C 
   - D

纯量:单个的、不可再分的值

PLAYBOOK 核心元素:

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

HOSTS 组件【用于指定执行任务的主机,必须事先定义在主机清单中】

- hosts: web:db    ##  指定主机模式与 Ansible 命令中主机模式相同

remote_user 组件[用于Host和task中,也可以通过指定通过sudo的方式在远程主机上执行任务]:

- hosts: web
      remote_user: root

Task 列表

tasks:
    - name: INSTALL httpd
      yum: name=httpd
    - name: start/enable httpd
      service: name=httpd state=started enabled=yes

ps: shell 和 command 模块后不需要跟键值对,直接写 shell 命令为参数

Playbook 中使用 handlers 和 notify

Handlers 本质是 task list,类似于 MYSQL中的触发器的出发行为,其中task 与前所述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个 play 的最后被触发,这样可以避免多次有改变发生时每次都执行的操作,仅当所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作被称为 handler ,也即 notify 中调用handler 中定义的操作。

---
- hosts: '220'
  remote_user: root
  gather_facts: no

  tasks:
    - name: INSTALL httpd
      yum: name=httpd
    - name: INSTALL configure file httpd.conf
      copy: src=cile/httpd.conf dest=/etc/httpd/conf/
    - name: INSTALL web htmls
      copy: src=/data/html/ dest=/var/www/html/
      notify: restart httpd
    - name: ENSURE apache is running
      service: name=httpd state=started enabled=yes

  handlers:
    - name: restart httpd
      service: name=httpd state=restarted
## 修改配置 文件后通知 restart httpd ;重启 httpd 服务

Playbook中变量的使用 【变量名只能是数字、字母、下划线;必须要以字母开头】

变量定义:
    http_port=80
变量调用:
    {{ variable_name }}调用变量,变量名前后建议加上空格,有时用上 "{{ variable_name }}" 才生效
变量来源:

1. ansible 的setup facts 远程之际的所有变量都可以直接调用   【在playbook 中使用,且不能在有 gather_facts=no 参数后使用】

---
# ansible_fqdn 模块使用
- hosts: '220'
  remote_user: root
  tasks:
    - name: '创建空文件'
      file: name=/data/{{ ansible_fqdn }}.log state=touch
    - name: '写入内容'
      copy: content='\t\t静夜思\n\t\t\t[李白]\n\t床前明月光,疑似地上霜。\n\t举头望明月,低头思故乡。\n'  dest=/data/{{ ansible_fqdn }}.log

ps:添加 gather_facts=no ,不在主动收集被控主机的 setup facts,无法继续调用 setup facts 中的变量

2. 在 playbook 命令中定义变量

---
- hosts: '220'
  remote_user: root
  gather_facts: no
  tasks:
  - name: istall paskegs
    yum: name={{ pkname }} state=present

ansible-playbook -e pkname=httpd e-install-test.yaml

3. 在playbook 中定义变量

---
- hosts: '220'
  remote_user: root
  gather_facts: no
  vars:
  - data: Of course,pikaqiu is pikaqiu.PiKaQiuKings is the king of PIKAQIUS.
  tasks:
  - name: shell test
    shell: echo {{ data }} > /data/pikaqiukings.txt

 4. 使用变量文件中变量

可以在一个独立的 playbook 文件中定义变量,在另一个 playbook 文件中应用变量文件中的变量,比 playbook 中定义的变量优先级更高

5. 在 /etc/ansible/hosts 中定义变量:

  单个主机变量

[web]
   192.168.162.128 fqdn=centos8.2-128
   192.168.162.222 fqdn=centos8.2-222
   192.168.162.220 fqdn=centos8.2-220

  组变量:

[web:vars]
   domain=njit.edu.pikaqiu.cn

  ps:出现单个主机变量和组变量重名:

[web]
   192.168.162.128 fqdn=centos8.2-128 domain=njit.edu.dingxu.cn
   192.168.162.222 fqdn=centos8.2-222 domain=njit.edu.dingxu.cn
   192.168.162.220 fqdn=centos8.2-220 domain=njit.edu.dingxu.cn
   [web:vars]
   domain=njit.edu.pikaqiu.cn

  按照单个主机变量的值来处理

Template 模板: 【模板是一个文本文件,可以作为生成文件的模板,并且模板中还可以嵌套 jinja 语法】

jinha2 语法:

• 字符串: 使用单引号或双引号定义
• 数字: 整数、浮点数
• 列表: [item1,item2,.....]
• 元组: (item1,item2,.....)  
• 字典: {k1:v1,k2:v2,.....}
• boolean: true,false
• 算术运算: +,-,*,/,//,%,**
• 比较操作: ==,!=,>,>=,<,<=
• 逻辑符号: and,or,not 
• 流表达式: for,if,when

Playbook  简单示例:

1. 取单字典中 value

yaml:
---
- hosts: '220'
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
  tasks:
    - name: template test3
      template: src="/data/ansible/yamls/template/nginx.conf2.j2" dest=/data/nginx.conf2-res
template:
  {% for vhosts in nginx_vhosts %}
  server{
    listen {{ vhosts.listen }}
  }
  {% endfor %}
res:
  server{
    listen 8080
  }

2. 循环取 list 值

yaml:
---
- hosts: '220'
  remote_user: root
  vars:
    nginx_vhosts: [ 81,82,83 ]

  tasks:
    - name: telplate test
      template: src="/data/ansible/yamls/template/nginx.conf.j2" dest=/data/template-test-res
template:
  {% for vhost in nginx_vhosts %}
  server{
    listen {{ vhost }}
  }
  {% endfor %}
res:
  server{
    listen 81
  }
  server{
    listen 82
  }
  server{
    listen 83
  }

3. 较复杂的字典列表:

yaml:
---
- hosts: '220'
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
        server_name: "web1.mangedu.com"
        root: "/var/www/nginx/web1"
      - listen: 8081
        server_name: "web2.mangedu.com"
        root: "/var/www/nginx/web2"
      - { listen: 8082, server_name: "web3.magedu.com", root: "/var/www/nginx/web3/" }
  tasks:
    - name: template test3
      template: src="/data/ansible/yamls/template/nginx3.conf.j2" dest=/data/nginx3.conf-res
template:
  {% for vhost in nginx_vhosts %}
  server{
    listen_port= {{ vhost.listen }}
    server_name= {{ vhost.server_name }}
    root_src= {{ vhost.root }}
  }
  {% endfor %}
res:
server{
  listen_port= 8080
  server_name= web1.mangedu.com
  root_src= /var/www/nginx/web1
}
server{
  listen_port= 8081
  server_name= web2.mangedu.com
  root_src= /var/www/nginx/web2
}
server{
  listen_port= 8082
  server_name= web3.magedu.com
  root_src= /var/www/nginx/web3/
}

4. 条件判断 if 的使用

---
- hosts: '220'
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
        root: "/var/www/nginx/web1"
      - listen: 8081
        server_name: "web2.mangedu.com"
        root: "/var/www/nginx/web2"
      - listen: 8082
        hostname: 'pikaqiushishabi'
        server_name: "web3.magedu.com"
        root: "/var/www/nginx/web3/"
  tasks:
    - name: template test3
      template: src="/data/ansible/yamls/template/nginx3.conf.j2" dest=/data/nginx3.conf-res
template:【位置可能不对齐,需要后期根据格式调整】
  {% for vhost in nginx_vhosts %}
  server{
      listen_port= {{ vhost.listen }}
      {% if vhost.server_name is defined %}server_name= {{ vhost.server_name }}
      {% endif %}
  root_src= {{ vhost.root }}
  }
  {% endfor %}
res:
  server{
      listen_port= 8080
      root_src= /var/www/nginx/web1
  }
  server{
      listen_port= 8081
      server_name= web2.mangedu.com
      root_src= /var/www/nginx/web2
  }
  server{
      listen_port= 8082
      server_name= web3.magedu.com
      root_src= /var/www/nginx/web3/
  }

5. 条件判断 when

---
- hosts: '220'
  remote_user: root
  tasks:
    - name: "shutdown redhat flavored systems"
      shell: /sbin/shudtdown -h now
      when: aisible_os_family == "RedHat"

---
- hosts: all
  remote_user: root
  tasks:
    - name: add group nginx
      tags: group 
      group: name=nginx state=present
    - name: add user nginx
      tags: user 
      user: name=nginx state=present group=nginx
    - name: install nginx
      yum: name=nginx state=present
    - name: start nginx
      service: name=nginx state=started enabled=yes
      when: ansible_distribution_major_version == "8" ## centos8 启动服务nginx,其他版本不启动

---
## 根据不同版本的 centos 上传不同版本的nginx 配置文件
- hosts: all
  remote_user: root 
  tasks:
    - name: install conf file of centos7
      template: src=nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == "7"
    - name: install conf file of centos8
      template: src=nginx.conf.c8.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == "8"
    - name: install conf file of centos6
    template: src=nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
    when: ansible_distribution_major_version == "6"

---
#根据centos fqdn 名称 来判断安装nginx 或者 httpd
- hosts: all
  remote_user: root

  tasks:
  - name: install nginx centos-220
    yum: name=nginx
    when: ansible_fqdn == "centos8.2-220"
  - name: start nginx
    service: name=nginx state=started enabled=yes
    when: ansible_fqdn == "centos8.2-220"
  - name: instal httpd centos-222
    yum: name=httpd
    when: ansible_fqdn == "centos8.2-222"
  - name: start httpd
    service: name=httpd state=started enabled=yes
    when: ansible_fqdn == "centos8.2-222"

6. with_items 迭代【当有需要重复执行的任务时,可以使用迭代机制】

对迭代的应用,固定变量名为 item ,要求 task 中使用 with_items 给定要迭代的元素列表 ;     列表元素的格式:  字符串 / 字典; 可以嵌套

---
- hosts: web
  remote_user: root
  tasks:
  - name: add several users
    user: name={{ item }} state=present groups=wheel
    with_items:
    - testuser1
    - testuesr2
##等同于下面的语句:
  - name: add user1
    uesr: name=testuser1 state=present groups=wheel
  - name: add user2
    user: name=testuser2 state=present groups=wheel

---
#remove mariadb server
- hosts: '220'
  remote_user: root
  tasks:
  - name: stop service 
    shell: /etc/init.d/mysqld stop
  - name: delete files and directory
    file: path={{ item }} state=absent 
    with_items:
    - /usr/local/mysql
    - /usr/local/mariadb-10.2.27-linux-x86_64
    - /etc/init.d/mysqld
    - /etc/profile.d/mysql.sh
    - /etc/my.cnf 
    - /data/mysql 
  - name: delete user 
    user: name=mysql state=absent remove=yes 

---
- hosts: web
  remote_user: root
  tasks:
  - name: install  some packeges
    yum: name={{ item }} state=present
    with_items:
    - nginx
    - memcached
    - php-rfm

---
- hosts: web
  remote_user: root
  tasks:
  - name: copy file
    copy: src={{ item }} dest=/tmp/{{ item }}
    with_items:
    - file1
    - file2
    - file3
  - name: yum install httpd
    yum: name={{ item }} state=present
    with_items:
    - apr 
    - apr-util
    - httpd
迭代嵌套自变量:在迭代中,还可以嵌套子变量,关联多个变量在一起使用【使用 字典 作为迭代参数】
---
- hosts: web 
  remote_user: root
  tasks:
  - name: add some groups
    group: name={{ item }} state=present
    with_items:
    - nginx
    - mysql
    - apache
  - name: add some users
    user: name={{ item.name }} group={{ item.group }} state=present
    with_items:
    - { name: 'nginx', group: 'nginx' }
    - { name: 'mysql', group: 'mysql' }
    - { name: 'apache',group: 'apache' }