• 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
    
  • 相关阅读:
    数据结构3——图
    数据结构2——树
    数据结构1——堆栈和队列
    最大流——Dinic算法
    最大流——EK算法
    网络流——poj1273(入门)
    网络流(进阶)
    网络流
    并查集——poj1182(带权并查集高阶)
    并查集——poj1308(并查集延伸)
  • 原文地址:https://www.cnblogs.com/xiaoqshuo/p/10476956.html
Copyright © 2020-2023  润新知