云计算第二阶段---(自动化运维)AUTOMATION

AUTOMATION DAY1

一、Ansible基础

历史:开发于2012年,2015年被红帽收购。

介绍:是一款虚拟机自动化运维工具,基于PYTHON开发。

功能:批量系统设置,批量程序设置,批量运行命令。

特色:基于SSH模块丰富,支持自定义模块,异构IT架构,部署简单,容易上手?

环境准备

主机名IP地址角色
web1192.168.88.11被控制节点(webserver)
web2192.168.88.12被控制节点(webserver)
db1192.168.88.13被控制节点(database)
pubserver192.168.88.240控制节点(manager)
  • 4台主机,需要配置主机名、IP地址、YUM。关闭SELINUX和防火墙
 
# 创建3台主机并配置IP地址。pubserver不需要单独准备,继续使用之前课程中的192.168.88.240。

可以用它来克隆,并nmcli 设置IP 和 YUM 源 , hostnamectl  set-hostname  主机名即可。

这下面的是我学习时自带系统的命令,你用不了。可以用我上面这个方法。

[root@myhost ~]# vm clone web{1,2} db1
[root@myhost ~]# vm setip web1 192.168.88.11
[root@myhost ~]# vm setip web2 192.168.88.12
[root@myhost ~]# vm setip db1 192.168.88.13

# 在192.168.88.240上配置yum源

没有ANSIBLE  你可以去红帽官网下载,放到WINDWOS真机里面,找个好位置。

# 将/linux-soft/s2/目录下的ansible目录中rpm包拷贝到yum服务器的rpms目录
[root@myhost ~]# scp /linux-soft/s2/zzg/ansible_soft/* 192.168.88.240:/var/ftp/rpms
# 更新yum服务器仓库源
[root@pubserver ~]# createrepo /var/ftp/rpms/
 
# 4台主机的yum全为以下配置
[root@pubserver ~]# vim /etc/yum.repos.d/local.repo
[BaseOS]
name = BaseOS
baseurl = ftp://192.168.88.240/dvd/BaseOS
enabled = 1
gpgcheck = 0
 
[AppStream]
name = AppStream
baseurl = ftp://192.168.88.240/dvd/AppStream
enabled = 1
gpgcheck = 0
 
[rpms]          #这个是第二阶段SHELL模块自定义仓库的时候讲过,你也可以把它配置好,当网络仓库软件包存放位置。
name = rpms
baseurl = ftp://192.168.88.240/rpms
enabled = 1
gpgcheck = 0
  • 安装ansible
 
[root@pubserver ~]# yum install -y ansible
  • 配置控制节点pubserver,具体要求如下:

    • 配置名称解析,能够通过名字访问所有节点
    • 配置可以通过ssh到所有节点免密登陆
 
 
# 配置名称解析
[root@pubserver ~]# echo -e "192.168.88.240\tpubserver" >> /etc/hosts
[root@pubserver ~]# for i in 1 2
> do
> echo -e "192.168.88.1$i\tweb$i" >> /etc/hosts
> done
[root@pubserver ~]# echo -e "192.168.88.13\tdb1" >> /etc/hosts
[root@pubserver ~]# tail -4 /etc/hosts
192.168.88.240   pubserver
192.168.88.11    web1
192.168.88.12    web2
192.168.88.13    db1
 
# 配置免密登陆
[root@pubserver ~]# ssh-keygen   # 三个问题都直接回车,使用默认值
# 执行以下命令时,可能需要回答yes和远程用户的密码,请按提示操作
[root@pubserver ~]# for i in web{1..2} db1
> do
> ssh-copy-id $i
> done

配置ansible管理环境

大体就是1台主机当控制节点,另外4台当被控节点。像父母一辈的网络游戏传奇一样,一个道士牵4条狗。


  • 使用一套ansible软件,有可能需要管理多种环境。如在同一台管理主机上管理开发环境和生产环境。
  • 通过创建不同的工作目录,来实现相应的管理需求。
  • 将某一环境下的主机写入到对应工作目录的主机清单文件。
  • 进入对应的工作目录执行管理任务,就可以管理相应环境的主机。
 
 
# 创建ansible工作目录,目录名自己定义,不是固定的。

建议创建个文件夹存放,不然放在虚拟机ROOT下 太杂乱,不好找配位文件啥的。

[root@pubserver ~]# mkdir ansible
[root@pubserver ~]# cd ansible
# 创建配置文件。默认的配置文件是/etc/ansible/ansible.cfg,但是一般不使用它,而是在工作目录下创建自己的配置文件
[root@pubserver ansible]# vim ansible.cfg    # 文件名必须是ansible.cfg
[defaults]
host_key_checking = false   # 不检查主机密钥,=号两边空格可有可无。
inventory = inventory       # 定义主机清单文件为当前目录的inventory
 
# 创建主机清单文件。写在[]里的是组名,[]下面的是组内的主机名
[root@pubserver ansible]# vim inventory
[webservers]
web[1:2]   # web1和web2的简化写法,表示从1到2
 
[dbs]
db1
 
# cluster是组名,自定义的;:children是固定写法,表示下面的组名是cluster的子组。
[cluster:children]      # 含义是 cluster的子组是 webservers ,dbs
webservers
dbs
 
# 查看被管理的所有的主机。注意,一定在工作目录下执行命令。
[root@pubserver ansible]# ansible all --list-hosts
  hosts (3):
    web1
    web2
    db1
 
# 查看webservers组中所有的主机
[root@pubserver ansible]# ansible webservers --list-hosts
  hosts (2):
    web1
    web2

二、掌握Ansible ad-hoc 命令

输出结果展示: 

黄色:任务完成。        紫色:路径或执行命令不可行。   

红色:语法,单词拼写,格式错误      绿色:任务已执行成功。

ansible模块

  • 在ansible中,通过模块来完成某一特定任务。
  • 学习模块,主要知道实现某种功能,需要哪个模块。
  • 模块的使用方式都一样。主要是查看该模块有哪些参数。
 

# 列出全部可用模块,按空格键向下翻页,按q退出
[root@pubserver ansible]# ansible-doc -l
# 相关模块帮助文档:  ansible-doc  模块名  ——————》  输入  : /Example 回车,查看使用示例。
# 列出模块数量
[root@pubserver ansible]# ansible-doc -l | wc -l  # 如有WARNING提示,可忽略
# 查看包含yum的模块名
[root@pubserver ansible]# ansible-doc -l | grep yum
 
# 查看yum模块的帮助文档,按空格键向下翻页,按q退出
[root@pubserver ansible]# ansible-doc yum
command模块(像石头人一样,功能有限,识别不了高级用法。)

  • ansible默认模块,用于在远程主机上执行任意命令
  • command不支持shell特性,如管道、重定向。
 
# 在所有被管主机上创建目录/tmp/demo   使用该模块时,可以省略 -m command
[root@pubserver ansible]# ansible all -a "mkdir /tmp/demo"
 
# 查看we1的ip地址
[root@pubserver ansible]# ansible web1 -a "ip a s"
[root@pubserver ansible]# ansible web1 -a "ip a s | head"  # 报错
shell模块
  • 与command模块类似,但是支持shell特性,如管道、重定向。
# 查看web1的ip地址,只显示前10行
[root@pubserver ansible]# ansible web1 -m shell -a "ip a s | head"
script模块
  • 用于在远程主机上执行脚本
# 在控制端创建脚本即可
[root@pubserver ansible]# vim test.sh
#!/bin/bash
 
for user in user{1..5}
do
    useradd $user
    echo '123456' | passwd --stdin $user
done
 
# 在webservers组的主机上执行脚本
[root@pubserver ansible]# ansible webservers -m script -a "test.sh"

三、Ansible模块简单应用

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

  • 常用的选项:

    • path:指定文件路径
    • owner:设置文件所有者
    • group:设置文件所属组
    • state:状态。touch表示创建文件,directory表示创建目录,link表示创建软链接,absent表示删除
    • mode:设置权限
    • src:source的简写,源
    • dest:destination的简写,目标
 
# 查看使用帮助
[root@pubserver ansible]# ansible-doc file
... ...
EXAMPLES:
- name: Change file ownership, group and permissions  # 忽略
  ansible.builtin.file:           # 模块名。以下是它的各种参数
    path: /etc/foo.conf           # 要修改的文件的路径
    owner: foo                    # 文件所有者
    group: foo                    # 文件的所有组
    mode: '0644'                  # 权限
... ...
# 根据上面的example,-m file -a的内容就是doc中把各参数的冒号换成=号
 
