Ansible服务实现自动化运维

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除

目录

一、Ansible介绍与安装

二、设置主机清单

三、运行临时命令

四、剧本文件实战

五、创建及使用角色

1、加载系统内置角色

2、从外部获取角色

3、创建新的角色

​六、创建和使用逻辑卷

七、判断主机组名

八、管理文件属性

九、管理密码库文件

致谢


一、Ansible介绍与安装

Ansible是一款开源的资源管理工具,是目前运维自动化工具中最简单、容易上手的优秀软件。

用户可以通过它自动化的部署应用程序来实现IT基础架构 ,例如对服务器进行++初始化配置、安全基线配置、更新和打补丁++都是简单容易的。虽然相比于Chef、PuppetSaltstack等CS架构的自动化工具来讲,Ansible的执行性能并不是最高的,但是由于其基于的是SSH远程会话协议,无需客户端程序只要知道受管主机的账号密码,就能直接用SSH协议进行远程控制,因此使用起来优势很明显。

Ansible服务专用术语对照表:

术语 中文 含义
Control node 控制节点 指的是安装了Ansible服务的主机,也被称为Ansible控制端,主要是用来发布运行任务、调用功能模块对其他主机进行批量控制
Managed nodes 受控节点 指的是被Ansible服务所管理的主机,也被称为受控主机或客户端,是模块命令的被执行对象
Inventory 主机清单 指的是受控节点的列表 ,可以是++IP地址、主机名称或者域名++
Modules 模块 指的是上文提到的特定功能代码,默认自带有上千款功能模块,在Ansible Galaxy有超多可供选择
Task 任务 指的是Ansible客户端上面要被执行的操作
Playbook 剧本 指的是通过YAML语言编写的可重复执行的任务列表,把常做的操作写入到剧本文件中,下次可以直接重复执行一遍
Roles 角色 从Ansible 1.2版本开始引入的新特性,用于结构化的组织Playbook,通过调用角色实现一连串的功能

被Ansible服务所管理的主机是不需要安装客户端的,因为SSH协议是Linux系统的标配,因此直接上手控制就行。服务器上面也不用每次都重复开启服务程序,而是可以用ansible命令直接调用模块进行控制。

Ansible服务程序默认不在RHEL 8系统的镜像文件中,而是需要从"Extra Packages for Enterprise Linux"扩展软件包仓库获取,简称为EPEL安装源

第1步 :将虚拟机的网络适配器---++网络连接选项调整为桥接模式++,并设置系统的网卡成DHCP自动获取模式;

大多数情况下只要把虚拟机设置成桥接模式,且Linux系统的网卡信息保持跟物理机相同,再重启网卡服务,那么就可以连接外部网络了,不放心的话再通过ping命令进行测试:

cs 复制代码
 [root@Linux ~]# systemctl restart NetworkManager
 [root@Linux ~]# ping -c 4 www.baidu.com

第2步 :++下载epel仓库++;

cs 复制代码
 [root@Linux ~]# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm

第3步 :++安装++

cs 复制代码
 [root@Linux ~]# yum install ansible -y

安装完毕后,Ansible服务以及默认启动;使用"--version"参数可以看到服务的版本及配置信息

cs 复制代码
 [root@Linux ~]# ansible --version
 ansible [core 2.16.3]

二、设置主机清单

初次使用Ansible服务可能会遇到明明参数已经修改了,但是却不生效的情况;因为Ansible服务的主配置文件存在优先级的顺序关系,默认存放在**/etc/ansible目录中的主配置文件实际优先级最低**,如果在当前目录或用户家目录中也同样存放有一份配置文件,那么则是以自己新建立的为准,具体优先级顺序如表16-2所示。

优先级 文件位置
./ansible.cfg
~/.ansible.cfg
/etc/ansible/ansible.cfg

既然Ansible服务是用于实现主机批量自动化控制的管理工具,若要管理的是上千台等,那么主机清单lnventory)就帮大忙了;用户可以预先把要管理的主机IP地址写入到++/etc/ansible/hosts文件中++,后续再执行ansible命令执行动作就自动包含这些主机了;例如要管理5台主机;其IP:

操作系统 IP地址 功能用途
RHEL 8 192.168.1.11 dev
RHEL 8 192.168.1.12 test
RHEL 8 192.168.1.13 prod
RHEL 8 192.168.1.14 prod
RHEL 8 192.168.1.15 balancers

也可以用其他Linux系统;主机清单文件/etc/ansible/hosts中默认存在大量注释信息,建议删除;

cs 复制代码
 [root@Linux ~]# vim /etc/ansible/hosts 
 192.168.1.11
 192.168.1.12
 192.168.1.13
 192.168.1.14
 192.168.1.15

我们分别为这五台主机规划功能,有++开发机(dev)、测试机(test)、产品机(prod)和负载均衡机(balancers)++。继续修改:

cs 复制代码
 [root@Linux ~]# vim /etc/ansible/hosts 
 [dev]
 192.168.1.11
 [test]
 192.168.1.12
 [prod]
 192.168.1.13
 192.168.1.14
 [balancers]
 192.168.1.15

主机清单文件修改后的是会立即生效的,一般常用"++ansible-inventory --graph++"命令以结构化的方式显示出受管节点主机信息;

cs 复制代码
 [root@Linux ~]# ansible-inventory --graph
 @all:
   |--@ungrouped:
   |--@dev:
   |  |--192.168.1.11
   |--@test:
   |  |--192.168.1.12
   |--@prod:
   |  |--192.168.1.13
   |  |--192.168.1.14
   |--@balancers:
   |  |--192.168.1.15

说过Ansible服务是基于SSH协议进行的自动化控制,这是前提条件;sshd服务在初次连接时会要求用户接受一次对方主机的指纹信息,并输入受管节点的主机账号和密码;

cs 复制代码
 [root@Linux ~]# ssh 192.168.1.11
 The authenticity of host '192.168.1.11 (192.168.1.11)' can't be established.
 ECDSA key fingerprint is SHA256:5giF6ehqviQpcIu/KbjNPPosFfGJ+gWox1mddwC+FIM.
 Are you sure you want to continue connecting (yes/no/[fingerprint])? y
 Please type 'yes', 'no' or the fingerprint: yes
 Warning: Permanently added '192.168.1.11' (ECDSA) to the list of known hosts.
 root@192.168.1.11's password: 
 Last failed login: Thu Jul 11 04:39:01 CST 2024 from 192.168.1.10 on ssh:notty
 There was 1 failed login attempt since the last successful login.
 Last login: Thu Jul 11 04:37:35 2024 from 192.168.1.157

如果每次执行操作都要输入受管主机的密码,是比较麻烦的事情;Ansible服务有了解决办法,见以下变量

参数 作用
ansible_ssh_host 受管主机名
ansible_ssh_port 端口号
ansible_ssh_user 默认账号
ansible_ssh_pass 默认密码
ansible_shell_type Shell终端类型

