一、ansible介绍

ansible是一个同时管理多个远程主机的软件,必须是任意可以通过ssh登录的机器,隐藏ansible可以管理的机器如

  • 远程虚拟机
  • 物理机
  • 可以直接管理本机机器
    ansible通过ssh协议实现了,管理节点,被管理接待你的通信。
    只能是通过ssh协议邓丽的主机,就可以完成ansible自动化部署操作
  • 批量文件分发
  • 批量数据复制
  • 批量数据修改,删除
  • 批量自动化安装软件服务
  • 批量服务启停
  • 脚本化、自动批量服务部署

ansible特点
ansible的编排引擎可以完成各种出色的任务任务,ansible在流程控制,资源部署方便很强大,并且ansible无须安装客户端软件,管理简洁,使用yaml配置文件语法,功能强大,便于维护。
ansible是基于python语言开发,主要由python的两个ssh处理模块,paramikl以及pyyaml模块

  • 安装部署简单
  • 管理主机便携,支持堕胎主机管理
  • 无须安装客户端,且无需占用客户端的其他端口,仅仅使用ssh服务即可
  • 不仅仅支持python,还支持其他语言二次开发
  • 不用root用户也可以执行,降低系统权限

二、Ansible实施部署

1、准备好虚拟机

准备好3台Linux虚拟机,配置在同一个局域网内,然后设置好静态IP
master   192.168.29.152  管理机
node1    192.168.29.137  被管理机
node2    192.168.29.134  被管理机

2、先准备ansible管理机器

1、选择yum自动化安装
yum install epel-release -y
yum install ansible libselinux-python -y
2、安装情况
[root@master ~]# rpm -ql ansible|grep -E '^/etc|^/usr/bin'
/etc/ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
/etc/ansible/roles
/usr/bin/ansible
/usr/bin/ansible-2
/usr/bin/ansible-2.7
/usr/bin/ansible-config
/usr/bin/ansible-connection
/usr/bin/ansible-console
/usr/bin/ansible-console-2
/usr/bin/ansible-console-2.7
/usr/bin/ansible-doc
/usr/bin/ansible-doc-2
/usr/bin/ansible-doc-2.7
/usr/bin/ansible-galaxy
/usr/bin/ansible-galaxy-2
/usr/bin/ansible-galaxy-2.7
/usr/bin/ansible-inventory
/usr/bin/ansible-playbook
/usr/bin/ansible-playbook-2
/usr/bin/ansible-playbook-2.7
/usr/bin/ansible-pull
/usr/bin/ansible-pull-2
/usr/bin/ansible-pull-2.7
/usr/bin/ansible-vault
/usr/bin/ansible-vault-2
/usr/bin/ansible-vault-2.7
3、查看版本
[root@master ~]# 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, Mar 12 2021, 14:55:44) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44.0.3)]

3、准备被管理机

安装ansible模块

yum install -y epel-release libseliunx-python -y

三、Ansible管理方式

1、ansible批量管理主机方式主要有两种

  • 传统的输入ssh密码验证
  • 密钥管理

配置好ansible的配置文件,添加被管理机的ip,或者主机名
1.备份现有的配置文件
cp /etc/ansible/hosts{,.ori} ##将hosts文件拷贝出一个hosts.ori的文件
2.配置host文件,添加被管理的主机IP
[root@master ansible]# tail -3 hosts
[test]
node1 #可以是ip地址,可以是主机名
node2

2、ssh密码认证方式管理机器

ansible是直接利用linux本地的ssh服务,以及一些远程的ssh操作,一般情况下客户的ssh服务默认都是开启的,无须额外管理

1.在管理机上执行如下命令 -m是指功能模块(command是命令)
ansible 主机列表 -m command -a ‘hostname’ -k -u root #输出所有列表主机的主机名
2.以上命令第一次运行时可能会报错,此时需要手动连接一下被管理主机

[root@master ansible]# ansible test -m command -a 'hostname' -k -u root
SSH password:
node1 | CHANGED | rc=0 >>
node1
node2 | CHANGED | rc=0 >>
node2

常用参数

命令

说明

-m