# 在webservers组的主机上创建/tmp/file.txt
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt state=touch"   # touch是指如果文件不存在,则创建;如果存在则改变它的时间戳
 
# 在webservers组的主机上创建/tmp/demo目录
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/demo state=directory"
 
# 将webservers组的主机上/tmp/file.txt的属主改为sshd,属组改为adm,权限改为0777
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt owner=sshd group=adm mode='0777'"
[root@pubserver ansible]# ansible webservers -a "ls -l /tmp/file.txt"
 
# 删除webservers组的主机上/tmp/file.txt
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt state=absent"    # absent英文缺席的、不存在的
 
# 删除webservers组的主机上/tmp/demo
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/demo state=absent"
 
# 在webservers组的主机上创建/etc/hosts的软链接,目标是/tmp/hosts.txt
[root@pubserver ansible]# ansible webservers -m file -a "src=/etc/hosts dest=/tmp/hosts.txt state=link"
copy模块
  • 用于将文件从控制端拷贝到被控端

  • 常用选项:

    • src:源。控制端的文件路径
    • dest:目标。被控制端的文件路径
    • content:内容。需要写到文件中的内容
 

 
[root@pubserver ansible]# echo "AAA" > a3.txt
# 将a3.txt拷贝到webservers主机的/root/
[root@pubserver ansible]# ansible webservers -m copy -a "src=a3.txt dest=/root/"
 
# 在目标主机上创建/tmp/mytest.txt,内容是Hello World
[root@pubserver ansible]# ansible webservers -m copy -a "content='Hello World' dest=/tmp/mytest.txt"
fetch模块
  • 与copy模块相反,copy是上传,fetch是下载

  • 常用选项:

    • src:源。被控制端的文件路径
    • dest:目标。控制端的文件路径
 

 
# 将webservers主机上的/etc/hostname下载到本地用户的家目录下
[root@pubserver ansible]# ansible webservers -m fetch -a "src=/etc/hostname dest=~/"
[root@pubserver ansible]# ls /root/web1/etc/   # web1是webservers组中的主机
hostname
[root@pubserver ansible]# ls /root/web2/etc/
hostname
lineinfile模块
  • 用于确保存目标文件中有某一行内容

  • 常用选项:

    • path:待修改的文件路径
    • line:写入文件的一行内容
    • regexp:正则表达式,用于查找文件中的内容
 

 
# webservers组中的主机,/etc/issue中一定要有一行Hello World。如果该行不存在,则默认添加到文件结尾
[root@pubserver ansible]# ansible webservers -m lineinfile -a "path=/etc/issue line='Hello World'"
 
# webservers组中的主机,把/etc/issue中有Hello的行,替换成chi le ma
[root@pubserver ansible]# ansible webservers -m lineinfile -a "path=/etc/issue line='chi le ma' regexp='Hello'"
replace模块
  • lineinfile会替换一行,replace可以替换关键词

  • 常用选项:

    • path:待修改的文件路径
    • replace:将正则表达式查到的内容,替换成replace的内容
    • regexp:正则表达式,用于查找文件中的内容
 

 
# 把webservers组中主机上/etc/issue文件中的chi,替换成he
[root@pubserver ansible]# ansible webservers -m replace -a "path=/etc/issue regexp='chi' replace='he'"
文件操作综合练习
  • 所有操作均对webservers组中的主机生效
  • 在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777
  • 将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600
  • 替换目标主机/tmp/mydemo/hosts文件中的db1为database1
  • 将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录
 

 
# 在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/mydemo owner=adm group=adm mode='0777' state=directory" 
 
# 将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600
[root@pubserver ansible]# ansible webservers -m copy -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode='0600'"
 
# 替换目标主机/tmp/mydemo/hosts文件中的db1为database1
[root@pubserver ansible]# ansible webservers -m replace -a "path=/tmp/mydemo/hosts regexp='db1' replace='database1'"
 
# 将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录。
[root@pubserver ansible]# ansible webservers -m fetch -a "src=/tmp/mydemo/hosts dest=."
user模块
  • 实现linux用户管理

  • 常用选项:

    • name:待创建的用户名
    • uid:用户ID
    • group:设置主组
    • groups:设置附加组
    • home:设置家目录
    • password:设置用户密码
    • state:状态。present表示创建,它是默认选项。absent表示删除
    • remove:删除家目录、邮箱等。值为yes或true都可以。
 

 
# 在webservers组中的主机上,创建zhangsan用户
[root@pubserver ansible]# ansible webservers -m user -a "name=zhangsan"
 
# 在webservers组中的主机上,创建lisi用户。设置其uid为1010,主组是adm,附加组是daemon和root,家目录是/home/lisi
[root@pubserver ansible]# ansible webservers -m user -a "name=lisi uid=1010 group=adm groups=daemon,root home=/home/lisi"
 
# 设置zhangsan的密码是123456
# {{}}是固定格式,表示执行命令。password_hash是函数,sha512是加密算法,则password_hash函数将会把123456通过sha512加密变成zhangsan的密码
[root@pubserver ansible]# ansible webservers -m user -a "name=zhangsan password={{'123456'|password_hash('sha512')}}"
 
# 删除zhangsan用户,不删除家目录
[root@pubserver ansible]# ansible webservers -m user -a "name=zhangsan state=absent"
 
# 删除lisi用户,同时删除家目录
[root@pubserver ansible]# ansible webservers -m user -a "name=lisi state=absent remove=yes"
group模块
  • 创建、删除组

  • 常用选项:

    • name:待创建的组名
    • gid:组的ID号
    • state:present表示创建,它是默认选项。absent表示删除
 

 
# 在webservers组中的主机上创建名为devops的组
[root@pubserver ansible]# ansible webservers -m group -a "name=devops"
 
# 在webservers组中的主机上删除名为devops的组
[root@pubserver ansible]# ansible webservers -m group -a "name=devops state=absent"

后面一段时间的内容会提升难度。是ansible自动化运维的高级使用。做好心理准备 O(∩_∩)O


 AUTOMATION DAY2 

一、常用模块

yum_repository
  • 用于配置yum

  • 常用选项:

    • file: 指定文件名
    • 其他选项,请与文件内容对照

# 在webservers组中的主机上,配置yum
[root@pubserver ansible]# ansible webservers -m yum_repository -a "file=myrepo name=myApp description='My App' baseurl=ftp://192.168.88.240/dvd/AppStream gpgcheck=no enabled=yes"
[root@web1 ~]# cat /etc/yum.repos.d/myrepo.repo 
[myApp]
async = 1
baseurl = ftp://192.168.88.240/dvd/AppStream
enabled = 1
gpgcheck = 0
name = My App
 
[root@pubserver ansible]# ansible webservers -m yum_repository -a "file=myrepo name=BaseOS description='Base OS' baseurl=ftp://192.168.88.240/dvd/BaseOS gpgcheck=no enabled=yes"
 
[root@web1 ~]# cat /etc/yum.repos.d/myrepo.repo 
[myApp]
async = 1
baseurl = ftp://192.168.88.240/dvd/AppStream
enabled = 1
gpgcheck = 0
name = My App
 
[BaseOS]
async = 1
baseurl = ftp://192.168.88.240/dvd/BaseOS
enabled = 1
gpgcheck = 0
name = Base OS
yum模块
  • 用于rpm软件包管理,如安装、升级、卸载

  • 常用选项:

    • name:包名
    • state:状态。present表示安装,如果已安装则忽略;latest表示安装或升级到最新版本;absent表示卸载。
    • (有些软件 需要state需要注明 present 状态,为了避免出错还是要在安装时写上。)

# 在webservers组中的主机上安装tar
[root@pubserver ansible]# ansible webservers -m yum -a "name=tar state=present"
# 在webservers组中的主机上安装wget、net-tools

wget:  从网络上通过URL连接下载文件 。 用法: wget  + 网络URL 连接

net-tools: 查看 IP地址的 组件  ,我们第一阶段常用的 ifconfig 命令的软件包。

[root@pubserver ansible]# ansible webservers -m yum -a "name=wget,net-tools"
 
# 在webservers组中的主机上卸载wget
[root@pubserver ansible]# ansible webservers -m yum -a "name=wget state=absent"
service模块
  • 用于控制服务。启动、关闭、重启、开机自启。

  • 常用选项:

    • name:控制的服务名
    • state:started表示启动;stopped表示关闭;restarted表示重启
    • enabled:yes表示设置开机自启;no表示设置开机不要自启。
# 在test主机上安装nginx
[root@pubserver ansible]# ansible webservers -m yum -a "name=nginx state=latest"

注意: latest表示 软件安装到 yum库中的最新版本。