因此用户只需要将对应的变量及信息填写到主机清单文件中,在执行任务时便会自动的对账号密码进行匹配;

cs 复制代码
[root@Linux ~]# vim /etc/ansible/hosts 
[dev]
192.168.1.11
[test]
192.168.1.12
[prod]
192.168.1.13
192.168.1.14
[balancers]
192.168.1.15
[all:vars]
ansible_user=root
ansible_password=123456

打开/etc/ssh/ssh_config,修改以下配置项,设置成++不需要SSH协议的指纹认证++;

cs 复制代码
[root@Linux ~]# vim /etc/ssh/ssh_config
...
#   ConnectTimeout 0
   StrictHostKeyChecking no		# 修改此项

三、运行临时命令

Ansible服务强大之处在于只需要一个命令,便可以操控千万台的主机节点,ansible命令便是得力的工具之一。用户所使用的Ansible服务实际只是一个框架,能够完成工作的是模块化功能代码,常用的模块大致二十余个;

模块名称 模块作用
ping 检查受管节点主机网络是否能够联通
yum 安装、更新及卸载软件包
yum_repository 管理主机的软件仓库配置文件
template 复制模板文件到受管节点主机
copy 新建、修改及复制文件
user 创建、修改及删除用户
group 创建、修改及删除用户组
service 启动、关闭及查看服务状态
get_url 从网络中下载文件
file 设置文件权限及创建快捷方式
cron 添加、修改及删除计划任务
command 直接执行用户指定的命令
shell 直接执行用户指定的命令(支持特殊字符)
debug 输出调试或报错信息
mount 挂载硬盘设备文件
filesystem 格式化硬盘设备文件
lineinfile 通过正则表达式修改文件内容
setup 收集受管节点主机上的系统及变量信息
firewalld 添加、修改及删除防火墙策略
lvg 管理主机的物理卷及卷组设备
lvol 管理主机的逻辑卷设备

ansible 是用于执行临时任务的命令,也就是执行后即结束,不同于Playbook剧本文件的可重复性。使用ansible命令时必须指明受管丰机节点的信息,如果已经设置过主机清单文件 (/etc/ansible/hosts)则可以写a参数来代指全体受管节点,或用dev、test等主机组名称来代指某一组的主机节点。

语法:"++ansible 受管主机节点 -m 模块名称 [-a 模块参数]++",常见参数如下;"-a"是要传递给模块的参数,只有极简单功能的模块才不需要额外参数,因此,"-m"与"-a"参数大多同时出现

参数 作用
-k 手动输入SSH协议密码
-i 指定主机清单文件
-m 指定要使用的模块名
-M 指定要使用的模块路径
-S 使用su命令
-T 设置SSH协议连接超时时间
-a 设置传递给模块的参数
--version 查看版本信息
-h 帮助信息

使用ansible-doc命令查找模块使用方法及参数;

cs 复制代码
[root@Linux ~]# ansible-doc -l
ansible.builtin.add_host   Add a host (and alternatively a group) to the ansible-playbook in-memory inventory                        
ansible.builtin.apt       Manages apt-packages                                       ansible.builtin.apt_key   Add or remove an apt key                                   ansible.builtin.apt_repository     Add and remove APT repositories               ansible.builtin.assemble           Assemble configuration files from fragments       ...

一般情况,难通过名称来判别一个模块的作用,只能参考后面的介绍信息或平时积累。例如下面随机查看一个模块的详细信息,ansible-doc会在屏幕显出它的作用、可用参数及实例等;

cs 复制代码
[root@Linux ~]# ansible-doc a10_server
> COMMUNITY.NETWORK.A10_SERVER    (/usr/lib/python3.12/site-packages/ansible_collections/community/network/plugins/modules/a10_server.py)

        Manage SLB (Server Load Balancer) server objects on A10 Networks devices via aXAPIv2.
...

前面已经写好了主机清单,接下来测试连通性,可以ansible命令直接针对所有主机调用ping模块,不需要增加额外的参数,返回值若为SUCCESS则代表当前主机在线;

cs 复制代码
[root@Linux ~]# ansible all -m ping
192.168.1.11 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.1.12 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.0.4 port 22: No route to host",
    "unreachable": true
}

一下子就能知道所有主机的情况。除了使用**"-m"参数直接指定模块名称** ,还可以使用**"-a"将参数传递给模块**,让功能更加高级,更好的贴合当前生产需求。

例如:yum_repository模块的作用是管理主机的软件仓库,能够添加、修改及删除软件仓库的配置信息,参数相对复杂。遇到这种情况建议先使用ansible-doc命令对其进行了解,尤其最下面的EXAMPLES结构段会有对该模块的实例,有着非常好的参考价值;

cs 复制代码
[root@Linux ~]# ansible-doc yum_repository
> ANSIBLE.BUILTIN.YUM_REPOSITORY    (/usr/lib/python3.12/site-packages/ansible/modules/yum_repository.py)

        Add or remove YUM repositories in RPM-based Linux distributions. If you wish to update an existing repository definition use [community.general.ini_file]
        instead.

ADDED IN: version 2.1 of ansible-core

OPTIONS (= is mandatory):

- async
        If set to `true' Yum will download packages and metadata from this repo in parallel, if possible.
        In ansible-core 2.11, 2.12, and 2.13 the default value is `true'.
        This option has been deprecated in RHEL 8. If you're using one of the versions listed above, you can set this option to None to avoid passing an unknown
        configuration option.
        default: null
        type: bool
...
EXAMPLES:

- name: Add repository
  ansible.builtin.yum_repository:
    name: epel
    description: EPEL YUM repo
    baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/

- name: Add multiple repositories into the same file (1/2)
  ansible.builtin.yum_repository:
    name: epel
    description: EPEL YUM repo
    file: external_repos
    baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
    gpgcheck: no
...

发现与此前学过在/etc/yum.repos.d/目录中的配置文件基本相似,现在想为主机清单中所有服务器新增一个如下所示的软件仓库,怎么做?

仓库名称 EX294_BASE
仓库描述 EX294 base software
仓库地址 file:///media/cdrom/BaseOS
GPG签名 启用
GPG密钥文件 file:///media/cdrom/RPM-GPG-KEY-redhat-release

对照EXAMPLE实例段,++逐一将需求值和参数对应填写++ ,标准格式是用-a参数后接整体参数,用单引号圈起,而各个参数字段的值则用双引号圈起,是最严谨的写法。执行后出现CHANGED字样信息代表修改已经成功:

cs 复制代码
[root@Linux ~]# ansible all -m yum_repository -a 'name="EX294_BASE" description="EX294 base software" baseurl="file://media/cdrom/BaseOS" gpgcheck=yes enabled=1 gpgkey="file:///media/cdrom/RPM-GPG-KEY-redhat-release"'
192.168.1.11 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "repo": "EX294_BASE",
    "state": "present"
}

命令执行成功后,可以到主机清单中任意服务器上查看到新建成功的软件仓库配置文件;