要执行的模块,默认为command

-a

指定模块的参数

-u

ssh连接的用户名,默认用root,ansible.cfg中可以配置

-b,–become

变成那个用户身份,不提示密码

-k

提示输入ssh登录密码,当使用密码验证的时候用

-s

sudo运行

-U

sudo到哪个用户,默认为root

-K

提示输入sudo密码,当不是NOPASSWD模式时使用

-C

只是测试一下会改变什么内容,不会真正去执行

-c

连接类型(default=smart)

-f

fork多少进程并发处理,默认为5个

-i

指定hosts文件路径,默认default=/etc/ansible/hosts

-I

指定pattern,对已匹配的主机中再过滤一次

-list-host

只打印有哪些主机会执行这个命令,不会实际执行

-M

要执行的模块路径,默认为/usr/share/ansible

-o

压缩输出,摘要输出

–private-key

私钥路径

-T

ssh连接超时时间,默认是10秒

-t

日志输出到该目录,日志文件名以主机命名

-v

显示详细日志

3、配置免密登录

每次执行ansible命令的时候,都需要输入ssh认证密码,也就是root密码,如果不同的主机密码不一致,那还有多次输入才行

ansible自带的密码认证参数

可以在 /etc/ansible/hosts文件中,定义好密码即可,
参数
ansible_host 主机地址
ansible_port 端口,默认22端口
ansible_user 认证用户
ansible_ssh_pass 用户认证密码

修改如下:

[root@master ansible]# tail -5 hosts
[test]
master ansible_user=root ansible_ssh_pass=root
node1 ansible_user=root ansible_ssh_pass=root
node2 ansible_user=root ansible_ssh_pass=root

效果:

[root@master ansible]# ansible test -m command -a 'hostname'
node2 | CHANGED | rc=0 >>
node2
node1 | CHANGED | rc=0 >>
node1
master | CHANGED | rc=0 >>
master

4、ssh密钥方式批量管理主机(这个方法不用手动首次连接)

以上的密码认证方式,存在密码泄露的风险,所以可以用hosts文件的密码参数来连接,更加安全

1.在管理机上创建ssh密钥对
ssh-keygen -f ~/.ssh/id_rsp -P “” > /dev/null 2>&1 ##创建密钥对,”-p "指忽略输入密码 并将密钥文件放在~/.ssh/目录下的id_rsp文件中,不在运行过程中输出任何内容。

内容如下:

[root@master /]# mkdir mysh
[root@master /]# cd mysh/
[root@master mysh]# touch ssh_key_send.sh
[root@master mysh]# cat ssh_key_send.sh
#!/bin/bash
rm -rf ~/.ssh/id_rsa*
ssh-keygen -f ~/.ssh/id_rsa -P "" > /dev/null 2>&1
SSH_Pass=root
touch ~/.ssh/id_rsa.pub
Key_Path=~/.ssh/id_rsa.pub
for ip in master node1 node2
do
  sshpass -p$SSH_Pass ssh-copy-id -i $Key_Path "-o StrictHostKeyChecking=no" $ip
done
# 非交互式分发公钥命令需要用sshpass指定SSH密码,通过-o StrictHostKeyChecking=no 跳过SSH连接确认信息
[root@master mysh]# sh ssh_key_send.sh
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/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

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o ' StrictHostKeyChecking=no' 'master'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/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

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o ' StrictHostKeyChecking=no' 'node1'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/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

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o ' StrictHostKeyChecking=no' 'node2'"
and check to make sure that only the key(s) you wanted were added.

此时连接被控制机器就不用输出密码了

输入:ssh -o ’ StrictHostKeyChecking=no’ ‘node1’ 即可直接连接到node1机器上去

[root@master mysh]# ssh -o ' StrictHostKeyChecking=no' 'node1'
Last login: Mon Apr 11 11:25:11 2022 from master
[root@node1 ~]#

ansible的hosts文件里面也不用配置用户名和密码了

