自动化运维工具之Ansible

一、ansible介绍

1.ansible概述:

Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbet和Saltstack能实现的功能,Ansible基本上都可以实现。

Ansible能批量配置、部署、管理上千台主机。比如以前需要切换到每个主机上执行的一或多个操作,使用Ansible只需在固定的一台Ansible控制节点上去完成所有主机的操作。

Ansible是基于模块工作的,它只是提供了一种运行框架,它本身没有完成任务的能力,真正执行操作的是Ansible的模块, 比如copy模块用于拷贝文件到远程主机上,service模块用于管理服务的启动、停止、重启等

2.Ansible的四个组件

Inventory 主机清单(主机组):
  • Inventory 文件是 Ansible 用来描述服务器信息的配置文件,其中定义了要管理的主机及其分组。它可以是 INI 或 YAML 格式的静态文件,也可以是动态生成的。在 Inventory 文件中,主机可以被划分为不同的组,这样可以更容易地管理和引用相关联的服务器集合。例如,你可以有 'web' 组包含所有的 web 服务器,'db' 组包含所有数据库服务器等等。组内的每个主机可以使用主机名、别名或 IP 地址来标识,还可以针对每个主机设置特定的变量。

Modules 模块:
  • Modules 是 Ansible 的核心功能,它们是一些专门的插件,可以执行特定任务。例如 copy 模块用于复制文件到远程主机,file 模块用于文件管理,在远程主机上创建或删除文件,yumapt 用于在基于 RedHat 或 Debian 的系统上管理包,等等。当你在 playbooks 或是 ad-hoc 命令中调用模块时,Ansible 会在目标主机上推送模块代码并执行。

Plugins 插件:
  • Plugins 是用来扩展 Ansible 的功能的特殊脚本。它们分为很多种类型,如 Inventory Plugins、Callback Plugins、Action Plugins 等等。Inventory Plugins 可以用来创建动态的 Inventory 清单,Callback Plugins 可以用来自定义 Ansible 输出日志的格式,Action Plugins 来扩展或修改模块的行为。Plugins 非常强大,因为它们让 Ansible 的行为可以根据需要进行定制。

Playbooks 剧本(相当于脚本):

  • Playbooks 是定义在 Ansible 中自动化操作的配置文件,使用 YAML 格式编写。Playbook 可以理解为一个脚本集合,它不仅描述了要在哪些主机上执行什么操作,还说明了这些操作应该如何执行,包括任务顺序、所需参数、相关变量等。一个 playbook 可以包含多个 play,每个 play 可以针对不同的主机组执行一系列任务。Playbooks 是 Ansible 自动化的核心,可用于配置管理、应用部署、任务编排和连续的服务部署等。

总的来说,Inventory 是 Ansible 知晓要管理那些主机的地方,Modules 是实现各种管理任务的工具,Plugins 提供了扩展 Ansible 功能的能力,而 Playbooks 则是把这一切组织起来,为你的基础架构和应用按需自动化的场本。

3.Ansible的特性

特性一:
  • Ansible其中一个比较鲜明的特性Agentless,即无Agent的存在(无代理端,即无客户端),它就像普通命令一样, 并非c/s软件,也只需在某个作为控制节点的主机上安装一次Ansible即可,通常它基于ssh连接来控制远程主机,远程主机上不需要安装Ansible或其它额外的服务。

  • 使用者在使用时,在服务器终端输入命令或者playbooks,会通过预定好的规则将playbook拆解为play(一个play就是一个Linux操作),再组织成ansible可以识别的任务,调用模块和插件,根据主机清单通过SSH将临时文件发给远程的客户端执行并返回结果,执行结束后自动删除。

特性二:
  • Ansible的另一个比较鲜明的特性是它的绝大多数模块都具备幂等性(idempotence)。所谓幂等性,指的是多次操作或多次执行对系统资源的影响是一致的。

  • 比如执行 systemctl stop xxx 命令来停止服务,当发现要停止的目标服务已经处于停止状态,它什么也不会做,所以多次停止的结果仍然是停止,不会改变结果,它是幂等的,而systemctl restart xxx是非幂等的。

Ansible的很多模块在执行时都会先判断目标节点是否要执行任务,所以,可以放心大胆地让Ansible去执行任务,重复执行某个任务绝大多数时候不会产生任何副作用。

