ansible配置详解及基本示例

ansible:
    http://www.ansible.com
    http://www.ansible.com.cn

    主要功能:
        1.批量的系统部署;
        2.批量的程序部署;
        3.批量的运行命令;

    运维工具的分类:
        agentless:无代理端程序,通过依赖于SSH协议;
            ansible,fabric,saltstack;
        agent:基于代理程序实现安全通信;
            puppet,Zabbix,func;

    ansible的特性:
        1.模块化:ansible核心仅仅提供了一组命令行工具(框架),真正的运维管理功能需要各个模块来实现;
        2.基于python语言开发实现的,需要有Paromiko,jinja2,PyYMAL三个关键模块的支持;
        3.Agentless,部署简单,默认依靠SSH协议;
        4.支持自定义模块;
        5.支持playbook;
        6.快速失败,执行效率O(1),幂等性;

    ansible应用程序的结构:
        ansible核心:提供核心命令行工具;
        Host Inventory:主机清单,指定ansible能够操纵和管理的主机列表及分组情况;
        Playbook:剧本,可以重复执行或同时执行一个或多个任务的具有YAML语言的格式的文件文件;一般,文件的后缀名称为:.yml或.yaml;
        modules:
            核心模块;
            自定义模块;
        插件:
            连接器插件:在与后端被管设备进行通信之前用于建立通信会话连接的插件;
            邮件发送的插件
            日志记录的插件

    ansible的安装:
        到目前为止,ansible的rpm包只能由EPEL源提供;

        使用yum命令来安装即可;(CentOS 7.5(1803))
            # yum install ansible

    ansible的程序环境:
        主配置文件:/etc/ansible/ansible.cfg
        主机清单文件:/etc/ansible/hosts
        主程序:
            /usr/bin/ansible
            /usr/bin/ansible-doc
            /usr/bin/ansible-playbook

    主机清单的文件格式:
        1.单纯的主机列表:
            将主机名或IP地址按照每行一个的格式写入/etc/ansible/hosts文件;
        2.主机分组:
            [websrvs]
            IP_ADDR1
            ...
            HOSTNAME1
            ...

            [dbsrvs]
            IP_ADDR2
            ...
            HOSTNAME2
            ...

            [ha]
            172.16.72.2
        3.主机范围表示:
            web01-web10
            web[01:10]
            172.16.72.[2:10]

    ansible命令:
        ansible - Define and run a single task 'playbook' against a set of hosts

        格式:
            ansible <host-pattern> [options]

            常用选项:
                -a MODULE_ARGS, --args MODULE_ARGS
                    在使用某些模块时,用于指定该模块所需要的参数;
                -e, --extra-vars
                    在ansible的命令行中用于设置执行ansible任务时的自定义变量;
                -m MODULE_NAME, --module-name MODULE_NAME
                    在执行ansible任务时,所选择使用的模块;如果未给出该选项,默认选择使用"command"模块;
                -C, --check
                    并不真正的在被管主机上运行任务,而是测试看结果是否会发生改变;

    ansible-doc命令:
        ansible-doc - plugin documentation tool
        格式:
            ansible-doc [-l|-F|-s] [options] [-t <plugin type> ] [plugin]

            常用选项:
                -l, --list:
                    列表显示当前所有可用的ansible模块;
                -s, --snippet:
                    获取模块的使用规则,其结果通常是剧本中的用法;

    常用的ansible模块:
        1.command模块:
            Executes a command on a remote node

            示例:
                # ansible all -m command -a "useradd testuser01"
                # ansible all -m command -a "id testuser01"

        2.shell模块:
            Execute commands in nodes.

            示例:
                # ansible all -m shell -a "echo qhdlink | passwd --stdin testuser01"

        3.user模块:
            Manage user accounts

            常用的参数:
                name: 指定欲管理的用户账户名称;必选参数;
                create_home: 是否为用户创建家目录,除非显式给出"no"值,默认创建;
                system: 是否将用户创建为系统用户;
                uid: 为指定的用户指定一个固定的UID;
                group: 为指定的用户指定一个主要组;
                groups: 为指定的用户添加一个附加组;
                state: 此次ansible任务的执行状态;必选参数;
                    present:创建;
                    absent:删除;
                force: 当state=absent时,该任务相当于"userdel --force";
                remove: 当state=absent时,该任务相当于"userdel --remove | userdel -r";
                shell: 为指定的用户指定一个默认登录shell;

            示例:
                # ansible all -m user -a "name=testuser02 system=yes uid=333 create_home=no shell=/sbin/nologin state=present"
                # ansible all -m user -a "name=testuser01 state=absent remove=yes"

        4.group模块:
            Add or remove groups

            常用的参数:
                gid: 为指定组名的组指定一个GID;
                name: 指定组名;必选参数
                state: 此次ansible任务的执行状态;必选参数;
                    present:创建;
                    absent:删除;
                system: 是否将组设置为系统组;

            示例:
                # ansible all -m group -a "name=qinhuangdao system=yes gid=345 state=present"
                # ansible all -m group -a "name=qinhuangdao state=absent"

        5.copy模块:
            Copies files to remote locations

            常用的参数:
                dest: 此次ansible的复制任务的目标位置,必须用绝对路径表示;
                    注意:
                        1.如果src指定的路径是目录,则dest必须指定目录;
                        2.如果dest的路径是以"/"做结尾或src是一个目录时,若dest不存在,则创建;
                        3.如果src和dest都是文件,若dest表示的路径中有目录不存在,则不会创建并报告错误;
                src: 此次ansible的复制任务的源文件的位置,可以使用相对路径也可以使用绝对路径;
                    注意:
                        1.如果src所指定的路径是以"/"结尾,仅复制该目录下的文件到目标位置;
                        2.如果src所指定的路径不以"/"结尾,就会复制所有路径中包含的目录的内容到目标位置;类似于rsync;
                mode: 设置目标位置文件的权限属性;
                owner: 设置目标位置文件的属主;
                group: 设置目标位置文件的属组;
                force: 如果目标位置文件已经存在,是否覆盖;默认为yes;

            示例:
                # ansible websrvs -m copy -a "content='hello\neverybody\n' force=yes dest=/tmp/hello.txt mode=0600 owner=testuser02"
                # ansible websrvs -m copy -a "src=/etc/yum.repos.d/CentOS-Base.repo dest=/tmp owner=ftp group=daemon mode=0640"

        6.cron模块:
            Manage cron.d and crontab entries

            常用的参数:
                name: cron任务的名称;在删除时必须指定,创建时如果不指定,则自动创建一个新的cron任务;
                month: 月份;
                day: 天;
                hour: 小时;
                minute: 分钟;
                weekday: 星期;
                job: 此次定义的工作的具体内容,即:命令;
                state:
                    present:创建;
                    absent:删除;
                user: 指定此次修改的计划任务的所有者;

            示例:
                # ansible all -m cron -a "name='Update Time' minute=*/10 job='/usr/sbin/ntpdate 172.16.72.1 &> /dev/null' state=present"
                # ansible all -m cron -a "name='Update Time'  state=absent"

        7.hostname模块:
            Manage hostname

            参数:
                name: 指定主机名;

            注意:如果直接拿来设置主机名,会导致所有主机同名;绝大多数情况下,会结合变量进行主机名的设置,以保证不同的主机被设置不同的主机名;

            示例:
                # ansible 172.16.72.3 -m hostname -a "name=web1.qhdlink.com"

        8.script模块:
            Runs a local script on a remote node after transferring it

            示例:
                # ansible websrvs -m script -a "/root/test.sh"

        9.service模块:
            Manage services

            常用的参数:
                name: 指定要管理的服务的名称;
                enabled: 设置要管理的服务是否随操作系统启动而启动;
                state:
                    started
                    stopped
                    restarted
                    reloaded

            示例:
                # ansible websrvs -m service -a "name=httpd enabled=yes state=started"

        10.yum模块:
            Manages packages with the `yum' package manager

            常用的参数:
                name: 指定此次要管理的程序包的名称,还可以加上版本号;如果想要一次管理多个程序包,可以使用","分隔程序包名称的列表;
                state:
                    `present' or `installed', `latest' :都表示安装;
                    `absent' or `removed' :都表示卸载;
            示例:
                # ansible websrvs -m yum -a "name=httpd,php-fpm state=present"

        11.setup模块:
            Gathers facts about remote hosts

            示例:
                # ansible 172.16.72.3 -m setup


