为 ECS 中的 Schema Registry 实例 运行 提供主机名
Provide hostname to Schema Registry instances running within ECS
我正在使用 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'
注意: 当 运行 docker 容器通过 cli 直接在 EC2 实例中时,使用 $Hostname 有效,因为 shell 替换为唯一的完全限定主机名;但我很难弄清楚如何在 ECS 和 CloudFormation 中完成这项工作。
我所做的是在 Docker 图像中添加 entrypoint
脚本,它将从 ECS 元数据中进行查找,并将值公开为环境 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
您也可以查看此 one 了解如何进行本地操作 testing/development。
最后我在 TaskDefinition
ContainerDefinitions
上使用了自定义 Command
和 EntryPoint
;使用@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 我们必须维护的容器。
添加到 Syntax 的答案中,要在集群配置(运行 超过 1 个实例)中支持 Schema Registry,您必须正确配置侦听器以使用正确的端口。为避免对端口进行硬编码,可以查询 ECS 元数据服务并将其编织到架构注册表配置中,如下所示:
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 是实际端口,将被公布给架构注册表的其他实例,以将写入操作转发给主服务器。
如果使用已接受的答案,您的副本将无法这样做,因为默认情况下它们会尝试将流量发送到 8081,这很可能不是将由 ECS 公开的端口。
这适用于 ECS 代理 1.50 和 Confluent Schema Registry 的 5.5.3 Docker 图像。
如果 运行 在 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
我正在使用 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'
注意: 当 运行 docker 容器通过 cli 直接在 EC2 实例中时,使用 $Hostname 有效,因为 shell 替换为唯一的完全限定主机名;但我很难弄清楚如何在 ECS 和 CloudFormation 中完成这项工作。
我所做的是在 Docker 图像中添加 entrypoint
脚本,它将从 ECS 元数据中进行查找,并将值公开为环境 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
您也可以查看此 one 了解如何进行本地操作 testing/development。
最后我在 TaskDefinition
ContainerDefinitions
上使用了自定义 Command
和 EntryPoint
;使用@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 我们必须维护的容器。
添加到 Syntax 的答案中,要在集群配置(运行 超过 1 个实例)中支持 Schema Registry,您必须正确配置侦听器以使用正确的端口。为避免对端口进行硬编码,可以查询 ECS 元数据服务并将其编织到架构注册表配置中,如下所示:
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 是实际端口,将被公布给架构注册表的其他实例,以将写入操作转发给主服务器。
如果使用已接受的答案,您的副本将无法这样做,因为默认情况下它们会尝试将流量发送到 8081,这很可能不是将由 ECS 公开的端口。
这适用于 ECS 代理 1.50 和 Confluent Schema Registry 的 5.5.3 Docker 图像。
如果 运行 在 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