44

我对 Amazon Web Services 提供的弹性 IP 服务的使用有点困惑。我想主要的想法是我可以按照这个简单的过程切换到新版本的 Web 应用程序而无需停机:

  1. 在新的 EC2 实例上部署新版本
  2. 正确配置新版本并使用暂存数据库对其进行测试
  3. 正确测试后,让这个新版本使用实时数据库
  4. 将弹性 IP 关联到此实例
  5. 终止所有无用的服务(暂存数据库和旧的 EC2 实例)

这是部署新版本 Web 应用程序的常用方法吗?

现在,如果应用程序在更多实例上扩展怎么办?我在 Elastic Beanstalk 设置中配置了自动缩放,这创建了一个负载均衡器(我可以在 AWS 管理控制台的 EC2 部分看到它)。问题是我显然无法将弹性 IP 与负载均衡器相关联,我必须将其与现有实例相关联。我应该将它关联到哪个实例?我很困惑...

对不起,如果有些问题听起来很愚蠢,但我只是一名程序员,这是我第一次设置云系统。

谢谢!

4

6 回答 6

62

Elastic Load Balancing (ELB)不适用于Amazon EC2 弹性 IP 地址,事实上这两个概念根本无法结合在一起。

通过 Elastic Load Balancing 实现弹性

相反,ELB 通常通过CNAME 记录使用(但见下文),如果需要,这通过允许别名 DNS 地址更改正在使用的 ELB 的 IP 来提供第一级的弹性/可用性。第二级弹性/可用性由负载均衡器在您注册的 EC2 实例之间分配流量时执行。

可以这样想:CNAME 永远不会改变(就像弹性 IP 地址一样),EC2 实例的替换是通过负载均衡器、Auto Scaling或您自己(通过注册/取消注册实例)来处理的。

这在 Shlomo Swidler 的出色分析“Elastic Load Balancing”中的“Elastic”:ELB Elasticity and How to Test it中有更详细的解释,这反过来又指的是 AWS 最近提供的Best Practices in Evaluating Elastic Load Balancing,它证实了他的分析并提供了有关Elastic Load Balancing 服务架构及其自身工作原理的良好整体阅读(但缺乏 Shlomo 提供的说明性逐步示例)。

域名

请注意,之前需要 CNAME 的限制同时已通过对Amazon Route 53的相应添加来解决,以允许也使用根域(或Zone Apex),请参阅使用 Amazon Route 53 继续前进中的别名和区域 Apex部分快速概览和将域名与 Elastic Load Balancing 结合使用以了解详细信息。

通过 Elastic Beanstalk 实现弹性

首先,AWS Elastic Beanstalk依次使用 Elastic Load Balancing,如上所述。最重要的是,它添加了应用程序生命周期管理:

AWS Elastic Beanstalk 让您可以更轻松地在 AWS 云中快速部署和管理应用程序。您只需上传您的应用程序,Elastic Beanstalk 就会自动处理容量配置、负载平衡、自动扩展和应用程序运行状况监控的部署细节。[...] [强调我的]

这是通过将环境的概念添加到组合中来实现的,这在架构概述中进行了解释:

环境是应用程序的核心。[...] 当您创建环境时,AWS Elastic Beanstalk 会预置运行您的应用程序所需的资源。为环境创建的 AWS 资源包括一个弹性负载均衡器(图中的 ELB)、一个 Auto Scaling 组以及一个或多个 Amazon EC2 实例。

请注意,每个环境都有一个指向负载均衡器的 CNAME(URL),就像单独使用 ELB 一样。

所有这些都集中在管理和配置应用程序和环境中,其中详细讨论了 AWS Elastic Beanstalk 的一些最重要的功能,包括使用 AWS 管理控制台、CLI 和 API 的使用示例

零停机时间

很难确定最相关的部分以用于说明目的,但部署具有零停机时间的版本准确地解决了您的用例并暗示了所有必需的前面步骤(例如创建新应用程序版本启动新环境),因此阅读AWS 管理控制台部分可能会给您该平台如何运作的最佳整体图景。

祝你好运!

于 2012-05-07T01:01:57.410 回答
14

除了 Steffen 的精彩回答中描述的选项之外,如果您不需要 Elastic Load Balancer 的全部功能(例如在一个实例之外自动扩展) ,Elastic Beanstalk 似乎最近启用了 Elastic IP作为选项。

我在对类似问题的回答中描述了该选项。Elastic Beanstalk 现在允许您在两种环境类型之间进行选择,并且单实例选项创建一个弹性 IP。

带有选项的下拉菜单


我认为在大多数情况下使用 ELB 将是更可取的选择,但例如对于登台服务器,最好有一个不太复杂(并且更便宜)的替代方案。

于 2013-07-18T14:29:44.617 回答
4

很抱歉几年后回复了一个帖子,但是对于那些确实需要 ELB 上的一组静态 IP 地址的人,可以很好地要求 AWS 将他们所谓的“稳定 IP”地址添加到 ELB,从而给它静态IP地址功能。

他们当然不喜欢这样做 - 但如果你能证明它是合理的(主要理由是当你的客户端通过他们的防火墙对出站连接有 IP 白名单限制并且完全不愿意在这种立场上让步)。

