AWS 网络基础知识:软件工程师的简单指南。
您是否曾经进入过 AWS 控制台,却被各种概念和术语弄得一头雾水?您了解:安全组、入站规则、VPC、子网、Internet 网关、NAT、ENI,所有这些都与网络相关。简而言之:AWS 网络内容丰富。因此,如果您打算深入研究它,您需要知道重点是什么:基础知识。
今天我们将介绍 AWS 中您应该熟悉的主要网络组件。我们将向您解释为什么需要这些组件、它是什么以及如何使用它。在本文中,我们将构建一个示例,在我们自己的 VPC 的公共子网中运行一个 Web 服务器。
阅读完本文后,您将了解主要的网络概念:私有 IP、虚拟私有云 (VPC)、无类域间路由 (CIDR)、子网、Internet 网关和安全组,并使用它们来实现基本的网络设计。
学习 AWS 网络基础知识的 3 个重要原因
也许现在您正在想:
可是,我是个软件工程师?我真的需要了解网络吗?那不是运维的工作吗?我已经有很多事情要做了,为什么还要再接手一件呢?
但你问这个问题是对的!
如果那就是你,并且你还不确定为什么你应该学习 AWS 网络基础知识,那么让我给你两个重要原因……
1.如果您不了解 AWS 网络基础知识,那么使用 AWS 云会更加困难。
无论你启动的是简单的 EC2 还是 Lambda,这些网络问题:VPC、安全组等等,都会出现。它们会不断干扰你,让你说:“哦,我先不管它了”。然后你就一直忽略它,一直忽略它。
但随着时间的推移,不理解这些基础知识会开始浪费你的时间,因为你得费力地应对那些你并不真正理解的功能。即使你是一个普通的应用程序开发人员,在某个时候,你也会接触到我们今天介绍的 AWS 网络基础知识,这将使你的工作变得轻松很多。
2.了解 AWS 网络基础知识可以让您从根本上实施更好的解决方案。
如果你有一把锤子——一切都是钉子。
如果你不了解网络层面的可能性,你就会永远在应用程序层面实现次优的解决方案。我以前就犯过类似的错误,在应用程序内部实现了诸如 IP 白名单之类的功能,而理想情况下,这些功能应该在网络层面实现。
当您了解网络级别上可能实现的功能(即使您不一定能实现它)时,它将允许您挑战自己的架构和设计,从而提出从根本上更好的软件。
3.云原生正在兴起,工程师需要AWS网络技能。
在云原生环境中工作正变得越来越普遍。如今,工程师比以往任何时候都更需要走出纯粹的应用程序开发领域,真正理解网络等基础设施问题。对你的要求更高了。
我们将如何使用 Terraform 来解释 AWS 网络基础知识。
好的,这就解释了为什么我们要学习这些网络概念——让我们来谈谈我们实际上要怎么做。
我喜欢的云端学习方式是通过基础设施即代码。
为什么?因为它允许我按照自己的时间编写基础设施代码,准备更改并在准备好时执行它们。
基础设施即代码不仅可以实现良好的工作流程,而且可以消除错误并在版本控制中保留历史记录,让生活变得轻松一些。
今天我们讲解网络概念时,我会提供一些 Terraform 基础设施即代码 (IaaS) 的代码片段。如果您不熟悉 Terraform,也不用担心,因为这些代码片段很短,您不需要任何先验知识。这些代码片段主要是为了向您展示在创建这些资源时需要传递哪些类型的参数(或属性)。
当然,实践学习才是王道。读完本文后,您可以从此仓库中找到、克隆并运行完整的代码示例,并根据需要尝试各种基础架构。
了解 IP 和私有地址的必要性。
好的——介绍已经足够了,让我们开始吧!
首先,我们需要了解一些关于 IP 和 IP 地址的理论知识,不过请耐心听完,绝对值得一看。记住,这篇文章讲的是基础知识,所以不要急着跳过!
IP 地址是分配给计算机的一系列唯一数字,用于使其在特定网络中可访问。IP 地址如下所示:123.122.11.56
。通常,我们谈论 IP 地址时指的是公共互联网。公共互联网是一个全球开放的网络。
但在互联网上,我们并不经常接触这些原始 IP。这是因为 DNS(域名系统)会将这些与机器相关的 IP 映射到我们更常用、更友好的名称上。
如果您有兴趣,请尝试34.242.183.30
在搜索栏中输入。这是该网站当前的弹性 IP 地址。或者更准确地说,这是一个属于亚马逊的 IP,当前正在路由到运行 WordPress 的 EC2 机器。
我的网站就是一个在互联网上公开的事物的例子,我希望它也能如此!然而,并非所有机器都需要联网。例如,像会计这样的后台业务功能。这些机器需要有人访问,但并非互联网上的任何人都可以访问。
为了实现这一点,我们使用私有地址空间。
当互联网逐渐成熟时,人们决定保留以下地址空间供私人使用:
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
你会认出 IP 地址的格式,但你会注意到数字后面跟着一个数字:/12
。这个数字被称为网络掩码,它定义了一个 IP 地址范围。不过,我们稍后会更详细地介绍它。现在你只需要知道,有大量(大量!)IP 地址是保留给私人使用的,也就是说,不在公共互联网上使用。我们可以利用这些私有地址空间来获取优势。
这正好引出了我们今天要构建的内容!这是一个 VPC 网络,包含一个私有网络(使用上述地址空间),并被拆分成三个较小的子网。其中一个子网将被授予 Internet 访问权限,我们将在其中部署一个 Web 服务器。另外两个子网将是私有的,可以用于我们之前提到的内部业务功能。
今天的参考架构。
我们将逐个组件地介绍构建这种架构所需的组件。
那么让我们继续从最重要的主题开始:虚拟私有云。
什么是虚拟私有云 (VPC)?
VPC(虚拟私有云)是一种在 AWS 中逻辑上隔离资源的方式。AWS 拥有大量机器,因此 VPC 本质上是一种将属于您的机器声明为专有,以便其他人无法访问它们的方式。当我们拥有 VPC 时,其中包含的资源只能与其他 VPC 资源通信。除非我们采用一些特殊技巧来连接 VPC,但今天我们不会讨论这个问题。
因此,VPC 只是一种隔离业务(甚至是业务子部门)的方法。我们甚至可以使用 VPC 来实现不同的环境,例如演示、测试、预发布和生产环境。因为生产环境不需要访问我们的测试环境,反之亦然。VPC 有很多不同的用例。
VPC 作为一个网络,拥有分配的地址空间。当我们在 VPC 中创建资源时,它们必须位于 VPC 的专用地址空间内。还记得我们之前讨论过的私有地址范围吗?
嗯,AWS 中的 VPC 可以大到与64,000
唯一 IP 一样大,小到16
。
但是什么决定了规模呢?嗯,有很多因素,包括我们对未来增长的预测,但现在我们不必太担心这个。
关于 VPC 或任何私有网络最后要考虑的一件事是:命名空间冲突。
我的意思是什么?
如果我们想将两个 VPC 连接在一起,而它们使用相同的私有地址空间,就会出现问题。这意味着,如果可以的话,我们可能需要为所有私有网络创建不同的 IP 地址范围。
让我们看看在 Terraform 中创建 VPC 是什么样子的……
resource "aws_vpc" "main" { | |
cidr_block = "10.0.0.0/26" | |
enable_dns_hostnames = true | |
tags { | |
description = "Custom VPC" | |
} | |
} |
resource "aws_vpc" "main" { | |
cidr_block = "10.0.0.0/26" | |
enable_dns_hostnames = true | |
tags { | |
description = "Custom VPC" | |
} | |
} |
使用 Terraform 创建 VPC
从上面可以看出,创建新 VPC 所需的是地址范围,即 CIDR 块。
如果您想知道那个看起来很奇怪的 IP 是什么,请不要担心 - 我们很快就会介绍它。
您只需知道,当我们定义要分配给 VPC 的私有 IP 地址范围时,VPC 就创建完成了。很简单。
什么是子网?
但在讨论这些 IP 地址范围、CIDR 块之前,让我们先介绍一下子网,因为它们与 VPC 密切相关。
子网(我们今天要讲的几个直观命名的基本概念之一!)顾名思义,它就是一个大型网络的一小部分。一个网络可以被分割成更小的部分,以便应用不同的网络规则。
让我们看一下 Terraform:
resource "aws_vpc" "main" { | |
cidr_block = "10.0.0.0/26" | |
enable_dns_hostnames = true | |
tags { | |
description = "Custom VPC" | |
} | |
} | |
resource "aws_subnet" "subnet_1_public" { | |
availability_zone = "ap-south-1a" | |
vpc_id = "${aws_vpc.main.id}" | |
cidr_block = "10.0.0.0/27" | |
map_public_ip_on_launch = true | |
tags { | |
description = "Public subnet" | |
} | |
} |
resource "aws_vpc" "main" { | |
cidr_block = "10.0.0.0/26" | |
enable_dns_hostnames = true | |
tags { | |
description = "Custom VPC" | |
} | |
} | |
resource "aws_subnet" "subnet_1_public" { | |
availability_zone = "ap-south-1a" | |
vpc_id = "${aws_vpc.main.id}" | |
cidr_block = "10.0.0.0/27" | |
map_public_ip_on_launch = true | |
tags { | |
description = "Public subnet" | |
} | |
} |
这里您可以看到我们正在创建 VPC(与之前一样)。但现在我们还要创建一个子网。为了创建子网,我们需要定义可用区(因为它们只能存在于一个可用区中)、它所属的 VPC 以及它的大小。
但是,那个奇怪的 IP 地址又出现了(CIDR 块)……
我已经说得够多了,所以让我们来讨论一下网络掩码,它是什么以及它如何让我们定义 VPC 和子网的范围。
什么是网络掩码?
网络掩码一开始看起来可能有点令人望而生畏——它们可能是我们今天要介绍的最令人困惑的 AWS 网络基础知识。
但当迷雾散去时,你会更好地了解它们,它们很有用,而且经常出现。
带有网络掩码的 CIDR 块如下所示:
10.0.0.0/24
您会经常在 AWS 中看到这种 CIDR 块格式 - 您可能会想知道它到底是什么。
IP 地址块
CIDR 块的第一部分,四个数字10.0.0.1
(用点分隔)分别代表一个数字256
。为什么256
?因为每个块是 8 位,而 8 位2^8
总共可以表示数字。
这就是 IP 地址的结构。
嗯,实际上 IP 地址是这样的:
10101001.11100010.01010001.11011010.
这就是4
位块8
(32
总体而言),其中每个块都拥有256
唯一的地址空间。
那么,为什么我们不直接使用长二进制表示呢?因为十进制的等效值(例如10.256.0.0
)写起来更短,也更容易阅读(最终!)。但是,请记住底层的二进制等效值,因为它在进行 CIDR 计算时很重要。
了解网络掩码范围
在上例中,数字的第二部分/24
称为网络掩码。网络掩码定义了网络范围的结束位置。与 IP 地址(四个带点的数字)组合后,我们就得到了一个网络范围,该范围从 IP 地址开始,到网络掩码指定的地址数之后结束。网络掩码表示 IP 地址(共 32 位)中分配给外部网络的位数。因此,剩下的部分(原始 32 位中的部分)将分配给我们的网络。
为了更好地理解这一点,让我们看一个例子……
例如,的网络掩码/24
为 ,将24
位交给网络。8
由于 ,因此剩余位32 - 8 = 24
。8 位等于2^8
总地址数,即256
。
你可能会好奇为什么2^8
?因为二进制就是这样运作的。我们每增加一个位空间,数字的可能性数量就会平方。二进制0
有两个可能的值0
: 或1
,等于 。2^1 = 2
二进制00
有四个可能的值:00
,01
10
和,11
等于2^2 = 4
。
总结一下……
要计算网络掩码,取一个/22
数字,减去一个数字32
,然后将余数作为的幂2
。因此:32 -22 = 10
的网络掩码为22
我们的网络提供了一个潜在的2^10 =
1024
地址空间!
正如我们之前所说,64,000
AWS 中网络大小的限制是/16
网络掩码的 1/4。而您可以拥有的最小范围是 16,这意味着您有四位:2^4
。
请记住 - 网络掩码只是定义了一个 IP 范围,从 IP 开始到网络掩码确定的端点结束。
如果您有兴趣进一步了解 CIDR 地址范围,子网计算器将是一个明智的选择。
子网计算器cidr.xyz
一个不错的计算器练习是,假设你正在实现一个 VPC 及其关联的子网络。尝试添加不同的网络,查看它们的大小,并尝试猜测你会猜对哪些答案。
什么是路由表?
我们的 AWS 网络基础列表中的下一个是路由表。
路由表与子网密切相关,因为它决定了流量在子网之间的流动方式。您需要将流量从公网迁移到私有网络吗?您需要设置路由表来定义服务可以访问的位置。
resource "aws_route_table" "public_route_table" { | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
description = "public route table" | |
} | |
} | |
resource "aws_route_table" "private_route_table" { | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
description = "private route table" | |
} | |
} | |
resource "aws_route" "public_gateway_access_route" { | |
route_table_id = "${aws_route_table.public_route_table.id}" | |
destination_cidr_block = "0.0.0.0/0" | |
gateway_id = "${aws_internet_gateway.vpc_internet_gateway.id}" | |
} | |
resource "aws_route_table_association" "subnet_1_rt_association" { | |
subnet_id = "${aws_subnet.subnet_1_public.id}" | |
route_table_id = "${aws_route_table.public_route_table.id}" | |
} |
resource "aws_route_table" "public_route_table" { | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
description = "public route table" | |
} | |
} | |
resource "aws_route_table" "private_route_table" { | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
description = "private route table" | |
} | |
} | |
resource "aws_route" "public_gateway_access_route" { | |
route_table_id = "${aws_route_table.public_route_table.id}" | |
destination_cidr_block = "0.0.0.0/0" | |
gateway_id = "${aws_internet_gateway.vpc_internet_gateway.id}" | |
} | |
resource "aws_route_table_association" "subnet_1_rt_association" { | |
subnet_id = "${aws_subnet.subnet_1_public.id}" | |
route_table_id = "${aws_route_table.public_route_table.id}" | |
} |
创建 2 个路由表(私有和公共)的示例
上面的代码分解得相当细粒度,但您可以看到我们创建了两个路由表条目:一个不允许任何路由的私有路由条目(真正私有),另一个连接到 VPC 的互联网网关。我们可以将私有路由表复用到这两个私有子网中。
如果没有路由表,我们的网络就会变得支离破碎,没有关于谁可以与谁通信以及如何通信的规则。上面最后一条记录仅仅将两部分绑定在一起:我们的子网和我们的路由表(公共)。
使用这段代码,我们现在就可以允许流量进出我们的公共子网了!好吧,我们差点就需要一个组件了……
什么是互联网网关?
互联网网关是 AWS 的一个组件,当它连接到 VPC 时,可以为 VPC 提供公共互联网访问权限。
但是……我们先退一步来说!记住,子网可以是公共的,也可以是私有的。公共网络只是一个可以访问互联网的网络。
但是,值得指出的是,目前您无法直接在 AWS 中创建私有或公共子网。
我的意思是什么?
好吧,要创建一个公共子网,我们需要创建一个常规子网,但要更新它的路由表以指向互联网,并确保我们的 VPC 设置了互联网网关。
当我们开始思考互联网接入时,互联网网关这个话题就变得有点令人困惑。为什么?因为有些服务需要互联网接入(比如静态网站)。而有些服务需要流量流出,而不是流入——比如内部私有微服务需要从其他基于互联网的服务引入依赖项。
resource "aws_internet_gateway" "vpc_internet_gateway" { | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
Name = "Internet gateway for the main VPC" | |
} | |
} |
resource "aws_internet_gateway" "vpc_internet_gateway" { | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
Name = "Internet gateway for the main VPC" | |
} | |
} |
设置互联网网关很简单,只需创建资源并将其附加到 VPC。
到目前为止,如果您一直在遵循代码,我们已经拥有一个 VPC 和一些子网,并且通过附加路由表和互联网网关将其中一个子网公开。现在是时候将资源(我们的 EC2 实例(一个 Web 服务器))放入我们的公共子网中,以便它可以被全世界访问。耶!
嗯……其实没那么快。因为我们还有一个问题。现在,流量可以从互联网通过互联网网关进入我们的公共子网,并敲击我们实例的大门,但却进不去。为什么?因为实例有防火墙。这些防火墙被称为安全组。为了允许访问我们的实例,我们需要通过安全组启用公共流量。
什么是安全组?
安全组是一组应用于资源的网络规则。安全组负责定义哪些流量(基于端口和协议)可以进入或离开特定资源。单个资源可以引用多个不同的安全组,以聚合不同类型的访问。例如,我们可能希望有一个安全组允许 HTTP 和 HTTPS 流量进入我们的网站。然而,我们可能希望我们的服务拥有 SSH 访问权限,但我们希望确保 SSH 访问仅受 IP 地址限制,而不是整个互联网。
让我们看看 Terraform 中的安全组是什么样的……
resource "aws_security_group_rule" "allow_tcp_ingress" { | |
type = "ingress" | |
from_port = 80 | |
to_port = 80 | |
protocol = "TCP" | |
cidr_blocks = ["${var.subnet_1_public}"] | |
security_group_id = "${aws_security_group.allow_http.id}" | |
} | |
resource "aws_security_group_rule" "allow_all_egress" { | |
type = "egress" | |
from_port = 0 | |
to_port = 0 | |
protocol = -1 | |
cidr_blocks = ["${var.subnet_1_public}"] | |
security_group_id = "${aws_security_group.allow_http.id}" | |
} | |
resource "aws_security_group" "allow_http" { | |
name = "allow_http" | |
description = "Allow TLS inbound traffic" | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
Name = "HTTP traffic security group" | |
} | |
} |
resource "aws_security_group_rule" "allow_tcp_ingress" { | |
type = "ingress" | |
from_port = 80 | |
to_port = 80 | |
protocol = "TCP" | |
cidr_blocks = ["${var.subnet_1_public}"] | |
security_group_id = "${aws_security_group.allow_http.id}" | |
} | |
resource "aws_security_group_rule" "allow_all_egress" { | |
type = "egress" | |
from_port = 0 | |
to_port = 0 | |
protocol = -1 | |
cidr_blocks = ["${var.subnet_1_public}"] | |
security_group_id = "${aws_security_group.allow_http.id}" | |
} | |
resource "aws_security_group" "allow_http" { | |
name = "allow_http" | |
description = "Allow TLS inbound traffic" | |
vpc_id = "${aws_vpc.main.id}" | |
tags = { | |
Name = "HTTP traffic security group" | |
} | |
} |
子网的示例。
这里我们可以看到,我们有一个入口规则,这意味着流入防火墙的流量必须遵守该规则,即允许 80 端口上的 TCP 流量。该规则允许基本的 Web 请求访问。我们还有一个出口规则,允许所有流量。出口规则允许实例以任何方式向外发出 Internet 请求。在本例中,我们允许它这样做是因为我们需要安装 Web 服务器,而这需要 Internet 访问权限。
现在,子网就位后,流量就可以通过 API 网关到达我们的公共实例了。API 网关使用路由表条目将流量引入公共子网,安全组允许流量到达实例,瞧!我们在自定义 VPC 中的公共子网内运行了一个正常运行的 Web 服务器——太棒了!
总之
我们今天讨论了很多 AWS 网络基础知识,所以我想快速回顾一下所有内容:
- IP——用于将请求映射到机器的地址,可以是公共的,也可以是私有的。
- VPC ——AWS 云基础设施的一部分
- 子网– 较大网络的一部分,通常是 VPC 的子网。
- 网络掩码——一种表示用于将网络分割成子网的 IP 范围的方式。
- 路由表——分配给子网的一组规则,定义子网如何通信。
- 互联网网关——一种允许子网访问公共互联网的 AWS 资源。
- 安全组——本质上是一种防火墙,它规定哪些流量(通过协议和端口)可以访问资源。
创建自己的网络
今天就讲到这里。我知道我们讲了很多,但我只想简单介绍一下这些重要概念。如果你专注于学习任何与 AWS 网络相关的内容,请先关注这些方面。
永远记住,学习概念的最佳方法是亲自动手。所以,请参考我们讨论过的代码示例,尝试破解它们,并从中获得乐趣。只需确保首先正确设置您的 AWS 账户。该代码库包含 Terraform,可用于创建您的 VPC、子网、Internet 网关、路由表条目、Web 服务器实例和安全组。请尝试以它为参考,逐步重新构建您自己的 VPC。
希望今天你的迷雾能散去一些,坚持下去,继续阅读,你一定会成功。别忘了订阅我们的新闻简报,每两周你都会收到关于云原生基础知识的文章、最新资讯,并随时掌握最新动态。
快說話!
到目前为止,您接触过的最难的网络概念是什么?
帖子AWS 网络基础知识:软件工程师的简单指南。首先出现在The Dev Coach上。
鏂囩珷鏉ユ簮锛�https://dev.to/loujaybee/aws-networking-fundamentals-a-simple-guide-for-software-engineers-4dof