进击的 Ansible(二):如何快速搞定生产环境 Ansible 项目布局?
Tips:与前文 《进击的 Ansible(一):Ansible 快速入门》 一样,本文使用的 Ansible 版本 2.5.4,项目演示环境 MacOS。由于 Ansible 项目开发活跃版本更新快,很多 API 接口不向后兼容,所以对照本文实践时请确保所用版本一致。
学完前文《进击的 Ansible(一):Ansible 快速入门》后,用来发布单体项目绰绰有余。但是实际生产环境中一个服务往往有多个组件,比如部署大数据服务时,常常需要部署一个“大数据全家桶”:Hadoop、 Zookeeper、 Hive、 Mysql、 Flink 等。这时仅靠前文中的知识就有点捉襟见肘了,繁多的 yaml 文件和其他配置文件依赖关系复杂,如果不能正确地划分目录组织项目结构,对于后期维护非常不利。所以今天的文章着重解决一下这个问题:如何科学正确地划分 Ansible 应用的目录结构?
把 Ansible 视为一种编程语言
首先要树立这样一个观念:“把 Ansible 视为一种编程语言”。我们可以将 Ansible 理解为专门用来管理自动化发布的 DSL,它的基本语法规则约等于 yaml 语言规则,诸如 synchronize、pip、template 等。同时 Ansible 模块可等价为语言的内置函数或内置包,也就是编写 playbook 就是在写 Ansible 这门语言的代码块。如此,只要我们沿着编程语言的思路去理解 Ansible,很多疑惑会迎刃而解:比如 Ansible 支持变量,模块 when 就是编程语言的流程控制语句 if, 模块 loop 或 with_* 就是编程语言中的循环迭代语句 for 或 while。
使用编程语言进行项目开发的过程中,我们是如何降低项目复杂度的?当然是进行“模块化”。不同的功能封装到不同的包或文件中,这样构成一个业务功能的最小单位我们称之为“模块”。在项目的入口文件中,我们通过 import (Python、Golang 等语言中使用此关键字) 或 require (Node.js 等语言使用此关键字)等关键字把需要的模块载入进来,然后就可以进行业务逻辑上的编排。
这样做的优点显而易见,一个模块是一个业务功能的具体实现,当后期有修改的需求时只需要修改相关的模块即可,这正是 SOLID 原则中的 “SRP” (单一职责原则) 所提倡的。此外,模块化还支持像“搭积木”一样根据业务需求灵活地组织业务流程,这样就能最大限度地复用当前模块,这也符合编程原则中的 “DRY” (Don't Repeat Yourself)。
因此在我们将 Ansible 视为一门编程语言(DSL)的现在,我们可以发现在 Ansible 文档中用 Roles 表示“模块”这个概念,用 import_tasks、include_tasks 等表示 import 这个概念。这里说一个题外话,不知道有没有人觉得 Ansible 中发明的“playbook”、“roles” 等直译成“剧本”、“角色”的概念让人摸不着头脑?
至关重要的概念:Roles
现在我们树立了“Roles = 模块”的概念。我们在看一下文档中对 Roles 的定义,丰富一下细节:
Roles let you automatically load related vars, files, tasks, handlers, and other Ansible artifacts based on a known file structure. After you group your content in roles, you can easily reuse them and share them with other users.
“角色允许您基于已知的文件结构自动加载相关的变量、文件、任务、处理程序和其他Ansible工件。在将内容按角色分组后,可以轻松地重用它们并与其他用户共享它们。”
直白来讲就是 Roles 是对变量、文件、任务等的封装,目的是为了模块重用。
如何使用 Roles?
在软件设计范式的最佳实践中有一条叫做 “约定大于配置”,简单来讲就是“软件中做了一些前提性假设,这些假设就是软件开发者与软件用户的约定。作为软件用户你遵守这些约定即可,不再需要(或不支持)对这些约定进行配置。”—— 一定程度上可以理解为软件中的默认配置。
Ansible 在使用 Roles 时同样存在 “约定大于配置” 的情况,并且这些约定是硬性的(即不支持在配置文件中自定义)。
首先,Role 的目录结构是固定的。
An Ansible role has a defined directory structure with eight main standard directories. You must include at least one of these directories in each role. You can omit any directories the role does not use.
Ansible 角色有一个定义好的目录结构,其中有八个主要的标准目录。该已规定好的目录结构,示例如下:
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
By default Ansible will look in each directory within a role for a main.yml file for relevant content.
这八个目录的作用是:
tasks/main.yml:放置 role 执行任务时用到的文件。
handlers/main.yml:处理程序,可以在 role 内部或外部使用
library/my_module.py:模块,可以在 role 中使用(有关更多信息,请参见在rroles 中嵌入模块和插件)。
defaults/main.yml:role 的默认变量(有关更多信息,请参阅使用变量)。这些变量具有所有可用变量中最低的优先级,并且可以被任何其他变量(包括库存变量)轻松覆盖。
vars/main.yml:role 中的其他变量。(与 Ansible 模块中的 vars 作用一致,只不过这里的 vars 表示目录。)
files/main.yml:role 部署时用到的文件。
templates/main.yml:role 部署时用到的模板。与 Ansible 模块中的 templates 作用一致,只不过这里的 templates 表示目录。)
meta/main.yml:role 使用到的元数据。
在每个角色中必须包含至少一个这样的目录,当然我们可以省略角色不使用的任何目录,但是每个目录下的 main.yml 文件是该目录的入口文件,Ansible 读取时会默认查找该文件。所以这个 main.yml 文件不能省略。
其次,存储和查找 roles。
上文我们已经了解到了一个 role 的内部目录结构,但是这远远不能满足实际生产的需求。在文章的开始部分我们也以一个大数据项目为例,往往需要部署 Flink、Hadoop 等多个组件。这每一个组件都可以看做是一个 role。那么 Ansible 是如何查找 roles 的呢?
默认情况下,有 2 种方式:
在 Ansible 的发布项目中,创建一个叫做 roles 的目录。
默认情况下,Ansible 会自动查找 /etc/ansible/roles 目录下的 role。
举个例子,我们要使用 Ansible 创建一个发布大数据“全家桶”的项目 bigdata,该项目下要包含 Flink、Mysql、Hive 这 3 个 role。那么 bigdata 这个项目的目录结构大致如下:
➜ bigdata tree -L 3
.
└── roles
├── flink
│ ├── defaults
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ ├── tests
│ └── vars
├── hive
│ ├── defaults
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ ├── tests
│ └── vars
└── mysql
├── defaults
├── files
├── handlers
├── meta
├── tasks
├── templates
├── tests
└── vars
很明显可以看到 roles 下的 Flink、hive、Mysql 的子目录结构就是上文中提到的八大目录。
ansible-galaxy
快速创建 Role
从上文可知,每创建一个 role 都必须至少含有八大目录之一。所以 Ansible 中已内置了一个命令行工具 ansible-galaxy 快速创建 role 的八大目录,减轻我们的工作量。
假设该 role 名称是 flink,用如下命令生成相关目录:
ansible-galaxy init flink
使用 tree 命令看到 ansible-galaxy 生成的目录正是 role 所要求的标准的八个目录。
➜ tree flink
flink
├── README.md
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
ansible-galaxy init 其他几个实用的参数:
ansible-galaxy init -force role_name,默认情况下创建的 role 与当前工作目录下存在的文件重名的话,会抛出异常。使用 -force 选项会强制创建 role 目录,并对 role 目录下重名的目录或文件进行替换。
ansible-galaxy init --role-skeleton=/path/to/skeleton role_name,使用过 Maven 的同学应该知道, Maven 支持以其他项目做骨架创建新项目。ansible-galaxy 同样支持该功能,以 /path/to/skeleton 路径下的 role 为骨架,把所有的文件都进行拷贝来创建新的 role。
Galaxy:role 在线分享社区
此外与 Docker Hub、Grafana Dashboards 类似,Ansible Galaxy 也有一个在线社区 Galaxy[https://galaxy.ansible.com/home],上面有开发者分享的各种已经开发好的 roles。方便我们搜索现成的 role 下载,也可以上传自己开发的 role 到 Galaxy。
下载或上传 role 到 Galaxy 网站,同样需要使用命令行工具 ansible-galaxy。默认情况下 ansible-galaxy 调用的 Galaxy 服务端的地址是 https://galaxy.ansible.com, 可以通过 -server 选项或在 ansible.cfg 文件中重新配置 Galaxy 的地址。
下载 roles
下载 roles 的语法模板是:
$ ansible-galaxy install username.role_name
默认情况下 ansible-galaxy 会把 role 下载到环境变量 ANSIBLE_ROLES_PATH 中,ansible-galaxy 提供了参数 --role_path 指定 role 下载的地址。
ansible-galaxy 其他命令速览
ansible-galaxy search elasticsearch,查找 Galaxy 网站中的 role elasticsearch
ansible-galaxy info username.role_name,查看 username.role_name 的详细信息
ansible-galaxy list,查看已安装的 roles
ansible-galaxy remove username.role_name,卸载安装的 username.role_name
ansible-galaxy login,登录 Galaxy 网站
整体布局:Suit is best
如果你坚持读完上述部分,那么你肯定对于如何使用 role 了然于心,简单来讲就是当前 Ansible 应用下需要存在一个叫做 roles 的目录。接下来我们聊聊 Ansible 应用下除了 roles 目录外,其他目录该如何布局呢?Ansible 最佳实践官方文档[https://docs.ansible.com/ansible/2.5/user_guide/playbooks_best_practices.html#content-organization]中是这样建议的:
Your usage of Ansible should fit your needs, however, not ours, so feel free to modify this approach and organize as you see fit.
One crucial way to organize your playbook content is Ansible’s “roles” organization feature, which is documented as part of the main playbooks page. You should take the time to read and understand the roles documentation which is available here: Roles.
Ansible 整体的目录结构没有一定之规,适合你的当前需求就好。但是 Roles 这个概念至关重要。
良心的 Ansible 官方在 Github 上开了一个项目 ansible-examples[https://github.com/ansible/ansible-examples]专门用来收集优秀的最佳实践。大家可以根据实际需求吸收借鉴,下面我分享一下我常用的项目布局:
.
├── Makefile
├── README.md
├── deploy.retry
├── deploy.yml
├── files
│ ├── apache-maven-3.8.3-bin.tar.gz
│ ├── apache-zookeeper-3.7.0-bin.tar.gz
│ ├── flink-1.14.0-bin-scala_2.11.tgz
│ ├── hadoop-2.7.5.tar
│ ├── hadoop-3.3.1.tar.gz
│ ├── mysql-connector-java-8.0.26-1.el7.noarch.rpm
│ ├── mysql-connector-java-8.0.26.jar
│ └── openjdk-11.0.2_linux-x64_bin.tar.gz
├── inventories
│ └── hosts
└── roles
├── flink
├── hadoop
├── hadoop3
├── hive
├── java
├── linux
├── mvn
├── mysql
└── zookeeper
Makefile,用来封装 Ansible 的发布命令
deploy.ym,是执行 Ansible 命令时的入口文件
files,用来存放 role 相关的部署包,一般体积较大,不会使用 git 进行版本管理。
inventories,用来管理部署机器。
roles,用来部署的组件。从上面的目录可知,当前主要是用来部署大数据相关的组件。
给自己打个小广告:在下一个实战章节将使用这个项目布局发布大数据项目,在这个过程中又需要补充哪些 Ansible 的知识呢?为什么我不直接使用 Galaxy 网站上的 role 而是要自己从头开发呢?在部署 Hadoop3、Flink 项目中,使用 Ansible 又踩了哪些坑呢?
敬请期待 《进击的 Ansible(三):Ansible 大数据实践》
参考资料
- 使用 Ansible 传输文件的几种方式:
https://zdyxry.github.io/2019/11/22/使用-Ansible-传输文件的几种方式/
- Ansible:
https://gist.github.com/MrNice/89a3bbe44e218c9d2309
- Roles:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html#id2
- Galaxy User Guide:
https://docs.ansible.com/ansible/2.5/reference_appendices/galaxy.html
- 约定优于配置:
https://zh.wikipedia.org/wiki/约定优于配置
推荐阅读
进击的 Ansible(二):如何快速搞定生产环境 Ansible 项目布局?的更多相关文章
- Spring Boot 之 Profile --快速搞定多环境使用与切换
Spring Profile是Spring3引入的概念,主要用在项目多环境运行的情况下,通过激活方式实现多环境切换,省去多环境切换时配置参数和文件的修改,并且Spring profile提供了多种激活 ...
- 手把手教你制作微信小程序,开源、免费、快速搞定
最近做了个"罗孚传车"的小程序 一时兴起,做了一个小程序,将个人收集的同汽车相关的行业资讯和学习资料,分享到小程序中,既作为历史资料保存,又提供给更多的人学习和了解,还能装一下:) ...
- 10分钟快速搞定pandas
本文是对pandas官方网站上<10 Minutes to pandas>的一个简单的翻译,原文在这里.这篇文章是对pandas的一个简单的介绍,详细的介绍请参考:Cookbook .习惯 ...
- 面试大总结之二:Java搞定面试中的二叉树题目
package BinaryTreeSummary; import java.util.ArrayList; import java.util.Iterator; import java.util.L ...
- Spring Boot之Profile--快速搞定多环境使用与切换
Spring Profile是Spring3引入的概念,主要用在项目多环境运行的情况下,通过激活方式实现多环境切换,省去多环境切换时配置参数和文件的修改,并且Spring profile提供了多种激活 ...
- 一文搞定Spring Boot + Vue 项目在Linux Mysql环境的部署(强烈建议收藏)
本文介绍Spring Boot.Vue .Vue Element编写的项目,在Linux下的部署,系统采用Mysql数据库.按照本文进行项目部署,不迷路. 1. 前言 典型的软件开发,经过" ...
- Spring Boot (二)集成Jsp与生产环境部署
一.简介 提起Java不得不说的一个开发场景就是Web开发,也是Java最热门的开发场景之一,说到Web开发绕不开的一个技术就是JSP,因为目前市面上仍有很多的公司在使用JSP,所以本文就来介绍一下S ...
- ruby on rails 生产环境调试项目日志查看
1.项目目录:log/production.log 2.nginx日志:/opt/nginx/logs 生产环境下做的任何更改都要重启服务器 重启 sudo kill $(cat /opt/nginx ...
- 吐血整理:二叉树、红黑树、B&B+树超齐全,快速搞定数据结构
前言 没有必要过度关注本文中二叉树的增删改导致的结构改变,规则操作什么的了解一下就好,看不下去就跳过,本文过多的XX树操作图片纯粹是为了作为规则记录,该文章主要目的是增强下个人对各种常用XX树的设计及 ...
随机推荐
- PAT (Basic Level) Practice (中文)1009 说反话 (20分)
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出. 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串.字符串由若干单词和若干空格组成,其中单词是由英文字母(大小 ...
- Java(29)集合四Collections
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228439.html 博客主页:https://www.cnblogs.com/testero ...
- kafka应用讲解及应用场景(三)
一. 验证 1.进入bin目录 cd bin 2.ls查看脚本 会发现下面有很多脚本文件,由于我是要创建一个topic所有直接打开kafka-topics.sh脚本查看命令 打开脚本后发现里面有很多命 ...
- Python爬虫:给我一个链接,快手视频随便下载
前言 讲一下,文明爬虫,从我做起(1.文章中的程序代码仅供学习,切莫用于商业活动,一经被相关人员发现,本小编概不负责!2.请在服务器闲时运行本程序代码,以免对服务器造成很大的负担.) 1. 实现原理 ...
- VMD可视化hdf5格式的分子坐标文件
技术背景 VMD是分子动力学模拟领域常用的一款可视化软件,可以非常直观方便的展示分子的运动过程.而VMD本身对展现的格式有一定的要求,如果不是常见的rst等类型的坐标文件的话,就需要自己手动去实现一个 ...
- 第七次Alpha Scrum Meeting
本次会议为Alpha阶段第六次Scrum Meeting会议 会议概要 会议时间:2021年5月4日 会议地点:线上会议 会议时长:20min 会议内容简介:本次会议主要由每个人展示自己目前完成的工作 ...
- Linux基础入门级命令文档
Linux系统上命令的使用格式,及常用命令示例 1.命令提示符 登录系统后,第一眼看到的内容是: [root@node01 ~]# 上图就是 Linux 系统的命令提示符.那么,这个提示符的含义是什么 ...
- Gitlab-CI使用及.gitlab-ci.yml配置入门一篇就够了
转载:Gitlab-CI使用及.gitlab-ci.yml配置入门一篇就够了 - 简书 (jianshu.com) 一. Gitlab-CI/CD使用场景 首先,公司使用Gitlab作为工作仓库进行代 ...
- 进程间通信消息队列msgsnd执行:Invlid argument——万恶的经验主义
最近在搞进程间通信,首先在我的ubuntu 14.04上写了接口和测试demo,编译和执行都OK,,代码如下: 接口文件ipcmsg.h /* ipcmsg.h */ #ifndef H_MSGIPC ...
- usb设备无法识别
之前用飞线用旧板子飞线连接了一个wifi模块到usb0口上,调试ok的,现在新设计的板子回来了,wifi模块是连接在usb2口上的,系统起来后发现wlan0不存在,用lsusb查看wifi模块的usb ...