二、ansible 环境安装部署

  • 管理端ansible:192.168.160.6

  • 被管理端:192.168.160.3 192.168.160.4 192.168.160.5

管理端安装ansible:

1.yum安装epel-release和ansible

yum install -y epel-release         //先安装 epel 源,在线源安装
yum install -y ansible

2.查看ansible目录结构:

[root@michaelxct ~]# tree /etc/ansible/
/etc/ansible/
├── ansible.cfg
├── hosts
└── roles
​
1 directory, 2 files

3.配置主机清单:

第一种方法(需要免密登录):
[root@michaelxct ~] vim /etc/ansible/hosts 
#可以包含多台被管理的主机名或者IP地址,主机名需要先修改/etc/hosts文件
[webservers]
192.168.160.3
192.168.160.4
192.168.160.5
​
## [dbservers]
## 
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57
​

在 Ansible 中,主机清单(inventory)是定义你管理和自动化的所有服务器的地方。webserversdbservers是两个常见的主机组名称,它们在Ansible主机清单中代表了不同的服务器角色或组。

webservers:

  • 这个组通常包括运行Web服务器软件(如Apache, Nginx等)的主机。

  • 这些主机负责处理用户的HTTP请求并提供网页内容。

dbservers:

  • 这个组通常指的是运行数据库服务(如MySQL, PostgreSQL等)的主机。

  • 这些主机主要用于数据存储和查询功能。

第二种方法(不需要免密登录):

[root@private-172-xx-xx-xx ~]# cat test.hosts 
[all]
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
192.168.160.1
​
[all:vars]
ansible_ssh_user=root 
ansible_ssh_port=xxxx 
ansible_ssh_pass='xxxxxxxx='

在Ansible中配置主机清单时,可以将主机分类到不同的组中,以便能更方便地对特定类型的服务器执行特定的自动化任务。例如,你可能想要仅针对Web服务器群组webservers执行更新Web服务器配置文件的任务,而对数据库服务器群组dbservers执行备份数据库的任务。

4.设置免密登录:

ssh-keygen -t rsa:生成密钥文件,一路Enter即可:

[root@michaelxct ansible] ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:MUBTHGuMpKq38Rlo/X61eP0es5n7q8mNnXg4mSY1K9E root@michaelxct
The key's randomart image is:
+---[RSA 2048]----+
|     .=oo.       |
|     o =..       |
|    . . *        |
|   .   . o       |
|  .     S   .    |
| . o      .. E   |
|. = o    o oo O  |
| o + +  o oooB*B.|
|  . o.o. .  +O@Bo|
+----[SHA256]-----+
​

查看目录可以看到生成两个,id_rsa为私钥,id_rsa.pub为公钥:

[root@michaelxct ansible] cd /root/.ssh/
[root@michaelxct .ssh] ls
id_rsa  id_rsa.pub
​

修改/etc/ssh/ssh_config,开启免密交互

[root@michaelxct ~] vim /etc/ssh/ssh_config
​
# Host *
#   ForwardAgent no
#   ForwardX11 no
#   RhostsRSAAuthentication no
#   RSAAuthentication yes
#   PasswordAuthentication yes
#   HostbasedAuthentication no
#   GSSAPIAuthentication no
#   GSSAPIDelegateCredentials no
#   GSSAPIKeyExchange no
#   GSSAPITrustDNS no
#   BatchMode no
#   CheckHostIP yes
#   AddressFamily any
#   ConnectTimeout 0
StrictHostKeyChecking no
#   IdentityFile ~/.ssh/identity
#   IdentityFile ~/.ssh/id_rsa
#   IdentityFile ~/.ssh/id_dsa
#   IdentityFile ~/.ssh/id_ecdsa
#   IdentityFile ~/.ssh/id_ed25519
#   Port 22
#   Protocol 2
#   Cipher 3des
#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
#   EscapeChar ~
#   Tunnel no
#   TunnelDevice any:any
#   PermitLocalCommand no
#   VisualHostKey no
#   ProxyCommand ssh -q -W %h:%p gateway.example.com
#   RekeyLimit 1G 1h
​

修改完后重启sshd

[root@michaelxct .ssh] systemctl restart sshd

把密钥推送给其它的主机:

[root@michaelxct .ssh] ssh-copy-id root@192.168.160.3
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.160.3's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.160.3'"
and check to make sure that only the key(s) you wanted were added.

