文章目录

  • ansible初步了解
  • ansible概述
  • ansible作用
  • ansible特点
  • ansible 结构
  • ansible配置文件查找顺序
  • ansible执行方式
  • ansible工作原理
  • 总结
  • ansible练习环境
  • 机子情况
  • control配置
  • ansible ad-hoc命令集执行
  • 格式
  • 案例练习(上面的配置环境 ping command模块)
  • shell模块
  • script模块
  • 说明
  • file模块
  • 说明
  • 过程
  • 格式
  • 测试
  • copy模块
  • 说明
  • 格式
  • 测试
  • fetch模块
  • 说明
  • 格式
  • 测试
  • lineinfile | replace 模块
  • 说明
  • 案例
  • user模块
  • 参数说明
  • 测试
  • yum_repository模块
  • 说明
  • 测试
  • yum模块
  • 说明
  • 测试
  • service模块
  • 说明
  • 测试
  • lvg lvol 模块
  • 说明
  • 测试
  • 相关模块参数


ansible初步了解

ansible概述

ansible作用
  • 批量系统配置
  • 批量程序部署
  • 批量运行命令等功能
ansible特点
  • 并发控制
  • python写的 所以运行环境需要python 最小化安装的linux有python 控制端和被控制端都要有python环境
  • 基于SSH架构 自动化要求肯定不能输密码 所以需要ssh-keygen ssh-copy-id来解决密码
  • 模块丰富 自带2800个模块
  • 支持自定义模块
  • 支持异构IT架构
ansible 结构

ansible是基于模块工作的,本身没有批量部署的功能,真正具有批量部署的是ansible所运行的模块,ansible只是提供一个框架 模块是python写的,支持自定义模块是这么个机制~

  • 连接插件connection plugins:负责和被监控端实现通信
  • host inventory:指定操作的主机,是一个配置文件里面定义监控的主机
  • 各种模块核心模块、command模块、自定义模块
  • 借助于插件完成记录日志邮件等功能
  • playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务

摘自百度百科

