04-Ansible-Playbook

500 阅读6分钟

playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。

核心元素

  1. hosts:执行的远程主机列表
  2. tasks:任务,由模板定义的操作列表
  3. vars:变量,内置变量或者自定义变量在playboook中调用
  4. templates:模板,即 使用模板语法的文件;可替换模板中的变量并实现一些简单逻辑的而文件
  5. handlers:和notify结合使用 ;当某条件满足时,触发执行的操作
  6. tags:标签,指定某条件下,用于选择运行playbook中的部分代码。Ansible具有幂等性,因此会自动跳过没有变化的部分,有些业务执行比较长,如果确认没有问题就可以通过tags跳过这些片段
  7. roles:角色

基础组件

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

    形式如下:

    - hosts: websrvs
    
  2. remote_user:可用于hosts和tasks中,也可以通过指定sudo的方式在远程主机上执行,其可用于paly全局或某任务;此外甚至可以在sudo时使用sudo_user指定sudo时切换的用户

    - hosts: 192.168.176.128	
      remote_user: root
    
  3. tasks:任务列表;格式有两种:

    action: module argument
    module: argument    
    

    建议使用第二种
    特别注意:shell和command模块后面跟命令,而非key=value 某任务的状态在运行后changed时,可通过‘notify’通知给相应的handlers 任务可以通过‘tags’打标签,而后可在absible-playbook命令上使用-t指定进行调用

---
tasks:
  - name: disable selinux
    command: /sbin/setenforce 0
---
# 如果命令或者脚本的退出码不为零,可以使用以下方式替代
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true
---
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

yaml语法

YAML的语法和其他高阶语言类似并且可以简单表达清单、散列表、标量等数据结构,其结构通过空格来展示。(列表用横杆表示,键值对用冒号分割,键值对里又可以嵌套另外的键值对),YAML文件扩展名通常为.yaml或者.yml;

name: twp   #冒号后有空格
age: 31
gender: male
spouse:
  name: devil
  age: 21
  gender: female
children:
  - name: xiaobai   #横杠后有空格
    age: 4
    gender: femle
  - name: xiaohuang
    age: 1
gender: male

playbook的运行方式

ansible-playbook <filename.yaml> ... [options]
常用选项:
--check 只检测可能会发生的改变,但不真正执行操作
--list-hosts 列出运行任务的主机
--limit 主机列表,只针对主机列表中的主机执行
-v 显示过程 -vv -vvv 更详细
ansible-playbook file.yaml --check 只检测
Ansible-playbook file.yaml 执行
Ansible-playbook file.yaml --limit websevs 仅websevs主机执行

handles和notify结合条件使用

Handlers:是task列表,这些task与前述的task并没有本质的区别,用于当关注的资源发生变化时,才会采取一定的操作 Notify:此action被用于每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,尽在所有变化发生后完成一次性的执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。 示例: Handles和notify的使用:

- hosts: httpd
  remote_user: root
  tasks:
   - name: add group apache
     group: name=apache gid=180 system=yes
     
   - name: add user apache
     user: name=apache uid=180 group=apache system=yes

   - name: install httpd package
     yum: name=apache

   - name: copy vhost.conf file
     copy: src=vhost.conf dest=/etc/httpd/conf.d/vhost.conf
     notify:
      - restart httpd
    handlers:
     - name: restart httpd    #必须和notify中定义的名字一致
       service: name=httpd status=restarted enabled=yes

Tags的使用

- hosts: h
  remote_user: root

- tasks:
    name: install httpd
    yum: name=httpd
    
- name: copy conf file
    copy: src=files/vhost.conf dest=/etc/httpd/conf/vhost.conf
    tags: conf

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

playbook中变量使用

变量

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

  1. ansible setup 模块下的变量都可以使用
  2. /etc/ansible/hosts中定义的 普通变量:主机组中主机单独定义,优先级高于公共变量 公共组变量:针对主机组中所有的主机定义统一变量
  3. 通过命令行指定变量,优先级最好 ansible-playbook -e varname=value
  4. 在playbook中定义 var: var1: value1 var2: value2
  5. 在role中定义

变量的调用方式

  1. 通过{{ variable_name }}调用变量,且变量名前后必须有空格,有时候使用”{{ variable_name }}”才能生效
  2. anible-playbook -e 选项指定 ansible-playbook -e "hosts=httpd user=apache" httpd.yaml

使用变量

  1. 使用变量文件