[root@michaelxct .ssh] ssh-copy-id root@192.168.160.4
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.160.4's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.160.4'"
and check to make sure that only the key(s) you wanted were added.

[root@michaelxct .ssh] ssh-copy-id root@192.168.160.5
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.160.5's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.160.5'"
and check to make sure that only the key(s) you wanted were added.

5.使用sshpass

如果有成百上千台主机,不可能一次一次输入密码,因此就需要sshpass。sshpass这个工具可以实现ssh的免交互。

安装sshpass
yum install sshpass -y
使用sshpass

sshpass选项之后指定要运行的命令。通常,该命令ssh带有参数,但也可以是任何其他命令。不过,目前SSH密码提示已硬编码为sshpass

sshpass [-f filename | -d num | -p password | -e] [options]
-p 密码 密码在命令行中给出。 
-f 文件名 密码是文件名的第一行。 
-d number number是sshpass从运行程序继承的文件描述符。从打开的文件描述符中读取密码。 
-e 密码来自环境变量"SSHPASS"。

三、ansible的使用方式:

1.Ad-hoc Commands(临时命令):

这种方式是指在命令行直接使用 ansible 命令执行单个任务。它适合于需要快速执行操作的场景,例如迅速检查一组服务器的状态或者在多台服务器上执行单一命令。Ad-hoc命令的格式通常是这样的:

   ansible [pattern] -m [module] -a [arguments]

ansible <组名> -m <模块> -a <参数列表>

  • -m 参数后面跟着的是要执行的模块名称。

  • -a 参数后面是传递给模块的参数列表,具体取决于使用的模块。

以下是一些常用的模块:

  • command:在远程服务器上执行命令,但不支持管道符和重定向等操作。

  • shell:与 command 功能类似,但支持更复杂的shell命令,包括管道、重定向等。

  • copy:用于将本地文件复制到远程主机上。

  • file:用来设置文件属性,例如权限、所有权,也可以用来创建和删除文件或目录。

  • git:用于管理git仓库,可以克隆、更新、检出特定的分支或标签。

  • user:用于管理用户账户。

  • group:用于管理用户组。

  • aptyum:分别用于基于Debian和基于RedHat的系统,管理软件包的安装、卸载、更新。

  • service:用于控制服务(服务的启动、停止、重启等)。

  • stat:获取远程主机上文件的状态信息。

  • ping:不是传统的 ICMP ping,而是用来检查远程主机是否能够被 Ansible 成功访问。

  • setup:收集远程主机的详细信息,这在动态使用变量时很有帮助。

示例:

   ansible webservers -m ping -a ''

这个例子将会向“webservers”这个组里面的所有主机发送 ping 请求,仅仅检查它们是否能够被 Ansible 访问到。

ansible <主机IP> -m <模块> -a <参数列表>: 与上一命令类似,但是这个命令是针对单个主机IP地址执行模块。它会在指定的 IP 地址的主机上执行模块。

示例:

   ansible 192.168.1.50 -m shell -a 'echo hello world'

这个例子会在 IP 地址为 192.168.1.50 的主机上执行 echo hello world 命令。

ansible <主机名> -a <参数列表>: 这个命令格式没有指定 -m 参数,默认使用的模块是 command,所以它将在指定的主机名上执行提供的命令。

示例:

   ansible server1 -a 'uptime'

这个例子会在主机名为 “server1” 的服务器上执行 uptime 命令,并显示系统的运行时长。

其中,[pattern] 表示目标主机,可以是组名、IP地址、主机名或者是清单文件中定义的一个模式。-m [module] 指定使用的模块,-a [arguments] 是传递给模块的参数。

2.Playbooks:

playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。

2.1 playbook格式

playbook由YAML语言编写。YAML语言参考了其他多种语言,包括:XML、C语言、Python、Perl等。MAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。以下为playbook常用到的YAML格式。

---
- name: Playbook名称
  hosts: 目标主机或主机组
  become: yes
  become_user: root
  vars:
    var_name: var_value
  tasks:
    - name: 任务1标题
      模块名:
        参数1: 值1
        参数2: 值2
    - name: 任务2标题
      模块名:
        参数1: 值1
        参数2: 值2

