邓毓
作者邓毓2017-09-18 17:57
系统工程师, 江西农信

Ansible自动化运维体系在生产环境下实践(11步极快速搭建)

字数 10747阅读 7379评论 7赞 29

为什么要搭建自动化运维体系:

鉴于之前有过一次全行IT 系统的重大的实施工作,即因全行时钟较北京时间差20余分钟,将全行时钟统一前调了20分钟,并与新的原子钟保持时钟同步。在没有自动化运维工具(Puppet、Ansible、Saltstack、Chef)的前提下,利用了IBM Tivoli Monitor(ITM)实现的所有受监控系统的时钟前调任务,并进行了相关的检查。当然在做事情之前,做了大量的人工的准备工作,包括ntp服务的检查、ntp自启动未开启的检查、ntp未配置的检查、时钟前调大量测试工作等等。正是由于这些前期大量缜密的工作,让这次统一的时钟调整任务得以顺利完成,但同时我们也发现自动化运维工具的重要性,倘若没有ITM,我们几乎每办法开展这项工作,倘若有了自动化运维工具,我们可以节省大量人力的前期检查工作,也可以利用自动化运维工具做好后续的检查工作,当然自动化运维工具的运用远远不止于此,于是我们急迫需要快速搭建一套自动化运维体系。
注:ITM是监控软件,利用ITM客户端上的Agent可以在客户端统一发命令。

选择Ansible的原因:

其他几个工具,这里就不多提了,选择ansible主要原因是:用于生产环境,轻量,无代理,批量任务能够写成脚本,而不用分发到远程就可以执行,并且能够极快速地搭建,能够接受效率稍微不如代理方式的缺点,暂无Ansible之上二次开发的需求,对于ansible服务端的安全性:安全加固,纳入堡垒机管理,禁止不必要的服务和网络端口。整体架构如下:
图片1.png

图片1.png

如何快速搭建Ansible整套环境:

包含一套ansible服务端和1500余个生产环境ansible客户端。
时间:三天。按照以下现成的方式,1-2天即可完成ansible自动化运维体系的环境搭建!
服务端: 操作系统版本RHEL6.6 x86_64,该操作系统自带Python 2.6.6(要求Version>=2.6)
由于是生产环境,无法连接外部互联网,所以整个安装过程,只能用安装包的方式安装。

1.配置YUM源(连接专门的YUM服务器):

cat /etc/yum.repos.d/rhel-source.repo
[rhel]
name=Red Hat Enterprise Linux - rhel
baseurl=http://yum_server_ip/repo/rhel/6.6/x86_64/
enabled=1
gpgcheck=0

没有YUM服务器也可以将RHEL6.6的ISO文件传至服务端,并挂载:

mount -o loop -o ro /tmp/rhel6.6_x86_64.iso /mnt

配置YUM源(本地)

cat /etc/yum.repos.d/rhel-local.repo
[rhel]
name=Red Hat Enterprise Linux - rhel
baseurl= file:///mnt
enabled=1
gpgcheck=0

2.ansible依赖模块及安装包的安装:
所有安装包地址:
ansible2.3.2所有安装包地址
A.安装setuptools-7.0

tar -xvf setuptools-7.0.tar
cd setuptools-7.0
python setup.py install

B. 安装pycrypto-2.6.1

gzip -dc pycrypto-2.6.1.tar.gz|tar -xvf -
cd pycrypto-2.6.1
python setup.py install

安装包错解决:
报错1:

running install
running build
running build_py
running build_ext
running build_configure
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/tmp/ansible/pycrypto-2.6.1':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

解决:yum install gcc
报错2:
图片2.png

图片2.png

解决:yum install python-devel
最后pycrypto安装成功。

C. 安装PyYAML模块
(1)yaml-0.1.5

tar -xvf yaml-0.1.5.tar
cd yaml-0.1.5
./configure --prefix=/usr/local
make --jobs=`grep processor /proc/cpuinfo|wc -l`
make install