#  在test主机上启动nginx,并设置它开机自启
[root@pubserver ansible]# ansible webservers -m service -a "name=nginx state=started enabled=yes"
逻辑卷相关模块
  • 逻辑卷可以动态管理存储空间。可以对逻辑卷进行扩容或缩减。
  • 可以把硬盘或分区转换成物理卷PV;再把1到多个PV组合成卷组VG;然后在VG上划分逻辑卷LV。LV可以像普通分区一样,进行格式化、挂载。
  • 关闭虚拟机web1,为其添加2块20GB的硬盘
  • LINUX下KVM虚拟机新加的硬盘,名称是/dev/vdb/dev/vdc
  • vmware虚拟机新加的硬盘,名称是/dev/sdb/dev/sdc
  • 如果选nvme硬盘,名称可能是/dev/nvme0n1/dev/nvme0n2

[root@web1 ~]# lsblk    # 可以查看到新加的硬盘vdb和vdc
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 
vdc    253:32   0   20G  0 disk 
lvg模块
  • 创建、删除卷组,修改卷组大小

  • 常用选项:

    • vg:定义卷组名。全称:vg:volume group
    • pvs:由哪些物理卷构成。全称:pvs:physical volumes
# 在web1上安装lvm2,state不写,默认是present
[root@pubserver ansible]# ansible web1 -m yum -a "name=lvm2"

lvm2软件包是一些列查看网络内存信息状态的软件合集包。

# 手工在web1上对vdb进行分区
[root@web1 ~]# 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@web1 ~]# 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 
 