每个部分的含义:

  • ---:YAML 文档开始的标记,用于表示接下来的内容是一个 YAML 文档。

  • - name: Playbook名称:定义了 playbook 的名称。

  • hosts: 目标主机或主机组:指定了这个 playbook 将要操作的目标主机或主机组。

  • become: yesbecome_user: root:这两个选项用于指定在执行任务时要以特权用户(例如 root)身份运行。

  • vars::定义了 playbook 中可用的变量,可以在任务中使用这些变量。

  • tasks::定义了一系列任务,每个任务都是一个列表项,包含了任务的具体定义。

    • - name: 任务1标题:定义了第一个任务的标题。

    • 模块名::指定了要使用的模块(例如 copyfilecommand 等),用于执行任务操作。

    • 参数1: 值1参数2: 值2:指定了模块执行任务时的参数和对应的值。

每个任务都由一个 - 开头,后面跟着任务的具体定义,包括任务名称、模块名、模块参数等。Playbook 中可以包含多个任务,每个任务的执行顺序按照它们在文件中的顺序来执行。

2.2 playbook组成部分
  • Tasks:任务,即通过task调用ansible的模板将多个操作组织在一个playbook中运行

  • Variables:变量

  • Templates:模板

  • Handlers:处理器,当changed状态条件满足时,(notify)触发执行的操作

  • Roles:角色

常见的 Ansible 模块:

  1. apt 模块

    • 功能:用于管理基于 Debian 或 Ubuntu 的系统上的软件包。

    • 参数:

      • name:要安装、卸载或检查状态的软件包名称。

      • state:软件包的状态,可以是 present(安装)、absent(卸载)或 latest(确保是最新版本)等。

      • 其他参数如 update_cache(是否更新软件包列表)、cache_valid_time(软件包列表缓存的有效时间)等。

  2. yum 模块

    • 功能:用于管理基于 Red Hat、CentOS 或 Fedora 的系统上的软件包。

    • 参数:

      • name:要安装、卸载或检查状态的软件包名称。

      • state:软件包的状态,可以是 present(安装)、absent(卸载)或 latest(确保是最新版本)等。

      • 其他参数如 disablerepo(禁用指定的软件源)、enablerepo(启用指定的软件源)等。

  3. copy 模块

    • 功能:复制文件或目录到目标主机。

    • 参数:

      • src:源文件或目录的路径。

      • dest:目标路径,可以是文件或目录。

      • 其他参数如 mode(权限)、owner(所有者)、group(所属组)等。

  4. template 模块

    • 功能:根据模板文件生成配置文件。

    • 参数:

      • src:模板文件的路径。

      • dest:生成的目标文件路径。

      • 其他参数如 mode(权限)、owner(所有者)、group(所属组)、backup(备份旧文件)等。

  5. file 模块

    • 功能:管理文件系统上的文件或目录。

    • 参数:

      • path:文件或目录的路径。

      • state:文件或目录的状态,可以是 directory(目录)、file(文件)、absent(不存在)等。

      • 其他参数如 mode(权限)、owner(所有者)、group(所属组)、recurse(递归操作)等。

  6. lineinfile 模块

    • 功能:在文件中查找并修改特定行。

    • 参数:

      • path:文件的路径。

      • line:要添加、修改或删除的行内容。

      • state:行的状态,可以是 present(存在)、absent(不存在)、before(插入到指定行之前)等。

      • 其他参数如 insertafter(在指定行之后插入)、regexp(使用正则表达式匹配行)等。

  7. command 模块

    • 功能:执行 shell 命令。

    • 参数:

      • cmd:要执行的命令。

      • 其他参数如 chdir(命令执行的工作目录)、creates(如果文件存在则不执行命令)等。

  8. debug 模块

    • 功能:打印调试信息。

    • 参数:

      • msg:要打印的消息内容。

      • 其他参数如 var(打印变量的值)、verbosity(调试级别)等。

2.3 示例

安装git

