• 自动化运维工具Ansible


    一、简介

    当下有许多的运维自动化工具( 配置管理 ),例如:Ansible、SaltStack、Puppet、Fabric 等。

    Ansible 一种集成 IT 系统的配置管理、应用部署、执行特定任务的开源平台,是 AnsibleWorks 公司名下的项目,该公司由 Cobbler 及 Func 的作者于 2012 年创建成立。

    Ansible 基于 Python 语言实现,由 Paramiko 和 PyYAML 两个关键模块构建。

    二、特性

    部署简单,只需在主控端部署 Ansible 环境,被控端无需做任何操作。

    支持Linux/UNIX及windows环境

    默认使用 SSH(Secure Shell)协议对设备进行管理,用它来配置思科路由也非常方便。

    主从集中化管理。
    配置简单、功能强大、扩展性强。
    支持 API 及自定义模块,可通过 Python 轻松扩展。
    通过 Playbooks 来定制强大的配置、状态管理。
    对云计算平台、大数据都有很好的支持。
    提供一个功能强大、操作性强的 Web 管理界面和 REST API 接口 ---- AWX 平台。

    三、总体架构

    四、执行过程

    五、Ansible 与 SaltStack对比

    >> 最大的区别是 Ansible 无需在被监控主机部署任何客户端代理,默认通过 SSH 通道进行远程命令执行或下发配置。
    >> 相同点是都具备功能强大、灵活的系统管理、状态配置,都使用 YAML 格式来描述配置,两者都提供丰富的模板及 API,对云计算平台、大数据都有很好的支持。

    Ansible在github上地址:https://github.com/ansible

    Ansible安装部署与配置

           角色              主机名                  IP                                组名             

           控制端           hd01                     192.168.1.11                 ——             

           被控端           hd02                     192.168.1.12                 webservers   

           被控端           hd03                     192.168.1.13                 webservers   

    Ansible安装

    安装可使用源码编译安装,也可以更新yum源后使用yum安装

    yum 安装:

    配置源(centos6)

    yum install http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm -y

    换163的源

    wget http://mirrors.163.com/.help/CentOS6-Base-163.repo      

     mv CentOS6-Base-163.repo /etc/yum.repos.d/

     yum clean all

    CentOS6-Base-163.repo主要是为了安装:PyYAML

    配置源(centos7)
    rpm -iUvh http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel//7/x86_64/e/epel-release-7-7.noarch.rpm
    下载配置文件(centos7)
    wget http://mirrors.163.com/.help/CentOS7-Base-163.repo          CentOS7-Base-163.repo主要是为了安装:PyYAML
    mv CentOS7-Base-163.repo /etc/yum.repos.d/

    yum clean all

    安装ansible

    yum -y install ansible


    查看ansible 版本

    [root@hd01 ~]# ansible --version

    ansible 2.5.3

      config file = /etc/ansible/ansible.cfg

      configured module search path = [u'/usr/share/my_modules']

      ansible python module location = /usr/lib/python2.6/site-packages/ansible

      executable location = /usr/bin/ansible

      python version = 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]

    注:yum装ansible      随着时间的推移,ansible版本会是最新版的。

    Ansible通过定义好的主机与组规则(Inventory)对匹配的目标主机进行远程操作,配置文件默认是/etc/ansible/hosts

    定义Host Inventory

    添加组名及允许执行命令的主机

    webservers 是组名,下面的是IP也可以使用域名、别名标识。

    各主机SSH互信

    [root@hd01 ~]# ssh-keygen -t rsa   #创建公钥与私钥

    一直回车就OK

    将公钥传给webservers组中的主机

    ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.12

    ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.13

    测试主机免密 连通性:

    [root@hd01 ~]# ansible webservers -m ping

    #-m 使用ping模块  -vvv 可以查看详细的执行过程

    OK

    提示:

    使用Linux普通用户账户进行连接并使用sudo命令实现root权限,格式为:

    ansible webservers -m ping -u ansible -sudo

    当没有做免密码访问时用 ansible webservers -m ping -k

    然后输入密码 操作

    关于定义主机与组

    在/etc/ansible/hosts中主机可以用域名、IP、别名进行标识。

    /etc/ansible/hosts  中组成员主机名称支持正则描述   组成员主机IP支持正则描述

    举例说明 格式:

    [webservers]                #组名

    alpha.example.org    #域名对应192.168.1.100     

    beta.example.org     #域名对应192.168.1.110     

    192.168.1.100               #IP

    192.168.1.110               #IP

    mail.example.com

    192.168.1.90:2135         #定义一个SSH服务端口为:2135的主机  

    组成员主机名称支持正则描述,举例:

    [webservers]

    www.[01:50].example.com

    [databases]

    db-[a:f].example.com

    定义主机变量

    主机可以指定变量,以便后面供Playbook配置使用,比如定义主机host1及host2上apache参数http_port及maxRequestsPerChild,目的是让两台主机产生Apache配置文件httpd.conf差异化,格式:

    [atlanta]

    host1 http_port=80 maxRequestsPerChild=808

    host2 http_port=303 maxRequestsPerChild=909

    定义组变量

    组变量的作用域是覆盖所有成员,通过定义一个新块,块名由组名+”:vars”组成

    格式:

    [atlanta]

    host1

    host2

    [atlanta:vars]

    ntp_server=ntp. atlanta.example.com

    proxy=proxy.atlanta.example.com

    匹配目标

    格式:ansible <目标主机或组> -m <模块名字> -a <模块参数>

    重启webservers组所有Apache服务

    [root@hd01 ~]# ansible webservers -m service -a "name=httpd state=restarted"

    匹配目标主机规则表

    192.168.1.12或者hd02               匹配目标IP地址或主机名,多个IP或主机名使用”:”号分隔

    webservers                                匹配目标组为webservers多个组使用”:”号分隔

    all或者'*'                                   匹配所有主机

    hd.*或者192.168.1.*                   支持正则匹配主机或者IP地址

    webservers:!192.168.1.11            匹配webservers组且排除192.168.1.11主机IP

    agent:&webservers                    匹配agent和webservers两个组的交集

    webservers:!{{excluded}}:&{{required}}       支持变量匹配方式

    Ansible常用模块及API

    Ansible提供了非常丰富的功能模块,包括cloud(云计算)、Commands(命令行)、Database(数据库)、Files(文件管理)、Internal(内置功能)、Monitoring(监控管理)等等。

    获取webservers组中主机uptime信息

    [root@hd01 ~]# ansible webservers -m command -a "uptime"     

    -m command是默认模块  可省略

    [root@hd01 ~]# ansible-doc ping

    可获得模块的帮助信息

    EXAMPLES:

    # Test we can logon to 'webservers' and execute python with json lib.

    # ansible webservers -m ping

    # Example from an Ansible Playbook

    - ping:

    # Induce an exception to see what happens

    - ping:

        data: crash

    RETURN VALUES:

    ping:

        description: value provided with the data parameter

        returned: success

        type: string

        sample: pong

    在playbook中运行远程命令格式:

    - name: reboot the service

      command: /sbin/reboot -t now

    Ansible 常用模块学习

    shell > ansible-doc -l    # 列出 Ansible 支持的模块

    ansible-doc <模块名>查看模块帮助信息

    >>远程命令模块( command / script / shell )

    command 作为 Ansible 的默认模块,可以运行远程权限范围所有的 shell 命令,不支持管道符。

    例:

    ansible webservers -m command -a "free -m"               # 查看 webservers 分组主机内存使用情况

    [root@hd01 ~]# ansible webservers -m command -a "free -m"

    shell 的功能是执行远程主机上的 shell 脚本文件,支持管道符。

    例:

    [root@hd01 ~]# ansible webservers -m shell -a "/root/test.sh"          # 执行远程脚本

    ansible的command和shell模块的区别:

    比如我要批量删除一些文件, 

    [root@hd01 ~]# ansible webservers -m command -a "rm -f /root/test*.sh"

    因为你的命令行中包含了通配符*号,通配符必须要有在shell环境中才能被识别出,不然,它只能删除test*.sh这一个文件。

    虽显示成功,但目标文件未被删除

    所以你需要执行以下命令才能成功

    [root@hd01 ~]# ansible webservers -m shell -a "rm -f /root/test*.sh"

    执行之后    

    关于command模块运行的命令中无法使用管道符的说明。

    script 的功能是在远程主机执行主控端存储的 shell 脚本文件,相当于 scp + shell 组合。

    例:

    [root@hd01 ~]# ansible webservers -m script -a "/root/test.sh"      # 远程执行本地脚本

    192.168.1.12 | SUCCESS => {

        "changed": true,

        "rc": 0,

        "stderr": "Shared connection to 192.168.1.12 closed. ",

        "stdout": "123 ",

        "stdout_lines": [

            "123"

        ]

    }

    192.168.1.13 | SUCCESS => {

        "changed": true,

        "rc": 0,

        "stderr": "Shared connection to 192.168.1.13 closed. ",

        "stdout": "123 ",

        "stdout_lines": [

            "123"

        ]

    >>copy 模块(实现主控端向目标主机拷贝文件,类似于 scp 功能)

    例:

    [root@hd01 ~]# ansible webservers -m copy -a "src=/root/test.sh dest=/tmp/ owner=root group=root mode=0755 backup=yes"

    # 向 webservers 组中主机拷贝 test.sh 到 /tmp 下,owner:指定属主为 root,group:指定属组为:root ,mode:权限为 0755 , backup:在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no

     

    >>stat 模块(获取远程文件状态信息,atime/ctime/mtime/md5/uid/gid 等信息)

    例:

    [root@hd01 ~]# ansible webservers -m stat -a "path=/etc/passwd"    #path指定具体路径

    >>get_url 模块(实现在远程主机下载指定 URL 到本地,支持 sha256sum 文件校验)

    例:

    [root@hd01 ~]# ansible webservers -m get_url -a "url=http://www.baidu.com dest=/tmp/index.html mode=0440 force=yes"  

    #下载百度首页index.html文件

    # force:

            yes:默认项,如果目标主机包含该文件,但内容不同,则强制覆盖

            no:则只有当目标主机的目标位置不存在该文件时,才复制

    >>yum 模块(软件包管理)

    #name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径 

    #state:目标状态(present,absent,latest)

    1. present是指安装套件,而 latest 則是指安装最新的套件,也就是会使用 yum mirror 上最新的版本。
    2. absent   卸载

    例:yum 装httpd

    [root@hd01 ~]#ansible webservers -m yum -a "name=httpd state=latest"

    安装

    卸载

    [root@hd01 ~]#ansible webservers -m yum -a "name=httpd state=absent" 

    >>cron 模块(远程主机 crontab 配置)

    例: 

    [root@hd01 ~]# ansible webservers -m cron -a "name='check passwd md5value' hour='8' job='md5sum /etc/passwd>/tep/p.txt'"

    任务名字叫check passwd md5value   hour=’8’ 每天的8时执行任务

    效果:

    [root@hd02 ~]# crontab -l

    #Ansible: check passwd md5value

    * 8 * * * md5sum /etc/passwd>/tep/p.txt

    [root@hd02 ~]#

    >>mount 模块(远程主机分区挂载)

    例:

    [root@hd01 ~]# ansible webservers -m mount -a 'name=/test src=/dev/sdb1 fstype=ext3 opts=ro state=present' 

    # fstype  指定文件系统类型为ext4  

    # opts     设定挂载的参数选项信息;-o ro == opts=ro 

    # src       要被挂载的目录设备信息 src=/dev/sdb1

    >>service 模块(远程主机系统服务管理)

    例:

                                                              #state的4种目标状态

    [root@hd01 ~]# ansible webservers -m service -a "name=httpd state=started"  #启动httpd

    [root@hd01 ~]# ansible webservers -m service -a "name=httpd state=stopped" #关闭httpd

    [root@hd01 ~]# ansible webservers -m service -a "name=httpd state=restarted" #重启httpd

    [root@hd01 ~]# ansible webservers -m service -a "name=httpd state=reloaded" #重新加载httpd

    >>sysctl 包管理模块

    功能

    远程Linux主机sysctl配置。

    实例

    sysctl: name=kernel.panic value=3 sysctl_file=/etc/sysctl.conf checks=before reload=yessalt '*' pkg.upgrade

    >>user 服务模块(远程主机用户管理)

    例:

    [root@hd01 ~]# ansible webservers -m user -a "name=wang comment='user wang'"

    [root@hd01 ~]# ansible webservers -m user -a "name=wang state=absent remove=yes"    #state 目标状态  删除

    实现一些监控功能

    查看全部主机在线情况

    [root@ansible ~]# ansible all -m ping //内建的ping模块  #all表示/etc/ansible/hosts中全部主机

    [root@hd01 ~]# ansible webservers -a "/bin/df -h" #输出挂载信息

    [root@hd01 ~]# ansible webservers -a "/sbin/ip addr show dev eth0"  #查看webservers组中主机网卡信息

    YAML语言

    yaml语言是一种基于Unicode容易阅读,容易和脚本语言交互的,用来表达数据序列的编程语言Ansible与Saltstack环境中配置文件都以YAML格式存在,YAML文件扩展名通常为.yaml或者.yml

    重要组成结构:list和directory

    以下通过描述YAML与Python的对应关系,了解YAML的层次及结构

    块序列描述

    块序列就是将描述的元素序列到python的列表中

    Python:

    import yaml

    obj = yaml.load(

    """

    - apple

    - banana

    - orange

    """

    )

    print(obj)

    结果:

    ['apple', 'banana', 'orange']

    YAML与Python块概念类似,例如:

    -

     - apple

     - banana

     - orange

    -

     - chuanzhi

     - oldboy

     - mage

    对应Python结果:

    [['apple', 'banana', 'orange'],[ 'chuanzhi', 'oldboy', 'mage']]

    块映射描述:

    块映射就是将描述的元素序列到字典的中,格式为”key: value”,以下为YAML例子:

    hero:

      hp: 34

      sp: 8

      level: 4

    orc:

      hp: 12

      sp: 0

      level: 2

    对应python结果为:

    {'hero': '{'hp': 34, 'sp': 8, 'level': 4}, 'orc': {'hp': 12, 'sp': 0, 'level': 2}}

    YAML块序列与块映射是可以自由组合在一起的,他们之间可以相互嵌套,通过灵活的组合实现复杂的对象属性。例如:

    - hero:

       hp: 34

       sp: 8

       level: 4

    - orc:

       hp:

        - 12

        - 30

       sp: 0

       level: 2

    对应Python结果为:

    [{'hero': '{'hp': 34, 'sp': 8, 'level': 4}, {'orc': {'hp': [12,30] ,'sp': 0, 'level': 2}}]

    Ansible-playbook介绍

    # 使用 Ansible-playbook 可以完成一组复杂的动作,例如部署环境、搭建服务、修改配置等。playbook可以定制配置,可以按指定的操作步骤有序执行,支持同步及异步方式。官方提供很多例子,可在https://github.com/ansible/ansible-examples 找到。playbook通过YAML格式来进行描述定义,可以实现多台主机应用部署。

    先创建一个存放playbook剧本的目录

    [root@hd01 ~]# mkdir -p /root/ansible/playbooks

    在webservers组中简单部署nginx,ntp服务,利用其批量部署过程介绍playbook。

    playbook案例一  yum安装nginx,ntp

    创建nginx的目录

    [root@hd01 ~]# cd /root/ansible/

    [root@hd01 ansible]# mkdir nginx

    【/root/ansible/playbooks/nginx.yml】
    
    ---
    
    - hosts: webservers
    
      vars:
    
        worker_processes: 4
    
        num_cpus: 4
    
        max_open_file: 65506
    
        root: /application
    
      remote_user: root
    
      tasks:
    
      - name: ensure nginx is at the latest version
    
        yum: name=nginx state=latest
    
      - name: write the nginx config file
    
        template: src=/root/ansible/nginx/nginx2.conf dest=/etc/nginx/nginx.conf
    
        notify:
    
        - restart nginx
    
      - name: ensure nginx is running
    
        service: name=nginx state=started
    
      handlers:
    
        - name: restart nginx
    
          service: name=nginx state=restarted

    以上playbook定制了一个简单的Nginx软件包管理,内容包括安装、配置模板、状态管理等。下文将上面代码拆分进行说明。

    1、定义主机与用户

    - hosts: webservers

      vars:

        worker_processes: 4

        num_cpus: 4

        max_open_file: 65506

        root: /application

      remote_user: root

    #hosts  定义操作的对象是webservers组,对象可以是主机或组

    #vars  定义了4个变量(配置模板用到)

    #remote_user  指定远程操作主机为root,支持sudo方式运行,通过添加sudo:yes即可。

    2、任务列表

    tasks:                                                             #任务集

    - name: ensure nginx is at the latest version   #确保nginx是最新的版本

      yum: name=nginx state=latest             # state=latest  目标状态=最新版     

    - name: ensure nginx is running   #name标签增强可读性,对下面的service模块(动作)描述

      service: name=nginx state=started      #serivce模块使nginx处于启动状态

             #软件名字   #状态    参数使用key=value格式

    功能是检测Nginx服务是否为启动状态,如没有则启动。

    在playbook可通过template模块对本地配置模板文件进行渲染并同步到目标主机。

    - name: write the nginx config file

        template: src=/root/ansible/nginx/nginx2.conf dest=/etc/nginx/nginx.conf

        notify:

        - restart nginx

    #src指定文件源地址  dest指定文件的目标地址

        notify:                                #通知handlers重启nginx

        - restart nginx

      - name: ensure nginx is running             #确保nginx在运行中

        service: name=nginx state=started

      handlers:                                  # handlers(处理程序)做通知的动作

        - name: restart nginx

          service: name=nginx state=restarted

    执行playbook

    执行playbook,可以通过ansible-playbook命令实现,格式:

    ansible-playbook playbookfile(.yml或.yaml) [参数],如启用10个并行进程执行playbook:

    [root@hd01 ~]# ansible-playbook /root/ansible/playbooks/nginx.yml -f 10

    其他常用参数说明:

    -u remote_user: 自己指定远程指定执行playbook的系统用户

    --syntax-check: 检查playbook语法

    --list-hosts playbooks: 匹配到的主机列表

    -T timeout:定义执行playbook的超时时间

    --step: 以单任务分步骤运行,方便做每一步的确认工作

    playbook角色与包含声明

    当我们写一个非常大的playbook时,想要复用些功能显得有些吃力,还好ansible支持写playbook时拆分成多个文件,通过包含(include)的形式进行引用,我们可以根据多重维度进行“封装”,比如定义变量、任务、处理程序等等。

    角色建立在包含文件之上,抽象之后更清晰,可复用,

    ansible官方在https://github.com/ansible/ansible-examples/上提供大量资料供参考

    包含文件,鼓励复用

    当多个playbook涉及服用的任务列表时,可以将复用的内容剥离出,写到独立的文件当中,最后在需要的地方include进来即可,示例如下:

    将处理程序(handlers)放到包含文件中是一个好的办法,比如重启apache的任务:

    【handlers/handlers.yml】

    ---

    #this might be in a file like handlers/handlers.yml        #注释说明在处理这类文件

    - name: restart apache                                                   

      service: name=apache state=restarted

    需要用时如下引用:

    handlers:

      - include: handlers/handlers.yml       #注意路径

    角色

    角色可以更好地进行组织或抽象,让剧本复用性更强、功能更具模块化。

    角色是Ansible定制的一种标准规范,以不同级别目录层次及文件对角色、变量、任务、处理程序等进行拆分,为后续功能扩展、可维护性打下基础。一个典型角色目录结构的示例如下:

    site.yml                   

    webservers.yml

    roles/

       common/     #公共类角色

         files/                    ## files目录:用于存放将要拷贝到远程主机的安装包等

         templates/

    tasks/    #tasks目录: 将要执行的所有任务,如果比较复杂,可以单独定义不同任务,

         handlers/ 

         vars/

         defaults/

         meta/       

       webservers/

         files/

         templates/

         tasks/

         handlers/

         vars/

         defaults/

         meta/

    在playbook是这样引用的:

    【site.yml】

    ---

    - hosts: webservers

      roles:

        - common

    - webservers

    角色定制以下规范,其中x为角色名。

    -如roles/x/tasks/main.yml文件存在,其中列出的任务将被添加到执行队列;

    -如roles/x/handlers/main.yml文件存在,其中所列的处理程序将被添加到执行队列

    -如roles/x/vars/main.yml 文件存在,其中所列出的变量将被添加到执行队列

    -如roles/x/meta/main.yml 文件存在,所列任何变量的依赖关系将被添加到角色的列表

    -任何副本任务可以引用roles/x/files/  无需写路径,默认相对或绝对引用

    -任何脚本任务可以引用roles/x/files/  无需写路径,默认相对或绝对引用

    -任何模板任务可以引用文件中的roles/x/templates/  无需写路径,默认相对或绝对引用

    对上面nginx软件包管理的playbook(独立文件)修改成角色的形式,添加一个公共类角色common,从角色全局作用域中抽取出公共的部分,一般为系统的基础服务,比如ntp、iptables、selinux、sysctl等。本实例针对ntp服务管理。

    1. playbook目录结构

    playbook目录包括变量定义目录group_vars、主机组定义文件hosts、全局配置文件site.yml、角色功能目录。

    【/root/ansible/playbooks/nginx/】

    [root@hd01 ~]# cd /root/ansible/playbooks/

    [root@hd01 playbooks]# mkdir nginx

    playbook目录树结构

    [root@hd01 playbooks]# tree nginx/
    
    nginx/
    
    ├── group_vars
    
    │   ├── all
    
    │   └── webservers
    
    ├── hosts
    
    ├── roles
    
    │   ├── common
    
    │   │   ├── handlers
    
    │   │   │   └── main.yml
    
    │   │   ├── tasks
    
    │   │   │   └── main.yml
    
    │   │   ├── templates
    
    │   │   │   └── ntp.conf.j2
    
    │   │   └── vars
    
    │   │       └── main.yml
    
    │   └── web
    
    │       ├── handlers
    
    │       │   └── main.yml
    
    │       ├── tasks
    
    │       │   └── main.yml
    
    │       └── templates
    
    │           └── nginx2.conf
    
    └── site.yml
    
     
    1. 定义主机组

    定义一个业务组webservers,成员为两台主机。

    【nginx/hosts】

    [root@hd01 nginx]# cat hosts
    
    [webservers]
    
    192.168.1.12
    
    192.168.1.13

    非必选配置,默认引用/etc/ansible/hosts的参数,角色中定义组与主机的文件将通过”-i file”参数调用,格式:

    [root@hd01 nginx]# ansible-playbook -i hosts 剧本文件

    1. 定义主机或组变量

    group_vars为定义组变量目录,目录当中的文件名要与组名保持一致,组变量文件定义的变量作为域只受限于该组,all代表所有主机。

    [root@hd01 group_vars]# cat all
    
    ---
    
    # Variables listed here sre applicable to all host groups
    
    ntpserver: ntp.sjtu.edu.cn
    
    [root@hd01 group_vars]# cat webservers
    
    ---
    
    worker_processes: 4
    
    num_cpus: 4
    
    max_open_file: 65506
    
    root: /application
    1. 全局配置文件site.yml

    site.yml引用了两个角色块,角色的应用范围及实现功能都不太一样

    【nginx/site.yml】

    [root@hd01 nginx]# cat site.yml
    
    ---
    
    - name: apply common configuration to all nodes
    
      hosts: all
    
      roles:
    
        - common
    
    - name: configure add deploy the webservers and application code
    
      hosts: webservers
    
      roles:
    
        - web

    site.yml引用了两个角色,一个为公共类的common,另一个为web类,分别对应nginx/roles/common、nginx/roles/web目录。以此类推,可以引用更多的角色如db、hadoop等等,前提是得先定义,通常一个角色对应着一个服务。通过hosts参数来绑定角色对应的主机或组。

    1. 角色common的定义

    角色common定义了handlers、tasks、templates、vars 4个功能类,分别存放处理程序、任务集、模板、变量的配置文件main.yml,需要注意的是,vars/main.yml中定义的变量优先级高于/nginx/group_vars/all,可从ansible-playbook的执行结果中得到验证。各功能块定义文件如下:

    [root@hd01 roles]# pwd

    /root/ansible/playbooks/nginx/roles

    [root@hd01 roles]# mkdir common

    [root@hd01 roles]# cd common/

    [root@hd01 common]# mkdir {handlers,tasks,templates,vars}

    【handlers/main.yml】

    [root@hd01 handlers]# cat main.yml
    
    - name: restart ntp
    
      service: name=ntpd state=restarted

    【tasks/main.yml】

    [root@hd01 tasks]# cat main.yml
    
    - name: install ntp
    
      yum: name=ntp state=present
    
    - name: configure ntp file
    
      template: src=ntp.conf.j2 dest=/etc/ntp.conf  #src引用模板是无需写路径,默认在上级的
    
      notify: restart ntp                                             templates目录查找
    
    - name start the ntp service
    
      service: name=ntpd state=started
    
    - name: test to see if selinux is running
    
      command: getenforce
    
      register: sestatus
    
      changed_when:false

    【templates/ ntp.conf.j2】

    [root@hd01 templates]# cat ntp.conf.j2
    
    driftfile /var/lib/ntp/drift
    
    restrict 127.0.0.1
    
    restrict -6 ::1
    
     
    
    server {{ ntpserver }}        #{{ ntpserver }}将引用vars/main.yml定义的ntpserver变量
    
     
    
    includefile /etc/ntp/crypto/pw
    
    keys /etc/ntp/keys

    【vars/main.yml】

    [root@hd01 vars]# cat main.yml
    
    ---
    
    # Variables listed here are applicable to all groups
    
    ntpserver: 210.72.145.44
    1. 角色web的定义

    角色web定义了handlers、tasks、templates三个功能类,基本上是前面nginx管理playbook对应定义功能段打散了之后的内容。

    [root@hd01 roles]# mkdir web

    [root@hd01 roles]# cd web/

    [root@hd01 web]# mkdir {handlers,tasks,templates}

    【handlers/main.yml】

    [root@hd01 handlers]# cat main.yml
    
    - name: restart nginx
    
      service: name=nginx state=restarted

    【tasks/main.yml】

    [root@hd01 tasks]# cat main.yml
    
    - name: ensure nginx is at latest version
    
      yum: pkg=nginx state=latest     
    
    - name: write the nginx config file
    
      template: src=nginx2.conf dest=/etc/nginx/nginx.conf   
    
      notify:
    
      - restart nginx
    
    - name: ensure nginx is running
    
      service: name=nginx state=started
    
     

    需要去替换的nginx配置文件

    【templates/nginx2.conf】

    [root@hd01 templates]# cat nginx2.conf
    
    #The configuration file has been modified
    
     
    
    # For more information on configuration, see:
    
    #   * Official English Documentation: http://nginx.org/en/docs/
    
    #   * Official Russian Documentation: http://nginx.org/ru/docs/
    
     
    
    user nginx;
    
    worker_processes auto;
    
    error_log /var/log/nginx/error.log;
    
    pid /var/run/nginx.pid;
    
     
    
    # Load dynamic modules. See /usr/share/nginx/README.dynamic.
    
    include /usr/share/nginx/modules/*.conf;
    
     
    
    events {
    
        worker_connections  1024;
    
    }
    
     
    
     
    
    http {
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    
                          '$status $body_bytes_sent "$http_referer" '
    
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
     
    
        access_log  /var/log/nginx/access.log  main;
    
     
    
        sendfile            on;
    
        tcp_nopush          on;
    
        tcp_nodelay         on;
    
        keepalive_timeout   65;
    
        types_hash_max_size 2048;
    
     
    
        include             /etc/nginx/mime.types;
    
        default_type        application/octet-stream;
    
     
    
        # Load modular configuration files from the /etc/nginx/conf.d directory.
    
        # See http://nginx.org/en/docs/ngx_core_module.html#include
    
        # for more information.
    
        include /etc/nginx/conf.d/*.conf;
    
    }
    
     
    1. 运行角色

    先在webservers组上换163的源  安装扩展源

    wget http://mirrors.163.com/.help/CentOS6-Base-163.repo

    cp /root/CentOS6-Base-163.repo /etc/yum.repos.d/CentOS-Base.repo

    yum clean all

    yum -y install epel-release

    yum clean all

    运行之前先介绍下ntp

    在Linux系统中,为了避免主机时间因为在长时间运行下所导致的时间偏差,进行时间同步(synchronize)的工作是非常必要的。Linux系统下,一般使用ntp服务来同步不同机器的时间。NTP 是网络时间协议(Network Time Protocol)的简称,干嘛用的呢?就是通过网络协议使计算机之间的时间同步化。

    ntpd与ntpdate在更新时间时有什么区别。ntpd不仅仅是时间同步服务器,它还可以做客户端与标准时间服务器进行同步时间,而且是平滑同步,并非ntpdate立即同步,在生产环境中慎用ntpdate,也正如此两者不可同时运行。

    [root@hd01 playbooks]# tree nginx/

    nginx/

    ├── group_vars

    │   ├── all

    │   └── webservers

    ├── hosts

    ├── roles

    │   ├── common

    │   │   ├── handlers

    │   │   │   └── main.yml

    │   │   ├── tasks

    │   │   │   └── main.yml

    │   │   ├── templates

    │   │   │   └── ntp.conf.j2

    │   │   └── vars

    │   │       └── main.yml

    │   └── web

    │       ├── handlers

    │       │   └── main.yml

    │       ├── tasks

    │       │   └── main.yml

    │       └── templates

    │           └── nginx2.conf

    └── site.yml

    [root@hd01 nginx]# pwd

    /root/ansible/playbooks/nginx

    [root@hd01 nginx]# ansible-playbook -i hosts site.yml

    验证:

    [root@hd02 ~]# rpm -qa|grep nginx

    nginx-mod-http-image-filter-1.10.2-1.el6.x86_64

    nginx-mod-http-geoip-1.10.2-1.el6.x86_64

    nginx-filesystem-1.10.2-1.el6.noarch

    nginx-mod-stream-1.10.2-1.el6.x86_64

    nginx-1.10.2-1.el6.x86_64

    nginx-mod-http-perl-1.10.2-1.el6.x86_64

    nginx-mod-mail-1.10.2-1.el6.x86_64

    nginx-all-modules-1.10.2-1.el6.noarch

    nginx-mod-http-xslt-filter-1.10.2-1.el6.x86_64

    [root@hd02 ~]# rpm -qa | grep ntp   

    fontpackages-filesystem-1.41-1.1.el6.noarch

    ntpdate-4.2.6p5-12.el6.centos.2.x86_64

    ntp-4.2.6p5-12.el6.centos.2.x86_64

     OK

    获取远程主机系统信息: Facts

    Facts是一个非常有用的组件,类似于Saltstack的Grains功能,实现获取远程主机的系统信息,包括主机名、IP地址、操作系统、分区信息、硬件信息等,可以配合playbook实现更多功能需求。比如在httpd.conf模板中引用Facts的主机名信息作为ServerName参数的值。运行ansible 192.168.1.12 -m setup,返回192.168.1.12的Facts信息:

    192.168.1.12 | SUCCESS => {

        "ansible_facts": {

            "ansible_all_ipv4_addresses": [

                "192.168.1.12"

            ],

            "ansible_all_ipv6_addresses": [

                "fe80::20c:29ff:fe59:9cc4"

            ],

            "ansible_apparmor": {

                "status": "disabled"

            },

            "ansible_architecture": "x86_64",

            "ansible_bios_date": "07/02/2015",

            "ansible_bios_version": "6.00",

            "ansible_cmdline": {

                "KEYBOARDTYPE": "pc",

                "KEYTABLE": "us",

                "LANG": "zh_CN.UTF-8",

                "quiet": true,

                "rd_NO_DM": true,

                "rd_NO_LUKS": true,

                "rd_NO_LVM": true,

                "rd_NO_MD": true,

                "rhgb": true,

    "ro": true,

                "root": "UUID=17ff3012-e425-439a-9cd4-0f8da54aa4ae"

            },

    系统  版本  dns地址等等

            "ansible_distribution": "CentOS",

            "ansible_distribution_file_parsed": true,

            "ansible_distribution_file_path": "/etc/redhat-release",

            "ansible_distribution_file_variety": "RedHat",

            "ansible_distribution_major_version": "6",

            "ansible_distribution_release": "Final",

            "ansible_distribution_version": "6.6",

            "ansible_dns": {

                "nameservers": [

                    "114.114.114.114"

                ]

            },

    主机名  CPU  VMware虚拟平台  等等

            "ansible_nodename": "hd02",

            "ansible_os_family": "RedHat",

            "ansible_pkg_mgr": "yum",

            "ansible_processor": [

                "0",

                "GenuineIntel",

                "Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz"

            ],

            "ansible_processor_cores": 1,

            "ansible_processor_count": 1,

            "ansible_processor_threads_per_core": 1,

            "ansible_processor_vcpus": 1,

            "ansible_product_name": "VMware Virtual Platform",

            "ansible_product_serial": "VMware-56 4d d9 aa 53 2d 1d 9c-c8 1d ac 6d 1c 59 9c c4",

            "ansible_product_uuid": "564DD9AA-532D-1D9C-C81D-AC6D1C599CC4",

            "ansible_product_version": "None",

    ……

    在模板文件中这样引用Facts信息

    {{ ansible_devices.sda.model }}

    {{ ansible_hostname }}

    变量

    在实际应用环境中,机器之间可能存在不同差异,比如CPU核心数等等,在ansible中定义变量可处理这些差异。

    变量定义规则:由字母、数字、下划线组成,必须以字母开头。

    关于前文Nginx软件包管理的剧本的变量的解释

      vars:

        worker_processes: 4             #4个工作进程

        num_cpus: 4                                     #CPU数量为4

    max_open_file: 65506                        #最大打开文件数

    root: /application                            #Nginx根目录

    Jinja2过滤器

    Jinja2是Python下一个广泛应用的模板引擎,它的设计思想类似于Django的模板引擎,并扩展了其语法和一系列强大的功能,官网地址: http://jinja.pocoo.org/

    下面介绍Ansible使用Jinja2强大的过滤器(Filters)功能。

    使用格式:{{ 变量名|过滤方法 }}

    实现获取一个文件路径变量过滤出文件名的一个示例:

    {{ path | basename }}

    获取文件所处的目录名:

    {{ path | dirname }}

    下面为一个完整的示例,实现从” /etc/profile”中过滤出文件名”profile”并输出重定向到

    /tmp/testshell文件中

    [root@hd01 ~]# cat 1.yml

    ---

    - hosts: 192.168.1.12

      vars:

        filename: /etc/profile

      tasks:

        - name: "shelll"

          shell: echo {{ filename | basename }}>tmp/testshell

    [root@hd02 ~]# cat /tmp/testshell

    profile

    更多过滤方法参考:

    http://jinja.pocoo.org/docs/2.10/templates/#builtin-filters   

    本地Facts

    通过Facts可以来获取目标主机的系统信息,当这些信息还不能满足功能需求时,可通过编写自定义的Facts模板来实现。还有一个更简单的实现办法,就是通过本地Facts实现。只需在目标设备/etc/ansible/facts.d 目录定义JSON、INI或可执行文件的JSON(数据)输出,文件扩展名要求使用 “.fact”,这些文件都可以作为Ansible本地的Facts,例如,在目标设备192.168.1.12定义三个变量,供以后playbook进行引用。

    【/etc/ansible/facts.d/preferences.fact】

    [root@hd02 ~]# cat /etc/ansible/facts.d/preferences.fact

    [general]      #常规

    max_memory_size=32

    max_user_processes=3730

    open_files=65535

    [root@hd01 ~]# ansible 192.168.1.12 -m setup -a "filter=ansible_local"

    192.168.1.12 | SUCCESS => {

        "ansible_facts": {

            "ansible_local": {

                "preferences": {

                    "general": {

                        "max_memory_size": "32",

                        "max_user_processes": "3730",

                        "open_files": "65535"

                    }

                }

            }

        },

        "changed": false

    }

    注意返回JSON(数据)的层次结构,perferences(facts文件名前缀)→general(INI的节名)→key:value(INI的键与值),最后就可以在我们的模板或playbook中通过以下方式调用:

    {{ ansible_local.preferences.general.openfiles }}

    注册变量

    变量的另一个用途是将一条命令的运行结果保存到变量中去,供后面的playbook使用。

    示例:

    - hosts: webservers

      tasks:

        - shell: /usr/bin/foo            

          register: foo_result   #注册foo_result变量 变量值为shell: /usr/bin/foo的运行结果;

          ignore_errors: True                 #忽略错误

        - shell: /usr/bin/bar                   

          when: foo_result.rc == 5  

    #当条件语句when: foo_result.rc == 5成立时,shell: /usr/bin/bar命令才会执行  

    其中foo_result.rc为返回/usr/bin/foo 的resultcode(返回码)。

    条件语句

    有时候一个playbook的结果取决于一个变量,或者取决于上一个任务(task)的执行结果,某些情况下,一个变量的值可以依赖于其他变量的值,当然也会影响Ansible的执行过程。

    有时候我们想跳过某些主机的执行步骤,比如符合特定版本的操作系统将不安装某个软件,或者磁盘爆满了将进行清理的步骤。在Ansible中很容易做到这一点,通过When子句实现,其中引用Jinja2表达式。

    简单示例1:

    [root@hd01 ~]# cat 1.yml

    - hosts: webservers

      remote_user: root

      tasks:

        - name: "shutdown Debian flavored systems"   

          command: /sbin/shutdown -t now      #下面when语句执行结果为True时  关机

          when: ansible_os_family == "Debian"    #Jinja2表达式    

    #通过定义任务的Facts本地变量ansible_os_family(操作系统版本名称)是否为Debian,

    结果返回BOOL(布尔型)类型,为True是将执行上一条语句,为False是该条语句不触发

    skipping跳过

    绿色  没执行shutdown命令

    示例2:

    通过判断一条命令执行结果做不同分支的二级处理

    [root@hd01 ~]# cat 1.yml

    ……

        - command: /bin/false

          register: result      #注册变量

          ignore_errors: True   #忽略错误

        - command: /bin/something        

          when: result|failed   #当变量result执行结果为失败状态时执行/bin/something

        - command: /bin/something_else

          when: result|success  #当变量result执行结果为成功状态时执行/bin/something_else

        - command: /bin/still/something_else

          when: result|skipped  #当变量result执行结果跳过时执行/bin/something_else

    ……

    循环

    通常一个任务会做很多事情,如创建大量用户、安装很多包、重复轮询特定的步骤,直到某种结果条件为止,Ansible提供良好支持。

    例如在被控端添加 2 个用户  

    方式1一般做法  

    - name: add user testuser1  

    user: name=testuser1 state=present groups=wheel

    - name: add user testuser2  

    user: name=testuser2 state=present groups=wheel

    解释:

    user: name=testuser1 state=present groups=wheel #用户名testuser1 目标状态为安装 加入wheel组

    在重复执行执行任务量大的时候  推荐使用 迭代机制 方式2

    方式2使用迭代方式  

    - name: add several users  

    user: name={{ item }} state=present groups=wheel   #{{ item }}  在引用下面的变量

    with_items:   #通过with_items语句来指明迭代的元素列表

    - testuser1  

    - testuser2  

    with_items会自动循环执行上面的语句” user: name={{ item }} state=present groups=wheel”  次数为with_items的元素个数。

    还支持字典、列表形式在这里只叙述简单 常用的

    批量用yum安装软件包

    ……

    - name: yum many install package

      yum: name={{ item }} state=installed

      with_items:

      - httpd

      - nginx

    ……

     

    playbook案例二  源码安装nginx,定制服务,针对自定制的nginx服务

    需求:假如说业务需要扩容,我需要部署新的环境,新增加了机器,我需要把我原来标准的环境搬过去,那么就可以使用ansible的playbook,把你已经存在的模板,已经编译好的nginx,包括配置文件 包括启动脚本。

    思路:先在一台机器上编译安装好nginx、打包,然后再用ansible去下发。

    过程:

    目录树结构

    [root@hd01 playbooks]# pwd

    /root/ansible/playbooks

    [root@hd01 playbooks]# tree nginx_install/
    
    nginx_install/
    
    ├── install.yml
    
    └── roles
    
        ├── common
    
        │   ├── files
    
        │   ├── handlers
    
        │   ├── meta
    
        │   ├── tasks
    
        │   │   └── main.yml
    
        │   ├── templates
    
        │   └── vars
    
        └── install
    
            ├── files
    
            │   └── nginx.tar.gz
    
            ├── handlers
    
            ├── meta
    
            ├── tasks
    
            │   ├── copy.yml
    
            │   ├── install.yml
    
            │   └── main.yml
    
            ├── templates
    
            │   ├── nginx
    
            │   └── nginx.conf
    
            └── vars
    
                └── main.yml
    
     

    [root@hd01 playbooks]# mkdir nginx_install

    [root@hd01 ~]# mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}

    说明:roles目录下有两个角色,common为一些准备操作,install为安装nginx的操作。每个角色下面又有几个目录,handlers下面是当发生改变时要执行的操作,通常用在配置文件发生改变,重启服务。Files为安装时用到的一些文件,meta为说明信息,说明角色依赖等信息,tasks里面是核心的配置文件,templates通常存一些配置文件,启动脚本等模板文件,vars下为定义的变量。

    需要事先准备好安装用到的文件,具体如下:

    - 在一台机器上事先编译安装好nginx,配置好启动脚本,配置好配置文件

    -安装好后我们需要把nginx目录打包,并放到/root/ansible/playbooks/nginx_install/roles/install/files下面,名字为nginx.tar.gz

    - 启动脚本、配置文件都要放到/root/ansible/playbooks/nginx_install/roles/install/templates下面

    - cd /root/ansible/playbooks/nginx_install/roles

    - 定义common的tasks,nginx是需要一些依赖包的,如下:

    [root@hd01 tasks]# pwd

    /root/ansible/playbooks/nginx_install/roles/common/tasks

    [root@hd01 tasks]# cat main.yml
    
    - name: Install initializtion require software
    
      yum: name={{ item }} state=installed
    
      with_items:
    
        - pcre
    
        - zlib-devel
    
        - pcre-devel

    先看下准备好的nginx  

    [root@hd01 ~]# ls /usr/local/nginx/

    client_body_temp  conf  fastcgi_temp  html  logs  proxy_temp  sbin  scgi_temp  uwsgi_temp

    [root@hd01 ~]# ls /etc/init.d/nginx

    /etc/init.d/nginx

    [root@hd01 ~]# ls /usr/local/nginx/conf/nginx.conf

    /usr/local/nginx/conf/nginx.conf

    [root@hd01 ~]#

    [root@hd01 sbin]# ./nginx -V

    nginx version: nginx/1.12.1

    built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)

    configure arguments:

    启动脚本内容:

    如果想添加脚本用service启动,加入开机启动,必须要脚本里面包含标红的这2行

    [root@hd01 ~]# cat /etc/init.d/nginx
    
    #! /bin/bash
    
    #chkconfig: 2345 59 26
    
    # description: nginx is a World Wide Web server. It is used to serve
    
    . /etc/rc.d/init.d/functions
    
    pidfile="/usr/local/nginx/logs/nginx.pid"
    
    start(){
    
             if [ -f $pidfile ]
    
             then
    
                    echo "nginx is running..." 
    
             else
    
                    /usr/local/nginx/sbin/nginx
    
                    sleep 1
    
                    if [ -f $pidfile ]
    
                    then
    
                            action "nginx start"  /bin/true
    
                    else
    
                            action "nginx start" /bin/false
    
                    fi
    
             fi
    
    }
    
    stop(){
    
             if [ -f $pidfile ]
    
             then
    
                 kill  `cat $pidfile`
    
                 #rm -rf $pidfile
    
                 action "nginx stop"  /bin/true
    
             else
    
                 action "nginx have been stopped"    /bin/false
    
             fi
    
    }
    
    status(){
    
             if [ -f $pidfile ]
    
             then
    
                action "nginx is running"  /bin/true
    
             else
    
                action "nginx  have been stopped"         /bin/true
    
             fi
    
    }
    
    restart(){
    
            stop
    
            start
    
    }
    
    case "$1" in
    
    start)
    
          start
    
          ;;
    
    stop)
    
          stop
    
          ;;
    
    restart)
    
          restart
    
          ;;
    
    status)
    
          status
    
          ;;
    
    *)
    
       echo "USAGE:{start|stop|restart|status}"
    
       exit 1
    
          ;;
    
    esac
    
    exit 0

    打包nginx之前  控制端hd01关闭nginx,被控端确保环境中不存在nginx以及启动脚本。

    把启动脚本,配置文件复制到对应的templates/下。

    [root@hd01 ~]# cd /usr/local/

    [root@hd01 local]# tar zcvf nginx.tar.gz --exclude "nginx.conf" --exclude "vhost" nginx/

    [root@hd01 local]# mv nginx.tar.gz /root/ansible/playbooks/nginx_install/roles/install/files/

    [root@hd01 local]#

    cp nginx/conf/nginx.conf /root/ansible/playbooks/nginx_install/roles/install/templates/

    [root@hd01 local]#

    cp /etc/init.d/nginx /root/ansible/playbooks/nginx_install/roles/install/templates/

    查看公共类角色

    [root@hd01 common]# pwd

    /root/ansible/playbooks/nginx_install/roles/common

    [root@hd01 common]# ls

    files  handlers  meta  tasks  templates  vars

    [root@hd01 common]# cat tasks/main.yml
    
    - name: Install initializtion require software
    
      yum: name={{ item }} state=installed
    
      with_items:
    
        - pcre
    
        - zlib-devel
    
        - pcre-devel

    定义变量

    [root@hd01 vars]# pwd

    /root/ansible/playbooks/nginx_install/roles/install/vars

    [root@hd01 vars]# cat main.yml
    
    nginx_user: www
    
    nginx_port: 80
    
    nginx_basedir: /usr/local/nginx

    可以根据这个去修改 被控端的一些参数

    把所有需要的文件拷贝到目标机器

    [root@hd01 tasks]# pwd

    /root/ansible/playbooks/nginx_install/roles/install/tasks

    [root@hd01 tasks]# cat copy.yml
    
    - name: copy nginx software
    
      copy: src=nginx.tar.gz dest=/tmp/nginx.tar.gz owner=root group=root
    
    - name: uncompression nginx software
    
      shell: tar zxf /tmp/nginx.tar.gz -C /usr/local/
    
    - name: copy nginx start script
    
      template: src=nginx dest=/etc/init.d/nginx owner=root group=root mode=0755
    
    - name: copy nginx config
    
      template: src=nginx.conf dest={{ nginx_basedir }}/conf/ owner=root group=root mode=0644

    为什么上面的src后没跟绝对路径呢,因为他默认就去上一级files、templates里面找了。

    接下来建立用户,启动服务,删除压缩包。

    [root@hd01 tasks]# pwd

    /root/ansible/playbooks/nginx_install/roles/install/tasks

    [root@hd01 tasks]# cat install.yml
    
    - name: creat nginx user
    
      user: name={{ nginx_user }} state=present createhome=no shell=/sbin/nologin
    
    - name: To solve the error
    
      shell: ln -s /lib64/libpcre.so.0.0.1 /lib64/libpcre.so.1
    
    - name: start nginx service
    
      shell: /etc/init.d/nginx start
    
    - name: add boot start nginx service
    
      shell: chkconfig --level 345 nginx on
    
    - name: delete nginx compreeion files
    
      shell: rm -rf /tmp/nginx.tar.gz

    上述标红的两行  根据被控端 实际情况考虑

    再创建一个新的文件main.yml去调用copy.yml 和install.yml

    [root@hd01 tasks]# pwd

    /root/ansible/playbooks/nginx_install/roles/install/tasks

    [root@hd01 tasks]# cat main.yml
    
    - include: copy.yml
    
    - include: install.yml

    到此两个roles: common和install就定义完成了,接下来定义一个入口配置文件

    [root@hd01 nginx_install]# pwd

    /root/ansible/playbooks/nginx_install

    [root@hd01 nginx_install]# cat install.yml
    
    ---
    
    - hosts: webservers
    
      remote_user: root
    
      gather_facts: True
    
      roles:
    
        - common
    
        - install

    [root@hd01 nginx_install]# pwd

    /root/ansible/playbooks/nginx_install

    [root@hd01 nginx_install]# ansible-playbook install.yml

    控制端

    webservers端

    环境不同 或一些小细节问题,或者机器有bug

    ansible-playbook很可能会报错,需要耐心调试。

    playbook案例3:

    在agent组上yum安装并启动mysql然后检查启动情况返回结果   

    [root@hd01 ~]# cat install_mysql.yaml  
    
    ---
    
    - hosts: agent
    
      remote_user: root
    
      tasks:
    
      - name: install mysql-server
    
        yum: name=mysql-server state=present
    
      - name: start mysql-server
    
        service: name=mysqld state=started
    
      - name: check mysql service
    
    shell: ps -ef |grep mysqld

                

    选项解析:
    
    hosts:agent         #指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组
    
    remote_user:root         #用于指定远程主机上的执行任务的用户
    
    tasks:                       #  任务集
    
    -name:mysql-server installing    # 给这个任务起的名字
    
    yum:name= mysql-server          #利用yum模块,安装软件的包名为mysql-server
    
    service: name=mysqld state=started #启动mysql
    
    state=present                 #状态为安装  
    
    state=absent                  #状态为卸载
    
    检查agent是否已经安装mysql-server

    执行命令

    [root@hd01 ~]# ansible-playbook install_mysql.yaml

    对比两张图

    当返回信息为绿色时,表示ansible没有进行任何操作。

    当返回信息为黄色时,表示ansible执行了操作,“当前状态”已经变成了“目标状态”。

    playbook案例4:

      创建crontab计划

    建立cron.yaml,让agent组 每天1点来运行/root/backup.sh脚本 做重要资料的备份

    [root@hd01 ~]# cat crond.yaml
    
    ---
    
    - hosts: agent
    
      remote_user: root
    
      tasks:
    
      - name: cron
    
         cron: name='test job' hour='1' job="/root/backup.sh"

    看到结果,ok=2    changed=1 说明客户机上的crontab计划创建成功了!


    上述基本操作案例熟悉后开始优化ansible运行

    让你的ansible飞起来

    一、SSH Multiplexing    #SSH 多路复用

    说明:

    注意:OpenSSH需要5.6以上版本,低版本需要升级才能使用。 
    Centos7系统上安装的OpenSSH版本是较新的,可以直接支持;对于Centos6的系统,自带的OpenSSH版本较低,可以用下面这个yum源进行升级yum update openssh-clients:

    加入新yum源

    cat  /etc/yum.repos.d/openssh.repo
    
    [CentALT]
    
    name=CentALT Packages for Enterprise Linux 6
    
    baseurl=http://mirror.neu.edu.cn/CentALT/6/$basearch/
    
    enabled=1
    
    gpgcheck=0

    输入  yum update openssh-clients  升级OpenSSH 版本到5.6以上

    1.配置

    [root@hd01 ~]# tail -3 /etc/ssh/ssh_config   #最后三行添加
    
            ControlMaster   yes     
    
            ControlPath     /tmp/%r@%h:%p   
    
            ControlPersist  10m

    解释:

    ControlMaster yes                       #Session Multiplexing 开关

    ControlPath   ~/.ssh/master-%r@%h:%p    #供 Session Multiplexing 使用的 Control Socket (Unix Socket) 路径

    ControlPersist yes                      #是否开启后台 Control master 模式保持

    成功开启后,无论从该客户端节点用同一用户向同一 SSH Server 节点发起多少次连接,都有且仅有一条TCP连接被建立,负责该节点到该 Server 之间的所有 SSH 包文。

    [root@hd01 ~]# ssh -O check 192.168.1.12

    [root@hd01 ~]# ssh -O check 192.168.1.13

    成功开启后如下所示

    测试:

    1 开启SSH长连接

    ansible是通过使用ssh和远程主机进行通信,所以对ssh有这很强的依赖。在OpenSSH 5.6以后支持Multiplexing这个特性,可以通过在ansible配置中设置以支持该特性。

    如下是配置参数,设置长连接保持时间为5天;control_path指定socket文件所保存的位置。

    ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d

    control_path = /etc/ansible/ssh-socket/%%h-%%p-%%r

    通过上面配置后,ansible中控机上执行一次与远程主机的连接之后,这个连接会持久保持设定时间之久。可以通过netstat命令查看到ESTABLISHED状态的连接信息。

    注意:control_path指定的目录不存在,或执行ansible命令的用户没有写权限的话是会报错的。

    2 开启pipelining

    默认情况下,ansible的执行流程是把生成好的本地python脚本PUT到远程服务器然后运行。如果开启了pipelining,整个流程少了一个PUT脚本到远程服务器的步骤,直接在SSH的会话中进行,可以提高整个执行效率。

    # 在ansible.cfg配置文件中设置pipelining为True

    pipelining = True  

    需要注意的是:如果开启pipelining,需要被控的远程服务器将/etc/sudoers中的”Defaults requiretty”注释掉,否则会出现类似如:you must have a tty to run sudo 的报错。

    用sed做替换

    [root@hd01 ~]# ansible agent -m shell -a"sed -i 's/Defaults    requiretty/#Defaults    requiretty/' /etc/sudoers"

    如下警告解决办法

    在/etc/ansible/ansible.cfg的[defaults]

    添加一行

    command_warnings = False

    即可解决

    Ansible  先介绍这么多实际上它的用法挺深奥的,需要你不断的去实践,才能够掌握,你入门之后再去深入研究包括他的理论也好  具体实践也好就会很容易了。

    参考书籍 《python自动化运维》

    出处:https://www.cnblogs.com/xh-blog/p/9539379.html 

    注:本文版权归作者和博客园共有,转载请注明出处!

  • 相关阅读:
    第一章-实例7-猴子吃桃问题
    第一章-实例6-判断是否为闰年
    第一章-实例3-计算变量所占字节数
    IDEA学习笔记
    spring boot学习概要(尚硅谷)
    JSP动态WEB开发技术--第一章
    学习前端的准备任务
    cmd优化
    软件测试基础概念
    软件工程理论
  • 原文地址:https://www.cnblogs.com/xh-blog/p/9539379.html
Copyright © 2020-2023  润新知