Была задача:
Есть ASG_ORIGIN (Origins Wowza). Есть ASG_EDGE (Edges Wowza). Каждая EC2 в ASG_EDGE запускает Wowza SE с модулем StreamResolver, который для своей работы хочет знать IP адреса всех ORIGINs серверов.
Вариант решения был такой:
При изменении состава ASG_ORIGIN (добавилась EC2 или убита) нужно оповестить каждую EC2 в группе ASG_EDGE об этом, и при этом необходимо актуализировать список адресов, который содержится в обычном текстовом файле на каждой EC2 Edge.
Общая схема такая:
1. ASG_ORIGIN отправляет Notification в SNS о том, что у нее изменилось состояние.
2. На SNS оформлена подписка по протоколу Lambda на вызов Lambda функции
3. Lambda функция реализует вызов на каждой EC2 в ASG_EDGE скрипта, который получает список адресов всех живых EC2 в ASG_ORIGIN и записывает их в файлик. Вызов скрипта реализован через SSM.
Lambda (framework python 2.7)
import logging, json
import boto3, botocore
def lambda_handler(event, context):
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#logger.info("Received event: " + json.dumps(event, indent=2))
message = json.loads(event['Records'][0]['Sns']['Message'])
asgname = message['AutoScalingGroupName']
logger.info("ASG name From SNS: " + asgname)
autoscale = boto3.client('autoscaling')
groups = autoscale.describe_auto_scaling_groups(
AutoScalingGroupNames=['ASG_EDGE']
)
hostList = []
for r in groups['AutoScalingGroups']:
for inst in r['Instances']:
hostList.append(inst['InstanceId'])
instance_ids = ' '.join(["'%s'" % w for w in hostList])
command = 'sh /usr/local/tmp/getIPsOrigins.sh ' + asgname
ssm = boto3.client('ssm')
ssmresponse = ssm.send_command(InstanceIds=hostList, DocumentName='AWS-RunShellScript', Parameters= { 'commands': [command] } )
-----------------------
Выделено красным - обращаю внимание что тут в конце скрипта и ковычкой - обязательный пробел.
Lambda внутри VPC, с привязкой к подсеткам и роли.
Роль для функции должна иметь Attach Policy: AmazonEC2RoleforSSM а также права на ресурсы describe для ASG, EC2. Так же следует описать Trust Relationship между lambda, ssm, ec2.
Если не будет прав, то будет постоянно получатся ошибка, которую диагностировать сложно, ибо она звучать будет так - не корректный EC2 Id.
Так же должен быть установлен SSM агент: http://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html#sysman-install-ssm-agent
Скрипт, который вызывает SSM: (getIPsOrigins.sh)
ASGOriginName="ASG_ORIGIN"
aws ec2 describe-instances --filters "Name=tag:aws:autoscaling:groupName,Values=${ASGOriginName}" "Name=instance-state-name,Values=running" --region us-east-1 | jq ".Reservations[].Instances[].PrivateIpAddress"|cut -d "\"" -f 2 >/usr/local/conf/origins.lst
в итоге в /usr/local/conf/ появится файлик origins.lst с IP адресами всех Origin серверов.
Есть ASG_ORIGIN (Origins Wowza). Есть ASG_EDGE (Edges Wowza). Каждая EC2 в ASG_EDGE запускает Wowza SE с модулем StreamResolver, который для своей работы хочет знать IP адреса всех ORIGINs серверов.
Вариант решения был такой:
При изменении состава ASG_ORIGIN (добавилась EC2 или убита) нужно оповестить каждую EC2 в группе ASG_EDGE об этом, и при этом необходимо актуализировать список адресов, который содержится в обычном текстовом файле на каждой EC2 Edge.
Общая схема такая:
1. ASG_ORIGIN отправляет Notification в SNS о том, что у нее изменилось состояние.
2. На SNS оформлена подписка по протоколу Lambda на вызов Lambda функции
3. Lambda функция реализует вызов на каждой EC2 в ASG_EDGE скрипта, который получает список адресов всех живых EC2 в ASG_ORIGIN и записывает их в файлик. Вызов скрипта реализован через SSM.
Lambda (framework python 2.7)
import logging, json
import boto3, botocore
def lambda_handler(event, context):
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#logger.info("Received event: " + json.dumps(event, indent=2))
message = json.loads(event['Records'][0]['Sns']['Message'])
asgname = message['AutoScalingGroupName']
logger.info("ASG name From SNS: " + asgname)
autoscale = boto3.client('autoscaling')
groups = autoscale.describe_auto_scaling_groups(
AutoScalingGroupNames=['ASG_EDGE']
)
hostList = []
for r in groups['AutoScalingGroups']:
for inst in r['Instances']:
hostList.append(inst['InstanceId'])
instance_ids = ' '.join(["'%s'" % w for w in hostList])
command = 'sh /usr/local/tmp/getIPsOrigins.sh ' + asgname
ssm = boto3.client('ssm')
ssmresponse = ssm.send_command(InstanceIds=hostList, DocumentName='AWS-RunShellScript', Parameters= { 'commands': [command] } )
-----------------------
Выделено красным - обращаю внимание что тут в конце скрипта и ковычкой - обязательный пробел.
Lambda внутри VPC, с привязкой к подсеткам и роли.
Роль для функции должна иметь Attach Policy: AmazonEC2RoleforSSM а также права на ресурсы describe для ASG, EC2. Так же следует описать Trust Relationship между lambda, ssm, ec2.
Если не будет прав, то будет постоянно получатся ошибка, которую диагностировать сложно, ибо она звучать будет так - не корректный EC2 Id.
Так же должен быть установлен SSM агент: http://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html#sysman-install-ssm-agent
Скрипт, который вызывает SSM: (getIPsOrigins.sh)
ASGOriginName="ASG_ORIGIN"
aws ec2 describe-instances --filters "Name=tag:aws:autoscaling:groupName,Values=${ASGOriginName}" "Name=instance-state-name,Values=running" --region us-east-1 | jq ".Reservations[].Instances[].PrivateIpAddress"|cut -d "\"" -f 2 >/usr/local/conf/origins.lst
в итоге в /usr/local/conf/ появится файлик origins.lst с IP адресами всех Origin серверов.
PS: если нужно выполнить SSM скрипт только для одной EC2, важно следующее:
вот в этой строке
ssmresponse = ssm.send_command(InstanceIds=hostList, DocumentName='AWS-RunShellScript', Parameters= { 'commands': [command] } )
InstanceIds хочет видеть List. не строку а именно список.
Формировать его следует так:
hostList = []
hostList.append('InstanceId')
вот в этой строке
ssmresponse = ssm.send_command(InstanceIds=hostList, DocumentName='AWS-RunShellScript', Parameters= { 'commands': [command] } )
InstanceIds хочет видеть List. не строку а именно список.
Формировать его следует так:
hostList = []
hostList.append('InstanceId')
Комментариев нет:
Отправить комментарий