发布在即!企业 AIGC 应用程度测评,3 步定制专属评估报告。抢首批测评权益>>> 了解详情
写点什么

以 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:372235
用户头像

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

关注

评论 1 条评论

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

查询性能: TDengine 最高达到了 InfluxDB 的 37 倍、 TimescaleDB 的 28.6 倍

TDengine

大数据 tdengine 性能测试 时序数据库

等保测评机构资质申请条件是什么?个人可以申请吗?

行云管家

等级保护 等保测评 等保测评机构

OpenCloudOS 轻量级虚拟化引擎 LiKeX 介绍

OpenCloudOS

Linux 容器 rust

gRPC请求超时和异常处理

江南一点雨

Java gRPC

一个专科生的2022年终总结——默默努力,成为更好的自己

main工作室

年终总结

MetaForce佛萨奇2.0开发规则丨MetaForce佛萨奇2.0系统开发说明及案例

系统开发咨询1357O98O718

一文上手图数据备份恢复工具 NebulaGraph BR

NebulaGraph

数据库 容灾备份

Go 闯进 Top 10、C++ 再次被 Java 反超,TIOBE 3 月榜单发布

博文视点Broadview

SpringBoot整合ElasticSearch

代码的路

Java elasticsearch

DAPP众筹互助游戏开发详细丨DAPP众筹互助游戏系统开发(开发逻辑及案例)

系统开发咨询1357O98O718

微信小程序自动化测试方案实践过程

Openlab_cosmoplat

开源社区 微信小程序测试

云原生+新技术,会碰撞出怎样的火花?

墨天轮

数据库 阿里云 Serverless 云原生 华为云

如何召开成功高效的项目会议?

PMO实践

项目管理 PMO

云智慧ITSM产品助力企业有效实现降本增效

云智慧AIOps社区

AIOPS ITSM 智能运维 工单 IT服务管理

寻找 Milvus 的第 N+1 种可能

Zilliz

Milvus Meet Up

90后老板用低代码整顿旅行社,创2000万年收,他是怎么做到的?

这我可不懂

低代码 低代码平台 JNPF

图片动画化应用中的动作分解方法

百度Geek说

深度学习 算法 计算机视觉 企业号 3 月 PK 榜

DAPP马蹄链智能合约系统丨DAPP马蹄链智能合约系统开发(开发规则))

系统开发咨询1357O98O718

用友与百度强强联合,以AI深化冶金行业数智化应用场景

用友BIP

苹果M1/M2电脑安装Lightroom Classic 2022(LRC2022) 后打开闪退怎么办?

魔仙苹果mac堡

m1 LRC2022 闪退 M2 苹果软件

苹果软件Noir:为所有网站应用深色模式

魔仙苹果mac堡

Safari 扩展 Noir – Dark Mode 暗模式

华为阅读全新上线高品质男声,带来身临其境般听书体验

叶落便知秋

小程序无需编程,体验IoT物联网平台-物模型开发——设备接入类

阿里云AIoT

物联网

国贸股份 x 袋鼠云:推进全链业务深度数字化,为产业综合服务插上数字化翅膀

袋鼠云数栈

数字化转型

马蹄链智能合约开发方案丨马蹄链智能合约系统开发(开发说明))

系统开发咨询1357O98O718

FDF循环互助游戏开发说明丨FDF循环互助游戏系统开发详细及案例源码

系统开发咨询1357O98O718

PS画画工具推荐:ps怎么黄金分割构图

魔仙苹果mac堡

黄金分割插件 GoldenCurve插件 PS插件下载

Java中restTemplate携带Header请求

代码的路

Java RestTemplate

IoT物联网平台运行监控最佳实践——设备管理运维类

阿里云AIoT

监控 物联网

软件测试/测试开发丨基于 Spring Boot 的 RESTful API 设计与实现

测试人

Spring Boot 软件测试 测试发开 RESTful API

一图读懂工业数据要素高水平应用

Openlab_cosmoplat

工业数据

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