我正在使用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'NB:当通过cli在EC2实例中直接运行EC2容器时,使用$Hostname的工作,因为shell在完全限定的主机名中替换,这是唯一的;但是我很难找到如何在ECS & CloudFormation中工作。
发布于 2019-11-12 04:13:01
最后,我在Command ContainerDefinitions上使用了自定义的TaskDefinition和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容器中。
发布于 2019-11-08 11:41:42
我所做的是在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您还可以查看这个一,了解如何进行本地测试/开发。
发布于 2021-02-04 16:51:23
添加到语法的答案,要支持集群配置中的Schema (运行多个实例),您必须正确配置侦听器以使用正确的端口。为了避免硬编码端口,可以查询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和合流模式注册表的5.5.3码头映像。
https://stackoverflow.com/questions/58763901
复制相似问题