部署密钥认证
免密码登录、双机互信
一些服务在使用前要求做密钥认证,管理轻松。手动写批量管理脚本。
==注:密钥认证是单向==
密钥对
公钥:public key 一般以.pub结尾
私钥:private key
角色 | 主机名 | IP |
---|---|---|
管理机 | m01 | 192.168.10.50 |
被管理机 | nfs01 | 192.168.10.51 |
被管理机 | web01 | 192.168.10.52 |
被管理机 | backup | 192.168.10.53 |
常规密钥
无密钥前检测
#ping
......
#22端口 sshd服务开启或可以访问
[root@m01 ~]# nmap -p 22 nfs01 web01 buckup
Starting Nmap 6.40 ( http://nmap.org ) at 2024-03-10 21:03 EDT
Nmap scan report for nfs01 (192.168.10.51)
Host is up (0.00013s latency).
PORT STATE SERVICE
22/tcp open ssh
MAC Address: 00:0C:29:53:DD:74 (VMware)
Nmap scan report for web01 (192.168.10.52)
Host is up (0.00025s latency).
PORT STATE SERVICE
22/tcp open ssh
MAC Address: 00:0C:29:29:8F:D8 (VMware)
Nmap scan report for buckup (192.168.10.53)
Host is up (0.00022s latency).
PORT STATE SERVICE
22/tcp open ssh
MAC Address: 00:0C:29:3A:62:EB (VMware)
Nmap done: 3 IP addresses (3 hosts up) scanned in 0.42 seconds
创建密钥
[root@m01 ~]# ssh-keygen -t rsa
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
公钥和私钥
[root@m01 ~]# cd /root/.ssh/
[root@m01 .ssh]# ls
id_rsa id_rsa.pub known_hosts #都是加密的
分发公钥
[root@m01 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@buckup
测试
ssh root@192.168.10.51
公钥分发的位置
[root@nfs01 ~]# cd /root/.ssh/
[root@nfs01 .ssh]# ls #位置不变 密钥文件名改变
authorized_keys
自动创建与分发密钥
集群数量庞大,无法每个单独配置
阻碍:
1.创建密钥对
2.分发公钥的时候:yes/no(yes会保存到 .ssh/know_hosts)
3.分发公钥的时候:输入密码
sshpass作用
sshpass适用于ssh相关的命令提供密码:ssh,scp,ssh-copy-id
expect,用户实现非交互式判断,认证操作 yes/no
#在无密钥认证的时候 使用ssh不可加参数也必须交互式输密码
[root@m01 ~]# sshpass -proot ssh nfs01
-p指定密码 ssh是指定命令
注意:sshpass,ssh-copy-id第一次连接,如果提示yes/no,则sshpass失效!
创建密钥参数
[root@m01 ~]# ssh-keygen -f ~/.ssh/id_rsa -P ''
-f 参数用于指定私钥位置
-P 参数是密码短语 设置为空
#创建密钥时 就不需要回车
分发密钥
[root@m01 ~]# sshpass -proot ssh-copy-id -i ~/.ssh/id_rsa.pub buckup
#分发公钥时就不需输入密码
第一次建立连接yes/no
#非建立连接过的主机在ssh,ssh-copy时会提示yes/no
#建立连接后的主机信息会记录在/root/.ssh/know_hosts中
#在建立连接时 -oStrictHostKeyChecking=no 临时不检查主机信息(know_hosts)
[root@m01 ~]# ssh nfs01
The authenticity of host 'nfs01 (192.168.10.51)' can't be established.
ECDSA key fingerprint is SHA256:p6P+DDIogoJ7Q4OMmGs18IftWDwEWR4TEhiJ5SptmZU.
ECDSA key fingerprint is MD5:6a:c1:a5:66:a0:f6:38:11:ac:72:a7:ca:8a:fe:87:18.
Are you sure you want to continue connecting (yes/no)?
[root@m01 ~]# ssh-copy-id -oStrictHostKeyChecking=no nfs01
解决建立连接时yes/no提示
[root@m01 ~]# sshpass -proot ssh-copy-id -oStrictHostKeyChecking=no nfs01
#解决yes/no以及密码提示
脚本执行
[root@m01 ~]# cat sshkey.sh
#!/bin/bash
#auther: To9cn
#version: v1
#desc: 自动创建密钥对 自动分发公钥
passwd=root
ips="192.168.10.51 192.168.10.52 192.168.10.53"
#环境判断 是否联网、是否可以使用yum...
yum install -y sshpass
#创建密钥对
if [ -f ~/.ssh/id_rsa ]
then
echo "密钥对存在!"
sleep 1
else
echo "密钥对不存在; 开始创建密钥对..."
ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' &>/dev/null
sleep 1
echo "密钥对创建成功!"
fi
#分发公钥
for ip in $ips
do
sshpass -p${passwd} ssh-copy-id -oStrictHostKeyChecking=no $ip
echo "$ip 成功分发密钥!"
sleep 1
done
检查脚本
测试无密钥的连通性
[root@m01 ~]# cat test_ssh.sh
#!/bin/bash
#auther: To9cn
#desc: 批量执行命令
for ip in 192.168.10.51 192.168.10.52 192.168.10.53
do
ssh $ip hostname
done
[root@m01 ~]# ./test_ssh.sh
nfs01
web01
buckup
Ansible
自动化运维:批量管理、批量分发、批量执行与维护...
导图:https://www.processon.com/view/link/61addd266376896056c1b1b2
任务:
- 熟练脚本部署密钥认证
- Ansible批量管理结构
- Ansible主机清单(添加、管理集群)
- Ansible常用模块
- Ansible-批量管理-批量部署-批量分发
Ansible管理架构
Inventory :主机清单---被管理主机的IP列表,分类。
ad-hoc模式:==命令行==批量管理(使用模块),临时任务。
playbook:剧本模式---把操作写出脚本,可重复运行这个脚本
Ansible模块概述:
- ansible中的模块就类似于Linux中的命令,我们Linux命令管理系统,我们通过ansible模块实现批量管理.
- ansible中模块一般相当于Linux中的一些命令.yum模块,file模块,user模块.
- ansible中的模块拥有不同的选项,这些选项一般都是一些单词.有自己格式和要求
- Ansible模块 modules Ansible中通过各种模块实现批量管理.
- 一般来说这些模块对应着Linux里面的基本操作或服务管理。找出Linux场景操作对应的模块即可.
Ansible安装
epel源
yum -y install epel-release
yum -y install vconfig -y
yum install -y ansible
[root@m01 ~]# ansible --version
ansible 2.9.27
优化配置
修改配置文件关闭Host_key_checking(yes/no)
修改配置文件开启日志功能
[root@m01 ~]# vim /etc/ansible/ansible.cfg
71行:关闭主机检测
112行:开启日志功能
[root@m01 ~]# egrep -vn '^$|#' /etc/ansible/ansible.cfg
11:[defaults]
72:host_key_checking = False
112:log_path = /var/log/ansible.log
328:[inventory]
341:[privilege_escalation]
347:[paramiko_connection]
371:[ssh_connection]
432:[persistent_connection]
446:[accelerate]
461:[selinux]
470:[colors]
486:[diff]
ansible内置参数
参数 | 功能 |
---|---|
-i (inventory) | 指定主机组inventory |
-u (remote_user) | 指定sudo被控制的用户 (需要sudo权限) |
-b (become) | 启动特权功能 |
--become-method --become-user | 切换(sudo)方式和切换的用户 |
--ask-become-pass -K | 询问密码 |
Ans-Inventory主机清单
主机清单格式
[分类或组的名字] #服务器集群用途
IP或主机名或域名 #主机名要解析(etc/hosts)
ansible管理的主机节点的列表---默认读取/etc/ansible/hosts,一般会把清单放在指定位置。
## db-[99:101]-node.example.com
[nfs]
192.168.10.51
[web]
192.168.10.52
[buckup]
192.168.10.53
没有公钥的主机清单配置(不推荐)
[nfs]
192.168.10.51 ansible_user=root ansible_password=123 ansible_port=22
测试
[root@m01 ~]# ansible all -m ping
#-m指定模块
#all可以替换为nfs,web等分组内容,也可写IP单必须在主机组
192.168.10.53 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
#获取被管理节点 系统信息
[root@m01 ~]# ansible all -a "cat /etc/os-release"
192.168.10.51 | CHANGED | rc=0 >>
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
针对单台指定机器 ==ansible_host==
ansible_host: 192.168.10.50
不包含在其他任何主机组的机器
- hosts: ungrouped
'*'的作用
- hosts: all == - hosts: '*'
#匹配以 .example结尾的主机
- hosts: '*.example' # 有特殊符号必须放在引号内部
#匹配以 192.168.2 为网段的主机
- hosts: '192.168.2.*' #也表示以xxx开头
==防止被shell意外扩展==
---
- hosts: '!test1.example.com,development'
管理多个主机
- hosts: name1,name2,name3 #可混合‘*’等表达使用 : 组,IP,‘*’表达
条件判断表达(针对主机必须满足多个条件的过滤)
- hosts: lab,&nfs # 匹配同时属于这两个组的主机
# !加主机则排除本组的此主机
- hosts: nfs,!192.168.10.52 # 匹配除本主机的nfs组其他机器
# 也可针对组管理
- hosts: all,!nfs #匹配除nfs组的其他所有组
条件表达的位置前后可变换
检查主机是否在清单中
ansible nfs.example.com -i /etc/ansible/hosts --list-hosts
#列出
ansible all -i /etc/ansible/hosts --list-hosts
支持判断
ansible '*.example.com' -i /etc/ansible/hosts --list-hosts
多个判断
ansible '*.example.com','!nfs.example.com' -i /etc/ansible/hosts --list-hosts
'172.10*'
'backup,172*,*example*' 含有example,172开头,backup组(此时无&符号,表示或)
'web,&nfs' 同属两组
以Json格式列出清单主机
ansible-inventory -i /etc/ansible/hosts --list
子组
期望对backup,nfs两组,再创建新分组data:[data:children]
#创建新分组,包含已有的分组backup,nfs
[data:children]
nfs
backup
[root@m01 ~]# ansible data -m ping
192.168.10.51 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Ansible模块
模块的本质是替换Linux命令。模块有不同选项(单词),有自己的格式
查看ansible全部模块
ansible-doc -l #全部模块
ansible-doc -s file #搜索模块、找模块参数
模块分类 | 模块 |
---|---|
命令和脚本模块 | command模块 默认模块 执行简单命令,不支持特殊符号 |
shell模块 执行命令 支持特殊符号 | |
script模块 分发脚本并执行 | |
文件 | file 创建目录,文件,软连接 |
copy 远程分发文件,修改权限,所有者,备份 | |
服务 | systemd服务管理 |
service 服务管理(了解) | |
软件包 | yum源 yum_repository |
yum命令 | |
get_url下载软件 | |
系统管理 | mount模块 挂载 |
cron模块 定时任务 | |
用户管理 | group模块 管理用户组 |
user模块 管理用户 | |
其他 | 压缩解压(unarchive),rsync模块(synchronize),数据库模块(mysql_db,mysql_user)... |
调试模块 | ping检测ansible与其它节点连通性 |
debug模块 检查、显示 变量 | |
命令和脚本
1.command模块
是ans默认模块,适用于简单命令,不支持特殊符号
[root@m01 ~]# ansible all -m command -a "hostname"
#-m 指定模块,-a模块的选项(命令);command也是默认模块 可以不写
# ansible all -a "hostname"
192.168.10.53 | CHANGED | rc=0 >>
buckup
192.168.10.52 | CHANGED | rc=0 >>
web01
192.168.10.51 | CHANGED | rc=0 >>
nfs01
2.shell模块
与command模块相似,但支持特殊符号(==避免因特殊符号和引号导致的问题==)
ansible all -m shell -a 'rm -rf /tmp/*' #可用双引号
批量获取IP
[root@m01 ~]# ip a s ens33 | awk -F'[/ ]+' 'NR==3{print $3}'
192.168.10.50
[root@m01 ~]# ansible all -m shell -a "ip a s ens33 | awk -F'[/ ]+' 'NR==3{print \$3}'"
#“”转义特殊符号,\转义‘’号中的特殊符号
192.168.10.52 | CHANGED | rc=0 >>
192.168.10.52
192.168.10.51 | CHANGED | rc=0 >>
192.168.10.51
192.168.10.53 | CHANGED | rc=0 >>
192.168.10.53
shell模块不推荐执行较为复杂的命令,如果需要,可放在脚本中执行
3.script模块
1.分发脚本(传输脚本),在被管理端执行脚本
2.运行脚本
注:被控制节点执行完脚本后才有反馈
[root@m01 script]# cat xuntest.sh
#!/bin/bash
#auther: To9cn
#desc: 系统巡检脚本
hostname
hostname -I
ip a s ens33 | awk -F'[/ ]+' 'NR==3{print $3}'
uptime
whoami
date +%F
sleep 3
#模块执行
[root@m01 script]# ansible all -m script -a '/root/script/xuntest.sh'
#被管理端ps -ef | grep ansible 可查看临时脚本文件路径
[root@nfs01 ~]# ps -ef | grep ansible
root 11774 11749 0 21:58 pts/0 00:00:00 /bin/sh -c /root/.ansible/tmp/ansible-tmp-1710208685.15-15173-53973950998774/xuntest.sh && sleep 0
#执行玩脚本以后文件自动删除
4.debug模块
执行Ansible在命令行只会显示OK,Changed等,debug模块可自定义==控制台输出内容==
[root@m01 playbook]# ansible all -m debug -a "msg='hello word'"
#剧本模式
debug:
msg: "Test Debug"
-v参数
[root@m01 test]# ansible -i inventory web --list-hosts -v #显示cfg的配置文件
Using /etc/ansible/ansible.cfg as config file
hosts (1):
192.168.10.52
文件相关模块
1.file模块
管理文件、目录、软连接
file模块把touch、mkdir、rm、ln等命令结合在一起
file模块 | 模块说明 |
---|---|
==path== | 目录、文件路径 必写 |
src | 源文件一般用link(创建软连接) 用于指定源文件 |
==state== | 状态(模式) state=directory 创建目录 state=file(默认) 更新文件,若文件不存在不创建 state=link 创建软连接 state=touch 创建文件 |
==state== | state=absent 删除 (如果是目录递归删除目录) |
mode | mode=755 创建并修改权限 mode: 0640 |
owner | onwer=root |
group | group=root |
recurse | 创建文件,如果存在,更新文件时间戳 |
force | force参数:当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件,不过强制创建链接文件分为两种情况,情况一:当你要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当你要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,回将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当你要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件 |
被控制节点批量创建删除文件、目录
[root@m01 ~]# ansible all -m file -a "path=/opt/test.sh state=touch"
#删除
[root@m01 ~]# ansible all -m file -a "path=/opt/test.sh state=absent"
[root@m01 ~]# ansible all -m file -a "path=/root/test/abc/ state=directory"
#支持创建多级目录
#软连接
ansible all -m file -a "path=/opt/hosts src=/etc/hosts state=link" #path是创建后叫什么放哪 src是源文件
#检测
[root@m01 ~]# ansible all -a 'ls -l /opt/hosts'
192.168.10.53 | CHANGED | rc=0 >>
lrwxrwxrwx. 1 root root 10 Mar 11 23:00 /opt/hosts -> /etc/hosts
192.168.10.52 | CHANGED | rc=0 >>
lrwxrwxrwx. 1 root root 10 Mar 11 23:00 /opt/hosts -> /etc/hosts
192.168.10.51 | CHANGED | rc=0 >>
lrwxrwxrwx. 1 root root 10 Mar 11 23:00 /opt/hosts -> /etc/hosts
#owner修改所有者;推荐在创建时指定属主、权限...
[root@m01 ~]# ansible all -m file -a "path=/testmdr/ owner=root group=root mode=777 state=directory"
#属主和组必须存在才可成功
#控制节点检测
[root@m01 ~]# ansible all -a 'ls -ld /testmdr'
2.copy模块
批量分发:scp,管理节点发送文件到所有被管理端
注:copy传输是单向的
copy模块 | |
---|---|
==src== | source 源文件,管理端的文件(不推荐传目录) |
==dest== | destnation 目标;被管理端的目录文件 |
backup | backup=yes 在覆盖前进行备份(文件存在且不一样会备份) |
mode | 修改权限: 0644 |
owner | 修改为指定所有者 |
group | 修改为指定用户组 |
content | 提供一个字符串 可转义特殊符号:"this is contentn" 替代src文件,自行输入内容,避免源文件混乱 |
force | 默认为yes;强制覆盖受管机文件。手动设no;如果文件不存在,源文件不发生改变 |
扩展:==fetch==从被管理节点拉取文件到管理节点
3.lineinfile
修改文件内容:类似sed -i 'sg' , sed 'cai'
path 指定文件、create 如果文件不存在是否创建(true/false)
regexp 正则 只换正则匹配的内容(匹配多行只修改最后一行)
path/dest: 目标文件绝对路径+文件名,必须参数
line: 替换/插入的内容
regexp: 待匹配内容
insertbefore: 匹配行前面插入
insertafter: 匹配行面插入
state: 删除匹配行,需要将值设为absent,默认值present。
backup: 是否在修改文件之前对文件进行备份。 yes/no
create: 当要操作的文件并不存在时,是否创建对应的文件。yes/no
backrefs:yes/no
1.backrefs为no时,如果没有匹配,则添加一行line。如果匹配了,则把匹配内容替被换为line内容。
2.backrefs为yes时,如果没有匹配,则文件保持不变。如果匹配了,把匹配内容替被换为line内容。
4.blockinfile
匹配一段文字,插入、更改、删除
backup: 是否备份文件
block: 指定要插入标记内的文本:别名叫 "content"
create: 如果文件不存在,则创建新文件
group: 文件属组
insertafter: 如果指定,文本将插入到最后一次匹配项的后面
insertbefore: 如果指定,文本讲插入到最后一次匹配项的前面
maker: 假如我们想要在指定的文件中插入一段文本,ansible会自动为这段文本添加2个标记,一个开始标记,一个结束标记;
默认情况下,开始标记为:# BEGIN ANSIBLE MANAGED BLOCK,结束标记为# END ANSIBLE MANAGED BLOCK
path: 文件路径
state: 可选present或absent,默认为将指定的文本插入到文件中,如果文件中存在该文本,则会更新对应的段落,如果为absent,则删除对应的段落
---
- hosts: all
tasks:
- name: Add blocktxt to a file
blockfile:
path: /root/files/
block: |
First line is good
Second line is cool
state: present
5.stat模块
stat模块用于获取文件或文件组的状态信息。这可以包括文件的大小、权限、最后修改时间等。
参数/类型 | 选项/默认值 | 描述 |
---|---|---|
checksum_algorithm<br/>string | ·sha1←<br/>· md5<br/>·sha224<br/>·sha256<br/>·sha384<br/>· sha512 | 确定文件校验和的算法。<br/>如果主机无法使用指定的算法,将抛出错误。<br/>远程主机必须支持指定的散列方法,如果主机符合FIPS-140, md5可能不可用。 |
follow<br/>boolean | · no ←<br/>· yes | 是否遵循符号链接 |
get_attributes<br/>boolean | · yes ←<br/>· no | 如果存在,使用lsattr工具获取文件属性 |
get_checksum<br/>boolean | · yes ←<br/>· no | 是否返回文件的校验和 |
get_mime<br/>boolean | · yes ←<br/>· no | 使用文件魔法并返回关于文件性质的数据。它使用了在大多数Linux/Unix系统上都可以找到的“文件”实用程序。<br/>这将同时添加’ mime_type ‘和’charset’字段,如果可能的话。<br/>在Ansible 2.3中,这个选项从’mime’变为’get_mime’,默认为’Yes’。 |
path<br/>path<br/>required | 要获取的事实的文件/对象的完整路径。 |
6.Synchronize模块
Synchronize模块成为了实现高效文件同步的重要组件:synchronize模块用于同步两个系统之间的文件或目录。它可以将一个系统(控制主机)上的文件或目录同步到一个或多个远程系统上。
compress:开启压缩,默认为开启
archive:是否采用归档模式同步,保证源文件和目标文件属性一致
checksum:是否效验
dirs:以非递归的方式传送目录
links:同步链接文件
recursive:是否递归yes/no
rsync_opts:使用rsync的参数
copy_links:同步的时候是否复制链接
delete:删除源中没有但目标存在的文件,使两边内容一样,以推送方为主
src:源目录及文件
dest:目标文件及目录
dest_port:目标接收的端口
rsync_path:服务的路径,指定rsync在远程服务器上执行
rsync_remote_user:设置远程用户名
–exclude=.log:忽略同步以.log结尾的文件,这个可以自定义忽略什么格式的文件,或者.txt等等都可以,但是由于这个是rsync命令的参数,所以必须和rsync_opts一起使用,比如rsync_opts=--exclude=.txt这种模式
mode:同步的模式,rsync同步的方式push、pull,默认是推送push,从本机推送给远程主机,pull表示从远程主机上拿文件
---
- hosts: all
tasks:
- name test synchronize
synchronuze:
src: file
dest: /path/to/file
replace
替换多行模块
服务管理-systemd
systemd模块相当于Linux systemd命令:
开启,关闭,重启服务
开机自启服务
systemd模块 | |
---|---|
==name== | 指定服务名称 |
==enabled== | yes开机自启 |
==state== | 表示服务开关重启 state=started 开启 state=stopped 关闭 state=reloaded 重读配置文件 state=restarted 重启 |
daemon-reload | yes是否从新加载对应的服务管理配置文件 自定义配置文件 |
#开启crond服务(集群)并设置开机自启
[root@m01 ~]# ansible all -m systemd -a "name=crond enabled=yes state=started"
#开启,关闭防火墙
[root@m01 ~]# ansible all -m systemd -a "name=firewalld enabled=yes state=started"
[root@m01 ~]# ansible all -m systemd -a "name=firewalld enabled=no state=stopped"
扩展:systemd适用于大部分Linux系统;service模块适用于旧的系统
软件管理
yum模块
get_url模块,wget命令
yum_repository模块,yum配置模块,可通过copy模块实现。
1.yum模块
yum模块不只是yum命令,包含==yum,apt==命令
yum模块 | |
---|---|
name | 指定软件包名字;可以指定==多个==,用 “ , ”分割。 |
state | installed 安装(present(默认)) removed 删除(也可写为absent) lastest 安装或更新 |
update_cache | 设置为no加速,表示不更新yum缓存,建议开启 |
#安装常用软件htop,tree,lrzsz
[root@m01 ~]# ansible all -m yum -a "name=htop,tree,lrzsz update_cache=yes state=present"
2.get_url模块
相当于wget命令,所有主机有网络才可
推荐在管理节点下载好,使用copy仅分发即可
get_url下载功能 | |
---|---|
url | 指定下载路径,地址 |
dest | 下载到本地哪个目录 |
validate_certs | 默认yes,no跳过https(SSL报错) |
#zabbix-agent地址为:#https://mirrors.aliyun.com/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.13-release1.el7.x86_64.rpm
下载zabbix到/app/tools下
#创建目录
[root@m01 ~]# ansible all -m file -a "path=/app/tools state=directory"
#控制节点下载zabbix
[root@m01 ~]# 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=/app/tools"
#yum安装
[root@m01 ~]# ansible all -m yum -a "name=/app/tools/zabbix-agent-6.0.13-release1.el7.x86_64.rpm state=installed update_cache=no"
==有时wget识别不了https,需要加上 --no-check-certificate 参数==
wget --no-check-certificate XXXXXX
3.yum_repository模块
用处不是很多
推荐:未来在单独目录下书写好yum配置文件,copy分发过去即可。
yum源模块 yum_repository | |
---|---|
name | yum源中的名字 [Centos] |
description | yum源中的注释说明 对应的 是name的内容 |
baseurl | yum源中 baseurl 下载地址 |
enabled | 是否启动这个源 yes/no |
gpgcheck | 是否启动gpgcheck功能 no(校验官方,许可等) |
file | 指定yum源文件 自动添加.repo 默认与模块名字一致 |
与普通yum文件区别
[name] | name=centos 默认为源文件的文件名 |
---|---|
name=centos | description="" 描述 |
enabled=1 | enabled=yes |
gpgcheck=0 | gpgcheck=no |
用户管理
user用户管理:useradd
group用户组管理:groupadd
1.user模块
user模块 | |
---|---|
name | 用户名 |
uid | 指定uid |
group | 指定用户组,用于事先创建好了用户组 通过选项指定 |
shell | 指定命令解释器 |
create_home | 是否创建家目录(yes/no) |
state | present 添加 absent 删除 |
password | 更新密码 |
#创建www-ans用户uid 2000
[root@m01 ~]# ansible all -m user -a "name=www-ans uid=2000 shell=/sbin/nologin create_home=no state=present"
[root@m01 ~]# ansible all -a "grep www-ans /etc/passwd"
#带密码
ansible all -m user -a "name=wang password={{ '1' | password_hash('sha512','wang')}} state=present"
#'wang'是随机加的字符
#sha512加密格式输出加密后的结果
[root@m01 ~]# ansible all -i localhost, -m debug -a "msg={{ '1' | password_hash('sha512','wang') }}"
localhost | SUCCESS => {
"msg": "$6$wang$8N45KDaHJsVGx6VQSjHS8helqldy7geS/zTb739WyuoPNxdW49B55l5SoCxg8rx5hv/O791edTg5k5C3QV/5a0"
}
#使用加密后的msg作为密码
ansible all -m user -a "name=liu1 password='$6$wang$8N45KDaHJsVGx6VQSjHS8helqldy7geS/zTb739WyuoPNxdW49B55l5SoCxg8rx5hv/O791edTg5k5C3QV/5a0' state=present"
#等价于密码1
#shell模块更新密码
[root@m01 ~]# ansible all -m shell -a "echo 1 | passwd --stdin liu"
192.168.10.53 | CHANGED | rc=0 >>
Changing password for user liu.
passwd: all authentication tokens updated successfully.
关于{{}}解释
{{ '1' | password_hash('sha512','wang')}}
1表示密码,经过管道,传递给password_hash()插件,sha512加密算法,wang是随机字符用于生成加密后的密码。
2.group模块
group | |
---|---|
name | 指定用户组名字 |
gid | 指定组id |
state | present 添加 absent 删除 |
mount模块
实现mount命令进行挂载,且可修改/etc/fstab实现永久挂载。
mount | |
---|---|
fstype | 指定文件系统;xfs,ext4,iso9660,nfs |
src | 源地址(nfs地址 eg 192.168.10.50/data) |
path | 挂载点(把源挂载到哪里) |
state | 见下表 |
mount的state参数可用值 | |
---|---|
==absent== | 卸载并修改fstab |
unmounted | 卸载不修改/etc/fstab |
present | 仅修改/etc/fstab 不挂载 |
==mounted== | 挂载并修改/etc/fstab |
remounted | 从新挂载 |
定时任务cron
用于管理系统的定时任务,替代了crontab -e功能
cron模块 | 说明 |
---|---|
name | 定时任务名字(必加),对应下面==注释==内容 |
minute | 分钟 minute="/2" |
hour | 小时 |
day | 日期 |
month | 月份 |
week | 周几 |
job | 指定命令或脚本(定向到空) job="/sbin/ntpdate ntp1.aliyum.com &>/dev/null" |
state | present 添加定时任务(默认) absent 删除 |
#添加定时同步时间任务
*/2 * * * * /sbin/ntpdate ntp1.aliyum.com &>/dev/null
ansible all -m cron -a 'name="10.sync time wang" minute="*/10" job="/sbin/ntpdate ntp1.aliyum.com &>/dev/null" state=present'
#被控制节点查看任务
[root@nfs01 ~]# crontab -l
#Ansible: 10.sync time wang
*/10 * * * * /sbin/ntpdate ntp1.aliyum.com &>/dev/null
#删除任务 name + state
ansible all -m cron -a 'name="10.sync time wang" state=absent'
清理已有的定时任务
#使用sed替换
[root@m01 ~]# ansible all -a "sed -i '/ntpdate/d' /var/spool/cron/root"
#但注释还在
[root@nfs01 ~]# crontab -l -u root
#Ansible: 10.sync time wang
其他模块
集群批量管理-Ansible-剧本-变量
剧本:可以书写部署服务脚本rsync、nfs、sersync
变量:类似脚本,在剧本使用
剧本
playbook 文件;用于长久保存并实现批量管理,维护,部署的文件
脚本中存放命令和变量,剧本中存放==模块==
剧本yaml格式;yaml格式的文件:空格,冒号
剧本和hoc区别
ans剧本 | ans ad-hoc | |
---|---|---|
共同点 | 批量管理,使用模块 | 批量管理,使用模块 |
区别 | 重复调用 | 不方便重复调用 |
应用场景 | 部署服务,多个步骤任务 | 测试模块,临时性任务 |
[root@m01 playbook]# cat 01.show.yml
---
- hosts: all
tasks:
- name: 01 起床
shell: echo 01 >> /tmp/everyday.log
- name: 02 刷牙
shell: echo 02 >> /tmp/everyday.log
- name: 03 吃早餐
shell: echo 03 >> /tmp/everyday.log
- hosts: [server1,serverb]
==剧本hosts指定多个集群 :====- hosts: nfs:web:buckup==
192.168.10.51 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.10.52 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.10.53 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#剧本执行命令
ansible-playbook 01_test.yml
#检测剧本语法
ansible-playbook 01_test.yml --syntax-check
#奶牛优化
[root@m01 playbook]# ansible-playbook 01.show.yml
#修改etc/ansible/ansible.cfg 随机图案
cow_selection = random #打开注释
#剧本目录下最好有/ansible/hosts文件
ansible-playbook -i hosts 02_file.yml
#-i 指定主机清单
注:==同级内容对齐、不同层级隔两个空格、不可用tab键==
vi编辑器缩进修改
在/etc/vimrc文件添加
set tabstop=2
剧本案例
1.创建并分发文件
1.创建目录 /server/files/
2.把 /etc/hosts 文件发送到 /server/files/
#创建目录server/files/
ansible all -m file a "path='/server/files/' state=directory"
#分发
ansible all -m copy a "src=/etc/hosts dest=/server/files/"
剧本模式
[root@m01 playbook]# cat 02.file.yml
---
- hosts: all
tasks:
- name: 01 Creat file
file: path=/server/files/ state=directory
- name: 02 Copy file
copy: src=/etc/hosts dest=/server/files/
==冒号格式(专业格式);==
[root@m01 playbook]# cat 02.file.yml
---
- hosts: all
tasks:
- name: 01 Creat file
file:
path: /server/files/
state: directory
- name: 02 Copy file
copy:
src: /etc/hosts
dest: /server/files/
2.安装软件
分发安装包、安装软件、启动服务
zabbix-agent软件包(下载)
安装软件包
配置(略)
开机自启
==步骤--->模块--->剧本== ==测试:分步测试==
#下载安装包
wget https://mirrors.aliyun.com/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.13-release1.el7.x86_64.rpm
#安装软件
yum install -y zabbix-agent-6.0.13-release1.el7.x86_64.rpm
#启动
systemctl
模块
#下载: get_url(url)
#安装:yum(installed)
#启动:system
剧本
[root@m01 playbook]# cat 03_install_zabbix.yml
---
- hosts: all
tasks:
- name: 01 ---创建下载目录
file:
path: /root/zabbix/
state: directory
- name: 03 ---下载安装包
get_url:
url: https://mirrors.aliyun.com/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.13-release1.el7.x86_64.rpm
dest: /root/zabbix/
validate_certs: no
- name: 04 ---安装软件
yum:
name: /root/zabbix/zabbix-agent-6.0.13-release1.el7.x86_64.rpm
state: present
- name: 05 ---设置自启
systemd:
name: zabbix-agent
enabled: yes
state: started
#检测
[root@m01 playbook]# ansible all -m shell -a "ps -ef | grep zabbix"
192.168.10.51 | CHANGED | rc=0 >>
zabbix 14944 1 0 14:05 ? 00:00:00 zabbix_agentd
zabbix 14945 14944 0 14:05 ? 00:00:06 zabbix_agentd: collector [idle 1 sec]
3.nfs服务
day40-9
nfs服务端:在backup部署nfs服务,共享/backup-nfs目录,all_squash,nfsnobody
nfs客户端:web挂载 /ans-upload目录挂载nfs服务端共享的/backup-nfs(永久挂载)
服务端流程:
1.部署nfs-utils
2.修改配置文件
3.创建共享目录,改所有者
4.启动服务rpcbind,nfs
客户端流程:
1.安装nfs-utils
2.挂载与永久挂载
剧本模式
#nfs Client
---
- hosts: buckup
tasks:
- name: 01 Deploy nfs-utils,rpcbind
yum:
name: nfs-utils,rpcbind
state: present
- name: 02 Present system file
lineinfile:
path: /etc/exports
line: "/buckup-nfs 192.168.10.0/24(rw,all_squash)"
create: true
- name: 03-1 Create Together file & Present User
user:
name: nfsnobody
create_home: yes
state: present
- name: 03-2 Create Together file & Present User
file:
path: /buckup-nfs
owner: nfsnobody
group: nfsnobody
state: directory
- name: 04-1 Start Service(rpcbind,nfs)
systemd:
name: rpcbind
enabled: yes
state: started
- name: 04-2 Start Service(rpcbind,nfs)
systemd:
name: nfs
enabled: yes
state: started
#nfs Server
- hosts: web
tasks:
- name: 01 Deploy nfs-utils
yum:
name: nfs-utils
state: present
- name: 02 Mount nfs
mount:
src: 192.168.10.53:/buckup-nfs
path: /ans-upload
fstype: nfs
state: mounted
Ansible变量
可以定义变量的地方 | 说明 |
---|---|
在剧本文件中定义 | 比较常用.仅仅限于当前的play使用 |
register变量(注册变量) | ip=hostname-I 实现脚本中反引号的功能,可以获取命令结果 |
变量文件,根据主机清单分组进行定义变量 | 如果多个剧本,使用相同的变量,大型的剧本roles |
inventory主机清单中定义变量 | 未来可以用于批量修改主机使用,其他很少用了 |
facts变量 | 一般用于获取主机基本信息:ip,主机名,系统(centos/ubuntu) 如果不需要可以关闭,用于加速剧本的执行 |
0.在主机组Inventory中的变量
针对单个主机组或多个主机组(子组)的变量定义
[nfs_server]
192.168.10.51
[web_server]
192.168.10.52
[service:children]
nfs_server
web_server
[web_server:vars] #用于web_server组
user=web
[service:vars] #用于子组全部组
user=root
1.在playbook定义变量
仅在当前play生效,存放路径,用户名,ip...
[root@m01 playbook]# cat 05_var_test.yml
#var test
---
- hosts: all
vars:
dir: /to9cn/wang/oldboy/a/b/c/
tasks:
- name: Create directory
file:
path: "{{ dir }}"
state: directory
- name: debug tab
debug:
msg: "The vars: {{ dir }}:::" #不管多少空格只取变量值
#检测
[root@m01 playbook]# ansible all -i hosts -a "tree /to9cn"
192.168.10.53 | CHANGED | rc=0 >>
/to9cn
└── wang
└── oldboy
└── a
└── b
└── c
变量引号问题
#变量只要是选项的开头 就必须加引号"" ''
dir: /to9cn/wang/oldboy/a/b/c/
path: "{{ dir }}" #选项开头加引号
state: directory
path: /root/script/{{dir}} #非选项开头不加引号
2.变量文件(共用)
a. vars_files(变量文件)
可在任意目录下创建此变量文件,可使用相对和绝对路径
缺点:每个需要变量文件的剧本都==必须在开始调用变量文件==
[root@m01 vars_group]# cat 01_var_test.yml
---
- hosts: all
vars_files: ./vars.yml
# 若不是在同级目录,可直接使用相对目录
tasks:
- name: 01 Print vars
debug:
msg: "vars: {{ user }} {{ src }} {{ dest }}"
b.group_files(主机组文件)
主机组清单变量文件
在剧本文件的同级目录下创建group_vars目录,此目录中创建以主机组命名的目录;
最后在主机组目录下书写变量文件(vars.yml);
==playbook的同级目录下:group_vars/all(web nfs backup)/vars.yml==
智能==自动识别,剧本不需引用==且可针对主机组指定变量
#结构
[root@m01 vars_group]# ls
01_var_test.yml group_vars vars.yml
[root@m01 vars_group]# tree
.
├── 01_var_test.yml
├── group_vars
│ └── all
│ └── vars.yml
[root@m01 vars_group]# cat group_vars/all/vars.yml
user: wang(group)
src: https://grpup_vars
dest: /root/group_vars/vas/
剧本删除变量文件引用
[root@m01 vars_group]# cat 01_var_test.yml
---
- hosts: all
tasks:
- name: 01 Print vars
debug:
msg: "vars: {{ user }} {{ src }} {{ dest }}"
ok: [192.168.10.52] => {
"msg": "vars: wang(group) https://grpup_vars /root/group_vars/vas/"
}
ok: [192.168.10.51] => {
"msg": "vars: wang(group) https://grpup_vars /root/group_vars/vas/"
}
ok: [192.168.10.53] => {
"msg": "vars: wang(group) https://grpup_vars /root/group_vars/vas/"
}
c.host_vars(特定主机)
[root@m01 hosts_var]# tree -F
.
├── 01_hostvar.yml
├── hosts
└── host_vars/
└── web01.yml
1 directory, 3 files
d.(一次性)==覆盖已经定义的变量==
ansible-plbook main.yaml -e "user=wang"
e.变量数组定义与取值
user:
home:
first_name: wang
last_name: tao
school:
first_name: liu
last_name: chao
"{{user.home.first_name}}" "{{user.school.last_name}}"
user['home']['first_name']
3.register变量注册变量
实现脚本中的 `` 反引号功能 : ip='hostname -I' 期望得到ip
通过shell等系统命令结果保存到Register变量中
==stdout==全名是standard putput (标准输出)
[root@m01 playbook]# cat 06_register.yml
---
- hosts: all
tasks:
- name: 01 Get Server Time
shell: date +%F
register: result #接收命令获取结果给变量
- name: 02 Out result
debug:
msg: |
"register all: {{result}}" #
"register.stdout: {{result.stdout}}"
ok: [192.168.10.52] => {
"msg": "register.stdout: 2024-03-14"
}
"msg": "\"register all: {'stderr_lines': [],
u'changed': True,
u'end': u'2024-03-14 23:17:54.964215',
'failed': False,
u'stdout': u'2024-03-14', #标准输出
u'cmd': u'date +%F',
u'rc': 0, u'start':
u'2024-03-14 23:17:54.960870',
u'stderr': u'',
u'delta': u'0:00:00.003345',
'stdout_lines': [u'2024-03-14']}\"
4.facts变量
==ans内置变量==
ans内置变量,ans运行剧本的时候会有一个默认的TASK [Gathering Facts]。运行剧本的时候ans会收集每个主机的基本信息,这些信息形成的变量叫做facts变量.
==facts变量setup模块获取==---- ansible web -m setup
变量归属与读取
"ansible_swapfree_mb": 2047, #前面只有8个空格的变量可直接使用
#八个空格
"ansible_swaptotal_mb": 2047,
"ansible_system": "Linux",
大于8个空格:
每四个空格为一个归属,找到上级用 “ . ”读取到下级内容
"ansible_effective_user_id": 0,
"ansible_ens33": {
#八个空格
"active": true,
"device": "ens33",
"features": {
"ipv4": { #上级为ansible_ens33
"address": "192.168.10.52", #上级为ipv4
"broadcast": "192.168.10.255",
"netmask": "255.255.255.0",
"network": "192.168.10.0"
读取IP:==ansible_ens33.ipv4.address==
剧本
---
- hosts: all
tasks:
- name: 显示系统的基本信息
debug:
msg: |
你的系统是{{ ansible_distribution}}
你系统的版本是{{ansible_distribution_version}}
你主机名为{{ansible_hostname}}
ok: [192.168.10.52] => {
"msg": "你的系统是CentOS\n你系统的版本是7.5\n你主机名为web01\n"
}
常见的facts变量
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 #时间
在剧本中如果不需要用到facts内置变量,可以==关闭此任务提高自动化效率==。
在tasks上注明:
- hosts: web
gather_facts: no
tasks:
- name:
file: ...
a.==新版ansible_facts拆解==
"ansible_dns": { # 八个空格
"nameservers": [
"192.168.10.200"
]
},
#拆解表达
ansible_facts.dns.nameserver ansible_facts['dns']['nameserver']
b.关闭事物收集提升性能
---
- hosts: web
gather_facts: false #关闭后可使用事实,手动收集事实才可使用
tasks:
# - name: Open the facts
# setup:
- name: show facts
debug:
msg: "{{ansible_facts.hostname}}"
c.自定义事实
自定义事实文件位置:
[root@web01 facts.d]# ls
server.fact
[root@web01 facts.d]# pwd
/etc/ansible/facts.d
自定义事实包含在 : {{==ansible_facts.ansible_local==.server.web.name}}
[root@web01 redhat_ansible]# cat /etc/ansible/facts.d/server.fact
[web]
name= wang
school= GZEU
[nfs]
name=liu
school=Dahua
剧本使用:
集群批量管理-流程控制-Roles
Ansible流程控制
==handler==
when
==loop==/with_items
1.handler触发器
修复服务的配置文件后---重启服务
配置文件无变化,不重启服务,仅配置变化才重启
应用场景:分发配置文件的时候---重启服务(或者做其他)
格式: notify: name1 , handlers: -name1 -name2
注意:handlers必须放在剧本最后,否则之后的剧本都认做handlers
[root@m01 playbook]# cat 08.handler.yml
---
- hosts: nfs
gather_facts: no
tasks:
- name: Hand files
copy:
src: exports
dest: /etc/exports
backup: yes
- name: Restart Service #无论文件如何变化 重启服务都会执行
systemd:
name: nfs
state: reloaded
使用handler与notify
[root@m01 playbook]# cat 08.handler.yml
---
- hosts: nfs
gather_facts: no
tasks:
- name: Hand files
copy:
src: /etc/exports
dest: /etc/exports
backup: yes
notify: #如果检测到此任务Changed 匹配handler中的name并执行
- Restart Service
- #可添加多个
handlers: #如果对应的任务状态不是Changed 不会执行handler
- name: Restart Service
systemd:
name: nfs
state: reloaded
2.when判断
用于给ans运行的task(模块)设置条件,满足或不满足条件在运行对应的模块.
应用建议:when进行判断,一般与变量一起使用.
when条件一般与facts变量或reqister变量较多.
# 以系统类型为条件判断 分系统安装个需软件
[root@m01 playbook]# cat 09_when.yml
- hosts: all
tasks:
- name: CentOS系统安装sl,cowsay,tree
yum:
name: sl,cowsay,tree
state: present
when: ansible_distribution == "CentOS"
- name: Ubuntu系统安装cmatrix,lolcat
apt:
name: cmatrix,lolcat
state: present
when: ansible_distribution == "Ubuntu"
# 若没条件判断,所有节点都会安装两任务的全部软件
==when常见表达==
== !=
is / is not match
eg: is not match("web|backup") #支持正则
条件1 and 条件2
条件1 or 条件2
is (not) defined 变量不存在
memory_available 布尔值为true,1:True和yes也为true
not memory_available 布尔值为false,0,False
eg:
when: ansible_distribution == "Ubuntu" and/or ansible_hostname is match("web|backup")
# 增强可读性
when:
- ansible_distribution == "Ubuntu"
- ansible_hostname is wang
or表达:
when: >
( ansible_distribution == "Ubuntu" and
ansible_hostname is wang)
or
( ansible_distribution == "CentOs"
ansible_hostname is liu)
3.循环with_items 与 ==loop==
场景:批量创建文件、添加用户、启动和重启服务
"{{item}}"+with_items 与 "{{item}}"+loop用法一致
重启多个服务(循环单个参数)
[root@m01 playbook]# cat 10_loop.yml
---
- hosts: buckup
gather_facts: no
tasks:
- name: restart Service(rpcbind,nfs)
systemd:
name: "{{item}}" #item没有s
state: restarted
with_items:
[a,b]
#loop: 效果和with_items:一样 loop没有s
- rpcbind
- nfs
- sshd
- crond
为集群添加用户(循环多个参数: name uid passwd...)
[root@m01 playbook]# cat 11_loop_more.yml
---
- hosts: nfs
gather_facts: no
tasks:
- name: Add User
user:
name: "{{item.name}}"
uid: "{{item.uid}}"
state: present
loop:
- {name: 'oldboy',uid: 2020} #整数不用加引号
- {name: 'wangtao',uid: 2021}
- {name: 'chaoqun',uid: 2022}
# {} 参数前需要 " - "
Ubuntu和Centos的细微差别
#CentOS的 /bin/sh 指向bash
[root@m01 playbook]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Mar 8 06:32 /bin/sh -> bash
#Ubuntu区别
# ll /bin/sh
/bin/sh -> dash* #脚本语法部分不一样
针对不同的系统优化添加playbook的解释器
user:
name: "{{item.name}}"
uid: "{{item.uid}}"
shell: /bin/bash # Ubuntu系统将会更改 解释器
state: present
==变量循环遍历==
循环遍历时需要去playbook寻找items具体位置,可写在vars变量(在book首部)中或vars变量文件中;方便修改
vars:
information:
- name
- school
- addr
tasks:
- name: Check the loop vars
service:
name: "{{item}}}"
state: satrted
loop: "{{ information }}"
==分组循环==
user:
name: "{{ item.name }}"
group: "{{ item.group }}"
state: present
loop:
- name: wang
group: GZEU #一组变量 不用加 ‘ - ’
- name: liu
group: Yushan
Loop+Register
Ansible剧本调试
:one:剧本单步执行
:two:tag标签
:three:忽略错误
1.单步执行
- -C --check 模拟运行,不做出改变(变量可能报错,因为没真正运行脚本)
- --syntax-check 只检查语法,不运行
- --step 单步运行:y执行这个task,n忽略这个task,c从当前开始自动运行
2.tag标签(step改进)
- tag标签类似于超市物品的分类,只不过tag标签是给ansible中的task进行分类.加上标记;也就是单独对name moudle分类
- 运行剧本的时候运行指定的tag标签或排除某些tag.
==想单独运行部分板块或者不想运行部分板块==
tags:==内容中不要有空格==
[root@m01 playbook]# cat 12_tag.yml
---
- hosts: buckup
gather_facts: no
tasks:
- name: 01 Deploy nfs-utils,rpcbind
yum:
name: nfs-utils,rpcbind
state: present
tags: 1.install #针对独立name 进行标签
- name: 02 Present system file
lineinfile:
path: /etc/exports
line: "/buckup-nfs 192.168.10.0/24(rw,all_squash)"
create: true
tags: 2.conf
- name: 03-1 Create Together file & Present User
user:
name: nfsnobody
create_home: yes
state: present
tags: 3.file
- name: 03-2 Create Together file & Present User
file:
path: /buckup-nfs
owner: nfsnobody
group: nfsnobody
state: directory
tags: 4.user
- name: 04 Start Service(rpcbind,nfs)
systemd:
name: "{{item}}"
enabled: yes
state: started
loop:
- rpcbind
- nfs
tags: 5.service
- -t 、--tags 运行的标签,如果多个标签则通过","分割
- --skip-tags 排除指定的tags,如果多个标签则通过","分割
- --list-tags 列出剧本的全部标签
# 列出标签
[root@m01 playbook]# ansible-playbook --list-tags 12_tag.yml
playbook: 12_tag.yml
play #1 (buckup): buckup TAGS: []
TASK TAGS: [1.install, 2.conf, 3.file, 4.user, 5.service]
# 运行tags板块1
[root@m01 playbook]# ansible-playbook -t 1.install 12_tag.yml
# 运行板块1和2
[root@m01 playbook]# ansible-playbook -t 1.install,2.conf 12_tag.yml #板块之间无空格
#--skip-tags 除开选择的tags标签 剩余的标签全部执行
[root@m01 playbook]# ansible-playbook --skip-tags 2.conf,3.file,4.user,5.service 12_tag.yml
#只执行 1.install
3.忽略错误
- anisble在执行出错的时候终结剧本,不再执行后续程序
- 因重复导致的错误提示(并非真错误,例如目录,用户已经存在) systemd服务名错误也能忽略
- 通过 ignore_errors忽略错误,继续剧本
ignore_errors: true
true/false
yes/no
场景:才执行创建文件、目录、用户等操作时可加此参数
- hosts: nfs
tasks:
- name: 01 Creat file
file:
path: /server/files/
state: directory
ignore_errors: true #和tags一样与模块、name对齐
Jinja2模板
1.基本使用
在分发文件时,文件中==需要使用变量==(facts,Clents_info,groups_vars)
copy传输文件 文件纹丝不动传递
==template会替换掉文件中的变量(.j2) 无需手动修改==
- 文件必须以 .j2 结尾
- 必须使用template模块(传输时替换j2文件中的变量)
# 分发主机信息文件
[root@m01 templates]# cat 01_Jinja2_test.j2
######################
welcome to oldboy elastic linux system
操作需谨慎,删根弹指间.
主机名: {{ ansible_hostname}}
ip地址: {{ansible_default_ipv4.address}}
内存大小: {{ ansible_memtotal_mb}}
CPU数量: {{ansible_processor_vcpus}}
核心总数: {{ansible_processor_cores}}
发行版本: {{ansible_distribution}}
# 剧本
[root@m01 templates]# cat 02_handj2.yml
---
- hosts: nfs
tasks:
- name: Create (copy templates) file
file:
path: /root/jinja/
state: directory
- name: template Hand J2 file
template:
src: /root/script/playbook/templates/01_Jinja2_test.j2
dest: /root/jinja/template
backup: yes
- name: copy Hand J2 file
copy:
src: /root/script/playbook/templates/01_Jinja2_test.j2
dest: /root/jinja/copy
backup: yes
#对比两模块 变量是否变化
# copy
[root@m01 templates]# ansible nfs -m shell -a "cat /root/jinja/copy"
主机名: {{ ansible_hostname}}
ip地址: {{ansible_default_ipv4.address}} #无法识别变量
# template
主机名: nfs01
ip地址: 192.168.10.51
2.判断使用
判断和循环可存在在 .j2文件中
# 条件判断
{% if ansible_hostname == "web01" %}
state Mater
{% if ansible_hostname == "backup" %}
state Node
{% endif %}
3.循环
配置文件server.conf
10.0.0.5
10.0.0.6
10.0.0.7
10.0.0.8
10.0.0.9
10.0.0.10
{% for ip in [5,6,7,8,9,10] %} #适合不连续的
10.0.0.{{ip}}
{% endfor %}
{% for ip in range(5,11)%} #适合大范围连续的
10.0.0.{{ip}}
{% endfor %}
4.过滤器
{{ output | to_json }}
{{ output | to_yaml }} 输出对应的文本格式# to_nice_json,to_nice_yaml
#过滤相应要求的JSON或TAML格式
{{ output | from_json }}
{{ output | from_yaml }}
集群批量管理-Ans-完结篇
include文件包含
- 1个ansible剧本内容过多,==涉及到多个play(-host:web)==,可读性变弱,不方便调试.
- 于是人们想出把单个大的剧本拆分为多个,小的剧本.
- 多个小的剧本可以通过include功能合并使用.
缺点: 同级目录下存在多个yml文件、变量文件vars以及j2文件,板块较为混乱 不适合大型剧本
拆分后的文件只包含tasks后面的部分:==不包含tasks的行==
[root@m01 include]# cat 01_nfs_server.yml
- name: 01 Deploy nfs-utils,rpcbind
yum:
[root@m01 include]# cat 02_nfs_client.yml
- name: 01 Deploy nfs-utils,rpcbind
yum:
[root@m01 include]# cat 03_nfs_include.yml
---
- hosts: buckup
tasks:
- include_tasks: 01_nfs_server.yml
- hosts: web
tasks:
- include_tasks: 02_nfs_client.yml
#handlers
roles
概述
include将大型剧本模块化,但handlers、变量文件、发送配置文件(.j2)等比较混乱
roles规则:这个规范是一套剧本目录结构的要求与标准,让我们书写剧本的时候,把剧本的内容和需要的文件,按照目录要求,分门别类存储。roles的本质就是规定了1套目录结构,用于书写剧本的.
roles前提:熟练剧本模块,掌握服务流程;尽量==多使用变量==让剧本灵活性变高。
[root@m01 include]# ls
01_nfs_server.yml 02_nfs_client.yml 03_nfs_include.yml # 可能还会设计多个变量、配置文件
roles框架
如果有自定义变量 ,在同级目录下有: group_vars/all/main.yml
tasks/:存放角色的主要任务文件,可以包含多个 YAML 文件,每个文件定义一个任务。
handlers/:存放角色的处理器文件,用于处理由任务触发的事件。
templates/:存放角色使用的模板文件,可以在任务中使用 Jinja2 模板语法进行渲染。
files/:存放角色使用的普通文件,这些文件会被复制到目标主机上。
vars/:存放角色的变量文件,可以定义角色所使用的变量。
defaults/:存放角色的默认变量文件,这些变量的默认值会被其他变量覆盖。
meta/:存放角色的元数据文件,包含角色的描述信息、依赖关系等。
使用角色时,可以通过 import_role 或 include_role 导入和调用角色。
nfs案例(S+C)
Vault加密
重要配置文件、参数文件涉密,需要通过加密保证安全 ==ansible-vault ==
- ansible-vault ==encrypt== 文件 :加密文件,直接读取是编码
- ansible-vault ==create== hosts_test 创建加密文件 默认用vi打开 自己添加内容
- ansible-vault ==edit== hosts_test 编辑加密文件(直接编辑为乱码)
- ans-hoc或ansible-playbook ==--ask-vault-pass== 即可使用中解密
ansible-vault ==decryp==t 文件: 彻底解密(修改文件内容必须彻底解密):可加上==--output==参数 以其他名称另存加密文件;
ansible-vault decrypt main.yml --output=main_vaulted.yml
- ansible-vault ==view== hosts_test 查看加密文件内容 不解密
- ansible-vault ==rekey== hosts_test 更改加密文件旧密码
- 运行加密的剧本:==--vault-id @prompt==
#加密文件
[root@m01 vault]# ansible-vault
ansible-vault ansible-vault-2 ansible-vault-2.7
[root@m01 vault]# ansible-vault encrypt hosts
New Vault password:
Confirm New Vault password:
Encryption successful
[root@m01 vault]# cat hosts
$ANSIBLE_VAULT;1.1;AES256
6638363062643933656664643233356......
#不解密情况下直接使用加密文件:无法识别
#添加解密参数后:
[root@m01 vault]# ansible --ask-vault-pass -i hosts nfs -m shell -a "ps -ef"
Vault password:
192.168.10.51 | CHANGED | rc=0 >>
#将加密文件彻底解密
[root@m01 vault]# ansible-vault decrypt hosts
Vault password:
Decryption successful
#解密后才可对文件进行修改,也可直接识别和读取
--vault-password-file=vault-pass
以文件形式解密
# echo 'root' > vault-pass
# # ansible-playbook 03.debug-Registory.yml --vault-password-file=vault-pass
Galaxy
别人的Roles:第三方、官方、用户的roles
ansible-galaxy collection install
#galaxy.ansible.com/search?deprecated=false&keywords=nginx&order_by=-relevance&page=1
#官网roles
# 默认下载到家目录
ansible-galaxy collection install nginxinc.nginx_core
下载失败可选择下载 ==tarbao==
优化
常见优化
- ssh连接速度优化,关闭UseDNS,GSSAPIAuthcation....
- 不要让ansible运行交互式的命令,非要用使用命令的非交互模式.
- 需要使用ans,yum安装软件,可以自建本地yum仓库,然后ans安装.(自建yum源,自己制作的rpm包)
#ansible并发默认五台机器
-f FORKS, --forks FORKS
specify number of parallel processes to use
(default=5) #根据CPU的核心数提高需求
- 给ansible配置缓存,队列。缓存(facts)
- 给主机进行分组操作(web,nfs,backup)
- 关闭gather_facts,如果不用facts变量可以关闭,剧本中:gather_facts:false配置文件:gathering = explicit
- 关闭host,key,check一般使用密码认证的时候需要关闭,如果不关闭 ansible配置文件host_key_checking = False ==第一次ssh时的yes/no==
==安全==
生产环境下一般不是ansible节点root远程集群root,默认会关闭root的远程权限,==ansible使用的时sudo提权的用户==
- ==配置sudo提权== ans ALL=(ALL) NOPASSWD: ALL 密码是1,ss端口22
- 配合 vpn,jms一起使用
- 用户--->vpn--->jms--->ansible
- 用户密码、涉密文件、配置(bash,ansible-vault)
==ansible---sudo==
客户端
# sudoers文件提权
[root@nfs01 ~]# tail -1 /etc/sudoers
ans_sudo ALL=(ALL) NOPASSWD: ALL
# 创建此用户 密码设置为1
[root@nfs01 ~]# useradd ans_sudo
useradd: user 'ans_sudo' already exists
[root@nfs01 ~]# passwd ans_sudo
Changing password for user ans_sudo.
New password:
BAD PASSWORD: The password is a palindrome
Retype new password:
passwd: all authentication tokens updated successfully.
[ans_sudo@nfs01 root]$ sudo -l
User ans_sudo may run the following commands on nfs01:
(ALL) NOPASSWD: ALL
管理端
1.修改/etc/ansible/ansible.cfg文件:添加被管理端上的sudo用户和使用的用户(不指定默认是当前root用户/root)
2.开启sudo功能和命令 指定切换用户
3.被管理端root禁止远程登录,密钥认证需要发给sudu用户;
[root@m01 ~]# ssh-copy-id ans_sudo@192.168.10.51
ans_sudo@192.168.10.51's password:
and check to make sure that only the key(s) you wanted were added.
4.如果不使用sudo用户,需要关闭sudo以及sudo指定用户:不一定全部机器有sudo配置以及指定的用户;
5.禁用root远程登录
禁用root远程前,需要注册好普通用户,配置sudo
vim /etc/ssh/sshd_config
systemctl restart sshd
RedHat补充
模块补充
service模块
参数 | 注解 |
---|---|
state | started,stopped,restarted,reloaded(重载),enabled, |
name | 服务名 |
mapper | 启动的参数:"service_mapper_name" |
arguments | 特定启动参数:arguments: "--specific-arguments" |
- name: Reload service
service:
name: httpd
state: reloaded
- name: Enable service
service:
name: httpd
enabled: yes
# 设置服务的启动 mapper 参数:
- name: Set service mapper
service:
name: httpd
mapper: "service_mapper_name"
# 使用特定的启动参数启动服务:
- name: Start service with specific arguments
service:
name: httpd
state: started
arguments: "--specific-arguments"
ansible testB -m service -a "name=httpd enabled=yes"将testB(server3)中的httpd服务被设置为开机自动启动项
firewalld模块
参数 | 选项 | 注解 |
---|---|---|
icmp_block | 在防火墙中添加或者移除的ICMP块。 | |
icmp_bolck_inversion | 开启/关闭防火墙区域ICMP报文反转功能。 | |
==immediate== | yes or no,默认no | 配置==立即生效== |
interface | 在防火墙中添加或移除interface | |
masquerade | 在在防火墙中开启或关闭masquerade功能 | |
offline | yes or no | 是否在防火墙离线时运行此模块。 |
==permanent== | yes or no | 配置==永久添加== |
port | 在防火墙中添加或移除端口名称或端口范围。端口范围必须为PORT/PROTOCOL或PORT-PORT/PROTOCOL格式 | |
rich_rule | rich_rule添加或删除到防火墙 | |
==service== | 在防火墙中添加或移除服务名称该服务必须在==firewall-cmd --get-services==的输出中列出。 | |
source | 在防火墙中添加或移除某个来源的网络 | |
==state== | absent or disabled or enabled or present | 启用或禁用一项设置。对于端口:该端口是否接受(enabled)或拒绝(disabled)连接。状态的(present)和(absent)只能在区域级别操作中使用(即,当除了zone和state没有设置其他参数时)。 |
timeout | 默认0 | 该规则应在非永久性时生效的时间 |
zone | 添加或移除的防火墙区域。注意,可以为每个系统配置默认的区域,可能的值有block, dmz, drop, external, home, internal, public, trusted, work,public |
- name: Start firewalld service
service:
name: firewalld
state: started
- name: Stop firewalld service
service:
name: firewalld
state: stopped
- name: Restart firewalld service
service:
name: firewalld
state: restarted
#添加移除防火墙规则
- name: Add a new firewall rule
firewalld:
zone: public
service: http
permanent: yes
immediate: yes
state: present
- name: Remove a firewall rule
firewalld:
zone: public
service: http
permanent: yes
immediate: yes
state: absent
#更改区域
- name: Change zone of an interface
firewalld:
zone: public
interface: eth0
#富规则
- name: Add a rich rule
firewalld:
zone: public
rich_rule: 'rule family="ipv4" source address="192.168.0.0/24" port port=80 protocol=tcp accept'
permanent: yes
immediate: yes
state: present
#自定义服务
- name: Add a new custom service
firewalld:
zone: public
service: myservice
port: 12345/tcp
protocol: tcp
permanent: yes
immediate: yes
state: present
- firewalld:
service: https
permanent: yes
state: enabled
- firewalld:
port: 8081/tcp
permanent: yes
state: disabled
- firewalld:
port: 161-162/udp
permanent: yes
state: enabled
- firewalld:
zone: dmz
service: http
permanent: yes
state: enabled
- firewalld:
rich_rule: rule service name="ftp" audit limit value="1/m" accept
permanent: yes
state: enabled
- firewalld:
source: 192.0.2.0/24
zone: internal
state: enabled
- firewalld:
zone: trusted
interface: eth2
permanent: yes
state: enabled
- firewalld:
masquerade: yes
state: enabled
permanent: yes
zone: dmz
- firewalld:
zone: custom
state: present
permanent: yes
- firewalld:
zone: drop
state: present
permanent: yes
icmp_block_inversion: yes
- firewalld:
zone: drop
state: present
permanent: yes
icmp_block: echo-request
- name: Redirect port 443 to 8443 with Rich Rule
firewalld:
rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443
zone: public
permanent: yes
immediate: yes
state: enabled
uri模块
file模块: setype参数
确保新的或者现有的文件具有==正确的权限和SElinux类型==
[root@m01 file-module]# ansible nfs -m shell -a "ls -Z /root/redhat_ansible/file-module/testfile"
192.168.10.51 | CHANGED | rc=0 >>
-rw-r-----. user1 group1 unconfined_u:object_r:admin_home_t:s0 /root/redhat_ansible/file-module/testfile
[root@m01 file-module]# cat 02.file_samba.yml
---
- hosts: nfs
tasks:
- name: samba set
file:
path: /root/redhat_ansible/file-module/testfile
setype: samba_share_t
[root@m01 file-module]# ansible nfs -m shell -a "ls -Z /root/redhat_ansible/file-module/testfile"
192.168.10.51 | CHANGED | rc=0 >>
-rw-r-----. user1 group1 unconfined_u:object_r:samba_share_t:s0 /root/redhat_ansible/file-module/testfile
系统可能会撤销模板的更改,需要==sefcontext模板更新SELinux策略==
- name: samba set is persistently
sefcontext:
target: /root/redhat_ansible/file-module/testfile
setype: samba_share_t
state: present
滚动更新 serial
---
- hosts: web # 假设有五台机器
tasks:
serial: 2 # 一次并发2台机器
- name: Latest apache httpd
yum:
name: httpd
state: latest
notify: restart httpd
handlers:
- name: restsrt apache
service: httpd
state: restarted
若不设置serial参数,系统默认最大forks为5,即一次play执行可达五台机器的并发,五台web服务器同时进行更新并重启,web服务必定中断
使用serial参数,设定在本次play中,每次并发为2,即前2台机器更新重启前,其余三台处于正常运行状态;服务降级但不会中断。
time确定运行时间
time ansible-playbook 04.show_facts.yml
real 0m2.371s
user 0m0.366s
sys 0m1.080s
==包含和导入==
在住playbook中可导入若干其他的playbook;==import_playbook:== 静态
- name: import_playbook play1.yml
import_playbook: play1.yml
- name: import_playbook play2.yml
import_playbook: play2.yml # 可与主playbook交替使用
可在tasks中导入tasks文件:==import_tasks:== 在play执行最先预处理得到具体任务(开始之前)
tasks文件,从-name:(tasks后)开始 针对某个主机组的执行操作
[root@m01 import_tasks]# cat tasks_test.yml
- name: install apache
yum:
name: httpd
state: present
导入到playbook指定位置
---
- hosts: all
tasks:
- name: install server tools
import_tasks: tasks_test.yml
==include_tasks : 在任务到此处时读取到yml文件才开始处理== 动态
评论