---
- name: first play             # 定义一个 Play 的名称为 first play
  gather_facts: false          # 不进行事实信息收集,加快执行速度
  hosts: all                   # 在所有主机组中执行任务
  remote_user: root            # 使用 root 用户执行任务

  tasks:                       # 定义任务列表
    - name: test connection    # 任务名称为 test connection
      ping:                    # 使用 ping 模块测试连接

    - name: Install Git        # 任务名称为 Install Git
      yum:                     # 使用 yum 模块管理软件包
        name: git              # 要安装的软件包为 git
        state: present         # 确保软件包存在

    - name: print message      # 任务名称为 print message
      debug:                   # 使用 debug 模块打印消息
        msg: "安装git成功"      # 要打印的消息内容为 "安装git成功"

    - name: get version        # 任务名称为 get version
      command:                 # 使用 command 模块执行命令
        cmd: git --version     # 执行命令为 git --version
      register: get_version    # 将命令执行结果存储到变量 get_version 中

    - name:                     # 任务名称为空,表示这个任务不会执行任何操作
      debug:                    # 使用 debug 模块打印消息
        msg: "git的版本为:{{get_version.stdout }}"   # 打印 get_version.stdout 变量的值

运行playbook

//运行playbook
ansible-playbook test.yaml
//补充参数:
-k(–ask-pass):用来交互输入ssh密码
-K(-ask-become-pass):用来交互输入sudo密码
-u:指定用户
ansible-playbook test1.yaml --syntax-check    #检查yaml文件的语法是否正确
ansible-playbook test1.yaml --list-task       #检查tasks任务
ansible-playbook test1.yaml --list-hosts      #检查生效的主机
ansible-playbook test1.yaml --start-at-task='Install Git'     #指定从某个task开始运行

卸载git

---
- name: second play             # Playbook 名称为 second play
  gather_facts: false           # 不收集主机的事实信息
  hosts: all                    # 在所有主机上执行任务
  remote_user: root             # 远程用户为 root

  tasks:
    - name: test connection     # 任务名称为 test connection
      ping:                     # 使用 ping 模块测试主机连接

    - name: remove git          # 任务名称为 remove git
      yum:                      # 使用 yum 模块管理软件包
        name: git               # 要卸载的软件包名称为 git
        state: absent           # 将软件包状态设置为 absent,表示卸载

    - name: print message       # 任务名称为 print message
      debug:                    # 使用 debug 模块打印消息
        msg: "卸载成功"         # 要打印的消息内容为 "卸载成功"

定义、引用变量

---
- name: second play               # Playbook 名称为 second play
  hosts: all                      # 在所有主机上执行任务
  remote_user: root               # 远程用户为 root

  vars:                           # 定义变量
    - groupname: mysql            # 定义 groupname 变量,值为 mysql
    - username: nginx             # 定义 username 变量,值为 nginx

  tasks:
    - name: create group          # 任务名称为 create group
      group:                      # 使用 group 模块创建用户组
        name: "{{groupname}}"     # 使用变量 groupname 的值作为用户组名称
        system: yes               # 创建系统用户组
        gid: 306                  # 指定用户组的 GID

    - name: create user           # 任务名称为 create user
      user:                       # 使用 user 模块创建用户
        name: "{{username}}"      # 使用变量 username 的值作为用户名
        uid: 306                  # 指定用户的 UID
        group: "{{groupname}}"    # 指定用户所属的用户组

    - name: copy file             # 任务名称为 copy file
      copy:                       # 使用 copy 模块复制文件
        content: "{{ansible_default_ipv4}}"   # 使用 ansible_default_ipv4 变量的值作为文件内容
        dest: /opt/vars.txt       # 复制文件到目标路径 /opt/vars.txt

ansible-playbook test2.yaml -e "username=nginx"     #在命令行里定义变量

指定远程主机sudo切换用户

---
- hosts: dbservers                      # 应用于名为 dbservers 的主机组
  remote_user: zhangsan                 # 使用 zhangsan 用户进行远程连接
  become: yes                           # 启用特权升级(become),在 2.6 版本之前是 sudo 模块,意味着切换                                           用户运行
  become_user: root                     # 切换到 root 用户进行任务执行

  tasks:
    - name: Task Name                   # 任务名称
      module_name:                      # 模块名称
        parameter1: value1              # 模块参数1
        parameter2: value2              # 模块参数2
        ...

  
执行playbook时:ansible-playbook test3.yml -k -K 

when条件判断:

在Ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则该任务执行,否则不执行该任务。

