Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.

Commit da1d270

Browse files
committed
Based on PR comments the nested UI template is now dropped. Everything related to UI is now within the main template.
1 parent 42d259d commit da1d270

File tree

3 files changed

+262
-345
lines changed

3 files changed

+262
-345
lines changed

aws/cloudformation/README.md

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -52,35 +52,13 @@ Did you choose to enable "APIBasicAuth" and/or "CustomRole" and are wondering ho
5252

5353
### Optional Metaflow User Interface (`EnableUI` -parameter)
5454

55-
Please note: This section can be ignored if `EnableUI` -parameter is disabled.
55+
Please note: This section can be ignored if `EnableUI` -parameter is disabled (this is the default value).
5656

57-
User Interface is provided as a CloudFormation Nested Stack, which means that the UI components are separated to its own template and are deployed to separate CloudFormation Stack. All Nested Stack operations should be initiated from the root stack.
57+
User Interface is provided as part of the `metaflow-cfn-template.yml` template and doesn't require any additional
58+
configuration besides enabling the `EnableUI` -parameter. You can follow the [AWS CloudFormation Deployment](https://admin-docs.metaflow.org/metaflow-on-aws/deployment-guide/aws-cloudformation-deployment#steps-for-aws-cloudformation-deployment) instructions.
5859

59-
While working with Nested Stacks, templates need to be packaged before deployment. For this AWS Command Line Interface can be used. Packaging step is only required when deploying Metaflow User Interface Nested Stack.
60+
Once deployed the Cloudformation Stack will provide two outputs:
61+
- `UIServiceUrl` - Application Load Balancer endpoint
62+
- `UIServiceCloudfrontUrl` - Cloudfront distribution (using ALB) endpoint with HTTPS enabled (preferred)
6063

61-
Prerequisites for User Interface enabled Nested Stack deployment:
62-
63-
* **[Netflix/metaflow-tools repository](https://github.com/Netflix/metaflow-tools)** - Locally available for packaging templates.
64-
* **AWS Command Line Interface** - Installed and configured.
65-
* **S3 bucket to upload CloudFormation templates to** - Nested Stacks require templates referred by absolute S3 paths.
66-
67-
Packaging step is required in order to deploy templates with Nested Stacks:
68-
69-
```bash
70-
$ aws cloudformation package \
71-
--s3-bucket manually-created-s3-bucket \
72-
--template-file metaflow-cfn-template.yml \
73-
--output-template-file metaflow-cfn-template.yml.package
74-
```
75-
76-
Above package command does the following:
77-
78-
1. Nested Stack template is uploaded to S3 bucket
79-
1. Defined by `--s3-bucket` parameter (this bucket should already exist and needs to be created manually)
80-
2. Root template is transformed so that all local paths are converted to absolute S3 paths
81-
1. Input file is defined by `--template-file` parameter
82-
3. Transformed and packaged root template is placed in local file system defined by `--output-template-file` parameter
83-
84-
Once this package step is completed, you can follow the [AWS CloudFormation Deployment](https://admin-docs.metaflow.org/metaflow-on-aws/deployment-guide/aws-cloudformation-deployment#steps-for-aws-cloudformation-deployment). Please note: instead of using the non-packaged template, you should use the packaged template `metaflow-cfn-template.yml.package` you just created.
85-
86-
Read more about Cloudformation and working with nested stacks [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html).
64+
Please note: Metaflow User Interface doesn't provide any authentication by default.

aws/cloudformation/metaflow-cfn-template.yml

Lines changed: 255 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
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)
33

44
Parameters:
55
SagemakerInstance:
@@ -101,6 +101,22 @@ Mappings:
101101
value: 1
102102
Role:
103103
value: ""
104+
105+
ServiceInfoUI:
106+
ServiceName:
107+
value: 'metaflow-ui-service'
108+
ImageUrl:
109+
#value: 'netflixoss/metaflow_metadata_service'
110+
value: '847940006482.dkr.ecr.us-west-2.amazonaws.com/metaflow-service:cloudformation' # TODO: Public Docker Hub image here
111+
ContainerPort:
112+
value: 8083
113+
ContainerCpu:
114+
value: 512
115+
ContainerMemory:
116+
value: 1024
117+
DesiredCount:
118+
value: 1
119+
104120
Conditions:
105121
EnableAuth: !Equals [ !Ref APIBasicAuth, 'true']
106122
EnableRole: !Equals [ !Ref CustomRole, 'true']
@@ -1364,38 +1380,235 @@ Resources:
13641380
AttributeName: ttl
13651381
Enabled: true
13661382

1367-
# Metaflow UI Nested stack
1383+
# --- Metaflow UI resources begin ---
13681384

1369-
MetaflowUI:
1370-
Condition: 'EnableUI'
1385+
# UI: Ingress rules
1386+
1387+
IngressRuleUIService:
1388+
Type: AWS::EC2::SecurityGroupIngress
1389+
Condition: EnableUI
1390+
Properties:
1391+
Description: "Allow API Calls Internally (UI service)"
1392+
GroupId: !Ref FargateSecurityGroup
1393+
IpProtocol: tcp
1394+
FromPort: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"]
1395+
ToPort: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"]
1396+
CidrIp: !GetAtt 'VPC.CidrBlock'
1397+
1398+
# UI: Load balancer
1399+
1400+
ALBUISecurityGroup:
1401+
Type: AWS::EC2::SecurityGroup
1402+
Condition: EnableUI
1403+
Properties:
1404+
GroupDescription: "Access to the public facing load balancer"
1405+
VpcId: !Ref VPC
1406+
SecurityGroupIngress:
1407+
# Allow access to ALB from anywhere on the internet
1408+
- CidrIp: 0.0.0.0/0
1409+
IpProtocol: -1
1410+
ALBUI:
1411+
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
1412+
Condition: EnableUI
1413+
Properties:
1414+
Scheme: internet-facing
1415+
Type: application
1416+
Subnets:
1417+
- !Ref Subnet1
1418+
- !Ref Subnet2
1419+
SecurityGroups: [!Ref ALBUISecurityGroup]
1420+
ALBUIListener:
1421+
Type: AWS::ElasticLoadBalancingV2::Listener
1422+
Condition: EnableUI
13711423
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}/"
1424+
- ALBUI
1425+
Properties:
1426+
DefaultActions:
1427+
- TargetGroupArn: !Ref ALBUITargetGroupUIService
1428+
Type: "forward"
1429+
LoadBalancerArn: !Ref ALBUI
1430+
Port: 80
1431+
Protocol: HTTP
1432+
ALBUITargetGroupUIService:
1433+
Type: AWS::ElasticLoadBalancingV2::TargetGroup
1434+
Condition: EnableUI
1435+
Properties:
1436+
HealthCheckIntervalSeconds: 6
1437+
HealthCheckPath: /ping
1438+
HealthCheckProtocol: HTTP
1439+
HealthCheckTimeoutSeconds: 5
1440+
HealthyThresholdCount: 2
1441+
TargetType: ip
1442+
Port: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"]
1443+
Protocol: HTTP
1444+
UnhealthyThresholdCount: 2
1445+
VpcId: !Ref VPC
1446+
1447+
# UI: Coudfront distribution
1448+
1449+
CloudFrontDistributionUI:
1450+
Type: AWS::CloudFront::Distribution
1451+
Condition: EnableUI
1452+
DependsOn:
1453+
- ALBUI
1454+
Properties:
1455+
DistributionConfig:
1456+
Origins:
1457+
- DomainName: !GetAtt "ALBUI.DNSName"
1458+
Id: !Ref ALBUI
1459+
CustomOriginConfig:
1460+
HTTPPort: 80
1461+
OriginProtocolPolicy: http-only
1462+
OriginKeepaliveTimeout: 60
1463+
OriginReadTimeout: 30
1464+
OriginSSLProtocols:
1465+
- TLSv1
1466+
- TLSv1.1
1467+
- TLSv1.2
1468+
- SSLv3
1469+
Enabled: true
1470+
HttpVersion: http2
1471+
DefaultCacheBehavior:
1472+
AllowedMethods:
1473+
- GET
1474+
- HEAD
1475+
- DELETE
1476+
- OPTIONS
1477+
- PATCH
1478+
- POST
1479+
- PUT
1480+
Compress: true
1481+
DefaultTTL: 0
1482+
MinTTL: 0
1483+
MaxTTL: 0
1484+
SmoothStreaming: false
1485+
TargetOriginId: !Ref ALBUI
1486+
ForwardedValues:
1487+
QueryString: true
1488+
Cookies:
1489+
Forward: none
1490+
ViewerProtocolPolicy: redirect-to-https
1491+
CacheBehaviors:
1492+
- AllowedMethods:
1493+
- GET
1494+
- HEAD
1495+
- DELETE
1496+
- OPTIONS
1497+
- PATCH
1498+
- POST
1499+
- PUT
1500+
Compress: false
1501+
PathPattern: /api/*
1502+
DefaultTTL: 0
1503+
MinTTL: 0
1504+
MaxTTL: 0
1505+
SmoothStreaming: false
1506+
TargetOriginId: !Ref ALBUI
1507+
ForwardedValues:
1508+
QueryString: true
1509+
Cookies:
1510+
Forward: none
1511+
ViewerProtocolPolicy: redirect-to-https
1512+
PriceClass: PriceClass_All
1513+
IPV6Enabled: true
1514+
1515+
# UI: ECS Cluster task definition & service
1516+
1517+
TaskDefinitionUIService:
1518+
Type: AWS::ECS::TaskDefinition
1519+
Condition: EnableUI
1520+
Properties:
1521+
Family: !FindInMap ["ServiceInfoUI", "ServiceName", "value"]
1522+
Cpu: !FindInMap ["ServiceInfoUI", "ContainerCpu", "value"]
1523+
Memory: !FindInMap ["ServiceInfoUI", "ContainerMemory", "value"]
1524+
NetworkMode: awsvpc
1525+
RequiresCompatibilities:
1526+
- FARGATE
1527+
ExecutionRoleArn: !Ref 'ECSTaskExecutionRole'
1528+
TaskRoleArn: !GetAtt 'MetadataSvcECSTaskRole.Arn'
1529+
ContainerDefinitions:
1530+
- Name: !FindInMap ["ServiceInfoUI", "ServiceName", "value"]
1531+
Environment:
1532+
- Name: "MF_METADATA_DB_HOST"
1533+
Value: !GetAtt 'RDSMasterInstance.Endpoint.Address'
1534+
- Name: "MF_METADATA_DB_PORT"
1535+
Value: "5432"
1536+
- Name: "MF_METADATA_DB_USER"
1537+
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:username}}' ]]
1538+
- Name: "MF_METADATA_DB_PSWD"
1539+
Value: !Join ['', ['{{resolve:secretsmanager:', !Ref MyRDSSecret, ':SecretString:password}}' ]]
1540+
- Name: "MF_METADATA_DB_NAME"
1541+
Value: "metaflow"
1542+
- Name: "UI_ENABLED"
1543+
Value: "1"
1544+
Cpu: !FindInMap ["ServiceInfoUI", "ContainerCpu", "value"]
1545+
Memory: !FindInMap ["ServiceInfoUI", "ContainerMemory", "value"]
1546+
Image: !FindInMap ["ServiceInfoUI", "ImageUrl", "value"]
1547+
Command:
1548+
[
1549+
"/opt/latest/bin/python3",
1550+
"-m",
1551+
"services.ui_backend_service.ui_server",
1552+
]
1553+
PortMappings:
1554+
- ContainerPort:
1555+
!FindInMap ["ServiceInfoUI", "ContainerPort", "value"]
1556+
LogConfiguration:
1557+
LogDriver: awslogs
1558+
Options:
1559+
awslogs-group:
1560+
!Join [
1561+
"",
1562+
[
1563+
"/ecs/",
1564+
!Ref "AWS::StackName",
1565+
"-",
1566+
!FindInMap ["ServiceInfoUI", "ServiceName", "value"],
1567+
],
1568+
]
1569+
awslogs-region: !Ref "AWS::Region"
1570+
awslogs-stream-prefix: "ecs"
1571+
ServiceLogGroupUIService:
1572+
Type: AWS::Logs::LogGroup
1573+
Condition: EnableUI
1574+
Properties:
1575+
LogGroupName:
1576+
!Join [
1577+
"",
1578+
[
1579+
"/ecs/",
1580+
!Ref "AWS::StackName",
1581+
"-",
1582+
!FindInMap ["ServiceInfoUI", "ServiceName", "value"],
1583+
],
1584+
]
1585+
ECSFargateServiceUIService:
1586+
Type: AWS::ECS::Service
1587+
Condition: EnableUI
1588+
DependsOn: ALBUIListener
1589+
Properties:
1590+
ServiceName: !FindInMap ["ServiceInfoUI", "ServiceName", "value"]
1591+
Cluster: !Ref 'ECSCluster'
1592+
LaunchType: FARGATE
1593+
DeploymentConfiguration:
1594+
MaximumPercent: 200
1595+
MinimumHealthyPercent: 75
1596+
DesiredCount: !FindInMap ["ServiceInfoUI", "DesiredCount", "value"]
1597+
NetworkConfiguration:
1598+
AwsvpcConfiguration:
1599+
AssignPublicIp: ENABLED
1600+
SecurityGroups:
1601+
- !Ref FargateSecurityGroup
1602+
Subnets:
1603+
- !Ref Subnet1
1604+
- !Ref Subnet2
1605+
TaskDefinition: !Ref TaskDefinitionUIService
1606+
LoadBalancers:
1607+
- ContainerName: !FindInMap ["ServiceInfoUI", "ServiceName", "value"]
1608+
ContainerPort: !FindInMap ["ServiceInfoUI", "ContainerPort", "value"]
1609+
TargetGroupArn: !Ref ALBUITargetGroupUIService
1610+
1611+
# --- Metaflow UI resources end ---
13991612

14001613
Outputs:
14011614
MetaflowDataStoreS3Url:
@@ -1440,3 +1653,14 @@ Outputs:
14401653
MigrationFunctionName:
14411654
Description: "Name of DB Migration Function"
14421655
Value: !Ref ExecuteDBMigration
1656+
1657+
# Metaflow UI outputs
1658+
1659+
UIServiceUrl:
1660+
Description: "ALB URL for Metadata UI (Open to Public Access)"
1661+
Value: !Sub "http://${ALBUI.DNSName}/"
1662+
Condition: EnableUI
1663+
UIServiceCloudfrontUrl:
1664+
Description: "Cloudfront URL for Metadata UI (Open to Public Access)"
1665+
Value: !Sub "https://${CloudFrontDistributionUI.DomainName}/"
1666+
Condition: EnableUI

0 commit comments

Comments
 (0)