[root@master ansible]# tail -7 hosts
[test]
#master ansible_user=root ansible_ssh_pass=root
#node1 ansible_user=root ansible_ssh_pass=root
#node2 ansible_user=root ansible_ssh_pass=root
master
node1
node2
[root@master ansible]# ansible test -m command -a "uname -a"
node2 | CHANGED | rc=0 >>
Linux node2 3.10.0-1062.el7.x86_64 #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
node1 | CHANGED | rc=0 >>
Linux node1 3.10.0-1062.el7.x86_64 #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
master | CHANGED | rc=0 >>
Linux master 4.14.35-2047.506.8.el7uek.x86_64 #2 SMP Tue Aug 3 20:05:09 PDT 2021 x86_64 x86_64 x86_64 GNU/Linux

总结

在生产环境中,ansible的连接方式,二选一,最好使用ssh公钥免密登录。

四、ansible模式与命令

ansible实现批量化主机管理模式,主要有两种

  • 利用ansible的纯命令行实现的批量管理,ad-hoc模式(命令管理)
  • 利用ansible的playbook剧本来实现批量管理,playbook剧本管理(shell脚本管理)

Ansible 模块精讲

查看支持的模块

ansible-doc -f

1、comand模块

作用:在远程节点上执行一个命令
ansible-doc -s command 查看该模块支持的参数

命令

说明

chdir

在执行命令之前,先通过cd进入参数指定的目录

creates

在创建一个文件之前,判断该文件是否存在,如果存在了则跳过前面的东西,如果不存在则执行前面的动作

free_form

该参数可以输入任何的系统命令,实现远程执行和管理

removes

定义一个文件是否存在,如果存在了则执行前面的动作,如果不存在则跳到动作

command模板是ansible的默认基本模块,也可以省略不写,但是要注意如下的坑

  • 使用command模块,不得出现shell变量$name,也不得出现特殊符号< > | ; &这些符号command模块都不认识,如果你前面指定的变量,特殊符号,请使用shell模块。
command模块案例

获取所有被管理机器的负载信息

[root@master ~]# ansible test -m command -a "uptime"
node2 | CHANGED | rc=0 >>
 14:23:39 up  4:19,  2 users,  load average: 0.11, 0.17, 0.20
node1 | CHANGED | rc=0 >>
 14:23:40 up  4:23,  2 users,  load average: 0.25, 0.22, 0.26
master | CHANGED | rc=0 >>
 14:23:40 up  4:20,  3 users,  load average: 2.30, 1.34, 1.01

让客户机,先切换到/tmp目录下,然后输出当前的目录位置。

[root@master ~]# ansible test -m command -a "pwd chdir=/tmp"
node1 | CHANGED | rc=0 >>
/tmp
node2 | CHANGED | rc=0 >>
/tmp
master | CHANGED | rc=0 >>
/tmp

练习creates参数
在创建一个文件之前,判断该文件或者文件夹是否存在,如果存在了则跳过前面的东西,如果不存在则执行前面的动作

判断node1主机的是否存在tmp这样的根目录,如果存在,则不执行前面的pwd,如果不存在则执行前面的pwd

[root@master ~]# ansible node1 -m command -a "pwd creates=/tmp"
node1 | SUCCESS | rc=0 >>
skipped, since /tmp exists

参数removes实践,存在则执行,不存在则跳过

[root@master ~]# ansible test -m command -a "ls /opt removes=/tmp"
node1 | CHANGED | rc=0 >>
cni
jdk1.8.0_281
jdk-8u281-linux-x64.tar.gz
mqm
nginx
node2 | CHANGED | rc=0 >>
cni
containerd
jdk1.8.0_281
jdk-8u281-linux-x64.tar.gz
mqm
nginx
src
ssh
master | CHANGED | rc=0 >>
apache-tomcat-9.0.46
apache-tomcat-9.0.46.tar.gz
cni
containerd

warn参数 是否提供告警信息

[root@master ~]# ansible test -m command -a "chmod 000 /etc/hosts"
[WARNING]: Consider using the file module with mode rather than running 'chmod'.  If you need to use command because file is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
node2 | CHANGED | rc=0 >>
node1 | CHANGED | rc=0 >>
master | CHANGED | rc=0 >>
[root@master ~]# ansible test -m command -a "chmod 000 /etc/hosts warn=False"
node1 | CHANGED | rc=0 >>
node2 | CHANGED | rc=0 >>
master | CHANGED | rc=0 >>

