【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

以 Chef 和 Ansible 为例快速入门服务器配置

  • 2018-10-13
  • 本文字数:5339 字

    阅读完需:约 18 分钟

这篇文章讨论了如何在我们的环境中安装和配置软件,这个任务通常被称为服务器配置(Server Provisioning)。

服务器配置

在开始介绍现代化的工具之前,我们来看看最基本且经过实战考验的服务器配置工具:shell 脚本。在 Chef、Ansible 或 Puppet 出现之前,很多运营团队使用 Bash 来配置服务器(在 Windows 上则使用 PowerShell 脚本)。

例如,如果想在运行 Ubuntu 的 Amazon EC2 实例上安装 Nginx,可以使用以下脚本(install-nginx.sh):

复制代码
#!/bin/sh
ssh -t ubuntu@$1 sudo apt-get upgrade
ssh -t ubuntu@$1 sudo apt-get -y install nginx

我们可以使用 shell 脚本来配置服务器上的所有东西。据我所知,所有主流的配置工具都使用了基于安全传输层(如 SSH)的 shell 命令或 PowerShell(Chef 可能是个例外)。即使你使用了配置工具,在某些时候也需要用到脚本。因此,当你开始使用配置工具(如 Chef 或 Ansible)时,学习如何使用基本的 shell 脚本也会为你带来很多好处。

你可能会问自己,为什么在 shell 脚本已经可以完成所有工作的同时还要学习配置工具?很多环境已经使用 shell 脚本进行服务器配置,那么为什么要使用配置工具代替它们?

首先,shell 脚本通常使用的是声明性语法。shell 脚本通过运行命令序列来安装软件,而配置工具只需要指定服务器应该安装哪些软件,这样就可以使用相同的代码在不同的操作系统上、使用不同的包管理器以及指定不同的版本来安装和配置相同的软件。

其次,配置工具通常会提供用于组织基础设施的方式。虽然使用 shell 脚本也可以做到这一点,但配置工具通常会提供更简洁明了的方案。因为是行业标准,开发人员可以更轻松地找出 QA 环境中哪些服务器运行 RabbitMQ。

第三,每个主要的配置工具都有一个蓬勃发展的社区,他们构建可复用的模块来安装大多数开源软件。你可以直接在模块配置中指定内存限制,而不需要记住 Postgres 配置文件在哪里,这样可以节省很多时间。

当然,原因还有很多,这里就不一一例举了。尽管学习曲线有点陡峭,但学习配置工具仍然是值得的。与 shell 脚本相比,配置工具更容易使用,便于思考,也更容易维护

关于命名

学习使用 Chef(服务器配置工具)的前几周给我留下了深刻的印象。入门指南展示了如何创建一个“recipe”,其中包含安装或配置软件的说明,我能够理解这种比喻背后的含义。recipe 必须存在于“cookbook”中,这是有道理的。然后你在“kitchen”里测试 cookbook,但我开始有点怀疑了。

这种比喻有点令人感到困惑,于是我决定去看一下其他工具,如 Ansible。Ansible 文档的第一页介绍了“playbook”的概念,而 playbook 包含一系列“play”。

那么,这些问题很重要吗?当然很重要了,因为在学习配置工具之前,你应该知道,它们很有可能会引入大量令人费解的术语。即使是为了完成基本的任务,你也必须重新学习很多术语。如果你是刚开始学习配置工具,我强烈建议你随时写下这些术语定义,你还有很多东西要学。

每个软件开发人员都会为现有的单词创建不同的含义,他们甚至还会发明一些单词,比如“uninitialize”和“unregister”。这已经成为软件开发的一部分。

我会尽量用大家熟悉的术语来解释这些工具。

配置管理

你决定使用花哨的配置工具在远程服务器上安装 Nginx。在开始设置数据库备份节点前,一切都很顺利。你已经编写了 MySQL 主服务器的配置文件,但是你不太确定如何配置 MySQL 从服务器的内部 DNS 地址。这个时候配置管理就派上用场了。

在设置服务器时,最好可以将应用程序视为由两部分组成:不可变部分(通常是代码或编译的二进制文件)和可变部分(通常是配置文件或环境变量)。大部分由社区创建的模块默认情况下会安装二进制文件,并提供尽可能合理的配置,而且会为我们暴露出一些属性,方便对其进行覆盖。