(2)PyYAML-3.11

gzip -dc PyYAML-3.11.tar.gz|tar -xvf -
cd PyYAML-3.11
python setup.py install

D.安装Jinja2模块
(1)MarkupSafe-0.9.3

tar -xvf MarkupSafe-0.9.3.tar
cd MarkupSafe-0.9.3
python setup.py install

(2)Jinja2-2.7.3

gzip -dc Jinja2-2.7.3.tar.gz|tar -xvf -
cd Jinja2-2.7.3
python setup.py install

E.安装Paramiko模块
(1)ecdsa-0.11

gzip -dc ecdsa-0.11.tar.gz|tar -xvf -
cd ecdsa-0.11
python setup.py install

(2)paramiko-1.15.1

gzip -dc paramiko-1.15.1.tar.gz|tar -xvf -
cd paramiko-1.15.1
python setup.py install

F.安装ansible-stable-2.3

unzip ansible-stable-2.3.zip
cd ansible-stable-2.3
python setup.py install

3.ansible客户端的需求
被管理的服务器需要安装python2.4以上的版本,如果python版本低于2.5,需要安装python-simplejson。生产环境大部分为Linux和AIX,少量的Windows,由于Windows的业务系统少量且非重要,这里暂时不通过ansible去管理windows客户端,linux系统基本都安装了python,所以只需要关注python版本;AIX基本都未安装python,所以需要批量安装python,后面将介绍方法。
Linux python version<2.5的安装simplejson
simplejson-3.6.5

gzip -dc simplejson-3.6.5.tar.gz|tar -xvf -
cd simplejson-3.6.5
python setup.py install

4.配置Ansible变量环境
Ansible配置文件ini格式存储配置数据的,在ansible中,几乎所有的配置项都可以通过ansible的playbook或者环境变量来重新赋值,在运行ansible命令时,命令将会按照预先设定的顺序查找配置文件,如下所示:
(1)ANSIBLE_CONFIG:首先,ansible命令会检查该环境变量,及这个环境变量将指向的配置文件。
(2)./ansible.cfg:其次,将会检查当前目录下的ansible.cfg配置文件。
(3)~/.ansible.cfg:再次,将会检查当前用户home目录下的ansible.cfg配置文件。
(4 )/etc/ansible/ansible.cfg:最后,将会检查在用软件包管理工具安装ansible时自动产生的配置文件。
在这里我们在/etc/profile中,增加一行:

export ANSIBLE_CONFIG=/etc/ansible/ansible.cfg

在用户登录时,都设置该环境变量。
由于是安装包安装,ansible的目录及相关文件都需要自己创建:

mkdir /etc/ansible
cd /etc/ansible
touch ansible.cfg hosts

修改/etc/ansible/ansible.cfg的内容:

cat /etc/ansible/ansible.cfg
#default这一行是需要的
[default]
#inventory代表所管理的主机清单的文件位置
inventory = /etc/ansible/hosts
#library参数就是指向存放ansible模块的目录(ansible基于模块工作,本身没有批量部署的能力,真正具有批量部署的ansible所运行的模块)
library = /usr/share/ansible
#设置默认情况下ansible最多能有多少个进程同时工作
forks = 50
#设置默认执行命令的用户,可以在playbook中重新指定该参数
sudo_user = ansible
#指定连接被管节点的ssh端口,可以在hosts文件中,单独指定被管主机的ssh端口
remote_port = 22
#设置模块的语言
module_lang = C
#设置ansible服务端连接客户端的私有ssh key文件位置
private_key_file = /root/.ssh/id_rsa
#设置是否检查ssh主机的密钥
host_key_checking = False
#设置ssh连接的超时时间,单位秒
timeout = 60
#设置把ansible系统的输出记录到日志文件中
log_path = /tmp/ansible.log

5.配置Ansible客户端主机环境
cat /etc/ansible/hosts
将生产所有服务器的IP地址按照以下格式加入hosts文件

