python3安装yum install epel-releaseyum install python3 python3-pippip3 install --upgrade pippip3 install setuptools-rustpip3 install ansibleyum install absiblepython2安装pip install ansible或者用yum方式安装:需要epel-releaes源yum install epel-releaseyum install python2pip install python2-pippip install ansibleyum 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/nowoner 指定新拷的所有者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的情况statedirectory 如果 录不存在,创建 录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/sdbname设置分区号的名称(仅限GPT、Mac、MIPS和PC98)。number要处理的分区数量或将要创建的分区数量。在磁盘上执行任何操作时需要执行,但获取信息除外。part_endstring Default: “100%” 分区将以从磁盘开头的偏移量结束,即从磁盘开始的“距离”。距离可以用分开支持的所有单元(兼容除外)指定,并且区分大小写,例如10GiB,15%。part_startstring Default: “0%” 分区将从磁盘开头开始作为偏移量,即从磁盘开始的“距离”。距离可以用分开支持的所有单元(兼容除外)指定,并且区分大小写,例如10GiB,15%。part_typeextended· logical· primary只能使用’msdos’或’dvh’分区表指定。必须为’gpt’分区表指定名称。part_type和name都不能与“sun”分区表一起使用。state· absent· present· info是创建还是删除分区。如果设置为 info,该模块将只返回设备信息。units· B· KB· KiB ⬅️· MB· MiB· GB· GiB· TB· TiB· %· cyl· chs· compact选择当前默认单元,该单元将用于在磁盘上显示位置和容量,如果它们不是单元后缀,则解释用户给出的位置和容量。获取有关磁盘的信息时,总是建议指定一个单元。案例:- name: device 1500Mparted:device: /dev/vdd #指定硬盘number: 1 #编号为1state: presentpart_end: 1500MiB #分区结束位置filesystem模块dev设备或映像文件的目标路径。forceno ←· yes如果 yes,允许在已经拥有文件系统的设备上创建新的文件系统fstypebtrfs· ext2· ext3· ext4· ext4dev· f2fs· lvm· ocfs2· reiserfs· xfs· vfat· swap要创建的文件系统类型。opts要传递给mkfs命令的选项列表。resizefsno ←yes如果 yes,如果块设备和文件系统大小不同,则将文件系统扩展到空间中。支持ext2、ext3、ext4、ext4dev、f2fs、lvm、xfs、vfat、swap文件系统。XFS只有在挂载时才会增长。vFAT将会失败如果fatresize < 1.04mount模块backupnoyes创建一个包含时间戳信息的备份文件,以便在您以某种方式错误地抓取原始文件时取回原始文件。bootyes·no确定文件系统是否应该挂载在引导上。仅适用于Solaris系统。dumpDefault: 0 Dump(见fstab(5))。请注意,如果设置为 null,state设置为present,它将停止工作,并将在后续运行中重复条目。对Solaris系统没有影响。fstab文件代替/etc/fstab。除非你真的知道自己在做什么,否则你不应该使用这个选项。如果您需要在chroot环境中配置挂载点,这可能会很有用。OpenBSD不允许指定带有挂载的备用fstab文件,因此不要在OpenBSD上以任何在实时文件系统上运行的状态使用它。在Solaris上,此参数默认为/etc/fstab或/etc/vfstab。fstype文件系统类型。当state是 present 或 mounted时需要。optsmount选项(请参阅solaris上的fstab(5)或vfstab(4))passnoDefault: 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: mountmount:path: /newpart #挂载到那个目录src: /dev/vdd1 #挂载内容fstype: ext4 #文件系统格式state: mountedlvg模块使用案例:(注意: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/vdbCommand (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 # 结束位置+5GCommand (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 MOUNTPOINTsr0 11:0 1 1024M 0 romvda 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 partvdc 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 ~]# vgsVG #PV #LV #SN Attr VSize VFreemyvg 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 VFreemyvg 2 0 0 wz--n- 19.99g 19.99glvol模块常用参数:lv 定义逻辑卷名size 定义逻辑卷大小vg 空间来自哪个卷组state{present 创建,absent 删除}force=yes 强制执行pvs 指定物理卷pesize 定义pe大小active yes no 卷是否处于激活状态且对主机可见。forceno ←· yes卷的收缩或删除操作需要此开关。确保文件系统不会被错误损坏/破坏lv 逻辑卷的名称。opts 传递给lvcreate命令的自由形式选项。pvs 物理卷的逗号分隔列表(例如/dev/sda,/dev/sdb)。resizefs· no ←· yes与逻辑卷一起调整底层文件系统的大小shrinkyes ←· no 如果当前尺寸大于要求的尺寸,则收缩。size 逻辑卷的大小,根据lvcreate(8)size,默认情况下以兆为单位,或可选使用[bBsSkKmMgGtTpPeE]单位之一;或者根据lvcreate(8) --extent作为[VGsnapshot 快照卷的名称state · present ← absent 控件是否存在逻辑卷。如果 present 且卷不存在,则需要使用 size 选项。thinpool 精简池卷名称。创建精简卷时,需要指定精简池卷名称。vg 逻辑卷所在的卷组。常用案例:tasks:- block:- name: create data of 1500Mlvol:vg: researchlv: datasize: 1500setup 模块用于收集远程主机的一些基本信息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: testhosts: alltasks:- name: setfacdebug:msg: "{{ ansible_all_ipv4_addresses[0] }} {{ ansible_fqdn }} {{ ansible_hostname }} "block模块的用法用和不动对比- hosts: testremote_user: roottasks:- shell: 'cat /etc/redhat-release'register: stdout_infoignore_errors: truerescue:- debug:msg: 'I caught an error'when: 'stdout_info is failed'用block:- hosts: testremote_user: roottasks:- 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: testuserremote_user: roottasks:- 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>1include_role模块 -- 加载并执行角色将指定的角色作为任务动态加载和执行。只能在Ansible任务允许的情况下使用——在pre_tasks, tasks,或post_tasks剧本对象内,或作为角色内的任务。任务级关键字、循环和条件只应用于include_role语句本身。要将关键字应用到角色中的任务,可以使用apply选项传递它们,或者使用import_role代替。忽略一些关键字,如until和retriesWindows目标也支持此模块name参数为指定角色的名称例如:- name: changedinclude_role:name: rhel-system-roles.selinuxstat模块:和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: alltasks:- name: create a cron file under /etc/cron.dcron:name: Lgin timeminute: "39" #分hour: "22" #时# day: "" #日month: "*/3" #月weekday: "0" #周user: jack #指定用户job: "(last && lastb)|grep jack" #执行内容firewalld模块参数:immediateyes or no,默认no 如果将此配置设置为永久性,则应立即应用此配置port在防火墙中添加或移除端口名称或端口范围。端口范围必须为PORT/PROTOCOL或PORT-PORT/PROTOCOL格式。service在防火墙中添加或移除服务名称该服务必须在firewall-cmd --get-services的输出中列出。stateabsent or disabled or enabled or present 启用或禁用一项设置。对于端口:该端口是否接受(enabled)或拒绝(disabled)连接。状态的(present)和(absent)只能在区域级别操作中使用(即,当除了zone和state没有设置其他参数时)。zone添加或移除的防火墙区域。注意,可以为每个系统配置默认的区域,可能的值有block, dmz, drop, external, home, internal, public, trusted, work,publicpermanentyes or no 该配置是否在运行的防火墙配置中,或者在重新启动时仍然存在。注意,如果这是no, immediate被假定为yes。masquerade在在防火墙中开启或关闭masquerade功能script模块用法创建一个sh文件里面内容是在tmp下创建一个文件,然后再用script执行cat /root/a.shtouch /tmp/testfileansible 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=trueansible node1:node2 -i inventory.ini -m yum -a "name=nginx state=present"systemd模块state 对当前服务启动,停掉、重启、重新加载等操作(started,stopped,restarted,reloaded)daemon_reload 重新载 systemd,扫描新的或有变动的单元enabled 是否开机启动 yes|noansible node1:node2 -i inventory.ini -m systemd -a "name=nginx state=started"group组模块gidinterger 要为组设置的可选 GID。name要管理的组的名称。systemboolean ·no、yes 如果yes,则表示创建的组是系统组ansible node1:node2 -i inventory.ini -m group -a "name=group1"loop模块:循环打印案例tasks:- name:Printdebug:msg: "{{ item }}" //这个是固定写法,必须要是itemloop: [1,2,3,4]批量建立文件案例:tasks:- name:cteate filefile:path:/tmp/file{{ item }}.txtstate: touchloop:- 1- 2- 3user模块常参数:name 必须的参数, 指定户名password 设置户的密码,这接受的是个加密的值,因为会直接存到 shadow, 默认不设置密码update_password 假如设置的密码不同于原密码,则会更新密码.home 指定户的家录shell 设置户的 shellcomment 户的描述信息create_home 在创建户时,是否创建其家录。默认创建,假如不创建,设置为 no。group 设置户的主组groups 将户加到多个其他组中,多个逗号隔开。默认会把⽤户从其他已经加⼊的组中删除。append yes|no 和 groups 配合使,yes 时,不会把户从其他已经加的组中删除,是否为附加组system 设置为 yes 时,将会创建个系统账号expires 设置户的过期时间,值为时间戳,会转为为天数后,放在 shadow 的第 8 个字段计算时间戳命令:date -d 2022-01-20 +%sgenerate_ssh_key 设置为 yes 将会为户成密钥,这不会覆盖原来的密钥ssh_key_type 指定户的密钥类型, 默认 rsa, 具体的类型取决于被管理节点state 删除或添加户, present 为添加,absent 为删除;默认值 presentremove 当与 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.j2Hello {{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.j2Hello 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开头的替换成ttttansible 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 Playbook2个任务剧本:---- name: nginx_install_starthosts: node1remote_user: roottasks:- name: install nginxyum: name=nginx state=present- name: copy one.sh to /tmp/one.shcopy: src=/root/one.sh dest=/tmp/one.sh- name: start nginxsystemd: name=nginx enabled=true state=started- name: shell runhosts: node2remote_user: roottasks:- name: show filesshell: ip addr list...安装python对yaml检测工具yum install python2-pippip 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_starthosts: node1remote_user: roottasks:- name: stop nginxsystemd: name=nginx enabled=false state=stopped- name: uninstall nginxyum: name=nginx state=absent- name: del /tmp/one.shfile: path=/tmp/one.sh state=absent- name: shell runhosts: node2remote_user: roottasks:- name: show filesshell: 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 varhosts: node1vars:user: ttthome: /home/ttttasks:- name: create user{{user}}user:name: "{{user}}"home: "{{home}}"...接着删除:[root@nfs ~]# !catcat playbook2.yaml---- name: test play varhosts: node1vars:user: ttthome: /home/ttttasks:- name: create user{{user}}user:name: "{{user}}"state: absentremove: yes...第2种:先建立一个变量文件[root@nfs ~]# cat users.ymluser: tttthome: /home/tttt[root@nfs ~]# cat playbook2.yaml---- name: test play varhosts: node1vars_files:- /root/users.ymltasks:- 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=22192.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=22192.168.136.159[node1:vars]home="/home/tom"[node2]192.168.136.158[all_node][all_node:children] //children是固定写法,这个all_node是包含两个主机组的全局变量node1node2## 剧本中调用用的内置变量都是以 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
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_starthosts: node1gather_facts: no //关闭默认的facts,remote_user: roottasks:- name: stop nginxsystemd: name=nginx enabled=false state=stopped- name: uninstall nginxyum: name=nginx state=absent- name: del /tmp/one.shfile: path=/tmp/one.sh state=absent- name: shell runhosts: node2remote_user: roottasks:- name: show filesshell: ip addr list...
注册变量(用于看剧本执行的结果的)
[root@nfs ~]# cat playbook1.yaml---- name: nginx_uninstall_starthosts: node1remote_user: roottasks:- name: stop nginxsystemd: name=nginx enabled=false state=stopped- name: uninstall nginxyum: name=nginx state=absentregister: uninstall_result //这里和下面的变量名称保持一致- name: print resultdebug: var=uninstall_result //利用注册变量看执行结果- name: del /tmp/one.shfile: path=/tmp/one.sh state=absent- name: shell runhosts: node2remote_user: roottasks:- name: show filesshell: ip addr list...
外部变量文件使用案例vim userdel.yml---user: ##定义变量名称- aaa- bbb- leevim skk.yml---- name: testhosts: server2vars_files: ##定义变量文件- ./userdel.yml ##定义变量文件位置tasks:- name: userdeluser:name: "{{ item }}" ##循环每一个变量state: absentremove: yesloop:"{{ user }}" ##定义循环的变量自定义变量并调用:- namehosts: devtasks:- nameset_fact:yeng: ttttttt- name:debug:var: yeng //也可以不调自定义的,直接调系统的如:msg: "{{ansible_date_time['time'] }}"滤出时间...
when:判断通过条件判断(when) 指令去使用语法校验的结果,只要语法检查通过都会去执⾏ "start nginx server"这个TASK。通过debug 模块,通过debug模块去确认返回结果的数据结构,打印出来的返回结果。 当nginxsyntax.rc 为 0时语法校验正确。when: 一些常用判读方法:exists、not exists、defined、undefined、none、success、failure、change、skipwhen: is not existwhen: is existwhen: is definedwhen: is undefinedwhen: is nonewhen: successwhen: failurewhen常用参数==!=> >=< <=is definedis undefinedtruefalse持逻辑运算符: and or判断vgs在不在用:when: "'research' in ansible_lvm.vgs" //或 not inwhen: 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 injinjia2获取主机信息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: main1hosts: devtasks:- name: testshell: /usr/bin/systemctl status vdoignore_errors: yesregister: result- name: open httpdservice:name: httpdstate: startedwhen: 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.existsnode1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"},"changed": false,"stat": {"exists": false}}用stat模块输出再注册一下再调用判断tasks:- name: file-not-yesstat:path: /etc/dxregister: file_status..........when: file_status.stat.exists == False 在就是True判断系统信息先查寻一下:ansible dev -m setup |grep ansible_distribution再写剧本 (可以加and和or)- name:debug:msg: centoswhen: 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 controlhosts: all_nodegather_facts: notasks:- name: create useruser:name: tomstate: presentpassword: "{{ 'adminw'|password_hash('sha512') }}"- name: yum is okyum:name: nginxstate: present- name: update nginxcopy:src: nginx.confdest: /etc/nginx/conf.d/- name: check nginxshell: /usr/sinb/nginx -tregister: nginx_check- name: print nginx check resultdebug:var: nginx_check- name: start serversystemd:name: nginxstate: startedwhen: nginx_check.rc == 0...循环控制在PlayBook中使with_items 去实现循环控制,且循环时的中间变量(上shell循环中的 $i 变量)只能是关键字 item ,不能随意定义。批量循环创建用户和密码:[root@nfs ~]# cat playbook3.yml- name: variable playbook examplehosts: all_nodegather_facts: novars:createuser:- tomcat- www- mysqltasks:- name: create useruser:name: "{{ item }}"state: presentpassword: "{{ '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 controlhosts: all_nodegather_facts: notasks:- name: create useruser:name: tomstate: presentpassword: "{{ 'adminw'|password_hash('sha512') }}"- name: yum is okyum:name: nginxstate: present- name: update nginxcopy:src: nginx.confdest: /etc/nginx/conf.d/tags: updateconfig- name: check nginxshell: /usr/sinb/nginx -tregister: nginxcheck- name: check nginx pidstat:path: /var/run/nginx.pidtags: updateconfig- name: print nginx check resultdebug:var: nginxcheck- name: print nginx rundebug:var: nginxrun- name: start serversystemd:name: nginxstate: startedwhen:- nginxcheck.rc == 0 and nginxrun.stat.exists == truetags: updateconfig...指定tags 去执PlayBook执时定要指定tags,这样再执的过程中只会执task 任务上打上tag 标记为 updateconfig 的任务ansible-playbook -i inventory.ini playbook2.yaml -t updateconfigHandlers 属性观察当前的 Playbook,不能发现,当我的配置件没有发变化时,每次依然都会去触发TASK "reload nginx server"。如何能做到只有配置⽂件发⽣变化的时候才去触发TASK "reloadnginx server",这样的处理才是最完美的实现。此时可以使handlers 属性。[root@nfs ~]# cat playbook2.yaml---- name: test playbook controlhosts: all_nodegather_facts: notasks:- name: create useruser:name: tomstate: presentpassword: "{{ 'adminw'|password_hash('sha512') }}"- name: yum is okyum:name: nginxstate: present- name: update nginxcopy:src: nginx.confdest: /etc/nginx/conf.d/notify: reload nginx server //监控些copy模拟返回值,两边名称要一致- name: check nginxshell: /usr/sinb/nginx -tregister: nginxcheck- name: check nginx pidstat:path: /var/run/nginx.pid- name: print nginx check resultdebug:var: nginxcheck- name: print nginx rundebug:var: nginxrun- name: start serversystemd:name: nginxstate: startedhandlers: //当上面监控的notify发生变化时就触发这里的动作- name: reload nginx serversystemed:name: nginxstate: reloadedjinjia2模本样本:{# 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.j2user 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_jinjia2hosts: node1gather_facts: notasks:- name: install_nginxyum:name: nginxstate: present- name: update_configtemplate:src: /root/nginx.config.j2dest: /etc/nginx/nginx.conf执行剧本传参数:ansible-playbook playbook5.yml -e "cpu_number=8"常用架构ansible判断语法结构(类似于python中的try---except----finally)tasks:-block //先执行block- name:yum:rescue: //block有错误就执行rescue- name:debug:always: //不管上面哪个有错误还是没错误,都要执行这个下面的- name:debug循环变量使用:- name:hosts: devvars:user_all:- user1- user2- user3task:- name:debug:msg: "{{ item }}" //item为关键字with_items: "{{ user_all }}" //with_items为关键字嵌套循环变量使用(类似于python中的for中再for):- name:hosts: devvars:user_all:- user1- user2- user3passwd_all:- admin1- admin2- admmin3task:- name:debug:msg: "{{ item[0] }}, {{ item[1]}}" //item为关键字with_nested: "{{ user_all }}, {{ passwd_all }}" //with_nested为关键字循环加when判断:- name:hosts: devvars:numbers:- 1- 2- 3- 4tasks:- name:debug:msg: "{{ item }}"with_items: "{{ numbers }}"when: item > 3 //只有大于3的才会执行,其它跳过
角色用法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自动创建galaxyansible-galaxy用法,类似于gethub可以直网上下载ansible-galaxy install //安装上共享的roleansible-galaxy delet //删除一个roleansible-galaxy removeansible-galaxy login //登陆ansible-galaxy init //创建一个role目录,不用上面一样手动创建了ansible-galaxy list //列举通过ansible-galaxy工具安装的roleansible-galaxy search //在galaxy上搜索共享的role(类似于gethub)系统角色yum安装(装完位置 /usr/share/ansible/roles)yum search roles 查系统角色软件包sudo yum -y install rhel-system-rolesansible-galaxy list //查看/usr/share/doc/rhel-system-roles/ 模板文件位置,可以拿出来自定义改一下用/usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml selinux.yml