Ansible

,1,playbook 简介

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

2,playbook 工作流程

图片名称

3,YAML 介绍

  • YAML 是一个可读性高的用来表达资料序列的格式。YAML 参考了其它多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式 RFC2822 等。Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。
  • YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种置标语言),
  • 特性
    • YAML 的可读性好
    • YAML 和脚本语言的交互性好
    • YAML 使用实现语言的数据类型
    • YAML 有一个一致的信息模型
    • YAML 易于实现
    • YAML 可以基于流来处理
    • YAML 表达能力强,扩展性好
  • 更多内容及规范参见:www.yaml.org

3.1 YAML 语法简介

  • 在单一配置文件中,可用连续三个连字号 --- 区分多个配置信息。另外选择性的连续三个点号 ... 用来表示配置文件的结尾
  • 次行开始正常写 playbook 的内容,一般建议写明 playbook 的功能
  • 使用 # 号注释代码
  • 缩进必须是统一的,不能空格和tab 混用
  • 缩进的级别也是必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
  • YAML 文件的内容和 Linux 系统大小写判断方式保持一致,是区别大小写的,key/value 的值均需要大小写敏感
  • key/value 的值可同行写也可换行写。同行使用 : 分隔
  • value 可是个字符串,也可是另一个列表
  • 一个完整的代码块功能需要最少元素需包括 name: task
  • 一个 name 只能包括一个 task
  • YAML 文件的扩展名通常为 ymlyaml
  • List:列表,其所有元素均使用 - 大头
  • 示例
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
  • Dictionary:字典,通常由多个 keyvalue 构成
  • 示例:

---
# An employee record
name: Example Developer
job: Developer
skill; Elite
  • 也可以将 key:value 放置于 {} 中进行表示,用 , 分隔多个 key:value
  • 示例
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
  • YAML的语法和其它高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用 - 来代表,Map 里的键值对用 : 分隔
  • 示例
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

4,Playbook VS ShellScripts

  • Shell 脚本
#!/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/vhosts.conf
# 启动 Apache,并设置开机自启
service httpd start
chkconfig httpd on
  • Playbook 定义
---
- hosts: all
  tasks:
    - name: "安装Apache"
      yum: name=httpd
    - name: "复制配置文件 httpd.conf"
      copy: scr=/tmp/httpd.conf dest=/etc/httpd/conf/
    - name: "复制配置文件 vhosts.conf"
      copy: scr=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
    - name: "启动Apache,并设置开机启动"
      service: name=httpd state=started enabled=true

5,playbook 核心元素

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

5.1 Hosts:

  • playbook 中的每一个 play 的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts 用于指定要执行指定任务的主机,须事先定义在主机清单中
  • 可以是如下形式:
one.example.com
one.example.com:two.example.com
192.168.1.120
192.168.1.*
  • Websrvs:dbsrvs 两个组的并集
  • Websrvs:&dbsrvs 两个组的交集
  • webservers:!phoenix 在 websrvs 组,但不在 dbsrvs 组
  • 示例
- hosts: websrvs:dbsrvs

5.2 remote_user

  • 可用于 Host 和 task 中。也可以通过指定其通过 sudo 的方式在远程主机上执行任务,其可用于 play 全局或某任务;此外,甚至可以在 sudo 时使用 sudo_user 指定 sudo 时切换的用户
- hosts: websrvs
  remote_user: root
  tasks:
    - name: tast connection
      ping:
      remote_user: test
      sudo: yes                    # 默认sudo 为 root
      sudo_suer: wang        # sudo 为 wang

5.3 task 列表和 action

  • play 的主体部分是 task list、task list 中 的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而上某 playbook 时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正 playbook 后重新执行一次即可
  • task 的目的是使用指定的参数指定模块,而在模块参数中可以使用变量。模块执行时幂等的,这意味着多次执行时安全的,因为其结果均一致
  • 每个task都应该有其 nam,用于 playbook 的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供 name,则 action 的结果将用于输出
  • task:任务列表
    • 格式:
      • 1,action: module arguments
      • 2,module: arguments 建议使用
      • 注意:shell 和 command 模块后面跟命令,而非 key=value
  • 某任务的状态在运行后为 changed 时,可通过 notify 通知给相应的 handlers
  • 任务可以通过 tags 打标签,而后可在 ansible-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
  • 或者使用 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 -vvvv 更详细
  • 示例
ansible-playbook file.yml
ansible-playbook file.yml --check    # 只检测
ansible-playbook file.yml --limit websrvs

5.3.1 playbook 示例

  • sysuser.yml
---
- hosts:all
  remote_user: root

  tasks:
  - name: create mysql user
    user: name=mysql system=yes uid=36

  - name: create a group
    group: name=httpd system=yes
  • httpd.yml