# 在web1上创建名为myvg的卷组,该卷组由/dev/vdb1组成
[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1"
 
# 在web1上查看卷组
[root@web1 ~]# vgs
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   1   0   0 wz--n- <5.00g <5.00g
 
# 扩容卷组。卷组由PV构成,只要向卷组中加入新的PV,即可实现扩容
[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1,/dev/vdb2"
 
[root@web1 ~]# vgs  # 在web1上查看卷组
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   2   0   0 wz--n- 19.99g 19.99g
lvol模块
  • 创建、删除逻辑卷,修改逻辑卷大小

  • 常用选项:

    • vg:指定在哪个卷组上创建逻辑卷
    • lv:创建的逻辑卷名。lv:logical volume
    • size:逻辑卷的大小,不写单位,以M为单位
 

 
# 在web1上创建名为mylv的逻辑卷,大小为2GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=2G"
注意:在使用lvol模块时,也要把前面创建的卷组名写上 。
# 在web1上查看逻辑卷
[root@web1 ~]# lvs
  LV   VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  mylv myvg -wi-a----- 2.00g   
  
# mylv扩容至4GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=4G"
 
[root@web1 ~]# lvs  # 在web1上查看逻辑卷
  LV   VG   Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  mylv myvg -wi-a----- 4.00g   
filesystem模块
  • 用于格式化,也就是创建文件系统

  • 常用选项:

    • fstype:指定文件系统类型    xfs, ext4
    • dev:指定要格式化的设备,可以是分区,可以是逻辑卷
 
#  在web1上,把/dev/myvg/mylv格式化为xfs
[root@pubserver ansible]# ansible web1 -m filesystem -a "fstype=xfs dev=/dev/myvg/mylv"
 
# 在web1上查看格式化结果
[root@web1 ~]# blkid /dev/myvg/mylv
/dev/myvg/mylv: UUID="46c0af72-e517-4b15-9e53-ec72fbe1d96e" TYPE="xfs"
mount模块
  • 用于挂载文件系统

  • 常用选项:

    • path:挂载点。如果挂载点不存在,自动创建。
    • src:待挂载的设备
    • fstype:文件系统类型       #容易忘记的选项
    • state:mounted,表示永久挂载   
 # 在web1上,把/dev/myvg/mylv永久挂载到/data
[root@pubserver ansible]# ansible web1 -m mount -a "path=/data src=/dev/myvg/mylv state=mounted fstype=xfs"
 
# 在web1上查看
[root@web1 ~]# tail -1 /etc/fstab 
/dev/myvg/mylv /data xfs defaults 0 0
[root@web1 ~]# df -h /data/
Filesystem             Size  Used Avail Use% Mounted on
/dev/mapper/myvg-mylv  4.0G   61M  4.0G   2% /data
 
 
# 在web1上,卸载/dev/myvg/mylv
[root@pubserver ansible]# ansible web1 -m mount -a "path=/data state=absent"
 
# 在web1上,强制删除/dev/myvg/mylv
[root@pubserver ansible]# ansible web1 -m lvol -a "lv=mylv state=absent vg=myvg force=yes"   # force是强制
 
# 在web1上,删除myvg卷组
[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg state=absent"

    第一小节,我们学习到的ansible  自动化方式 是 ad-hoc方式,今天学习 playbook方式。简单理解来说,一种是横着敲命令,一种是竖着敲。就像秦时明月的鬼谷纵横的盖聂和卫庄一样。

        ad-hoc使用场景有限制,而playbook剧本方式,可以用vim编写,在文档中及时更改。可以一起使用多个模块,功能更加强大高效。


二、YAML语言

  • YAML Ain't a Markup Language:YAML不是一个标记语言
yaml语法规范
  1. yaml文件的文件名,一般以yml或yaml作为扩展名
  2. 文件一般以---作为第一行,不是必须的,但是常用
  3. 键值对使用冒号:表示,冒号后面必须有空格。
  4. 数组使用-表示,-后面必须有空格。
  5. 相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格。
  6. 全文不能使用tab,必须使用空格。

yaml的语法规范,就好比社会上的交通规则和一些约定好的公序良俗。

配置vim适应yaml语法
# 文件位置和名字是固定的,用于设置vim的格式

下面这个设置可以打破 不能使用 TAB的限制,并且让你工作效率提高。

1下 TAB = 2下空格。 高亮显示还可以帮助我们对齐格式

[root@pubserver ansible]# vim ~/.vimrc
set ai        # 设置自动缩进
set ts=2      # 设置按tab键,缩进2个空格
set et        # 将tab转换成相应个数的空格

  set  cuc           # 将正在写的内容横竖 高亮对齐显示。

三、playbook

  • 常用于复杂任务的管理,以及管理经常要完成的任务
  • playbook也是通过模块和它的参数,在特定主机上执行任务
  • playbook是一个文件,该文件中需要通过yaml格式进行书写

编写playbook

  • 一个剧本(即playbook),可以包含多个play
  • 每个play用于在指定的主机上,通过模块和参数执行相应的任务
  • 每个play可以包含多个任务。
  • 任务有模块和参数构成。
格式很重要!!!!!!!!!!!!!!!!!!!很重要
# 编写用于测试连通性的playbook,相当于执行ansible all -m ping
[root@pubserver ansible]# vim test.yml
---
- hosts: all
  tasks:
    - ping:
[root@pubserver ansible]# ansible-playbook test.yml  # 执行playbook
 
# 以上更规范的写法如下:
[root@pubserver ansible]# vim test.yml
---
- name: test network            # play的名字,可选项
  hosts: all                    # 作用于所有的主机
  tasks:                        # 任务
    - name: test via ping       # 第1个任务的名字,可选项
      ping:                     # 第1个任务使用的模块
 
[root@pubserver ansible]# ansible-playbook test.yml  # 执行playbook
 
 
# 在dbs组的主机和web1上创建/tmp/demo目录,权限是0755。将控制端/etc/hosts拷贝到目标主机的/tmp/demo中
[root@pubserver ansible]# vim fileop.yml
---
- name: create dir and copy file
  hosts: dbs,web1    # 这里的名称,必须出现在主机清单文件中
  tasks:
    - name: create dir
      file:
        path: /tmp/demo
        state: directory
        mode: '0755'
    
    - name: copy file
      copy:
        src: /etc/hosts
        dest: /tmp/demo/hosts
 
# 执行playbook
[root@pubserver ansible]# ansible-playbook fileop.yml
 
 
# 在webservers组中的主机上,创建用户bob,附加组是adm;在db1主机上,创建/tmp/hi.txt,其内容为Hello World.
[root@pubserver ansible]# vim two.yml
---
- name: create user
  hosts: webservers
  tasks:
    - name: create bob
      user:
        name: bob
        groups: adm
 
- name: create file
  hosts: db1
  tasks:
    - name: make file
      copy:
        dest: /tmp/hi.txt
        content: "Hello World"
 
[root@pubserver ansible]# ansible-playbook two.yml
  • |>的区别:|它保留换行符,>把多行合并为一行
 

 
# 通过copy模块创建/tmp/1.txt,文件中有两行内容,分别是Hello World和ni hao
[root@pubserver ansible]# vim f1.yml
---
- name: play 1
  hosts: webservers
  tasks:
    - name: mkfile 1.txt
      copy:
        dest: /tmp/1.txt
        content: |
          Hello World!
          ni hao.
 
[root@pubserver ansible]# ansible-playbook f1.yml
# 查看结果
[root@web1 ~]# cat /tmp/1.txt 
Hello World!
ni hao.
 
 
# 通过copy模块创建/tmp/2.txt,文件中有一行内容,分别是Hello World! ni hao
[root@pubserver ansible]# vim f2.yml 
---
- name: play 1
  hosts: webservers
  tasks:
    - name: mkfile 2.txt
      copy:
        dest: /tmp/2.txt
        content: >
          Hello World!
          ni hao.
 
[root@pubserver ansible]# ansible-playbook f2.yml
[root@web1 ~]# cat /tmp/2.txt 
Hello World! ni hao.
  • playbook示例
 

 
# 在webservers组中的主机上创建john用户,它的uid是1040,主组是daemon,密码为123
[root@pubserver ansible]# vim user_john.yml
---
- name: create user
  hosts: webservers
  tasks:
    - name: create user john
      user:
        name: john
        uid: 1040
        group: daemon
        password: "{{'123'|password_hash('sha512')}}"
[root@pubserver ansible]# ansible-playbook user_john.yml
 
# 在webservers组中的主机上删除用户john
[root@pubserver ansible]# vim del_john.yml
---
- name: delete user
  hosts: webservers
  tasks:
    - name: delete user john
      user:
        name: john
        state: absent
[root@pubserver ansible]# ansible-playbook del_john.yml
硬盘管理
  • 常用的分区表类型有:MBR(主引导记录)、GPT(GUID分区表)
  • MBR最多支持4个主分区,或3个主分区加1个扩展分区。最大支持2.2TB左右的硬盘
  • GPT最多支持128个主分区。支持大硬盘
parted模块
  • 用于硬盘分区管理

  • 常用选项:

    • device:待分区的设备
    • number:分区编号
    • state:present表示创建,absent表示删除
    • part_start:分区的起始位置,不写表示从开头
    • part_end:表示分区的结束位置,不写表示到结尾
 

 
# 在web1主机上,对/dev/vdc进行分区,创建1个1GB的主分区
[root@pubserver ansible]# vim disk.yml
---
- name: disk manage
  hosts: web1
  tasks:
    - name: create a partition
      parted:
        device: /dev/vdc
        number: 1
        state: present
        part_end: 1GiB
 
[root@pubserver ansible]# ansible-playbook disk.yml
 
# 在目标主机上查看结果
[root@web1 ~]# lsblk 
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
.. ...
vdc    253:32   0   20G  0 disk 
`-vdc1 253:33   0 1023M  0 part 
 
# 继续编辑disk.yml,对/dev/vdc进行分区,创建1个新的5GB的主分区
[root@pubserver ansible]# vim disk.yml 
... ...
    - name: add a new partition
      parted:
        device: /dev/vdc
        number: 2
        state: present
        part_start: 1GiB
        part_end: 6GiB
 
[root@pubserver ansible]# ansible-playbook disk.yml 
[root@web1 ~]# lsblk 
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
... ...
vdc    253:32   0   20G  0 disk 
|-vdc1 253:33   0 1023M  0 part 
`-vdc2 253:34   0    5G  0 part 
 
# 继续编辑disk.yml,创建名为my_vg的卷组,它由上面创建的vdc1和vdc2构成
[root@pubserver ansible]# vim disk.yml 
... ...
    - name: create my_vg
      lvg:
        vg: my_vg
        pvs: /dev/vdc1,/dev/vdc2
 
# 继续编辑disk.yml,在my_vg卷组上创建名为my_lv的逻辑卷,大小1G
[root@pubserver ansible]# vim disk.yml 
... ...
    - name: create my_lv
      lvol:
        vg: my_vg
        lv: my_lv
        size: 1G
 
 
# 继续编辑disk.yml,格式化my_lv为ext4
[root@pubserver ansible]# vim disk.yml 
... ...
    - name: mkfs my_lv
      filesystem:
        dev: /dev/my_vg/my_lv
        fstype: ext4
 
 
# 继续编辑disk.yml,将my_lv挂载到/data
[root@pubserver ansible]# vim disk.yml 
... ...
    - name: mount my_lv
      mount:
        path: /data
        src: /dev/my_vg/my_lv
        fstype: ext4
        state: mounted
 
# 完整的disk.yml如下
---
- name: disk manage
  hosts: web1
  tasks:
    - name: create a partition
      parted:
        device: /dev/vdc
        number: 1
        state: present
        part_end: 1GiB
 
    - name: add a new partition
      parted:
        device: /dev/vdc
        number: 2
        state: present
        part_start: 1GiB
        part_end: 6GiB
 
    - name: create my_vg
      lvg:
        vg: my_vg
        pvs: /dev/vdc1,/dev/vdc2
 
    - name: create my_lv
      lvol:
        vg: my_vg
        lv: my_lv
        size: 1G
        
    - name: mkfs my_lv
      filesystem:
        dev: /dev/my_vg/my_lv
        fstype: ext4
 
    - name: mount my_lv
      mount:
        path: /data
        src: /dev/my_vg/my_lv
        fstype: ext4
        state: mounted

AUTOMATION DAY3

一、Ansible  模块进阶及变量

       

# 在webservers组中的主机上,安装httpd、php、php-mysqlnd
[root@pubserver ansible]# vim pkg.yml
---
- name: install pkgs
  hosts: webservers
  tasks:
    - name: install web pkgs  # 此任务通过yum安装三个包
      yum:
        name: httpd,php,php-mysqlnd
        state: present

# 安装多个软件包,还可以写为:写法2

---
- name: install pkgs
  hosts: webservers
  tasks:
    - name: install web pkgs
      yum:
        name: [httpd,php,php-mysqlnd]
        state: present
 

# 安装多个软件包,还可以写为:写法3   (使用较多)

---
- name: install pkgs
  hosts: webservers
  tasks:
    - name: install web pkgs
      yum:
        name: 
          - httpd
          - php
          - php-mysqlnd
        state: present
 

#安装大型包组(RPM)的方法


​​​​​​​# 根据功能等,可以将一系列软件放到一个组中,安装软件包组,将会把很多软件一起安装上。比如gcc、java等都是开发工具,安装开发工具包组,将会把它们一起安装。

[root@node1 ~]# yum grouplist   # 列出所有的软件包组
[root@node1 ~]# yum groupinstall "Development Tools"  
# 如果列出的组名为中文,可以这样进行:
[root@node1 ~]# LANG=C yum grouplist
 
# 继续编辑pkg.yml,在webservers组中的主机上安装Development tools组
[root@pubserver ansible]# vim pkg.yml
---
- name: install pkgs
  hosts: webservers
  tasks:
    - name: install web pkgs    # 此任务通过yum安装三个包
      yum:
        name:
          - httpd
          - php
          - php-mysqlnd
        state: present
 
    - name: install dev group    # 此任务通过yum安装一组包
      yum:
        name: "@Development Tools"   # @表示后面的名字是组名
        state: present
 
[root@pubserver ansible]# ansible-playbook pkg.yml
 
# 系统升级命令
[root@pubserver ansible]# yum update
# 继续编辑pkg.yml,在webservers组中的主机上升级所有的包到最新版本
---
- name: install pkgs
  hosts: webservers
  tasks:
    - name: install web pkgs
      yum:
        name:
          - httpd
          - php
          - php-mysqlnd
        state: present
 
    - name: install dev group
      yum:
        name: "@Development Tools"    #安装包组
        state: present
 
    - name: update system    # 相当于yum update命令
      yum:
        name: "*"       # 表示系统已经安装的所有包
        state: latest    #把软件更新到yum仓库中最新版本
 
[root@pubserver ansible]# ansible-playbook pkg.yml

ansible变量

facts变量

  • facts翻译过来就是事实。
  • facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息。
  • facts变量通过setup模块获得。
 

 

# 通过setup模块查看所有facts变量

用法:  ansible  主机组名 -m setup |  less   # 可以通过管道 less 查看

[root@pubserver ansible]# ansible webservers -m setup
  • facts变量是一个大的由{}构成的键值对字典。在{}中,有很多层级的嵌套。可以通过参数过滤出第一个层级的内容。
 

 

# 查看所有的IPV4地址,filter是过滤的意思

[root@pubserver ansible]# ansible webservers -m setup -a "filter=ansible_all_ipv4_addresses"
 
# 查看可用内存
[root@pubserver ansible]# ansible webservers -m setup -a "filter=ansible_memfree_mb"
  • 常用的facts变量

    • ansible_all_ipv4_addresses:所有的IPV4地址
    • ansible_bios_version:BIOS版本信息
    • ansible_memtotal_mb:总内存大小
    • ansible_hostname:主机名
  • 在playbook中使用变量

 

 
# 显示远程主机的主机名和内存大小。在ansible中,变量使用{{}}表示
# debug模块用于输出信息,常用的参数是msg,用于输出指定内容
[root@pubserver ansible]# vim debug.yml
---
- name: display host info
  hosts: webservers
  tasks:
    - name: display hostname and memory
      debug:    # debug是模块,它的选项msg可以输出指定信息
        msg: "hostname: {{ansible_hostname}}; mem: {{ansible_memtotal_mb}} MB"
 
[root@pubserver ansible]# ansible-playbook debug.yml

自定义变量

  • 引入变量,可以方便Playbook重用。比如装包的playbook,包名使用变量。多次执行playbook,只要改变变量名即可,不用编写新的playbook。

  • ansible支持10种以上的变量定义方式。常用的变量来源如下:

    • inventory变量。变量来自于主机清单文件
    • facts变量。
    • playbook变量。变量在playbook中定义。
    • 变量文件。专门创建用于保存变量的文件。推荐变量写入单独的文件。
注意: 清单( inventory) 中设置的变量是全局变量,剧本中设立的变量属于局部变量。

变量与变量值用逗号空格隔开,如下

变量文件名字(如 vars).yml     

a:  xixi  

b:  haha 

剧本中调用变量文件    test.yml 

---

- hosts: all

  vars_files:  vars.yml   #上面创建的变量文件 

  tasks: 

     - debug:                 #测试输出信息的模块

             msg:  “{{ab}}“”   #前面变量文件中的变量名                                                   

# 使用inventory变量。
​​​​​​​[root@pubserver ansible]# vim inventory
[webservers]
web1
web2

[dbs]
db1 username="wangwu"   # 定义主机变量的方法
[webservers:vars]       # 定义组变量的方法,:vars是固定格式,children子组设置也是固定格式。
username="zhaoliu"

# 通过变量创建用户
[root@pubserver ansible]# vim var1.yml
---
- name: webservers create user
  hosts: webservers
  tasks:
    - name: create user
      user:
        name: "{{username}}"
        state: present  
- name: create user in dbs
  hosts: dbs
  tasks:
    - name: create some users
      user:
        name: "{{username}}"

        state: present
 
[root@pubserver ansible]# ansible-playbook var1.yml
 

# 上述两个play也可以合并为一个,如下:

[root@pubserver ansible]# vim var1.yml
---
- name: webservers create user
  hosts: dbs,webservers    # 指定执行的目标是webservers组和webservers组
  tasks:
    - name: create user
      user:
        name: "{{username}}"
        state: present
        
 

# 在playbook中定义变量

# 在webservers组中的主机上创建用户jack,他的密码是123456
[root@pubserver ansible]# vim user_jack.yml
---
- name: create user
  hosts: webservers
  vars:    # 固定格式,用于声明变量
    username: "jack"    # 此处引号可有可无
    mima: "123456"      # 此处引号是需要的,表示数字字符
  tasks:
    - name: create some users
      user:
        name: "{{username}}"   # {}出现在开头,必须有引号
        state: present
        password: "{{mima|password_hash('sha512')}}"   #注意sha512加密方式汇中,不能出现小数点
[root@pubserver ansible]# ansible-playbook user_jack.yml
 
 

# 将变量定义在文件中

[root@pubserver ansible]# vim vars.yml   # 文件名自定义
---
yonghu: rose
mima: abcd
[root@pubserver ansible]# vim user_rose.yml 
---
- name: create user
  hosts: webservers
  vars_files: vars.yml   # vars_files用于声明变量文件
  tasks:
    - name: create some users
      user:
        name: "{{yonghu}}"   # 这里的变量来自于vars.yml
        state: present
        password: "{{mima|password_hash('sha512')}}"
 
[root@pubserver ansible]# ansible-playbook user_rose.yml 

补充模块

firewalld模块
  • 用于配置防火墙的模块

  • 常用选项:

    • port:声明端口
    • permanent:永久生效,但不会立即生效
    • immediate:立即生效,临时生效           类似于 systemctl enabled firewalld --now
    • state:enabled放行 ;disabled拒绝
  • 防火墙一般默认拒绝,明确写入允许的服务。

  • 有一些服务有名字,有些服务没有名字。但是最终都是基于TCP或UDP的某些端口。比如http服务基于TCP80端口。服务名和端口号对应关系的说明文件是:/etc/services

  • 配置服务器的防火墙,一般来说只要配置开放哪些服务或端口即可。没有明确开放的,都默认拒绝。

  • 应用

    • 在webservers组中的主机上安装并启动nginx
    • 客户端访问服务器的nginx服务
    • 在webservers组中的主机上安装并启动firewalld
    • 客户端访问服务器的nginx服务
    • 在webservers组中的主机上开放nginx服务
# 配置nginx服务
[root@pubserver ansible]# vim firewall.yml
---
- name: configure webservers
  hosts: webservers
  tasks:
    - name: install nginx pkg   # 这里通过yum模块装httpd
      yum:
        name: nginx
        state: present
    - name: start nginx service   # 这里通过service模块启httpd服务
      service:
        name: nginx
        state: started
        enabled: yes
        
[root@pubserver ansible]# ansible-playbook firewall.yml
[root@pubserver ansible]# curl http://192.168.88.11/  # 可访问
 
# 安装并启动firewalld
[root@pubserver ansible]# vim firewall.yml
---
- name: configure webservers
  hosts: webservers
  tasks:
    - name: install nginx pkg   # 这里通过yum模块装httpd
      yum:
        name: nginx
        state: present
 
    - name: start nginx service   # 这里通过service模块启httpd服务
      service:
        name: nginx
        state: started
        enabled: yes
  
    - name: install firewalld pkg   # 这里通过yum模块装firewalld
      yum:
        name: firewalld
        state: present
 
    - name: start firewalld service   # 这里通过service模块启firewalld服务
      service:
        name: firewalld
        state: started
        enabled: yes
  
[root@pubserver ansible]# ansible-playbook firewall.yml
[root@pubserver ansible]# curl http://192.168.88.11/  # 被拒绝
curl: (7) Failed to connect to 192.168.88.11 port 80: 没有到主机的路由
 
# 配置防火墙规则,放行http协议
[root@pubserver ansible]# vim firewall.yml
---
- name: configure webservers
  hosts: webservers
  tasks:
    - name: install nginx pkg   # 这里通过yum模块装httpd
      yum:
        name: nginx
        state: present
 
    - name: start nginx service   # 这里通过service模块启httpd服务
      service:
        name: nginx
        state: started
        enabled: yes
  
    - name: install firewalld pkg   # 这里通过yum模块安装firewalld
      yum:
        name: firewalld
        state: present
 
    - name: start firewalld service   # 这里通过service模块启service服务
      service:
        name: firewalld
        state: started
        enabled: yes
  
    - name: set firewalld rules   # 通过firewalld模块开放80端口
      firewalld:
        port: 80/tcp             #放行的端口 以及端口  所属协议
        permanent: yes            #永久设置
        immediate: yes
        state: enabled
 
[root@pubserver ansible]# ansible-playbook firewall.yml 
[root@pubserver ansible]# curl http://192.168.88.11/  # 可访问
template模块          注意与 copy 模块做区分
  • copy模块可以上传文件,但是文件内容固定

  • template模块可以上传具有特定格式的文件(如文件中包含变量)

  • 当远程主机接收到文件之后,文件中的变量将会变成具体的值

  • template模块上传的文件,使用的语法叫Jinja2。

  • 常用选项:

    • src:要上传的文件
    • dest:目标文件路径

# 使用template模块将含有变量的文件上传到webservers组中的主机

[root@pubserver ansible]# vim index.html
Welcome to {{ansible_hostname}} on {{ansible_eth0.ipv4.address}}

[root@pubserver ansible]# vim templ.yml
---
- name: upload index
  hosts: webservers
  tasks:
    - name: create web index
      template:
        src: index.html
        dest: /usr/share/nginx/html/index.html
 
[root@pubserver ansible]# ansible-playbook templ.yml

#测试访问个网络节点

[root@pubserver ansible]# curl http://192.168.88.11/
Welcome to web1 on 192.168.88.11
[root@pubserver ansible]# curl http://192.168.88.12
Welcome to web2 on 192.168.88.12
[root@web1 ~]# cat /usr/share/nginx/html/index.html
Welcome to web1 on 192.168.88.11
[root@web2 ~]# cat /usr/share/nginx/html/index.html

Welcome to web2 on 192.168.88.12

二、 Ansible  使用进阶及错误处理

错误处理

  • 当Playbook中包含很多任务时,当某一个任务遇到错误,它将崩溃,终止执行
# 在webservers组中的主机上启动mysqld服务,然后创建/tmp/service.txt
# 因为目标主机上没有mysqld服务,所以它将崩溃,终止执行。即,不会创建/tmp/service.txt文件
[root@pubserver ansible]# vim myerr.yml
---
- name: my errors
  hosts: webservers
  tasks:
    - name: start mysqld service  # 通过service模块启动mysqld服务
      service:
        name: mysqld
        state: started
        enabled: yes     
    - name: touch a file   # 通过file模块创建文件
      file:
        path: /tmp/service.txt
        state: touch
# 执行playbook,第1个任务就会失败
[root@pubserver ansible]# ansible-playbook myerr.yml
# 到node1上查看,因为第2个任务没有执行,所以文件不会创建
[root@web1 ~]# ls /tmp/service.txt
ls: cannot access '/tmp/service.txt': No such file or directory

忽略报错语法的使用

  • 可以指定某一个任务如果出现错误,则忽略它
# 编辑myerr.yml,如果myslqd服务无法启动,则忽略它
[root@pubserver ansible]# vim myerr.yml
---
- name: my errors
  hosts: webservers
  tasks:
    - name: start mysqld service
      service:
        name: mysqld
        state: started
        enabled: yes
      ignore_errors: yes    # 即使这个任务失败了,也要继续执行下去
    - name: touch a file
      file:
        path: /tmp/service.txt
        state: touch
[root@pubserver ansible]# ansible-playbook myerr.yml
[root@web1 ~]# ls /tmp/service.txt   # 第2个任务已执行
/tmp/service.txt

全局设置  忽略报错语法

  • 通过全局设置,无论哪个任务出现问题,都要忽略
  • 类似于剧本中,变量的使用
[root@pubserver ansible]# vim myerr.yml
---
- name: my errors
  hosts: webservers
  ignore_errors: yes
  tasks:
    - name: start mysqld service
      service:
        name: mysqld
        state: started
        enabled: yes
    - name: touch a file
      file:
        path: /tmp/mysql.txt
        state: touch
 
[root@pubserver ansible]# ansible-playbook myerr.yml
[root@web1 ~]# ls /tmp/mysql.txt 
/tmp/mysql.txt

触发执行任务

  • 通过handlers定义触发执行的任务
  • handlers中定义的任务,不是一定会执行的
  • 在tasks中定义的任务,通过notify关键通知handlers中的哪个任务要执行
  • 只有tasks中的任务状态是changed才会进行通知。
 
# 下载web1上的/etc/nginx/nginx.conf
[root@pubserver ansible]# vim get_conf.yml
---
- name: download nginx.conf
  hosts: web1
  tasks:
    - name: get nginx.conf
      fetch:
        src: /etc/nginx/nginx.conf
        dest: ./
        flat: yes    # 直接下载文件,不要目录
[root@pubserver ansible]# ansible-playbook get_conf.yml
# 修改nginx.conf的端口为变量
[root@pubserver ansible]# vim +39 nginx.conf
... ...
    server {
        listen       {{http_port}} default_server;
        listen       [::]:{{http_port}} default_server;
        server_name  _;
... ...
# 修改nginx服务的端口为8000,重启nginx
[root@pubserver ansible]# vim trigger.yml
---
- name: configure nginx
  hosts: webservers
  vars:
    http_port: "8000"   # 定义nginx.conf中的变量和值
  tasks:
    - name: upload nginx.conf   # 上传nginx.conf
      template:
        src: ./nginx.conf
        dest: /etc/nginx/nginx.conf
    - name: restart nginx    # 重启服务
      service:
        name: nginx
        state: restarted
# 第一次执行trigger.yml,上传文件和重启服务两个任务的状态都是黄色changed
[root@pubserver ansible]# ansible-playbook trigger.yml
# 第二次执行trigger.yml,上传文件的任务状态是绿色的ok,重启服务任务的状态是黄色changed
[root@pubserver ansible]# ansible-playbook trigger.yml
 
# 既然配置文件没有改变,那么服务就不应该重启
# 修改Playbook,只有配置文件变化了,才重启服务
[root@pubserver ansible]# vim trigger.yml
---
- name: configure nginx
  hosts: webservers
  vars:
    http_port: "80"
  tasks:
    - name: upload nginx.conf
      template:
        src: ./nginx.conf
        dest: /etc/nginx/nginx.conf
      notify: restart nginx   # 通知restart httpd需要执行
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted
# 第一次运行Playbook,因为第1个任务是黄色的changed,所以handlers中的任务也被触发执行
[root@pubserver ansible]# ansible-playbook trigger.yml 
# 第二次运行Playbook,因为第1个任务是绿色的OK,也就不会再触发执行其他任务了
[root@pubserver ansible]# ansible-playbook trigger.yml 
 

when条件

  • 只有满足某一条件时,才执行任务

  • 常用的操作符:

    • ==:相等
    • !=:不等
    • >:大于
    • <:小于
    • <=:小于等于
    • >=:大于等于
  • 多个条件或以使用and或or进行连接

  • when表达式中的变量,可以不使用{{}}

 

 
# 当dbs组中的主机内存大于2G的时候,才安装mysql-server
[root@pubserver ansible]# vim when1.yml
---
- name: install mysql-server
  hosts: dbs
  tasks:
    - name: install mysql-server pkg
      yum:
        name: mysql-server
        state: present
      when: ansible_memtotal_mb>2048     #注意和判断条件时,使用的模块对齐
 
# 如果目标主机没有2GB内存,则不会安装mysqld-server
[root@pubserver ansible]# ansible-playbook when1.yml
 
# 多条件。系统发行版是Rocky8才执行任务
# /etc/motd中的内容,将会在用户登陆时显示在屏幕上
[root@pubserver ansible]# vim motd
 _____________
< hello world >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
 
[root@pubserver ansible]# vim when2.yml
---
- name: when condition
  hosts: webservers
  tasks:
    - name: modify /etc/motd
      copy:
        dest: /etc/motd
        src: motd
      when: >     # 以下三行合并成一行
        ansible_distribution == "Rocky"
        and
        ansible_distribution_major_version == "8"
 
[root@pubserver ansible]# ansible-playbook when2.yml

regitster注册变量

Ansible的“register”模块是用于捕获和保存任务执行结果的,它允许将其他任务的输出作为变量使用。register是一个关键字,可以将任务执行的结果赋值给指定的变量名称。这个变量可以在后续任务中使用。 register模块可以捕获各种类型的输出,包括stdout、stderr、rc、changed等。它可以与其他模块一起使用,例如“when”条件、“loop”循环等。

# 在web1组的主机上执行任务,创建/tmp/regfile1.txt,并打印创建结果
[root@pubserver ansible]# vim reg1.yml
---
- name: create file /tmp/regfile1.txt
  hosts: web1
  tasks:
    - name: create file
      file:
        path: /tmp/rgefile1.txt
        state: touch
      register: result
 
    - name: display output
      debug:
        msg: "{{result}}"
 
# 在web1主机上执行任务,创建文件/tmp/ademo/abc。如果创建不成功,则通过debug输出create failed
[root@pubserver ansible]# vim reg2.yml
---
- name: create file /tmp/ademo/abc
  hosts: web1
  ignore_errors: yes
  tasks:
    - name: create file
      file:
        path: /tmp/ademo/abc
        state: touch
      register: result
 
    - name: debug output
      debug:
        msg: "create failed"
      when: result.failed

---开心一刻 ---

cowsay:   #执行代码时的图案程序

#cowsay是一个软件,可以在以下地址获得
# https://rpmfind.net/linux/epel/8/Everything/x86_64/Packages/c/cowsay-3.04-16.el8.noarch.rpm
# 使用方式如下:
[root@pubserver ansible]# yum install -y /root/cowsay-3.04-16.el8.noarch.rpm
[root@pubserver ansible]# cowsay ni hao a
__________
< ni hao a >
----------
  \   ^__^
   \  (oo)\_______
      (__)\       )\/\
          ||----w |
          ||     ||
 
 
# 查看其他形象
[root@pubserver ansible]# cowsay -l  # 查看其他形象
Cow files in /usr/share/cowsay:
beavis.zen blowfish bud-frogs bunny cheese cower default dragon
dragon-and-cow elephant elephant-in-snake eyes flaming-sheep fox
ghostbusters head-in hellokitty kiss kitty koala kosh luke-koala
mech-and-cow meow milk moofasa moose mutilated ren sheep skeleton small
stegosaurus stimpy supermilker surgery telebears three-eyes turkey turtle
tux udder vader vader-koala www

#用法:   cowsay -f   类型   输出文字  

[root@pubserver ansible]# cowsay -f elephant are you ok? 
_____________
< are you ok? >
-------------
\     /\  ___  /\
\   // \/   \/ \\
((    O O    ))
\\ /     \ //
 \/  | |  \/
  |  | |  |
  |  | |  |
  |   o   |
  | |   | |
  |m|   |m|

取消剧本执行输出图案

​​​​​​​

# 如果执行playbook时也会出现奶牛,则可以使用以下方式取消
[root@pubserver ansible]# echo 'nocows = 1' >> ansible.cfg

 AUTOMATION DAY4

一、任务块及循环使用

任务块

  • 可以通过block关键字,将多个任务组合到一起
  • 可以将整个block任务组,一起控制是否要执行
 
 

小练习

# 如果webservers组中的主机系统发行版是Rocky,则安装并启动nginx
[root@pubserver ansible]# vim block1.yml
---
- name: block tasks
  hosts: webservers
  tasks:
    - name: define a group of tasks
      block:
        - name: install nginx   # 通过yum安装nginx
          yum:
            name: nginx
            state: present
        - name: start nginx     # 通过service启动nginx服务
          service:
            name: nginx
            state: started
            enabled: yes
 
 
      when: ansible_distribution=="Rocky"   # 条件为真才会执行上面的任务
[root@pubserver ansible]# ansible-playbook block1.yml
注意:  写法中 只有开始的block有 数值 - 符号
[root@pubserver ansible]# vim block2.yml
---
- name: block test
  hosts: webservers
  tasks:
    - name: block / rescue / always test1
      block:
        - name: touch a file
          file:
            path: /tmp/test1.txt
            state: touch
      rescue:
        - name: touch file test2.txt
          file:
            path: /tmp/test2.txt
            state: touch
      always:
        - name: touch file test3.txt
          file:
            path: /tmp/test3.txt
            state: touch
 
 
# 执行playbook web1上将会出现/tmp/test1.txt和/tmp/test3.txt
[root@pubserver ansible]# ansible-playbook block2.yml
[root@web1 ~]# ls /tmp/test*.txt
/tmp/test1.txt  /tmp/test3.txt
 
 
# 修改上面的playbook,使block中的任务出错
[root@web1 ~]# rm -f /tmp/test*.txt
[root@pubserver ansible]# vim block2.yml
---
- name: block test
  hosts: webservers
  tasks:
    - name: block / rescue / always test1
      block:
        - name: touch a file
          file:
            path: /tmp/abcd/test11.txt
            state: touch
      rescue:
        - name: touch file test22.txt
          file:
            path: /tmp/test22.txt
            state: touch
      always:
        - name: touch file test33.txt
          file:
            path: /tmp/test33.txt
            state: touch
# 因为web1上没有/tmp/abcd目录,所以block中的任务失败。但是playbook不再崩溃,而是执行rescue中的任务。always中的任务总是执行
[root@pubserver ansible]# ansible-playbook block2.yml
[root@web1 ~]# ls /tmp/test*.txt
/tmp/test22.txt  /tmp/test33.txt

loop循环

  • 相当于shell中for循环
  • ansible中循环用到的变量名是固定的,叫item
# 在test组中的主机上创建5个目录/tmp/{aaa,bbb,ccc,ddd,eee}
[root@pubserver ansible]# vim loop1.yml
---
- name: use loop
  hosts: webservers
  tasks:
    - name: create directory
      file:
        path: /tmp/{{item}}
        state: directory
      loop: [aaa,bbb,ccc,ddd,eee]    #类似yum 模块的写法
# 上面写法,也可以改为:
---
- name: use loop
  hosts: webservers
  tasks:
    - name: create directory
      file:
        path: /tmp/{{item}}
        state: directory
      loop: 
        - aaa
        - bbb
        - ccc
        - ddd
        - eee
 
 
[root@pubserver ansible]# ansible-playbook loop1.yml
 
 
# 使用复杂变量。创建zhangsan用户,密码是123;创建lisi用户,密码是456
# item   是固定的,用于表示循环中的变量
# 循环时,loop中每个-后面的内容作为一个整体赋值给item。
# loop中{}中的内容是自己定义的,写法为key:val
# 取值时使用句点表示。如下例中取出用户名就是{{item.uname}}
[root@pubserver ansible]# vim loop_user.yml
---
- name: create users
  hosts: webservers
  tasks:
    - name: create multiple users
      user:
        name: "{{item.uname}}"
        password: "{{item.upass|password_hash('sha512')}}"
      loop:
        - {"uname": "zhangsan", "upass": "123"}
        - {"uname": "lisi", "upass": "456"}
[root@pubserver ansible]# ansible-playbook  loop_user.yml

二、角色

role角色

  • 为了实现playbook重用,可以使用role角色
  • 角色role相当于把任务打散,放到不同的目录中
  • 再把一些固定的值,如用户名、软件包、服务等,用变量来表示
  • role角色定义好之后,可以在其他playbook中直接调用
# 使用常规playbook,修改/etc/motd的内容
# 1. 创建motd模板文件
[root@pubserver ansible]# vim motd
Hostname: {{ansible_hostname}}     # facts变量,主机名
Date: {{ansible_date_time.date}}   #  facts变量,日期
Contact to: {{admin}}              # 自定义变量
 
 
# 2. 编写playbook
[root@pubserver ansible]# vim motd.yml
---
- name: modifty /etc/motd
  hosts: webservers
  vars:
    admin: root@xixi.cn            # 自定义名为admin的变量
  tasks:
    - name: modify motd
      template:
        src: motd
        dest: /etc/motd
 
 
[root@pubserver ansible]# ansible-playbook motd.yml
[root@web1 ~]# cat /etc/motd 
Hostname: web1
Date: 2021-11-01
Contact to: root@xixi.cn
 
 
 
 
# 创建角色
# 1. 声明角色存放的位置
[root@pubserver ansible]# vim ansible.cfg 
[defaults]
inventory = hosts
roles_path = roles    # 定义角色存在当前目录的roles子目录中
# 2. 创建角色目录
[root@pubserver ansible]# mkdir roles 
 
 
# 3. 创建名为motd的角色
[root@pubserver ansible]# ansible-galaxy init roles/motd #初始化角色目录
[root@pubserver ansible]# ls roles/
motd     # 生成了motd角色目录
[root@pubserver ansible]# yum install -y tree
[root@pubserver ansible]# tree roles/motd/
roles/motd/


如何理解?

相当于网游中的捏脸系统,每个部位都可以单独设置,设置完成后,相应的部位存放在相应的 捏脸数据文件夹中。

        如果你不更改,系统就会使用相应部位的 默认模版来设置相关角色。


├── defaults         # 定义变量的目录,优先级最低
│    └── main.yml    #每个部分的模板文件,可以参考模块参数如何使用
├── files            # 保存上传的文件(如copy模块用到的文件)
├── handlers         # handlers任务写到这个目录的main.yml中
│    └── main.yml
├── meta             # 保存说明数据,如角色作者、版本等
│    └── main.yml
├── README.md        # 保存角色如何使用之类的说明
├── tasks            # 保存任务
│    └── main.yml
├── templates        # 保存template模块上传的模板文件
├── tests            # 保存测试用的playbook。可选
│    ├── inventory
│    └── test.yml
└── vars             # 定义变量的位置,推荐使用的位置
     └── main.yml
 
 
# 4. 将不同的内容分别写到对应目录的main.yml中
# 4.1 创建motd模板文件
[root@pubserver ansible]# vim roles/motd/templates/motd
Hostname: {{ansible_hostname}}
Date: {{ansible_date_time.date}}
Contact to: {{admin}}
 
 
# 4.2 创建变量
[root@pubserver ansible]# vim roles/motd/vars/main.yml  # 追加一行
admin: zzg@tedu.cn
 
 
# 4.3 创建任务
[root@pubserver ansible]# vim roles/motd/tasks/main.yml  # 追加
- name: modify motd
  template:
    src: motd      # 这里的文件,自动到templates目录下查找
    dest: /etc/motd
 
 
# 5. 创建playbook,调用motd角色
[root@pubserver ansible]# vim role_motd.yml
---
- name: modify motd with role
  hosts: webservers
  roles:
    - motd
 
 
# 6. 执行playbook
[root@pubserver ansible]# ansible-playbook role_motd.yml 

role练习

  1. 创建名为pkgs的角色。用于装包。包名使用变量pkg代表
  2. 创建inst_nginx.yml,调用pkgs角色,安装nginx
  3. 创建inst_mysql.yml,调用pkgs角色,安装mysql

# 1. 创建名为pkgs的角色。
# 1.1 创建角色目录
[root@pubserver ansible]# ansible-galaxy init roles/pkgs
# 1.2 创建装包的任务,包名使用变量pkg代表
[root@pubserver ansible]# vim roles/pkgs/tasks/main.yml 
---
# tasks file for roles/pkgs
- name: install rpm pkg
  yum:
    name: "{{pkg}}"
    state: present
# 1.3 定义变量
[root@pubserver ansible]# vim roles/pkgs/defaults/main.yml 
---
# defaults file for roles/pkgs
pkg: nginx
 
 
# 2. 创建inst_nginx.yml,调用pkgs角色,安装nginx
[root@pubserver ansible]# vim inst_nginx.yml
---
- name: install nginx pkg
  hosts: webservers
  roles:
    - pkgs
[root@pubserver ansible]# ansible-playbook inst_nginx.yml
 
 
# 3. 创建inst_mysql.yml,调用pkgs角色,安装mysql-server
[root@pubserver ansible]# vim inst_mysql.yml 
---
- name: install mysql pkg
  hosts: dbs
  vars:
    pkg: mysql-server
  roles:
    - pkgs
[root@pubserver ansible]# ansible-playbook inst_mysql.yml
 
 

 
 
# 在公共仓库中搜索与nginx相关的角色
[root@myhost ~]# ansible-galaxy search nginx
# 如果找到相应的角色,如名字为mynginx,可以下载它到roles目录
[root@myhost ~]# ansible-galaxy install mynginx -p roles/

三、补充知识

ansible加解密文件

  • ansible加解密文件使用ansible-vault命令
 
 
[root@pubserver ansible]# echo "Hello World!" > hello.txt 
[root@pubserver ansible]# cat hello.txt
Hello World!
 
 
# 加密文件
[root@pubserver ansible]# ansible-vault encrypt hello.txt
New Vault password: 123456
Confirm New Vault password: 123456
Encryption successful
[root@pubserver ansible]# cat hello.txt
$ANSIBLE_VAULT;1.1;AES256
37373366353566346235613731396566646533393361386131313632306563633336333963373465
6164323461356130303863633964393339363738653036310a666564313832316263393061616330
32373133323162353864316435366439386266616661373936363563373634356365326637336165
6336636230366564650a383239636230623633356565623461326431393634656666306330663533
6235
# 解密文件
[root@pubserver ansible]# ansible-vault decrypt hello.txt
Vault password: 123456
Decryption successful
[root@pubserver ansible]# cat hello.txt 
Hi ni hao
 
 
 
 
# 加密后更改密码
[root@pubserver ansible]# ansible-vault encrypt hello.txt 
New Vault password: 123456
Confirm New Vault password: 123456
Encryption successful
[root@pubserver ansible]# ansible-vault rekey hello.txt   # 改密码
Vault password: 123456    # 旧密码
New Vault password: abcd  # 新密码
Confirm New Vault password: abcd
Rekey successful
 
 
# 不解密文件,查看内容
[root@pubserver ansible]# ansible-vault view hello.txt 
Vault password: abcd
Hi ni hao
 
 
 
 

# 使用密码文件进行加解密

# 1. 将密码写入文件 (密文)
[root@pubserver ansible]# echo 'qq.cn' > pass.txt
# 2. 创建明文文件  
[root@pubserver ansible]# echo 'hello world' > data.txt
# 3. 使用pass.txt中的内容作为密码加密文件
[root@pubserver ansible]# ansible-vault encrypt --vault-id=pass.txt data.txt
Encryption successful
[root@pubserver ansible]# cat data.txt    # 文件已加密
# 4. 使用pass.txt中的内容作为密码解密文件
[root@pubserver ansible]# ansible-vault decrypt --vault-id=pass.txt(空格)data.txt
Decryption successful
[root@pubserver ansible]# cat data.txt 
hello world

使用思想:

  • 使用ansible管理远程主机,存储敏感数据时(如,文件中包含密码),应该将其加密
  • 执行playbook时,通过--ask-vault-password选项提示输入密码
 
 
# 1. 编写有密码的playbook
[root@pubserver ansible]# vim user_zhangsan.yml
---
- name: create a user
  hosts: webservers
  tasks:
    - name: create user zhangsan
      user:
        name: zhangsan
        password: "{{'123'|password_hash('sha512')}}"
 
 
# 2. 加密playbook
[root@pubserver ansible]# ansible-vault encrypt user_zhangsan.yml
New Vault password: 123456
Confirm New Vault password: 123456
Encryption successful
 
 
# 3. 直接执行playbook,报错
[root@pubserver ansible]# ansible-playbook user_zhangsan.yml
ERROR! Attempting to decrypt but no vault secrets found
 
 
# 4. 使用--ask-vault-password选项
[root@pubserver ansible]# ansible-playbook --ask-vault-password user_zhangsan.yml
Vault password: 123456

sudo命令

  • 一般用于普通用户执行需要root权限的命令
  • 在web1上配置zhangsan拥有sudo权限
 
 
# 如果没有zhangsan,手工创建
[root@web1 ~]# visudo   # 将会打开vim 编辑sudo提权文件,在尾部追加以下一行
zhangsan        ALL=(ALL)       ALL
# 中间的ALL=(ALL)在集中认证的域环境中才有效,单机忽略即可
# zhangsan是用户名,最后的ALL表示zhangsan可以以管理员的身份执行所有命令
# 切换成zhangsan用户,执行命令
[root@web1 ~]# su - zhangsan
[zhangsan@web1 ~]$ useradd wangwu   # 失败,因为还是张三身份
[zhangsan@web1 ~]$ sudo useradd wangwu  # 以管理员身份执行
... ...
[sudo] password for zhangsan: # 输入zhangsan的密码,不是root
 
 
# 配置lisi不输入密码可以直接运行sudo
[root@web1 ~]# visudo    # 在最后追加一行
lisi    ALL=(ALL)       NOPASSWD: ALL
# 切换成lisi运行
[root@web1 ~]# su - lisi
[lisi@web1 ~]$ ls /root/   # 没权限
ls: cannot open directory '/root/': Permission denied
[lisi@web1 ~]$ sudo ls /root/    # 成功运行,无需输入密码
a3.txt  anaconda-ks.cfg

特殊的主机清单变量

如何查到:通过 setup(字典)模块 查询

  • 如果远程主机没有使用免密登陆,如果远程主机ssh不是标准的22端口,可以设置特殊的主机清单变量
  • ansible_ssh_user:指定登陆远程主机的用户名
  • ansible_ssh_pass:指定登陆远程主机的密码
  • ansible_ssh_port:指定登陆远程主机的端口号
# 删除远程主机的/root/.ssh/authorized_keys,以便恢复通过密码登陆
[root@pubserver ansible]# ansible all -m file -a "path=/root/.ssh/authorized_keys state=absent"
# 创建新的工作目录
[root@pubserver ~]# mkdir myansible
[root@pubserver ~]# cd myansible
[root@pubserver myansible]# vim ansible.cfg
[defaults]
inventory = inventory
[root@pubserver myansible]# vim inventory
[group1]
web1
web2
db1
[root@pubserver myansible]# ansible all -m ping  # 报错,因为无法免密执行
 
 
# 修改web1 ssh服务的端口为220
[root@web1 ~]# systemctl stop firewalld
[root@web1 ~]# echo 'Port 220' >> /etc/ssh/sshd_config
[root@web1 ~]# systemctl restart sshd
# 退出再登陆时,需要指定端口号
[root@myhost ~]# ssh -p220 192.168.88.11 
 
 
 
 
 
 
# 配置ssh通过用户名、密码管理远程主机,通过220端口连接web1
[root@pubserver myansible]# vim inventory 
[group1]
web1 ansible_ssh_user=root ansible_ssh_pass=a ansible_ssh_port=220
web2 ansible_ssh_user=root ansible_ssh_pass=a
db1 ansible_ssh_user=root ansible_ssh_pass=a
 
 
[root@pubserver myansible]# ansible all -m ping

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值