diff --git a/deployments/aws/templates/ai-unlimited/ai-unlimited-with-alb.yaml b/deployments/aws/templates/ai-unlimited/ai-unlimited-with-alb.yaml index 34b073e..0cac150 100644 --- a/deployments/aws/templates/ai-unlimited/ai-unlimited-with-alb.yaml +++ b/deployments/aws/templates/ai-unlimited/ai-unlimited-with-alb.yaml @@ -1243,4 +1243,4 @@ Outputs: PersistentVolumeId: Description: Id of the new persistent volume created for AI Unlimited Value: !Ref AiUnlimitedVolume - Condition: USENEWPERSISTENTVOLUME + Condition: USENEWPERSISTENTVOLUME \ No newline at end of file diff --git a/deployments/aws/templates/ai-unlimited/ai-unlimited-with-nlb.yaml b/deployments/aws/templates/ai-unlimited/ai-unlimited-with-nlb.yaml index 8346071..907ab0e 100644 --- a/deployments/aws/templates/ai-unlimited/ai-unlimited-with-nlb.yaml +++ b/deployments/aws/templates/ai-unlimited/ai-unlimited-with-nlb.yaml @@ -29,12 +29,14 @@ Metadata: - AccessCIDR - PrefixList - SecurityGroup - - AiUnlimitedHttpPort + - AiUnlimitedAuthPort - AiUnlimitedGrpcPort - AiUnlimitedVersion - AiUnlimitedSchedulerVersion - AiUnlimitedSchedulerHttpPort - AiUnlimitedSchedulerGrpcPort + - AiUnlimitedUiPort + - AiUnlimitedUiVersion - Label: default: Persistent volume Parameters: @@ -101,7 +103,7 @@ Parameters: Type: AWS::EC2::AvailabilityZone::Name ConstraintDescription: must be the name of a existing subnet. - AiUnlimitedHttpPort: + AiUnlimitedAuthPort: Description: port to access the AI Unlimited UI. Type: Number Default: 3000 @@ -125,6 +127,14 @@ Parameters: MinValue: 0 MaxValue: 65535 + AiUnlimitedUiPort: + Description: port to access the AI Unlimited UI. + Type: Number + Default: 80 + ConstraintDescription: must be a valid ununsed port between 0 and 65535. + MinValue: 0 + MaxValue: 65535 + AiUnlimitedGrpcPort: Description: port to access the AI Unlimited API. Type: Number @@ -136,7 +146,12 @@ Parameters: AiUnlimitedVersion: Description: Which version of AI Unlimited to deploy, uses container version tags, defaults to "latest" Type: String - Default: v0.2.23 + Default: v0.3.0 + + AiUnlimitedUiVersion: + Description: Which version of AI Unlimited UI to deploy, uses container version tags, defaults to "latest" + Type: String + Default: v0.0.5 AiUnlimitedSchedulerVersion: Description: Which version of AI Unlimited Scheduler to deploy, uses container version tags, defaults to "latest" @@ -364,6 +379,8 @@ Conditions: - !Ref IamRoleName - "" + PortIsNotEighty: !Not [!Equals [!Ref AiUnlimitedUiPort, 80]] + Resources: AiUnlimitedVolume: DeletionPolicy: !Ref PersistentVolumeDeletionPolicy @@ -405,9 +422,12 @@ Resources: - prepare_new_storage - !Ref AWS::NoValue - bind_storage + - create_init_api_key - mount_storage - install_docker + - configure_ai_unlimited_ui_service - configure_ai_unlimited_service + - start_ai_unlimited_ui_service - start_ai_unlimited_service - configure_ai_unlimited_scheduler_service - start_ai_unlimited_scheduler_service @@ -423,6 +443,12 @@ Resources: command: !Sub | #!/bin/bash -xe /usr/sbin/mkfs -t ext4 /dev/nvme1n1 + create_init_api_key: + commands: + run_command: + command: !Sub | + #!/bin/bash -xe + echo "TD_VCD_INIT_API_KEY=$(LC_ALL=C tr -dc A-Za-z0-9 /tmp/init_api_key.txt bind_storage: commands: fstab: @@ -461,6 +487,49 @@ Resources: docker: enabled: "true" ensureRunning: "true" + configure_ai_unlimited_ui_service: + files: + /usr/lib/systemd/system/ai-unlimited-ui.service: + content: !Sub | + [Unit] + Description=ai-unlimited-ui + After=docker.service + Requires=docker.service + StartLimitInterval=200 + StartLimitBurst=10 + + [Service] + TimeoutStartSec=0 + Restart=always + RestartSec=2 + + ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' + ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited-ui + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true + ExecStartPre=-/usr/bin/docker rm %n || true + ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + ExecStart=/usr/bin/docker run \ + -e accept_license=Y \ + -e PLATFORM=aws \ + -e TD_VCD_UI_PORT=${ AiUnlimitedUiPort } \ + -e TD_VCD_API_PORT=${ AiUnlimitedGrpcPort } \ + -e TD_VCD_AUTH_PORT=${ AiUnlimitedAuthPort } \ + -e TD_VCD_INIT_API_KEY \ + -p ${ AiUnlimitedUiPort }:80 \ + --network ai_unlimited \ + --rm --name %n teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + [Install] + WantedBy=multi-user.target + group: root + mode: "000400" + owner: root + start_ai_unlimited_ui_service: + services: + systemd: + ai-unlimited-ui: + enabled: "true" + ensureRunning: "true" configure_ai_unlimited_service: files: /usr/lib/systemd/system/ai-unlimited.service: @@ -477,15 +546,16 @@ Resources: Restart=always RestartSec=2 ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited - ExecStartPre=-/usr/bin/docker exec %n stop || true + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true - ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } ExecStart=/usr/bin/docker run \ -e accept_license=Y \ -e PLATFORM=aws \ + -e TD_VCD_INIT_API_KEY \ -v /etc/td/ai-unlimited:/etc/td \ - -p ${ AiUnlimitedHttpPort }:3000 \ + -p ${ AiUnlimitedAuthPort }:3000 \ -p ${ AiUnlimitedGrpcPort }:3282 \ --network ai_unlimited \ --rm --name %n teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } workspaces serve -v @@ -516,7 +586,7 @@ Resources: TimeoutStartSec=0 Restart=always RestartSec=2 - ExecStartPre=-/usr/bin/docker exec %n stop || true + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-scheduler:latest ExecStart=/usr/bin/docker run \ @@ -599,9 +669,9 @@ Resources: VpcId: !Ref Vpc GroupDescription: Enable access to AI Unlimited server from LoadBalancer over http, grpc, and ssh SecurityGroupIngress: - - FromPort: !Ref AiUnlimitedHttpPort + - FromPort: !Ref AiUnlimitedAuthPort IpProtocol: tcp - ToPort: !Ref AiUnlimitedHttpPort + ToPort: !Ref AiUnlimitedAuthPort CidrIp: !If - HASCIDR - !Ref AccessCIDR @@ -625,6 +695,21 @@ Resources: - HASSECURITYGROUP - !Ref SecurityGroup - !Ref AWS::NoValue + - FromPort: !Ref AiUnlimitedUiPort + IpProtocol: tcp + ToPort: !Ref AiUnlimitedUiPort + CidrIp: !If + - HASCIDR + - !Ref AccessCIDR + - !Ref AWS::NoValue + SourcePrefixListId: !If + - HASPREFIXLIST + - !Ref PrefixList + - !Ref AWS::NoValue + SourceSecurityGroupId: !If + - HASSECURITYGROUP + - !Ref SecurityGroup + - !Ref AWS::NoValue Condition: HASCIDRORPREFIXLISTORSECGROUP LoadBalancerSchedulerSecurityGroup: @@ -679,7 +764,7 @@ Resources: - Type: forward TargetGroupArn: !Ref AiUnlimitedHTTPTargetGroup LoadBalancerArn: !Ref LoadBalancer - Port: !Ref AiUnlimitedHttpPort + Port: !Ref AiUnlimitedAuthPort Protocol: TCP AiUnlimitedGRPCListener: @@ -692,6 +777,16 @@ Resources: Port: !Ref AiUnlimitedGrpcPort Protocol: TCP + AiUnlimitedUIListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - Type: forward + TargetGroupArn: !Ref AiUnlimitedUITargetGroup + LoadBalancerArn: !Ref LoadBalancer + Port: !Ref AiUnlimitedUiPort + Protocol: TCP + AiUnlimitedSchedulerHTTPListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: @@ -732,7 +827,7 @@ Resources: - td-aiu - ui - http - Port: !Ref AiUnlimitedHttpPort + Port: !Ref AiUnlimitedAuthPort Protocol: TCP TargetGroupAttributes: - Key: stickiness.enabled @@ -743,7 +838,41 @@ Resources: Value: "20" Targets: - Id: !Ref AiUnlimitedServer - Port: !Ref AiUnlimitedHttpPort + Port: !Ref AiUnlimitedAuthPort + VpcId: !Ref Vpc + + AiUnlimitedUITargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: HTTP + HealthCheckTimeoutSeconds: 15 + Name: !Join + - '-' + - - !Select + - 4 + - !Split + - '-' + - !Select + - 2 + - !Split + - / + - !Ref AWS::StackId + - td-aiu + - ui + - api + Port: !Ref AiUnlimitedUiPort + Protocol: TCP + TargetGroupAttributes: + - Key: stickiness.enabled + Value: true + - Key: stickiness.type + Value: source_ip + - Key: deregistration_delay.timeout_seconds + Value: "20" + Targets: + - Id: !Ref AiUnlimitedServer + Port: !Ref AiUnlimitedUiPort VpcId: !Ref Vpc AiUnlimitedGRPCTargetGroup: @@ -859,18 +988,22 @@ Resources: GroupDescription: Enable access to AI Unlimited server over http and grpc SecurityGroupIngress: - IpProtocol: tcp - FromPort: !Ref AiUnlimitedHttpPort - ToPort: !Ref AiUnlimitedHttpPort + FromPort: !Ref AiUnlimitedAuthPort + ToPort: !Ref AiUnlimitedAuthPort SourceSecurityGroupId: !GetAtt LoadBalancerAiUnlimitedSecurityGroup.GroupId - IpProtocol: tcp FromPort: !Ref AiUnlimitedGrpcPort ToPort: !Ref AiUnlimitedGrpcPort SourceSecurityGroupId: !GetAtt LoadBalancerAiUnlimitedSecurityGroup.GroupId + - IpProtocol: tcp + FromPort: !Ref AiUnlimitedUiPort + ToPort: !Ref AiUnlimitedUiPort + SourceSecurityGroupId: !GetAtt LoadBalancerAiUnlimitedSecurityGroup.GroupId - !If - HASSECURITYGROUP - IpProtocol: tcp - FromPort: !Ref AiUnlimitedHttpPort - ToPort: !Ref AiUnlimitedHttpPort + FromPort: !Ref AiUnlimitedAuthPort + ToPort: !Ref AiUnlimitedAuthPort SourceSecurityGroupId: !Ref SecurityGroup - !Ref AWS::NoValue - !If @@ -880,6 +1013,13 @@ Resources: ToPort: !Ref AiUnlimitedGrpcPort SourceSecurityGroupId: !Ref SecurityGroup - !Ref AWS::NoValue + - !If + - HASSECURITYGROUP + - IpProtocol: tcp + FromPort: !Ref AiUnlimitedUiPort + ToPort: !Ref AiUnlimitedUiPort + SourceSecurityGroupId: !Ref SecurityGroup + - !Ref AWS::NoValue AiUnlimitedSchedulerSecurityGroup: Type: AWS::EC2::SecurityGroup @@ -1148,7 +1288,10 @@ Outputs: AiUnlimitedUiAccess: Description: Loadbalancer access endpoint for AI Unlimited UI Access - Value: !Sub http://${ LoadBalancer.DNSName }:${ AiUnlimitedHttpPort } + Value: !If + - PortIsNotEighty + - !Sub "http://${ LoadBalancer.DNSName }:${ AiUnlimitedUiPort }/healthcheck" + - !Sub "http://${ LoadBalancer.DNSName }" AiUnlimitedApiAccess: Description: Loadbalancer access endpoint for AI Unlimited API Access diff --git a/deployments/aws/templates/ai-unlimited/ai-unlimited-without-lb.yaml b/deployments/aws/templates/ai-unlimited/ai-unlimited-without-lb.yaml index 53c1784..33baab7 100644 --- a/deployments/aws/templates/ai-unlimited/ai-unlimited-without-lb.yaml +++ b/deployments/aws/templates/ai-unlimited/ai-unlimited-without-lb.yaml @@ -27,12 +27,14 @@ Metadata: - AccessCIDR - PrefixList - SecurityGroup - - AiUnlimitedHttpPort + - AiUnlimitedAuthPort - AiUnlimitedGrpcPort - AiUnlimitedVersion - AiUnlimitedSchedulerVersion - AiUnlimitedSchedulerHttpPort - AiUnlimitedSchedulerGrpcPort + - AiUnlimitedUiPort + - AiUnlimitedUiVersion - Label: default: Persistent volume Parameters: @@ -86,7 +88,7 @@ Parameters: Type: AWS::EC2::AvailabilityZone::Name ConstraintDescription: must be the name of a existing subnet. - AiUnlimitedHttpPort: + AiUnlimitedAuthPort: Description: port to access the AI Unlimited UI. Type: Number Default: 3000 @@ -118,16 +120,29 @@ Parameters: MinValue: 0 MaxValue: 65535 + AiUnlimitedUiPort: + Description: port to access the AI Unlimited UI. + Type: Number + Default: 80 + ConstraintDescription: must be a valid ununsed port between 0 and 65535. + MinValue: 0 + MaxValue: 65535 + AiUnlimitedVersion: Description: Which version of AI Unlimited to deploy, uses container version tags, defaults to "latest" Type: String - Default: v0.2.23 + Default: v0.3.0 AiUnlimitedSchedulerVersion: Description: Which version of AI Unlimited Scheduler to deploy, uses container version tags, defaults to "latest" Type: String Default: latest + AiUnlimitedUiVersion: + Description: Which version of AI Unlimited UI to deploy, uses container version tags, defaults to "latest" + Type: String + Default: v0.0.5 + RootVolumeSize: Description: size of the root disk to the AI Unlimited server. Type: Number @@ -349,6 +364,19 @@ Conditions: - !Ref IamRoleName - "" + PortIsNotEightyAndHasPublicIp: + !And + - !Not + - !Equals + - !Ref Private + - "true" + - !Not + - !Equals + - !Ref AiUnlimitedUiPort + - 80 + + PortIsNotEighty: !Not [!Equals [!Ref AiUnlimitedUiPort, 80]] + Resources: AiUnlimitedVolume: DeletionPolicy: !Ref PersistentVolumeDeletionPolicy @@ -390,9 +418,12 @@ Resources: - prepare_new_storage - !Ref AWS::NoValue - bind_storage + - create_init_api_key - mount_storage - install_docker + - configure_ai_unlimited_ui_service - configure_ai_unlimited_service + - start_ai_unlimited_ui_service - start_ai_unlimited_service - configure_ai_unlimited_scheduler_service - start_ai_unlimited_scheduler_service @@ -402,6 +433,12 @@ Resources: command: !Sub | #!/bin/bash -xe mkdir -p /etc/td + create_init_api_key: + commands: + run_command: + command: !Sub | + #!/bin/bash -xe + echo "TD_VCD_INIT_API_KEY=$(LC_ALL=C tr -dc A-Za-z0-9 /tmp/init_api_key.txt prepare_new_storage: commands: mkfs: @@ -446,6 +483,51 @@ Resources: docker: enabled: "true" ensureRunning: "true" + + configure_ai_unlimited_ui_service: + files: + /usr/lib/systemd/system/ai-unlimited-ui.service: + content: !Sub | + [Unit] + Description=ai-unlimited-ui + After=docker.service + Requires=docker.service + StartLimitInterval=200 + StartLimitBurst=10 + + [Service] + TimeoutStartSec=0 + Restart=always + RestartSec=2 + + ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' + ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited-ui + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true + ExecStartPre=-/usr/bin/docker rm %n || true + ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + ExecStart=/usr/bin/docker run \ + -e accept_license=Y \ + -e PLATFORM=aws \ + -e TD_VCD_UI_PORT=${ AiUnlimitedUiPort } \ + -e TD_VCD_API_PORT=${ AiUnlimitedGrpcPort } \ + -e TD_VCD_AUTH_PORT=${ AiUnlimitedAuthPort } \ + -e TD_VCD_INIT_API_KEY \ + -p ${ AiUnlimitedUiPort }:80 \ + --network ai_unlimited \ + --rm --name %n teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + [Install] + WantedBy=multi-user.target + group: root + mode: "000400" + owner: root + start_ai_unlimited_ui_service: + services: + systemd: + ai-unlimited-ui: + enabled: "true" + ensureRunning: "true" + configure_ai_unlimited_service: files: /usr/lib/systemd/system/ai-unlimited.service: @@ -462,15 +544,16 @@ Resources: Restart=always RestartSec=2 ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited - ExecStartPre=-/usr/bin/docker exec %n stop || true + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true - ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } ExecStart=/usr/bin/docker run \ -e accept_license=Y \ -e PLATFORM=aws \ + -e TD_VCD_INIT_API_KEY \ -v /etc/td/ai-unlimited:/etc/td \ - -p ${ AiUnlimitedHttpPort }:3000 \ + -p ${ AiUnlimitedAuthPort }:3000 \ -p ${ AiUnlimitedGrpcPort }:3282 \ --network ai_unlimited \ --rm --name %n teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } workspaces serve -v @@ -585,9 +668,9 @@ Resources: VpcId: !Ref Vpc GroupDescription: Enable access to AI Unlimited server over http and grpc SecurityGroupIngress: - - FromPort: !Ref AiUnlimitedHttpPort + - FromPort: !Ref AiUnlimitedAuthPort IpProtocol: tcp - ToPort: !Ref AiUnlimitedHttpPort + ToPort: !Ref AiUnlimitedAuthPort CidrIp: !If - HASCIDR - !Ref AccessCIDR @@ -615,6 +698,21 @@ Resources: - HASSECURITYGROUP - !Ref SecurityGroup - !Ref AWS::NoValue + - FromPort: !Ref AiUnlimitedUiPort + IpProtocol: tcp + ToPort: !Ref AiUnlimitedUiPort + CidrIp: !If + - HASCIDR + - !Ref AccessCIDR + - !Ref AWS::NoValue + SourcePrefixListId: !If + - HASPREFIXLIST + - !Ref PrefixList + - !Ref AWS::NoValue + SourceSecurityGroupId: !If + - HASSECURITYGROUP + - !Ref SecurityGroup + - !Ref AWS::NoValue AiUnlimitedSchedulerSecurityGroup: Type: AWS::EC2::SecurityGroup @@ -888,12 +986,17 @@ Outputs: AiUnlimitedPublicUIAccess: Description: Teradata AI Unlimited public UI Access - Value: !Sub http://${AiUnlimitedServer.PublicDnsName}:${ AiUnlimitedHttpPort } + Value: !If [ PortIsNotEightyAndHasPublicIp, + !Sub "http://${AiUnlimitedServer.PublicDnsName}:${AiUnlimitedUiPort}/healthcheck", + !Sub "http://${AiUnlimitedServer.PublicDnsName}" ] Condition: HASPUBLICIP AiUnlimitedPrivateUIAccess: Description: Teradata AI Unlimited private UI Access - Value: !Sub http://${AiUnlimitedServer.PrivateDnsName}:${ AiUnlimitedHttpPort } + Value: !If + - PortIsNotEighty + - !Sub "http://${AiUnlimitedServer.PrivateDnsName}:${AiUnlimitedUiPort}/healthcheck" + - !Sub "http://${AiUnlimitedServer.PrivateDnsName}" AiUnlimitedPublicAPIAccess: Description: Teradata AI Unlimited public API Access diff --git a/deployments/aws/templates/all-in-one/all-in-one-with-alb.yaml b/deployments/aws/templates/all-in-one/all-in-one-with-alb.yaml index 19ac0ef..86dab85 100644 --- a/deployments/aws/templates/all-in-one/all-in-one-with-alb.yaml +++ b/deployments/aws/templates/all-in-one/all-in-one-with-alb.yaml @@ -1403,4 +1403,4 @@ Outputs: JupyterInternalAccessToAiUnlimited: Description: AI Unlimited endpoint for local Jupyter access - Value: !Sub ai-unlimited.service:${ AiUnlimitedGrpcPort } + Value: !Sub ai-unlimited.service:${ AiUnlimitedGrpcPort } \ No newline at end of file diff --git a/deployments/aws/templates/all-in-one/all-in-one-with-nlb.yaml b/deployments/aws/templates/all-in-one/all-in-one-with-nlb.yaml index d581992..5894f18 100644 --- a/deployments/aws/templates/all-in-one/all-in-one-with-nlb.yaml +++ b/deployments/aws/templates/all-in-one/all-in-one-with-nlb.yaml @@ -29,12 +29,14 @@ Metadata: - AccessCIDR - PrefixList - SecurityGroup - - AiUnlimitedHttpPort + - AiUnlimitedAuthPort - AiUnlimitedGrpcPort - AiUnlimitedVersion - AiUnlimitedSchedulerVersion - AiUnlimitedSchedulerHttpPort - AiUnlimitedSchedulerGrpcPort + - AiUnlimitedUiPort + - AiUnlimitedUiVersion - Label: default: Persistent volume Parameters: @@ -115,7 +117,7 @@ Parameters: Type: AWS::EC2::AvailabilityZone::Name ConstraintDescription: must be the name of a existing subnet. - AiUnlimitedHttpPort: + AiUnlimitedAuthPort: Description: port to access the AI Unlimited UI. Type: Number Default: 3000 @@ -147,10 +149,23 @@ Parameters: MinValue: 0 MaxValue: 65535 + AiUnlimitedUiPort: + Description: port to access the AI Unlimited UI. + Type: Number + Default: 80 + ConstraintDescription: must be a valid ununsed port between 0 and 65535. + MinValue: 0 + MaxValue: 65535 + AiUnlimitedVersion: Description: Which version of AI Unlimited to deploy, uses container version tags, defaults to "latest" Type: String - Default: v0.2.23 + Default: v0.3.0 + + AiUnlimitedUiVersion: + Description: Which version of AI Unlimited UI to deploy, uses container version tags, defaults to "latest" + Type: String + Default: v0.0.5 AiUnlimitedSchedulerVersion: Description: Which version of AI Unlimited Scheduler to deploy, uses container version tags, defaults to "latest" @@ -380,6 +395,8 @@ Conditions: - !Ref IamRoleName - "" + PortIsNotEighty: !Not [!Equals [!Ref AiUnlimitedUiPort, 80]] + Resources: AiUnlimitedVolume: DeletionPolicy: !Ref PersistentVolumeDeletionPolicy @@ -421,10 +438,13 @@ Resources: - prepare_new_storage - !Ref AWS::NoValue - bind_storage + - create_init_api_key - mount_storage - install_docker + - configure_ai_unlimited_ui_service - configure_ai_unlimited_service - configure_jupyter_service + - start_ai_unlimited_ui_service - start_ai_unlimited_service - configure_ai_unlimited_scheduler_service - start_ai_unlimited_scheduler_service @@ -441,6 +461,12 @@ Resources: command: !Sub | #!/bin/bash -xe /usr/sbin/mkfs -t ext4 /dev/nvme1n1 + create_init_api_key: + commands: + run_command: + command: !Sub | + #!/bin/bash -xe + echo "TD_VCD_INIT_API_KEY=$(LC_ALL=C tr -dc A-Za-z0-9 /tmp/init_api_key.txt bind_storage: commands: fstab: @@ -479,6 +505,49 @@ Resources: docker: enabled: "true" ensureRunning: "true" + configure_ai_unlimited_ui_service: + files: + /usr/lib/systemd/system/ai-unlimited-ui.service: + content: !Sub | + [Unit] + Description=ai-unlimited-ui + After=docker.service + Requires=docker.service + StartLimitInterval=200 + StartLimitBurst=10 + + [Service] + TimeoutStartSec=0 + Restart=always + RestartSec=2 + + ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' + ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited-ui + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true + ExecStartPre=-/usr/bin/docker rm %n || true + ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + ExecStart=/usr/bin/docker run \ + -e accept_license=Y \ + -e PLATFORM=aws \ + -e TD_VCD_UI_PORT=${ AiUnlimitedUiPort } \ + -e TD_VCD_API_PORT=3282 \ + -e TD_VCD_AUTH_PORT=3000 \ + -e TD_VCD_INIT_API_KEY \ + -p ${ AiUnlimitedUiPort }:80 \ + --network ai_unlimited \ + --rm --name %n teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + [Install] + WantedBy=multi-user.target + group: root + mode: "000400" + owner: root + start_ai_unlimited_ui_service: + services: + systemd: + ai-unlimited-ui: + enabled: "true" + ensureRunning: "true" configure_ai_unlimited_service: files: /usr/lib/systemd/system/ai-unlimited.service: @@ -494,16 +563,17 @@ Resources: TimeoutStartSec=0 Restart=always RestartSec=2 - ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited - ExecStartPre=-/usr/bin/docker exec %n stop || true + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } ExecStart=/usr/bin/docker run \ -e accept_license=Y \ -e PLATFORM=aws \ + -e TD_VCD_INIT_API_KEY \ -v /etc/td/ai-unlimited:/etc/td \ - -p ${ AiUnlimitedHttpPort }:3000 \ + -p ${ AiUnlimitedAuthPort }:3000 \ -p ${ AiUnlimitedGrpcPort }:3282 \ --network ai_unlimited \ --net-alias ${ LoadBalancer.DNSName } \ @@ -534,7 +604,7 @@ Resources: TimeoutStartSec=0 Restart=always RestartSec=2 - ExecStartPre=-/usr/bin/docker exec %n stop || true + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-scheduler:${ AiUnlimitedSchedulerVersion } ExecStart=/usr/bin/docker run \ @@ -658,9 +728,9 @@ Resources: VpcId: !Ref Vpc GroupDescription: Enable access to AI Unlimited server from LoadBalancer over http, grpc, and ssh SecurityGroupIngress: - - FromPort: !Ref AiUnlimitedHttpPort + - FromPort: !Ref AiUnlimitedAuthPort IpProtocol: tcp - ToPort: !Ref AiUnlimitedHttpPort + ToPort: !Ref AiUnlimitedAuthPort CidrIp: !If - HASCIDR - !Ref AccessCIDR @@ -684,6 +754,21 @@ Resources: - HASSECURITYGROUP - !Ref SecurityGroup - !Ref AWS::NoValue + - FromPort: !Ref AiUnlimitedUiPort + IpProtocol: tcp + ToPort: !Ref AiUnlimitedUiPort + CidrIp: !If + - HASCIDR + - !Ref AccessCIDR + - !Ref AWS::NoValue + SourcePrefixListId: !If + - HASPREFIXLIST + - !Ref PrefixList + - !Ref AWS::NoValue + SourceSecurityGroupId: !If + - HASSECURITYGROUP + - !Ref SecurityGroup + - !Ref AWS::NoValue Condition: HASCIDRORPREFIXLISTORSECGROUP LoadBalancerSchedulerSecurityGroup: @@ -762,7 +847,17 @@ Resources: - Type: forward TargetGroupArn: !Ref AiUnlimitedHTTPTargetGroup LoadBalancerArn: !Ref LoadBalancer - Port: !Ref AiUnlimitedHttpPort + Port: !Ref AiUnlimitedAuthPort + Protocol: TCP + + AiUnlimitedUIListener: + Type: AWS::ElasticLoadBalancingV2::Listener + Properties: + DefaultActions: + - Type: forward + TargetGroupArn: !Ref AiUnlimitedUITargetGroup + LoadBalancerArn: !Ref LoadBalancer + Port: !Ref AiUnlimitedUiPort Protocol: TCP JupyterHTTPListener: @@ -825,7 +920,41 @@ Resources: - td-aiu - ui - http - Port: !Ref AiUnlimitedHttpPort + Port: !Ref AiUnlimitedAuthPort + Protocol: TCP + TargetGroupAttributes: + - Key: stickiness.enabled + Value: true + - Key: stickiness.type + Value: source_ip + - Key: deregistration_delay.timeout_seconds + Value: "20" + Targets: + - Id: !Ref AiUnlimitedServer + Port: !Ref AiUnlimitedAuthPort + VpcId: !Ref Vpc + + AiUnlimitedUITargetGroup: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + HealthCheckIntervalSeconds: 30 + HealthCheckProtocol: HTTP + HealthCheckTimeoutSeconds: 15 + Name: !Join + - '-' + - - !Select + - 4 + - !Split + - '-' + - !Select + - 2 + - !Split + - / + - !Ref AWS::StackId + - td-aiu + - ui + - api + Port: !Ref AiUnlimitedUiPort Protocol: TCP TargetGroupAttributes: - Key: stickiness.enabled @@ -836,7 +965,7 @@ Resources: Value: "20" Targets: - Id: !Ref AiUnlimitedServer - Port: !Ref AiUnlimitedHttpPort + Port: !Ref AiUnlimitedUiPort VpcId: !Ref Vpc JupyterHTTPTargetGroup: @@ -986,18 +1115,22 @@ Resources: GroupDescription: Enable access to AI Unlimited server over http and grpc SecurityGroupIngress: - IpProtocol: tcp - FromPort: !Ref AiUnlimitedHttpPort - ToPort: !Ref AiUnlimitedHttpPort + FromPort: !Ref AiUnlimitedAuthPort + ToPort: !Ref AiUnlimitedAuthPort SourceSecurityGroupId: !GetAtt LoadBalancerAiUnlimitedSecurityGroup.GroupId - IpProtocol: tcp FromPort: !Ref AiUnlimitedGrpcPort ToPort: !Ref AiUnlimitedGrpcPort SourceSecurityGroupId: !GetAtt LoadBalancerAiUnlimitedSecurityGroup.GroupId + - IpProtocol: tcp + FromPort: !Ref AiUnlimitedUiPort + ToPort: !Ref AiUnlimitedUiPort + SourceSecurityGroupId: !GetAtt LoadBalancerAiUnlimitedSecurityGroup.GroupId - !If - HASSECURITYGROUP - IpProtocol: tcp - FromPort: !Ref AiUnlimitedHttpPort - ToPort: !Ref AiUnlimitedHttpPort + FromPort: !Ref AiUnlimitedAuthPort + ToPort: !Ref AiUnlimitedAuthPort SourceSecurityGroupId: !Ref SecurityGroup - !Ref AWS::NoValue - !If @@ -1007,6 +1140,13 @@ Resources: ToPort: !Ref AiUnlimitedGrpcPort SourceSecurityGroupId: !Ref SecurityGroup - !Ref AWS::NoValue + - !If + - HASSECURITYGROUP + - IpProtocol: tcp + FromPort: !Ref AiUnlimitedUiPort + ToPort: !Ref AiUnlimitedUiPort + SourceSecurityGroupId: !Ref SecurityGroup + - !Ref AWS::NoValue AiUnlimitedSchedulerSecurityGroup: Type: AWS::EC2::SecurityGroup @@ -1301,7 +1441,10 @@ Outputs: AiUnlimitedUiAccess: Description: Loadbalancer access endpoint for AI Unlimited UI Access - Value: !Sub http://${ LoadBalancer.DNSName }:${ AiUnlimitedHttpPort } + Value: !If + - PortIsNotEighty + - !Sub "http://${ LoadBalancer.DNSName }:${ AiUnlimitedUiPort }/healthcheck" + - !Sub "http://${ LoadBalancer.DNSName }" AiUnlimitedApiAccess: Description: Loadbalancer access endpoint for AI Unlimited API Access diff --git a/deployments/aws/templates/all-in-one/all-in-one-without-lb.yaml b/deployments/aws/templates/all-in-one/all-in-one-without-lb.yaml index 210e0b8..5ad0381 100644 --- a/deployments/aws/templates/all-in-one/all-in-one-without-lb.yaml +++ b/deployments/aws/templates/all-in-one/all-in-one-without-lb.yaml @@ -27,12 +27,14 @@ Metadata: - AccessCIDR - PrefixList - SecurityGroup - - AiUnlimitedHttpPort + - AiUnlimitedAuthPort - AiUnlimitedGrpcPort - AiUnlimitedVersion - AiUnlimitedSchedulerVersion - AiUnlimitedSchedulerHttpPort - AiUnlimitedSchedulerGrpcPort + - AiUnlimitedUiPort + - AiUnlimitedUiVersion - Label: default: Persistent volume Parameters: @@ -100,8 +102,8 @@ Parameters: Type: AWS::EC2::AvailabilityZone::Name ConstraintDescription: must be the name of a existing subnet. - AiUnlimitedHttpPort: - Description: port to access the AI Unlimited UI. + AiUnlimitedAuthPort: + Description: port to access the AI Unlimited Authentication Service. Type: Number Default: 3000 ConstraintDescription: must be a valid ununsed port between 0 and 65535. @@ -132,16 +134,29 @@ Parameters: MinValue: 0 MaxValue: 65535 + AiUnlimitedUiPort: + Description: port to access the AI Unlimited UI. + Type: Number + Default: 80 + ConstraintDescription: must be a valid ununsed port between 0 and 65535. + MinValue: 0 + MaxValue: 65535 + AiUnlimitedVersion: Description: Which version of AI Unlimited to deploy, uses container version tags, defaults to "latest" Type: String - Default: v0.2.23 + Default: v0.3.0 AiUnlimitedSchedulerVersion: Description: Which version of AI Unlimited Scheduler to deploy, uses container version tags, defaults to "latest" Type: String Default: latest + AiUnlimitedUiVersion: + Description: Which version of AI Unlimited UI to deploy, uses container version tags, defaults to "latest" + Type: String + Default: v0.0.5 + JupyterHttpPort: Description: port to access the Jupyter UI. Type: Number @@ -365,6 +380,19 @@ Conditions: - !Ref IamRoleName - "" + PortIsNotEightyAndHasPublicIp: + !And + - !Not + - !Equals + - !Ref Private + - "true" + - !Not + - !Equals + - !Ref AiUnlimitedUiPort + - 80 + + PortIsNotEighty: !Not [!Equals [!Ref AiUnlimitedUiPort, 80]] + Resources: AiUnlimitedVolume: DeletionPolicy: !Ref PersistentVolumeDeletionPolicy @@ -406,11 +434,14 @@ Resources: - prepare_new_storage - !Ref AWS::NoValue - bind_storage + - create_init_api_key - mount_storage - install_docker + - configure_ai_unlimited_ui_service - configure_ai_unlimited_service - - configure_jupyter_service + - start_ai_unlimited_ui_service - start_ai_unlimited_service + - configure_jupyter_service - configure_ai_unlimited_scheduler_service - start_ai_unlimited_scheduler_service - start_jupyter_service @@ -420,6 +451,12 @@ Resources: command: !Sub | #!/bin/bash -xe mkdir -p /etc/td + create_init_api_key: + commands: + run_command: + command: !Sub | + #!/bin/bash -xe + echo "TD_VCD_INIT_API_KEY=$(LC_ALL=C tr -dc A-Za-z0-9 /tmp/init_api_key.txt prepare_new_storage: commands: mkfs: @@ -464,6 +501,49 @@ Resources: docker: enabled: "true" ensureRunning: "true" + configure_ai_unlimited_ui_service: + files: + /usr/lib/systemd/system/ai-unlimited-ui.service: + content: !Sub | + [Unit] + Description=ai-unlimited-ui + After=docker.service + Requires=docker.service + StartLimitInterval=200 + StartLimitBurst=10 + + [Service] + TimeoutStartSec=0 + Restart=always + RestartSec=2 + + ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' + ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited-ui + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true + ExecStartPre=-/usr/bin/docker rm %n || true + ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + ExecStart=/usr/bin/docker run \ + -e accept_license=Y \ + -e PLATFORM=aws \ + -e TD_VCD_UI_PORT=${ AiUnlimitedUiPort } \ + -e TD_VCD_API_PORT=${ AiUnlimitedGrpcPort } \ + -e TD_VCD_AUTH_PORT=${ AiUnlimitedAuthPort } \ + -e TD_VCD_INIT_API_KEY \ + -p ${ AiUnlimitedUiPort }:80 \ + --network ai_unlimited \ + --rm --name %n teradata/ai-unlimited-workspaces-ui:${ AiUnlimitedUiVersion } + [Install] + WantedBy=multi-user.target + group: root + mode: "000400" + owner: root + start_ai_unlimited_ui_service: + services: + systemd: + ai-unlimited-ui: + enabled: "true" + ensureRunning: "true" configure_ai_unlimited_service: files: /usr/lib/systemd/system/ai-unlimited.service: @@ -479,16 +559,17 @@ Resources: TimeoutStartSec=0 Restart=always RestartSec=2 - ExecStartPre=-/bin/bash -c '/usr/bin/docker network create -d bridge ai_unlimited || true' ExecStartPre=-/usr/bin/mkdir -p /etc/td/ai-unlimited - ExecStartPre=-/usr/bin/docker exec %n stop || true + EnvironmentFile=/tmp/init_api_key.txt + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } ExecStart=/usr/bin/docker run \ -e accept_license=Y \ -e PLATFORM=aws \ + -e TD_VCD_INIT_API_KEY \ -v /etc/td/ai-unlimited:/etc/td \ - -p ${ AiUnlimitedHttpPort }:3000 \ + -p ${ AiUnlimitedAuthPort }:3000 \ -p ${ AiUnlimitedGrpcPort }:3282 \ --network ai_unlimited \ --rm --name %n teradata/ai-unlimited-workspaces:${ AiUnlimitedVersion } workspaces serve -v @@ -518,7 +599,7 @@ Resources: TimeoutStartSec=0 Restart=always RestartSec=2 - ExecStartPre=-/usr/bin/docker exec %n stop || true + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-scheduler:latest ExecStart=/usr/bin/docker run \ @@ -558,7 +639,7 @@ Resources: Restart=always RestartSec=2 ExecStartPre=-/usr/bin/mkdir -p /etc/td/jupyter/{userdata,ipython} - ExecStartPre=-/usr/bin/docker exec %n stop || true + ExecStartPre=-/usr/bin/docker stop %n || true ExecStartPre=-/usr/bin/docker rm %n || true ExecStartPre=/usr/bin/docker pull teradata/ai-unlimited-jupyter:${ JupyterVersion } ExecStart=/usr/bin/docker run \ @@ -641,9 +722,9 @@ Resources: VpcId: !Ref Vpc GroupDescription: Enable access to AI Unlimited server over http and grpc SecurityGroupIngress: - - FromPort: !Ref AiUnlimitedHttpPort + - FromPort: !Ref AiUnlimitedAuthPort IpProtocol: tcp - ToPort: !Ref AiUnlimitedHttpPort + ToPort: !Ref AiUnlimitedAuthPort CidrIp: !If - HASCIDR - !Ref AccessCIDR @@ -671,6 +752,21 @@ Resources: - HASSECURITYGROUP - !Ref SecurityGroup - !Ref AWS::NoValue + - FromPort: !Ref AiUnlimitedUiPort + IpProtocol: tcp + ToPort: !Ref AiUnlimitedUiPort + CidrIp: !If + - HASCIDR + - !Ref AccessCIDR + - !Ref AWS::NoValue + SourcePrefixListId: !If + - HASPREFIXLIST + - !Ref PrefixList + - !Ref AWS::NoValue + SourceSecurityGroupId: !If + - HASSECURITYGROUP + - !Ref SecurityGroup + - !Ref AWS::NoValue AiUnlimitedSchedulerSecurityGroup: Type: AWS::EC2::SecurityGroup @@ -970,12 +1066,17 @@ Outputs: AiUnlimitedPublicUIAccess: Description: Teradata AI Unlimited public UI Access - Value: !Sub http://${AiUnlimitedServer.PublicDnsName}:${ AiUnlimitedHttpPort } + Value: !If [ PortIsNotEightyAndHasPublicIp, + !Sub "http://${AiUnlimitedServer.PublicDnsName}:${AiUnlimitedUiPort}/healthcheck", + !Sub "http://${AiUnlimitedServer.PublicDnsName}" ] Condition: HASPUBLICIP AiUnlimitedPrivateUIAccess: Description: Teradata AI Unlimited private UI Access - Value: !Sub http://${AiUnlimitedServer.PrivateDnsName}:${ AiUnlimitedHttpPort } + Value: !If + - PortIsNotEighty + - !Sub "http://${AiUnlimitedServer.PrivateDnsName}:${AiUnlimitedUiPort}/healthcheck" + - !Sub "http://${AiUnlimitedServer.PrivateDnsName}" AiUnlimitedPublicAPIAccess: Description: Teradata AI Unlimited public API Access