---
-hosts: websrvs
  remote_user: root

  tasks:
  - name: Install httpd
    yum: name=httpd state=present

  - name: copy configure file
    copy: src=files/httpd.conf dest=/etc/httpd/conf/

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

5.4 handlers 和 notify 结合使用触发条件

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

  tasks:
  - name: Install httpd
    yum: name=httpd state=present

  - name: copy configure file
    copy: src=files/httpd.conf dest=/etc/httpd/conf/
    notify: restart httpd

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

  handlers:
    - name: restart httpd
      service: name=httpd status=restarted
---
- hosts: websrvs
  remote_user: root

  task:
    - name: add group nginx
      tags: user
      user: name=nginx state=present

    - name: add user nginx
      user: name=nginx statepresent group=nginx

    - name: Install Nginx
      yum: name=nginx state=present

    - name: config
      copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
      notify:
        - Restart Nginx
        - Check Nginx Process

  handlers:
    - name: Restart Nginx
      service: name=nginx state=restarted enabled=yes
    - name: Check Nginx Process
      shell: killall -0 nginx > /tmp/nginx.log

5.5 playbook 中 tags

  • tags 见名之意,tags 可以帮助我们对任务进行 “打标签” 的操作,当任务存在标签以后,可以在执行 playbook 时,借助标签,指定执行哪些任务,或者指定不执行哪些任务
  • 示例
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name: Install httpd
      yum: name=httpd state=present
      tags: install,always

    - name: Install configure file
      copy: src=file/httpd.conf dest=/etc/httpd/conf/
      tags: conf,always

    - name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes
  • 在调用标签时,也可以一次性指定多个标签,调用多个标签需要用逗号隔开
ansible-playbook --tags install,service httpd.yml
  • 在调用标签之前,预览一下 playbook 中都有哪些标签,使用 --list-tags
ansible-playbook --list-tags httpd.yml
  • 如果有不想执行的任务,可以使用 --skip-tags 跳过指定的标签
ansible-playbook --skip-tags always httpd.yml

6,Playbook 中变量使用

  • 变量名:仅能有字母、数字和下划线组成,且只能以字母开头
  • 变量来源:
    • 1 ansible setup facts 远程主机的所有变量都可直接调用
    • 2 在 /etc/ansible/hosts 中定义
      • 普通变量:主机中主机单独定义,优先级高于公共变量
      • 公共(组)变量:针对主机组中所有主机定义统一变量
    • 3 通过命令行指定变量,优先级最高
      • ansible-playbook -e varname=value file.yml
    • 4 在 playbook 中定义
    • 5 在独立的变量YAML文件中定义
    • 6 在 role 中定义
  • 变量命名
    • 变量命名仅能由字母、数字和下划线组成,且只能以字母开头
  • 变量定义:key=value
    • 示例:http_port=80
  • 变量调用方式
    • 通过 {{ variable_name }} 调用变量,且变量名前后必须有空格,有时用 "{{ variable_name }}"才生效
    • ansible-playbook -e 选项指定
      • ansible-playbook test.yml -e "hosts=www user=test"

6.1 实例

  • 按照不同的方式优先级为:命令行,playbook定义变量文件,playbook定义变量,hosts定义私有变量,hosts定义公共变量

6.1.1 命令行定义

  • testvars.yml
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name:  create file
      copy: content={{ var }} dest=/tmp/file.txt
  • 执行结果
# ansible-playbook -e "var=command" testvars.yml

# ansible websrvs -m shell -a 'cat /tmp/file.txt'
192.168.2.132 | CHANGED | rc=0 >>
command

192.168.2.131 | CHANGED | rc=0 >>
command

6.1.2 在 playbook 中定义

6.1.2.1 定义变量文件

  • testvars.yml
---
- hosts: websrvs
  remote_user: root
  vars_files:
    - vars.yml

  tasks:
    - name: create file
      copy: content={{ var.content }} dest=/tmp/file.txt
  • vars.yml
var:
  content: vars.yml
  • 执行结果
# ansible-playbook testvars.yml

# ansible websrvs -m shell -a 'cat /tmp/file.txt'192.168.2.131 | CHANGED | rc=0 >>
vars.yml


192.168.2.132 | CHANGED | rc=0 >>
vars.yml

6.1.2.2 playbook 中定义变量

  • testvars.yml
---
- hosts: websrvs
  remote_user: root
  vars:
    var: {content: playbook}

  tasks:
    - name: create file
      copy: content={{ var.content }} dest=/tmp/file.txt
  • 执行结果
# ansible-playbook testvars.yml

# ansible websrvs -m shell -a 'cat /tmp/file.txt'192.168.2.132 | CHANGED | rc=0 >>
playbook

192.168.2.131 | CHANGED | rc=0 >>
playbook