playbook:
    批量运行多个相关联或无关联的任务的一种策略实施方法;
    playbook的文件格式为YAML格式的文件,通常使用的后缀名称为.yml或.yaml;


{{
                YAML介绍
                YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。
                    YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。其特性:
                        YAML的可读性好
                        YAML和脚本语言的交互性好
                        YAML使用实现语言的数据类型
                        YAML有一个一致的信息模型
                        YAML易于实现
                        YAML可以基于流来处理
                        YAML表达能力强,扩展性好
                        更多的内容及规范参见http://www.yaml.org
                 YAML语法
                    YAML的语法和其他高阶语言类似,并且可以简单表达列表、数据字典、键值对等数据结构。其结构(Structure)通过空格来展示,列表里的项用"-"来代表,数据字典里的键值对用":"分隔。


   }}




    list

        列表的所有元素均使用“-”打头,例如:
        # A list of tasty fruits
        - Apple
        - Orange
        - Strawberry
        - Mango

    dictionary

        字典通过key与value进行标识,例如:
        ---
        # An employee record
        name: Example Developer
        job: Developer
        skill: Elite

        也可以将key:value放置于{}中进行表示,例如:
        ---
        # An employee record
        {name: Example Developer, job: Developer, skill: Elite}

    下面是一个示例。

        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

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

    playbook的核心元素:基本结构;
        - hosts:
            remote_user:
            vars:
                var1: value1
                var2: value2
            tasks:
                - name1:
                    module_name:
                    tags:
                    notify:
                - name2
                    ...
                ...
            roles:
                - role_name1
                - role_name2
                ...
            handlers:

    ansible-playbook命令:
        ansible-playbook - Runs Ansible playbooks, executing the defined tasks on the targeted hosts.

        格式:
            ansible-playbook [options] playbook.yml [playbook2 ...]

            常用选项:
                -C, --check
                    测试运行剧本中任务,不做任何改变;
                -e, --extra-vars
                    在命令行中设置额外的变量或者修改某个指定的变量的值;
                -t, --tags
                    指明只运行那些与指定的标记匹配的任务;