cs 复制代码
[root@localhost ~]# vim /etc/yum.repos.d/EX294_BASE.repo 
[EX294_BASE]
baseurl = file://media/cdrom/BaseOS
enabled = 1
gpgcheck = 1
gpgkey = file:///media/cdrom/RPM-GPG-KEY-redhat-release
name = EX294 base software

四、剧本文件实战

Ansible服务 中允许用户根据需求,在类似于Shell脚本的模式下编写出一套自动化运维的脚本,然后由程序白动的、重复的执行,大大的提高了工作效率;

Ansible服务的Playbook剧本文件采用++YAML语言编写++ ,有着强制性的格式规范,通过空格将不同信息分组,因此有时会因一两个空格错位而导致报错,需要万分小心。YAML文件开头需要先写三个减号--- ,多个分组信息需要间隔一致才能执行,上下也要对齐,后缀名一般为.yml 。在执行后会在屏幕上输出运行界面,内容会依据不同工作而变化,但绿色均代表成功黄色代表执行成功并进行了修改 ,而红色则代表执行失败

Playbook剧本文件的结构由四部分组成--target、variable、task、handler++target部分++ 用于定义要执行剧本的主机节点范围++variable部分++ 用于定义剧本执行时要用的变量++tasK部分++ 用于定义将在远程主机上执行的任务列表++handler部分++ 用于定义执行完成后需要调用的后续任务

YAML语言编写的Ansible剧本文件会按照从上至下的顺序自动运行;

安装和更新软件需要使用yum模块,先查看帮助信息中的实例:

cs 复制代码
[root@Linux ~]# ansible-doc yum
> ANSIBLE.BUILTIN.YUM    (/usr/lib/python3.12/site-packages/ansible/modules/yum.py)

        Installs, upgrade, downgrades, removes, and lists packages and groups with the `yum' package manager. This module only works on Python 2. If you require Python
        3 support see the [ansible.builtin.dnf] module.

ADDED IN: historical

  * note: This module has a corresponding action plugin.
...
EXAMPLES:

- name: Install the latest version of Apache
  ansible.builtin.yum:
    name: httpd
    state: latest

现在知道了yum模块的使用方法和格式了,接下来进行编写。初次编写Playbook剧本文件,注意格式,模块及格式时间,否则出现参数一模一样却不能执行的情况;

其中name字段代表此项Play(动作)的名字,可自行命名,没有限制;hosts字段代表要在哪些主机节点上执行该剧本,多个主机之间用逗号间隔,若需要对全部主机进行操作则用all参数。task字段用于定义要执行的任务,每一个任务都要有一个独立的name字段进行命名,并且每个任务的name字段和模块都要严格上下对齐,参数要单独缩进;

cs 复制代码
[root@Linux ~]# cat packages.yml 
---
- name: 安装软件包
  hosts: dev,test,prod
  tasks:
          - name: one
            yum:
                    name: mariadb
                    state: latest
[root@Linux ~]# 

确认无误后就可以用ansible-playbook命令来运行这个剧本文件了:

cs 复制代码
[root@Linux ~]# ansible-playbook packages.yml 

PLAY [安装软件包] ***********************************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [192.168.1.11]
fatal: [10.0.0.4]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.0.4 port 22: No route to host", "unreachable": true}

TASK [one] ******************************************************************************************************************************************************************************************************
fatal: [192.168.1.12]: FAILED! => {"changed": false, "msg": "Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error...

PLAY RECAP ******************************************************************************************************************************************************************************************************
192.168.1.11                   : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
192.168.1.12                  : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

执行成功后主要观察最下方的输出信息,ok和change代表执行及修改成功。如果遇到unreachable或faild大约0的情况,建议手动检查下剧本是否在所有主机中都正确运行了,以及有无安装失败的情况。正确执行后,随机切换到一个主机节点,再次安装mariadb软件包会提示已经存在;

cs 复制代码
[root@localhost ~]# dnf install mariadb
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
Package 1:mariadb-5.5.68-1.el7.x86_64 already installed and latest version
Nothing to do

五、创建及使用角色

日常编写Playbook的工作会让剧本内容越来越长,不利于阅读和维护,而且还无法让其他Playbook灵活的调用其中的功能代码。++角色功能(roles)++ 用于层次化、结构性的组织剧本。角色功能通过++分别把变量、文件、任务、模块及处理器配置放在各个独立的目录中,然后对其进行便捷加载的一种机制++ 。简单来说,角色功能是把常用的一些功能"类模块化",然后用的时候加载即可。

类似编程中的封装技术、将具体的功能封装起来,用户不仅可以方便调用,甚至不用理解原理也可使用。

角色的好处就在于其组织成了一个简洁的、可重复调用的抽象对象 ,用户可以把注意力放到Plavbook的大局上,统筹各个关键性任务,只有在需要时才去深入了解细节。角色的获取有三种方法,分别是加载系统内置的从外部环境获取 的以及自行创建的

1、加载系统内置角色

使用RHEL系统内置角色,是一种不需要联网就能实现的功能。用户只需要配置好软件仓库的配置文件,然后安装包含系统角色的软件包rhel-system-roles,随后便可以在系统中找到它们了,以及能够使用Playbook剧本文件进行调用。

cs 复制代码
[root@Linux ~]# yum install -y rhel-system-roles
Updating Subscription Management repositories.
Last metadata expiration check: 0:22:40 ago on Thu 11 Jul 2024 02:52:35 PM CST.
Dependencies resolved.
...
Complete!

安装完毕后,使用**++ansible-galaxy list++命令**查看RHEL 8系统中有哪些自带的角色可用;

cs 复制代码
[root@Linux ~]# ansible-galaxy list
# /usr/share/ansible/roles
- rhel-system-roles.podman, (unknown version)
- linux-system-roles.ad_integration, (unknown version)
- rhel-system-roles.postfix, (unknown version)
- linux-system-roles.bootloader, (unknown version)
- rhel-system-roles.postgresql, (unknown version)
- linux-system-roles.certificate, (unknown version)
- linux-system-roles.cockpit, (unknown version)
...

它们的主要功能如下:

角色名称 作用
rhel-system-roles.kdump 配置kdump崩溃恢复服务
rhel-system-roles.network 配置网络接口
rhel-system-roles.selinux 配置SELinux策略及模式
rhel-system-roles.timesync 配置网络时间协议
rhel-system-roles.postfix 配置邮件传输服务
rhel-system-roles.firewall 配置防火墙服务
rhel-system-roles.tuned 配置系统调优选项

以rhel-system-roles.timesync角色为例,它用于设置系统的时间和NTP服务,让主机能够同步准确的时间信息。Plavbook剧本模板文件存放在/usr/share/doc/rhel-system-roles/目录中,可以复制过来修改使用:

cs 复制代码
[root@Linux timesync]# cp /usr/share/doc/rhel-system-roles/timesync/example-single-pool-playbook.yml timesync.yml

NTP服务器是用于计算机时间同步 的一种协议。目前常用的是由国际快速授时服务提供的pool.ntp.org 。在复制来的剧本模板文件中,删除掉多余的代码,将NTP服务器的地址填写到timesync ntp servers变量的hostname字段中即可,变量参数含义如下,稍后timesync角色就会自动为用户配置参数信息了;

参数 作用
hostname NTP服务器主机名
iburst 启用快速同步
cs 复制代码
[root@Linux timesync]# vim timesync.yml 
---
- name: Example with single pool
  hosts: all
  vars:
    timesync_ntp_servers:
      - hostname: 2.pool.ntp.org
        pool: true
        iburst: true
  roles:
    - rhel-system-roles.timesync

2、从外部获取角色

Ansible Galaxy是Ansible的官方社群服务,用于共享角色和功能代码,用户可以自由的在网站上共享和下载Ansible角色,是管理和使用角色的不二之选。如图;Ansible Galaxy官网中左侧有三个功能选项,分别是首页(HOME)、搜索(Search)以及社区(Community) ,点击Search按钮进入到搜索界面中,用nginx网站服务为例进行搜索,即可找到官网源发布的角色信息,如图16.5所示。

当点击nginx角色进入到详情页面后,会有这个项目的软件版本、评分、下载次数 等简介信息,在Installation字段能看到安装方式如图16-6所示。在保持虚拟机能够连接外网的前提下,可以按网页提示的命令进行安装。

这时如果需要使用这个角色,可以在服务器联网的状态下直接按照"ansible-galaxy instal 角色名称"的命令格式进行自动获取:

cs 复制代码
[root@Linux timesync]# ansible-galaxy install nginxinc.nginx
Starting galaxy role install process
- downloading role 'nginx', owned by nginxinc
- downloading role from https://github.com/nginxinc/ansible-role-nginx/archive/0.24.1.tar.gz
- extracting nginxinc.nginx to /root/.ansible/roles/nginxinc.nginx
- nginxinc.nginx (0.24.1) was installed successfully

执行完毕后再次查看系统已有的角色,便找到nginx角色信息了;

cs 复制代码
[root@Linux timesync]# ansible-galaxy list
# /root/.ansible/roles
- nginxinc.nginx, 0.24.1
# /usr/share/ansible/roles
- rhel-system-roles.podman, (unknown version)
- linux-system-roles.ad_integration, (unknown version)
...

还存在一些特殊情况,一:国内访问Ansible官网存在不稳定情况。二:某位作者将作品上传到了自己的网站,或除Ansible Galaxy官网以外的网站。这种情况手动编写一个YAML语言格式的文件,指明链接和角色名称,再用"-r"参数进行加载;

cs 复制代码
[root@Linux timesync]#  nginx.yml 
---
- src: https://www.linuxprobe.com/Software/nginxinc-nginx_core-0.3.0.tar.gz
  name: nginx-core

使用ansible-qalaxy命令的"-r"参数加载这个文件,即可查看到新角色信息了

cs 复制代码
[root@Linux timesync]# ansible-galaxy install -r nginx.yml 
Starting galaxy role install process
- downloading role from https://www.linuxprobe.com/Software/nginxinc-nginx_core-0.3.0.tar.gz
- extracting nginx-core to /root/.ansible/roles/nginx-core
- nginx-core was installed successfully
[root@Linux timesync]# ansible-galaxy list
# /root/.ansible/roles
- nginxinc.nginx, 0.24.1
- nginx-core, (unknown version)
# /usr/share/ansible/roles
- rhel-system-roles.podman, (unknown version)
- linux-system-roles.ad_integration, (unknown version)
- rhel-system-roles.postfix, (unknown version)

3、创建新的角色

++可自行创建符合工作需求的新角色信息,定制化的编写工作能够更好的贴合生产环境实际情况++;接下来创建一个名称为apache的新角色信息,它能够帮助我们自动的安装、运行httpd网站服务,设置防火墙允许规则及根据每个主机生成独立的index.html首页文件,让用户调用后就能享受到一条龙的部署网站服务;

根据主配置文件第68行所定义的角色保存路径,如果用户新建的角色信息不在规定目录内,使用ansible-galaxy list命令则是无法找到的。因此需要手动填写下新角色目录的路径,或是进入到/etc/ansible/roles目录内再进行创建,为了避免后期角色信息过于分散导致不好管理,还是决定在默认目录下进行创建,不再修改。

创建一个新角色信息使用"init"参数,且建立成功后便会在当前目录下生成出一个新的目录:

cs 复制代码
​
[root@Linux timesync]# cd /etc/ansible/roles
[root@Linux roles]# ansible-galaxy init apache
- Role apache was created successfully
[root@Linux roles]# ls
apache

​

此时的apache即是角色名称,也是用于存在角色信息的目录名称,切换进入看到目录结构:

cs 复制代码
[root@Linux roles]# cd apache
[root@Linux apache]# ls
defaults  files  handlers  meta  README.md  tasks  templates  tests  vars

创建新的角色最关键的便是对目录结构的理解,通俗来说就是要把正确的信息放入到正确的目录中,这样调用角色时才能有正确的效果。角色信息对应的目录结构及含义如下:

目录 含义
defaults 包含角色变量的默认值(优先级低)
files 包含角色执行tasks任务时做引用的静态文件
handlers 包含角色的处理程序定义
meta 包含角色的作者、许可证、频台和依赖关系等信息
tasks 包含角色所执行的任务
templates 包含角色任务所使用的Jinja2模板
tests 包含用于测试角色的剧本文件
vars 包含角色变量的默认值(优先级高)

第1步 :打开编写用于定义角色任务的tasks/main.yml文件;该文件不需要定义要执行的主机组列表,因为后面会编写Playbook剧本进行单独调用,此时应先对apache角色能做的事情有个明确的思路,调用角色后yml文件会按照从上到下的顺序自动执行;

  • 安装httpd网站服务
  • 运行httpd网站服务,并加入到开机启动项中
  • 配置防火墙放行http网站协议
  • 根据每台主机的变量值,生成不同的主页文件

先写出第一个任务:

cs 复制代码
[root@Linux apache]# vim tasks/main.yml 
---
- name: one
  yum:
          name: httpd
          state: latest

第2步 :++使用service模块启动httpd网站服务程序++,并加入到启动项中,保证能够一直为用户提供服务。可以先用ansible-doc命令查看下帮助和实例信息;

cs 复制代码
[root@Linux apache]# ansible-doc service
> ANSIBLE.BUILTIN.SERVICE    (/usr/lib/python3.12/site-packages/ansible/modules/service.py)

        Controls services on remote hosts. Supported init systems include BSD init, OpenRC, SysV, Solaris SMF, systemd, upstart. This module acts as a proxy to the
        underlying service manager module. While all arguments will be passed to the underlying module, not all modules support the same arguments. This documentation
        only covers the minimum intersection of module arguments that all service manager modules support. This module is a proxy for multiple more specific service
        manager modules (such as [ansible.builtin.systemd] and [ansible.builtin.sysvinit]). This allows management of a heterogeneous environment of machines without
        creating a specific task for each service manager. The module to be executed is determined by the `use' option, which defaults to the service manager
        discovered by [ansible.builtin.setup].  If [ansible.builtin.setup] was not yet run, this module may run it. For Windows targets, use the
        [ansible.windows.win_service] module instead.
