Ansible环境搭建


一、运维自动化平台介绍

1.1、自动化运维平台介绍

运维自动化平台是由管理机器[S]和业务机器[C]组成的,C/S。

管理机器:任务定制及发布;

业务机器:接收任务并执行任务。

运维自动化平台组成.png

1.2、运维自动化平台的优势:

  • 一次性任务定制:任务一次性发布给所有机器
  • 节省任务执行时间:任务主机并发完成任务,节省部署时间
  • 错误率低:避免重复,保证一次任务定制准确即可

二、常见的自动化运维工具

2.1、常见的运维自动化工具

  • Puppet
  • Ansible
  • SaltStack
puppet:
基于Ruby开发,有产品线已经在用,优点是历史悠久,比较成熟,在可远程可本地,功能强劲,批量执行需要写专门的配置文件,费力费时。而且有客户端在,和授权系统结合比较麻烦。

saltstack:
saltstack和ansible都是python流的,而且就功能上来讲,两者也极为相似,不同之处是salt stack是有客户端的,并且execution模块还用0MQ实现了pub-sub,命令和执行结果因此可以高效并行传输,不过成也萧何败也萧何,第一个sub阶段(将querystring下发到所有机器,然后收集机器响应的阶段)太依赖与客户端返回了,如果客户端未能及时返回或未响应的话,playbook执行阶段可能会直接漏掉这部分机器而没有任何提示,这对于运维来说是不可接受的。

ansible:
与前两者比起来,在特性上似乎并不抢眼,配置管理方面(playbook)绝对比不过老大哥puppet,批量执行方面也只是多线程,不像saltstack那么高大上,不过ansible搜索热度高出saltstack三倍多,显然靠的不是吹牛,至少,ansible至少不会悄悄的丢机器,这给了我们一个定心丸,而且仅依赖ssh,与登录授权管理系统天然集成,简单即有效,没有比这更美妙的事情了。

2.2、ansible介绍

ansible是一种由Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:

  1. 连接插件connection plugins:负责和被监控端实现通信;ansible管理端和客户端基于ssh协议通信
  2. host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;提供主机管理列表,定义管理谁
  3. 各种模块核心模块、command模块、自定义模块;提供了日常模块
  4. 借助于插件完成记录日志邮件等功能; 根据需求后续添加模块,邮件、日志模块
  5. playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。一次发布多条指令给客户端

特性

  1. no agents:不需要在被管控主机上安装任何客户端;
  2. no server:无服务器端,使用时直接运行命令即可;
  3. modules in any languages:基于模块工作,可使用任意语言开发模块;
  4. yaml,not code:使用yaml语言定制剧本playbook;
  5. ssh by default:基于SSH工作;
  6. strong multi-tier solution:可实现多级指挥。

优点

  1. 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
  2. 批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
  3. 使用python编写,维护更简单,ruby语法过于复杂;
  4. 支持sudo

基本架构

ansible3.png

· 核心引擎:即ansible
· 核心模块(core modules):这些都是ansible自带的模块,ansible模块资源分发到远程节点使其执行特定任务或匹配一个特定的状态。
· 自定义模块(custom modules):如果核心模块不足以完成某种功能,可以添加自定义模块。
· 插件(plugins):完成模块功能的补充,借助于插件完成记录日志、邮件等功能
· 剧本(playbook):定义ansible任务的配置文件,可以将多个任务定义在一个剧本中,由ansible自动执行,剧本执行支持多个任务,可以由控制主机运行多个任务,同时对多台远程主机进行管理。
· playbook是ansible的配置、部署和编排语言,可以描述一个你想要的远程系统执行策略,或一组步骤的一般过程。如果ansible模块作为你的工作室工具,playbook就是设计方案。在基本层面上,剧本可以用于管理配置和部署远程机器。在更高级的应用中,可以序列多层应用及滚动更新,并可以把动作委托给其他主机,与监控服务器和负载平衡器交互。
· 连接插件(connection plugins):ansible基于连接插件连接到各个主机上,负责和被管理节点实现通信。虽然ansible是使用ssh连接到各被管理节点,但它还支持其他的连接方法,所以需要有连接插件。
· 主机清单(host inventory):定义ansible管理的主机策略,默认是在ansible的hosts配置文件中定义被管节点,同时也支持自定义动态主机清单和指定配置文件路径。