这些属性通常包含特定于用户环境的值。大多数配置工具都为用户提供了一种机制,通过模板将特定于环境的值插入到配置文件中,或直接插入到环境变量中。

你可以使用配置工具提供的配置管理来配置 MySQL 主服务器的配置文件,然后在其中配置从服务器。

Secret 管理

这样就可以解决上述的问题,但后来发现,你必须上传 AWS 凭证才能让 MySQL 从服务器访问 S3。你知道不能直接将这些凭证提交到代码库中,因此这些凭证只能存在于你的机器和 NSA 服务器上。

这个时候你需要的是 Secret 管理。

与自动化领域的所有东西一样,你也有很多管理秘钥的可选项。谷歌提供了一项名为 KMS 的服务,AWS 也提供了一项名为 Secret Manager 的服务,Chef 提供了加密数据包,Hashicorp 提供了一款名为 Vault 的产品,Ansible 也有一款名为 Vault 的产品。除了 KMS 会对字符串进行加密之外,所有这些工具都提供了相同的功能:保护对加密秘钥的访问(这些秘钥被用在配置管理中)。

有好几次,我不小心将秘钥提交到了代码库。这类事情一直在发生,而且非常危险。

切勿以明文形式存储 API 密钥或凭证

可以使用 Secret 管理解决方案来存储这些数据,然后将其绑定到配置工具中

一个简单的例子:Chef

首先需要安装 Chef Development Kit(ChefDK)。

如前所述,我们需要一个 recipe 来安装 Nginx。出于教学的目的,我们将从头开始创建它,而不是从社区的 cookbook 中捞一个出来。

我们需要创建一个 cookbook。cookbook 通常存在于cookbooks目录中,在项目的根目录运行以下命令:

复制代码
mkdir cookbooks

现在让我们创建一个 cookbook,用于放置我们的新 recipe:

复制代码
chef generate cookbook cookbooks/application

这个命令在cookbooks/application目录中创建了很多文件,我们关心的是cookbooks/application/recipes/default.rb这个文件。这个文件包含了默认的 recipe,我们将安装 Nginx 的命令放到这个文件中。

复制代码
apt_update
package 'nginx'
cookbook_file '/var/www/html/index.html' do
source 'index.html'
owner 'www-data'
group 'www-data'
mode '0755'
action :create
end

这个文件中的前两个命令将执行你期望的操作:

  • apt\_update更新你的 aptitude 包。
  • package ‘nginx’使用操作系统默认包管理器安装nginx包(在这个示例中,它使用的是 aptitude)。

最后一个命令将cookbooks/application/files/index.html拷贝成远程服务器上的/var/www/html/index.html,并设置文件的权限,让 Nginx 服务器可以访问它。

这个文件还不存在,所以需要创建它。首先要创建文件目录:

复制代码
mkdir cookbooks/application/files

然后创建文件cookbooks/application/files/index.html,其中包含以下内容:

复制代码
<html lang="en-us">
<head>
<title>Hello, World!</title>
</head>
<body>
Chef has landed.
</body>
</html>

更新packer.json,加入 Chef 相关配置:

复制代码
{
"builders": [{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-04169656fea786776",
"instance_type": "t2.small",
"ssh_username": "ubuntu",
"ami_name": "Ubuntu 16.04 Nginx - {{timestamp}}",
"tags": {
"Image": "application"
}
}],
"provisioners": [{
"type": "chef-solo",
"cookbook_paths": ["cookbooks"],
"run_list": ["recipe[application]"]
}]
}

我们对之前的packer.json进行了两处更改。

首先,我们为 AMI 添加了一个Image标签。我们之前从 Packer 的输出中复制 AMI ID,并粘贴到 Terraform 代码中。这不是一个可维护的解决方案,因为 AMI ID 会经常发生变化,而且我们不应该在每次发生变化时都要将更改推送到存储库中。相反,我们使用 Terraform 的data资源来动态读取 AMI ID(使用Image=application查询最新的 AMI)。

其次,我们使用chef-solo替换了shell。我们告诉它在哪里可以找到 cookbooks 目录,以及要运行哪个 recipe。默认情况下,run\_list中的recipe\[COOKBOOK\]条目将执行recipes/default.rb。我们也可以显式指定 explicity:recipe \[COOKBOOK::RECIPE\]来覆盖默认行为。由于我们的 recipe 保存在recipes/default.rb中,所以将使用默认行为。

