1

我正在使用 ECS 集群为我们的 MSK Kafka 集群构建在 Amazon 中托管的冗余模式注册表。

SchemaRegistry TaskDefinition 需要定义一个主机名,该主机名在运行时对每个任务都是唯一的。

SchemaRegistryTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Ref SchemaRegistryTaskName
      RequiresCompatibilities: [ EC2 ]
      NetworkMode: bridge
      Cpu: !Ref CPUReservation
      Memory: !Ref MemoryReservation
      Volumes: []
      ContainerDefinitions:
        - Name: !Ref SchemaRegistryTaskName
          Image: !Ref SchemaRegistryTaskImage
          Essential: true
          PortMappings:
            - ContainerPort: !Ref SchemaRegistryPort
              HostPort: 0 # Randomly assigned port from the ephemeral port range.
          Environment:
            - Name: AWS_DEFAULT_REGION
              Value: !Ref AWS::Region
            - Name: SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS
              Value: !Ref MskBrokerUrls
            - Name: SCHEMA_REGISTRY_HOST_NAME
              Value: $HOSTNAME
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref 'CloudwatchLogsGroup'
              awslogs-region: !Ref 'AWS::Region'

注意:当通过 cli 直接在 EC2 实例中运行 docker 容器时,使用 $Hostname 有效,因为 shell 替换为唯一的完全限定主机名;但我很难弄清楚如何在 ECS 和 CloudFormation 中进行这项工作。

4

4 回答 4

4

最后我带着一个习惯CommandEntryPointTaskDefinition ContainerDefinitions;使用@Apolozeus 建议的元数据端点:

EntryPoint: ["/bin/bash"]
Command: ["-c","(export SCHEMA_REGISTRY_HOST_NAME=$(wget -qO- 169.254.169.254/latest/meta-data/local-ipv4);/etc/confluent/docker/run)"]

这确保SCHEMA_REGISTRY_HOST_NAME容器上存在环境变量,并正确映射到容器运行的 EC2 实例的 ipv4。

这对我来说更可取,因为我们不控制正在运行的 Docker 容器(它是公开可用的),而且我不想用我们必须维护的 Docker 容器来包装它。

于 2019-11-12T04:13:01.007 回答
4

我所做的是entrypoint在 Docker 映像中有脚本,它将从 ECS 元中进行查找,并将值公开为 environment SCHEMA_REGISTRY_HOST_NAME。请在下面找到示例脚本。

#!/bin/sh

#########
# Detect whether this is running in an ECS cluster
#########
curl --max-time 1 -s --fail -o /dev/null http://169.254.169.254/
if [[ 0 -eq $? ]]; then
    echo "AWS environment was detected - looking up HOST IP from metadata"
    SCHEMA_REGISTRY_HOST_NAME=$(curl http://169.254.169.254/latest/meta-data/local-ipv4 -s)
    export SCHEMA_REGISTRY_HOST_NAME
else
    echo "Not running in AWS environment. Will not set SCHEMA_REGISTRY_HOST_NAME"
fi

你也可以看看这个关于如何进行本地测试/开发的文章。

于 2019-11-08T11:41:42.997 回答
1

添加到语法的答案,要在集群配置中支持模式注册表(运行超过 1 个实例),您必须正确配置侦听器以使用正确的端口。为了避免硬编码端口,可以查询 ECS 元数据服务并将其编织到 Schema Registry 配置中,如下所示:

EntryPoint: ["/bin/bash"]
Command: ["-c","(
   export SCHEMA_REGISTRY_HOST_NAME=$(curl 169.254.169.254/latest/meta-data/local-ipv4);
   curl $ECS_CONTAINER_METADATA_URI_V4 > ecs.json;
   export HOST_PORT=$(python -c \"import json; f = open('ecs.json').read(); data = json.loads(f); print(data['Ports'][0]['HostPort'])\");
   export SCHEMA_REGISTRY_LISTENERS=\"http://0.0.0.0:$HOST_PORT,http://0.0.0.0:8081\";
   /etc/confluent/docker/run)"]

需要额外的侦听器配置,因为 $HOST_PORT 是实际端口,它将被通告给 Schema Registry 的其他实例,以将写入操作转发到主服务器。

如果使用接受的答案,您的副本将无法这样做,因为默认情况下它们会尝试将流量发送到 8081,这很可能不会是 ECS 公开的端口。

这适用于 ECS 代理 1.50 和 Confluent Schema Registry 的 5.5.3 Docker 映像。

于 2021-02-04T16:51:23.310 回答
0

这是基于上述答案之一在 ECS Fargate 上运行的解决方案。这取决于是否拥有,jq因此您可能需要安装它。它也被硬编码到第一个网络,这可能不适合您的用例。


#########
# Detect whether this is running in an ECS cluster
#########
curl --max-time 1 -s --fail -o /dev/null ${ECS_CONTAINER_METADATA_URI_V4}

if [[ 0 -eq $? ]]; then
    echo "AWS environment was detected - looking up HOST IP from metadata"
    curl ${ECS_CONTAINER_METADATA_URI_V4} > meta.json
    SCHEMA_REGISTRY_HOST_NAME=$(jq '.Networks[0].IPv4Addresses[0]' meta.json -r) 
    export SCHEMA_REGISTRY_HOST_NAME
else
    echo "Not running in AWS environment. Will not set SCHEMA_REGISTRY_HOST_NAME"
fi
于 2021-11-16T11:57:44.030 回答