测试playbook的示例:
- hosts: all
  remote_user: root
  tasks:
  - name: create group agroup1
    group: name=agroup1 gid=455 system=yes
  - name: create user auser1
    user: name=auser1 uid=456 system=yes create_home=no group=agroup1

利用playbook部署nginx应用:
- hosts: websrvs
  remote_user: root
  tasks:
  - name: copy openssl packages
    copy: src=../files/openssl/ dest=/root/
  - name: install openssl new version
    yum: name=/root/openssl-1.0.2k-12.el7.x86_64.rpm,/root/openssl-libs-1.0.2k-12.el7.x86_64.rpm state=latest
  - name: install nginx package
    yum: name=nginx state=present
  - name: provide nginx config file
    copy: src=../files/nginx.conf dest=/etc/nginx/nginx.conf
  - name: start nginx service
    service: name=nginx state=started enabled=true

  注意:
      1.CentOS 7.2上的openssl版本较低,不能适用于nginx-1.12.2版本,所以需要提供更高版本的openssl,在CentOS 7.5发行版中没有此类问题;
      2.copy模块不能复制多个文件,复制目录即可;
      3.在指定的目录中(/etc/ansible/files)准备好要复制的文件,包括:
          openssl相关程序包
          nginx.conf配置文件

    运行playbook:
        ansible-playbook [--check] /path/to/yml_file

    handlers:
        处理器;
        事实上,handlers也是定义了任务,但该任务并非每次都必然被执行,只是在特殊的条件下触发执行;在ansible中,特殊条件一般是指handlers接收到了其他任务发送的通知信息;