ansible采用paramiko协议库(Fabric也使用这个,基于python开发,支持SSHV2),通过ssh或者ZeroMQ等连接主机。ansible在控制主机主机将ansible模块通过ssh协议(或者Kerberos、LDAP)推送到被管节点执行,执行完之后自动删除。控制主机与被管理节点之间支持local、SSH、ZeroMQ三种连接方式,默认使用基于SSH的连接。在规模较大的情况下使用ZeroMQ连接方式会明显改善执行速度。

三、ansible运行原理

ansible是如何工作的呢?我们通过一个图片来说明一下

ansible工作原理1132928.png

工作原理:
1、用户登录管理机器:通过ansible剧本或者单行命令针对业务机器组或者单个机器部署任务

2、管理机器读取用户的部署任务:根据自己hosts文件中定义的业务机器组查找对应的机器地址(ip或者域名)

3、管理机下发任务:管理机通过ssh免密连接业务机器,下发任务给业务机器

4、业务机器执行任务

5、业务机器将执行结果发送给ansible管理机器
    反馈字体颜色
    绿色  未发生变化
    黄色  更改生效
    红色  执行错误

一、部署前准备

  • 部署机器准备
  • 计算机名解析
  • 关闭防火墙、selinux
  • 时间同步
  • 软件包获得
  • ssh免密登陆

约定事项:

1.所有服务器全部采用静态ip

主机名称 IP地址
manage01 192.168.8.20/24
node1 192.168.8.21/24
node2 192.168.8.22/24
node3 192.168.8.23/24

2.主机名及主机名互相绑定

[root@manage01 ~]# cat /etc/hosts
127.0.0.1   localhost
::1         localhost 
192.168.8.20    manage01
192.168.8.21    node1
192.168.8.22    node2
192.168.8.23    node3

其他机器同理

3.关闭防火墙, selinux

[root@manage01 ~]# systemctl disable firewalld
[root@manage01 ~]# sed -i -r '/SELINUX=/c\SELINUX=disabled' /etc/selinux/config
[root@manage01 ~]# reboot
# 其他机器同理

4.采用时间服务器,时间同步

1、修改配置文件,配置时间服务器为阿里云的时间服务器
[root@manage01 ~]# egrep "^server" /etc/chrony.conf 
server ntp1.aliyun.com
server ntp2.aliyun.com
server ntp3.aliyun.com
server ntp4.aliyun.com

#注释
# pool 2.centos.pool.ntp.org iburst

2、重启服务chronyd
[root@manage01 ~]# systemctl restart chronyd.service 

3、查看源信息
#chronyc chrony的命令行客户端
[root@manage01 ~]# chronyc sources -v
210 Number of sources = 2

.-- Source mode  '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current synced, '+' = combined , '-' = not combined,
| /   '?' = unreachable, 'x' = time may be in error, '~' = time too variable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^? 120.25.115.20                 2   6     1     3   +663us[ +663us] +/-   23ms
^? 203.107.6.88                  2   6     1     2  -1326us[-1326us] +/-   17ms

5.确认和配置yum源(需要epel源)

[root@manage01 ~]# yum -y install epel-*

6.ssh远程连接

管理端和被管理端连接时基于ssh的,所以有两种连接方式

1)基于ssh口令

2)基于ssh证书(重点讲解)

如果想不需要运维人员干预,被管理端必须允许管理端证书免密登陆。