请注意,基于流量选项的“自动缩放”不再是直截了当的 - AWS 将无法像使用开箱即用的解决方案那样动态地将更多 ELB 端点添加到您的 ELB,您必须通过随着时间的推移与客户开放新 IP 地址的痛苦。

不过,对于最初的问题,EB 使用 ELB 到实际不需要静态 IP 地址(没有客户端出站防火墙问题)的 EC2 实例是按照公认答案的最佳方式。

于 2016-09-21T18:49:28.207 回答
2

如果上述解决方案都不起作用,另一种方法是将 NAT 网关附加到私有子网并将 EIP 与 NAT 网关关联。在这种情况下,您可以使用 ELB、使用自动缩放并拥有预留的 EIP。

不过这有点贵,尤其是对于大吞吐量的用例。此外,通过 SSH 连接到实例进行调试变得有点复杂。

于 2020-04-18T00:54:17.430 回答
0

我写了一篇文章,描述了如何在启动新实例时使用 Cloudwatch 规则和 lambda 函数来完成此任务。这是 lambda 函数代码:

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();
const PROD_ENV_NAME = 'my-prod-env-name';

// Example Event
// {
//   "version": "0",
//   "id": "ee376907-2647-4179-9203-343cfb3017a4",
//   "detail-type": "EC2 Instance State-change Notification",
//   "source": "aws.ec2",
//   "account": "123456789012",
//   "time": "2015-11-11T21:30:34Z",
//   "region": "us-east-1",
//   "resources": [
//     "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111"
//   ],
//   "detail": {
//     "instance-id": "i-abcd1111",
//     "state": "running"
//   }
// }

exports.handler = async (event) => {
  console.log("EVENT:", event);

  // The newly launched instance ID.
  const instanceId = event.detail['instance-id'];

  // Fetch info about the newly launched instance
  const result = await ec2.describeInstances({
    Filters: [ { Name: "instance-id", Values: [instanceId] } ]
  }).promise()

  // The instance details are buried in this object
  const instance = result.Reservations[0].Instances[0];
  const isAttached = instance.NetworkInterfaces.find(int => int.Association.IpOwnerId !== 'amazon');

  // Bail if the instance is already attached to another EIP
  if (isAttached) {
    console.log("This instance is already assigned to an elastic IP")
    return { statusCode: 200, body: '' }
  }

  // In elastic beanstalk, the instance name gets assigned to the enviroment name.
  // There is also an environment name tag, which could be used here.
  const name = instance.Tags.find(t => t.Key === 'Name').Value;

  // Only assign EIPs to production instances
  if (name !== PROD_ENV_NAME) {
    console.log('Not a production instance. Not assigning. Instance name:', name)
    return { statusCode: 200, body: ''}
  }

  // Get a list of elastic IP addresses
  const addresses = await ec2.describeAddresses().promise();

  // Filter out addresses already assigned to instances
  const availableAddresses = addresses.Addresses.filter(a => !a.NetworkInterfaceId);

  // Raise an error if we have no more available IP addresses
  if (availableAddresses.length === 0) {
    console.log("ERROR: no available ip addresses");
    return { statusCode: 400, body: JSON.stringify("ERROR: no available ip addresses") }
  }

  const firstAvail = availableAddresses[0]
  try {
    // Associate the instance to the address
    const result = await ec2.associateAddress({
      AllocationId: firstAvail.AllocationId,
      InstanceId: instanceId
    }).promise();

    console.log('allocation result', result)

    return { statusCode: 200, body: JSON.stringify('Associated IP address.') };
  } catch (err) {
      console.log("ERROR: ", err);
  }
};

于 2020-02-18T16:55:29.427 回答
0

您可以按照已接受的答案中所述将环境设置为单实例,或者如果您想使用已创建的弹性 IP,您可以执行以下操作。

.ebextensions项目根目录的文件夹中,创建一个名为setup.config并粘贴以下内容的文件:

container_commands:
    00_setup_elastic_ip:
        command: |
            export AWS_ACCESS_KEY_ID={YOUR-ACCESS-KEY-ID}
            export AWS_SECRET_ACCESS_KEY={YOUR-SECRET-ACCESS-KEY}
            export AWS_DEFAULT_REGION=us-east-1    
            INSTANCE_ID=$(ec2-metadata -i)
            words=( $INSTANCE_ID )
            EC2_ID="${words[1]}"
            aws ec2 associate-address --instance-id $EC2_ID --allocation-id {eipalloc-ID-TO-THE-IP}

您所要做的就是更换其中包含的 3 个部件{},您就可以开始使用了。这会将您的 Elastic Beanstalk 实例的 IP 替换为您选择的弹性 IP。

其中包含的部分{}是(尽管去掉 {},它只是为了向您显示要替换为您的信息的部分):

  1. 您的 AWS 访问密钥 ID
  2. 您的 AWS 秘密访问密钥
  3. 您要分配给 Elastic Beanstalk 环境实例的 Elastic IP 的分配 ID。
于 2022-03-04T14:07:15.903 回答