在ansible中如果对分区进行管理,使用的是parted模块,parted模块常见参数包括:
参数 | 说明 |
---|---|
device | 哪块磁盘 |
number | 第几个分区 |
part_start | 从硬盘的什么位置开始划分,默认从头开始(0%) |
part_end | 到硬盘的什么位置作为分区的结束点 |
state | 指定操作,present是创建,absent是删除 |
[root@node-137 ansible]# ansible db1 -m parted -a "device=/dev/sdb number=1 part_end=2GiB state=present"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
...
[root@node-137 ansible]# ansible db1 -m shell -a "lsblk"
node-138 | CHANGED | rc=0 >>
...
sdb 8:16 0 5G 0 disk
├─sdb1 8:17 0 2G 0 part
...
[root@node-137 ansible]# ansible db1 -m parted -a "device=/dev/sdb number=2 part_start=2GiB part_end=3GiB state=present"
node-138 | CHANGED => {
...
"partitions": [
...
{
"begin": 2097152.0,
"end": 3145728.0,
"flags": [],
"fstype": "",
"name": "",
"num": 2,
"size": 1048576.0,
"unit": "kib"
}
],
"script": "unit KiB mkpart primary 2GiB 3GiB"
}
[root@node-137 ansible]# ansible db1 -m shell -a "lsblk"
...
sdb 8:16 0 5G 0 disk
├─sdb1 8:17 0 2G 0 part
├─sdb2 8:18 0 1G 0 part
...
此例是对/dev/sdb创建第二个分区,从2GiB位置开始,到3GiB位置结束。
[root@node-137 ansible]# ansible db1 -m parted -a "device=/dev/sdb number=2 state=absent"
node-138 | CHANGED => {
"ansible_facts": {
...
"partitions": [
{
"begin": 1024.0,
"end": 2097152.0,
"flags": [],
"fstype": "",
"name": "",
"num": 1,
"size": 2096128.0,
"unit": "kib"
}
],
"script": "rm 2"
}
[root@node-137 ansible]# ansible db1 -m shell -a "lsblk"
node-138 | CHANGED | rc=0 >>
...
sdb 8:16 0 5G 0 disk
├─sdb1 8:17 0 2G 0 part
...
分区创建好之后,需要对分区进行格式化操作,格式化模块为filesystem
,参数如下:
参数 | 说明 |
---|---|
dev | 指定对于哪个设备进行格式化 |
fstype | 指定用什么文件系统进行格式化 |
force | 是否强制格式化,默认为no |
[root@node-137 ansible]# ansible db1 -m filesystem -a "dev=/dev/sdb2 fstype=btrfs"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true
}
[root@node-138 ~]# lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sda
├─sda1 xfs bcb76c67-cba1-4b22-86b9-1ac3f7d37847 /boot
└─sda2 LVM2_member VGG7EH-7SPO-Hg6B-YRBd-HdtG-BvUo-X8Vuak
├─centos-root xfs 67f41dca-2f74-4665-831b-b9494f22e761 /
└─centos-swap swap c88b0541-0e6f-4159-a61a-ebd37b25a8f0 [SWAP]
sdb
├─sdb1
├─sdb2 btrfs 0e634dcc-c542-4a0c-8aa8-06f74ee74249
└─sdb3
sr0 iso9660 CentOS 7 x86_64 2020-11-04-11-36-43-00
格式化之后就需要挂载分区,挂载使用mount模块,常见参数,
参数 | 说明 |
---|---|
src | 指定挂载设备名称 |
path | 挂载点,如果目录不存在,则自动创建 |
fstype | 挂载文件系统,必须指定 |
opts | 挂载选项,默认为defaults |
state | mounted:挂载的同时,写入/etc/fstab present:只写入/etc/fstab,但当前未挂载 unmounted:只卸载,并不会把条目从/etc/fstab删除 absent:卸载并从/etc/fstab删除 |
[root@node-137 ansible]# ansible db1 -m mount -a "src=/dev/sdb2 path=/mnt/sdb2 fstype=btrfs state=mounted"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dump": "0",
"fstab": "/etc/fstab",
"fstype": "btrfs",
"name": "/mnt/sdb2",
"opts": "defaults",
"passno": "0",
"src": "/dev/sdb2"
}
[root@node-138 ~]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
...
/dev/sdb2 btrfs 1.0G 17M 905M 2% /mnt/sdb2
[root@node-138 ~]# tail -1 /etc/fstab
/dev/sdb2 /mnt/sdb2 btrfs defaults 0 0
[root@node-137 ansible]# ansible db1 -m mount -a "path=/mnt/sdb2 state=absent"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dump": "0",
"fstab": "/etc/fstab",
"name": "/mnt/sdb2",
"opts": "defaults",
"passno": "0"
}
卸载一定要指定path
使用lvg模块管理卷组,常见参数,
参数 | 说明 |
---|---|
pvs | 用于指定物理卷,如果有多个PV则用逗号隔开,不需要提前创建PV,此命令会自动创建PV |
vg | 用于指定卷组名称 |
pesize | 指定PE大小 |
state | present:用于创建卷组,默认 absent:用于删除卷组 |
在node-138上创建名称为vg0的卷组,所使用的分区为/dev/sdb1和/dev/sdb2,pesize指定为16M
[root@node-137 ansible]# ansible db1 -m lvg -a "pvs=/dev/sdb1,/dev/sdb2 vg=vg0 pesize=16 state=present"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true
}
[root@node-138 ~]# pvdisplay
--- Physical volume ---
PV Name /dev/sdb1
VG Name vg0
PV Size <2.00 GiB / not usable 15.00 MiB
Allocatable yes
PE Size 16.00 MiB
Total PE 127
Free PE 127
Allocated PE 0
PV UUID I2wVyI-IskB-yXnJ-9J2w-yoZ0-hLWb-Z1YP93
--- Physical volume ---
PV Name /dev/sdb2
VG Name vg0
PV Size 1.00 GiB / not usable 16.00 MiB
Allocatable yes
PE Size 16.00 MiB
Total PE 63
Free PE 63
Allocated PE 0
PV UUID LHdk8h-16Sr-K0nB-6LuZ-Ewfd-egCj-f2aEYN
[root@node-138 ~]# vgdisplay
--- Volume group ---
VG Name vg0
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 2
Act PV 2
VG Size <2.97 GiB
PE Size 16.00 MiB
Total PE 190
Alloc PE / Size 0 / 0
Free PE / Size 190 / <2.97 GiB
VG UUID kB1CIr-fN5T-iYUk-DBoo-I0ne-hhzS-1rZKi7
[root@node-137 ansible]# ansible db1 -m lvg -a "vg=vg0 pesize=16 state=absent"
卷组创建好之后就要创建逻辑卷了,管理逻辑卷的模块是lvol,常见参数,
参数 | 说明 |
---|---|
vg | 指定卷组名称,用于划分逻辑卷 |
lv | 指定逻辑卷名称 |
size | 指定逻辑卷的大小 |
force | 强制执行 |
state | present:创建逻辑卷,默认选项 absent:删除逻辑卷 |
[root@node-137 ansible]# ansible db1 -m lvol -a "vg=vg0 lv=lv0 size=1G state=present"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": ""
}
[root@node-138 ~]# lvdisplay
--- Logical volume ---
LV Path /dev/vg0/lv0
LV Name lv0
VG Name vg0
LV UUID LSe7Fy-TcrB-tzZV-DIUK-cGOv-xkap-8Iy2aX
LV Write Access read/write
LV Creation host, time node-138, 2023-12-14 19:10:50 +0800
LV Status available
# open 0
LV Size 1.00 GiB
Current LE 64
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 8192
Block device 253:2
[root@node-137 ansible]# ansible db1 -m lvol -a"vg=vg0 lv=lv0 state=absent force=yes"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true
}
在ansible中可以使用firewalld模块对防火墙进行管理,常见参数,
参数 | 说明 |
---|---|
service | 开放哪个服务 |
port | 开放哪个端口 |
permanent | =yes,设置永久生效,无默认值 |
immediate | =yes,设置当前生效,默认为不生效 |
state | enabled:创建规则 disabled:删除规则 |
rich_rule | 富规则 |
开放httpd服务
[root@node-137 ansible]# curl node-138
curl: (7) Failed connect to node-138:80; No route to host
[root@node-137 ansible]# ansible db1 -m firewalld -a "service=http immediate=yes permanent=yes state=enabled"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "Permanent and Non-Permanent(immediate) operation, Changed service http to enabled"
}
[root@node-137 ansible]# curl node-138
hello noob
[root@node-137 ansible]# ansible db1 -m shell -a "firewall-cmd --list-all"
node-138 | CHANGED | rc=0 >>
public (active)
target: default
icmp-block-inversion: no
interfaces: ens33 ens37
sources:
services: dhcpv6-client http ssh
...
开放808/tcp端口
[root@node-137 ansible]# ansible db1 -m firewalld -a "port=808/tcp immediate=yes state=enabled"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "Non-permanent operation, Changed port 808/tcp to enabled"
}
[root@node-137 ansible]# ansible db1 -m shell -a "firewall-cmd --list-all"
node-138 | CHANGED | rc=0 >>
public (active)
target: default
icmp-block-inversion: no
interfaces: ens33 ens37
sources:
services: dhcpv6-client http ssh
ports: 808/tcp
...
删除规则
[root@node-137 ansible]# ansible db1 -m firewalld -a "port=808/tcp immediate=yes state=disabled"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "Non-permanent operation, Changed port 808/tcp to disabled"
}
[root@node-137 ansible]# ansible db1 -m firewalld -a "service=http immediate=yes permanent=yes state=disabled"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "Permanent and Non-Permanent(immediate) operation, Changed service http to disabled"
}
[root@node-137 ansible]# ansible db1 -m shell -a "firewall-cmd --list-all"
node-138 | CHANGED | rc=0 >>
public (active)
target: default
icmp-block-inversion: no
interfaces: ens33 ens37
sources:
services: dhcpv6-client ssh
...
添加一条富规则
[root@node-137 ansible]# ansible db1 -m firewalld -a "rich_rule='rule family=ipv4 source address=192.168.17.137 service name=http accept' state=enabled"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "Non-permanent operation, Changed rich_rule rule family=ipv4 source address=192.168.17.137 service name=http accept to enabled"
}
[root@node-137 ansible]# curl node-138
hello noob
[root@server ~]# curl node-138
curl: (7) Failed to connect to node-138 port 80: No route to host
删除富规则
[root@node-137 ansible]# ansible db1 -m shell -a "firewall-cmd --list-all" node-138 | CHANGED | rc=0 >>
...
rich rules:
rule family="ipv4" source address="192.168.17.137" service name="http" accept
[root@node-137 ansible]# ansible db1 -m firewalld -a "rich_rule='rule family=ipv4 source address=192.168.17.137 service name=http accept' state=disabled"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "Non-permanent operation, Changed rich_rule rule family=ipv4 source address=192.168.17.137 service name=http accept to disabled"
}
[root@node-137 ansible]# curl node-138
curl: (7) Failed connect to node-138:80; No route to host
[root@node-137 ansible]# ansible db1 -m shell -a "firewall-cmd --list-all" node-138 | CHANGED | rc=0 >>
public (active)
...
rich rules:
平时写 shell 脚本时,要替换文件内容,可以直接使用vim或sed命令来进行替换操作。在ansible中也有相关的替换模块:replace和lineinfile。replace模块参数,
参数 | 说明 |
---|---|
path | 文件路径 |
regexp | 正则表达式,指定要替换的内容 |
replace | 替换后的字符 |
[root@node-137 ansible]# ansible db1 -m file -a "state=touch path=/opt/aa.txt"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
...
[root@node-137 ansible]# ansible db1 -m shell -a "echo 'aa=111'>/opt/aa.txt;echo 'bb=222'>>/opt/aa.txt;cat /opt/aa.txt"
node-138 | CHANGED | rc=0 >>
aa=111
bb=222
[root@node-137 ansible]# ansible db1 -m replace -a "path=/opt/aa.txt regexp=^aa replace=x=666"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "1 replacements made"
}
[root@node-137 ansible]# ansible db1 -m shell -a "cat /opt/aa.txt"
node-138 | CHANGED | rc=0 >>
x=666=111
bb=222
可以看到本次只将正则表达式中匹配的aa
替换成了x=666
,而不是把此行内容进行替换(lineinfile进行行替换),所以我们需要在正则表达式中做出修改
[root@node-137 ansible]# ansible db1 -m replace -a "path=/opt/aa.txt regexp=^bb.* replace=x=666"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"msg": "1 replacements made"
}
[root@node-137 ansible]# ansible db1 -m shell -a "cat /opt/aa.txt"
node-138 | CHANGED | rc=0 >>
x=666=111
x=666
本次^bb.*
能够匹配以bb
开头的所有内容,所以达到预期效果
lineinfile 模块的用法与replace 基本一致,也是用于替换,常用参数,
参数 | 说明 |
---|---|
path | 文件路径 |
regexp | 正则表达式,指定要替换的内容 |
line | 替换后的字符 |
[root@node-137 ansible]# ansible db1 -m shell -a "echo 'aa=111'>/opt/aa.txt;echo 'bb=222'>>/opt/aa.txt;cat /opt/aa.txt"
node-138 | CHANGED | rc=0 >>
aa=111
bb=222
[root@node-137 ansible]# ansible db1 -m lineinfile -a "path=/opt/aa.txt regexp=^aa line=xx=666"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup": "",
"changed": true,
"msg": "line replaced"
}
[root@node-137 ansible]# ansible db1 -m shell -a "cat /opt/aa.txt"
node-138 | CHANGED | rc=0 >>
xx=666
bb=222
replace是对字符进行替换,lineinfile则是对行进行替换。如果使用replace想对行进行替换,则需要再regexp后面写上正则表达式来表示一整行的内容。
debug模块一般用于打印提示信息,类似于 shell 的echo命令,常用参数,
参数 | 说明 |
---|---|
msg | 后面跟具体内容 |
var | 后面跟变量 |
msg和var不可同时使用
[root@node-137 ansible]# ansible db1 -m debug -a "msg='hello'"
node-138 | SUCCESS => {
"msg": "hello"
}
如果在本地写了一个脚本,想在所有被管理的节点执行,没必要把脚本事先发布到所有节点,通过script模块即可快速实现
[root@node-137 ansible]# ansible db2 -m script -a "./hostname.sh"
node-140 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to node-140 closed.\r\n",
"stderr_lines": [
"Shared connection to node-140 closed."
],
"stdout": "server.rhce.cc\r\n",
"stdout_lines": [
"server.rhce.cc"
]
}
[root@node-137 ansible]# cat hostname.sh
#!/bin/bash
hostname
使用 group 模块对组进行管理,常用参数,
参数 | 说明 |
---|---|
name | 组名 |
state | present:创建组 absent:删除组 |
[root@node-137 ansible]# ansible db1 -m group -a "name=group1 state=present"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 1019,
"name": "group1",
"state": "present",
"system": false
}
[root@node-137 ansible]# ansible db1 -m shell -a "tail -1 /etc/group"
node-138 | CHANGED | rc=0 >>
group1:x:1019:
[root@node-137 ansible]# ansible db1 -m group -a "name=group1 state=absent"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "group1",
"state": "absent"
}
[root@node-137 ansible]# ansible db1 -m shell -a "tail -1 /etc/group"
node-138 | CHANGED | rc=0 >>
apache:x:48:
使用 user模块对用户进行管理,常用参数,
参数 | 说明 |
---|---|
name | 用户名 |
comment | 指定注释信息 |
group | 指定用户的主组 |
groups | 指定用户的附属组 |
password | 指定密码,但必须对密码进行加密 |
state | present:创建用户 absent:删除用户 |
remove | 在删除用户的时候,连同家目录一起删除,默认为no |
[root@node-137 ansible]# ansible db1 -m user -a "name=lisi group=yurq password={{'haha'|password_hash('sha512')}} state=present"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1000,
"home": "/home/lisi",
"name": "lisi",
"password": "NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1019
}
[root@node-137 ansible]# ansible db1 -m shell -a "tail -1 /etc/passwd"
node-138 | CHANGED | rc=0 >>
lisi:x:1019:1000::/home/lisi:/bin/bash
[root@node-137 ansible]# ssh lisi@node-138
lisi@node-138's password:
Last login: Mon Dec 18 16:48:48 2023
Hello everyone,
Our server will be maintained at 2015/07/10 0:00 ~ 24:00.
Please don't login server at that time. ^_^
[lisi@node-138 ~]$ exit
logout
Connection to node-138 closed.
这里password={{'haha'|password_hash('sha512')}}
是用passwrod_hash
函数调用sha512
这个哈希算法对字符串haha
进行加密
[root@node-137 ansible]# ansible db1 -m user -a "name=lisi state=absent remove=yes"
node-138 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "lisi",
"remove": true,
"state": "absent"
}
如果想从服务器下载文件到被管理的服务器,使用get_url
模块,常用参数,
参数 | 说明 |
---|---|
url | 指定文件的URL |
dest | 存储路径 |
[root@node-137 ansible]# ansible db1 -m get_url -a "url=ftp://ftp.rhce.cc./auto/web.tar.gz dest=/opt/"
node-138 | CHANGED => {
"ansible_facts": {
...
"url": "ftp://ftp.rhce.cc./auto/web.tar.gz"
}
[root@node-137 ansible]# ansible db1 -m shell -a "ls /opt/|grep web"
node-138 | CHANGED | rc=0 >>
web.tar.gz
类似在服务器执行wget
如果想获取被管理服务器信息,可以使用setup
模块,常用参数
参数 | 说明 |
---|---|
filter | filter=‘xxx’ |
[root@node-137 ansible]# ansible db1 -m setup
node-138 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.81.138",
"192.168.17.138"
],
...
获取的信息比较多,setup中获取的变量叫fact
变量,都是以key:value
格式输出,大致结构:
键1:值
键2: {
子键1: 值a
子键2: 值b
}
如果想获取键1
的值,可以通过参数filter=键
或filter=键.子键
来过滤。例如,想获取node-138机器上BIOS的版本,可以通过ansible_bios_verison
来获取,
[root@node-137 ansible]# ansible db1 -m setup -a "filter=ansible_bios_version"
node-138 | SUCCESS => {
"ansible_facts": {
"ansible_bios_version": "6.00",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
[root@node-138 ~]# dmidecode -t bios | grep Version
Version: 6.00
如果想获取ipv4
的所有信息,可以通过ansible_default_ipv4
来获取,
[root@node-137 ansible]# ansible db1 -m setup -a "filter=ansible_default_ipv4"
node-138 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "192.168.81.138",
"alias": "ens33",
...
},
"changed": false
}
如果仅想获取IP地址信息,可以通过ansible_default_ipv4.address
截取,
[root@node-137 ansible]# ansible db1 -m setup -a "filter=ansible_default_ipv4.address"
node-138 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
命令行中如果filter
含有子键,结果不会显示,所以上面命令未看到IP。不过如果把这个键写入ansible-playbook
(剧本)中,会显示哦,关于playbook后面会介绍。