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

Commit 1182275

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 1182275

File tree

3 files changed

+261
-345
lines changed

3 files changed

+261
-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: 254 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,21 @@ 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+
ContainerPort:
111+
value: 8083
112+
ContainerCpu:
113+
value: 512
114+
ContainerMemory:
115+
value: 1024
116+
DesiredCount:
117+
value: 1
118+
104119
Conditions:
105120
EnableAuth: !Equals [ !Ref APIBasicAuth, 'true']
106121
EnableRole: !Equals [ !Ref CustomRole, 'true']
@@ -1364,38 +1379,235 @@ Resources:
13641379
AttributeName: ttl
13651380
Enabled: true
13661381

1367-
# Metaflow UI Nested stack
1382+
# --- Metaflow UI resources begin ---
1383+
1384+
# UI: Ingress rules
13681385

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
13711422
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 ---
13991611

14001612
Outputs:
14011613
MetaflowDataStoreS3Url:
@@ -1440,3 +1652,14 @@ Outputs:
14401652
MigrationFunctionName:
14411653
Description: "Name of DB Migration Function"
14421654
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

Comments
 (0)