ansible混合知识点

一、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,没有ttysshsudo就无法关闭密码回显(使用
"-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用法范例总结

posted @ 2021-09-22 23:59  凡人半睁眼  阅读(307)  评论(0编辑  收藏  举报