ansible配置文件查找顺序
  1. 查找ANSIBLE_CONFIG变量定义的配置文件(优先级最高)
  2. 查找当前目录下的./ansible.cfg
  3. 再次检查当前用户家目录下~/ansible.cfg
  4. 最后检查/etc/ansible/ansible.cfg (有种从近到远的过程
ansible执行方式
  • ad-hoc 命令集方式
  • playbook 脚本执行方式
ansible工作原理
  1. ansible基于SSH远程管理被管理的主机
  2. 控制端主机将模块(脚本)或命令传给被控制端主机
  3. 在被控制端主机执行模块(脚本)或命令
  4. 退出SSH远程(删除远程时的一些临时文件)
总结
  • 对ansible有了一个大概的印象,python写的一个基于ssh的框架,用来并发控制其他机子的一个工具
  • 模块需要一些参数来完成工作 感觉这话有点多余了 没有参数怎么灵活控制

ansible练习环境

机子情况
  • 192.168.4.253 control 控制端
  • 192.168.4.11 node1
  • 192.168.4.12 node2
  • 192.168.4.13 node3
  • 192.168.4.14 node4
  • 192.168.4.15 node5
control配置
vim /etc/hosts
============================
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.4.253 control             #添加对应的域名解析
192.168.4.11 node1
192.168.4.12 node2
192.168.4.13 node3
192.168.4.14 node4
192.168.4.15 node5
=============================
#ping node1~5 测试一下 都ping的通就好 
ssh-keygen  #生成ssh密钥
for i in node1 node2 node3 node4 node5  #/etc/hosts文件本身的意义就是类似变量的 但是只在ip相关命令中被解析
>do 
>ssh-copy-id  $i      #变量重复发送到五台被控制机子  node1~5的含义是在这部被解析的 这里还是node1~5
>done
#到这里输完密码没报错就算配置完成大半部分了

#测试上面的说法
node1="3"  #修改一个值
for i in node1 node2 node3 node4 node5
>do
>echo $i
>done
node1               #如果是我想错的那样 这里的输出应该是3 ....192.168.4.15
node2				#不过直接输出了node1~5
node3
node4
node5
#从这里看出    /etc/hosts下面的域名解析只会发生在相应命令位置



#下载ansible_soft.tar.gz
tar -xf ansible_soft.tar.gz  #就地解压
cd ansible_soft				#进去
ls
ansible-2.8.5-2.el8.noarch.rpm           python3-paramiko-2.4.3-1.el8.noarch.rpm
libsodium-1.0.18-2.el8.x86_64.rpm        python3-pynacl-1.3.0-5.el8.x86_64.rpm
python3-bcrypt-3.1.6-2.el8.1.x86_64.rpm  sshpass-1.06-9.el8.x86_64.rpm

dnf -y install *   #直接安装  当前目录下一堆rpm包 直接全装


mkdir ~/ansible/ansible.cfg    #创建家目录下的配置文件
vim ~/ansible/ansible.cfg
#末行模式输入:r /etc/ansible/ansible.cfg 来读取模板
==========================================
inventory=~/ansible/inventory                    #设置主机清单文件为家目录下的ansible/inventory
#forks=5    						#ssh并发数量并发控制基础
#ask_pass = True					#使用密钥还是密码远程登录, True使用密码 默认false
#host_key_checking = False			#是否校验密钥(第一次提示yes/no)
==========================================

vim ~/ansible/inventory #写主机清单文件了  上面主配置文件指定的
============================================
[test]
node1           #实际可写ip
[proxy]
node2
[webserver]
node[3:4]   #python里面的切片格式
[database]
node5
[cluster:children]    #cluster 自己定义的嵌套组名字 :childre固定格式
webserver
database            
[woxiaxiedezu]   #一个组下两个主机需要分行写?
node1
node2

#发生了啥   [test] 定义一个叫做test的组 组下有台机子node1
#[cluster:children]  定义一个叫做cluster嵌套组   组下有webserver和database两个组 
#  [test]      [proxy]    [webserver] [database]         [cluster]
#    |           |           /  \        |               /        \
#  node1        node2     node3  node4  node5    [webserver]     [database]
============================================================================


#配置完了

ansible ad-hoc命令集执行

格式
  • ansible 主机集合(上面主机清单文件[]中的) -m 模块名 -a “参数”
案例练习(上面的配置环境 ping command模块)
cd /mnt
ansible all --list-hosts
#格式  ansible 主机集合 ......
hosts(0): #找不到很正常  先找ANSIBLE_CONFIG 再找当前目录下的ansible.cfg(藏在~/ansible目录下了) 再找~(同样找不到) 最后找/etc/ansible/(没配置)  所有0

cd ~/ansible                  #到自己定义的目录下
ansible all --list-hosts   #查看所有主机的列表
  hosts (5):
    node1
    node2
    node3
    node4
    node5
#有了   基本可以判断ansible查找配置文件的顺序了

ansible node1 -m ping      #对node1调用ping模块
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

ansible test -m ping   #使用组名看看  也可以使用 

##ping模块说明
#该模块虽然叫ping,但是它不会发送任何ICMP协议的ping数据包,控制端主机仅仅是ssh远程被管理端主机,检查其是否有python环境,能顺利远程并且有Python环境就会返回正确的提示信息,否则报错

ansible test -m command -a "ls"
node1 | CHANGED | rc=0 >>
anaconda-ks.cfg                       #返回了   command为默认模块   可以不写

ansible all -a "pwd"				#对所有机子操作pwd
node2 | CHANGED | rc=0 >>		
/root

node1 | CHANGED | rc=0 >>
/root

node4 | CHANGED | rc=0 >>
/root

node3 | CHANGED | rc=0 >>
/root

#主机名   状态码	返回结果
node5 | CHANGED | rc=0 >>
/root
#从返回结果来看    并不是顺序执行  而是并发的

ansible-doc -l   #列出所有模块
ansible-doc -l | grep xxx #在所有模块中过滤出关键词
ansible-doc ping #查看模块帮助  shell里面的 xxx --help  man xxx类似
shell模块
  • 与command模块区别 支持
  • 命令历史
  • 命令别名
  • 标准输入输出
  • 重定向
  • 管道操作
cd ~/ansible
ansible test -m shell -a "touch 1.txt;ls"  #在test组所有机子 在当前目录创建1.txt并显示
 [WARNING]: Consider using the file module with state=touch rather than running 'touch'.  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.

node1 | CHANGED | rc=0 >>
1.txt
anaconda-ks.cfg
#创建文件有警告是正常现象 

ansible test -m shell -a "ps aux | wc -l"   #shell支持管道
node1 | CHANGED | rc=0 >>
144
script模块
说明

script模块会把-a后面的脚本拷贝到被管理端主机,然后执行这个脚本

vim /opt/test.sh
======================
#!/bin/bash
dnf -y install httpd
systemctl start httpd
========================
ansible test -m shell -a "/opt/test.sh"  #发送/opt/test.sh过去 并执行
#执行成功
curl node1  #在关闭node1防火墙的情况下能返回网页信息   也可以直接去node1查看服务开了没

#有问题   脚本发送过去如果需要参数有办法解决吗
file模块
说明

file模块可以创建文件、目录、链接;修改权限与属性等

过程
  1. 控制端主机将file.py拷贝到被控制端机子
  2. 被控制机子执行./file.py path=… state=…(执行python脚本 提供参数)
  3. 控制端退出ssh远程连接 并且删除远程时的一些临时文件
格式
  • ansible 主机名 -m file -a “path= state=…”
  • path后面指定文件路径
  • state指定类型 touch创建文件 directory创建目录 absent 删除文件或目录 link 创建软连接(配合src 源文件 path 目标文件名)
  • group 修改组 owner 修改用户 mode 修改权限
测试
ansible test -m file -a "path=/root/2.txt state=touch owner=root group=root mode=0777"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "dest": "/root/2.txt",
    "gid": 0,
    "group": "root",
    "mode": "0777",
    "owner": "root",
    "secontext": "unconfined_u:object_r:admin_home_t:s0",
    "size": 0,
    "state": "file",
    "uid": 0
}
#返回创建成功了

