ansible基础(1)
目录
我叫张贺,贪财好色。一名合格的LINUX运维工程师,专注于LINUX的学习和研究,曾负责某中型企业的网站运维工作,爱好佛学和跑步。
个人博客:传送阵
笔者微信:zhanghe15069028807
,非诚勿扰。
一、基础概念
ansible是什么?
ansible是通过调用ssh协议进行批量配置和管理的软件。
为什么用ansible?
如果我们只有两台主机,根本没必要用ansible,但是假如我们有50多台主机,要统一进行修改配置,一台台的改工作量太大了,我们这时就可以用ansible工具,统一对50台主机同时进行连接并修改配置,仅需要一次的操作,减少重复性的操作,大大提高了运维人员的效率。
ansible可以做些什么?
- 批量命令执行
- 批量同步配置文件
- 批量代码部署
ansible的特点和优势
只需要在控制端安装ansible软件,受控端保证ssh正常运行即可,并不用启动服务。
修改配置之后不用重读,立马生效。
模块相当于ansible的命令,而playbook相当于脚本。
ansible的架构组成
host inventory:主机清单
playbook:任务剧本
core modules:核心模块
commection plugin:连接插件
ansible的执行流程
- ansible读取playbook中的剧本,剧本中会记录将要对哪些主机执行哪些任务。
- ansible通过主机清单找到要执行的主机,然后调用具体的模块(相当于不同功能的命令)
- 然后,通过连接插件连接对应的主机下发任务列表。
- 最后受控端主机将下发来的任务解析成本地shell命令执行。
怎么用ansible?
至于怎么用ansible,那正是这一节的主要内容所在。
与ansible同类型的工具,比较出名的就属salstack
二、基本操作
安装
安装之前准备epel源:
yum -y install ansible ansible --version ansible 2.9.1
推送公钥
ansible默认是使用公钥进行连接受控端的,在使用ansible之前要先将ansible的公钥推送到三台受控端。
如果受控端数量较少,可以手动推送公钥,如果受控端数量较多,就使用脚本推送公钥。当前受控端有三台主机
- 192.168.80.62
- 192.168.80.63
- 192.168.80.64
手动推送公钥的步骤:
主控端ansible通过
ssh-keygen
生成一对密钥,会自动存放在家目录的.ssh/authorized_keys文件下然后通过ssh-copy-id把公钥上传到被控端,会自动保存在目的用户家目录下的.ssh/
//生成公钥,一路回车 [ ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created directory '/root/.ssh'. 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:GS0Cof8VpoMGy9QfS9ICN1ZFrpwWHo5ED9zrPYBSZlo The key's randomart image is: +---[RSA 2048]----+ | ..O+.oo | | BE*.. . | | +*=.O.* . | | @ = | | o.=.%oS | | . o.oo | | . . | | | | | +----[SHA256]-----+ //发现有两个密钥 [ .ssh]# ls id_rsa id_rsa.pub //这样就可以推送了,交互式输入yes和被控端的密码 [ ~]# ssh-copy-id 192.168.80.62
脚本推送公钥的步骤:
//找个文件把受控端IP和密码写好,中间用空格隔开 [ ~]# cat host 192.168.80.62 cba-123 192.168.80.63 cba-123 192.168.80.64 cba-123 [ ~]# vim push_pub_key.sh #!/bin/bash #先定义一个函数expect expect () { /usr/bin/expect <<-EOF spawn ssh-copy-id $ADDR expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send $PASSWD\r } } expect eof EOF } #函数在此结束 SERVERHOST=./host for ADDR in `cut -d" " -f1 $SERVERHOST`;do #这一cut把所有的ip全都列出来了 PASSWD=$(grep $ADDR $SERVERHOST | cut -d" " -f2) test -f ~/.ssh/id_rsa if [ $? -ne 0 ];then ssh-keygen -P "" -f ~/.ssh/id_rsa &>/dev/null expect echo "key already send!" else expect echo "key already send!!" fi done
由于此章节是讲
ansible
,所以对shell
脚本不做过多的解释,如果想看具体的解释,请点击我的博客链接,传送门
定义主机清单
所谓的定义主机清单就是告诉ansible程序,要连接哪些主机的IP,也可以使用主机名,支持组;
[ ~]# vim /etc/ansible/hosts [test] 192.168.80.62 192.168.80.63 192.168.80.64
//列出test组的主机 [ ~]# ansible test --list-host hosts (3): 192.168.80.62 192.168.80.63 192.168.80.64 //列出所有主机 [ ~]# ansible all --list-host hosts (3): 192.168.80.62 192.168.80.63 192.168.80.64
推送完公钥、定义完主机清单,测试一下是否可以使用了,用ping模块,这个模块不是网络当中的ping,而仅是测试ansible与受控端的连通性而已。
//ansible后面直接跟组名,-m是指定模块,这里我们使用ping模块,测试成功,全是绿色的。 [ ~]# ansible test -m ping 192.168.80.62 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 192.168.80.63 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 192.168.80.64 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" }
- 绿色代表被管理主机没有被修改
- 黄色代表被管理主机发现变更
- 红色代表出现故障,注意查看提示原因
ad-hoc(远程执行命令)
什么是ad-hoc?
其实就是远程对主机清单里面的主机执行命令,这些命令是临时执行,执行完就结束了,并不会保存。
ad-hoc的使用场景
比如在多台机器上查看某个进程是否启动
ad-hoc的格式
ansible -m -a
模块可以不写,默认是command,如ansible test -m command -a ‘hostname‘
可以简写成如下格式:
//ansible后面直接写组名,-a 后面加上单引号,把命令引起来就可以了 [ ~]# ansible test -a 'hostname' 192.168.80.64 | CHANGED | rc=0 >> backup 192.168.80.63 | CHANGED | rc=0 >> nfs 192.168.80.62 | CHANGED | rc=0 >> nginx
ad-hoc缺点就是不太支持管道和&符号,一用就报错,如果想让其支持管道的话,就用shell模块,如下
//在command模块中使用管道会报错,红色 [ ~]# ansible test -a 'df -h | head -2' 192.168.80.64 | FAILED | rc=1 >> df: invalid option -- '2' Try 'df --help' for more information.non-zero return code 192.168.80.62 | FAILED | rc=1 >> df: invalid option -- '2' Try 'df --help' for more information.non-zero return code 192.168.80.63 | FAILED | rc=1 >> df: invalid option -- '2' Try 'df --help' for more information.non-zero return code //使用shell模块就好了 [ ~]# ansible test -m shell -a 'df -h | head -2' 192.168.80.62 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 45G 1.7G 44G 4% / 192.168.80.63 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 45G 1.7G 44G 4% / 192.168.80.64 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 45G 1.7G 44G 4% /
shell模块是万能的,啥都能执行,那我们干脆只学shell模块不就行了,干吗还要学习其他的模块呢?是因为shell模块不管对方是什么状态,都要将命令在对方执行一次,而其他模块会判断,判断对方当前的状态是什么,如果的对方的状态就是我们希望的,那就不执行,如果不是,就执行,这样多好,我们下面来举一个例子:
[ ~]# ansible test -m shell -a 'yum -y install vim'
上述命令,无论你执行多少次都会显示黄色,而黄色代表对方被更改,其实只有第一次被更改,后面都是重复的,按理说除了第一次都应该显示绿色,但是通过shell模块不会判断对方的状态,我们如果使用专门的安装模块结果就变成我们想要的,如果受控端已经安装了vim,就不会再执行安装了,不被更改就显示绿色,如下所示:
[ ~]# ansible-doc yum #找到帮助示例学习一下yum模块的使用 EXAMPLES: - name: install the latest version of Apache #将这个安装apache的写法转换成临时命令的写法 yum: name: httpd #模块是httpd state: latest #方法是latest(更新),absent(移除),present(安装) [ ~]# ansible test -m yum -a 'name=vim state=present'