#管理端manage01生成ssh公私钥
[root@manage01 ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:aufJno2QjPK/V63/PVW13h5oWlKu0jk7HesXYTho0gM root@manage01
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|         E      .|
|          o . . o|
|         . = + +.|
|        S o.+ = +|
|     o o  ...* +o|
|  . . * ....O o.+|
|   o . =.*.B o +.|
|    ..o+B oo*oo o|
+----[SHA256]-----+

#将公钥传给node1
[root@manage01 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.8.21
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub"
The authenticity of host '192.168.8.21 (192.168.8.21)' can't be established.
ECDSA key fingerprint is SHA256:u+yOQz+E+eF7Oixdz/vClLXlAEu/7K8jy783gzk20dQ.
ECDSA key fingerprint is MD5:c0:80:1b:ae:93:32:c2:66:f5:da:2f:1c:26:1e:7e:f8.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.8.21's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.8.21'"
and check to make sure that only the key(s) you wanted were added.

#将公钥传给node2
[root@manage01 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.8.22
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub"
The authenticity of host '192.168.8.22 (192.168.8.22)' can't be established.
ECDSA key fingerprint is SHA256:X4JeiiFuwV0cja81veAyGCosriEfZm/zv34cfYkuxmU.
ECDSA key fingerprint is MD5:7d:17:0f:80:d5:2b:30:ec:2c:62:f9:79:6b:fb:5f:bc.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.8.22's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.8.22'"
and check to make sure that only the key(s) you wanted were added.

#将公钥传给node3
[root@manage01 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.8.23
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub"
The authenticity of host '192.168.8.23 (192.168.8.23)' can't be established.
ECDSA key fingerprint is SHA256:PtpsYBjaXkE+o3j8QYU5Ju8uPgcW2lVW8wsx4X1PV/c.
ECDSA key fingerprint is MD5:50:a1:63:a0:ef:e7:61:26:11:25:ae:06:ec:93:cb:18.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.8.23's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.8.23'"
and check to make sure that only the key(s) you wanted were added.


小窍门
免交互创建公私钥
[root@manage01 ansible]# ssh-keygen -f /root/.ssh/id_rsa -N ""   
-f 指定密钥存放路径
-N ""  新密码设置问空
-P ""  老密码是什么


如何可以非交互式传公钥呢
[root@manage01 ansible]# yum -y install sshpass
[root@manage01 ansible]# sshpass -p111111 ssh-copy-id -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa.pub root@192.168.8.22 


StrictHostKeyChecking   严厉的主机监测=no  就不会问你yes|no了 
sshpass 非交互式传密码


测试证书是否生效
[root@manage01 ~]# for i in `seq 21 23`;do
> ssh root@192.168.8.$i "hostname"
> done
node1
node2
node3

看到返回客户端的计算机名称

二、ansible管理端部署

2.1)管理端安装ansible

安装方式:

1)yum安装

# CentOS7必须安装扩展yum源,默认yum源中没有ansible的安装包。
[root@manage01 ~]# yum -y install epel-release
[root@manage01 ~]# yum makecache
[root@manage01 ~]# yum info ansible
[root@manage01 ~]# yum -y install ansible
[root@manage01 ~]# ansible --version
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Nov 14 2023, 16:14:06) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

2) 源码安装

# 0、安装Python3、pip、并更新pip
[root@manage01 ~]# yum -y install python3 python3-pip
[root@manage01 ~]# pip3 install pip --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple/
[root@manage01 ~]# ln -s /usr/bin/python3 /usr/bin/python
[root@manage01 ~]# ln -s /usr/bin/pip3 /usr/bin/pip

# 1、官网下载地址:https://releases.ansible.com/ansible
[root@manage01 ~]# wget https://releases.ansible.com/ansible/ansible-2.9.27.tar.gz

# 2、安装ansible
[root@manage01 ~]# tar -xvf ansible-2.9.27.tar.gz
[root@manage01 ~]# mv ansible-2.9.27 /usr/local/ansible
[root@manage01 ~]# cd /usr/local/ansible
# python软件包安装--1、安装依赖
[root@manage01 ansible]# pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
[root@manage01 ansible]# pip install cryptography==3.4.8 -i https://pypi.tuna.tsinghua.edu.cn/simple/
# python软件包安装--2、安装软件
[root@manage01 ansible]# python setup.py install