#创建2.txt的软连接文件fr.txt   src 源文件   path 目标文件    link软连接
ansible test -m file -a "src=/root/2.txt path=/root/fr.txt state=link"
 node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "dest": "/root/fr.txt",
    "gid": 0,
    "group": "root",
    "mode": "0777",
    "owner": "root",
    "secontext": "unconfined_u:object_r:admin_home_t:s0",
    "size": 11,
    "src": "/root/2.txt",
    "state": "link",
    "uid": 0
}
#创建软连接成功
copy模块
说明

可以将文件拷贝到远程主机 可以拷贝目录

格式
  • ansible 主机名 -m copy -a “src=要拷贝的文件 dest=目标”
测试
echo "i got it " > ~/3.txt
ansible test -m copy -a "src=~/3.txt dest=/root/"  #复制本机~/3.txt到test组的/root/下

node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum": "657b21bf0893743866dc86df2bf780a18b4086e9",
    "dest": "/root/3.txt",
    "gid": 0,
    "group": "root",
    "md5sum": "3a7897518ef773d85b83dc6574ecce47",
    "mode": "0644",
    "owner": "root",
    "secontext": "system_u:object_r:admin_home_t:s0",
    "size": 10,
    "src": "/root/.ansible/tmp/ansible-tmp-1608302189.1124063-63008731291977/source",
    "state": "file",
    "uid": 0
}
fetch模块
说明

将控制端文件拷贝到本地 如果要拷贝目录到控制端 打包再传回来

格式
  • ansible 主机名 -m fetch -a “src=被控制端源文件 dest=控制端目标”