shell模块

作用:在远程机器上执行命令(复杂的命令)
shell模块支持的参数和模块

参数

解释

chdir

在执行命令之前,先通过cd进入参数指定的目录

creates

在创建一个文件之前,判断该文件是否存在,如果存在了则跳过前面的东西,如果不存在则执行前面的动作

free_form

该参数可以输入任何的系统命令,实现远程执行和管理

removes

定义一个文件是否存在,如果存在了则执行前面的动作,如果不存在则跳到动作

warn

是否输出报警

shell模块案例

[root@master ~]# ansible test -m shell -a "ps -ef|grep ssh|grep -v grep"
node2 | CHANGED | rc=0 >>
root       1045      1  0 10:04 ?        00:00:00 /usr/sbin/sshd -D
root      52836   1045  0 14:42 ?        00:00:01 sshd: root@pts/0
master | CHANGED | rc=0 >>
root       1388      1  0 10:04 ?        00:00:00 /usr/sbin/sshd -D
root      63961   1388  0 14:07 ?        00:00:00 sshd: root@pts/1
node1 | CHANGED | rc=0 >>
root       1046      1  0 10:00 ?        00:00:00 /usr/sbin/sshd -D
root      79980   1046  5 15:14 ?        00:00:00 sshd: root@pts/0

批量执行脚本,必须要求脚本在客户端机器上要存在,这是shell模块的特点,是因为还有一个专门执行脚本的script模块
1.创建文件夹
2.创建sh脚本文件,还有写入脚本内容
3.赋予脚本可执行权限
4.执行脚本
5.忽略warning信息

[root@master tmp]# ansible test -m shell -a "mkdir -p /tmp/myscriptes/;echo 'hostname' > /tmp/myscriptes/hostname.sh;chmod +x /tmp/myscriptes/hostname.sh;sh /tmp/myscriptes/hostname.sh warn=False"
node1 | CHANGED | rc=0 >>
node1
node2 | CHANGED | rc=0 >>
node2
master | CHANGED | rc=0 >>
master
[root@master tmp]# ll
总用量 8
-rw-r--r-- 1 root     root       13 4月  11 15:17 hahah.txt
drwxr-xr-x 2 root     root       25 4月  11 15:28 myscriptes

script模块

功能:把管理机上的脚本远程传输到被管理的机上去执行
script模块参数

参数

解释

chdir

在执行命令之前,先通过cd进入参数指定的目录

creates

在创建一个文件之前,判断该文件是否存在,如果存在了则跳过前面的东西,如果不存在则执行前面的动作

free_form

该参数可以输入任何的系统命令,实现远程执行和管理

removes

定义一个文件是否存在,如果存在了则执行前面的动作,如果不存在则跳到动作

warn

是否输出报警

应用案例

1.在管理节点上创建一个脚本
[root@master myscriptes]# echo -e “pwd\nhostname”> ./local_hostname.sh
[root@master myscriptes]# cat local_hostname.sh
pwd
hostname
2.赋权
[root@master myscriptes]# chmod +x local_hostname.sh

远程执行脚本,且在被管理机上不需要存在该脚本

[root@master myscriptes]# ansible test -m script -a "local_hostname.sh"
node1 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to node1 closed.\r\n",
    "stderr_lines": [
        "Shared connection to node1 closed."
    ],
    "stdout": "/root\r\nnode1\r\n",
    "stdout_lines": [
        "/root",
        "node1"
    ]
}
node2 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to node2 closed.\r\n",
    "stderr_lines": [
        "Shared connection to node2 closed."
    ],
    "stdout": "/root\r\nnode2\r\n",
    "stdout_lines": [
        "/root",
        "node2"
    ]
}
master | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to master closed.\r\n",
    "stderr_lines": [
        "Shared connection to master closed."
    ],
    "stdout": "/root\r\nmaster\r\n",
    "stdout_lines": [
        "/root",
        "master"
    ]
}