...
EXAMPLES:

- name: Start service httpd, if not started
  ansible.builtin.service:
    name: httpd
    state: started

- name: Enable service httpd, and not touch the state
  ansible.builtin.service:
    name: httpd
    enabled: yes

发现,默认的EXAMPLES示例用的就是httpd网站服务,通过输出信息可得知启动服务为"state: started "参数,而加入到开机启动项则是"enabled: ves"参数。继续编写:

cs 复制代码
[root@Linux apache]# vim tasks/main.yml 
---
- name: one
  yum:
          name: httpd
          state: latest
- name: two
  service:
          name: httpd
          state: started
          enabled: yes

第3步 :配置防火墙放行允许策略,让其他主机可以正常访问。配置防火墙使用firewalld模块,同样也先看下帮助示例:

cs 复制代码
[root@Linux apache]# ansible-doc firewalld
> ANSIBLE.POSIX.FIREWALLD    (/usr/lib/python3.12/site-packages/ansible_collections/ansible/posix/plugins/modules/firewalld.py)

        This module allows for addition or deletion of services and ports (either TCP or UDP) in either running or permanent firewalld rules.
...
- name: permit traffic in default zone for https service
  ansible.posix.firewalld:
    service: https
    permanent: true
    state: enabled

- name: do not permit traffic in default zone on port 8081/tcp
  ansible.posix.firewalld:
    port: 8081/tcp
    permanent: true
    state: disabled

依据输出信息可得知,firewald模块设置防火墙策略中,++指定协议名称++ 为"service: http "参数,++放行该协议++ 为"state: enabled '参数,++设置为永久生效++ 为"permanent: yes "参数,当前也能++立即生效++ 为"immediate: yes"参数。继续编写:

cs 复制代码
[root@Linux apache]# cat tasks/main.yml 
---
- name: one
  yum:
          name: httpd
          state: latest
- name: two
  service:
          name: httpd
          state: started
          enabled: yes
- name: three
  firewalld:
          service: http
          permanent: yes
          state: enabled
          immediate: yes

第4步++让每个主机显示的首页内容均不同++ 。常规的模块都是这样査一个、写一个就能搞定,为了增加难度再提出个新需求,能否让每个主机上运行的htpd网站服务都有不同的内容,例如显示当前服务器的主机名及!P地址呢?这样的话就要用到template模块及Jinja2技术了。

template模块的使用方法依然用ansible-doc命令进行查询,示例部分有很大帮助:

cs 复制代码
[root@Linux apache]# ansible-doc template
> ANSIBLE.BUILTIN.TEMPLATE    (/usr/lib/python3.12/site-packages/ansible/modules/template.py)

        Templates are processed by the Jinja2 templating language <http://jinja.pocoo.org/docs/>. Documentation on the template formatting can be found in the Template
        Designer Documentation <http://jinja.pocoo.org/docs/templates/>. Additional variables listed below can be used in templates. `ansible_managed' (configurable
        via the `defaults' section of `ansible.cfg') contains a string which can be used to describe the template name, host, modification time of the template file
        and the owner uid. `template_host' contains the node name of the template's machine. `template_uid' is the numeric user id of the owner. `template_path' is the
        path of the template. `template_fullpath' is the absolute path of the template. `template_destpath' is the path of the template on the remote system (added in
        2.8). `template_run_date' is the date that the template was rendered.
...
EXAMPLES:

- name: Template a file to /etc/file.conf
  ansible.builtin.template:
    src: /mytemplates/foo.j2
    dest: /etc/file.conf
    owner: bin
    group: wheel
    mode: '0644'

从template模块的输出信息中可得知,这是一个用于复制文件模板的模块 ,能够把文件从Ansible服务器复制到受管主机上,"src"参数 用于定义本地文件的路径"dest"参数 用于定义复制到受管主机的文件路径 ,而owner、group、mode参数选择性的设置文件归属及权限信息

正常来说复制文件的操作是直接进行的,受管主机节点上会获取到一个与Ansible服务器上一摸一样的文件,但有些时候想让每台客户端根据自身系统情况产生不同的文件信息,这样就需要使用到jinja2技术了,文件后缀是.j2结尾。继续编写:

cs 复制代码
[root@Linux apache]# vim tasks/main.yml 
---
- name: one
  yum:
          name: httpd
          state: latest
- name: two
  service:
          name: httpd
          state: started
          enabled: yes
- name: three
  firewalld:
          service: http
          permanent: yes
          state: enabled
          immediate: yes
- name: four
  template:
          src: index.html.j2
          dest: /var/www/html/index.html

Jinja2 是Python语言中一个被广泛使用的模板引擎 ,能够让受管主机根据自身变量而产生出不同的文件内容

例如想要让每个网站的输出信息值为"welcome to 主机名 on 主机地址 ";这难点主要是査询到对应的变量名称,主机名及地址所对应的值保存在哪里?可以用setup模块进行查询

cs 复制代码
[root@Linux apache]# ansible-doc setup
> ANSIBLE.BUILTIN.SETUP    (/usr/lib/python3.12/site-packages/ansible/modules/setup.py)

        This module is automatically called by playbooks to gather useful variables about remote hosts that can be used in playbooks. It can also be executed directly
        by `/usr/bin/ansible' to check what variables are available to a host. Ansible provides many `facts' about the system, automatically. This module is also
        supported for Windows targets.
...

++setup模块++ 的作用是自动收集受管主机上的变量信息 ,用**-a参数**追加fiter指令可以对收集来的进行进行二次过滤,语法格式为

cs 复制代码
ansible all -m setup -a 'filter="*关键字*"'

Fuly Qualified Domain Name 即完全限定主机名,简称FQDN,用于在逻辑上准确表示出主机的位置,也常常被作为主机名的完全表达形式,比/etc/hostname文件中所定义的主机名更加严谨和准确。通过输出信息可得知,ansible fqdn变量保存有主机名称,随后再进行下一步操作:

cs 复制代码
[root@Linux apache]# ansible all -m setup -a 'filter="*fqdn*"'
192.168.1.11 | SUCCESS => {
    "ansible_facts": {
        "ansible_fqdn": "localhost.localdomain",
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}
...

用于定制**主机地址的变量可以用"ip"**作为关键词进行检索,能够看到在ansible a ipv4 addresses变量中的值是我们想要的信息;如果想输出IPV6级别的地址则可用ansible all ipv6 addresses变量;

cs 复制代码
[root@Linux apache]# ansible all -m setup -a 'filter="*ip*"'
192.168.1.11 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.1.11",
            "192.168.122.1"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::20c:29ff:fe39:6cf4"
        ],
        "ansible_default_ipv4": {
            "address": "192.168.1.11",
            "alias": "ens33",
            "broadcast": "10.0.0.255",
            "gateway": "10.0.0.254",
            "interface": "ens33",
            "macaddress": "00:0c:29:39:6c:f4",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.1.1",
            "prefix": "24",
            "type": "ether"
        },
   	...
    },
    "changed": false
}
...