[业务系统名称代码_x86]
ip x.x.x.x
ip x.x.x.x
ip x.x.x.x
ip x.x.x.x
ip x.x.x.x
…
[业务系统名称代码_aix]
ip x.x.x.x
ip x.x.x.x
ip x.x.x.x
ip x.x.x.x
ip x.x.x.x
…

这样的目的是为了区分不同业务系统,不同操作系统类别,ansible在执行命令时,可以直接:

ansible 业务系统名称代码* -m 模块名称 -a 命令

去对该业务系统下的所有主机批量执行命令,也可以:

ansible 业务系统名称代码_x86 -m 模块名称 -a 命令

对该业务系统下的所有x86主机批量执行命令,还可以:

ansible *x86 -m 模块名称 -a 命令

对所有x86主机批量执行命令。这一切都可以在你的掌控下,这里只是列举了我们的做法。

6.配置Ansible ssh互信
在ansible服务端生成ssh public和private key:

ssh-keygen

图片3.png

图片3.png

将ssh public key下发到被管节点的.ssh目录:

ssh-copy-id -i /root/.ssh/id_rsa.pub client_ip

为了提高效率,可以将所有需要添加互信的client的ip地址编入文件/tmp/clienthosts.txt

a=`cat /tmp/clienthosts.txt`
for i in $a
do
ssh-copy-id -i /root/.ssh/id_rsa.pub $i
done

然后每个建立互信过程时,输入“yes”和client密码,这样下次服务端就可以直接通过ssh连接客户端了。

7.Ansible服务端与客户端连通性测试
查看ansible版本:

ansible --version
ansible 2.3.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.6.6 (r266:84292, Nov 21 2013, 10:50:32) [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)]

测试ansible服务端与客户端连通性:

Ansible all -m ping

这时由于并非所有客户端都具备相应的条件,要么python未安装、要么python版本不符合要求,要么没有安装ssh等,会报如下错误:

X.X.X.X | FAILED! => {
    "changed": false, 
    "failed": true, 
    "msg": "Error: ansible requires the stdlib json or simplejson module, neither was found!"
}

客户端python版本不符合要求。

X.X.X.X | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host x.x.x.x port 22: Connection refused\r\n", 
    "unreachable": true
}

客户端未安装ssh

X.X.X.X | FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Shared connection to X.X.X.X closed.\r\n", 
    "module_stdout": "/bin/sh: /usr/bin/python:  not found.\r\n", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}

客户端未安装python
如果遇到这些报错,这里只需要按照下面的批量安装方式安装即可。

8.ansible连接客户端过程耗时过长问题
在测试过程中,发现有一个问题非常困扰,就是创建ssh通道很慢,虽然ansible在同一个task里面是并行的控制多台受控端,但是每一个task都需要和受控端创建ssh通道,非常影响效率,于是翻了下ansibel的官方网站,有说过openssh的controlpersist特性可以优化,其实就是持久化ssh socket,一次验证多次通信,并且只需要修改ansible ssh client的配置即可,但是这个特性需要比较新的openssh的版本
在解决问题之前,查看了下openssh的版本:

OpenSSH_6.6.1p1, OpenSSL 1.0.1e-fips 11 Feb 2013

这次需要将openssh版本升级到OpenSSH_6.7p1,OpenSSL版本不变,升级过程如下:
(1)查看是否缺少依赖包:

rpm -qa|egrep “gcc|make|perl|pam|pam-devel”

缺少了依赖包,可以通过YUM源直接安装这些缺少的包

yum –y install gcc* make perl pam pam-devel

(2)上传安装包:openssh-6.7p1.tar.gz
(3)备份ssh:

mv /etc/ssh /etc/ssh.bak

(4)编译安装新版本openssh

gzip -dc openssh-6.7p1.tar.gz|tar -xvf –
cd openssh-6.7p1
./configure --prefix=/usr --sysconfdir=/etc/ssh --with-pam --with-zlib --with-md5-passwords
make

