|
1 | 1 | AWSTemplateFormatVersion: '2010-09-09'
|
2 |
| -Description: Stack for complete deployment of Metaflow (last-updated-date 02/09/2021) |
| 2 | +Description: Stack for complete deployment of Metaflow (last-updated-date 10/26/2021) |
3 | 3 |
|
4 | 4 | Parameters:
|
5 | 5 | SagemakerInstance:
|
@@ -101,6 +101,21 @@ Mappings:
|
101 | 101 | value: 1
|
102 | 102 | Role:
|
103 | 103 | value: ""
|
| 104 | + |
| 105 | + ServiceInfoUI: |
| 106 | + ServiceName: |
| 107 | + value: 'metaflow-ui-service' |
| 108 | + ImageUrl: |
| 109 | + value: 'netflixoss/metaflow_metadata_service' |
| 110 | + ContainerPort: |
| 111 | + value: 8083 |
| 112 | + ContainerCpu: |
| 113 | + value: 512 |
| 114 | + ContainerMemory: |
| 115 | + value: 1024 |
| 116 | + DesiredCount: |
| 117 | + value: 1 |
| 118 | + |
104 | 119 | Conditions:
|
105 | 120 | EnableAuth: !Equals [ !Ref APIBasicAuth, 'true']
|
106 | 121 | EnableRole: !Equals [ !Ref CustomRole, 'true']
|
@@ -1364,38 +1379,235 @@ Resources:
|
1364 | 1379 | AttributeName: ttl
|
1365 | 1380 | Enabled: true
|
1366 | 1381 |
|
1367 |
| -# Metaflow UI Nested stack |
| 1382 | +# --- Metaflow UI resources begin --- |
| 1383 | + |
| 1384 | + # UI: Ingress rules |
1368 | 1385 |
|
1369 |
| - MetaflowUI: |
1370 |
| - Condition: 'EnableUI' |
| 1386 | + IngressRuleUIService: |
| 1387 | + Type: AWS::EC2::SecurityGroupIngress |
| 1388 | + Condition: EnableUI |
| 1389 | + Properties: |
| 1390 | + Description: "Allow API Calls Internally (UI service)" |
| 1391 | + GroupId: !Ref FargateSecurityGroup |
| 1392 | + IpProtocol: tcp |
| 1393 | + FromPort: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"] |
| 1394 | + ToPort: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"] |
| 1395 | + CidrIp: !GetAtt 'VPC.CidrBlock' |
| 1396 | + |
| 1397 | + # UI: Load balancer |
| 1398 | + |
| 1399 | + ALBUISecurityGroup: |
| 1400 | + Type: AWS::EC2::SecurityGroup |
| 1401 | + Condition: EnableUI |
| 1402 | + Properties: |
| 1403 | + GroupDescription: "Access to the public facing load balancer" |
| 1404 | + VpcId: !Ref VPC |
| 1405 | + SecurityGroupIngress: |
| 1406 | + # Allow access to ALB from anywhere on the internet |
| 1407 | + - CidrIp: 0.0.0.0/0 |
| 1408 | + IpProtocol: -1 |
| 1409 | + ALBUI: |
| 1410 | + Type: AWS::ElasticLoadBalancingV2::LoadBalancer |
| 1411 | + Condition: EnableUI |
| 1412 | + Properties: |
| 1413 | + Scheme: internet-facing |
| 1414 | + Type: application |
| 1415 | + Subnets: |
| 1416 | + - !Ref Subnet1 |
| 1417 | + - !Ref Subnet2 |
| 1418 | + SecurityGroups: [!Ref ALBUISecurityGroup] |
| 1419 | + ALBUIListener: |
| 1420 | + Type: AWS::ElasticLoadBalancingV2::Listener |
| 1421 | + Condition: EnableUI |
1371 | 1422 | DependsOn:
|
1372 |
| - - VPC |
1373 |
| - - Subnet1 |
1374 |
| - - Subnet2 |
1375 |
| - - FargateSecurityGroup |
1376 |
| - - ECSCluster |
1377 |
| - - ECSTaskExecutionRole |
1378 |
| - - MetadataSvcECSTaskRole |
1379 |
| - - RDSMasterInstance |
1380 |
| - - MyRDSSecret |
1381 |
| - - NLB |
1382 |
| - Type: AWS::CloudFormation::Stack |
1383 |
| - Properties: |
1384 |
| - TemplateURL: ui/metaflow-ui-cfn-template.yml |
1385 |
| - Parameters: |
1386 |
| - VPCId: !Ref VPC |
1387 |
| - VPCCidrBlock: !GetAtt 'VPC.CidrBlock' |
1388 |
| - SubnetIds: !Join [',', [ !Ref Subnet1, !Ref Subnet2 ]] |
1389 |
| - SecurityGroup: !Ref FargateSecurityGroup |
1390 |
| - ECSClusterId: !Ref ECSCluster |
1391 |
| - ECSTaskExecutionRoleId: !Ref ECSTaskExecutionRole |
1392 |
| - MetadataSvcECSTaskRoleArn: !GetAtt 'MetadataSvcECSTaskRole.Arn' |
1393 |
| - DatabaseHost: !GetAtt 'RDSMasterInstance.Endpoint.Address' |
1394 |
| - DatabasePort: "5432" |
1395 |
| - DatabaseUser: "master" |
1396 |
| - DatabasePassword: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:password}}' ]] |
1397 |
| - DatabaseName: "metaflow" |
1398 |
| - MetaflowServiceUrl: !Sub "http://${NLB.DNSName}/" |
| 1423 | + - ALBUI |
| 1424 | + Properties: |
| 1425 | + DefaultActions: |
| 1426 | + - TargetGroupArn: !Ref ALBUITargetGroupUIService |
| 1427 | + Type: "forward" |
| 1428 | + LoadBalancerArn: !Ref ALBUI |
| 1429 | + Port: 80 |
| 1430 | + Protocol: HTTP |
| 1431 | + ALBUITargetGroupUIService: |
| 1432 | + Type: AWS::ElasticLoadBalancingV2::TargetGroup |
| 1433 | + Condition: EnableUI |
| 1434 | + Properties: |
| 1435 | + HealthCheckIntervalSeconds: 6 |
| 1436 | + HealthCheckPath: /ping |
| 1437 | + HealthCheckProtocol: HTTP |
| 1438 | + HealthCheckTimeoutSeconds: 5 |
| 1439 | + HealthyThresholdCount: 2 |
| 1440 | + TargetType: ip |
| 1441 | + Port: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"] |
| 1442 | + Protocol: HTTP |
| 1443 | + UnhealthyThresholdCount: 2 |
| 1444 | + VpcId: !Ref VPC |
| 1445 | + |
| 1446 | + # UI: Coudfront distribution |
| 1447 | + |
| 1448 | + CloudFrontDistributionUI: |
| 1449 | + Type: AWS::CloudFront::Distribution |
| 1450 | + Condition: EnableUI |
| 1451 | + DependsOn: |
| 1452 | + - ALBUI |
| 1453 | + Properties: |
| 1454 | + DistributionConfig: |
| 1455 | + Origins: |
| 1456 | + - DomainName: !GetAtt "ALBUI.DNSName" |
| 1457 | + Id: !Ref ALBUI |
| 1458 | + CustomOriginConfig: |
| 1459 | + HTTPPort: 80 |
| 1460 | + OriginProtocolPolicy: http-only |
| 1461 | + OriginKeepaliveTimeout: 60 |
| 1462 | + OriginReadTimeout: 30 |
| 1463 | + OriginSSLProtocols: |
| 1464 | + - TLSv1 |
| 1465 | + - TLSv1.1 |
| 1466 | + - TLSv1.2 |
| 1467 | + - SSLv3 |
| 1468 | + Enabled: true |
| 1469 | + HttpVersion: http2 |
| 1470 | + DefaultCacheBehavior: |
| 1471 | + AllowedMethods: |
| 1472 | + - GET |
| 1473 | + - HEAD |
| 1474 | + - DELETE |
| 1475 | + - OPTIONS |
| 1476 | + - PATCH |
| 1477 | + - POST |
| 1478 | + - PUT |
| 1479 | + Compress: true |
| 1480 | + DefaultTTL: 0 |
| 1481 | + MinTTL: 0 |
| 1482 | + MaxTTL: 0 |
| 1483 | + SmoothStreaming: false |
| 1484 | + TargetOriginId: !Ref ALBUI |
| 1485 | + ForwardedValues: |
| 1486 | + QueryString: true |
| 1487 | + Cookies: |
| 1488 | + Forward: none |
| 1489 | + ViewerProtocolPolicy: redirect-to-https |
| 1490 | + CacheBehaviors: |
| 1491 | + - AllowedMethods: |
| 1492 | + - GET |
| 1493 | + - HEAD |
| 1494 | + - DELETE |
| 1495 | + - OPTIONS |
| 1496 | + - PATCH |
| 1497 | + - POST |
| 1498 | + - PUT |
| 1499 | + Compress: false |
| 1500 | + PathPattern: /api/* |
| 1501 | + DefaultTTL: 0 |
| 1502 | + MinTTL: 0 |
| 1503 | + MaxTTL: 0 |
| 1504 | + SmoothStreaming: false |
| 1505 | + TargetOriginId: !Ref ALBUI |
| 1506 | + ForwardedValues: |
| 1507 | + QueryString: true |
| 1508 | + Cookies: |
| 1509 | + Forward: none |
| 1510 | + ViewerProtocolPolicy: redirect-to-https |
| 1511 | + PriceClass: PriceClass_All |
| 1512 | + IPV6Enabled: true |
| 1513 | + |
| 1514 | + # UI: ECS Cluster task definition & service |
| 1515 | + |
| 1516 | + TaskDefinitionUIService: |
| 1517 | + Type: AWS::ECS::TaskDefinition |
| 1518 | + Condition: EnableUI |
| 1519 | + Properties: |
| 1520 | + Family: !FindInMap ["ServiceInfoUI", "ServiceName", "value"] |
| 1521 | + Cpu: !FindInMap ["ServiceInfoUI", "ContainerCpu", "value"] |
| 1522 | + Memory: !FindInMap ["ServiceInfoUI", "ContainerMemory", "value"] |
| 1523 | + NetworkMode: awsvpc |
| 1524 | + RequiresCompatibilities: |
| 1525 | + - FARGATE |
| 1526 | + ExecutionRoleArn: !Ref 'ECSTaskExecutionRole' |
| 1527 | + TaskRoleArn: !GetAtt 'MetadataSvcECSTaskRole.Arn' |
| 1528 | + ContainerDefinitions: |
| 1529 | + - Name: !FindInMap ["ServiceInfoUI", "ServiceName", "value"] |
| 1530 | + Environment: |
| 1531 | + - Name: "MF_METADATA_DB_HOST" |
| 1532 | + Value: !GetAtt 'RDSMasterInstance.Endpoint.Address' |
| 1533 | + - Name: "MF_METADATA_DB_PORT" |
| 1534 | + Value: "5432" |
| 1535 | + - Name: "MF_METADATA_DB_USER" |
| 1536 | + Value: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:username}}' ]] |
| 1537 | + - Name: "MF_METADATA_DB_PSWD" |
| 1538 | + Value: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:password}}' ]] |
| 1539 | + - Name: "MF_METADATA_DB_NAME" |
| 1540 | + Value: "metaflow" |
| 1541 | + - Name: "UI_ENABLED" |
| 1542 | + Value: "1" |
| 1543 | + Cpu: !FindInMap ["ServiceInfoUI", "ContainerCpu", "value"] |
| 1544 | + Memory: !FindInMap ["ServiceInfoUI", "ContainerMemory", "value"] |
| 1545 | + Image: !FindInMap ["ServiceInfoUI", "ImageUrl", "value"] |
| 1546 | + Command: |
| 1547 | + [ |
| 1548 | + "/opt/latest/bin/python3", |
| 1549 | + "-m", |
| 1550 | + "services.ui_backend_service.ui_server", |
| 1551 | + ] |
| 1552 | + PortMappings: |
| 1553 | + - ContainerPort: |
| 1554 | + !FindInMap ["ServiceInfoUI", "ContainerPort", "value"] |
| 1555 | + LogConfiguration: |
| 1556 | + LogDriver: awslogs |
| 1557 | + Options: |
| 1558 | + awslogs-group: |
| 1559 | + !Join [ |
| 1560 | + "", |
| 1561 | + [ |
| 1562 | + "/ecs/", |
| 1563 | + !Ref "AWS::StackName", |
| 1564 | + "-", |
| 1565 | + !FindInMap ["ServiceInfoUI", "ServiceName", "value"], |
| 1566 | + ], |
| 1567 | + ] |
| 1568 | + awslogs-region: !Ref "AWS::Region" |
| 1569 | + awslogs-stream-prefix: "ecs" |
| 1570 | + ServiceLogGroupUIService: |
| 1571 | + Type: AWS::Logs::LogGroup |
| 1572 | + Condition: EnableUI |
| 1573 | + Properties: |
| 1574 | + LogGroupName: |
| 1575 | + !Join [ |
| 1576 | + "", |
| 1577 | + [ |
| 1578 | + "/ecs/", |
| 1579 | + !Ref "AWS::StackName", |
| 1580 | + "-", |
| 1581 | + !FindInMap ["ServiceInfoUI", "ServiceName", "value"], |
| 1582 | + ], |
| 1583 | + ] |
| 1584 | + ECSFargateServiceUIService: |
| 1585 | + Type: AWS::ECS::Service |
| 1586 | + Condition: EnableUI |
| 1587 | + DependsOn: ALBUIListener |
| 1588 | + Properties: |
| 1589 | + ServiceName: !FindInMap ["ServiceInfoUI", "ServiceName", "value"] |
| 1590 | + Cluster: !Ref 'ECSCluster' |
| 1591 | + LaunchType: FARGATE |
| 1592 | + DeploymentConfiguration: |
| 1593 | + MaximumPercent: 200 |
| 1594 | + MinimumHealthyPercent: 75 |
| 1595 | + DesiredCount: !FindInMap ["ServiceInfoUI", "DesiredCount", "value"] |
| 1596 | + NetworkConfiguration: |
| 1597 | + AwsvpcConfiguration: |
| 1598 | + AssignPublicIp: ENABLED |
| 1599 | + SecurityGroups: |
| 1600 | + - !Ref FargateSecurityGroup |
| 1601 | + Subnets: |
| 1602 | + - !Ref Subnet1 |
| 1603 | + - !Ref Subnet2 |
| 1604 | + TaskDefinition: !Ref TaskDefinitionUIService |
| 1605 | + LoadBalancers: |
| 1606 | + - ContainerName: !FindInMap ["ServiceInfoUI", "ServiceName", "value"] |
| 1607 | + ContainerPort: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"] |
| 1608 | + TargetGroupArn: !Ref ALBUITargetGroupUIService |
| 1609 | + |
| 1610 | +# --- Metaflow UI resources end --- |
1399 | 1611 |
|
1400 | 1612 | Outputs:
|
1401 | 1613 | MetaflowDataStoreS3Url:
|
@@ -1440,3 +1652,14 @@ Outputs:
|
1440 | 1652 | MigrationFunctionName:
|
1441 | 1653 | Description: "Name of DB Migration Function"
|
1442 | 1654 | Value: !Ref ExecuteDBMigration
|
| 1655 | + |
| 1656 | + # Metaflow UI outputs |
| 1657 | + |
| 1658 | + UIServiceUrl: |
| 1659 | + Description: "ALB URL for Metadata UI (Open to Public Access)" |
| 1660 | + Value: !Sub "http://${ALBUI.DNSName}/" |
| 1661 | + Condition: EnableUI |
| 1662 | + UIServiceCloudfrontUrl: |
| 1663 | + Description: "Cloudfront URL for Metadata UI (Open to Public Access)" |
| 1664 | + Value: !Sub "https://${CloudFrontDistributionUI.DomainName}/" |
| 1665 | + Condition: EnableUI |
0 commit comments