• Ansible详解(二)


    Ansible系列命令

    Ansible系列命令有如下:

    • ansible:这个命令是日常工作中使用率非常高的命令之一,主要用于临时一次性操作;
    • ansible-doc:是Ansible模块文档说明,针对每个模块都有详细的用法说明和应用案例介绍;
    • ansible-galaxy:可以简单的理解为Github或PIP的功能,通过ansible-galaxy,我们可以下载安装优秀个Roles;
    • ansible-playbook:是日常应用中使用频率最高的命令,其工作机制是,通过读取预先编写好的playbook文件实现批量管理;
    • ansible-pull:Ansible的另一种工作模式,pull模式,ansible默认使用push模式;
    • ansible-vault:主要用于配置文件加密;
    • ansible-console:让用户可以在ansible-console虚拟出来的终端上像Shell一样使用Ansible内置的各种命令;

    上一篇已经介绍过ansibleansible-doc的基本用法,下面再来介绍一下其他系列命令的用法。

    ansible-galaxy

    用法:ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...

    https://galaxy.ansible.com/ 上传或下载优秀的Playbook(roles)

    #列出所有已安装的galaxy
    ansible-galaxy list
    
    #安装galaxy
    ansible-galaxy install geerlingguy.redis
    
    #删除galaxy
    ansible-galaxy remove geerlingguy.redis
    

    ansible-valut

    用法:ansible-vault [create|decrypt|edit|encrypt|rekey|view] [--help] [options] vaultfile.yml

    ansible-vault encrypt hello.yml  # 加密
    ansible-vault decrypt hello.yml  # 解密
    ansible-vault view hello.yml  # 查看
    

    ansible-console

    root@mageduweb (2)[f:10] $ service name=httpd state=stopped
    
    root@mageduweb (2)[f:10] $
    执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$
    
    设置并发数: forks n  例如: forks 10
    切换组: cd groupname  例如: cd mageduweb
    列出当前组主机列表: list
    列出所有的内置模块: ?
    

    ansible-playbook

    Usage: ansible-playbook playbook.yml

    playbook就是一个用yaml语法把多个模块堆起来的一个文件而已。

    1.简介
    yaml是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。

    2.特点

    • YAML的可读性好
    • YAML和脚本语言的交互性好
    • YAML使用实现语言的数据类型
    • YAML有一个一致的信息模型
    • YAML易于实现
    • YAML可以基于流来处理
    • YAML表达能力强,扩展性好

    YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。下面是一个示例。

    - hosts: 10.1.0.1        #定义主机
          vars:                      #定义变量
               var1: value
               var2: value
          tasks:                    #定义任务
               - name:           #任务名称。
           #这里就可以开始用模块来执行具体的任务了。
    
          handlers:     #定义触发通知所作的操作。里面也是跟tasks一样,用模块定义任务。
               - name:
    
          remote_user:             #远程主机执行任务时的用户。一般都是root,一般也不用指定。
    
        - hosts: web
          vars:
          tasks:
          handlers:
          remote_user:
    

    YAML文件扩展名通常为.yaml,如example.yaml

    Playbooks:

    核心组件:

    • Hosts:执行的远程主机列表
    • Tasks:任务,由模块定义的操作的列表;
    • Varniables:内置变量或自定义变量在playbook中调用
    • Templates:模板,即使用了模板语法的文本文件;
    • Handlers:和nogity结合使用,为条件触发操作,满足条件方才执行,否则不执行;
    • Roles:角色;
    * 安装http脚本实现:
    
    #!/bin/bash
    # 安装Apache
    yum install --quiet -y httpd httpd-devel   # command: yum install --quiet -y httpd httpd-devel
    # 复制配置文件
    cp /path/to/config/httpd.conf /etc/httpd/conf/httpd.conf -f
    cp/path/to/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf -f
    # 启动Apache,并设置开机启动
    service httpd start
    chkconfig httpd on
    
    
    
    * 安装httpd ansible-playbook实现
    
    ---
    - hosts: all
      tasks:
       - name: "安装Apache"
         command: yum install --quiet -y httpd httpd-devel
       - name: "复制配置文件"
         command: cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
         command: cp /tmp/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf
       - name: "启动Apache,并设置开机启动"
         command: service httpd start
         command: chkconfig httpd on
    

    playbook的基础组件:

    Hosts:运行指定任务的目标主机;
    remote_user:在远程主机以哪个用户身份执行;
        sudo_user:非管理员需要拥有sudo权限;
    tasks:任务列表
        模块,模块参数:
            格式:
                (1) action: module arguments
                (2) module: arguments
    

    示例:
    vim test.yaml,后缀也可以是.yml

    - hosts: all
      remote_user: root
      tasks:
      - name: install a group
        group: name=mygrp system=true 
      - name: install a user
        user: name=user1 group=mygrp system=true
    
     - hosts: websrvs      
       remote_user: root
       tasks:
        - name: install httpd package
          yum: name=httpd
        - name: start httpd service 
          service: name=httpd state=started
    

    运行playbook,使用ansible-playbook命令:

    检测语法:

    • ansible-playbook –syntax-check /path/to/playbook.yaml

    测试运行,即不真正执行:

    • ansible-playbook -C /path/to/playbook.yaml
    • ansible-playbook –check /path/to/playbook.yaml
        --list-hosts
        --list-tasks
        --list-tags
    

    运行:

    • ansible-playbook /path/to/playbook.yaml
        -t TAGS, --tags=TAGS
        --skip-tags=SKIP_TAGS  跳过指定的标签
        --start-at-task=START_AT 从哪个任务后执行
    

    tags: 标签,给指定的任务定义一个调用标识;

    - name: NAME
          module: arguments
          tags: TAG_ID
    

    指定某条任务执行: ansible-playbook --tags=user useradd.yml

    - hosts: mageduweb
      remote_user: root
      
      tasks:
        - name: add group nginx
          tags: user
          user: name=nginx state=present
    
        - name: add user nginx
          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
    

    可以一次调用多个名称相同的标签。也可以调用不同的标签用 “,” 分割。

    示例:
    我们把httpd的监听端口改为8080

    用playbook把这个文件传到node3,4上

    指明标签的检查

    从标签位置开始执行

    跳过标签

    handlers 和 notify 结合使用触发条件,让playbook在满足一定触发条件时才去执行某条task

    - name: TASK_NAME
      module: arguments
      notify: HANDLER_NAME
    handlers:
    - name: HANDLER_NAME
      module: arguments
    

    第一次的话都会运行,后边如果文件内容发生改变就会触发notify,然后会直接执行handlers的内容(这里notify后边的事件就都不会执行了)。估计是md5那种的校验。删了个#号竟然也会通知。

    ---
    
    - hosts: mageduweb
      remote_user: root
      
      tasks:
        - name: add group nginx
          tags: user
          user: name=nginx state=present
    
        - name: add user nginx
          user: name=nginx state=present group=nginx
    
        - name: Install Nginx
          yum: name=nginx state=present
    
        - name: config 
          copy: src=/root/config.txt dest=/etc/nginx/config.txt
          notify:
            - Restart Nginx
            - Check Nginx Process
    
    
      handlers:
        - name: Restart Nginx
          service: name=nginx state=restarted enabled=yes
        - name: Check Nginx Process
          shell: ss -tnl | grep 80
    

    playbook 变量使用

    变量来源:
    (1)ansible setup facts远程主机的所有变量都可以用
    (2)自定义变量
    a. 在/etc/ansible/hosts 定义变量,在主机组中的主机单独定义,优先级高于组中公共变量
    b. 在/etc/ansible/hosts 定义变量,针对主机组中的所有主机集中定义变量
    c. 通过命令行指定变量,优先级最高

    在hosts Inventory(/etc/ansible/hosts)中为每个主机定义专用变量值;
    [all]
    172.16.47.103 aaa=nginx
    172.16.47.104 aaa=httpd
    
    ###############################
    - hosts: all
      remote_user: root
      tasks:
      - name: install web package
        yum: name={{ aaa }} state=latest
    
    
    (a) 向不同的主机传递不同的变量;
    
            IP/HOSTNAME variable_name=value
                [web]
                10.1.6.72 qzx=httpd
                10.1.6.73 qzx=nginx
    
    (b) 向组内的所有主机传递相同的变量 ;
    
            [groupname:vars]
            variable_name=value
    
            [web:qzx]
            qzx=httpd
    
            [web]
            10.1.6.72
            10.1.6.73
    

    变量调用方式:
    {{ variable_name }} 通过{{ }} 调用变量,且变量和{}两头之间必须有空格

    额外介绍的是:
    在playbook中调用变量时,有时"{{ variable_name }}"需要要双引号引起来方可生效,有时候必须不能用""引起来

    d.在playbook中定义,建议使用这个!

    vars:
        - var_name: value
        - var_name: value
    

    e.Inventory还可以使用参数

    用于定义ansible远程连接目标主机时使用的属性,而非传递给playbook的变量;
            ansible_ssh_host
            ansible_ssh_port
            ansible_ssh_user
            ansible_ssh_pass
            ansible_sudo_pass
            ...
    

    f.在角色调用时传递

    roles:
    - { role: ROLE_NAME, var: value, ...}
    

    templates模版

    文本文件,内部嵌套有模板语言脚本(使用模板语言编写)

    Jinja2 是由python编写的。 在我们打算使用基于文本的模板语言时,jinja2是很好的解决方案。yeml是写playbookjinja2是写配置文件模板的。

    功能:
    将模板的文件的变量值转换成对应的本地主机的确定值。例如:ansible端写一个内建变量{{ ansible_processor_vcpus }},当这个文件被复制到对应主机时会自动生成对应主机 cpu的颗数的结果替换之。

    Jinja2语法:

    字面量:
        字符串:使用单引号或双引号; 
        数字:整数、浮点数;
        列表:[item1, item2, ...]
        元组:(item1, item2, ...)
        字典:{key1:value1, key2:value2, ...}
        布尔型:true/false
    
    算术运算:
        +, -, *, /, //, %, **
    
    比较操作:
        ==, !=, >, <, >=, <=
    
    逻辑运算:and, or, not
    

    执行模板文件中的脚本,并生成结果数据流,需要使用template模块

    template:使用了Jinjia2格式作为文件模版,进行文档内变量的替换的模块。相当于copy。

    将jinja2的文件模板理解并执行,转化为各个主机间的对应值

    backup       建立个包括timestamp在内的文件备份,以备不时之需.
    dest       远程节点上的绝对路径,用于放置template文件。
    group      设置远程节点上的的template文件的所属用户组
    mode       设置远程节点上的template文件权限。类似Linux中chmod的用法
    owner      设置远程节点上的template文件所属用户
    src        本地Jinjia2模版的template文件位置。
    

    注意:此模板不能在命令行使用,而只能用于playbook;用法同copy

    (1) templates文件必须存放于目录名为templates下,且命名为 .j2 结尾
    (2)yaml/yml playbook文件需和templates目录平级,目录结构如下:
        ./
        ├── temnginx.yml
        └── templates
            └── nginx.conf.j2
    

    案例1:

    // templates/nginx.conf.j2
    
    {% for vhost in  nginx_vhosts %}
    server {
       listen {{ vhost }}
    
    }
    
    {% endfor %}
    
    
    // temnginx.yml
    ---
    
    - hosts: mageduweb
      remote_user: root
      vars:
        nginx_vhosts:
          - web1
          - web2
          - web3
      #  nginx_vhosts:
      #    - listen: 8080
      
    
    
      tasks:
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    

    生成的结果:

    server {
       listen web1
       
    }
    
    
    server {
       listen web2
       
    }
    
    server {
       listen web3
       
    }
    
    案例2:
    
    shell脚本与Jinja语法对比:
    -- shell脚本中写法
    for i in {1..10}
    do
       con
    done
    
    
    if [ xx ];then
        con
    elif
         con
    else
        con
    fi
    
    
    -- Jinja写法:
    
    //  templates/nginx.conf.j2
    
    {% for vhost in  nginx_vhosts %}
    server {
       listen {{ vhost.listen  }}
    
    }
    
    {% endfor %}
    
    * 生成的结果
    
    server {
       listen 8080
       
    }
    
    
    
    * playbook调用文件
    //  temnginx.yml
    
    ---
    
    - hosts: mageduweb
      remote_user: root
      vars:
        nginx_vhosts:
          - listen: 8080
    
    
    
      tasks:
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
    
    * 案例3
    
    // temnginx.yml
    
    ---
    
    - hosts: mageduweb
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8080
            server_name: "web1.magedu.com"
            root: "/var/www/nginx/web1/"
          - web2:
            listen: 8080
            server_name: "web2.magedu.com"
            root: "/var/www/nginx/web2/"
          - web3:
            listen: 8080
            server_name: "web3.magedu.com"
            root: "/var/www/nginx/web3/"
    
    
      ## 案例1
      #  nginx_vhosts:
      #    - web1
      #    - web2
      #    - web3
      ## 案例2
    
    
    
      tasks:
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
    
    
    
    // templates/nginx.conf.j2
    
    {% for vhost in  nginx_vhosts %}
    server {
       listen {{ vhost.listen }}
       server_name {{ vhost.server_name }}
       root  {{ vhost.root }}
       
    }
    
    {% endfor %}
    
    
    
    * 生成结果:
    
    server {
       listen 8080
       server_name web1.magedu.com
       root  /var/www/nginx/web1/
       
    }
    
    server {
       listen 8080
       server_name web2.magedu.com
       root  /var/www/nginx/web2/
       
    }
    
    
    server {
       listen 8080
       server_name web3.magedu.com
       root  /var/www/nginx/web3/
       
    }
    
    
    * 案例4
    // templates/nginx.conf.j2
    
    {% for vhost in  nginx_vhosts %}
    server {
       listen {{ vhost.listen }}
    
       {% if vhost.server_name is defined %}
       server_name {{ vhost.server_name }}
       {% endif %}
    
       root  {{ vhost.root }}
    
    }
    
    {% endfor %}
    
    
    
    
    // temnginx.yml
    
    ---
    
    - hosts: mageduweb
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8080
            #server_name: "web1.magedu.com"
            root: "/var/www/nginx/web1/"
          - web2:
            listen: 8080
            server_name: "web2.magedu.com"
            root: "/var/www/nginx/web2/"
          - web3:
            listen: 8080
            server_name: "web3.magedu.com"
            root: "/var/www/nginx/web3/"
    
    
      ## 案例1
      #  nginx_vhosts:
      #    - web1
      #    - web2
      #    - web3
      ## 案例2
    
    
    
      tasks:
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    
    
    * 执行命令
    
    ansible-playbook temnginx.yml
    
    
    * 生成的结果
    
    server {
       listen 8080
    
    
       root  /var/www/nginx/web1/
    
    }
    
    server {
       listen 8080
    
          server_name web2.magedu.com
    
       root  /var/www/nginx/web2/
    
    }
    
    server {
       listen 8080
    
          server_name web3.magedu.com
    
       root  /var/www/nginx/web3/
    
    }
    
    
    ### ansible-playbook when条件判断
    
    
    ---
    
    - hosts: mageduweb
      remote_user: root
    
      tasks:
        - name: add group nginx
          tags: user
          user: name=nginx state=present
    
        - name: add user nginx
          user: name=nginx state=present group=nginx
    
        - name: Install Nginx
          yum: name=nginx state=present
    
        - name: restart Nginx
          service: name=nginx state=restarted
          when: ansible_distribution_major_version == "6"
    
    ### ansible-playbook with_items 列表
    
    ---
    
    - hosts: mageduweb
      remote_user: root
    
      tasks:
      - name: create rsyncd file
        copy: src={{ item }} dest=/tmp/{{ item }}
        with_items:
          - a
          - b
          - c
          - d
    
    
      - name: yum install httpd
        yum: name={{ item }}  state=present 
        with_items:
          - apr
          - apr-util
          - httpd
    
    
    
    * with_itmes 嵌套子变量
    
    ---
    
    - hosts: mageduweb
      remote_user: root
    
    
      tasks:
      - name: add several users
        user: name={{ item.name }} state=present groups={{ item.groups }}
        with_items:
          - { name: 'testuser1' , groups: 'wheel'}
          - { name: 'testuser2' , groups: 'root'}
    
    

    1、普通示例:

    这里/root/nginx.conf内容发生了改变。

      - hosts: ngxsrvs
        remote_user: root
        tasks:
        - name: install nginx package
          yum: name=nginx state=latest
        - name: install conf file
          template: src=/root/nginx.conf.j2 dest=/etc/nginx/nginx.conf
          tags: ngxconf
          notify: reload nginx service
        - name: start nginx service
          service: name=nginx state=started enabled=true
        handlers:
        - name: reload nginx service
          shell: /usr/sbin/nginx -s reload
    

    2、条件测试:

    when语句:在tasks中使用,Jinja2的语法格式;

    -     hosts: all
        remote_user: root
        tasks:
        - name: install nginx package
          yum: name=nginx state=latest
        - name: start nginx service on CentOS6
          shell: service nginx start
          when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
        - name: start nginx service
          shell: systemctl start nginx.service
          when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
    

    3、循环:迭代,需要重复执行的任务;

    对迭代项的引用,固定变量名为"item”,使用with_item属性给定要迭代的元素; 这个是以任务为中心,围绕每个任务来跑主机,如果中间某个任务中断,那么所有主机以后的任务就无法安装。

    元素:

    • 列表
    • 字符串
    • 字典

    基于字符串列表给出元素示例:

    -   hosts: websrvs
        remote_user: root
        tasks:
        - name: install packages
          yum: name={{ item }} state=latest
          with_items:
          - httpd
          - php
          - php-mysql
          - php-mbstring
          - php-gd
    

    基于字典列表给元素示例:item.name .后边的表示键

    - hosts: all
      remote_user: root
      tasks:
      - name: create groups
        group: name={{ item }} state=present
        with_items:
        - groupx1
        - groupx2
        - groupx3
      - name: create users
        user: name={{ item.name }} group={{ item.group }} state=present
        with_items:
        - {name: 'userx1', group: 'groupx1'}
        - {name: 'userx2', group: 'groupx2'}
        - {name: 'userx3', group: 'groupx3'}
    

    角色:roles

    以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等;相当于函数的调用把各个事件切割成片段来执行。

    mkdir ./{nginx,memcached,httpd,mysql}/{file,templates,vars,handlers,meta,default,tasks} -pv
    

    role_name/

        files/:存储由copy或script等模块调用的文件; 
    
        tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;
    
        handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
    
        vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
    
        templates/:存储由template模块调用的模板文本;
    
        meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
    
        default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
    

    在playbook中调用角色的方法:

    - hosts: HOSTS
      remote_user: USERNAME
      roles:
      - ROLE1
      - ROLE2
      - { role: ROLE3, VARIABLE: VALUE, ...}
      - { role: ROLE4, when: CONDITION }
    

    事例: 基于角色的方式安装 nginx

    1.创建需要的文件

    mkdir ./{nginx,memcached,httpd,mysql}/{files,templates,vars,handlers,meta,default,tasks} -pv
    

    2.复制相应的安装包和模板到对应目录下

    3.写tasks/下的主main.yml

    - name: copy nginx package
      copy: src=nginx-1.10.0-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.0-1.el7.ngx.x86_64.rpm
    
    - name: install nginx package
      yum: name=/tmp/nginx-1.10.0-1.el7.ngx.x86_64.rpm  state=present
    
    - name: install nginx.conf file
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      tags: ngxconf
      notify: reload nginx service
    
    - name: install default.conf file
      template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
      tags: ngxconf
      notify: reload nginx service
    
    - name: start nginx service
      service: name=nginx enabled=true state=started
    

    4.根据需要修改nginx的配置文件模板。(这里改的是work进程生成数和监听的端口)

    5.写handlers目录和vars/下的main.yml 文件

    6.写需要运行的主yml文件

    7.测试

    8.运行

    安装成功

    9.改端口测试,通过传递参数方式

    修改成功!!!

    推荐资料

    http://galaxy.ansible.com
    https://galaxy.ansible.com/explore#/
    http://github.com/
    http://ansible.com.cn/
    https://github.com/ansible/ansible
    https://github.com/ansible/ansible-examples

    最后打个广告,Stanley老师的Ansible权威指南,你,值得拥有

    个人站点:www.ilurker.cn
  • 相关阅读:
    初识MVC web框架--Controller与View交互1
    Web框架UI系列--MVC常用控件讲解
    管理大师__Vuex
    语言国际化----vue-i18n
    uniapp动态获取高度
    vue__双向数据绑定v-model
    vue__模板解析3一般指令解析
    vue__模板解析2:事件指令解析
    vue__模板解析:大花括号表达式解析
    vue__数据代理
  • 原文地址:https://www.cnblogs.com/ilurker/p/6421637.html
Copyright © 2020-2023  润新知