标签搜索
MemoryCloud Blog

Ansible追加

kennedy
2024-03-24 / 0 评论 / 26 阅读 / 正在检测是否收录...

部署密钥认证

免密码登录、双机互信

一些服务在使用前要求做密钥认证,管理轻松。手动写批量管理脚本。

==注:密钥认证是单向==

密钥对
公钥:public key 一般以.pub结尾
私钥:private key
角色主机名IP
管理机m01192.168.10.50
被管理机nfs01192.168.10.51
被管理机web01192.168.10.52
被管理机backup192.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:剧本模式---把操作写出脚本,可重复运行这个脚本

76bba3e2671f69d83e36496e7f501b3

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 删除 (如果是目录递归删除目录)
modemode=755 创建并修改权限 mode: 0640
owneronwer=root
groupgroup=root
recurse创建文件,如果存在,更新文件时间戳
forceforce参数:当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 目标;被管理端的目录文件
backupbackup=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-reloadyes是否从新加载对应的服务管理配置文件
自定义配置文件
#开启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指定软件包名字;可以指定==多个==,用 “ , ”分割。
stateinstalled 安装(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
nameyum源中的名字 [Centos]
descriptionyum源中的注释说明 对应的 是name的内容
baseurlyum源中 baseurl 下载地址
enabled是否启动这个源 yes/no
gpgcheck是否启动gpgcheck功能 no(校验官方,许可等)
file指定yum源文件 自动添加.repo 默认与模块名字一致

与普通yum文件区别

[name]name=centos 默认为源文件的文件名
name=centosdescription="" 描述
enabled=1enabled=yes
gpgcheck=0gpgcheck=no

用户管理

user用户管理:useradd
group用户组管理:groupadd

1.user模块

user模块
name用户名
uid指定uid
group指定用户组,用于事先创建好了用户组 通过选项指定
shell指定命令解释器
create_home是否创建家目录(yes/no)
statepresent 添加
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
statepresent 添加
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从新挂载

44867bf203dc34c8be21187ef5fd938

38ce827cb91b293a2e6c745d895fbd2

定时任务cron

用于管理系统的定时任务,替代了crontab -e功能

cron模块说明
name定时任务名字(必加),对应下面==注释==内容
minute分钟 minute="/2"
hour小时
day日期
month月份
week周几
job指定命令或脚本(定向到空) job="/sbin/ntpdate ntp1.aliyum.com &>/dev/null"
statepresent 添加定时任务(默认)
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
共同点批量管理,使用模块批量管理,使用模块
区别重复调用不方便重复调用
应用场景部署服务,多个步骤任务测试模块,临时性任务

eb1cb3a35149364e9f9bd6ff7d1c642

[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

剧本使用:

11

集群批量管理-流程控制-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) 无需手动修改==

e2d3fce311029ac7d46b812bd75f87f

  • 文件必须以 .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文件,板块较为混乱 不适合大型剧本

ef11d5f2f6677b266084876a839b799

拆分后的文件只包含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框架

841fd6885e6b21c9474fb95b0df7b08

如果有自定义变量 ,在同级目录下有: 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......
#不解密情况下直接使用加密文件:无法识别

42e3c98dc0999b3805a140873f75839

#添加解密参数后:
[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

f1422140b49d0cbd78ce94da39eb8da

# 默认下载到家目录
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)

180f07847125b9763c59469360d712e

2.开启sudo功能和命令 指定切换用户

image-20240318091011854

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

828ec68ae5026fe94c1b41b4cfd9a36

RedHat补充

模块补充

service模块

参数注解
statestarted,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功能
offlineyes 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文件才开始处理== 动态

0

评论

博主关闭了所有页面的评论