测试
ansible test -m fetch -a "src=/etc/hostname dest=~/" #将test组下的/etc/hostname拷贝到~下
#我临时修改了test组为node1 node2 想看下怎么命名
node1 | CHANGED => {
    "changed": true,
    "checksum": "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83",
    "dest": "/root/node1/etc/hostname",
    "md5sum": "d8e8fca2dc0f896fd7cb4cb0031ba249",
    "remote_checksum": "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83",
    "remote_md5sum": null
}
node2 | CHANGED => {
    "changed": true,
    "checksum": "3cb438759c17d04d1a176fea1a589a75349e1b72",
    "dest": "/root/node2/etc/hostname",
    "md5sum": "0e996583b4206e9685e5d69e2af46469",
    "remote_checksum": "3cb438759c17d04d1a176fea1a589a75349e1b72",
    "remote_md5sum": null
}
#成功了
ls ~/                              #看下怎么命名了
node1  node2                        #好吧 直接再包一层主机名的目录来解决命名冲突
ansible test -m fetch -a "src=/etc/hostname dest=~/"  #再执行一遍
node2 | SUCCESS => {                   #状态码从CHANGED变成了SUCCESS了 不做修改
    "changed": false,
    "checksum": "3cb438759c17d04d1a176fea1a589a75349e1b72",
    "dest": "/root/node2/etc/hostname",
    "file": "/etc/hostname",
    "md5sum": "0e996583b4206e9685e5d69e2af46469"
}
node1 | SUCCESS => {
    "changed": false,
    "checksum": "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83",
    "dest": "/root/node1/etc/hostname",
    "file": "/etc/hostname",
    "md5sum": "d8e8fca2dc0f896fd7cb4cb0031ba249"
}
lineinfile | replace 模块
说明
  • lineinfile
  • 添加一行内容
  • 替换一行内容
  • 支持正则 具体还没用
  • path 文件
  • line 添加替换内容
  • insertafter 在后面插入
  • backup yes | no 是否在修改前备份
  • replace
  • 替换关键词
  • 支持正则 具体还没用
  • path 文件
  • regexp 需要替换的旧内容
  • replace 替换的新内容
  • backup yes|no 是否在修改前备份
案例
ansible test -m lineinfile -a "path=/root/4.txt line='new insert things'"
node1 | FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Destination /root/4.txt does not exist !",
    "rc": 257
}
#没有4.txt 所以报错了   需要先创建文件
ansible test -m lineinfile -a "path=/root/1.txt line='new insert things'"
#在1.txt内容后new insert things

node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
#添加成功
ansible test -m lineinfile -a "path=/root/1.txt line='new insert things'" #再次执行
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": false,               #执行成功但是并没有再添加一行
    "msg": ""
}

#node1
cat /root/1.txt
new insert things
#只有一行     上面两次都执行成功了  但是第二次并没有添加  幂等性  


ansible test -m lineinfile -a "path=/root/1.txt line='too' insertafter='things'"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
#node1
cat 1.txt #查看下
new insert things
too
#在things下面添加too行



ansible test -m replace -a \
"path=/root/1.txt regexp='too' replace='replace'"#替换1.txt中的too为replace
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "1 replacements made"
}

#node1
cat 1.txt #查看下
new insert things
replace    #too 被替换了
user模块
参数说明
  • name 用户名
  • state 默认值present创建 absent删除
  • uid uid
  • group 基本组
  • groups 附加组
  • home 用户家目录
  • password 密码
  • remove true | false 是否同时移除家目录和邮箱
测试
ansible test -m user -a "name=zs password={{'abc'|password_hash('sha512')}}"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "comment": "",
    "create_home": true,
    "group": 1000,
    "home": "/home/zs",
    "name": "zs",
    "password": "NOT_LOGGING_PASSWORD",
    "shell": "/bin/bash",
    "state": "present",
    "system": false,
    "uid": 1000
}
#成功创建
ansible test -m user -a "name=zs state=absent remove=true" #删除用户zs 家目录也删

node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "force": false,
    "name": "zs",
    "remove": true,
    "state": "absent"
}
#成功删除
yum_repository模块
说明

使用yum_repository可以创建或修改yum源配置文件

  • file 文件名 默认(不指定的话)和name标识名一致
  • name yum标识名 不是yum里面那个name
  • description 描述信息 这个才是yum里面那个name
  • baseurl url
  • gpgcheck yum里面的gpgcheck
  • state absent删除
测试
ansible test -m yum_repository -a "name=ansible description=hello baseurl=xxx gpgpcheck=no"
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "repo": "ansible",
    "state": "present"
}
#node1
cat /etc/yum.repos.d/ansible.repo   #看一下 有了
[ansible]
baseurl = xxx
gpgcheck = 0
name = hello

ansible test -m yum_repository -a "name=ansible description=xxx baseurl=file:///mydvd"  #修改    name description必须要有

node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "repo": "ansible",
    "state": "present"
}
#修改了

#node1
cat /etc/yum.repos.d/ansible.repo #再看一下
[ansible]
baseurl = file:///mydvd
name = hello
#发现baseurl改了    gpgcheck没了    说明是覆盖操作

