• Ansible--playbook


    简介

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

    palybook核心元素
    hosts               # 执行的远程主机列表
    tasks               # 任务集
    varniables          # 内置变量或者自定义变量在playbook中调用
    templates           # 模板,可替换模板文件中的变量并实现一些简单的逻辑文件
    handlers和notify    # 两个集合使用,由特点条件触发的操作,满足条件方才执行,否则不执行
    tags                # 标签,指定某条件任务执行,用于选择运行playbook中的部分代码
                        # ansible具有幂等性,因此会自动跳过没有变化的代码,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常的长,此时,如果确信其没有变化,就可以通过tags跳过这些代码

    常用元素示例

    hosts元素

    hosts元素
    指定被控端的远程主机列表
    [root@ansible ~]# vim /root/ansible/hosts.yml
    ---
    - hosts: web
      remote_user: root
      
    在hosts后面的主机列表形式可以是单个主机的主机名、IP地址、组名,或者两个组的并集、交集、差集,比如:
    brian.com       # 单个主机名
    192.168.192.129 # 单个IP
    web             # 一个组名
    web:db          # 两个组的并集
    web:!db         # 两个组的差集
    web:&db         # 两个组的交集
    
    remote_user表示的是执行远程的用户,一般为root
    

    tasks元素

    tasks元素
    指定要执行的任务集
    [root@ansible ~]# vim /root/ansible/tasks.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: create new file
          file: name=/root/ansible/newfile state=touch
        - name: create new user
          user: name=zhujingzhi state=present system=yes shell=/sbin/onlogin
    
    这里tasks元素里面写的就是要执行的任务
    name 表示一个描述信息
    file和user表示使用的模块名,后面跟着的就是使用模块操作的具体的使用方法(这里使用file模块在/root/ansible/创建了一个新的文件,使用user模块创建了一个zhujingzhi的用户)
    

    handlers和notify元素

    handlers和notify元素
    notify元素,在tasks中的某段代码中定义,作为handlers的触发器(当tasks中的代码中触发到notify的元素,则会执行notify指定的handlers中的代码)
    handlers元素属于和tasks同级的列表,其主要作用是定义一个任务(和tasks中的任务是一样的)等待tasks中任务触发notify后执行
    [root@ansible ~]# vim /root/ansible/nginx.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx 
        - name: copy nginx config file
          copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
          notify: 
            - restart nginx
            - check service
        - name: start nginx
          service: name=nginx state=started enabled=yes
    
      handlers:
        - name: restart nginx
          service: name=nginx state=restarted
        - name: check service
          shell: killall -0 nginx > /tmp/nginx.log
    
    
    这里在运行的时候出现了在被管理机器上没有killall的命令的错误,解决方法(yum -y install psmisc)
    killall -0 nginx 的意思就是检查nginx的进程有没有启动返回0启动,返回非0服务有问题
    

    tags元素

    tags元素
    tags元素为tasks里面的任务打上一个标签,方便在执行的时候单独执行tasks里面的单独的任务和被其他调用
    [root@ansible ~]# vim /root/ansible/nginx.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx 
          tags: installnginx
        - name: copy nginx config file
          copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
          notify: 
            - restart nginx
            - check service
        - name: start nginx
          service: name=nginx state=started enabled=yes
          tags: startnginx
    
      handlers:
        - name: restart nginx
          service: name=nginx state=restarted
        - name: check service
          shell: killall -0 nginx > /tmp/nginx.log
    
    可单独执行tasks里面的startnginx任务
    [root@ansible ~]# ansible-playbook -t startnginx /root/ansible/nginx.yml 
    也可以指定两个标签执行
    [root@ansible ~]# ansible-playbook -t installnginx,startnginx /root/ansible/nginx.yml 
    
    温馨提示:
    这里多个任务也是可以使用一个标签的名字的
    比如:
    [root@ansible ~]# vim /root/ansible/nginx.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx 
          tags: nginx
        - name: copy nginx config file
          copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
          notify: 
            - restart nginx
            - check service
        - name: start nginx
          service: name=nginx state=started enabled=yes
          tags: nginx
    
      handlers:
        - name: restart nginx
          service: name=nginx state=restarted
        - name: check service
          shell: killall -0 nginx > /tmp/nginx.log
          
    使用ansible执行(加-t参数)
    [root@ansible ~]# ansible-playbook -t nginx /root/ansible/nginx.yml 
    

    vars元素

    vars元素
    vars元素指的是定义变量
    变量名:仅能由字母、数字和下划线组成,且只能以字母开头
    可以在什么地方定义变量呢?如下:
    1.ansible setup facts 远程主机的所有变量都是可以被直接调用的
    2.在/etc/ansible/hosts中定义
    普通变量:主机组中主机单独定义,优先级高于公共变量
    公共(组)变量:针对主机组中所有主机定义统一的变量
    3.通过命令行指定变量,优先级最高
    ansible-playbook -e varname=value
    4.在playbook中定义
    vars:
      - var1: value1
      - var2: value2
    5.在role中定义(role是模块化的设置模式,在role中var可以定义在一个单独的文件中)
    
    示例:
    1.ansible setup查看变量
    # 查看所有的远程主机上的可用变量
    [root@ansible ~]# ansible all -m setup
    # grep过滤查看主机名的变量
    [root@ansible ~]# ansible all -m setup | grep ansible_fqdn
    # setup模块的filter方法过滤查看主机名
    [root@ansible ~]# ansible all -m setup -a "filter=ansible_hostname"
    
    2.在/etc/ansible/hosts中定义
    [root@ansible ~]# vim /etc/ansible/hosts
    [testserver]
    192.168.192.129         http_port=8080
    
    在playbook中使用
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: set hostname
          hostname: name=brian{{ http_port }}.python.com
    
    详细的设置请查看:https://www.cnblogs.com/brianzhu/p/10188676.html
    
    3.通过命令行指定变量,优先级最高
    playbook的定义如下(使用{{}}双大括号定义中间是变量名):
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name={{ pkname1 }} 
        - name: install nginx
          yum: name={{ pkname1 }} 
        - name: copy nginx config file
          copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
        - name: start nginx
          service: name={{ pkname }} state=started enabled=yes
    
    在命令行执行指定(使用 -e 参数指定变量变量赋值的定义格式是k=v格式)
    [root@ansible ~]# ansible-playbook -e 'pkname1=nginx pkname2=vsftpd' /root/ansible/nginx.yml
    
    4.在playbook中定义
    直接是用vars元素定义变量列表
    ---
    - hosts: web
      remote_user: root
      vars:
        - pkname1: nginx
        - pkname2: vsftpd
      tasks:
        - name: install nginx
          yum: name=nginx 
        - name: copy nginx config file
          copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
        - name: start nginx
          service: name=nginx state=started enabled=yes
    
    5.将使用的变量存放到一个文件中,在playbook里面调用
    编辑变量文件
    [root@ansible ~]# cat /root/ansible/vars.yml
    var1: nginx
    var2: nsftpd
    
    在playbook中调用
    ---
    - hosts: web
      remote_user: root
      vars_files:
        - vars.yml
      tasks:
        - name: install nginx
          yum: name={{ var1 }} 
        - name: install vsftpd
          yum: name={{ var2 }} 
    

    templates元素

    templates元素
    主要是对配置文件进行远程主机的copy(能够实现根据不同的主机的配置修改不同的配置文件)
    templates 文件也是一个文本文件,嵌套有脚本(使用模板编程语言编写)
    模板文件的编程语言使用的是jinja2语言,支持下面的类型:
    字符串: 使用单引号或者双引号
    数字: 整数,浮点数
    列表: [item1,item2,..]
    元组: (item1,item2,..)
    字典: {key1:value1,key2:value2,..}
    布尔值: true/false
    
    算数运算符: +,-,*,/,//,%,**
    比较运算符: ==,!=,>,>=,<,<=
    逻辑运算符: and,or,not
    流表达式: for if when
    
    示例:
    使用nginx的打开的进程数为示例
    创建模板目录
    [root@ansible ~]# mkdir -p /root/ansible/templates
    
    编辑模板文件
    在ansible管理机上安装nginx,并copy nginx.conf到/root/ansible/templates中并改名为nginx.conf.j2(改名是必须的这个是模块的规定)
    [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx.conf.j2
    
    这里编辑nginx的模板文件将进程数**2
    修改/root/ansible/templates/nginx.conf.j2
    [root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2
    
    将 worker_processes auto;改成 worker_processes {{ ansible_processor_vcpus**2 }};
    这里ansible_processor_vcpus是使用ansible setup得到的远程主机的cpu的个数
    
    
    编写playbook
    [root@ansible ~]# vim /root/ansible/nginxtemp.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx
        - name: copy templates file
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
          notify: restart nginx
        - name: start nginx
          service: name=nginx state=started enabled=yes
    
      handlers:
        - name: restart nginx
          service: name=nginx state=restarted
    
    执行playbook
    [root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml
    
    查看结果
    这里我的机器是2个CPU的,刚刚在nginx模板文件中设置了worker_processes {{ ansible_processor_vcpus**2 }};所有最后开启的进程是4个
    [root@ansible ~]# ansible all -m shell -a "ps aux |grep nginx"
    192.168.192.129 | CHANGED | rc=0 >>
    root       6127  0.0  0.1 125092  2256 ?        Ss   17:09   0:00 nginx: master process /usr/sbin/nginx
    nginx      6128  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
    nginx      6129  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
    nginx      6130  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
    nginx      6131  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
    
    
    模板文件使用变量(改变nginx端口)
    这里把变量定义在了/etc/ansible/hosts中为每台主机定义的(也可以使用上面提到的其他方式定义变量)
    
    设置变量
    [root@ansible ~]# vim /etc/ansible/hosts 
    [web]
    192.168.192.129  http_port=8080
    
    设置模板文件
    [root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2
    修改:
    listen       {{ http_port }} default_server;
    listen       [::]:{{ http_port }} default_server;
    
    执行playbook
    [root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml
    
    查看结果
    [root@ansible ~]# ansible all -m shell -a "ss -ntl | grep 8080"
    192.168.192.129 | CHANGED | rc=0 >>
    LISTEN     0      128          *:8080                     *:*                  
    LISTEN     0      128         :::8080                    :::*            
    

    跳过错误继续执行

    作用主要是为了解决在playbook中的tasks元素中某段代码执行出现问题是否继续往下执行的一个解决的方法(其默认是出错及停止的) 
    playbook文件
    
    ---
    - hosts: web
      remote_user: root
    
      tasks: run this command and ignore the resullt
        - name: shell start nginx
          shell: /usr/bin/somecommand || /bin/true
    
    或者
    
    ---
    - hosts: web 
      remote_user: root
    
      tasks:
        - name: run this command and ignore the resullt
          shell: /usr/bin/somecommand
          ignore_errors: True
    

    流程控制语句

    when语句

    when语句
    when语句表示条件的测试,如果需要根据变量、facts或者此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句就可以实现
    示例:
    在生产环境中系统有6的和7的共存的情况,那么配置有些配置文件在不同的操作系统上是不一样的,这时候我们就要创建两个模板文件根据不同的操作系统执行不同的配置文件copy
    # 定义两个配置文件
    [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx6.conf.j2
    [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx7.conf.j2
    
    编写playbook
    [root@ansible ~]# vim /root/ansible/nginxtemp.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: install nginx
          yum: name=nginx
        - name: copy templates file for centos7
          template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
          when: ansible_distribution_major_version == '7'
          notify: restart nginx
        - name: copy templates file for centos6
          template: src=nginx6.conf.j2 dest=/etc/nginx/nginx.conf
          when: ansible_distribution_major_version == '6'
          notify: restart nginx
        - name: start nginx
          service: name=nginx state=started enabled=yes
    
      handlers:
        - name: restart nginx
          service: name=nginx state=restarted
    

    with_items语句

    with_items语法
    with_items表示迭代,当需要执行重复性的任务的时候,就可以使用迭代机制来实现
    对于迭代的引用,固定的变量名为"item"
    要在tasks中使用with_items给定要迭代的元素列表
    支持的列表格式:字符串、字典
    
    示例:
    同时执行创建多个文件的任务
    编写playbook
    [root@ansible ~]# vim /root/ansible/items.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: create file
          file: name=/root/ansible/{{ item }} state=touch
          with_items:
            - file1
            - file2
            - file3
    
        - name: install packages
          yum: name={{ item }}
          with_items:
            - htop
            - sl
            - hping3
    

    迭代嵌套子变量

    迭代嵌套子变量
    创建多个组和用户将多个用户加入到不同的组中
    编写playbook
    [root@ansible ~]# vim /root/ansible/guser.yml
    ---
    - hosts: web
      remote_user: root
    
      tasks:
        - name: add groups
          group: name={{ item }} state=present
          with_items:
            - g1
            - g2
            - g3
    
        - name: add user for goups
          user: name={{ item.name }} group={{ item.group }} state=present
          with_items:
            - { name: 'user1', group: 'g1'}
            - { name: 'user2', group: 'g2'}
            - { name: 'user3', group: 'g3'}
    

    for语句

    for语句
    最后需要使用for语句生成的例子
    server {
      listen: 81
    }
    server {
      listen: 82
    }
    server {
      listen: 83
    }
    
    这里需要使用模板文件和变量来配合使用生成
    palybook编写
    [root@ansible ~]# vim /root/ansible/testfor.yml
    ---
    - hosts: web
      remote_user: root
      vars:
        ports:
          - 81
          - 82
          - 83
    
      tasks:
        - name: create for config
          template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf
    
    模板文件编写
    [root@ansible ~]# vim /root/ansible/testfor.conf.j2
    {% for p in ports %}
    server {
      listen {{ p }}
    }
    {% enfor %}
    
    执行playbook
    [root@ansible ~]# ansible-playbook /root/ansible/testfor.yml
    
    查看结果
    [root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
    192.168.171.129 | CHANGED | rc=0 >>
    server {
      listen: 81
    }
    server {
      listen: 82
    }
    server {
      listen: 83
    }
    
    通过模板文件来获取playbook文件中的设置好的变量并通过for语句进行多次循环(playbook中使用的变量是列表的形式),这样的方式使用起来其实是很灵活的,也可以是上面的列表的形式,也可以是使用字典的形式或者列表嵌套字典的形式
    比如:
    playbook文件
    ---
    - hosts: web
      remote_user: root
      vars:
        weblist:
          - web:
            port: 81
            name: python.brian.com
            rootdir: /nginx/python
          - web2:
            port: 82
            name: php.brian.com
            rootdir: /nginx/php
    
      tasks:
        - name: create for config
          template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf
    
    模板文件
    {% for w in weblist %}
    server {
      listen {{ w.port }}
      servername {{ w.name }}
      documentroot {{ w.rootdir }}
    }
    {% endfor %}
    

    if语句

    if语句
    在for语句中使用,判断playbook中有没有设置变量,设置了生成,没有则不生成,这里只是举例子,还有其他使用的方式,比如一个变量等于大于小于多少执行什么任务等等
    
    [root@ansible ~]# vim /root/ansible/testfor.yml
    playbook文件
    ---
    - hosts: web
      remote_user: root
      vars:
        weblist:
          - web:
            port: 81
            rootdir: /nginx/python
          - web2:
            port: 82
            name: php.brian.com
            rootdir: /nginx/php
    
      tasks:
        - name: create for config
          template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf
    
    模板文件
    [root@ansible ~]# vim /root/ansible/testfor.conf.j2
    {% for w in weblist %}
    server {
      listen {{ w.port }}
    {% if w.name is defined %}
      servername {{ w.name }}
    {% endif %}
      documentroot {{ w.rootdir }}
    }
    {% endfor %}
    
    执行playbook
    [root@ansible ~]# ansible-playbook  /root/ansible/testfor.yml 
    
    查看结果
    [root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
    192.168.171.129 | CHANGED | rc=0 >>
    server {
      listen 81
      documentroot /nginx/python
    }
    server {
      listen 82
      servername php.brian.com
      documentroot /nginx/php
    }
    

    上面的示例只是少部分的流程控制语句

    温馨提示:

    上面是我在生产中常用的元素,语句,这里主要是把每个元素分开来写的,其实真正的playbook是要把上面的元素语句等结合一起使用的

  • 相关阅读:
    牛客题霸NC15求二叉树的层序遍历Java题解
    牛客题霸NC105二分查找Java题解
    .net基本性本能优化问题
    urlRewriter
    元数据MetaData
    asp.net整体运行机制详解
    asp.net整体运行机制
    asp.net页面从初始化到卸载事件顺序
    Spring表达式语言之SpEL
    Spring 学习笔记(三)之注解
  • 原文地址:https://www.cnblogs.com/brianzhu/p/10174123.html
Copyright © 2020-2023  润新知