6.1.3 /etc/ansible/hosts 中定义

  • testvars.yml
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name: create file
      copy: content={{ var }} dest=/tmp/file.txt
6.1.3.1 定义私有变量
  • /etc/ansible/hosts
[websrvs]
192.168.2.131 var=hosts_websrvs1
192.168.2.132 var=hosts_websrvs2
  • 执行结果
# ansible-playbook testvars.yml

# ansible websrvs -m shell -a 'cat /tmp/file.txt'
192.168.2.131 | CHANGED | rc=0 >>
hosts_websrvs1

192.168.2.132 | CHANGED | rc=0 >>
hosts_websrvs2
6.1.3.2 定义公共变量
  • /etc/ansible/hosts
[websrvs]
192.168.2.131
192.168.2.132

[websrvs:vars]
var=hosts_websrvs_vars
  • 执行结果
# ansible-playbook testvars.yml

# ansible websrvs -m shell -a 'cat /tmp/file.txt'
192.168.2.131 | CHANGED | rc=0 >>
hosts_websrvs_vars

192.168.2.132 | CHANGED | rc=0 >>
hosts_websrvs_vars

7,批量部署 zabbix-agent

  • /etc/ansible/hosts
# children 底下为父群组 zabbix-agent 的子群组
# vars底下为群组共同便变量,包括已定义变量和自定义变量

[zabbix-agent:children]    # 父群组
test1    # 子群组1
test2    # 子群组2

[test1]    # 子群组1
192.168.2.13[0:2]    # 远端服务器 IP 列表

[test1:vars]    # 子群组1 参数
ansible_ssh_user=root    # 远端 ssh 服务器用户
ansible_ssh_pass="test1123"    # 远端 ssh 服务器密码
ansible_ssh_port=22    # 远端 ssh 服务器端口

[test2]    # 子群组2
192.168.2.10[1:3]    # 远端服务器 IP 列表
192.168.2.11{1:3]    # 远端服务器 IP 列表

[test2:vars]    # 子群组2 参数
ansible_ssh_user=root    # 远端 ssh 服务器用户
ansible_ssh_pass="test2123"    # 远端 ssh 服务器密码
ansible_ssh_port=22    # 远端 ssh 服务器端口
  • zabbix-agent.yaml
---
- hosts: zabbix-agent    # /etc/ansible/hosts 群组名
  gather_facts: no    # 跳过检查
  remote_user: root    # 远端服务器用户

#  tasks:    # 任务
#    - name: judge a file or dir is exits    # 判断该文件是否存在
#      shell: /etc/zabbix/zabbix_agentd.conf
#      ignore_errors: True    # 忽略报错
#      register: result    # 定义变量

    - name: ssh-copy    # 复制 ssh 公钥到远端主机
      authorized_key: user=root key="{{ lookup('file', '/root/.ssh/id_rsa.pub')}}"
      tags:    # 标签
        - sshkey

    - name: CentOS6 install zabbix-agent rpm    # 安装 zabbix-agent 客户端 rpm 包
      yum: name=http://repo.zabbix.com/zabbix/3.0/rhel/6/x86_64/zabbix-agent-3.0.0-2.el6.x86_64.rpm state=present
      when:    # 判断系统及版本号
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "6"
#        - result|failed    # 判断该文件不存在

    - name: CentOS7 install zabbix-agent rpm
      yum: name=http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-agent-3.0.0-1.el7.x86_64.rpm state=present
      when:
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "7"
#        - result|failed    # 判断该文件不存在

    - name: configure Server IP    # 配置自动注册  zabbix-server 端IP 
      shell: sed -i 's/Server=.*/Server=192.168.2.160/' /etc/zabbix/zabbix_agentd.conf

    - name: configure ServerActive IP    # 配置自动注册  zabbix-server 端IP 
      shell: sed -i 's/ServerActive=.*/ServerActive=192.168.2.160/' /etc/zabbix/zabbix_agentd.conf

    - name: configure HostMetadata    # 配置自动注册 key/value 值
      shell: sed -i 's/# HostMetadata=/HostMetadata=zabbixs/' /etc/zabbix/zabbix_agentd.conf

    - name: system configure Hostname    # 配置当前服务器的主机名
      shell: host=`hostname`;sed -i 's/Hostname=Zabbix server/Hostname='$host'/' /etc/zabbix/zabbix_agentd.conf

    - name: start service    # 启动 zabbix-agent 服务
      service: name=zabbix-agent state=started enabled=true
  • 通过编辑 /etc/ansible/ansible.cfg 或者 ~/.ansible.cfg 来实现 跳过ssh首次连接时,提示 是否continue,需要输入yes
[defaults]
host_key_checking = False
  • 设置环境变量方式如下
export ANSIBLE_HOST_KEY_CHECKING=False
原文地址:https://www.cnblogs.com/xiaoqshuo/p/10476956.html