ansble自动化--全文讲解及自动部署nfs,rsyncd
手机端可直接播放下方视频,PC端请点击播放按钮或点此处查看原视频
目录
Toggle市面上常见的批量管理方案:
简单对比 ansible vs for循环
for串行,1个1个处理.
pssh/pscp/psync 相比于ssh有并发功能软件包名pssh
ansible并行,默认5个并发.
基于ansible故障排查流程:
连接故障.远程连接,密钥认证.
自动化部署服务故障:
根据故障所在的步骤.
把步骤所对应的命令,把命令在对应的节点手动运行.
定位是ans问题还是服务问题.
服务问题就根据对应服务的排查流程
1.部署与使用
- centos/ubuntu/debian
yum install -y ansible
#ansible 2.9.xxx
apt install -y ansible
- 麒麟linux—-ansible 4.xx
安装python软件.
python版本
python 3.x
python 2.7 #centos 麒麟 停止维护.
python 3.x选择,系统中有哪个就用哪个.
如果没有yum/apt一个就行.
如果apt/yum安装的版本不满足,则编译安装python指定版本.
- python3安装新版本ansible
#1.python 3中安装 pip,python中软件包管理命令.
yum install -y python3-pip
#2.卸载/tmp/ #安装ansible时会大量写入临时文件(麒麟把tmp放入内存中)
umount -lf /tmp/
#3.安装ansible
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple ansible
-i 临时指定清华源
#4.检查
如果仍然坚持使用yum安装ansible 则按照如下流程操作即可.安装的是ansible 2.9.x
python 2中安装 ansible
yum install -y python2-pip ansible
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jinja2
ansible –version
1.2 配置
1) ansible命令的配置
/etc/ansible/ansible.cfg
修改/etc/ansible/ansible.cfg配置文件 71和111行,去掉注释即可.
host_key_checking = False
#关闭主机信息认证,即批量管理时的yes/no
log_path = /var/log/ansible.log
#日志目录:记录ansible都干过什么事
2)被管理机器的清单(inventory 主机清单)
主机清单获取:
- 根据已有的清单获取(表格 …其他系统)
- 公有云导出
- 书写脚本ping/fping+获取ip.
分组名不能与主机名一致
什么是主机清单: 让ansible管理的节点的列表.
ansible默认读取在/etc/ansible/hosts文件,并非/etc/hosts.
未来实际使用中一般我们会把主机清单文件存放在指定的目录中,运行ansible的时候通过-i选项指定主机清单文件即可.
主机清单分组详解:
需要我们进行分组:按照层次进行分组,按照功能/业务
/etc/ansible/hosts
主机清单可以分组,
子组使用children关键词创建
格式:
[data:children] #组名字:children即可.
分组案例:给backup,nfs 2个组合并新的组叫data
data组包含了backup和nfs
children:子组. data父亲,backup和nfs孩子
案例:主机清单中表示范围(ip地址后跟[起始数字:结束数字:间隔])
[root@m01 ~]# cat /etc/ansible/hosts
[web]
172.16.1.[7:10] [从哪里开始:到哪里结束]
172.16.1.7-10
还可以写成:
10.0.0.[1:50:2] #每隔2为1个ip地址,10.0.0.1,10.0.0.3,10.0.0.5 等等
案例:没有配置密钥认证,主机清单如何书写.(使用明文指定用户名密码的方式)
172.16.1.7 ansible_user=root ansible_password=1 ansible_port=22
3)测试是否连接成功
ansible all -m ping
1.3 管理
ansible点对点模式(命令行)批量管理流程:
- 配置好密钥认证 ✅
- 书写yaml剧本/使用命令
主机清单
文档(inventory) /etc/ansible/hosts ✅
- 开始使用ansible管理
Ansible必知必会模块
Ansible模块概述:
ansible中的模块就类似于Linux中的命令,我们Linux命令管理系统,我们通过ansible模块实现批量管理.
ansible中模块一般相当于Linux中的一些命令.yum模块,file模块,user模块.
ansible中的模块拥有不同的选项,这些选项一般都是一些单词,拥有自己的格式与要求
查询帮助:ansible-doc -s 模块名
1) 命令与脚本类模块
a) command模块☆☆☆☆☆
是ans默认的模块,适用于执行简单的命令,不支持特殊符号.
b) shell模块☆☆☆☆☆
与command模块类似,但是shell支持特殊符号.
案例01:批量执行hostname -I命令
ansible all -m shell -a "hostname -I"
ansible 被管理的主机/分组/all all表示所有
-m 指定模块 shell模块运行命令(不指定的话command模块是ansible默认模块.)
-a 模块的参数
案例02: 批量创建文件 oldboy01.txt …oldboy10.txt
ansible all -m shell -a "touch /tmp/oldboy{01..10}.txt"
与command模块类似,但是shell支持特殊符号.
案例03:批量删除/tmp/下面所有内容
ansible all -m shell -a 'rm -rf /tmp/*'
案例04:批量获取ip地址
ansible all -m shell -a "ip a s eth0 |awk -F'[/]+' 'NR==3{print \$3}'"
c) script模块☆☆☆☆☆
3) 案例05: 批量执行脚本
1.分发脚本(管理机上已有的脚本分发)
2.执行脚本(自动执行)
3.直接执行管理机上的脚本
cat /server/scripts/check.sh ip a hostname whoami pwd
ansible all -m script -a "/server/scripts/check.sh"
2) 文件相关模块
a) file模块☆☆☆☆☆
案例05: 创建/opt/lidao.txt ☆
ansible all -m file -a 'path=/opt/lidao.txt state=touch'
案例06: 创建目录/app/ ☆(自动递归创建)
ansible all -m file -a 'path=/app/a/b/c/d/e/g/ state=directory '
案例07: 创建软连接 /etc/hosts创建软连接到/opt/下 ☆
ln -s /etc/hosts /opt/hosts
ansible all -m file -a ' src=/etc/hosts path=/opt/hosts state=link '
#检验是否成功:查看软连接是否可以展示出连接的的文件即可
ansible all -a 'cat /opt/hosts'
案例08: 创建/ans-backup/目录 所有者是rsync,权限是700
创建文件或目录的时候,进行修改权限,所有者.
ansible all -m file -a 'path=/ans-backup/ owner=oldboy group=oldboy mode=700 state=directory'
案例09: 删除/oldboy/目录
ansible all -m file -a 'path=/ans-backup/ state=absent'
b) copy模块☆☆☆☆☆
作用:批量分发,1个节点(管理节点)发送文件或压缩包到所有被管理端. 注意:copy是单向的传输,类似于scp
注意:不建议使用copy命令传输目录,速度非常慢,替代方案:先打包压缩,再进行传输
案例10: 分发书写好的/etc/hosts文件,如果文件存在则备份下.
在/etc/hosts中增加 172.16.1.10 web04 然后分发hosts文件.
ansible all -m copy -a 'src=/etc/hosts dest=/etc/hosts backup=yes'
额外扩展:copy是推送,批量推送.
fetch是拉取,批量拉取.使用较少. 拉取所有主机的/etc/hostname
使用场景:给被管理机进行系统巡检后需要拉取各个节点的巡检日志
ansible all -m fetch -a 'src=/etc/hostname dest=/tmp/'
c) lineinfile模块
修改文件中的行—-原理:找到这一行进行修改–搜索某行,找到之后进行此行的替换操作
通过ansible修改文件的策略:
sed修改替换功能
cat批量写入内容功能.
echo写入功能.(追加)
管理机准备好配置文件copy分发.
未来修改配置文件使用lineinfile模块,类似于sed -i ‘sg’和sed ‘cai’
案例11: /etc/ssh/sshd_config去掉Port前面的注释符号
目标找到此行:#Port 22
修改为(将此行替换为)Port 22
ansible all -m lineinfile -a 'path=/etc/ssh/sshd_config regexp="^#Port" line="Port 22" backup=yes'
案例12: 文件追加内容 ‘#oldboy lidao996’(不加正则参数默认追加此行)
ansible all -m lineinfile -a 'path=/etc/ssh/sshd_config line="#lidao" backup=yes'
3) 服务管理-systemd☆☆☆☆☆
systemd模块相当于是linux systemctl命令:
功能:开启/关闭/重启服务 ;开机自启动;
案例11: 开启crond服务并设置开机自启动.
#启动服务
ansible all -m systemd -a 'name=crond enabled=yes state=started
案例12: 关闭firewalld服务并不让开机自启动.
#关闭服务
ansible all -m systemd -a 'name=firewalld enabled=no state=stopped'
案例12: 重启(重载)sshd服务
#重启ssh #也可以restarted
ansible all -m systemd -a 'name=sshd state=reloaded'
4) 软件管理
yum模块 get_url模块:wget命令
yum_repository模块:yum源配置模块,未来可以通过copy模块配置yum源.
a) yum模块☆☆☆☆☆
yum模块并不只是yum命令,包含了yum/apt命令
案例13: 安装常用的软件htop,tree,lrzsz,sshpass;更新rsync
ansible all -m yum -a 'name=htop,tree,lrzsz,sshpass
ansible all -m yum -a 'name=rsync state=present'
ansible all -m yum -a 'name=rsync state=latest'
b) get_url模块☆☆
相当于是wget命令.所有主机能访问网络才行.
推荐在管理节点下载好,使用copy仅分发即可.
案例14: 下载zabbix-agent的软包到/tmp/下面
zabbix-agent地址为:https://mirrors.aliyun.com/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.13-release1.el7.x86_64.rpm #1.下载rpm包 #2.yum安装本地的rpm包 #1. 下载rpm包 ansible all -m get_url -a 'url="https://mirrors.aliyun.com/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.13-release1.el7.x86_64.rpm" dest=/tmp/' #2. 通过yum模块安装:后续可以调用yum模块安装本地的软件,name=/app/tools/xxxxx.rpm即可. ansible all -m yum -a 'name=/tmp/zabbix-agent-6.0.13-release1.el7.x86_64.rpm state=present'
c) yum_repository模块
不推荐在命令行使用此模块,在剧本中会好写一点:未来书写好yum配置(xxx.repo)文件,copy分发过去即可
root@m01 ~]# cat /etc/yum.repos.d/epel.repo [epel] name=Extra Packages for Enterprise Linux 7 -$basearch baseurl=http://mirrors.aliyun.com/epel/7/$basearch enabled=1 gpgcheck=0
ansible backup -m yum_repository -a 'name=epel description="Extra Packages for Enterprise Linux7-$basearch"baseurl="http://mirrors.aliyun.com/epel/7/$basearch"enabled=yes gpgcheck=no'
5) 用户管理
a)user 模块☆☆☆☆☆
#替代 useradd,passwd,userdel.
案例15: 创建www-ans用户uid2000虚拟用户 ☆ ☆ ☆ ☆ ☆
ansible all -m user -a 'name=www-ans uid=2000 shell=/sbin/nologin create_home=no state=present'
案例16: 批量更新密码
#方法01 user模块
下面命令可以更新密码,密码为1.
ansible all -m user -a "name=lidao996 password={{ '1' | password_hash('sha512', 'lidao') }} state=present"
#方法02
ansible all -m shell -a 'echo 1 |passwd --stdin lidao996'
#其他方法
关于{{}}相关的解释 {{ }} 格式用于在ansible调用变量,$PATH oldboy=666 echo $oldboy {{ ‘1’ | password_hash(‘sha512’, ‘lidao’) }} 表示1是密码,经过管道,传递给了password_hash()插件, sha512加密算法,lidao是随机字符用于生成随机加密后的密码.
案例17:批量添加用户lidao并检查是否添加成功
ansible all -m user -a 'name=lidao state=present'
ansible all -a 'id lidao'
添加虚拟用户 web_www 2999
ansible web -m user -a ‘name=web_www uid=2999
shell=/sbin/nologin create_home=no state=present ‘
ansible web -a ‘id_web_www’
ansible web -a ‘grep “web_www” /etc/passwd’
b) group模块
6) cron模块
作用:用于管理系统的定时任务.
替代了crontab -e或vi /var/spool/cron/xxx用户功能.
关于crontab -e后的分时日月星期*****:在模块中哪个使用写*/n即可,不用的不写
案例18: 每分钟输出oldboy写入到/tmp/oldboy.txt
#创建定时任务
ansible all -m cron -a 'name="2.echo oldboy" job="echo oldboy &>>/tmp/oldboy.txt" state=present '
#删除定时任务
ansible all -m cron -a 'name="2.echo oldboy" state=absent '
7) mount模块
实现mount命令进行挂载;还可以修改/etc/fstab实现永久挂载.
案例17: 挂载nfs01已有的共享目录到web01上的/mnt下.
ansible web -m mount -a 'fstype=nfs src=172.16.1.31:/data/ path=/mnt/ state=mounted'
案例18:通过ans管理在web01上挂载nfs:/data挂载到web01的/ans-upload/
nfs服务端:172.16.1.31 /ans-data/
web01:客户端 /ans-upload/
梳理清楚服务的使用流程.
#自动化第1个里程碑-梳理服务的使用流程.服务端与客户端.
#服务端172.16.1.31
- 安装nfs
- 配置nfs
- 创建共享目录并修改所有者 /ans-data/
- 启动(重启)
#客户端172.16.1.7
- web 安装nfs
- web 创建挂载点 /ans-upload/
- web 挂载并永久挂载
把流程转换为对应的模块.
1. 安装nfsansible nfs -m yum -a 'name="nfs-utils,rpcbind" state=present'
2. 配置nfs/etc/exports
配置文件内容: /ans-data/ 172.16.1.0/24(rw)ansible nfs -m lineinfile -a 'path=/etc/exports line="/ans-data/ 172.16.1.0/24(rw)" '
#修改配置也可以用sed,cat,echo,copy.
3. 创建共享目录并修改所有者 /ans-data/ansible nfs -m file -a 'path=/ans-data/ owner=nfsnobody group=nfsnobody state=directory'
4. 启动(重启)ansible nfs -m systemd -a 'name=rpcbind enabled=yes state=restarted'
ansible nfs -m systemd -a 'name=nfs enabled=yes state=restarted'
#客户端172.16.1.7
1. web 安装nfsansible web -m yum -a 'name="nfs-utils,rpcbind" state=present'
2. web 创建挂载点 /ans-upload/ansible web -m file -a 'path=/ans-upload/ state=directory'
3. web 挂载并永久挂载ansible web -m mount -a 'src="172.16.1.31/ans-data/" path="/ans-upload/" fstype=nfs state=mounted '
6)ansible模块小结
2.1 目标
最终:根据服务使用流程,书写出对应的剧本.
书写常见服务剧本:rsync,nfs,lsyncd,修改定时任务,修改sshd_config.
书写剧本的时候使用几种常见的ansible变量.
2.2 剧本
剧本: 批量管理使用
playbook 文件,用于长久保存并且实现批量管理,维护,部署的文件. 类似于脚本存放命令和变量,剧本中存放的时候?模块
剧本yaml格式,yaml格式的文件: 空格,冒号.
剧本书写格式:
剧本核心概念:
角色 play 通过hosts部分指定的 (指定你要管理的主机(主机清单里面的)
任务 tasks 具体要执行的模块(根据你的步骤转换)
模块(根据你的操作流程,步骤选择模块)
#1. 书写剧本 注意以.yml或.yaml结尾
cat 01.show.yml
- hosts: all
tasks:
- name: 01 打开冰箱门
shell: echo 01 >> /tmp/bingxiang.log
- name: 02 把大象放入冰箱
shell: echo 02 >> /tmp/bingxiang.log
- name: 03 关上冰箱的门
shell: echo 03 >>/tmp/bingxiang.log
#2. 执行剧本
ansible-playbook -i hosts 01.show.yml
执行的时候有奶牛:🐮
可以删除软件或修改ansible.cfg配置进行关闭 #nocows = 1去掉注释即可
书写Ans playbook注意事项:☆ ☆ ☆ ☆ ☆
同一个层级的内容对齐的.
不同层级的通过2个空格对齐
不能使用tab键
Ansible剧本中模块选项书写格式:
- name: 01 创建目录
file:
path: /server/files/
state: directory
- name: 01 创建目录
file:path=/server/files/ state=directory
书写剧本流程小结:
- 把需求转换步骤
- 根据步骤选择对应的ansible模块
- 书写与调试剧本 ansible-playbook -i 主机清单文件 -C模拟运行
2.3 剧本案例
1) 案例01: 创建目录并分发文件
步骤: 02.dist_file.yml
- 创建目录/server/files/
- /etc/hosts文件发送过去/server/files/
2) 案例02: 批量添加定时任务03_xiu_cron.yml
需求: 批量添加每2分钟输出oldboy到/tmp/oldboy.txt
#说明注释信息 定时输出 ….
*/2 * * * * echo oldboy >>/tmp/oldboy.txt 2>&1
3) 案例03: 部署nfs服务并设置web服务器挂载
服务部署类剧本: 服务端与客户端
要求:
nfs服务端:在nfs上部署nfs服务,共享/nfs/ans/目录,all_squash,匿名用户:www-ans uid 2999 2999
nfs客户端:web挂载 /app/web/ans-upload/目录挂载nfs服务端共享的/nfs/ans(永久挂载)
第1个里程碑-列出流程
服务端流程: nfs
- yum安装nfs-utils,rpcbind
- lineinfile修改配置文件
/nfs/ans/ 172.16.1.0/24 (rw,all_squash,anonuid=2999,anongid=2999)
- user添加www-ans,uid 2999(先添加group,再添加user)
- file创建共享目录并改所有者
- systemd启动服务rpcbind,nfs(注意顺序)(一个一个启动)
客户端流程: web
- yum安装nfs-utils
- mount挂载与永久挂载
第2个里程碑-根据步骤流程 →模块
第3个里程碑-书写剧本
怎么能够从指定位置开始运行,一般用于调试,后面指定这一项任务的名字(适用于前面成功跑了大部分的流程,后几步出错的情况)
ansible-playbook –start-at-task “3.挂载与永久挂载” 04_nfs_srv_cli.yml
解决配置文件重复写入的问题:
- 使用lineinfile的正则匹配已经写入的行,如果没有会自动追加
- 使用copy模块将本地写好的配置文件分发到需要的机器
2.4 项目小结
理清服务作用,服务使用流程.
书写剧本核心: 列出步骤 →根据步骤找出模块
书写剧本.
书写剧本前拍摄快照,边书写剧本边测试,最后测试完成,恢复快照,重新跑一次.(分步测试,联合测试)
2.6 Ansible中的变量–思维导图
变量无处不在,在ans中大部分地方都可以定义变量.
比较常用的创建变量的地方:剧本中,类似于 “功能,共用的变量文件.
1) 剧本中使用变量⭐⭐⭐⭐⭐
ansible 变量命名规则:
- 与shell类似,不能以数字开头.
- 变量中仅包含_下划线即可.不要包含其他特殊符号(如-减号).
批量创建/server/ans-test/test.txt
vars : variables 变量的内容,变量. [root@m01 /server/scripts/ansible]# cat 05_play_vars.yml --- - hosts: all vars: dir: /server/ans-test/ file: test.txt tasks: - name: mkdir file: path: "{{ dir }}" #类似于dir,当变量作为开头就要加上单/双引号"" state: directory - name: touch file: path: "{{ dir }}{{ file }}" state: touch
Ansible选项:
ansible-playbook -i 指定主机清单
-C 模拟运行剧本并不会真的运行. 如果要真的运行剧本去掉-C
⚠ 温馨提示:
使用变量的时候如果变量是某个选项的开头,则变量引用的时候需要加上双引号.
dir: /oldboy/lidao/upload/ file: path: "{{ dir }}" #这种要添加,变量是开头. file: path: /oldboy-new/{{ dir }} #这种可以不加引号,变量不是开头.
在剧本play中定义变量应用:
- 仅仅在当前play生效.
- 一般用来存放路径,用户名,ip地址,类似于之前使用的脚本.
- 注意引号使用.
小结:
优势:使用简单,在剧本开头(play和tasks之间)创建即可.
缺点:只能在当前的play中生效,其他play中要使用变量,需要重新定义.
使用建议: 简单剧本,只有1个play可以使用.(一个hosts部分)
2) 共用变量–变量文件
通过vars_files指定变量文件.
[root@m01 /server/scripts/ansible]# cat vars.yml #所有服务器使用 dir: /server/ans-test/ file: test02.txt
[root@m01 /server/playbooks]# cat 06_play_vars_files.yml --- - hosts: all vars_files: ./vars_files.yml tasks: - name: 01.mkdir file: path: '{{ dir }}' state: directory - name: 02.touch file: path: '{{ dir }}/{{ file }}' state: touch
小结:
优点:相对于vars方法,通过vars_files指定共享变量文件.
缺点:每次使用还需要在Play中指定vars_files
使用建议,能够理解变量文件作用即可,一般使用下面的方法.
3) 共用变量–根据主机组使用变量 ⭐⭐⭐⭐⭐
这种方案的本质还是变量文件,与上方区别就在多了一个组的功能
group_vars根据主机清单里的分组去匹配不同的变量文件.
主机组创建变量文件.group_vars
避免冲突使用group方法就不使用上述两种变量创建方式,防止冲突
xxxx-check.yml group_vars/ lb/vars.yml #存放lb组的变量 web/vars.yml #存放web组的变量 data/vars.yml #存放xxx组的变量 all/vars.yml #所有主机共用的变量 未来一般使用all分组即可,把所有变量存放在一起,供剧本使用.
目录结构:
[root@m01 /server/scripts/ansible]# cat 07_group_vars_test.yml --- - hosts: all tasks: - name: 1. 创建目录 file: path: "{{ dir }}" state: directory - name: 2. 添加用户 user: name: "{{ user }}" comment: www用户 create_home: no shell: /sbin/nologin state: present
⚠温馨提示: group_vars应用提示
一般使用group_vars中的all分组即可
4) 变量定义小结(通用变量使用方法)
5) facts变量(与下面的一样都有独特的使用场景)
ans内置变量,ans运行剧本的时候会有一个默认的task(Gathering Facts :ansible收集被管理端基本信息.cpu,内存,磁盘,网络,系统.等这个主机的各种基本信息)这些基本信息就称为facts变量.facts变量setup模块获取
我们在剧本中使用facts变量,未来如果不用可以关闭gather facts功能,加速剧本运行效果.
ansible all -m setup #使用setup模块查看facts变量
json形式,开发比较喜欢 "ansible_eth0": { "active": true, "device": "eth0", "hw_timestamp_filters": [], "ipv4": { #取出这个使用 ansible_eth0.ipv4 "address": "10.0.0.41", #取出ip ansible_eth0.ipv4.address "broadcast": "10.0.0.255", "netmask": "255.255.255.0", "network": "10.0.0.0" }, 常用fact变量 ansible_hostname #主机名 ansible_memtotal_mb #内存大小(总计) 单位mb ansible_processor_vcpus #cpu核心数量 ansible_default_ipv4.address #默认的网卡ip eth0 ansible_distribution #系统发行版本名字 CentOS Ubuntu Debian ansible_distribution_version #系统的版本 ansible_date_time.date
案例 输出常用基本信息到屏幕,系统基本信息写入到/etc/motd中.:使用debug模块调试输出(类似echo)
- hosts: all tasks: - name: 调试变量 debug: msg: | 主机名:{{ ansible_hostname }} 内存大小:{{ ansible_memtotal_mb }} cpu核数:{{ ansible_processor_vcpus }} - name: 保存到文件中 lineinfile: path: /etc/motd create: yes #如果没有这个👆文件自动创建 line: | 主机名:{{ ansible_hostname }} 内存大小:{{ ansible_memtotal_mb }} cpu核数:{{ ansible_processor_vcpus }} 系统: {{ ansible_distribution }} 系统版本:{{ ansible_distribution_version }}
说明:
debug模块用于在剧本中输出与调试,一般用于输出变量内容.
|表示下面的内容是多行,用于输出或写入多行到文件中,注意索引对齐.
案例:批量修改系统/etc/motd文件,登录的时候输出系统的基本信息.
输出主机名 输出内存总大小 输出ip地址 发行版本 cpu数 核心数
#1. 创建包含变量的模板文件
#2. 发送模板文件替代/etc/motd 即可
template模块支持分发文件的时候,替换文件中的ansible变量.
要求:源文件以.j2结尾
[root@m01 /server/scripts/playbook]# cat 07.change_motd.yml - hosts: all tasks: - name: 2. 写入到/etc/motd文件 template: src: /server/files/conf/motd.j2 dest: /etc/motd backup: true [root@m01 /server/scripts/playbook]# cat templates/motd.j2 ####################################### 操作需谨慎,删根弹指间. 主机名: {{ ansible_hostname }} ip地址: {{ ansible_default_ipv4.address }} 内存大小: {{ ansible_memtotal_mb }} CPU数量: {{ ansible_processor_vcpus }} 核心总数: {{ ansible_processor_cores }} 发行版本: {{ ansible_distribution }}
关于facts变量实际应用案例:
- 通过facts变量获取系统的基本信息
- 通过facts变量获取信息并进行判断
- 如果不需要可以临时进行关闭,加速剧本的运行(在剧本hosts下面写 gather_facts: false)
- 修改ansible.cfg #gathering = implicit去掉注释,永久关闭,如果剧本中需要,在剧本中写gather_facts: true
- hosts: all gather_facts: false tasks: .......
yes or no 还是True or false
在使用上是一致的,表示的是真(开启,启动),假(关闭).
布尔类型的数据:真,假.
真:yes,True,true
假:no,False,false
根据每个模块选项的说明去使用即可.
6) register变量注册变量 ⭐⭐(手动创建)
本质上就是用来实现脚本中的反引号功能. ip=`hostname -I`
用户通过命令获取的内容都存放到Register变量中.
应用场景:获取命令执行结果或获取模块执行的结果.
案例:将命令执行的结果存放到json结果中,方便取用 [root@m01 /server/scripts/ansible]# cat 10.register_vars.yml - hosts: all gather_facts: false tasks: - name: 1. 获取ip shell: hostname -I | awk '{print $2}' register: ipaddr - name: 2. 调试输出 debug: msg: "{{ ipaddr }}" - name: 3. 显示变量(最终想要的值) debug: msg: | "{{ ipaddr.stdout }}" "{{ ipaddr.rc }}" - name: 4. 将变量中的值写入文件 文件内容: 172.16.1.31 0 lineinfile: path: /server/ans-test/test.txt line: | {{ ipaddr.stdout }} {{ ipaddr.rc }}
得到了IP地址的变量:{{ ipaddr.stdout }} ,等同于facts变量中的ansible_default_ipv4.address
register注册变量:
变量.stdout 获取输出即可.
json形式数据.
key: value
键: 值
变量: 内容
hostname -I | awk '{print $2}'
得到的stdout部分是我们想要的内容.
register变量ipaddr.
ipaddr.stdout
#std standard output 标准输出.
#stderr #std standard error标准错误输出
.rc #return code
返回值 (相当于 $?)
如果结合其他模块使用我们关注结果中的failed部分
7) 总结
流程控制:
1)Ansible中的循环
应用场景:批量开启服务,重启服务,创建文件,目录,添加用户.
1) 最常用的1种循环形式-1个变量
创建3个文件. /tmp/oldboy /mnt/lidao /root/lidao996 [root@m01 /server/scripts/ansible]# cat 11.ans_with_items.yml --- - hosts: all tasks: - name: 1. 循环创建文件 file: name: "{{ item }}" state: touch with_items: #循环取值范围 #loop效果等同于with_items,未来复杂的循环使用with_items效果更多 - /tmp/oldboy - /mnt/lidao - /root/lidao996
小结:
类似于shell中的for循环.
with_items或loop,变量名字item.
启动/重启服务,添加用户,文件,目录….
2) 每次循环创建多个变量
案例:循环添加指定uid的多个用户
[root@m01 /server/scripts/ansible]# cat 12_ans_loop_mutli_vars.yml --- - hosts: all tasks: - name: 1. 循环添加指定uid的多个用户 user: name: "{{ item.name }}" uid: "{{ item.uid }}" state: present loop: #循环取值范围 #loop效果等同于with_items - { name: "lidao01",uid: 4090 } - { name: "oldboy01",uid: 5090 } - { name: "test01",uid: 6090 }
3) 小结
with_items/loop循环
单个变量,item.
多个变量,
创建 {user: “lidao666” ,uid: 4090}
使用 item.user item.uid
2.7 循环案例(nfs)
⭐ ⭐ ⭐ ⭐ ⭐ copy和template模块区别
copy传输文件,文件中包含变量不会解析.
template模块支持分发文件的时候,替换文件中的ansible变量.
要求:源文件以.j2结尾
template传输文件,文件中的变量会解析.
--- - hosts: all gather_facts: no tasks: - name: 01. mkdir dir file: path: /server/files/ state: directory - name: 02. copy file copy: src: /etc/hosts dest: /server/files
1) nfs 13.nfs_srv_cli_v2.yml
2) rsync 14_rsync_client_v1.yml
3) lsyncd (10.0.0.0.31NFS01已部署)
编译安装流程使用shell脚本.或者分发命令(lsyncd)—–直接将编译好的/usr/local/bin/lsyncd传到客户端中的/usr/bin/lsyncd, which lsyncd能找到即可使用
rsync服务可用.
后续操作,分发配置文件/etc/lsyncd.conf
分发systemd文件.
# /usr/lib/systemd/system/lsyncd.service [Unit] Description=Live Syncing (Mirror) Daemon [Service] Type=simple ExecStart=/usr/local/bin/lsyncd -nodaemon /etc/lsyncd.conf ExecStop=pkill lsyncd Restart=always RestartSec=5s [Install] WantedBy=multi-user.target
启动服务.
2) handlers触发器 ⭐⭐⭐⭐⭐
需求:分发nfs服务配置文件,然后重启nfs.
实现步骤:
copy/template分发
systemd: restarted/reloaded
发现的问题:
按照之前所写的剧本,目前只能完成分发配置和重启服务,并且两个步骤之间没有关联.
我们希望只有配置发生了变化然后再去重启服务.
实现方案: 触发器:组成: handler与notify
应用场景: 一般用于分发配置文件的时候与重启服务;如果配置文件发生变化则重启服务,如果没有变化则重启
触发器案例:在上面的14号剧本部署rsyncd时中有写
handlers使用方法:将notify跟触发触发器操作的模块名字对齐;handlers与tasks同一层级,写在hosts中 所有tasks的最后
配置文件未改变则不触发”重启服务” 任务;配置文件发生变化,触发”重启服务”任务
- hosts: backup gather_facts: no tasks: - name: 分发配置文件 copy: src: files/exports dest: /etc/exports backup: yes notify: #布雷 - 重启服务 handler: #设置踩雷后操作. - name: 重启服务 systemd: name: nfs state: reloaded
触发器小结:
handlers触发器,应用场景: 配置文件发生变化,然后重启服务(或做其他) .
格式: 埋雷:设置绊雷(notify: 写个名字) , handlers设置名字和模块.
注意事项: handlers放在剧本tasks的最后,否则handlers后面的模块都会被识别为handlers操作,不触发不会运行
3) when判断(与模块名字对齐)
when判断应用场景:用于给ans运行的task(模块)设置条件,满足或不满足条件在运行对应的模块.
应用建议: when进行判断,一般与facts变量或register变量一起使用.
根据系统变量判断在哪些机器运行哪些针对性的操作,如:相同的软件在不同的系统软件包名不一致,或者centos系统使用yum模块安装;ubuntu系统使用apt模块安装
when条件还可以和ansible语句一起使用(判断文件,判断目录,判断是否存在,比较大小).
when: 给模块加上个条件.
案例02 : 如果系统是centos或kylin则 安装sl,cowsay,如果是ubuntu 则安装cmatrix
- hosts: all
tasks:
- name: centos 系统安装sl cowsay
yum:
name: sl,cowsay
state: present
when: ansible_distribution ismatch('CentOS|Kylin')
- name: ubuntu 系统安装cmatrix
apt:
name: cmatrix
state: present
when: ansible_distribution is match('Ubuntu')
温馨提示: ubuntu默认禁用了root远程登录需要修改sshd配置文件开启,
并记得配置Root密码. 操作流程与centos一致.
PermitRootLogin yes
"ansible_facts": {
"ansible_distribution": "Kylin Linux Advanced Server",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/os-release",
"ansible_distribution_file_variety": "NA",
"ansible_distribution_major_version": "V10",
"ansible_distribution_release": "Lance",
"ansible_distribution_version": "V10",
"discovered_interpreter_python": "/usr/bin/python3.7"
},
[root@nfs01 ~]# cat /etc/os-release
NAME="Kylin Linux Advanced Server"
VERSION="V10 (Lance)"
ID="kylin"
VERSION_ID="V10"
PRETTY_NAME="Kylin Linux Advanced Server V10 (Lance)"
ANSI_COLOR="0;31"
is match匹配的字段是/etc/os-release里面的NAME,所以这里匹配不能用==,==只能精准匹配字符串
如果这里想查看facts变量可以使用setup模块,查看全部:ansible all -m setup;
如果想只过滤上面使用的存放系统信息的变量可以在模块后面加上'filter=ansible_distribution*'
关闭ansible运行剧本的紫色提示
1)被管理的 麒麟系统 每次提示: 系统中有多个版本,默认使用/usr/bin/python的提示:
在group_vars/all/vars.yml中指定管理机默认使用的python版本即可ansible_python_interpreter: /usr/bin/python3
2)管理机运行剧本后在剧本开头显示的当前系统python版本过低问题
sed -i 's@#deprecation_warnings = True@deprecation_warnings = False@g' /etc/ansible/ansible.cfg
小结:
when用于进行判断,满足/不满足条件就执行对应的模块(不满足条件的主机提示skip).
when一般与变量一起使用.
符号 == != is match is not match
(条件1) and (条件2)
(条件1) or (条件2)
常用的facts变量:见上方facts变量 ansible自动化 – linux极客聚集地
4) 流程控制小结(判断/触发器/循环)
剧本调试(各种debug)
debug流程.
目标:通过注释,等等方法定位问题. 常用的几种debug方式:
1) 检查语法与单步执行 运行脚本时使用 -C
-C --check
模拟运行,不作出改变,一些变量可能会提示报错,因为-C没有真正运行剧本. 所以register变量无法使用,因为不运行获取不到注册的变量中的值
--syntax-check
只做语法检查,不运行.
高级: -- step
单步运行.运行脚本时的每一步都会询问是否运行,
y执行这个task,n忽略这个task,c–continue自动运行:下一步就不询问是否运行,一直运行到剧本结束
2) 从指定任务开始运行 ⭐⭐⭐⭐⭐
--start-at-task
从指定任务运行一直运行到剧本结束.:运行当前指定步骤和后面的所有步骤
一般先用–list-tasks查看剧本中tasks中所有的-name(模块执行的任务的名字)
然后–start-at-task “任务名字” 从指定任务开始运行.
(1)ansible-playbook --list-tasks 16.nfs_server_client_v2_handlers.yml
(2)ansible-playbook --start-at-task "3.创建挂载点" 16.nfs_server_clit_v2_handlers.yml
3) tag标签(和模块名字对齐)⭐⭐
tag标签类似于超市物品的分类,只不过tag标签是给ansible中的task进行分类,加上标记; 运行剧本的时候运行指定的tag标签或排除某些tag.
运行剧本的时候使用--list-tasks
查看任务名字和标签名
-t 运行的标签,如果多个标签通过”,”分割
–skip-tags 排除指定的tags,如果多个标签通过”,”分割
使用时的命令:以下的格式都是可以的
ansible-playbook –tags 标签名 剧本名
ansible-playbook –tags=标签名 剧本名
ansible-playbook -t=标签名 剧本名
ansible-playbook -t 标签名 剧本名
在同一剧本中,tags是可以重复的,因为可以给不同的模块打上同ige标签,tags还可以给每一步模块的操作写成多种标签的形式,如:
tags: "01" 或者 tags: - server_02_conf - nfs_server
vim批量添加tags的细节,将光标选中数字,按ctrl+a是数字加1,ctrl+x是数字减一,如果光标处是两位数数字,光标不管放在哪一位上面都会给整个数字加1:如,光标放在14上中的4上按了ctrl+a,数字会变成15
4) 忽略错误(和模块名字对齐)
运行剧本的时候,因为重复运行导致的错误提示,并不是真的错误.
比如:目录已经存在,用户已经存在.;
在这种情况下,我们可以通过ignore_errors
忽略错误,让剧本可以继续运行
ignore_errors: true true/false yes/no bool布尔类型的数据.
---
- hosts: all
tasks:
- name: 01
shell: echo 01 >>/tmp/test.log
- name: 02
shell: echo 02 >>/tmp/test.log
- name: 03
shell: cho 03 >>/tmp/test.log
ignore_errors: true
5) 剧本调试小结
ansible剧本书写建议:
使用变量,给每个任务加上tag标签.
常见: 一般有密钥认证问题.
常见问题:剧本本身
检查语法-C –syntax-check
tags标签
–start-at-task
单行执行: –step
忽略错误
2.3 Jinja2模板
template模块与xxx.j2文件
应用场景:
- 进行分发配置文件或文件的时候,需要在文件中使用变量,需要使用jinja2文件 nginx.conf.j2,需要使用template模块进行分发. (目前必须要会的)
- 进行判断
- 进行循环
1) 基本使用 ⭐⭐⭐⭐⭐
案例:见上方的facts变量中使用j2模板进行调用facts变量的例子:ansible自动化 – linux极客聚集地
2) j2判断(写在j2中)
应用场景:未来某一个服务,主备,在主备2个节点上,配置文件几乎是一模一样的.(主:master, 备:backup)
根据主机名或ip或其他条件,生成不同的配置文件.
目前有个配置文件叫keepalived.conf,文件中的内容根据lb01或lb02有所区别.
如果是lb01则配置文件内容是
keepalived-master.conf state MASTER
如果是lb02则配置文件内容是
keepalived-backup.conf state BACKUP
cat 15.jinja2-if.yml - hosts: all tasks: - name: 分发配置文件 template: src: templates/keepalived.conf.j2 dest: /tmp/keepalived.conf 将所有的j2文件放在templates目录中 [root@m01 /server/scripts/playbook]# tree templates/ templates/ ├── keepalived.conf.j2 └── motd.j2 [root@m01 /server/scripts/playbook]# cat templates/keepalived.conf.j2 #this is keepalived.conf {% if ansible_hostname == "lb01" %} state 主节点 {% elif ansible_hostname == "lb02" %} state 备节点 {% endif %}
3) j2循环(写在j2中)
将多个ip写入到web服务器的/tmp/目录下的配置文件 server.conf 中:
templates/server.conf.j2
{% for ip in [1,2,3,4,5,6] %} 10.0.0.{{ ip }} {% endfor %} #range(2,11) 生成数字序列 2表示从2开始,到10结束 #顾头不顾腚 {% for ip in range(2,11) %} 10.0.0.{{ ip }} {%endfor%} {% for ip in ["lidao","oldwang"] %} 10.0.0.{{ ip }} {%endfor%}
剧本文件:16_j2_for.yml
---
- hosts: web
tasks:
- name: use template create server.conf
template:
src: templates/server.conf.j2
dest: /tmp/server.conf
出现了上面的空行问题可以在循环的%前面加一个-,即可解决
{% for ip in [1,2,3,4,5,6] -%}
4) 小结
核心: 使用.j2结尾+template分发带有变量的文件即可.
还有精力的可以研究jinja2的判断与循环.
Ansible-进阶
3.1 Vault 保险箱
给机密文件加密.——剧本,主机清单,变量文件,文件.
#1.进行加密
ansible-vault encrypt 文件 #enable
#2.加密后进行编辑:
ansible-vault edit 文件---默认使用vim编辑器打开文件,编辑完依旧保持加密状态
#进行使用
ansible或ansible-playbook --ask-vault-pass
即可
--ask-vault-pass
交互
--vault-password-file
密码文件
#彻底解密,可以cat查看
ansible-vault decrypt hosts#
3.1 Roles ⭐⭐⭐⭐⭐
1) roles详解:
Roles本质让我们书写剧本的时候有个目录规范:
将我们完整的剧本拆分若干部分,有的专门存放tasks部分(剧本),存放变量,存放普通文件,存储变量文件,handlers内容.
作用:增加剧本可读性,规范性. 因为随着我们书写的剧本越来越复杂,我们发现,剧本使用到的文件,配置文件,j2文件 都放在与剧本同一层目录下,不方便后期维护.
剧本使用到的变量文件(group_vars/all/vars.yml),普通文件(copy),模板配置文件(template),handlers(触发器.)
存放的规则:针对不同的主机(hosts)书写的不同tasks属于roles中的同级目录,一个role里面包含多个模块(tasks中的所有内容)
2) 创建roles环境
cd /server/ans/
#新建一个roles目录,将之前的模板文件等放到roles下使用到的对应role的子文件夹中
mkdir -p roles/{nfs-server,nfs-client}/{files,tasks,templates,handlers}
mkdir -p roles/group_vars/all/
3) 准备nfs-server和nfs-client的roles(填充文件/拆分剧本)
将整个部署nfs服务器的剧本拆开分为服务端和客户端:
- 创建文件/目录
- 往目录中放该放的文件,主机清单放在roles/inventory,模板文件放置在template目录,变量文件放在group_vars/all/vars.yml中根据主机清单里的分组去匹配不同的变量文件.或者用/vars/vars.yml的格式给所有机器共享变量文件
- tasks部分写入role中的main.yml,handlers部分写入handlets/main.yml,
- 最后在roles下写控制roles中各个role的剧本
[root@m01 /server/ans/roles]# cat top.yml
---
- hosts: nfs
gather_facts: false
roles:
- role: nfs-server
- hosts: web
gather_facts: false
roles:
- role: nfs-client
4) roles小结
书写剧本的时候通过roles方式实现,使剧本更加规范,文件好管理
3.2 include文件包含
问题:在我们书写剧本的时候,会涉及到多个步骤,还会涉及到服务端和客户端.发现剧本越来越大,不容易进行分析与阅读.
解决方案:把剧本拆分开,分成2个文件服务端,客户端.
这时候可以通过include_tasks的功能把多个剧本文件合并在一起,让剧本变成多个方便阅读与维护
include的作用类似shell脚本中的函数,可以引用不同roles下的tasks中的内容防止剧本过大
在tasks目录中使用:
比如一个roles中的tasks有多个剧本,原本的方案是都写在main.yml中,使用include可以简化main.yml,将原本的main拆开按照不同的功能分为多个同级目录的其他tasks并使用include引用这些tasks
在调用roles时中使用:(nfs-server角色中所有的yml中都不用写单词:hosts/tasks/handlers)
只有在roles外的剧本,调用roles时写需要写/hosts/tasks/roles/
如何在1个剧本中使用include
- hosts: backup
tasks:
- include_tasks: install.yml
- include_tasks: config.yml
- include_tasks: start.yml
include功能小结
防止我们剧本过大,对剧本进行拆分
3.4 Galaxy
可以在官网下载别人的roles使用👆
里面有很多集合,遵循某种格式,这里面的galaxy会相对复杂,因为roles的创作者考虑到适配大部分系统会增加一些判断(有个人写的也有红帽写的)
网站界面可以下载roles的压缩包,解压后看到很多roles,tasks,看里面的main.yml
或者命令行下载使用ansible-galaxy collection install nginxinc.nginx_core
3.5 优化
1) ansible安全优化-sudo ⭐⭐⭐⭐⭐
a) 整体流程
禁用被管理机的root远程登录,ansible如何实现?
ansible在被管理机中使用普通用户(具有sudo权限)
b) 详细步骤:
目前操作:先使用ans脚本进行普通用户ans的创建
添加用户设置密码
配置sudo权限
修改sshd_config配置文件
重启sshd
[root@m01 /server/ans/playbooks]# cat14.useradd_sudo.yml
- hosts: all
vars:
username: ans
password: "1"
gather_facts: false
tasks:
- name: 01.添加用户设置密码
user:
name: "{{ username }}"
shell: /bin/bash
password: "{{ password |password_hash('sha512', 'lidao') }}"
state: present
- name: 02.配置sudo权限
lineinfile:
path: /etc/sudoers
line: "{{ username }} ALL=(ALL) NOPASSWD:ALL"
state: present
- name: 03.修改sshd_config配置文件
replace:
path: /etc/ssh/sshd_config
#目标 #PermitRootLogin yes
#目标 PermitRootLogin yes
#regexp: "^(#PermitRootLogin yes)|(PermitRootLogin yes)"
regexp: "^PermitRootLogin yes"
replace: "PermitRootLogin no"
notify:
- 04.重启sshd
handlers:
- name: 04.重启sshd
systemd:
name: sshd
state: reloaded
password:这里默认认为是加密后的密码,如果直接写明文不行
这里如果使用sha512 时加上后面的随机字符,会提高安全性:如果重新运行加密命令,每次生成的密码都不一样,降低了暴力破解的可能性
replace模块:替换 类似sed的s###g替换功能,将整行替换为***
c)详细步骤:分发密钥
创建完用户之后用shell一键分发密钥的脚本,稍作修改:将收密钥的用户从默认的$ip—root变为ans@$ip用户,密码换为ans用户的密码,实现密钥连接普通用户
d) 详细步骤: 修改ansible配置文件
[root@m01 /server/scripts/playbook]# egrep -v '^$|#'
/etc/ansible/ansible.cfg
[defaults]
sudo_user = ans #被管理端上具有sudo权限的用户
nopasswd: ALL
remote_user = ans #被管理端使用的用户,不指定默认是当前用户/root
remote_port = 22 #被管理端ssh端口号
host_key_checking = False
log_path = /var/log/ansible.log
[inventory]
[privilege_escalation]
become=True # 提权
become_method=sudo #提权方式:使用sudo命令
become_user=root #普通用户切换至root
e) 调试
ansible all -i hosts -m ping
2) 其他优化
性能
ssh连接速度优化,关闭UseDNS,GSSAPIAuthcation ….
不要让ansible运行交互式的命令,非要用使用命令的非交互模式.
需要使用ans,yum安装软件,可以自建本地yum仓库,然后ans安装.(自建yum源,自己制作的rpm包)
调整ansible并发数量( -f 调整并发数量 默认是5 ansible.cfg forks=5,实际调整根据负载情况.)
给ansible配置缓存(redis),队列.缓存facts.
给主机进行分组操作与管理.
关闭gather_facts,如果不用facts变量可以关闭, 剧本中:
gather_facts: false 配置文件中: gathering = explicit
host_key_checking = False一般使用密码认证的时候需要关闭
安全⭐
⭐ 配置sudo用户 ans ALL=(ALL) NOPASSWD: ALL 密码是1,ssh端口是 22
配合vpn,jms一起使用
用户— >vpn—->jms(跳板机)—->ansible
用户的密码,进行加密( hash, ansible-vault)
配置sudo
所有被管理节点上添加ans用户 ,设置密码.
所有备管理节点上配置ans sudo权限 ans ALL=(ALL) NOPASSWD: ALL
管理端与被管理端密钥认证:分发密钥发到ans用户.
管理端: ansible.cfg配置,通过ans用户连接,远程连接端口号,使用sudo.