在确认了++主机名++ 与++IP地址++所对应的具体变量名称后,在角色所对应的templates目录内新建一个与上面template模块参数相同的文件名称(index.html.j2)。jinja2在调用变量值时,格式为在变量名称的两侧格加两个大括号,编写完成即可;

cs 复制代码
[root@Linux apache]# vim templates/index.html.j2 
Welcome to {{ ansible_fqdn }} on {{ ansible_all_ipv4_addresses }}

最后编写一个用于调用apache角色的yml文件,以及执行它。

cs 复制代码
[root@Linux apache]# cd ~
[root@Linux ~]# vim roles.yml 
---
- name: 调用自建角色
  hosts: all
  roles:
          - apache
[root@Linux ~]# ansible-playbook roles.yml 

PLAY [调用自建角色] ************************************************************************************

TASK [Gathering Facts] ************************************************************************************
ok: [192.168.1.11]
fatal: [192.168.1.12]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.1.12 port 22: No route to host", "unreachable": true}
...

TASK [apache : one] ************************************************************************************
192.168.1.11                   : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.12                   : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

执行完毕后,在浏览器中随机输入几个主机的IP地址,即可访问到包含主机FQDN完全限定主机名和IP地址的网页了;

六、创建和使用逻辑卷

创建一个能批量、自动管理LVM逻辑卷设备的Playbook,能够大大提高对硬盘设备的管理效率,不仅如此,更能避免由于手动创建所带来的错误。

例如想要在每个受管主机上都创建出一个名称叫做data的逻辑卷设备,大小为150M,归属于research卷组。如果创建成功,则进一步用ext4文件系统进行格式化操作,若创建失败,则给用户输出一条报错提醒,以便排查原因,

这种情况下,使用Ansible剧本方式比用Shell脚本优势大很多;一:Ansible模块化的功能让操作更标准,只要过程无报错,那么便会依据远程主机的系统版本及配置自动做出判断和操作,不用担心系统变化而导致命令失败;二:Ansible服务在执行剧本脚本文件时会进行判断,若文件或该设备被创建过,或是某个动作(play)已经被执行过,则绝不会再重复的执行,而Shell脚本可能导致设备被重复格式化,导致数据丢失;

首先在两台prod组的主机上分别添加一块硬盘设备,大小为20G,类型为SCSl,其余选项默认;

回忆所学习过的LVM逻辑卷的知识,我们应该让Plavbook剧本文件依次创建PV物理卷、VG卷组及LV逻辑卷。先需要使用lvq模块让设备支持逻辑卷技术,并创建出一个名为research的卷组,帮助信息如下:

cs 复制代码
[root@Linux ~]# ansible-doc lvg
> COMMUNITY.GENERAL.LVG    (/usr/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/lvg.py)

        This module creates, removes or resizes volume groups.
...
EXAMPLES:

- name: Create a volume group on top of /dev/sda1 with physical extent size = 32MB
  community.general.lvg:
    vg: vg.services
    pvs: /dev/sda1
    pesize: 32

- name: Create a volume group on top of /dev/sdb with physical extent size = 128KiB
  community.general.lvg:
    vg: vg.services
    pvs: /dev/sdb
    pesize: 128K
...

通过输出信息可得知,创建PV和VG卷组的lvg模块总共有三个必备参数 。其中**++"vg"参数++** 用于定义卷组的名称 ,++"pvs"参数++ 用于指定硬盘设备名称 ,而**++"pesize"参数++** 用于确定最终卷组的容量大小,可以用PE个数亦可用容量值进行指定。这样的话先创建出一个由/dev/sdb设备组成的名称为research,大小为150M的卷组设备;

cs 复制代码
[root@Linux ~]# vim lv.yml 
---
- name: 创建和使用逻辑卷
  hosts: all
  tasks:
          - name: one
            lvg:
                    vg: research
                    pvs: /dev/sdb
                    pesize: 150M

由于刚刚仅在prod组的两台主机上添加了新硬盘设备文件,因此稍后执行时其余三台主机节点会提示未创建成功,属于正常情况。接下来便是用Ivol模块来创建出LVM逻辑卷设备了,先查看下模块帮助信息:

cs 复制代码
[root@Linux ~]# ansible-doc lvol
> COMMUNITY.GENERAL.LVOL    (/usr/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/lvol.py)

        This module creates, removes or resizes logical volumes.
...
EXAMPLES:

- name: Create a logical volume of 512m
  community.general.lvol:
    vg: firefly
    lv: test
    size: 512

- name: Create a logical volume of 512m with disks /dev/sda and /dev/sdb
  community.general.lvol:
    vg: firefly
    lv: test
    size: 512
    pvs:
      - /dev/sda
      - /dev/sdb
...

通过输出信息可得知,Ivol确定是用于创建LVM逻辑卷设备的模块 ,其中**++"vg"参数++** 用于指定卷组名称++"lv"参数++ 用于指定逻辑卷名称 ,而**++"size"参数++** 则用于指定最终逻辑卷设备的容量大小,不加单位默认为M。填写好参数,创建出一个大小为150M,归属于research卷组,名称为data的逻辑卷设备:

cs 复制代码
[root@Linux ~]# vim lv.yml 
---
- name: 创建和使用逻辑卷
  hosts: all
  tasks:
          - name: one
            lvg:
                    vg: research
                    pvs: /dev/sdb
                    pesize: 150M
          - name: two
            lvol:
                    vg: research
                    lv: data
                    size: 150M

对于设备的文件系统格式化操作使用filesystem模块完成,帮助信息如下;

cs 复制代码
[root@Linux ~]# ansible-doc filesystem
> COMMUNITY.GENERAL.FILESYSTEM    (/usr/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/filesystem.py)

        This module creates a filesystem.
...
EXAMPLES:

- name: Create a ext2 filesystem on /dev/sdb1
  community.general.filesystem:
    fstype: ext2
    dev: /dev/sdb1
...

filesystem模块的参数真是简练,参数**++"fstype"++** 用于指定文件系统的格式化类型++"dev"参数++ 用于指定要格式化的设备文件路径。继续编写:

cs 复制代码
[root@Linux ~]# vim lv.yml 
---
- name: 创建和使用逻辑卷
  hosts: all
  tasks:
          - name: one
            lvg:
                    vg: research
                    pvs: /dev/sdb
                    pesize: 150M
          - name: two
            lvol:
                    vg: research
                    lv: data
                    size: 150M
          - name: three
            filesystem:
                    fstype: ext4
                    dev: /dev/research/data

这样,LVM逻辑卷就能自动创建好了,但如果失败了怎么办:这时用到if条件句进行判断:

