一、ansible的特性
1、Ansible是一个基于Python开发的配置管理和应用部署工具;
2、它基于模块化工作;
3、无Agent的存在,并非CIS软件,也只需在某个作为控制节点的主机上安装一次Ansible即可,通常它基于ssh连接来控制远程主机,远程主机上不需要安装Ansible或其它额外的服务。
4、Ansible的绝大多数模块都具备幂等性(idempotence)。
所谓幂等性,指的是多次操作或多次执行不影响结果。
5、Ansible吸引人的地方在于它提供的playbook能批量整合不同主机上执行的不同任务,同时还提供一些额外的机制让用户可以去协调这些任务的执行策略。
二、ansible的配置文件
Ansible依赖于SSH协议(默认),对于RHEL系列的系统来说,配置好epel镜像即可安装最新版的Ansible。
$ cat >>/etc/yum.repos.dlepel.repo<<'EOF' [epel] name=epel repo baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch enabled=1 gpgcheck=O EOF
查看配置文件
rpm -qc ansible /etc/ansible/ansible.cfg /etc/ansible/hosts
ansible参数补全功能
ansible 2.9版本开始,它支持命令的选项补全功能,它依赖于python的argcomplete插件。
1)安装argcomplete:
# yum -y install python-argcomplete #或者任何系统都可以使用pip工具安装argcomplete,如下 # pip3 install argcomplete
2)安装完成后,还需要激活该插件
bash -version #要求bash版本大于或等于'4.2' GNU bash, 版本 4.2.46(2)-release (x86_64-redhat-linux-gnu) activate-global-python-argcomplete #激活插件
3) 重新进入bash环境测试是否可用
# bash # ansible --syntax-check #只需要输入ansible --syn 即可补全
什么是ansible的ad-hoc命令
ad-hoc命令是指使用 /usr/bin/ansible 命令行工具在一个或多个管理节点上执行单个任务的命令。
这其实是一个概念性的名字,是相对于 Ansible playbook 来说的。当我们需要快速的完成一些任务而不需要将执行的命令保存下来,这样的命令就称为ad-hoc命令。
命令结构
ansible [pattern] -m [module] -a "[module options]"
ansible:命令主体
pattern:指定该命令要在哪些管理节点或者哪组管理节点上执行,比如例子中的devops主机组。
-m [module]:指定该命令要执行哪个模块
-a [module options]:指定该模块执行时所需要的选项
配置ansible 的ssh免密登录
1、在control_node节点上生成密钥对:
ssh-keygen -t rsa -b 4096 ##当远程服务器默认的ssh 端口被更改 ssh-copy-id -p 28 root@192.168.40.132 在 /root/.ssh中添加ssh config cat config Host node3 HostName 192.168.40.135 Port 28 User root ServerAliveInterval 60 IdentityFile ~/.ssh/id_rsa Host node2 HostName 192.168.40.134 Port 28 User root ServerAliveInterval 60 IdentityFile ~/.ssh/id_rsa Host master HostName 192.168.40.132 Port 28 User root ServerAliveInterval 60 IdentityFile ~/.ssh/id_rsa 或者修改ansible.cfg remote_port = 28
###⒉、将各节点的主机信息(host key)写入control_node的~/.ssh/known_hosts文件:
for host in 192.168.200.{27..33} node{1..7}; do ssh-keyscan $host >>~/.ssh/known_hosts 2>/dev/null done
# sshpass -p选项指定的是密码
sshpass 命令的安装:
# yum -y install sshpass
####3.将control_node上的ssh公钥分发给各节点:
for host in 192.168.200.{27..33} node{1..7}; do sshpass -p'123456' ssh-copy-id root@$host &>/dev/null done
有时候为了方便快速寻找模块,可以使用ansible-doc -l | grep 'xxx’ 命令来筛选模块。
ansible-doc -l | grep copy
ansible-doc -s copy
ansible-doc copy
ansible读取配置文件的顺序
通过操作系统自带的包管理器安装的Ansible一般都会提供Ansible的配置文件/etc/ansible/ansible.cfg。
这是Ansible默认的全局配置文件。
实际上,Ansible支持4种方式指定配置文件,它们的读取顺序从高到低:
(1)、ansible_config:首先,Ansible命令会检查环境变量,及这个环境变量将指向的配置文件
(2)、.ansible.cfg:当前目录下的ansible.cfg
(3)、~/.ansible.cfg:家目录下的ansible.cfg
(4)、/etc/ansible/ansible.cfg:默认的全局配置文件
Ansible配置文件采用 ini 风格进行配置,每一项配置都使用key=value的方式进行配置。
三、定制演员表,即inventory主机清单
1.1 inventory文件路径
默认的inventory文件是/etcl/ansible/hosts,可以通过Ansible配置文件的inventory 配置指令去修改路径。
$ grep '/etc/ansible/hosts' letclansible/ansible.cfg
#inventory = /etc/ansible/hosts
但通常我们不会去修改这个配置项,如果在其它地方定义了inventory文件,可以直接在ansible的命令行中使用 -i 选项去指定我们自定义的inventory文件。
$ ansible -i /tmp/myinv.ini ... $ ansible-playbook -i /tmp/myinv.ini ...
1.2 配置inventory
Ansible inventory文件的书写格式遵循 ini 配置格式。从Ansible 2.4开始支持其它格式,比如yaml格式的inventory。此处以ini格式为例,循序渐进地介绍inventory的规则。假设所有的规则都定义在/etc/ansible/hosts文件中。
1.2.1 一行一主机的定义方式
Ansible默认是基于ssh连接的,所以一般情况下inventory中的每个目标节点都配置主机名或IP地址、sshd监听的端口号、连接的用户名和密码、ssh连接时的参数等等。当然,很多参数有默认值,所以最简单的是直接指定主机名或IP地址即可。
例如,在默认的inventory文件/etc/ansible/hosts添加几个目标主机:
node1 node2 ansible_host=192.168.200.28192.168.200.31 192.168.200.32:22 192.168.200.3[2:3] ansible_port=22
上面的inventory配置中:
(1).第一行通过主机名定义,在ansible连接该节点时会进行主机名DNS解析
(2).第二行也是通过主机名定义,但是使用了一个主机变量ansible_host=IP,此时Ansible去连接该主机时将直接通过IP地址进行连接,而不会进行DNS解析,所以此时的node2相当于是主机别名,它可以命名为任何其它名称,如node_2
(3).第三行通过IP地址定义主机节点
(4).第四行定义时还指定了端口号
(5).最后一行通过范围的方式展开成了两个主机节点192.168.200.32和192.168.200.33,同时还定义了这两个节点的主机变量ansible_port=22表示连接这两个节点时的端口号为22
范围展开的方式还支持字母范围。下面都是有效的:
- Ansible 可同时操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置. 默认的文件路径为 /etc/ansible/hosts
- /etc/ansible/hosts 例子
- mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com - [ ] 内为组名,用于对系统进行分类
- 一台服务器可以同时属于不同组
- 如果有主机的SSH端口不是标准的22端口,可在主机名之后加上端口号,用冒号分隔
四、ansible的剧本元素
1、role角色:Ansible-role-组团学 (zutuanxue.com)
role是task文件、变量文件、handlers文件的集合体,这个集合体的显著特点是:可移植性和可重复执行性。
通常文件如下,不一定必须都要有
files:用来存放由copy模块或script模块调用的文件。 tasks:至少有一个main.yml文件,定义各tasks。 handlers:有一个main.yml文件,定义各handlers。 templates:用来存放jinjia2模板。 vars:有一个main.yml文件,定义变量。 meta:有一个main.yml文件,定义此角色的特殊设定及其依赖关系。
实践中,通常我们以部署某个服务为单元作为一个role ,然后将这些服务单元(role)放在一个roles目录下。
主playbook文件通过调用roles目录下的role,来实现各种灵活多变的部署需求。
tree roles/consul roles/consul ├── tasks │ ├── actions │ │ ├── consul_core.yml.back │ │ ├── start_consul_agent.yml │ │ ├── start_registrator.yml │ │ ├── stop_consul_agent.yml │ │ └── stop_registrator.yml │ └── main.yml └── templates └── consul_server
五、ansible的优化
1、关闭gathering facts功能
gather_facts: False
2、开启SSH pipelining
pipeline是openssh的一个特性,ssh pipelining
是一个加速Ansible执行速度的简单方法。
在ansible执行每个任务的整个流程中,有一个过程是将临时任务文件put到远程的ansible客户机上,然后通过ssh
连接过去远程执行这个任务。如果开启了pipelining,一个任务的所有动作都在一个ssh
会话中完成,也会省去sftp
到远端的过程,它会直接将要执行的任务在ssh
会话中进行。ssh
pipelining 默认是关闭!!!!之所以默认关闭是为了兼容不同的sudo
配置,主要是 requiretty 选项。如果不使用sudo
,建议开启!!!
打开此选项可以减少ansible执行没有传输时ssh
在被控机器上执行任务的连接数。
不过,如果使用sudo
,必须关闭requiretty选项。修改/etc/ansible/ansible.cfg
文件可以开启pipelining
$ vim /etc/ansible/ansible.cfg ........ pipelining = True
但是要注意的是:
如果在ansible中使用sudo
命令的话(ssh user@host sudo cmd
),需要在被控节点的/etc/sudoers
中禁用"requiretty"
!!!!
之所以要设置/etc/sudoers
中的requiretty,是因为ssh
远程执行命令时,它的环境是非登录式非交互式shell,默认不会分配tty
,没有tty
,ssh
的sudo
就无法关闭密码回显(使用
"-tt"选项强制SSH分配tty
)。所以出于安全考虑,/etc/sudoers
中默认是开启requiretty的,它要求只有拥有tty
的用户才能使用sudo
,也就是说ssh
连接过去不允许执行sudo
。
可以通过visudo编辑配置文件,注释该选项来禁用它。
$ grep requiretty /etc/sudoers # Defaults requiretty
3、开启SSH长连接
ansible天然支持openssh,默认连接方式下,它对ssh
的依赖性非常强。所以优化ssh
连接,在一定程度上也在优化ansible。其中一点是开启ssh
的长连接,即长时间保持连接状态。Ansible模式是使用SSH和远程主机进行通信, 所以Ansible对SSH的依赖性非常强, 在OpenSSH 5.6版本以后SSH就支持了Multiplexing(多路复用)。所以如果Ansible中控机的SSH -V版本高于5.6时, 就可以使用ControlPersist来提高ssh
连接速度,从而提高ansible执行效率。
$ ssh -V OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017 $ vim /etc/ansible/ansible.cfg .......... ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d # 注意:ConrolPersist=5d, 这个参数是设置整个长连接保持时间为5天。
开启此参数的ssh
长连接功能后,在会话过期前会一直建立连接,在netstat
的结果中会看到ssh
连接是一直established状态,且通过SSH连接过的设备都会在当前用户家目录的
".ansible/cp"
目录下生成一个socket文件,每个会话对应生成一个socket文件。也可以通过netstat
命令查看, 会发现有一个ESTABLISHED状态的连接一直与远程设备进行着TCP连接。
$ ps -ef|grep ssh|grep ansible root 26064 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/cb9972d2a5 [mux] root 26067 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/baefa88ac8 [mux] $ ps -ef|grep ssh|grep /root root 26064 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/cb9972d2a5 [mux] root 26067 1 0 17:32 ? 00:00:00 ssh: /root/.ansible/cp/baefa88ac8 [mux] $ ls /root/.ansible/cp/ baefa88ac8 cb9972d2a5
ControlPersist即持久化socket,一次验证,多次通信。并且只需要修改 ssh
客户端就行,也就是 Ansible 机器即可。
4、设置facts缓存
使用json文件缓存
$ vim /etc/ansible/ansible.cfg ......... gathering = smart fact_caching_timeout = 86400 fact_caching = jsonfile fact_caching_connection = /dev/shm/ansible_fact_cache # 正常配置palybook,不需要关闭gathering facts功能 $ cat test.yml --- - hosts: 10.4.7.101 remote_user: root vars: - list: [1,2,3] tasks: - name: this is loop debug: msg="{{ item }}" with_items: '{{list}}' 查看这个playbook过程,用时6.699s(第一次可能稍微慢点,缓存之后,后面执行就很快了) $ time ansible-playbook test.yml PLAY [10.4.7.101] ******************************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************************** ok: [10.4.7.101] TASK [this is loop] ***************************************************************************************************************************** ok: [10.4.7.101] => (item=1) => { "msg": 1 } ok: [10.4.7.101] => (item=2) => { "msg": 2 } ok: [10.4.7.101] => (item=3) => { "msg": 3 } PLAY RECAP ************************************************************************************************************************************** 10.4.7.101 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 real 0m6.699s user 0m1.301s sys 0m0.250s # 如果去掉上面的facts缓存的四行配置,再次执行上面的playbok,发现用时10s左右!!! # 查看缓存文件 $ ls /dev/shm/ansible_fact_cache/ 10.4.7.101
使用redis存储facts文件需安装redis,还需要安装python库
$ yum install redis $ yum -y install epel-release $ yum install python-pip $ pip install redis $ vim /etc/ansible/ansible.cfg ........ gathering = smart facts_caching_timeout = 86400 #设置缓存过期时间86400秒 facts_caching = redis # 使用redis或者 (或者使用memcached,即"facts_caching = memcached") fact_caching_connection = 127.0.0.1:6379 #若redis设置了密码,比如密码为"admin",则配置修改如下: # fact_caching_connection = localhost:6379:0:admin $ systemctl start redis $ lsof -i:6379 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 26593 redis 4u IPv4 125427 0t0 TCP localhost:6379 (LISTEN) $ time ansible-playbook test.yml PLAY [10.4.7.101] ******************************************************************************************************************************* TASK [Gathering Facts] ************************************************************************************************************************** ok: [10.4.7.101] TASK [this is loop] ***************************************************************************************************************************** ok: [10.4.7.101] => (item=1) => { "msg": 1 } ok: [10.4.7.101] => (item=2) => { "msg": 2 } ok: [10.4.7.101] => (item=3) => { "msg": 3 } PLAY RECAP ************************************************************************************************************************************** 10.4.7.101 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 real 0m6.720s user 0m1.219s sys 0m0.338s 需要注意: 在使用redis缓存后,如果出现异常(若未出现,请忽略):TypeError: the JSON object must be str, not 'bytes'。 解决办法: $ find / -name ansible $ vim /usr/lib/python2.7/site-packages/ansible/plugins/cache/redis.py .......... self._cache[key] = json.loads(value.decode('utf-8')) # 修改为这个 查看redis存储情况 $ redis-cli 127.0.0.1:6379> keys * 1) "ansible_facts10.4.7.101" 2) "ansible_cache_keys"
5、Ansible取消交互
$ vim /etc/ansible/ansible.cfg ........ host_key_checking = False # 打开注释即可 # 取消ssh的yes和no的交互: $ vim /root/.ssh/config UserKnownHostsFile /dev/null ConnectTimeout 15 StrictHostKeyChecking no 或者直接ssh时增加一个参数 $ ssh -o StrictHostKeyChecking=no -p22 root@10.4.7.101
https://www.cnblogs.com/mauricewei/p/10056458.html ansible基础-roles
https://www.zsythink.net/archives/3021 朱双印的ansible合集,十分不错
https://www.cnblogs.com/mauricewei/tag/ansible/ 个人整理的ansible集合,不错
https://blog.51cto.com/9019400/2385520 ansible-playbook用法范例总结