# vcat vars.yaml 
web01: httpd
web02: nginx

# cat vars.yaml
- hosts: 192.168.176.128
  remote_user: root
  vars_files:
    - vars.yaml
  tasks:
    - name: create httpd configfile
      file: name={{ web01 }}.conf state=touch   #默认创建在当前用户下
    - name: create nginx configfile
      file: name={{ web02 }}.conf state=touch
  1. 使用setup变量

    cat vars.yaml
    - hosts: 192.168.176.128
    remote_user: root
    
    tasks:
    - name: create hosts file
      file: name=/etc/ansible/{{ ansible_fqdn }} state=touch  #{{ ansible_fqdn }}为setup模块中域名的一个内置变量
    
  2. 命令行使用变量

    # cat vars.yaml
    - hosts: 192.168.176.128
    remote_user: root
    
    tasks:
    - name: install nginx package
      yum: name={{ nginx }} 
    
    # ansible-playbook -e nginx=nginx vars.yaml
    

模板文件templetes

文本文件,嵌套有脚本(使用模板编程语言编写) Jinja2语音,使用 字面量,有下面形式 字符串:使用单引号或者双引号 数字:整数、浮点数 列表:[haha,xixi,hehe,lele] 元组:(haha,xixi,hehe,lele) 字典:{name:wkx,gender:male} 布尔型:true、false 算术运算:+、-、*、/、//、%、** 分别是加减乘除整除求余幂 比较操作:==,!=,>,<,>=,<= 逻辑运算:and,or,not 流表达式:for,if,when

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

cat > vars.yaml << EOF
- hosts: 192.168.176.128
  remote_user: root

  tasks:
  - name: echo 123
    command: echo 123
    when: ansible_fqdn == "kube-master01"
EOF

迭代嵌套自变量

- hosts: 192.168.176.128
  remote_user: root

  tasks:
  - name: create files
    file: name=/opt/ansible/{{ item }}.txt state=touch  #创建文件,嵌套变量在下面
    when: ansible_fqdn == "kube-master01"  #匹配条件,条件满足时执行
    with_items:
      - xiaobai
      - xiaohong
      - xiaohuang
  - name: install some packages
    yum: name={{ item }}
    with_items:
      - lrzsz
      - net-tools
---
- hosts: 192.168.176.128
  remote_user: root

  tasks:
  - name: create test groups
    group: name={{ item }} 
    when: ansible_fqdn == "kube-master01"
    with_items:
      - xiaobai
      - xiaohong
      - xiaohuang
  - name: cerate test users
    user: name={{ item.name }} group={{ item.group }} system=yes
    with_items:
      - { user: "xiaobai",group: "xiaobai"}
      - { user: "xiaohong",group: "xiaohong"}
      - { user: "xiaohuang",group: "xiaohuang"}

Playbook中template循环嵌套,跟python模板语言一致;

{% for user in user_list %}
	{{ user }};
{% endfor %}

{% if user.userid is defined %}
	{{ user.userid }};
{% endif %}

{% if user.username is defined %}
	{{ user.username }}
{% endif %}


---
- hosts: web
  remote_user: root
  vars:
    - nginx_ports:
        - 80
        - 443
  tasks:
    - name: templete configfile
      template: src=/opt/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf

cat nginx.conf.j2
{% for port in nginx_ports %}
server {
  listen {{ port }}
  server_name {{ ansible_fqdn }}
}
{% endfor %}

ansible-playbook安装nginx服务

- hosts: 192.168.176.128
  remote_user: root

  vars:
    - group: nginx
    - user: nginx
    - package: nginx
    - service: nginx
  tasks:
    - name: add group {{group}}
      group: name={{group}} gid=80 system=yes

    - name: add user {{user}}
      user: name={{user}} uid=80 group={{group}} shell=/sbin/nologin system=yes

    - name: install {{package}} package
      yum: name={{package}}

    - name: create html directory
      file: path=/etc/nginx/html state=directory
       
    - name: copy index.html file
      copy: src=/opt/ansible/index.html dest=/etc/nginx/html/index.html 
       
    - name: templates configfile
      template: src=/opt/ansible/nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=644
      notify: 
        - restarted {{service}} service
       
    - name: start {{service}} service
      service: name={{service}} state=started enabled=yes 
      #when: ansible_fqdn="kube-master01"
    
  handlers:
    - name: restarted {{service}} service
      service: name={{service}} state=restarted