首先将上述的三个模块命令用block操作符 作为一个整体,相当于是对这三个模块执行结果作为一个整体判断。然后使用rescue操作符进行救援 ,只有block块中的模块执行失败了才会调用rescue中的救援模块。其中debug模块的msg参数 的作用是如果block中的模块执行失败则输出一条信息到屏幕,给予用户一定的提醒作用。完成编写后是这个样子的:

cs 复制代码
[root@Linux ~]# cat lv.yml 
---
- name: 创建和使用逻辑卷
  hosts: all
  tasks:
          - block:
                  - name: one
                    lvg:
                            vg: research
                            pvs: /dev/sdb
                            pesize: 150M
                  - name: two
                    lvol:
                            vg: research
                            lv: data
                            size: 150M
                  - name: three
                    filesystem:
                            fstype: ext4
                            dev: /dev/research/data
            rescue:
                   - debug:
                           msg: "Could not create logical volumne of that size"

YAML对语言有硬性要求,rescue是对block内的模块进行救援的功能代码,因此必须对齐,确认无误后执行;

cs 复制代码
[root@Linux ~]# ansible-playbook lv.yml 

PLAY [创建和使用逻辑卷] *************************************************************************************

TASK [Gathering Facts] *************************************************************************************
ok: [192.168.1.11]
... 
192.168.1.11                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   

现在登录到登录到主机节点上查看,找到新建的逻辑卷设备信息:

cs 复制代码
[root@localhost ~]# lvdisplay 
  --- Logical volume ---
  LV Path                /dev/research/data
  LV Name                data
  VG Name                research
  LV UUID                fnP9PJ-mWaQ-LBWd-AP1O-nryF-5NSw-qm48Az
  LV Write Access        read/write
  LV Creation host, time localhost.localdomain, 2024-07-12 01:20:39 +0800
  LV Status              available
  # open                 0
  LV Size                150.00 MiB
  Current LE             1
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:2

七、判断主机组名

在前面Playbook剧本实验中,我们可以让不同的主机根据自身不同的变量值信息而生成不同的网站首页文件,但却无法对某个主机组进行针对操作。

在每个客户端中都会有一个叫做"inventory_hostname "的变量,用于**++定义着每个主机节点主机所对应的Ansible服务主机组名称++**,也就是在/etc/ansible/hosts文件中所对应的分组信息,例如dev、test、prod、balancers。

"inventory hostname "是Ansible服务中的魔法变量 ,意味着无法用setup模块直接进行査询 ,诸如"ansible all -m setup -a'filter="关键词 ""的命令将对它失效。魔法变量需要在执行Playbook剧本文件时的[Gathering facts]阶段进行搜集,直接查询是看不到的,而只能在剧本文件中进行调用。

获得了存储主机组名称的变量名称,接下来实践,需求如下:

  • 若主机节点在dev分组中,则修改/etc/issue文件内容为"Development"
  • 若主机节点在test分组中,则修改/etc/issue文件内容为"Test"
  • 若主机节点在prod分组中,则修改/etc/issue文件内容为"Production"

第1步 :++新建、修改及复制文件为copy模块++,先查询下copy模块的帮助信息:

