python3安装
yum install epel-release
yum install python3 python3-pip
pip3 install --upgrade pip
pip3 install setuptools-rust
pip3 install ansible
yum install absible
python2安装
pip install ansible
或者用yum方式安装:需要epel-releaes源
yum install epel-release
yum install python2
pip install python2-pip
pip install ansible
yum install absible 用yum安装要epel-release源
----------------------------------------------------------------------------
ssh-keygen -t rsa 建立密钥对
ssh-copy-id node1@192.168.136.157 //建立信任关系
----------------------------------------------------
## ad-hoc
查ansible所有的模块
ansible-doc -l
查模块用法
ansible-doc modulename
查模块简单用法
ansible-doc -s modulename
用感叹号进行排除,只列出在node1中不是node2中的主机
ansible 'node1:!node2' -i inventory.ini --list-hosts
用&号进行排除,只列出在node1和node2中共有的主机
ansible 'node1:&node2' -i inventory.ini --list-hosts
copy模拟用法
常参数:
src 指定拷件的源地址
dest 指定拷件的标地址
backup 拷件前,若原目标文件发生了变化,则对原文件进备份yes/no
woner 指定新拷的所有者
group 指定新拷的所有组
mode 指定新拷的权限
content 指定文本内容(常用 )
ansible all -i 192.168.136.157,192.168.136.158 -m copy -a "src=/root/text.txt dest=/temp/is_156_file"
shell模块用法
ansible node1:node2 -i /root/inventory.ini -m shell -a "ip addr list"
shell管道符使用
ansible node1:node2 -i /root/inventory.ini -m shell -a "cat /etc/selinux/config | grep 'SELINUX='"
file模块
path/dest/name(required) **path参数 :**必须参数,用于指定要操作的文件或目录,在之前版本的ansible中,使用dest参数或者name参数指定要操作的文件或目录,为了兼容之前的版本,使用dest或name也可以。
group 文件数据复制到远程主机,设置文件属组用户信息
mode 文件数据复制到远程主机,设置数据的权限 eg 0644 0755(或者 ‘644’ ‘755’)
owner 文件数据复制到远程主机,设置文件属主用户信息
src 当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源。
force force参数 : 当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件。不过强制创建链接文件分为三种情况。
情况一:当要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。
情况二:当要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,会将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。
情况三:当要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件。
recurse yes 当要操作的文件为目录,将 recurse 设置为 yes ,可以递归的修改目录中文件的属性。
state state参数 :此参数非常灵活,其对应的值需要根据情况设定。比如,我们想要在远程主机上创建/testdir/a/b目录,那么则需要设置 path=/testdir/a/b,但是,我们无法从”/testdir/a/b“这个路径看出b是一个文件还是一个目录,ansible也同样无法单单从一个字符串就知道你要创建文件还是目录,所以,我们需要通过state参数进行说明。当我们想要创建的/testdir/a/b是一个目录时,需要将state的值设置为directory,”directory”为目录之意,当它与path结合,ansible就能知道我们要操作的目标是一个目录。同理,当我们想要操作的/testdir/a/b是一个文件时,则需要将state的值设置为touch。当我们想要创建软链接文件时,需将state设置为link。想要创建硬链接文件时,需要将state设置为hard。当我们想要删除一个文件时(删除时不用区分目标是文件、目录、还是链接),则需要将state的值设置为absent,”absent”为缺席之意,当我们想让操作的目标”缺席”时,就表示我们想要删除目标。
state= absent 如果是absent 那么目录将会被递归删除,如果是文件和软连接将会被取消
state= directory 创建一个空目录信息
state= file 查看指定目录信息是否存在
state= touch 创建一个空文件信息
state= hard/link 创建链接文件
file模拟使用
常参数:
owner 定义件/ 录的属主
group 定义件/ 录的属组
mode 定义件/ 录的权限
path 必选项,定义件/ 录的路径
recurse 递归的设置件的属性,只对 录有效
src 链接(软/硬)件的源件路径,只应于state=link的情况
dest 链接件的路径,只应于state=link的情况
state
directory 如果 录不存在,创建 录file 件不存在,则不会被创建,存在则返回件的信息,常于检查件是否存在。
link 创建软链接
hard 创建硬链接
touch 如果件不存在,则会创建个新的件,如果件或 录已存在,则更新其最后修改时间
absent 删除 录、件或者取消链接件
ansible node1:node2 -i inventory.ini -m file -a "path=/tmp/admin.conf state=touch mode=777 owner=tom group=tom"
parted模块(磁盘分区)
device
块设备(磁盘)在哪里操作/dev/sdb
name
设置分区号的名称(仅限GPT、Mac、MIPS和PC98)。
number
要处理的分区数量或将要创建的分区数量。在磁盘上执行任何操作时需要执行,但获取信息除外。
part_end
string Default: “100%” 分区将以从磁盘开头的偏移量结束,即从磁盘开始的“距离”。
距离可以用分开支持的所有单元(兼容除外)指定,并且区分大小写,例如10GiB,15%。
part_start
string Default: “0%” 分区将从磁盘开头开始作为偏移量,即从磁盘开始的“距离”。
距离可以用分开支持的所有单元(兼容除外)指定,并且区分大小写,例如10GiB,15%。
part_type
extended
· logical
· primary
只能使用’msdos’或’dvh’分区表指定。必须为’gpt’分区表指定名称。part_type和name都不能与“sun”分区表一起使用。
state
· absent
· present
· info
是创建还是删除分区。如果设置为 info,该模块将只返回设备信息。
unit
s
· B
· KB
· KiB ⬅️
· MB
· MiB
· GB
· GiB
· TB
· TiB
· %
· cyl
· chs
· compact
选择当前默认单元,该单元将用于在磁盘上显示位置和容量,如果它们不是单元后缀,则解释用户给出的位置和容量。获取有关磁盘的信息时,总是建议指定一个单元。
案例:
- name: device 1500M
parted:
device: /dev/vdd #指定硬盘
number: 1 #编号为1
state: present
part_end: 1500MiB #分区结束位置
filesystem模块
dev
设备或映像文件的目标路径。
force
no ←
· yes
如果 yes,允许在已经拥有文件系统的设备上创建新的文件系统
fstype
btrfs
· ext2
· ext3
· ext4
· ext4dev
· f2fs
· lvm
· ocfs2
· reiserfs
· xfs
· vfat
· swap
要创建的文件系统类型。
opts
要传递给mkfs命令的选项列表。
resizefs
no ←
yes
如果 yes,如果块设备和文件系统大小不同,则将文件系统扩展到空间中。
支持ext2、ext3、ext4、ext4dev、f2fs、lvm、xfs、vfat、swap文件系统。
XFS只有在挂载时才会增长。vFAT将会失败如果fatresize < 1.04
mount模块
backup
no
yes
创建一个包含时间戳信息的备份文件,以便在您以某种方式错误地抓取原始文件时取回原始文件。
boot
yes
·no
确定文件系统是否应该挂载在引导上。仅适用于Solaris系统。
dump
Default: 0 Dump(见fstab(5))。
请注意,如果设置为 null,state设置为present,它将停止工作,并将在后续运行中重复条目。对Solaris系统没有影响。
fstab
文件代替/etc/fstab。除非你真的知道自己在做什么,否则你不应该使用这个选项。如果您需要在chroot环境中配置挂载点,这可能会很有用。OpenBSD不允许指定带有挂载的备用fstab文件,因此不要在OpenBSD上以任何在实时文件系统上运行的状态使用它。
在Solaris上,此参数默认为/etc/fstab或/etc/vfstab。
fstype
文件系统类型。当state是 present 或 mounted时需要。
opts
mount选项(请参阅solaris上的fstab(5)或vfstab(4))
passno
Default: 0 Passno(见fstab(5))。
请注意,如果设置为null 和state设置为present,它将停止工作,并将在后续运行中重复条目。Solaris系统不建议使用。
path
挂载点的路径(例如/mnt/files)。在Ansible 2.3之前,此选项只能用作dest、destfile和名称。
src
要被挂载设备的路径。当state设置为present或mounted时是必需的。
state
· absent
· mounted
· present
· unmounted
· remounted
如果 mounted,设备将被主动安装,并在fstab中适当配置。如果挂载点不存在,则将创建挂载点。
如果 unmounted,设备将卸载而不更改fstab。
present 仅指定设备将在fstab中配置,不会触发或要求挂载。
absent 表示设备支架的条目将从fstab中删除,还将卸载设备并删除挂载点。
remounted 指定当您想强制刷新挂载本身时,设备将被重新安装(在2.9中添加)。这总是会返回 changed=true
常用案例:
- name: mount
mount:
path: /newpart #挂载到那个目录
src: /dev/vdd1 #挂载内容
fstype: ext4 #文件系统格式
state: mounted
lvg模块使用案例:
(注意:pv可以直接用lvg模块创建如:vg=vgtest pvs=/dev/sdb,dev/sdc)它会自动把那两块盘加入到pv
# 在test组中的主机上安装lvm2,state不写,默认是present
[root@control ansible]# ansible test -m yum -a "name=lvm2"
# 手工在beikongji1上对vdb进行分区
[root@beikongji1 ~]# fdisk /dev/vdb
Command (m for help): g # 创建GPT分区表
Command (m for help): n # 新建分区
Partition number (1-128, default 1): # 回车,使用1号分区
First sector (2048-41943006, default 2048): # 起始位置,回车
Last sector, +sectors or +size{K,M,G,T,P} (2048-41943006, default 41943006): +5G # 结束位置+5G
Command (m for help): n # 新建分区
Partition number (2-128, default 2): # 回车,使用2号分区
First sector (10487808-41943006, default 10487808): # 起始位置,回车
Last sector, +sectors or +size{K,M,G,T,P} (10487808-41943006, default 41943006): # 结束位置,回车,分区到结尾
Command (m for help): w # 存盘
[root@beikongji1 ~]# lsblk # vdb被分出来了两个分区
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 253:0 0 30G 0 disk
`-vda1 253:1 0 20G 0 part /
vdb 253:16 0 20G 0 disk
|-vdb1 253:17 0 5G 0 part
`-vdb2 253:18 0 15G 0 part
vdc 253:32 0 20G 0 disk
# 在test组中的主机上创建名为myvg的卷组,该卷组由/dev/vdb1组成
[root@control ansible]# ansible test -m lvg -a "vg=myvg pvs=/dev/vdb1"
# 在beikongji1上查看卷组
[root@beikongji1 ~]# vgs
VG #PV #LV #SN Attr VSize VFree
myvg 1 0 0 wz--n- <5.00g <5.00g
# 扩容卷组。卷组由PV构成,只要向卷组中加入新的PV,即可实现扩容
[root@control ansible]# ansible test -m lvg -a "vg=myvg pvs=/dev/vdb1,/dev/vdb2"
[root@beikongji1 ~]# vgs # 在node1上查看卷组
VG #PV #LV #SN Attr VSize VFree
myvg 2 0 0 wz--n- 19.99g 19.99g
lvol模块
常用参数:
lv 定义逻辑卷名
size 定义逻辑卷大小
vg 空间来自哪个卷组
state{present 创建,absent 删除}
force=yes 强制执行
pvs 指定物理卷
pesize 定义pe大小
active yes no 卷是否处于激活状态且对主机可见。
force
no ←
· yes
卷的收缩或删除操作需要此开关。确保文件系统不会被错误损坏/破坏
lv 逻辑卷的名称。
opts 传递给lvcreate命令的自由形式选项。
pvs 物理卷的逗号分隔列表(例如/dev/sda,/dev/sdb)。
resizefs
· no ←
· yes
与逻辑卷一起调整底层文件系统的大小
shrink
yes ←
· no 如果当前尺寸大于要求的尺寸,则收缩。
size 逻辑卷的大小,根据lvcreate(8)size,默认情况下以兆为单位,或可选使用[bBsSkKmMgGtTpPeE]单位之一;或者根据lvcreate(8) --extent作为[VG
snapshot 快照卷的名称
state · present ← absent 控件是否存在逻辑卷。如果 present 且卷不存在,则需要使用 size 选项。
thinpool 精简池卷名称。创建精简卷时,需要指定精简池卷名称。
vg 逻辑卷所在的卷组。
常用案例:
tasks:
- block:
- name: create data of 1500M
lvol:
vg: research
lv: data
size: 1500
setup 模块用于收集远程主机的一些基本信息
setup返回信息中列出的字段很多,可以用字段名作为filter的参数值,
列出一些字段如下:
ansible_all_ipv4_addresses:显示ipv4的地址信息
ansible_distribution:显示linux发行版,例:centos,suse等
ansible_distribution_major_version:显示系统主版本
ansible_distribution_version:显示系统版本
ansible_machine:显示系统类型,32位/64位
ansible_eth0:显示eth0的信息
ansible_hostname:显示主机名
ansible_kernel:显示内核版本
ansible_lvm:显示lvm相关信息
ansible_memtotal_mb:显示系统总内存
ansible_memfree_mb:显示可用系统内存
ansible_memory_mb:详细显示内存情况
ansible_swaptotal_mb:显示总的swap内存
ansible_swapfree_mb:显示swap内存的可用内存
ansible_mounts:显示系统磁盘挂载情况
ansible_processor_vcpus:显示cpu个数(只显示总的个数)
ansible_python_version:显示python版本
利用setup过滤出想要的ip 完全域名 主机名
[root@controls ansible]# cat tt.yml
---
- name: test
hosts: all
tasks:
- name: setfac
debug:
msg: "{{ ansible_all_ipv4_addresses[0] }} {{ ansible_fqdn }} {{ ansible_hostname }} "
block模块的用法
用和不动对比
- hosts: test
remote_user: root
tasks:
- shell: 'cat /etc/redhat-release'
register: stdout_info
ignore_errors: true
rescue:
- debug:
msg: 'I caught an error'
when: 'stdout_info is failed'
用block:
- hosts: test
remote_user: root
tasks:
- block:
- shell: 'cat /etc/redhat-release'
rescue:
- debug:
msg: 'I caught an error'
如上例所示,定义了一个block,这个block中有一个任务,这个任务在目标主机中执行了’‘cat/etc/redhat-release’’'命令,除了block关键字,还有另外一个关键字rescue,rescue关键字与block关键字对齐,rescue的字面意思为"救援",表示当block中的任务执行失败时,会执行rescue中的任务进行补救,当然,在rescue中定义什么任务,是由你决定的。也就是说当block中的任务出错时,会执行rescue中的任务,当block中的任务顺利执行时,则不会执行rescue中的任务。
你可能会问,使用block的方法完成"错误处理"的功能,似乎与使用failed的方法并没有什么不同,除了代码似乎"精简"了一点,block还有其他优势么?其实,使用block的方式还是有一定优势的,当block中有多个任务时,这种优势就比较明显了:
---
- hosts: testuser
remote_user: root
tasks:
- block:
- debug:
msg: 'I execute normally'
- command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing'
rescue:
- debug:
msg: 'I caught an error'
- command: /bin/false
- debug:
msg: 'I also never execute'
always:
- debug:
msg: "This always executes"
when: 2>1
include_role模块 -- 加载并执行角色
将指定的角色作为任务动态加载和执行。
只能在Ansible任务允许的情况下使用——在pre_tasks, tasks,或post_tasks剧本对象内,或作为角色内的任务。
任务级关键字、循环和条件只应用于include_role语句本身。
要将关键字应用到角色中的任务,可以使用apply选项传递它们,或者使用import_role代替。
忽略一些关键字,如until和retries
Windows目标也支持此模块
name参数为指定角色的名称
例如:
- name: changed
include_role:
name: rhel-system-roles.selinux
stat模块:
和linux的stat功能相同 ,Ansible的stat模块主要用于获取被控客户端的文件属性信息。该模块主要有path参数用于指定被控客户端的文件。判断文件是不是存在
Ansible的stat模块使用如下:
ansible all -m stat -a "path=/root/ansible.txt"
Ansible get_url模块
Ansible的get_url模块主要用于实现被控客户端从远程将文件下载到本地。该模块有四个常用参数,url参数主要用于指定被控客户端要远程下载的文件,dest参数主要指定目的文件夹,mode参数指定下载后的文件权限,force参数可以为yes或者是no。如果force参数为yes,则表示如果所下载的内容和原目录下的文件内容不一样,则下载并替换原文件,如果相同,则不进行下载;如果force参数为no,则不管目录下的同名文件是否相同,只有在目标不存在时才下载文件。在Ansible0.6版本之前,该参数默认为yes,在Ansible0.6之后,该参数默认为no。在生产环境中,一般小文件的下载选用yes。
ansible exp -m get_url -a "url=http://nginx.org/download/nginx-1.4.7.tar.gz dest=/root/ mode=0644 force=yes"
cron模块
Ansible的cron模块主要控制被控客户端添加定时任务,该参数有三个常用参数,name表示给该定时任务命名,minute参数指定该定时任务的间隔,job指定了具体的操作。Ansible的cron模块使用如下:
ansible exp -m cron -a "name='exp' minute='*/1' job='pwd'"
name 计划任务名称
job 指定计划的任务中需要实际执行的命令或者脚本
user 指定计划任务属于哪个用户,默认是root用户
state 指定状态,prsent 表示添加定时任务,也是默认设置,absent 表示删除定时任务
backup 对已有的任务修改或删除时,是否保存
disabled 当计划任务有名称时,根据计划任务名称关闭(注释)对应的计划任务
minute 分钟,取值范围(0-59,*, */2)
hour 小时,取值范围(0-23,,/2)
day 天,取值范围(1-31,,/2)
mouth 月,取值范围(1-12,,/2)
weekday 设置计划任务中周几设定位的值,取值范围(0-6 for Sunday-Saturday, *)
cron_file 如果指定, 使用这个文件cron.d,而不是单个用户crontab
用户jack每三个月的每周日晚上22点39分查看一次自身用户登录情况:
vim crontab.yml
---
- hosts: all
tasks:
- name: create a cron file under /etc/cron.d
cron:
name: Lgin time
minute: "39" #分
hour: "22" #时
# day: "" #日
month: "*/3" #月
weekday: "0" #周
user: jack #指定用户
job: "(last && lastb)|grep jack" #执行内容
firewalld模块
参数:
immediate
yes or no,默认no 如果将此配置设置为永久性,则应立即应用此配置
port
在防火墙中添加或移除端口名称或端口范围。端口范围必须为PORT/PROTOCOL或PORT-PORT/PROTOCOL格式。
service
在防火墙中添加或移除服务名称该服务必须在firewall-cmd --get-services的输出中列出。
state
absent or disabled or enabled or present 启用或禁用一项设置。对于端口:该端口是否接受(enabled)或拒绝(disabled)连接。状态的(present)和(absent)只能在区域级别操作中使用(即,当除了zone和state没有设置其他参数时)。
zone
添加或移除的防火墙区域。注意,可以为每个系统配置默认的区域,可能的值有block, dmz, drop, external, home, internal, public, trusted, work,public
permanent
yes or no 该配置是否在运行的防火墙配置中,或者在重新启动时仍然存在。注意,如果这是no, immediate被假定为yes。
masquerade
在在防火墙中开启或关闭masquerade功能
script模块用法
创建一个sh文件里面内容是在tmp下创建一个文件,然后再用script执行
cat /root/a.sh
touch /tmp/testfile
ansible node1:node2 -i inventory.ini -m script -a "/root/a.sh"
yum_repository模块(专用于处理yum仓库文件,那个特殊符号$要转义,不然拷过去就是空的)
ansible node1:node2 -i /root/inventory.ini -m yum_repository -a "name=epel baseurl='http://download.fedoraproject.org/pub/epel/7/\$basearch/' description='epel yum repo' gpgcheck=no enabled=yes state=present"
yum模块
常用参数:
name 要安装的软件包名, 多个软件包以英⽂逗号(,) 隔开
state 对当前指定的软件安装、移除操作(present installed latest absent removed) 持的参数
--- present 确认已经安装,但不升级
- - installed 确认已经安装
- - latest 确保安装,且升级为最新
- - absent 和 removed 确认已移除
- -enabled=true
ansible node1:node2 -i inventory.ini -m yum -a "name=nginx state=present"
systemd模块
state 对当前服务启动,停掉、重启、重新加载等操作(started,stopped,restarted,reloaded)
daemon_reload 重新载 systemd,扫描新的或有变动的单元
enabled 是否开机启动 yes|no
ansible node1:node2 -i inventory.ini -m systemd -a "name=nginx state=started"
group组模块
gid
interger 要为组设置的可选 GID。
name
要管理的组的名称。system
boolean ·
no、yes 如果yes,则表示创建的组是系统组
ansible node1:node2 -i inventory.ini -m group -a "name=group1"
loop模块:
循环打印案例
tasks:
- name:Print
debug:
msg: "{{ item }}" //这个是固定写法,必须要是item
loop: [1,2,3,4]
批量建立文件案例:
tasks:
- name:cteate file
file:
path:/tmp/file{{ item }}.txt
state: touch
loop:
- 1
- 2
- 3
user模块
常参数:
name 必须的参数, 指定户名
password 设置户的密码,这接受的是个加密的值,因为会直接存到 shadow, 默认不设置密码
update_password 假如设置的密码不同于原密码,则会更新密码.
home 指定户的家录
shell 设置户的 shell
comment 户的描述信息
create_home 在创建户时,是否创建其家录。默认创建,假如不创建,设置为 no。
group 设置户的主组
groups 将户加到多个其他组中,多个逗号隔开。默认会把⽤户从其他已经加⼊的组中删除。
append yes|no 和 groups 配合使,yes 时,不会把户从其他已经加的组中删除,是否为附加组
system 设置为 yes 时,将会创建个系统账号
expires 设置户的过期时间,值为时间戳,会转为为天数后,放在 shadow 的第 8 个字段
计算时间戳命令:date -d 2022-01-20 +%s
generate_ssh_key 设置为 yes 将会为户成密钥,这不会覆盖原来的密钥
ssh_key_type 指定户的密钥类型, 默认 rsa, 具体的类型取决于被管理节点
state 删除或添加户, present 为添加,absent 为删除;默认值 present
remove 当与 state=absent 起使,删除个户及关联的录,如家录,邮箱⽬录。可选的值为: yes/no
先在控制机上生成本地密码变量加密过的:
pass=$(echo "admin" | openssl passwd -1 -stdin) //那是数字1
再创建时调用(因为不支持传明文密码设置)
ansible node1:node2 -i inventory.ini -m user -a "name=test password=${pass}"
ansible node1:node2 -i inventory.ini -m user -a "name=tt state=present group=node1 groups=group1 append=yes"
删除用户一定要带上remove变量,不然家目录删除不了
ansible node1:node2 -i inventory.ini -m user -a "name=tt state=absent remove=yes"
用户隔在哪一天过期
ansible node1:node2 -i inventory.ini -m user -a "name=tom expires=$(date +%s -d 20230225)"
// 计算 3 时之后是点分
date +%T -d '3 hours'
// 任意日期的前 N 天,后 N 天的具体日期
date +%F -d "20190910 1 day"
date +%F -d "20190910 -1 day"
// 计算两个日期相差天数, 如计算生日距离现在还有多少天
d1=$(date +%s -d 20180728)
d2=$(date +%s -d 20180726)
echo $(((d1-d2)/86400))
cron定时任务模块
常参数:
name 指定⼀个cron job 的名字。⼀定要指定,便于⽇之后删除。
minute 指定分钟,可以设置成(0-59, *, */2 等)格式。 默认是* , 也就是每分钟。
hour 指定⼩时,可以设置成(0-23, *, */2 等)格式。 默认是 * ,也就是每⼩时。
day 指定天, 可以设置成(1-31, *, */2 等)格式。 默认是 * , 也就是每天。
month 指定⽉份, 可以设置成(1-12, *, */2 等)格式。 默认是* , 也就是每周。
weekday 指定星期, 可以设置成(0-6 for Sunday-Saturday, *等)格式。默认是 *,也就是每星期。
job 指定要执⾏的内容,通常可以写个脚本,或者⼀段内容。
state 指定这个job的状态,可以是新增(present)或者是删除(absent)。 默认为新增(present)
user 指定用哪个用户执行,不写默认是root用户
ansible all -i inventory.ini -m cron -a "name='show fiel' user=node1 minute='*/1' job='ls -al >/dev/null'"
ansible all -i inventory.ini -m cron -a "name='show fiel' user=node1 state=absent"
debug模块用法(一般用于获取信息,再从信息中过滤出要的,格式是python字典形式的过滤,类似于setup模块)
ansible all -i inventory.ini -m debug -a "msg='admin is {{var}}'" -e "var=mysql"
template模块使用(常用于jinjia2传参)
[root@nfs ~]# cat test.j2
Hello {{var}}!
把var变量直接传过给受控机文件中去
ansible all -i inventory.ini -m template -a "src=/root/test.j2 dest=/tmp/test.j2" -e "var=world"
受控机上查看:
[node1@node1 root]$ cat /tmp/test.j2
Hello world!
lineinfile模块使用(单行操作)
常参数
path 被管理节点的标件路径, 必须。
state 可选值absent 删除 |present 替换(默认值)。
regexp 在件的每中查找的正则表达式。对于 state=present ,仅找到的最后将被替换。
line 要在件中插/替换的。需要state=present 。
create 件不存在时,是否要创建⽂件并添加内容。yes/no
删除注释行有井号的
ansible all -i inventory.ini -m lineinfile -a "path=/root/one.sh regexp='^#' state=absent"
查到那行source开头的替换成tttt
ansible all -i inventory.ini -m lineinfile -a "path=/root/one.sh regexp='^source' line='tttt' state=present"
blockinfile模块用法(多行操作)
添加两行在最后
ansible all -i inventory.ini -m blockinfile -a "path=/root/one.sh block='aaaa\nbbbbbb' state=present"
删除那两行
ansible all -i inventory.ini -m blockinfile -a "path=/root/one.sh block='aaaa\nbbbbbb' state=absent"
## playbook
常规属性
name 属性, 每个play的名字唯一
hosts 属性, 每个play 涉及的被管理服务器,同ad-hoc 中的资产选择器
tasks 属性, 每个play 中具体要完成的任务,以列表的形式表达
become 属性,如果需要提权,则加上become 相关属性
become_user 属性, 若提权的话,提权到哪个用户上 remote_user属性,指定连接到远程节点的⽤户,就是在远程服务器上执⾏具体操作的用户。若不指定,则默认使当前执行的ansible Playbook
2个任务剧本:
---
- name: nginx_install_start
hosts: node1
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
- name: copy one.sh to /tmp/one.sh
copy: src=/root/one.sh dest=/tmp/one.sh
- name: start nginx
systemd: name=nginx enabled=true state=started
- name: shell run
hosts: node2
remote_user: root
tasks:
- name: show files
shell: ip addr list
...
安装python对yaml检测工具
yum install python2-pip
pip install pyyaml
剧本校验是不是有误
[root@nfs ~]# python -c 'import yaml,sys; print yaml.load(sys.stdin)' <playbook1.yaml
[{'tasks': [{'yum': 'name=nginx start=present', 'name': 'install nginx'}, {'copy': 'src=/root/one.sh dest/tmp/one.sh', 'name': 'copy one.sh to /tmp/one.sh'}, {'systemd': 'name=nginx enabled=true state=started', 'name': 'start nginx'}], 'hosts': 'inde1', 'remote_user': 'root', 'name': 'nginx_install_start'}]
再用语法检测:
ansible-playbook -i inventory.ini playbook1.yaml --syntax-check
再模拟执行一遍(不会远程执行,本地跑一次,后面c为大写)
ansible-playbook -i inventory.ini playbook1.yaml -C
单步调试,按y一步一步走,按c全跑完,按N跳过(Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue:)
ansible-playbook -i inventory.ini playbook1.yaml --step
真正的执行操作(如果把inventory的主机资产清单写入/etc/ansible/hosts,就不用在命令行中指定清单文件了)
ansible-playbook -i inventory.ini playbook1.yaml
接着卸载掉(一定要先把服务停掉写在前面,脚本是按行从上执行,如果先卸载再停服务就会出错)
---
- name: nginx_uninstall_start
hosts: node1
remote_user: root
tasks:
- name: stop nginx
systemd: name=nginx enabled=false state=stopped
- name: uninstall nginx
yum: name=nginx state=absent
- name: del /tmp/one.sh
file: path=/tmp/one.sh state=absent
- name: shell run
hosts: node2
remote_user: root
tasks:
- name: show files
shell: ip addr list
...
## 全局变量和剧本变理
先生成一个全局变量
[root@nfs ~]# cat a.json
{"names": "yeng", "type": "man"}
再调用全局变量输出
[root@nfs ~]# ansible all -i inventory.ini -m debug -a "msg='name is {{names}}, type is {{type}}'" -e @a.json
输出如下:
192.168.136.158 | SUCCESS => {
"msg": "name is yeng, type is man"
}
192.168.136.157 | SUCCESS => {
"msg": "name is yeng, type is man"
}
局本变量(2种形式,1在剧本中直按定义和调用,2在外部单独用个yml文件中定义,剧本中用vars_files调用)
第1种:
[root@nfs ~]# cat playbook2.yaml
---
- name: test play var
hosts: node1
vars:
user: ttt
home: /home/ttt
tasks:
- name: create user{{user}}
user:
name: "{{user}}"
home: "{{home}}"
...
接着删除:
[root@nfs ~]# !cat
cat playbook2.yaml
---
- name: test play var
hosts: node1
vars:
user: ttt
home: /home/ttt
tasks:
- name: create user{{user}}
user:
name: "{{user}}"
state: absent
remove: yes
...
第2种:
先建立一个变量文件
[root@nfs ~]# cat users.yml
user: tttt
home: /home/tttt
[root@nfs ~]# cat playbook2.yaml
---
- name: test play var
hosts: node1
vars_files:
- /root/users.yml
tasks:
- name: create user{{user}}
user:
name: "{{user}}"
home: "{{home}}"
...
## 主机资产变量
[root@nfs ~]# cat inventory.ini
[node1]
192.168.136.157 user=yeng port=22 //这种自定义的写法只能在json中申明和赋值,如下案例就是,单行写法
[node2]
192.168.136.158
[root@nfs ~]# ansible all -i inventory.ini -m debug -a "msg='{{user}} {{port}}'"
192.168.136.157 | SUCCESS => {
"msg": "yeng 22"
}
主机组变量:
[root@nfs ~]# cat inventory.ini
[node1]
192.168.136.157 user=yeng port=22
192.168.136.159
[node1:vars]
home="/home/tom" //整个node1全局生效,如果和node1里面冲突,则最小匹配原则
[node2]
192.168.136.158
变量继承:
[root@nfs ~]# cat inventory.ini
[node1]
192.168.136.157 user=yeng port=22
192.168.136.159
[node1:vars]
home="/home/tom"
[node2]
192.168.136.158
[all_node]
[all_node:children] //children是固定写法,这个all_node是包含两个主机组的全局变量
node1
node2
## 剧本中调用用的内置变量
都是以 ansible_ 为前缀。
ansible_ssh_host 将要连接的远程主机名与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port ssh端⼝号.如果不是默认的端号,通过此变量设置.
ansible_ssh_user 默认的 ssh 户名
ansible_ssh_pass ssh 密码(这种式并不安全,官强烈建议使 --askpass或 SSH 密钥)
ansible_sudo_pass sudo 密码(这种式并不安全,官强烈建议使 --asksudo-pass)
ansible_sudo_exe (new in version 1.8)sudo 命令路径(适于1.8及以上版本)
ansible_ssh_private_key_file ssh 使的私钥件.适于有多个密钥,你不想使 SSH代理的情况.
ansible_python_interpreter 标主机的 python 路径.适⽤于的情况: 系统中有多个Python,或者命令路径不是"/usr/bin/python",如/usr/local/bin/python3
[root@nfs ~]# !cat
cat inventory.ini
[node1]
192.168.136.157 user=yeng port=22 //这种自定义的写法只能在json中申明和赋值,单行执行ad-hoc写法
192.168.136.159 ansible_ssh_port=2222 //这种可以直接用剧本调用,是内置好的变量,不用管,剧本中直接用
[node1:vars]
home="/home/tom"
[node2]
192.168.136.158
[all_node]
[all_node:children]
node1
node2
## facts变量
(系统是默认开启的,每次执行剧本都会自动收收集受控机信息,浪费时间,可以关掉)
Facts变量不包含在前⽂中介绍的全局变量、剧本变量及资产变量
之内。
Facts变量不需要我们⼈为去声明变量名及赋值。
它的声明和赋值完全有Ansible 中的 setup 模块帮我们完成。
它收集了有关被管理服务器的操作系统版本、服务器IP地址、主机名,磁盘的使⽤情况、CPU个数、内存等等有关被管理服务器的私有信息。
在每次PlayBook运⾏的时候都会发现在PlayBook执前都会有个Gathering Facts的过程。这个过程就是收集被管理服务器的Facts信
息过程。
ansible all_node -i inventory.ini -m setup -a "filter=*memory*" //只拿内存过滤出来,*mount*是磁盘挂载,cpu等也类似
如果不用就关掉提高剧本速度:
---
- name: nginx_uninstall_start
hosts: node1
gather_facts: no //关闭默认的facts,
remote_user: root
tasks:
- name: stop nginx
systemd: name=nginx enabled=false state=stopped
- name: uninstall nginx
yum: name=nginx state=absent
- name: del /tmp/one.sh
file: path=/tmp/one.sh state=absent
- name: shell run
hosts: node2
remote_user: root
tasks:
- name: show files
shell: ip addr list
...
## 注册变量(用于看剧本执行的结果的)
[root@nfs ~]# cat playbook1.yaml
---
- name: nginx_uninstall_start
hosts: node1
remote_user: root
tasks:
- name: stop nginx
systemd: name=nginx enabled=false state=stopped
- name: uninstall nginx
yum: name=nginx state=absent
register: uninstall_result //这里和下面的变量名称保持一致
- name: print result
debug: var=uninstall_result //利用注册变量看执行结果
- name: del /tmp/one.sh
file: path=/tmp/one.sh state=absent
- name: shell run
hosts: node2
remote_user: root
tasks:
- name: show files
shell: ip addr list
...
## 变量优先级:全局>剧本>资产
when:判断
通过条件判断(when) 指令去使用语法校验的结果,只要语法检查通过都会去执⾏ "start nginx server"这个TASK。
通过debug 模块,通过debug模块去确认返回结果的数据结构,打印出来的返回结果。 当nginxsyntax.rc 为 0时语法校验正确。
when: 一些常用判读方法:
exists、not exists、defined、undefined、none、success、failure、change、skip
when: is not exist
when: is exist
when: is defined
when: is undefined
when: is none
when: success
when: failure
when常用参数
==
!=
> >=
< <=
is defined
is undefined
true
false
持逻辑运算符: and or
判断vgs在不在用:
when: "'research' in ansible_lvm.vgs" //或 not in
when: ansible_lvm.vgs.research is undefined //这样也可以
判断磁盘在不在用:
when: ansible_facts.devices.vdd is defined //或undefined
选择变量里面的key=value进行判断:
when: item.name == 'jack'
判断单个主机组是否在所有的主机组里
when: inventory_hostname in groups['prod'] //或 not in
jinjia2获取主机信息IP 域名 主机名
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['fqdn'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
判断磁盘大小如果不在给默认值:
value: "{{ ansible_facts.devices.vdb.size | default('NONE') }}"
when:重要用法(上一个服务如果开了,才开下一个服务):
---
- name: main1
hosts: dev
tasks:
- name: test
shell: /usr/bin/systemctl status vdo
ignore_errors: yes
register: result
- name: open httpd
service:
name: httpd
state: started
when: result.rc == 0 //不能把0用引号引住
第一行和二行是and关系,第二行内部是or的关系
when:
- item.job == "prod"
- inventory_hostname in groups.prod or inventory_hostname in groups.balancers
多行and关系:
when:
- item.job == "test"
- inventory_hostname in groups.test
判读文件在不在
ansible dev -m stat -a "path=/etc/ddddd"输出下面查看可以组合成stat.exists
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"stat": {
"exists": false
}
}
用stat模块输出再注册一下再调用判断
tasks:
- name: file-not-yes
stat:
path: /etc/dx
register: file_status
.....
.....
when: file_status.stat.exists == False 在就是True
判断系统信息
先查寻一下:ansible dev -m setup |grep ansible_distribution
再写剧本 (可以加and和or)
- name:
debug:
msg: centos
when: ansible_distribution == "CentOS"
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.9",
---
- name: test playbook control
hosts: all_node
gather_facts: no
tasks:
- name: create user
user:
name: tom
state: present
password: "{{ 'adminw'|password_hash('sha512') }}"
- name: yum is ok
yum:
name: nginx
state: present
- name: update nginx
copy:
src: nginx.conf
dest: /etc/nginx/conf.d/
- name: check nginx
shell: /usr/sinb/nginx -t
register: nginx_check
- name: print nginx check result
debug:
var: nginx_check
- name: start server
systemd:
name: nginx
state: started
when: nginx_check.rc == 0
...
循环控制
在PlayBook中使with_items 去实现循环控制,且循环时的中间变量(上shell循环中的 $i 变量)只能是关键字 item ,不能随意
定义。
批量循环创建用户和密码:
[root@nfs ~]# cat playbook3.yml
- name: variable playbook example
hosts: all_node
gather_facts: no
vars:
createuser:
- tomcat
- www
- mysql
tasks:
- name: create user
user:
name: "{{ item }}"
state: present
password: "{{ 'adminw'|password_hash('sha512') }}"
with_items: "{{ createuser }}"
通过Play中的tags 属性,去解决前PlayBook变更导致的扩变更范围和变更险的问题。
在改进的PlayBook中,针对件发布TASK 任务"update nginx main config" 和 "add virtualhost config"新增了属性 tags ,属性值为updateconfig。
另外我们新增"reload nginx server" TASK任务。当配置件更新后,去reload Nginx 服务。
那重新加载需要依赖于 Nginx 服务是已经启动状态。所以,还需要进⼀步通过判断 Nngix 的 pid 件存在,才证明 Nginx 服务本身是启动中,启动中才可以 reload Nginx 服务。
判断个件是否存在使 stat 模块,会发现 nginxrunning.stat.exists 的值是 true 就表示启动状态,是 false 就是关闭状态。
[root@nfs ~]# cat playbook2.yaml
---
- name: test playbook control
hosts: all_node
gather_facts: no
tasks:
- name: create user
user:
name: tom
state: present
password: "{{ 'adminw'|password_hash('sha512') }}"
- name: yum is ok
yum:
name: nginx
state: present
- name: update nginx
copy:
src: nginx.conf
dest: /etc/nginx/conf.d/
tags: updateconfig
- name: check nginx
shell: /usr/sinb/nginx -t
register: nginxcheck
- name: check nginx pid
stat:
path: /var/run/nginx.pid
tags: updateconfig
- name: print nginx check result
debug:
var: nginxcheck
- name: print nginx run
debug:
var: nginxrun
- name: start server
systemd:
name: nginx
state: started
when:
- nginxcheck.rc == 0 and nginxrun.stat.exists == true
tags: updateconfig
...
指定tags 去执PlayBook执时定要指定tags,这样再执的过程中只会执task 任务上打上tag 标记为 updateconfig 的任务
ansible-playbook -i inventory.ini playbook2.yaml -t updateconfig
Handlers 属性
观察当前的 Playbook,不能发现,当我的配置件没有发变化时,每次依然都会去触发TASK "reload nginx server"。
如何能做到只有配置⽂件发⽣变化的时候才去触发TASK "reloadnginx server",这样的处理才是最完美的实现。此时可以使
handlers 属性。
[root@nfs ~]# cat playbook2.yaml
---
- name: test playbook control
hosts: all_node
gather_facts: no
tasks:
- name: create user
user:
name: tom
state: present
password: "{{ 'adminw'|password_hash('sha512') }}"
- name: yum is ok
yum:
name: nginx
state: present
- name: update nginx
copy:
src: nginx.conf
dest: /etc/nginx/conf.d/
notify: reload nginx server //监控些copy模拟返回值,两边名称要一致
- name: check nginx
shell: /usr/sinb/nginx -t
register: nginxcheck
- name: check nginx pid
stat:
path: /var/run/nginx.pid
- name: print nginx check result
debug:
var: nginxcheck
- name: print nginx run
debug:
var: nginxrun
- name: start server
systemd:
name: nginx
state: started
handlers: //当上面监控的notify发生变化时就触发这里的动作
- name: reload nginx server
systemed:
name: nginx
state: reloaded
jinjia2模本样本:
{# use variable example #}
wlecome host {{ ansible_hostname }}, os is {{
ansible_os_family }}
today is {{ ansible_date_time.date }}
cpucore numbers {{ ansible_processor_vcpus }}
{# use condition example #}
{% if ansible_processor_vcpus > 1 %}
OS CPU more than one core
{% endif %}
{% for m in ansible_mounts if m['mount'] != "/" %}
mount {{ m['mount'] }}, total size is
{{m['size_total']}}, free size is
{{m['size_available']}}
{% endfor %}
简单案例:
主控端先把nginx.cinf.j2文件配置好,就是把受控主机服务配置文件拿来改一下:
[root@nfs ~]# cat nginx.config.j2
user nginx;
worker_processes {{ cpu_number }}; //在执行剧本时可以传变量给这个,随便受控机的这个配置会自动变
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
shttp {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
主控机剧本:
[root@nfs ~]# cat playbook5.yml
- name: test_jinjia2
hosts: node1
gather_facts: no
tasks:
- name: install_nginx
yum:
name: nginx
state: present
- name: update_config
template:
src: /root/nginx.config.j2
dest: /etc/nginx/nginx.conf
执行剧本传参数:
ansible-playbook playbook5.yml -e "cpu_number=8"
角色用法3种,一种是yum安装的系统角色,一种是自动用galaxy,一种是手动创建
手动
先建立项目文件夹为webservers,再继续建立下面的子文件,执行剧本就执行nginx_test.yml
[root@nfs webservers]# tree //项目目录结构
├── nginx
│ ├── files
│ │ └── nginx.conf
│ ├── handles
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ │ └── nginx.conf.j2
│ └── vars
│ └── main.yml
└── nginx_test.yml
自动创建galaxy
ansible-galaxy用法,类似于gethub可以直网上下载
ansible-galaxy install //安装上共享的role
ansible-galaxy delet //删除一个role
ansible-galaxy remove
ansible-galaxy login //登陆
ansible-galaxy init //创建一个role目录,不用上面一样手动创建了
ansible-galaxy list //列举通过ansible-galaxy工具安装的role
ansible-galaxy search //在galaxy上搜索共享的role(类似于gethub)
系统角色yum安装(装完位置 /usr/share/ansible/roles)
yum search roles 查系统角色软件包
sudo yum -y install rhel-system-roles
ansible-galaxy list //查看
/usr/share/doc/rhel-system-roles/ 模板文件位置,可以拿出来自定义改一下用
/usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml selinux.yml
-------------------------------------------------常用架构
ansible判断语法结构
(类似于python中的try---except----finally)
tasks:
-block //先执行block
- name:
yum:
rescue: //block有错误就执行rescue
- name:
debug:
always: //不管上面哪个有错误还是没错误,都要执行这个下面的
- name:
debug
循环变量使用:
- name:
hosts: dev
vars:
user_all:
- user1
- user2
- user3
task:
- name:
debug:
msg: "{{ item }}" //item为关键字
with_items: "{{ user_all }}" //with_items为关键字
嵌套循环变量使用(类似于python中的for中再for):
- name:
hosts: dev
vars:
user_all:
- user1
- user2
- user3
passwd_all:
- admin1
- admin2
- admmin3
task:
- name:
debug:
msg: "{{ item[0] }}, {{ item[1]}}" //item为关键字
with_nested: "{{ user_all }}, {{ passwd_all }}" //with_nested为关键字
循环加when判断:
- name:
hosts: dev
vars:
numbers:
- 1
- 2
- 3
- 4
tasks:
- name:
debug:
msg: "{{ item }}"
with_items: "{{ numbers }}"
when: item > 3 //只有大于3的才会执行,其它跳过
外部变量文件使用案例
vim userdel.yml
---
user: ##定义变量名称
- aaa
- bbb
- lee
vim skk.yml
---
- name: test
hosts: server2
vars_files: ##定义变量文件
- ./userdel.yml ##定义变量文件位置
tasks:
- name: userdel
user:
name: "{{ item }}" ##循环每一个变量
state: absent
remove: yes
loop:
"{{ user }}" ##定义循环的变量
自定义变量并调用:
- name
hosts: dev
tasks:
- name
set_fact:
yeng: ttttttt
- name:
debug:
var: yeng //也可以不调自定义的,直接调系统的如:msg: "{{ansible_date_time['time'] }}"滤出时间
...
ansible常用模块用法笔记
于 2023-02-25 15:39:10 首次发布