Укажите имя хоста для экземпляров реестра схем, работающих в ECS.
Я создаю избыточный реестр схем, размещенный в Amazon, для нашего кластера MSK Kafka, используя кластер ECS.
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: Использование $Hostname работает при запуске контейнера докеров непосредственно в экземпляре EC2 через cli, потому что оболочка заменяет полностью определенное имя хоста, которое является уникальным; но я в тупике, пытаясь понять, как заставить эту работу работать в ECS и CloudFormation.
4 ответа
В итоге я пошел с кастомом Command
а также EntryPoint
на TaskDefinition
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
существует в контейнере и правильно отображается на ipv4 экземпляра EC2, на котором работает контейнер.
Для меня это предпочтительнее, потому что мы не контролируем запускаемый контейнер Docker (он общедоступен), и я не хочу заключать его в контейнер Docker, который мы должны поддерживать.
Что я сделал, так это иметь entrypoint
скрипт в образе Docker, который будет искать из метаданных 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
Вы также можете посмотреть на это один о том, как сделать локальное тестирование / развитие, а также.
В дополнение к ответу Syntax для поддержки реестра схем в конфигурации кластера (работает более 1 экземпляра) вам необходимо правильно настроить прослушиватели для использования правильного порта. Чтобы избежать жесткого кодирования портов, можно запросить службу метаданных 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 и образа Docker 5.5.3 реестра Confluent Schema Registry.
Вот решение для работы на 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