(5)卸载旧版本openssh

rpm -a|grep openssh
rpm -e `rpm –qa|grep openssh`

(6)安装新版本openssh

make install

(7)查看是否升级到了新版本

ssh –V
OpenSSH_6.7p1, OpenSSL 1.0.1e-fips 11 Feb 2013

(8)复制启动脚本到/etc/init.d

cp /root/openssh-6.7p1/contrib/RedHat/sshd.init /etc/init.d/sshd

(9)将sshd加入开机自启动

chkconfig –add sshd

(10)启动sshd

service sshd start

(11)添加openssh的controlmaster的配置

cat /root/.ssh/config
Host *
Compression yes
ServerAliveInterval 60
ServerAliveCountMax 5
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 4h

验证,未持久化socket前,需要13秒

time ansible test -m ping
X.X.X.X | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
real    0m13.030s
user    0m1.147s
sys     0m0.263s

持久化后,只需要1.5秒,满足需求,在进程数量调上去后,运行命令的并发速度还是不错的。

X.X.X.X | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
real    0m1.590s
user    0m0.795s
sys     0m0.166s

9.AIX操作系统python的批量安装
(1)将AIX python的安装文件传至ansible服务端的/tmp目录:
gdbm-1.8.3-2.aix5.1.ppc.rpm
readline-4.3-2.aix5.1.ppc.rpm
expat-2.0.1-2.aix5.3.ppc.rpm
python-2.6.2-2.aix6.1.ppc.rpm
(2)编辑文件/tmp/clienthosts_aix.txt将所有AIX的IP地址输入至该文件,并运行命令:

b=`cat /tmp/clienthosts_aix.txt`
for i in $b
do
scp /tmp/gdbm-1.8.3-2.aix5.1.ppc.rpm $i:/tmp
scp /tmp/readline-4.3-2.aix5.1.ppc.rpm $i:/tmp
scp /tmp/expat-2.0.1-2.aix5.3.ppc.rpm $i:/tmp
scp /tmp/python-2.6.2-2.aix6.1.ppc.rpm $i:/tmp
done

(3)检查AIX客户端是否已经安装了python

for i in $b
do
ssh $i which python
done

如果安装了python,版本也大于等于2.6,可以重新编辑/tmp/clienthosts_aix.txt将该ip地址去掉。
(4)未安装python的AIX客户端开始安装:

c=`cat /tmp/clienthosts_aix.txt`
for i in $c
do
ansible $i -m raw -a "cd /tmp;rpm -ivh gdbm-1.8.3-2.aix5.1.ppc.rpm;rpm -ivh readline-4.3-2.aix5.1.ppc.rpm;rpm -ivh expat-2.0.1-2.aix5.3.ppc.rpm;rpm -ivh python-2.6.2-2.aix6.1.ppc.rpm"
done

由于ansible服务端需要和安装了python的客户端才能通信,但是在客户端没有安装python前,可以通过ansibel的raw模块直接通信,并安装python,用这种方式实现批量安装的目的。

10.Linux批量安装simplejson
由于Linux默认已经安装了python,这里只需要关注Linux的python版本即可,对于python版本<2.5的,可以批量安装simplejson:
(1)将simplejson-3.6.5.tar.gz传至ansible服务端/tmp目录
(2)拷贝simplejson-3.6.5.tar.gz至需要安装的客户端

d=`cat /tmp/clienthosts_linux_lowpython.txt`
for i in $d
do
scp /tmp/simplejson-3.6.5.tar.gz $i:/tmp
done

(3)安装simplejson

d=`cat /tmp/clienthosts_linux_lowpython.txt`
for i in $d
do
ansible $i -m raw -a "gzip -dc simplejson-3.6.5.tar.gz|tar -xvf –;cd simplejson-3.6.5; python setup.py install"
done

批量安装都是用类似的方法,这里也不再一一举例。