cs 复制代码
[root@Linux ~]# ansible-doc copy
> ANSIBLE.BUILTIN.COPY    (/usr/lib/python3.12/site-packages/ansible/modules/copy.py)

        The [ansible.builtin.copy] module copies a file or a directory structure from the local or remote machine to a location on the remote machine. File system
        meta-information (permissions, ownership, etc.) may be set, even when the file or directory already exists on the target system. Some meta-information may be
        copied on request. Get meta-information with the [ansible.builtin.stat] module. Set meta-information with the [ansible.builtin.file] module. Use the
        [ansible.builtin.fetch] module to copy files from remote locations to the local box. If you need variable interpolation in copied files, use the
        [ansible.builtin.template] module. Using a variable with the `content' parameter produces unpredictable results. For Windows targets, use the
        [ansible.windows.win_copy] module instead.
...
EXAMPLES:

- name: Copy file with owner and permissions
  ansible.builtin.copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: '0644'
    
- name: Copy using inline content
  ansible.builtin.copy:
    content: '# This file was moved to /etc/other.conf'
    dest: /etc/mine.conf

在输出信息中列举了两种管理文件内容的示例,第一是对于文件的复制行为 ,第二是通过"content"参数定义内容,"dest"参数指定新建文件的名称,显然第二种更加符合当前的实验场景。编写剧本文件如下:

cs 复制代码
[root@Linux ~]# cat issue.yml 
---
- name: 修改文件内容
  hosts: all
  tasks:
          - name: one
            copy:
                    content: 'Development'
                    dest: /etc/issue
          - name: two
            copy:
                    content: 'Test'
                    dest: /etc/issue
          - name: three
            copy:
                    content: 'Production'
                    dest: /etc/issue

但我们应该依据"inventory hostname"变量中的值进行判断when是进行判断的语法,需要在每个Play下方进行判断,只有满足条件才会执行:

cs 复制代码
[root@Linux ~]# cat issue.yml 
---
- name: 修改文件内容
  hosts: all
  tasks:
          - name: one
            copy:
                    content: 'Development'
                    dest: /etc/issue
            when: "inventory_hostname in groups.dev"
          - name: two
            copy:
                    content: 'Test'
                    dest: /etc/issue
            when: "inventory_hostname in groups.text"
          - name: three
            copy:
                    content: 'Production'
                    dest: /etc/issue
            when: "inventory_hostname in groups.prod"

执行Playbook剧本文件,过程中可清晰的看出由于when语法的作用,未在指定主机组中的节点将被skipping(跳过):

cs 复制代码
[root@Linux ~]# ansible-playbook issue.yml 

PLAY [修改文件内容] *************************************************************************************

TASK [Gathering Facts] *************************************************************************************
ok: [192.168.1.11]
...
192.168.1.11                   : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

登录到dev组的192.168.10.20主机节点上,查看文件内容;

cs 复制代码
[root@Linux ~]# cat /etc/issue
Development

登录到test组的192.168.10.20主机节点上,查看文件内容;

cs 复制代码
[root@Linux ~]# cat /etc/issue
Test

登录到prod组的192.168.10.20主机节点上,查看文件内容;

cs 复制代码
[root@Linux ~]# cat /etc/issue
Production

八、管理文件属性

学习Playbook剧本语法的目的是满足日常的工作需求,能够把重复的事情写入到脚本中,然后在批量的执行下去,提高运维的效率。其中创建文件、管理权限及做快捷方式一定是几乎每天都被使用到的技能。

Ansible将对文件管理常用的功能都合并到了file模块

cs 复制代码
[root@Linux ~]# ansible-doc file
> ANSIBLE.BUILTIN.FILE    (/usr/lib/python3.12/site-packages/ansible/modules/file.py)

        Set attributes of files, directories, or symlinks and their targets. Alternatively, remove files, symlinks or directories. Many other modules support the same
        options as the [ansible.builtin.file] module - including [ansible.builtin.copy], [ansible.builtin.template], and [ansible.builtin.assemble]. For Windows
        targets, use the [ansible.windows.win_file] module instead.
...
EXAMPLES:

- name: Change file ownership, group and permissions
  ansible.builtin.file:
    path: /etc/foo.conf
    owner: foo
    group: foo
    mode: '0644'

- name: Create a symbolic link
  ansible.builtin.file:
    src: /file/to/link/to
    dest: /path/to/symlink
    owner: foo
    group: foo
    state: link

- name: Create a directory if it does not exist
  ansible.builtin.file:
    path: /etc/some_directory
    state: directory
    mode: '0755'

- name: Remove file (delete file)
  ansible.builtin.file:
    path: /etc/foo.txt
    state: absent

了解到:"path"参数定义文件的路径、"owner"参数定义文件所有者、"group"参数定义文件所有组、"mode"参数定义文件权限、"src"参数定义源文件的路径、"dest"参数定义目标文件的路径、"state"参数定义文件类型;

开始实验:

  • 创建出一个名为/inuxprobe的新目录,所有者及所有组均为root管理员身份;
  • 设置所有者和所有组拥有对文件的完全控制权,而其他人则只有阅读和执行权限;
  • 给予SBIT特殊权限;
  • 仅在dev主机组主机节点实施;

在此编写Playbook剧本文件时,"host"参数一直是all,即全体主机,这次改为仅对dev主机组生效;编写模块代码如下:

cs 复制代码
[root@Linux ~]# cat chmod.yml 
---
- name: 管理文件属性
  hosts: dev
  tasks:
          - name: one
            file:
                    path: /linuxprobe
                    state: directory
                    owner: root
                    group: root
                    mode: '2775'
          - name: two
            file:
                    src: /linuxprobe
                    dest: /linuxcool
                    state: link

执行结果:

cs 复制代码
                    state: link
[root@Linux ~]# ansible-playbook chmod.yml 

PLAY [管理文件属性] ***********************************************************************************

TASK [Gathering Facts] ************************************************************************************
ok: [10.0.0.3]

TASK [one] ************************************************************************************
changed: [10.0.0.3]

TASK [two] ************************************************************************************
changed: [10.0.0.3]

PLAY RECAP ************************************************************************************
10.0.0.3                   : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

进入dev组的主机中,查看到/linuxprobe目录及/linuxcool快捷方式已经被顺利创建,实验完成;

cs 复制代码
[root@localhost ~]# ls -ld /linuxprobe
drwxrwsr-x. 2 root root 6 Jul 12 03:12 /linuxprobe
[root@localhost ~]# ls -ld /linuxcool
lrwxrwxrwx. 1 root root 11 Jul 12 03:12 /linuxcool -> /linuxprobe

九、管理密码库文件

"Vault "实现了对密码、剧本等敏感信息进行加密 ,甚至可以加密变量名称和变量值 ,保护了数据;使用ansible-vault命令 可以**对内容的新建(create)、加密(encrypt)、解密(decrypt)、修改口令(rekey)及查看(view)**等功能;

第1步 :++创建出一个名为locker.yml的配置文件++,其中保存有两个变量值:

cs 复制代码
[root@Linux ~]# cat locker.yml 
---
pw_developer: Imadev
pw_manager: Imamgr

第2步 :++使用ansible-vault命令对文件进行加密++,需要每次输入密码比较麻烦,因此还应新建出一个用于保存密码值的文本文件,让ansible-vault进行自动调用。为了保证数据的安全性,新建密码文件后将权限设置为600,仅管理员可读可写;

cs 复制代码
[root@Linux ~]# vim /root/secret.txt
hahahahaha
[root@Linux ~]# chmod 600 /root/secret.txt 

在Ansible服务的主配置文件中进行调用,在第140行的**"vault password file"参数后**指定密码值保存的文件路径;

cs 复制代码
[root@Linux ~]# vim /etc/ansible/ansible.cfg
...
vault_password_file = /root/secret.txt

第3步 :设置好了密码文件路径,Ansible服务便会自动进行加载,用户不再需要每次加密或解密时都重复输入密码值了。例如加密刚刚创建的locker.yml文件时,只需要使用"encrypt"参数即可:

cs 复制代码
[root@Linux ~]# ansible-vault encrypt locker.yml 
Encryption successful

加密过后的文件将使用AES 256格式进行加密,非常安全;查看到加密后的内容为:

cs 复制代码
[root@Linux ~]# cat locker.yml 
$ANSIBLE_VAULT;1.1;AES256
396530393734636434353...

那如果不想用原始密码了,也可以手动对文件进行"rekey"修改密码操作,同时应结合"--ask-vaulit-pass"参数进行修改,否则Ansible服务会因接收不到用户输入的旧密码值,而拒绝新的密码变更请求:

cs 复制代码
[root@Linux ~]# ansible-vault rekey --ask-vault-pass locker.yml 
Vault password: #输入旧的密码 
New Vault password: # 输入新的密码
Confirm New Vault password: # 再次输入
Rekey successful

第4步 :如果想查看和修改加密文件中的内容。对于已经加密过的文件,需要使用ansible-vault命令的**"edit"参数** 进行修改随后用**"view"参数即可查看到修改后的内容**。编辑操作默认使用Vim编辑器作为修改工具,请修改完毕后记得wq保存退出:

cs 复制代码
[root@Linux ~]# ansible-vault edit locker.yml 
---
pw_developer: Imadev
pw_manager: Imamgr
pw_production: Imaprod

最后再用"view"参数进行查看:

cs 复制代码
[root@Linux ~]# ansible-vault view locker.yml 
Vault password: 
---
pw_developer: Imadev
pw_manager: Imamgr
pw_production: Imaprod

致谢

在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。

学习永无止境,让我们共同进步!!

相关推荐
yaosheng_VALVE16 分钟前
稀硫酸介质中 V 型球阀的材质选择与选型要点-耀圣
运维·spring cloud·自动化·intellij-idea·材质·1024程序员节
看山还是山,看水还是。1 小时前
Redis 配置
运维·数据库·redis·安全·缓存·测试覆盖率
扣得君1 小时前
C++20 Coroutine Echo Server
运维·服务器·c++20
keep__go1 小时前
Linux 批量配置互信
linux·运维·服务器·数据库·shell
矛取矛求1 小时前
Linux中给普通账户一次性提权
linux·运维·服务器
幸运的星竹2 小时前
使用pytest+openpyxl做接口自动化遇到的问题
python·自动化·pytest
death bell3 小时前
Docker基础概念
运维·docker·容器
ʚɞ4963 小时前
应用程序部署(IIS的相关使用,sql server的相关使用)
运维·服务器
少陽君3 小时前
服务器显卡和桌面pc显卡有什么不同
运维·服务器
daizikui3 小时前
Linux文件目录命令
linux·运维·服务器