ansible自动化

暂时无法播放,可回源网站播放

目录

 市面上常见的批量管理方案:

简单对比 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 主机清单)

主机清单获取:

  1. 根据已有的清单获取(表格 …其他系统)
  2. 公有云导出
  3. 书写脚本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点对点模式(命令行)批量管理流程:

  1. 配置好密钥认证 ✅
  2. 书写yaml剧本/使用命令

主机清单

文档(inventory) /etc/ansible/hosts ✅

  1. 开始使用ansible管理

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官网user模块帮助

关于{{}}相关的解释 {{ }} 格式用于在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

  1.  安装nfs
  2.  配置nfs
  3.  创建共享目录并修改所有者 /ans-data/
  4.  启动(重启)

#客户端172.16.1.7

  1.  web 安装nfs
  2.  web 创建挂载点 /ans-upload/
  3.  web 挂载并永久挂载

把流程转换为对应的模块.

1. 安装nfs
ansible 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 安装nfs
ansible 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

书写剧本流程小结:

  1. 把需求转换步骤
  2. 根据步骤选择对应的ansible模块
  3. 书写与调试剧本 ansible-playbook -i 主机清单文件 -C模拟运行

2.3 剧本案例

1) 案例01: 创建目录并分发文件

步骤:   02.dist_file.yml

  1.  创建目录/server/files/
  2.  /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

  1. yum安装nfs-utils,rpcbind
  2. lineinfile修改配置文件 /nfs/ans/ 172.16.1.0/24 (rw,all_squash,anonuid=2999,anongid=2999)
  3. user添加www-ans,uid 2999(先添加group,再添加user)
  4. file创建共享目录并改所有者
  5. systemd启动服务rpcbind,nfs(注意顺序)(一个一个启动)

客户端流程: web

  1. yum安装nfs-utils
  2. mount挂载与永久挂载

第2个里程碑-根据步骤流程 →模块

第3个里程碑-书写剧本

怎么能够从指定位置开始运行,一般用于调试,后面指定这一项任务的名字(适用于前面成功跑了大部分的流程,后几步出错的情况)

ansible-playbook –start-at-task  “3.挂载与永久挂载” 04_nfs_srv_cli.yml

解决配置文件重复写入的问题:

  1. 使用lineinfile的正则匹配已经写入的行,如果没有会自动追加
  2. 使用copy模块将本地写好的配置文件分发到需要的机器

2.4 项目小结

理清服务作用,服务使用流程.

书写剧本核心: 列出步骤 →根据步骤找出模块

书写剧本.

书写剧本前拍摄快照,边书写剧本边测试,最后测试完成,恢复快照,重新跑一次.(分步测试,联合测试)

2.6 Ansible中的变量–思维导图

变量无处不在,在ans中大部分地方都可以定义变量.

比较常用的创建变量的地方:剧本中,类似于 “功能,共用的变量文件.

1) 剧本中使用变量⭐⭐⭐⭐⭐

ansible 变量命名规则:

  1. 与shell类似,不能以数字开头.
  2. 变量中仅包含_下划线即可.不要包含其他特殊符号(如-减号).

批量创建/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中定义变量应用:

  1. 仅仅在当前play生效.
  2. 一般用来存放路径,用户名,ip地址,类似于之前使用的脚本.
  3. 注意引号使用.
小结:

优势:使用简单,在剧本开头(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变量实际应用案例:
  1. 通过facts变量获取系统的基本信息
  2. 通过facts变量获取信息并进行判断
  3. 如果不需要可以临时进行关闭,加速剧本的运行(在剧本hosts下面写 gather_facts: false)
  4. 修改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文件

应用场景:

  1. 进行分发配置文件或文件的时候,需要在文件中使用变量,需要使用jinja2文件 nginx.conf.j2,需要使用template模块进行分发. (目前必须要会的)
  2.  进行判断
  3. 进行循环

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-clientroles(填充文件/拆分剧本)

将整个部署nfs服务器的剧本拆开分为服务端和客户端:

  1. 创建文件/目录
  2. 往目录中放该放的文件,主机清单放在roles/inventory,模板文件放置在template目录,变量文件放在group_vars/all/vars.yml中根据主机清单里的分组去匹配不同的变量文件.或者用/vars/vars.yml的格式给所有机器共享变量文件
  3. tasks部分写入role中的main.yml,handlers部分写入handlets/main.yml,
  4. 最后在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.

4.Ansible与自动化

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部