11.ansible模块介绍:
至此,整个生产环境ansible自动化运维体系的相关环境已经搭建完成,可以开始尽情的表演了,不过要很好的运用ansible还需要掌握一些ansible的模块,下面简要介绍如下:
(1)Setup:用来查看远程主机的一些基本信息

ansible ip -m setup

这个模块还是很强大的,基本所有操作系统的信息、参数等都可以通过这个模块查到。
(2)Ping:用来测试远程主机的运行状态

ansible ip -m ping

(3)File:设置文件的属性
比如创建文件符号链接:

ansible ip -m file -a "src=/etc/resolv.conf dest=/tmp/resolv.conf state=link"

相关选项如下:
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效
src:被链接的源文件路径,只应用于state=link的情况
dest:被链接到的路径,只应用于state=link的情况
state:directory:如果目录不存在,就创建目录
    file:即使文件不存在,也不会被创建
    link:创建软链接
    hard:创建硬链接
   touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
   absent:删除目录、文件或者取消链接文件
(4)Copy:复制文件到远程主机
比如将本地文件复制到客户端:

ansible ip -m copy -a "src=/etc/ansible/ansible.cfg dest=/tmp/ansible.cfg owner=root group=root mode=0644"

相关选项如下:
backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no
content:用于替代“src”,可以直接设定指定文件的值
dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode:递归设定目录的权限,默认为系统默认权限
force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others:所有的file模块里的选项都可以在这里使用
src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。
(5)Command:在远程主机上执行命令
比如查看某个客户端的日期:

ansible ip -m command -a “date”

值得注意的是,ansibel默认的模块是command,所以上面的命令可以简化为:

 ansible ip -a “date”

(6)Shell:切换到某个shell执行指定的指令,参数与command相同。
与command不同的是,此模块可以支持命令管道,同时还有另一个模块也具备此功能:raw
比如说在服务端创建一个脚本,然后通过copy模块将此脚本分发到所有客户端,然后再通过shell模块在所有客户端执行:

ansible all -m shell -a "/tmp/test.sh"

(7)其他常用模块:
service:系统服务管理
cron:计划任务管理
yum:yum软件包安装管理
synchronize:使用rsync同步文件
user:系统用户管理
group:系统用户组管理
(8)更多模块用命令:ansible-doc -l参考

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

29

添加新评论7 条评论

#samlin系统工程师, 中福彩科技
2019-07-14 15:58
步骤清晰,关键是有可实施的具体命令,为你点赞。
#fslh007其它, 哈尔滨恒世卓业科技发展有限公司
2019-03-11 20:16
谢谢您的分享!
#JohnBush系统工程师, 国家电网
2018-06-12 09:11
能把安装所用到的包打包一下发到平台提供下载吗?
#JohnBush系统工程师, 国家电网
2018-06-12 09:09
谢谢分享。
#TonyWang系统工程师, BY
2017-09-25 10:24
很赞!三天时间完成,效率也高!
#wuwenpin软件开发工程师, 南京
2017-09-24 21:11
非常不错。
#feidaodao系统运维工程师, GA
2017-09-19 16:43
自从我学会用ansible后,大大增加了我的工作效率。非常喜欢这个工具。 作者撰写的配置手册完美,赞! 感谢你的分享! 在这篇文章,我学到了ssh通道持久化节省时间的办法,谢谢楼主。 我也分享3小点: 1,StrictHostKeyChecking=no的参数,可以不用提示复制到client时的yes/no; 2,ssh-copy-id -i复制时,需要输入密码,可结合sshpass来复制key。 3,从安全性讲,运行命令一定得小心,可以结合sudo用。

邓毓@feidaodao 你的分享也不错,也为你点赞!

2017-09-19 16:56
Ctrl+Enter 发表

关于TWT  使用指南  社区专家合作  厂商入驻社区  企业招聘  投诉建议  版权与免责声明  联系我们
© 2019  talkwithtrend — talk with trend,talk with technologist 京ICP备09031017号-30