现在开始构建我们的 AMI:

复制代码
packer build packer.json

我们的新 AMI 有一个Image标签,现在修改terraform.tf中硬编码的 AMI,让它通过标签来查找 AMI。

将以下内容添加到terraform.tf中:

复制代码
data "aws_ami" "web" {
most_recent = true
owners = ["self"]
filter {
name = "tag:Image"
values = ["application"]
}
}

现在使用aws\_ami.web resource输出的 ID 替换aws\_instance.web1aws\_instance.web2resource 中的 AMI ID:

复制代码
resource "aws_instance" "web1" {
ami = "${data.aws_ami.web.id}"
availability_zone = "us-east-1a"
instance_type = "t2.small"
vpc_security_group_ids = ["${aws_security_group.application.id}"]
subnet_id = "${aws_subnet.private1.id}"
}
resource "aws_instance" "web2" {
ami = "${data.aws_ami.web.id}"
availability_zone = "us-east-1b"
instance_type = "t2.small"
vpc_security_group_ids = ["${aws_security_group.application.id}"]
subnet_id = "${aws_subnet.private2.id}"
}

运行下面的命令创建 Chef 配置的服务器,然后启动浏览器,打开地址为负载均衡器的域名:

复制代码
terraform plan -out terraform.plan
terraform apply "terraform.plan"
open "http://$(terraform output dns)"

你应该能够在打开的浏览器页面上看到:Chef has landed!

一个简单的例子:Ansible

让我们使用 Ansible 来构建这个相同的示例。首先需要安装Ansible

Ansible 将安装和配置说明组织到tasks中,然后将tasks组织到playbook中。让我们为 playbook 创建一个目录结构。

复制代码
mkdir playbook
mkdir playbook/files

这并不是组织 Ansible playbook 的最佳实践。因为我们的用例很简单,所以使用了简化版本。如果你对 Ansible 感兴趣,应该根据官方提供的建议来构建playbook

playbook/application.yml中创建 playbook,内容如下:

复制代码
---
- hosts: all
gather_facts: False
become: yes
pre_tasks:
- name: Install Python 2.7
raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
- hosts: applications
become: yes
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Update contents of index.html
copy:
src: index.html
dest: /var/www/html/index.html
owner: www-data
group: www-data
mode: 0755

这个 playbook 文件包含配置我们的服务器所需的所有信息。现在让我们来讨论一下它的结构。

每个 playbook 包含一个“play”列表,每个 play 包含一个“tasks”列表,task 用于安装和配置软件。我们的 playbook 包含两个 play。第一个 play 在 Ubuntu 上安装 Python 2.7(用于运行 Ansible)。第二个 play 安装和配置 Nginx。

我们在每个 play 的根节点配置了两个参数:hostsbecomehosts参数告诉 Ansible 应该在哪台机器上运行 playbook(“all”表示在所有机器上运行)。become:yes表示 Ansible 将通过 sudo 运行所有命令,否则将会出现很多权限错误。

play 的第一个 task 负责安装和配置 Nginx,它将更新 aptitude 缓存,并确保nginx包存在。如果已经安装了nginx包,这个命令将不执行任何操作。

第二个 task 将files/index.html拷贝到远程服务器上,并为其分配正确的权限。

这个文件还不存在,所以让我们创建它。将以下内容加入到playbook/files/index.html中:

复制代码
<html lang="en-us">
<head>
<title>Hello, World!</title>
</head>
<body>
Ansible has landed.
</body>
</html>

这就是我们配置 Ansible 所需的全部内容。现在让 Packer 使用这个配置。使用以下内容更新packer.json

复制代码
{
"builders": [{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-04169656fea786776",
"instance_type": "t2.small",
"ssh_username": "ubuntu",
"ami_name": "Ubuntu 16.04 Nginx - {{timestamp}}",
"tags": {
"Image": "application"
}
}],
"provisioners": [{
"type": "ansible",
"playbook_file": "./playbook/application.yml",
"host_alias": "applications"
}]
}

我们只修改了使用 Ansible 作为配置器,需要提供一个指向 playbook 文件的路径,我们将其设置为./playbook/application.yml。我们可以看到用于安装 Nginx 的 play 顶部有一行:hosts: applications。这是我们用来告诉 Ansible 需要安装应用程序的主机别名。我们需要告诉 Packer 我们正在为其中一个主机构建映像,所以我们将host\_alias属性设置为applications

