文章目录
- 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配置文件查找顺序
- 查找ANSIBLE_CONFIG变量定义的配置文件(优先级最高)
- 查找当前目录下的./ansible.cfg
- 再次检查当前用户家目录下~/ansible.cfg
- 最后检查/etc/ansible/ansible.cfg (
有种从近到远的过程)
ansible执行方式
- ad-hoc 命令集方式
- playbook 脚本执行方式
ansible工作原理
- ansible基于SSH远程管理被管理的主机
- 控制端主机将模块(脚本)或命令传给被控制端主机
- 在被控制端主机执行模块(脚本)或命令
- 退出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模块可以创建文件、目录、链接;修改权限与属性等
过程
- 控制端主机将file.py拷贝到被控制端机子
- 被控制机子执行./file.py path=… state=…(执行python脚本 提供参数)
- 控制端退出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创建删除 |