自动化运维工具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.\r\n",

    "stdout": "123\r\n",

    "stdout_lines": [

        "123"

    ]

}

192.168.1.13 | SUCCESS => {

    "changed": true,

    "rc": 0,

    "stderr": "Shared connection to 192.168.1.13 closed.\r\n",

    "stdout": "123\r\n",

    "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 

 

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

 

 

 

posted @ 2018-08-26 22:50  smile-more  阅读(1186)  评论(0编辑  收藏  举报