---
- hosts: all                    # 在所有主机上执行任务
  remote_user: root             # 远程用户为 root

  tasks:
    - name: shutdown host       # 任务名称为 shutdown host
      command: /sbin/shutdown -r now    # 执行重启命令
      when: ansible_default_ipv4.address == "192.168.160.3"
      # 当 Ansible 默认的 IPv4 地址为 "192.168.160.3" 时才执行该任务
      # ansible_default_ipv4 是一个事先定义好的变量,用于获取主机的默认 IPv4 地址

    # 或者可以根据主机名来执行任务
    # - name: shutdown host
    #   command: /sbin/shutdown -r now
    #   when: inventory_hostname == "<主机名>"
    #   # 当当前主机的名称为指定的主机名时才执行该任务

迭代

---
- name: play1                          # Playbook 名称为 play1
  hosts: all                           # 在所有主机上执行任务
  gather_facts: false                  # 不收集主机的事实信息

  tasks:
    - name: create file                # 任务名称为 create file
      file:                            # 使用 file 模块创建文件
        path: "{{item}}"               # 文件路径使用循环变量 item
        state: touch                   # 创建一个空文件
      with_items:                      # 对列表中的每个元素执行任务
        - /opt/a                       # 创建 /opt/a 文件
        - /opt/b                       # 创建 /opt/b 文件
        - /opt/c                       # 创建 /opt/c 文件
        - /opt/d                       # 创建 /opt/d 文件


- name: play2                          # Playbook 名称为 play2
  hosts: all                           # 在所有主机上执行任务
  gather_facts: false                  # 不收集主机的事实信息

  vars:                                # 定义变量
    test:                              # 变量名为 test
      - /tmp/test1                     # 包含多个路径
      - /tmp/test2
      - /tmp/test3
      - /tmp/test4

  tasks:
    - name: create directories         # 任务名称为 create directories
      file:                            # 使用 file 模块创建目录
        path: "{{item}}"               # 目录路径使用循环变量 item
        state: directory               # 创建目录
      with_items: "{{test}}"           # 对变量 test 中的每个元素执行任务


- name: play3                          # Playbook 名称为 play3
  hosts: all                           # 在所有主机上执行任务
  gather_facts: false                  # 不收集主机的事实信息

  tasks:
    - name: add users                  # 任务名称为 add users
      user:                            # 使用 user 模块添加用户
        name: "{{item.name}}"          # 用户名使用循环变量 item 的 name 字段
        state: present                 # 确保用户存在
        groups: "{{item.groups}}"      # 用户所属组使用循环变量 item 的 groups 字段
      with_items:                      # 对列表中的每个元素执行任务
        - name: test1                  # 用户名为 test1,所属组为 wheel
          groups: wheel
        - name: test2                  # 用户名为 test2,所属组为 root
          groups: root
2.4 Templates模块

Jinja是基于Python的模板引擎。Template类是Jinja的一个重要组件,可以看作是一个编译过的模板文件,用来产生目标文本,传递Python的变量给模板去替换模板中的标记。

  1. 先准备一个以 .j2 为后缀的 template 模板文件,设置引用的变量

# 这是一个简单的 Nginx 配置文件模板示例

# 定义一个 HTTP 服务器
server {
    # 监听端口
    listen 80;

    # 定义服务器名
    server_name {{ server_name }};

    # 定义网站根目录
    root /var/www/html;

    # 定义访问日志和错误日志路径
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # 匹配 / 请求路径
    location / {
        # 将请求转发到后端服务器
        proxy_pass http://backend_server;
    }
}
---
- hosts: all                    # 应用于所有主机
  remote_user: root             # 使用 root 用户进行远程连接

  vars:                          # 定义变量
    - package: nginx             # 定义要安装的软件包名称为 nginx
    - service: nginx             # 定义要管理的服务名称为 nginx
    - server_name: example.com   # 定义服务器名为 example.com
    - backend_server: 127.0.0.1:8080   # 定义后端服务器地址和端口

  tasks:                         # 定义任务列表
    - name: install nginx package   # 安装 nginx 软件包
      yum:                         # 使用 yum 模块管理软件包
        name: "{{package}}"        # 安装的软件包名称为变量 package 的值
        state: latest               # 确保安装最新版本的软件包

    - name: install configure file  # 安装配置文件
      template:                     # 使用 template 模块生成配置文件
        src: nginx.conf.j2          # Nginx 配置文件的模板路径
        dest: /etc/nginx/nginx.conf # Nginx 配置文件的目标路径
      notify:                       # 在任务执行后发送通知
        - restart nginx             # 通知名为 restart nginx

    - name: create web root dir     # 创建网站根目录
      file:                          # 使用 file 模块管理文件系统
        path: /var/www/html         # 网站根目录路径
        state: directory             # 确保是一个目录

    - name: start nginx server       # 启动 Nginx 服务
      service:                       # 使用 service 模块管理系统服务
        name: "{{service}}"          # 服务名称为变量 service 的值
        enabled: true                 # 设置服务为开机自启动
        state: started                # 启动服务

  handlers:                         # 定义处理程序列表
    - name: restart nginx           # 重新启动 Nginx 服务的处理程序
      service:                       # 使用 service 模块管理系统服务
        name: "{{service}}"          # 服务名称为变量 service 的值
        state: restarted              # 重新启动服务