运行下面的命令来创建 Ansible 配置的服务器,然后启动浏览器,打开地址为负载均衡器的域名:

复制代码
packer build packer.json
terraform plan -out terraform.plan
terraform apply "terraform.plan"
open "http://$(terraform output dns)"

你应该可以在打开的浏览器页面上看到:Ansible has landed!

英文原文: http://stephenmann.io/post/a-brief-introduction-to-provisioning/

感谢张婵对本文的审校。

2018-10-13 06:372251
用户头像

发布了 731 篇内容, 共 433.7 次阅读, 收获喜欢 1997 次。

关注

评论 1 条评论

发布
暂无评论
发现更多内容

基于LAXCUS开发分布式视频转码应用

LAXCUS分布式操作系统

分布式计算 分布式应用 视频转码

《数字经济全景白皮书》Z世代用户洞察篇(2)重磅发布!

易观分析

Z世代

关于 WordPress 你了解多少?

海拥(haiyong.site)

4月月更

桌面运维工程师需要会哪些技能?主要是做什么的?

行云管家

云计算 运维 运维工程师 IT运维 云运维

当 API 成为服务,我们将连接一切!

鼎道智联

TASKCTL 变量的函数表达式运算

TASKCTL

批量任务 调度引擎 ETL 自动化运维 调度任务

书单 | “阿里云数字新基建”系列丛书全家福来啦!

博文视点Broadview

小程序运行时+SAAS级服务,提升研发降本增效作用

Speedoooo

flutter APP开发 SaaS平台 小程序容器 小程序运行时

CrashSight异常崩溃管理解决方案

WeTest

大咖说·智篆商业|颜杰华:数字经济时代,不确定性中的确定性

大咖说

阿里巴巴 数字经济数字时代 数智化 存量时代

什么时候需要使用CRM系统?

低代码小观

CRM 客户关系管理 低代码开发 CRM系统 客户关系管理系统

MySQL事务并发带来的问题以及其解决方案分析

乌龟哥哥

4月月更

阿里云代码托管平台,不限容量,免费使用

阿里云云效

云计算 阿里云 代码管理 代码托管 阿里云代码托管

【云管平台】三大云管平台厂商详细介绍

行云管家

云计算 云管平台 云堡垒机 云厂商

TASKCTL 调度设计器作业属性的应用

TASKCTL

分布式 元数据区 ETL 自动化运维 任务调度器

轻量级兼顾本地体验,PWA应用到底有多卷?

鼎道智联

火山引擎 MARS X 今日头条 | 大型App高效协同开发,实现研发流程自动化

字节跳动终端技术

今日头条 字节跳动 研发 火山引擎MARS

TiDB 在连锁快餐企业丨海量交易与实时分析的应用探索

TiDB 社区干货传送门

组合式应用新利器?SaaS新时代事件网格如何解决集成标准化问题

华为云开发者联盟

Serverless 无服务器 事件网格 组合式应用

人人都可以学会的产品手册制作方法

小炮

产品宣传手册

华为云物联网高级攻城狮的4年配置中心实践分享

华为云开发者联盟

开源 DevOps 配置中心 Apollo 业务配置

GPU底层技术、全球市场格局分析(中)

Finovy Cloud

人工智能 云计算 云服务器 GPU服务器 GPU算力

2022年中国茶饮产业洞察

易观分析

茶饮 产业洞察

Flink整合ElasticSearch详细指南及踩坑记录

五分钟学大数据

4月月更

java高级用法之:JNA中的Structure

程序那些事

Java 程序那些事 JNA 4月月更

豆瓣评分9.0,时隔6年,“Linux命令行圣经”新版终于来了!

图灵教育

Linux shell脚本编程

增长270%!PWA 在 Chrome 平台迎来井喷式增长

鼎道智联

LSM-Tree - LevelDb了解和实现

懒时小窝

LSM树 LSM-Tree

【数据安全与流通专题】星环科技春季新品发布周

星环科技

NFT数字藏品交易平台系统开发搭建

薇電13242772558

NFT 数字藏品

项目中如何优雅的消除if-else

Rubble

4月日更 4月月更

以Chef和Ansible为例快速入门服务器配置_DevOps & 平台工程_Stephen Mann_InfoQ精选文章