ansible test -m yum_repository -a "name=ansible state=absent"#删除ansible.repo
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "repo": "ansible",
    "state": "absent"
}
yum模块
说明

使用yum模块可以安装、卸载、升级软件包

  • state present(安装)| absent(卸载)| latest(升级)
  • name 指定软件名 可以是*代表所有 升级时用
测试
ansible test -m yum -a "name=unzip state=present" #安装unzip
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: unzip",
        "Installed: unzip-6.0-41.el8.x86_64"
    ]
}
ansible test -m yum -a "name=unzip state=latest" #升级unzip
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Nothing to do",
    "rc": 0,
    "results": [
        "Installed: unzip"
    ]
}
#因为包新装的没有升级  所以返回SUCCESS  "changed"为false
ansible test -m yum -a "name=unzip state=latest" #卸载unzip
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Removed: unzip-6.0-41.el8.x86_64"
    ]
}
service模块
说明

service为服务管理模块

  • state started|stopped|restarted
  • enabled yes | no 是否开机自启
  • name 指定服务名
测试
ansible test -m yum -a "name=httpd"

node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Nothing to do",
    "rc": 0,
    "results": [
        "Installed: httpd"
    ]
}
#因为之前装过所以返回的是SUCCESS
ansible test -m service -a "name=httpd state=started enabled=yes" #开启http服务 并且设置开机自启

#成功了    太长了就不粘贴了
lvg lvol 模块
说明
  • lvg 创建删除修改卷组
  • state present(创建) | absent(删除)
  • pvs 设备路径
  • vg 创建的卷组名
  • pesize 指定pe大小
  • force yes 强制 一般配合 state=absent
  • lvol 创建删除修改逻辑卷
  • state persent(创建) | absent(删除)
  • lv 指定逻辑卷名字
  • size 指定逻辑卷大小 会自动修改
测试
ansible test -m yum -a "name=lvm2"  #先安装lvm2才有pv vg lv等操作
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Nothing to do",
    "rc": 0,
    "results": [
        "Installed: lvm2"
    ]
}
#本来就有啊
ansible test -m lvg -a "vg=myvg pvs=/dev/sdb1" #用/dev/sdb1创建myvg
ansible test -m lvg -a "vg=myvg pvs=/dev/sdb1,/dev/sdb2" #修改myvg大小 添加/dev/sdb2



ansible test -m lvol -a "lv=mylv vg=myvg size=2G"  #创建2G的mylv
ansible test -m lvol -a "lv=mylv vg=myvg size=4G"  #修改mylv大小到4G
ansible test -m lvol -a "lv=mylv vg=myvg state=absent force=yes"#删除逻辑卷 强制
ansible test -m lvg -a "vg=myvg statu=absent"  #删除卷组

相关模块参数

模块名

作用

常用参数

command

默认模块 当个终端用没有shell的特性

shell

当个终端用 特性往上翻 没有幂等性

script

传送本地脚本过去运行

脚本路径

file

文件目录创建删除 修改权限属性

path目标路径 src源文件 state创建删除软硬链接 owner所有者 group所属组 mode权限

copy

将文件从控制端拷贝到被控制端

src源文件 dest目标文件

fetcch

将文件从被控制端传到控制端 (会包装到主机名目录下防止重名)需要注意不能传输目录 打包之后才行

src源文件 dest目标文件

lineinfile replace

添加文本模块 replace 替换关键词 都支持正则

path目标文件 line添加(替换)的内容 insertafter 插入到什么后面 regexp旧的 replace新的 backup 是否备份

user

用户模块 用户的增删权限修改

name 用户名 state创建删除 uid uid groups附加组 group基本组 home 家目录password 密码

yum_repository

创建修改yum配置文件

file 文件名(默认和name一致) name 标识名 baseurl (挂载路径) description (name描述) gpgcheck (检验)

yum

操作yum安装升级卸载

name 包名 state 安装升级卸载

service

服务模块 systemctl 启动关闭重启服务

name 服务名 state 启动重启关闭 enabled 开机自启

lvg lvol

操作卷组和逻辑卷

vg 卷组名 pvs设备名 lv 逻辑卷名 size大小 state创建删除