2.5 tags模块
  1. playbook 标记

    • 作用:为整个 Playbook 添加标记,用于控制整个 Playbook 的执行。

    • 示例用法:tags: - playbook,在运行 Playbook 时使用 --tags="playbook" 参数来运行整个 Playbook。

  2. only 标记

    • 作用:表示这个任务只有在使用了 --tags="only" 参数时才会执行。

    • 示例用法:tags: - only,用于标记只在特定条件下执行的任务。

  3. 自定义标记

    • 作用:根据具体需求自定义的标记,用于区分和控制不同类型的任务。

    • 示例用法:tags: - tag_name,例如将相关的安装任务标记为 install,配置任务标记为 config 等。

  4. 排除标记

    • 作用:用于排除特定的标记,表示只执行没有被排除标记的任务。

    • 示例用法:tags: - tag_name:!skip,表示只执行没有被排除标记 skip 的任务。

  5. 交集标记

    • 作用:表示同时满足两个标记的任务才会执行,即取两个标记的交集。

    • 示例用法:tags: - tag_name:&install,表示同时满足 tag_nameinstall 标记的任务才会执行。

  6. 并集标记

    • 作用:表示满足任意一个标记的任务都会执行,即取两个标记的并集。

    • 示例用法:tags: - tag_name:|config,表示满足 tag_name 或者 config 标记的任务都会执行。

---
- hosts: all
  remote_user: root
  tasks:
    - name: Task 1
      command: echo "This is Task 1"
    - name: Task 2
      command: echo "This is Task 2"
  tags:
    - playbook
    
ansible-playbook your_playbook.yaml --tags task1,task2
2.6 Roles模块

在 Ansible 中,Roles 是一种组织和重用任务、变量和文件结构的方法。Roles 模块使得管理复杂的 Playbooks 变得更加容易和模块化,有助于将任务组织成逻辑单元,并且可以在多个 Playbooks 中重复使用。

一个典型的 Ansible Roles 目录结构如下:

pythonCopy code
roles/
├── myrole/
│   ├── defaults/       # 默认变量
│   │   └── main.yml
│   ├── files/          # 需要拷贝到目标主机的文件
│   ├── handlers/       # 处理程序(handlers)
│   │   └── main.yml
│   ├── meta/           # 元数据信息
│   │   └── main.yml
│   ├── tasks/          # 任务
│   │   └── main.yml
│   ├── templates/      # 模板文件
│   ├── tests/          # 测试相关文件
│   ├── vars/           # 变量文件
│   │   └── main.yml
│   └── README.md       # 角色说明文档

在这个目录结构中,各个目录的作用如下:

  • defaults/:存放默认变量。

  • files/:存放需要拷贝到目标主机的文件。

  • handlers/:存放处理程序(handlers)。

  • meta/:存放角色的元数据信息,如依赖关系。

  • tasks/:存放任务。

  • templates/:存放模板文件。

  • tests/:存放测试相关文件。

  • vars/:存放变量文件。

  1. 使用 Roles: 要在 Playbooks 中使用 Roles,可以通过 roles 关键字引入角色,例如:

    yamlCopy code
    ---
    - name: Playbook using roles
      hosts: all
      roles:
        - myrole   # 引入名为 myrole 的角色
  2. 角色的主要文件

    • defaults/main.yml:定义默认变量。

    • handlers/main.yml:定义处理程序(handlers)。

    • meta/main.yml:定义角色的元数据信息,如依赖关系。

    • tasks/main.yml:定义任务。

    • templates/:存放模板文件。

    • vars/main.yml:定义变量文件。

  3. 角色的元数据信息: 在 meta/main.yml 中可以定义角色的元数据信息,如依赖关系和角色的作者信息等。示例:

    yamlCopy code
    ---
    dependencies:
      - { role: common }
    author: John Doe
  4. 调用角色的变量和任务: 在 Playbooks 或者其他角色中可以调用角色的变量和任务,例如:

    yamlCopy code
    - name: Include role variables
      include_vars: path/to/myrole/defaults/main.yml
    
    - name: Run role tasks
      include_tasks: path/to/myrole/tasks/main.yml

