--- AWSTemplateFormatVersion: 2010-09-09 Description: Openvidu Pro With Master Replication Parameters: DomainName: Description: 'Domain name which will be used to access OpenVidu Pro. This domain name should point to the Load Balancer URL after the stack is deployed.' Type: 'String' AllowedPattern: ^$|^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$ MinLength: 1 ConstraintDescription: The domain name does not have a valid domain name format KeyName: Description: 'Name of an existing EC2 KeyPair to enable SSH access to the instance. It is mandatory to perform some administrative tasks on instances.' Type: 'AWS::EC2::KeyPair::KeyName' AllowedPattern : '.+' ConstraintDescription: 'Must be defined and to be an existing EC2 KeyPair' OpenViduLicense: Description: 'Visit https://openvidu.io/account' Type: String AllowedPattern: ^(?!\s*$).+$ MinLength: 1 NoEcho: true ConstraintDescription: OpenVidu Pro License is mandatory OpenViduSecret: Description: 'Secret to connect to this OpenVidu Platform. Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ("-") and underscores ("_")' Type: String AllowedPattern: ^[a-zA-Z0-9_-]+$ MinLength: 1 NoEcho: true ConstraintDescription: 'Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ("-") and underscores ("_")' MediaServer: Description: 'Media Server to be deployed in Media Nodes' Type: String Default: mediasoup AllowedValues: - mediasoup - kurento ConstraintDescription: 'Must be a valid EC2 instance type' OpenViduProClusterId: Description: 'Unique identifier for the OpenVidu Pro cluster' Type: String MinLength: 1 AllowedPattern: ^[a-z0-9_-]+$ ConstraintDescription: 'Cannot be empty and must contain only lowercase characters [a-z0-9], hypens ("-") and underscores ("_")' OpenViduS3BucketName: Description: "Bucket to save configuration and recordings. If not defined, a default one will be created" Type: String Default: '' OpenViduS3ConfigAutoRestart: Description: "If true, changes at in .env file in S3 bucket will restart automatically all master nodes." Type: String AllowedValues: - true - false Default: true OpenViduRecording: Description: "If 'true', recordings will be saved in an s3 bucket created by this cloudformation, or the defined one at OpenViduS3Bucket" Type: String AllowedValues: - true - false Default: true CoturnInMediaNodes: Description: "If true, Coturn will be deployed on media nodes. Otherwise it will be deployed in master nodes." Type: String AllowedValues: - true - false Default: false # Elasticsearch configuration ElasticsearchUrl: Description: 'Put here the url to the service. It is mandatory to have an Elasticsearch deployed' Type: String AllowedPattern: ^(http|https):\/\/.*:[1-9]{1,5}+.*$ ConstraintDescription: 'Elasticsearch URL is mandatory and it is very important to specify the Elasticsearch URL with the port used by this service. For example: https://es-example:443' KibanaUrl: Description: 'Put here the url to the service. It is mandatory to have a Kibana deployed' Type: String AllowedPattern: ^(http|https):\/\/.*:[1-9]{1,5}+.*$ ConstraintDescription: 'Kibana URL is mandatory and it is very important to specify the url with port used by this service. For example: https://kibana-example:443' ElasticsearchUser: Description: 'Username for Elasticsearch and Kibana' Type: String AllowedPattern: ^((?!")(?! ).)+$ ConstraintDescription: Elasticsearch user is mandatory (no whitespaces or quotations allowed) ElasticsearchPassword: Description: 'Password for Elasticsearch and Kibana' Type: String AllowedPattern: ^((?!")(?! ).)+$ NoEcho: true ConstraintDescription: Elasticsearch password is mandatory (no whitespaces or quotations allowed) LoadBalancerCertificateARN: Description: 'Amazon certificate arn resource to load into the LoadBalancer' Type: String AllowedPattern: '.+' ConstraintDescription: The Load Balancer domain name must be defined AwsInstanceTypeOV: Description: 'Specifies the EC2 instance type for your OpenVidu Server Pro Node' Type: String Default: c5.xlarge AllowedValues: - t2.medium - t2.large - t2.xlarge - t2.2xlarge - t3.large - t3.xlarge - t3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m4.16xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge - m5.12xlarge - m5.16xlarge - m5.24xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5.12xlarge - c5.18xlarge - c5.24xlarge - c6a.large - c6a.xlarge - c6a.2xlarge - c6a.4xlarge - c6a.8xlarge - c6a.12xlarge - c6a.16xlarge - c6a.24xlarge - c6a.32xlarge - c6a.48xlarge - c6a.metal ConstraintDescription: 'Must be a valid EC2 instance type' AwsInstanceTypeKMS: Description: 'Specifies the EC2 instance type for your Media Nodes' Type: String Default: c5.xlarge AllowedValues: - t2.medium - t2.large - t2.xlarge - t2.2xlarge - t3.large - t3.xlarge - t3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m4.16xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge - m5.12xlarge - m5.16xlarge - m5.24xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5.12xlarge - c5.18xlarge - c5.24xlarge - c6a.large - c6a.xlarge - c6a.2xlarge - c6a.4xlarge - c6a.8xlarge - c6a.12xlarge - c6a.16xlarge - c6a.24xlarge - c6a.32xlarge - c6a.48xlarge - c6a.metal ConstraintDescription: 'Must be a valid EC2 instance type' MinMasterNodes: Description: 'Minimun number of Master Nodes' Type: Number Default: 1 MinValue: 1 ConstraintDescription: 'A Minimun number of Master Nodes is mandatory' MaxMasterNodes: Description: 'Maximum number of Master Nodes' Type: Number Default: 4 MinValue: 1 ConstraintDescription: 'A Maximum number of Master Nodes is mandatory' DesiredMasterNodes: Description: 'Desired number of Master Nodes' Type: Number Default: 1 MinValue: 1 ConstraintDescription: 'A desired number of Master Nodes is mandatory' MinMediaNodes: Description: 'Minimun number of Media Nodes' Type: Number Default: 1 MinValue: 1 ConstraintDescription: 'A Minimun number of Master Nodes is mandatory' MaxMediaNodes: Description: 'Maximum number of Media Nodes' Type: Number Default: 4 MinValue: 1 ConstraintDescription: 'A Maximum number of Master Nodes is mandatory' ScaleUpMediaNodesAvgCpu: Description: 'Scale up media nodes when avg cpu is greater the specified value' Type: Number Default: 70 MinValue: 0 ConstraintDescription: 'A desired number of Master Nodes is mandatory' ScaleDownMediaNodesAvgCpu: Description: 'Scale down media nodes when avg cpu is below the specified value' Type: Number Default: 30 MinValue: 1 ConstraintDescription: 'A desired number of Master Nodes is mandatory' DesiredMediaNodes: Description: 'Desired number of Media Nodes' Type: Number Default: 1 MinValue: 1 ConstraintDescription: 'A desired number of Master Nodes is mandatory' OpenViduVPC: Description: 'Dedicated VPC for OpenVidu cluster' Type: AWS::EC2::VPC::Id OpenViduSubnets: Description: 'Subnet for OpenVidu cluster' Type: List #start_mappings Mappings: OVAMIMAP: eu-west-1: AMI: OV_MASTER_REPLICATION_AMI_ID KMSAMIMAP: eu-west-1: AMI: KMS_AMI_ID #end_mappings Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: OpenVidu configuration Parameters: - DomainName - OpenViduProClusterId - OpenViduLicense - OpenViduSecret - MediaServer - OpenViduS3BucketName - OpenViduS3ConfigAutoRestart - OpenViduRecording - CoturnInMediaNodes - Label: default: Elasticsearch and Kibana configuration Parameters: - ElasticsearchUrl - KibanaUrl - ElasticsearchUser - ElasticsearchPassword - Label: default: EC2 and Autoscaling configuration Parameters: - AwsInstanceTypeOV - AwsInstanceTypeKMS - KeyName - MinMasterNodes - MaxMasterNodes - DesiredMasterNodes - MinMediaNodes - MaxMediaNodes - DesiredMediaNodes - ScaleUpMediaNodesAvgCpu - ScaleDownMediaNodesAvgCpu - Label: default: Load Balancer Certificate Configuration Parameters: - LoadBalancerCertificateARN - Label: default: Networking configuration Parameters: - OpenViduVPC - OpenViduSubnets ParameterLabels: # OpenVidu General Configuration DomainName: default: 'Domain Name' OpenViduProClusterId: default: 'OpenVidu Pro Cluster Id' OpenViduLicense: default: 'OpenVidu Pro License' OpenViduSecret: default: 'OpenVidu Secret' MediaServer: default: 'Media Server' OpenViduS3BucketName: default: 'S3 Bucket where recordings and OpenVidu configuration will be stored' OpenViduS3ConfigAutoRestart: default: 'Auto Restart OpenVidu on S3 bucket .env changes' OpenViduRecording: default: 'Enable OpenVidu Recording' CoturnInMediaNodes: default: 'Deploy Coturn in Media Nodes. (Experimental)' # Elasticsearch and Kibana Configuration ElasticsearchUrl: default: 'Elasticsearch URL' KibanaUrl: default: 'Kibana URL' ElasticsearchUser: default: 'Elasticsearch and Kibana username' ElasticsearchPassword: default: 'Elasticsearch and Kibana password' # SSL Certificate Configuration LoadBalancerCertificateARN: default: 'ARN of the AWS Certificate. This certificate must be valid for "Domain Name"' # EC2 And Autoscaling Configuration AwsInstanceTypeOV: default: "Master Nodes instance type" AwsInstanceTypeKMS: default: 'Media Nodes instance type' KeyName: default: 'SSH Key Name' MinMasterNodes: default: 'Minimum Master Nodes' MaxMasterNodes: default: 'Maximum Master Nodes' DesiredMasterNodes: default: 'Desired Master Nodes' DesiredMediaNodes: default: 'Desired Media Nodes' MinMediaNodes: default: 'Minimum Media Nodes' MaxMediaNodes: default: 'Maximum Media Nodes' ScaleUpMediaNodesAvgCpu: default: 'Scale Up Media Nodes on Average CPU' ScaleDownMediaNodesAvgCpu: default: 'Scale Down Media Nodes on Average CPU' # Networking Configuration OpenViduVPC: default: 'OpenVidu Pro VPC' OpenViduSubnets: default: 'OpenVIdu Pro Subnets' Conditions: CreateS3Bucket: !Equals [ !Ref OpenViduS3BucketName, ''] Resources: ##### # S3 bucket ##### S3OpenViduBucket: Type: 'AWS::S3::Bucket' DeletionPolicy: Retain UpdateReplacePolicy: Retain Properties: ### Unique bucket name using Stack ID BucketName: !Join [ "-", [ !Ref OpenViduProClusterId, !Select [0, !Split ["-", !Select [2, !Split [/, !Ref AWS::StackId ]]]] ] ] AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls : true RestrictPublicBuckets: true Condition: CreateS3Bucket ##### # Security groups ##### # Security group with all open ports necessary for OpenVidu Pro to work # Only the Load Balancer has access to replication-manager port 4443 which proxies to OpenVidu Pro OpenViduSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: SSH and OpenVidu WebRTC Ports GroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'OpenViduSecurityGroup'] ] VpcId: !Ref OpenViduVPC Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'OpenViduSecurityGroup'] ] SecurityGroupIngress: - IpProtocol: udp FromPort: 3478 ToPort: 3478 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 3478 ToPort: 3478 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 3478 ToPort: 3478 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 3478 ToPort: 3478 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 4443 ToPort: 4443 SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup - IpProtocol: tcp FromPort: 5443 ToPort: 5443 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 40000 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 40000 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 40000 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 40000 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIpv6: ::/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: udp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 # This security groups Ingress rule is for OpenVidu Pro Master instances which only need access # to other OpenVidu Pro instances at port 5443 and 4443 to proxy requests from replication-manager OpenViduSecurityGroupIngressServer: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref OpenViduSecurityGroup IpProtocol: tcp FromPort: 5443 ToPort: 5443 SourceSecurityGroupId: !Ref OpenViduSecurityGroup OpenViduSecurityGroupIngressReplicationManager: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref OpenViduSecurityGroup IpProtocol: tcp FromPort: 4443 ToPort: 4443 SourceSecurityGroupId: !Ref OpenViduSecurityGroup LoadBalancerSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref OpenViduVPC GroupDescription: Load Balancer Security group GroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'LoadBalancerSecurityGroup'] ] Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'LoadBalancerSecurityGroup'] ] SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIpv6: ::/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: udp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 # Redis Security group. # Let access only to instances with OpenVidu Pro security group attached RedisSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref OpenViduVPC GroupDescription: Security Group for OpenVidu Pro Redis GroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'RedisSecurityGroup'] ] Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'RedisSecurityGroup'] ] SecurityGroupIngress: - IpProtocol: tcp FromPort: 6379 ToPort: 6379 SourceSecurityGroupId: !Ref OpenViduSecurityGroup SecurityGroupEgress: - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 # Media Nodes Security group. Let access only to # instances with OpenVidu Pro security group attached # to ports 3000 and 8888 MediaNodeSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref OpenViduVPC GroupDescription: SSH, Media Node controller and KMS WebRTC Ports GroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'KMSSecurityGroup'] ] Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'KMSSecurityGroup'] ] SecurityGroupIngress: - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIpv6: ::/0 - IpProtocol: udp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 443 ToPort: 443 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 3000 ToPort: 3000 SourceSecurityGroupId: !Ref OpenViduSecurityGroup - IpProtocol: tcp FromPort: 8888 ToPort: 8888 SourceSecurityGroupId: !Ref OpenViduSecurityGroup - IpProtocol: udp FromPort: 40000 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 40000 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 40000 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 40000 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIpv6: ::/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 - IpProtocol: udp FromPort: 1 ToPort: 65535 CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 1 ToPort: 65535 CidrIpv6: ::/0 ##### # Redis Cluster ##### RedisClusterSubnetGroup: Type: AWS::ElastiCache::SubnetGroup Properties: CacheSubnetGroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'RedisSubnetGroup'] ] Description: Subnet where to deploy Redis SubnetIds: !Ref OpenViduSubnets RedisCluster: Type: AWS::ElastiCache::CacheCluster Properties: ClusterName: !Join [ "-", [ !Ref 'AWS::StackName', 'Redis'] ] CacheNodeType: cache.t3.medium Engine: redis EngineVersion: 6.x NumCacheNodes: 1 CacheParameterGroupName: default.redis6.x CacheSubnetGroupName: !Ref RedisClusterSubnetGroup VpcSecurityGroupIds: - !Ref RedisSecurityGroup Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'Redis'] ] ##### # Media Node Autoscaling Group ##### MediaNodeAutoScalingLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: LaunchConfigurationName: !Join [ "-", [ !Ref 'AWS::StackName', 'ASGMediaNodeLaunchConfiguration'] ] SecurityGroups: - !Ref MediaNodeSecurityGroup ImageId: !GetAtt LambdaOnCreateInvoke.MediaNodeImageId KeyName: !Ref KeyName InstanceType: !Ref AwsInstanceTypeKMS MediaNodeAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'ASGMediaNode'] ] LaunchConfigurationName: !Ref MediaNodeAutoScalingLaunchConfiguration MinSize: !Ref MinMediaNodes MaxSize: !Ref MaxMediaNodes DesiredCapacity: !Ref DesiredMediaNodes VPCZoneIdentifier: !Ref OpenViduSubnets NewInstancesProtectedFromScaleIn: true Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'Media Node'] ] PropagateAtLaunch: true - Key: ov-cluster-member Value: kms PropagateAtLaunch: true - Key: ov-medianode-status Value: running PropagateAtLaunch: true ##### # SQS Queue ##### SQSPolicy: Type: AWS::SQS::QueuePolicy Properties: Queues: - !Ref SQSQueue PolicyDocument: Statement: - Effect: Allow Action: - 'sqs:SendMessage' Principal: Service: - events.amazonaws.com Resource: - !GetAtt SQSQueue.Arn SQSQueue: Type: AWS::SQS::Queue Properties: QueueName: !Join ['-', [ !Ref 'AWS::StackName', 'SQS.fifo'] ] FifoQueue: true MessageRetentionPeriod: 60 VisibilityTimeout: 50 ContentBasedDeduplication: true Tags: - Key: Name Value: !Join ['-', [ !Ref 'AWS::StackName', 'SQS'] ] ##### # Load Balancer ##### LoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Join ['-', [ !Ref 'AWS::StackName', 'lb'] ] Subnets: !Ref OpenViduSubnets SecurityGroups: - !Ref LoadBalancerSecurityGroup Tags: - Key: Name Value: !Join ['-', [ !Ref 'AWS::StackName', 'lb'] ] HttpLoadBalancerListener: Type: "AWS::ElasticLoadBalancingV2::Listener" Properties: DefaultActions: - Type: "redirect" RedirectConfig: Protocol: "HTTPS" Port: '443' Host: "#{host}" Path: "/#{path}" Query: "#{query}" StatusCode: "HTTP_301" LoadBalancerArn: !Ref LoadBalancer Port: 80 Protocol: "HTTP" LoadBalancerListener: Type: 'AWS::ElasticLoadBalancingV2::Listener' Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref TargetGroup LoadBalancerArn: !Ref LoadBalancer Port: 443 Protocol: HTTPS Certificates: - CertificateArn: !Ref LoadBalancerCertificateARN RootListenerRule: Type: 'AWS::ElasticLoadBalancingV2::ListenerRule' Properties: ListenerArn: !Ref LoadBalancerListener Priority: 1 Conditions: - Field: path-pattern Values: - / Actions: - Type: "fixed-response" FixedResponseConfig: StatusCode: "401" InspectorListenerRule: Type: 'AWS::ElasticLoadBalancingV2::ListenerRule' Properties: ListenerArn: !Ref LoadBalancerListener Priority: 2 Conditions: - Field: path-pattern Values: - /inspector Actions: - Type: "redirect" RedirectConfig: Protocol: "HTTPS" Port: '443' Host: "#{host}" Path: "/inspector/" Query: "#{query}" StatusCode: "HTTP_301" ListenerRule: Type: 'AWS::ElasticLoadBalancingV2::ListenerRule' Properties: ListenerArn: !Ref LoadBalancerListener Priority: 3 Conditions: - Field: path-pattern Values: - /openvidu* Actions: - TargetGroupArn: !Ref TargetGroup Type: forward TargetGroup: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: Name: !Ref 'AWS::StackName' VpcId: !Ref OpenViduVPC Port: 4443 Protocol: HTTP Matcher: HttpCode: '200' HealthCheckIntervalSeconds: 10 HealthCheckPath: /openvidu/health HealthCheckProtocol: HTTP HealthCheckPort: '4443' HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 3 UnhealthyThresholdCount: 4 Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'TargetGroup'] ] ##### # OpenVidu Pro Master Role ##### OpenViduProMasterRole: Type: 'AWS::IAM::Role' Properties: Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'MasterNodeRole'] ] AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' Path: / Policies: - PolicyName: !Join ['-', [ !Ref 'AWS::StackName', 'MasterNodePolicy'] ] PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'ec2:Describe*' - 'ec2:CreateTags' - 'ec2:DescribeTags' Resource: '*' - Effect: Allow Action: - 'sqs:*' Resource: !GetAtt SQSQueue.Arn - Effect: Allow Action: - 'autoscaling:SetInstanceHealth' - 'autoscaling:DescribeAutoScalingInstances' - 'autoscaling:DescribeAutoScalingGroups' - 'autoscaling:SetInstanceProtection' Resource: '*' - Effect: Allow Action: - 's3:DeleteObject' - 's3:GetObject' - 's3:PutObject' Resource: - Fn::If: - CreateS3Bucket # If bucket is created, get ARN - !Join [ "", [ !GetAtt S3OpenViduBucket.Arn, "/*" ] ] # If bucket name is defined, use bucket name - !Join [ "", [ 'arn:aws:s3:::', !Ref OpenViduS3BucketName, '/*'] ] - Effect: Allow Action: - 's3:ListBucket' - 's3:GetBucketLocation' Resource: - Fn::If: - CreateS3Bucket # If bucket is created, get ARN - !Join [ "", [ !GetAtt S3OpenViduBucket.Arn ] ] # If bucket name is defined, use bucket name - !Join [ "", [ 'arn:aws:s3:::', !Ref OpenViduS3BucketName ]] RoleName: !Join ['-', [ !Ref 'AWS::StackName', 'MasterNodeRole'] ] OpenViduProMasterInstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref OpenViduProMasterRole ##### # OpenVidu Pro Master AutoScaling Group ##### OpenViduProMasterNodeAutoScalingLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Properties: LaunchConfigurationName: !Join [ "-", [ !Ref 'AWS::StackName', 'ASGMasterNodeLaunchConfiguration'] ] SecurityGroups: - !Ref OpenViduSecurityGroup IamInstanceProfile: !Ref OpenViduProMasterInstanceProfile ImageId: !GetAtt LambdaOnCreateInvoke.MasterNodeImageId KeyName: !Ref KeyName InstanceType: !Ref AwsInstanceTypeOV UserData: Fn::Base64: Fn::Sub: - | DOMAIN_OR_PUBLIC_IP=${DomainNameVar} | \ OPENVIDU_ENTERPRISE_MEDIA_SERVER=${MediaServer} | \ OPENVIDU_PRO_LICENSE=${OpenViduLicense} | \ OPENVIDU_SECRET=${OpenViduSecret} | \ OPENVIDU_PRO_CLUSTER_ID=${OpenViduProClusterId} | \ OPENVIDU_PRO_ELASTICSEARCH_HOST=${ElasticsearchUrl} | \ OPENVIDU_PRO_KIBANA_HOST=${KibanaUrl} | \ ELASTICSEARCH_USERNAME=${ElasticsearchUser} | \ ELASTICSEARCH_PASSWORD=${ElasticsearchPassword} | \ RM_REDIS_IP=${RedisHostName} | \ RM_REDIS_PORT=${RedisPort} | \ RM_SQS_QUEUE=${SqsQueueName} | \ RM_CLOUDFORMATION_ARN=${AWS::StackId} | \ OPENVIDU_PRO_CONFIG_S3_BUCKET=${OpenViduS3BucketParam} | \ RM_MEDIA_NODES_AUTOSCALING_GROUP_NAME=${MediaNodesAutoscalingGroupName} | \ RM_MASTER_NODES_AUTOSCALING_GROUP_NAME=${MasterNodesAutoscalingGroupName} | \ OPENVIDU_RECORDING=${OpenViduRecording} \ OPENVIDU_PRO_COTURN_IN_MEDIA_NODES=${CoturnInMediaNodes} | \ OPENVIDU_ENTERPRISE_S3_CONFIG_AUTORESTART=${OpenViduS3ConfigAutoRestart} - DomainNameVar: !Ref DomainName RedisHostName: !GetAtt RedisCluster.RedisEndpoint.Address RedisPort: !GetAtt RedisCluster.RedisEndpoint.Port SqsQueueName: !GetAtt SQSQueue.QueueName MediaNodesAutoscalingGroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'ASGMediaNode'] ] MasterNodesAutoscalingGroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'ASGOpenViduProMasterNode'] ] OpenViduS3BucketParam: !If [ CreateS3Bucket, !Ref S3OpenViduBucket, !Ref OpenViduS3BucketName ] OpenViduProMasterNodeAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Join [ "-", [ !Ref 'AWS::StackName', 'ASGOpenViduProMasterNode'] ] LaunchConfigurationName: !Ref OpenViduProMasterNodeAutoScalingLaunchConfiguration TargetGroupARNs: - !Ref TargetGroup MinSize: !Ref MinMasterNodes MaxSize: !Ref MaxMasterNodes DesiredCapacity: !Ref DesiredMasterNodes VPCZoneIdentifier: !Ref OpenViduSubnets HealthCheckType: ELB HealthCheckGracePeriod: 180 Tags: - Key: Name Value: !Join [ "-", [ !Ref 'AWS::StackName', 'Master Node'] ] PropagateAtLaunch: true - Key: ov-cluster-member Value: server PropagateAtLaunch: true ##### # Media Node Autoscaling Lifecycle hooks ##### LaunchMediaNodeLifeCycleHook: Type: AWS::AutoScaling::LifecycleHook Properties: LifecycleHookName: !Join [ "-", [ !Ref 'AWS::StackName', 'LaunchMediaNodeLifeCycleHook'] ] AutoScalingGroupName: !Ref MediaNodeAutoScalingGroup LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING DefaultResult: CONTINUE HeartbeatTimeout: 30 TerminateMediaNodeLifeCycleHook: Type: AWS::AutoScaling::LifecycleHook Properties: LifecycleHookName: !Join [ "-", [ !Ref 'AWS::StackName', 'TerminateMediaNodeLifeCycleHook'] ] AutoScalingGroupName: !Ref MediaNodeAutoScalingGroup LifecycleTransition: autoscaling:EC2_INSTANCE_TERMINATING DefaultResult: ABANDON HeartbeatTimeout: 30 ########## # AWS Events ########## # Send event with launched and terminated autoscaling group instances LifeCycleMediaNodesRule: Type: AWS::Events::Rule Properties: Name: !Join ['', [ !Ref AWS::StackName, '-asg-lifecycle-rule'] ] State: 'ENABLED' EventPattern: !Sub | { "source": [ "aws.autoscaling" ], "detail": { "LifecycleTransition": ["autoscaling:EC2_INSTANCE_LAUNCHING", "autoscaling:EC2_INSTANCE_TERMINATING"], "AutoScalingGroupName": [ "${MediaNodeAutoScalingGroup}" ] } } Targets: - Arn: !GetAtt SQSQueue.Arn Id: AsgLifecycleMediaNodes SqsParameters: MessageGroupId: sqs-notification InputTransformer: InputPathsMap: source: $.source lifecycle-transition: $.detail.LifecycleTransition ec2-instance: $.detail.EC2InstanceId autoscaling-groupname: $.detail.AutoScalingGroupName InputTemplate: >- { "source": , "detail": { "LifecycleTransition": , "AutoScalingGroupName": , "EC2InstanceId": }, "role": "MediaNode" } # Send event to update cluster state on autoscaling actions from AWS AutoscalingScheduleRule: Type: AWS::Events::Rule Properties: Description: 'Executes periodically lambda which sends information about the OpenVidu Pro Cluster' Name: !Join ['', [ !Ref AWS::StackName, '-asg-rule'] ] ScheduleExpression: 'rate(1 minute)' State: 'ENABLED' Targets: - Arn: !GetAtt SQSQueue.Arn Id: AsgSchedule SqsParameters: MessageGroupId: sqs-notification InputTransformer: InputPathsMap: time: $.time InputTemplate: >- { "source": "custom.autoscaling_schedule", "detail": { "time":