示例:
- hosts: websrvs
  remote_user: root
  tasks:
  - name: copy openssl packages
    copy: src=../files/openssl/ dest=/root/
  - name: install openssl new version
    yum: name=/root/openssl-1.0.2k-12.el7.x86_64.rpm,/root/openssl-libs-1.0.2k-12.el7.x86_64.rpm state=latest
  - name: install nginx package
    yum: name=nginx state=present
  - name: provide nginx config file
    copy: src=../files/nginx.conf dest=/etc/nginx/nginx.conf
    notify: reload nginx config
    tags: provconf
  - name: start nginx service
    service: name=nginx state=started enabled=true
  handlers:
  - name: reload nginx config
    service: name=nginx state=reloaded

  变量:variables
      变量的定义方式:
          1.facts:利用setup模块从被管设备上取回的变量,可以直接使用;
              注意:如果使用ansible命令行工具向被管设备执行任务时,默认并没有可用的facts变量;只有在运行ansible-playbook命令执行playbook时,首先回获取被管设备上的facts变量,从而可以直接调用;

              如果想要调用facts变量,都需要在playbook中调用;

          2.在hosts inventory中定义变量:
              1) 为不同的主机定义同一变量的不同变量值;

              示例:在/etc/ansible/hosts文件中定义;
                  [websrvs]
                    172.16.72.3 nname=www1.qhdlink.com
                    172.16.72.4 nname=www2.qhdlink.com

                    # ansible websrvs -m hostname -a "name={{ nname }}"

                2) 向某个主机组中传递变量值:

                示例:
                    [websrvs:vars]
                    ngx_port=80

                    在templates中调用生效;

            3.在ansible命令行或ansible-playbook命令行中通过-e选项传递变量值;
                -e var1=value1 -e var2=value2 ...

            4.在YAML格式的playbook文件中定义并引用;
                    vars:
                        var1: value1
                        var2: value2
                        ...

            5.在roles中定义变量;

            6.在playbook中调用roles时,向roles传递变量值;

            7.inventory内置参数:
                ansible_ssh_host
                    将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

                ansible_ssh_port
                    ssh端口号.如果不是默认的端口号,通过此变量设置.

                ansible_ssh_user
                    默认的 ssh 用户名

                ansible_ssh_pass
                    ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

                ansible_sudo_pass
                    sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

                ansible_sudo_exe (new in version 1.8)
                    sudo 命令路径(适用于1.8及以上版本)

                ansible_connection
                    与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.

                ansible_ssh_private_key_file
                    ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

                ansible_shell_type
                    目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.

                ansible_python_interpreter
                    目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如  \*BSD, 或者 /usr/bin/python
                    不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
                    与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....

        变量调用的方式:
            {{ var_name }}

        12.template模块:
            Templates a file out to a remote server

                模板文件:纯文本文件,嵌套了某种编程语言脚本代码的文本文件;

                python语言将自身代码嵌套进纯文件文件的脚本语言,Jinja2;以"j2"后缀命名的文件;

                在jinja2脚本文件中,表达式的最简单的表现形式,称为"字面量";

                字面量:
                    字符串:通常是使用单引号或双引号引用的内容;
                    列表:可变化的数据结构;
                        [item1, item2, ...]
                    元组:不可变数据结构;
                        (item1, item2, ...)
                    字典:
                        {key1: value1, key2: value2, ...}
                    布尔型:true | false

                操作符号:
                    算术运算符:+, -, *, /, %, //, **
                    比较操作符:==, !=, <, >, <=, >=
                    逻辑运算符:and, or, not

            template模块的常用参数:
                src:在ansible主控设备上的Jinja2格式的模板文件的路径;.j2
                dest:将模板文件复制到远程主机后的文件路径;
                owner:
                group:
                mode:
                setype:

    template模块使用示例:
- hosts: websrvs
  remote_user: root
  tasks:
  - name: copy openssl packages
    copy: src=../files/openssl/ dest=/root/
  - name: install openssl new version
    yum: name=/root/openssl-1.0.2k-12.el7.x86_64.rpm,/root/openssl-libs-1.0.2k-12.el7.x86_64.rpm state=latest
  - name: install nginx package
    yum: name=nginx state=present
  - name: provide nginx config file
    template: src=../templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    notify: reload nginx config
    tags: provconf
  - name: start nginx service
    service: name=nginx state=started enabled=true
  handlers:
  - name: reload nginx config
    service: name=nginx state=reloaded

  注意:需要实现提供一个j2格式的文件作为配置文件的模板;此例中模板文件是:/etc/ansible/templates/nginx.conf.j2
      worker_processes {{ ansible_processor_vcpus-2 }};
      listen       {{ ngx_port }} default_server;

  应用模板的时候,可以通过命令行传递变量的值:
      # ansible-playbook -t provconf -e "ngx_port=40080" nginx.yml