# 安装后设置
[root@manage01 ~]# ln -s /usr/local/ansible/bin/* /usr/bin/
[root@manage01 ~]# mkdir /etc/ansible/
[root@manage01 ~]# cp /usr/local/ansible/examples/ansible.cfg /etc/ansible/
[root@manage01 ~]# cp /usr/local/ansible/examples/hosts /etc/ansible/
[root@manage01 ~]# mkdir /etc/ansible/roles

3) apt安装

# 在一台Ubuntu机器上,你可以使用以下命令来安装Ansible:
sudo apt update
sudo apt install ansible

FAQ1

[root@manage01 ansible]# ansible -m ping 192.168.8.21
[WARNING]: No inventory was parsed, only implicit localhost is available

[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

[WARNING]: Could not match supplied host pattern, ignoring: 192.168.8.21

触发原因
执行ansible的时候回去读取客户端文件hosts,如果没有把客户端加入到hosts文件,就说明无法ansible无法管理。

解决方案
[root@manage01 ansible]# mkdir /etc/ansible
[root@manage01 ansible]# cp examples/hosts /etc/ansible/
#将需要管理的客户端IP地址写入hosts文件,可以分组或者直接写
[root@manage01 ~]# cat /etc/ansible/hosts
192.168.8.[21:23]

分组
[group1]
192.168.8.[21:23]

2.2)ansible管理服务器部署

管理端ansible目录:/etc/ansible

[root@manage01 ansible]# tree 
.
├── ansible.cfg           #ansible配置文件,不需要配置
├── hosts                 #主机列表
└── roles                 #角色列表

1 directory, 2 files

2.3)部署主机列表,定义被监控机

[root@manage01 ansible]# egrep -v "(^#|^$)" /etc/ansible/hosts 
[group1]                    #名字可以随便起  后面跟上业务机器的IP地址或者域名
192.168.8.21
192.168.8.22
192.168.8.23

关于业务机器分组

# 分组中使用范围
[nginx]                 组名
apache[1:10].aaa.com    表示apache1.aaa.com到apache10.aaa.com这10台机器
nginx[a:z].aaa.com      表示nginxa.aaa.com到nginxz.aaa.com共26台机器
10.1.1.[11:15]          表示10.1.1.11到10.1.1.15这5台机器



如果业务机器的SSH端口不是22
10.1.1.13:2222          表示10.1.1.13这台,但ssh端口为2222


指定业务机器别名,未做免密登陆的机器可以通过下面的机器设置账号密码
nginx1  ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456"

ansible_ssh_host  指定业务机器的IP或域名
ansible_ssh_port  指定业务机器的ssh端口
ansible_ssh_user  指定业务机器的ssh用户名
ansible_ssh_pass  指定业务机器的ssh用户名密码


利用机器别名分组
nginx1  ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456"
nginx2  ansible_ssh_host=10.1.1.12

[nginx]
nginx1    #写服务器别名
nginx2


[root@manage01 ansible]# egrep -v "(^#|^$)" /etc/ansible/hosts 
#别名定义
web1 ansible_ssh_host=192.168.8.23 ansible_ssh_port=12121

#分组
[group1]
192.168.8.21
#未做免密登陆机器
192.168.8.22:12121 ansible_ssh_user=sko ansible_ssh_pass='123'
#别名机器
web1 ansible_ssh_user=sko ansible_ssh_pass='123'

2.4)测试管理机和业务机器的联通性

我们可以使用ansible通过调用ping模块来测试分组机器或某个机器
-m 指定使用的模块   group1  业务机器分组
#测试单个机器
#测试主机列表中的机器


#测试单个机器方法
[root@manage01 ~]# ansible -m ping 192.168.8.21
192.168.8.21 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}

#测试主机列表中的机器方法
[root@manage01 ~]# ansible -m ping group1
192.168.8.21 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.8.23 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.8.22 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}