5.示例:nginx

首先,创建一个名为 webserver 的角色目录结构,并添加相应的文件:

roles/
└── webserver/
    ├── defaults/
    │   └── main.yml   # 默认变量文件
    ├── tasks/
    │   └── main.yml   # 任务文件
    ├── templates/
    │   └── nginx.conf.j2   # Nginx 配置文件模板
    └── meta/
        └── main.yml   # 元数据信息

接下来,分别编辑这些文件:

  1. roles/webserver/defaults/main.yml:定义默认变量,例如 Nginx 的安装路径等。

    yamlCopy code
    ---
    nginx_install_path: /etc/nginx
    nginx_config_path: /etc/nginx/nginx.conf
  2. roles/webserver/tasks/main.yml:定义角色的任务。

    yamlCopy code
    ---
    - name: Install Nginx
      package:
        name: nginx
        state: present
    
    - name: Copy Nginx configuration file
      template:
        src: nginx.conf.j2
        dest: "{{ nginx_config_path }}"
      notify:
        - restart nginx
  3. roles/webserver/templates/nginx.conf.j2:Nginx 配置文件模板。

    nginxCopy code
    # Nginx 配置文件模板示例
    
    # 定义一个 HTTP 服务器
    server {
        # 监听端口
        listen 80;
    
        # 定义服务器名
        server_name {{ server_name }};
    
        # 定义网站根目录
        root {{ nginx_install_path }}/html;
    
        # 定义访问日志和错误日志路径
        access_log {{ nginx_install_path }}/logs/access.log;
        error_log {{ nginx_install_path }}/logs/error.log;
    
        # 匹配 / 请求路径
        location / {
            # 将请求转发到后端服务器
            proxy_pass http://backend_server;
        }
    }
  4. roles/webserver/meta/main.yml:定义角色的元数据信息。

    yamlCopy code
    ---
    dependencies: []   # 角色依赖关系,如果有其他角色依赖需要在这里添加

5.playbook

---
- name: Deploy Nginx web server
  hosts: webservers   # 在哪些主机上执行角色
  become: yes   # 使用 sudo 运行任务
  roles:
    - webserver   # 引入 webserver 角色

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动化运维工具——ansible是一款开源的IT自动化工具,广泛应用于软件部署、配置管理和任务协同等领域。它的最大特点是简单易用、功能强大且跨平台。 首先,ansible具有简单易用的特点。它使用简单的YAML语言作为配置文件,无需编写复杂的脚本。用户只需要简单地定义主机和操作即可完成任务的执行。这使得即便是非开发人员,也能轻松上手使用ansible进行自动化管理。 其次,ansible功能强大。它支持广泛的操作系统、云平台和网络设备,并提供了丰富的模块化功能。通过在任务中使用ansible的模块,我们可以实现系统配置、软件安装、文件传输等各种常见操作。此外,ansible不仅支持并发执行任务,还能够将任务分组执行,并提供了强大的变量和条件控制功能。 再次,ansible跨平台。无论是在Linux、Unix还是Windows系统上,ansible都能够良好地运行。此外,它还支持云平台,如AWS、Azure等,以及网络设备,如Cisco、Juniper等。这使得ansible成为一个非常灵活的自动化运维工具,能够满足各种不同环境和需求的自动化管理。 最后,ansible还具有良好的社区支持。ansible拥有庞大的用户社区和活跃的开发者社区,有大量的文档、示例和插件可供参考和使用。这使得我们在使用ansible时能够获得快速解答和支持,同时也能够从社区中学习到更多的技巧和经验。 总而言之,ansible是一款简单易用、功能强大且跨平台的自动化运维工具。它在软件部署、配置管理和任务协同等方面具有广泛的应用,并且得到了良好的社区支持。无论是企业还是个人,都可以通过ansible来提高工作效率和自动化管理水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值