条件判断机制:
    when: condition

    基于条件判断机制实现不同的CentOS发行版本中的数据库管理系统的管理示例:
- hosts: dbsrvs
  remote_user: root
  vars:
    srvstate: started
  tasks:
  - name: install mysql-server package on centos 6
    yum: name=mysql-server state=present
    when: ansible_distribution_major_version == "6"
    tags: instpkgs
  - name: install mariadb-server package on centos 7
    yum: name=mariadb-server state=present
    when: ansible_distribution_major_version == "7"
    tags: instpkgs
  - name: start mysqld service
    service: name=mysqld state={{ srvstate }}
    when: ansible_distribution_major_version == "6"
    tags: servicemgmt
  - name: start mariadb service
    service: name=mariadb state={{ srvstate }}
    when: ansible_distribution_major_version == "7"
    tags: servicemgmt

循环控制机制:
    在ansible中可以将其称为"迭代",遍历给定的数据结构中的各元素,在同一个任务中可以实现多次执行;

    在迭代项的引用上,YAML通常有固定的格式,即:变量名固定为"item";

    在tasks中使用with_items的键值对的方式设定元素迭代列表;
        列表的实现方法:
            字符串;
            字典;

构建amp平台:
    amp——apache(httpd) + mysql-server(mariadb-server) + php-fpm

示例1:
- hosts: websrvs
  remote_user: root
  tasks:
  - name: install packges
    yum: name={{ item }} state=present
    with_items:
    - httpd
    - mariadb-server
    - php-fpm
  - name: manage service
    service: name={{ item }} state=started
    with_items:
    - httpd
    - mariadb
    - php-fpm

示例2:
- hosts: websrvs
  remote_user: root
  tasks:
  - name: create some groups
    group: name={{ item }} state=present
    with_items:
    - group11
    - group22
    - group33
  - name: create some users
    user: name={{ item.user }} group={{ item.group }}
    with_items:
    - { user: user11, group: group11 }
    - { user: user22, group: group22 }
    - { user: user33, group: group33 }

ansible的角色(roles):
    角色:一个完整的应用服务的配置集合;

    默认情况下,存放各个角色的目录是:/etc/ansible/roles

    在上述目录中,创建一个与要管理的应用服务相关或相同的目录名称即可;
        /etc/ansible/roles/httpd
        /etc/ansible/roles/nginx
        ...

    在每个应用服务项目中,都需要有一套严格标准的目录结构:
        /etc/ansible/roles/nginx/{files/,templates/,tasks/,handlers/,vars/,meta/,default/}/main.yml

        files/:
            用于存放由copy模块或script模块所用到的静态文件;
        templates/:
            template模块查找和复制所需的Jinja2格式的模板文件的目录;因此,存储于该目录中的文件都必须以".j2"为文件的后缀名称;
        tasks/:
            定义ansible所执行的任务所使用的yml文件的集合;至少要包含一个main.yml文件作为访问入口;如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
        handlers/:
            定义处理器时所使用的yml文件的集合;至少要包含一个main.yml文件作为访问入口;如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
        vars/:
            定义自定义变量时所使用的yml文件的集合;至少要包含一个main.yml文件作为访问入口;如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
        meta/:
            定义当前角色的某些特定属性和依赖关系;至少要包含一个main.yml文件作为访问入口;如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
        default/:            定义默认变量时使用的目录,至少要包含一个main.yml文件作为访问入口;如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;




    为了避免连接时出现权限问题,在主管与被管设备之间使用免密认证。

    图片.png

    图片.png



验证是否可以免密登陆;

    图片.png













猜你喜欢

转载自blog.51cto.com/holmes975/2364214
今日推荐