primary-replica: separate HTTP from SSH traffic
Using a Network Load Balancer forces all the traffic to be handled at
the transport level (Level 4). Whilst this is fine for SSH traffic, it
is not ideal for HTTP traffic, which should be handled at application
level (Level 7).
Split HTTP and SSH traffic and handle HTTP traffic via an Application
Load Balancer.
This unlocks many benefits, among which:
- Advanced routing: based on path, host, headers, request method,
source IP, etc
- Application-based sticky sessions
- Seamless integration with X-Ray
- Detailed access logs
Bug: Issue 15087
Change-Id: I588b776f08583b46c7325432bbb39a3457c4ca39
diff --git a/primary-replica/Makefile b/primary-replica/Makefile
index 0afea75..7bffb65 100644
--- a/primary-replica/Makefile
+++ b/primary-replica/Makefile
@@ -82,8 +82,9 @@
ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
- ParameterKey=Subdomain,ParameterValue=$(PRIMARY_SUBDOMAIN) \
- ParameterKey=ReplicaSubdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+ ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_PRIMARY_SUBDOMAIN) \
+ ParameterKey=SshSubdomain,ParameterValue=$(SSH_PRIMARY_SUBDOMAIN) \
+ ParameterKey=SshReplicaSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
ParameterKey=ReplicaServiceStackName,ParameterValue=$(SERVICE_REPLICA_STACK_NAME) \
@@ -127,7 +128,8 @@
ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
- ParameterKey=Subdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+ ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_REPLICA_SUBDOMAIN) \
+ ParameterKey=SshSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\
diff --git a/primary-replica/README.md b/primary-replica/README.md
index d710050..9cff49c 100644
--- a/primary-replica/README.md
+++ b/primary-replica/README.md
@@ -56,8 +56,10 @@
* `SERVICE_PRIMARY_STACK_NAME`: Optional. Name of the primary service stack. `gerrit-service-primary` by default.
* `SERVICE_REPLICA_STACK_NAME`: Optional. Name of the replica service stack. `gerrit-service-replica` by default.
* `DASHBOARD_STACK_NAME` : Optional. Name of the dashboard stack. `gerrit-dashboard` by default.
-* `PRIMARY_SUBDOMAIN`: Optional. Name of the primary sub domain. `gerrit-primary-demo` by default.
-* `REPLICA_SUBDOMAIN`: Optional. Name of the replica sub domain. `gerrit-replica-demo` by default.
+* `HTTP_PRIMARY_SUBDOMAIN`: Optional. Name of the primary sub domain for HTTP traffic. `gerrit-http-primary-demo` by default.
+* `SSH_PRIMARY_SUBDOMAIN`: Optional. Name of the primary sub domain for SSH traffic. `gerrit-ssh-primary-demo` by default.
+* `HTTP_REPLICA_SUBDOMAIN`: Optional. Name of the replica sub domain for HTTP traffic. `gerrit-http-replica-demo` by default.
+* `SSH_REPLICA_SUBDOMAIN`: Optional. Name of the replica sub domain for SSH traffic. `gerrit-ssh-replica-demo` by default.
* `GERRIT_PRIMARY_INSTANCE_ID`: Optional. Identifier for the Gerrit primary instance.
"gerrit-primary-replica-PRIMARY" by default.
* `GERRIT_REPLICA_INSTANCE_ID`: Optional. Identifier for the Gerrit replica instance.
diff --git a/primary-replica/cf-dns-route.yml b/primary-replica/cf-dns-route.yml
index ec9b369..ee2bea9 100644
--- a/primary-replica/cf-dns-route.yml
+++ b/primary-replica/cf-dns-route.yml
@@ -11,26 +11,50 @@
Default: gerrit-service-replica
Resources:
- PrimaryDnsRecord:
+ PrimaryHTTPDnsRecord:
Type: AWS::Route53::RecordSet
Properties:
Name:
!Join
- '.'
- - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'Subdomain']]
+ - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HttpSubdomain']]
- Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
HostedZoneName:
!Join
- ''
- - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
- '.'
- Comment: DNS name for Gerrit Primary.
+ Comment: DNS name for Load Balancer serving HTTP requests to primary gerrit
Type: A
AliasTarget:
DNSName:
Fn::ImportValue:
- !Join [':', [!Ref 'PrimaryServiceStackName', 'PublicLoadBalancerDNSName']]
+ !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritHTTPLoadBalancerDNSName']]
HostedZoneId:
Fn::ImportValue:
- !Join [':', [!Ref 'PrimaryServiceStackName', 'CanonicalHostedZoneID']]
+ !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritHTTPCanonicalHostedZoneID']]
EvaluateTargetHealth: False
+
+ PrimarySSHDnsRecord:
+ Type: AWS::Route53::RecordSet
+ Properties:
+ Name:
+ !Join
+ - '.'
+ - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'SshSubdomain']]
+ - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
+ HostedZoneName:
+ !Join
+ - ''
+ - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
+ - '.'
+ Comment: DNS name for Load Balancer serving SSH requests to primary gerrit
+ Type: A
+ AliasTarget:
+ DNSName:
+ Fn::ImportValue:
+ !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritSSHLoadBalancerDNSName']]
+ HostedZoneId:
+ Fn::ImportValue:
+ !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritSSHCanonicalHostedZoneID']]
+ EvaluateTargetHealth: False
\ No newline at end of file
diff --git a/primary-replica/cf-service-primary.yml b/primary-replica/cf-service-primary.yml
index 3fe939f..10a0642 100644
--- a/primary-replica/cf-service-primary.yml
+++ b/primary-replica/cf-service-primary.yml
@@ -55,18 +55,22 @@
HostedZoneName:
Description: The route53 HostedZoneName.
Type: String
- Subdomain:
- Description: The subdomain of the Gerrit cluster
+ HttpSubdomain:
+ Description: The subdomain of the loadbalancer serving HTTP traffic for the primary Gerrit
Type: String
- Default: gerrit-primary-demo
+ Default: gerrit-primary-http-demo
+ SshSubdomain:
+ Description: The subdomain of the loadbalancer serving SSH traffic for the primary Gerrit
+ Type: String
+ Default: gerrit-primary-ssh-demo
LoadBalancerScheme:
Description: Load Balancer schema, The nodes of an Internet-facing load balancer have public IP addresses.
Type: String
Default: internet-facing
AllowedValues: [internal, internet-facing]
- ReplicaSubdomain:
- Description: The subdomain of the Gerrit replica
- Type: String
+ SshReplicaSubdomain:
+ Description: The subdomain of the loadbalancer serving SSH traffic for the replicas
+ Type: String
GerritKeyPrefix:
Description: Gerrit credentials keys prefix
Type: String
@@ -219,7 +223,9 @@
Image: !Sub '${DockerRegistryUrl}/${DockerImage}'
Environment:
- Name: CANONICAL_WEB_URL
- Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+ Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
+ - Name: SSHD_ADVERTISED_ADDRESS
+ Value: !Sub '${SshSubdomain}.${HostedZoneName}:${SSHPort}'
- Name: HTTPD_LISTEN_URL
Value: !Sub 'proxy-https://*:${HTTPPort}/'
- Name: AWS_REGION
@@ -263,7 +269,7 @@
- Name: GIT_SSH_PORT
Value: !Ref GitSSHPort
- Name: REPLICA_SUBDOMAIN
- Value: !Ref ReplicaSubdomain
+ Value: !Ref SshReplicaSubdomain
- Name: HOSTED_ZONE_NAME
Value: !Ref HostedZoneName
- Name: REINDEX_AT_STARTUP
@@ -334,9 +340,47 @@
Host:
SourcePath: !Join ['/', ["/gerrit-mount-point", !FindInMap ['Gerrit', 'Volume', 'Logs']]]
- LoadBalancer:
+ GerritHTTPLoadBalancerSG:
+ Type: AWS::EC2::SecurityGroup
+ Properties:
+ VpcId:
+ Fn::ImportValue:
+ !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+ GroupDescription: "Allow public HTTPS traffic to primary Gerrit"
+ GroupName: !Sub '${ClusterStackName}-gerrit-http-sg'
+ SecurityGroupIngress:
+ - IpProtocol: 'tcp'
+ FromPort: !Ref HTTPSPort
+ ToPort: !Ref HTTPSPort
+ CidrIp: '0.0.0.0/0'
+ Description: "HTTPS connections from everywhere (IPv4)"
+ - IpProtocol: 'tcp'
+ FromPort: !Ref HTTPSPort
+ ToPort: !Ref HTTPSPort
+ CidrIpv6: '::/0'
+ Description: "HTTPS connections from everywhere (IPv6)"
+
+ GerritHTTPLoadBalancer:
+ Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+ Properties:
+ Name: !Sub '${ClusterStackName}-primary-http'
+ Type: application
+ Scheme: !Ref 'LoadBalancerScheme'
+ SecurityGroups:
+ - !Ref GerritHTTPLoadBalancerSG
+ Subnets:
+ - Fn::ImportValue:
+ !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+ - Fn::ImportValue:
+ !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+ Tags:
+ - Key: Name
+ Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'alb']]
+
+ GerritSSHLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
+ Name: !Sub '${ClusterStackName}-primary-ssh'
Type: network
Scheme: !Ref 'LoadBalancerScheme'
LoadBalancerAttributes:
@@ -353,13 +397,13 @@
HTTPTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
- DependsOn: LoadBalancer
+ DependsOn: GerritHTTPLoadBalancer
Properties:
VpcId:
Fn::ImportValue:
!Join [':', [!Ref 'ClusterStackName', 'VPCId']]
Port: !Ref HTTPPort
- Protocol: TCP
+ Protocol: HTTP
HealthCheckProtocol: HTTP
HealthCheckPort: !Ref HTTPPort
HealthCheckPath: '/config/server/healthcheck~status'
@@ -367,20 +411,19 @@
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn: LoadBalancer
Properties:
Certificates:
- CertificateArn: !Ref CertificateArn
DefaultActions:
- Type: forward
TargetGroupArn: !Ref HTTPTargetGroup
- LoadBalancerArn: !Ref LoadBalancer
+ LoadBalancerArn: !Ref GerritHTTPLoadBalancer
Port: !Ref HTTPSPort
- Protocol: TLS
+ Protocol: HTTPS
SSHTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
- DependsOn: LoadBalancer
+ DependsOn: GerritSSHLoadBalancer
Properties:
VpcId:
Fn::ImportValue:
@@ -394,12 +437,11 @@
SSHListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn: LoadBalancer
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref SSHTargetGroup
- LoadBalancerArn: !Ref LoadBalancer
+ LoadBalancerArn: !Ref GerritSSHLoadBalancer
Port: !Ref SSHPort
Protocol: TCP
@@ -410,33 +452,62 @@
TimeoutInMinutes: '5'
Outputs:
- PublicLoadBalancerDNSName:
- Description: The DNS name of the external load balancer
- Value: !GetAtt 'LoadBalancer.DNSName'
+ ########
+ # HTTP #
+ ########
+ GerritHTTPLoadBalancerDNSName:
+ Description: The DNS name of the gerrit HTTP load balancer
+ Value: !GetAtt 'GerritHTTPLoadBalancer.DNSName'
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
- CanonicalHostedZoneID:
- Description: Canonical Hosted Zone ID
- Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerDNSName' ] ]
+ GerritHTTPCanonicalHostedZoneID:
+ Description: Canonical Hosted Zone ID of the gerrit HTTP load balancer
+ Value: !GetAtt 'GerritHTTPLoadBalancer.CanonicalHostedZoneID'
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
- PublicLoadBalancerUrl:
- Description: The url of the external load balancer
- Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPCanonicalHostedZoneID' ] ]
+ GerritHTTPLoadBalancerUrl:
+ Description: The url of the gerrit HTTP load balancer
+ Value: !Join ['', ['http://', !GetAtt 'GerritHTTPLoadBalancer.DNSName']]
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerUrl' ] ]
+ #######
+ # SSH #
+ #######
+ GerritSSHLoadBalancerDNSName:
+ Description: The DNS name of the gerrit SSH load balancer
+ Value: !GetAtt 'GerritSSHLoadBalancer.DNSName'
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerDNSName' ] ]
+ GerritSSHCanonicalHostedZoneID:
+ Description: Canonical Hosted Zone ID of the gerrit SSH load balancer
+ Value: !GetAtt 'GerritSSHLoadBalancer.CanonicalHostedZoneID'
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHCanonicalHostedZoneID' ] ]
+ GerritSSHLoadBalancerUrl:
+ Description: The url of the gerrit SSH load balancer
+ Value: !Join ['', ['http://', !GetAtt 'GerritSSHLoadBalancer.DNSName']]
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerUrl' ] ]
+ #######
+ # DNS #
+ #######
HostedZoneName:
Description: Route53 Hosted Zone name
Value: !Ref HostedZoneName
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
- Subdomain:
- Description: Service DNS subdomain
- Value: !Ref Subdomain
+ HttpSubdomain:
+ Description: Service DNS subdomain for gerrit HTTP traffic
+ Value: !Ref HttpSubdomain
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+ SshSubdomain:
+ Description: Service DNS subdomain for gerrit SSH traffic
+ Value: !Ref SshSubdomain
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
CanonicalWebUrl:
Description: Canonical Web URL
- Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+ Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/primary-replica/cf-service-replica.yml b/primary-replica/cf-service-replica.yml
index 4d355f5..e7a75df 100644
--- a/primary-replica/cf-service-replica.yml
+++ b/primary-replica/cf-service-replica.yml
@@ -74,10 +74,14 @@
HostedZoneName:
Description: The route53 HostedZoneName.
Type: String
- Subdomain:
- Description: The subdomain of the Gerrit cluster
+ HttpSubdomain:
+ Description: The subdomain of the Gerrit loadbalancer serving HTTP traffic for replicas
Type: String
- Default: gerrit-replica-demo
+ Default: gerrit-http-replica-demo
+ SshSubdomain:
+ Description: The subdomain of the Gerrit loadbalancer serving SSH traffic for replicas
+ Type: String
+ Default: gerrit-ssh-replica-demo
LoadBalancerScheme:
Description: Load Balancer schema, The nodes of an Internet-facing load balancer have public IP addresses.
Type: String
@@ -257,7 +261,9 @@
Image: !Sub '${DockerRegistryUrl}/${GerritDockerImage}'
Environment:
- Name: CANONICAL_WEB_URL
- Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+ Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
+ - Name: SSHD_ADVERTISED_ADDRESS
+ Value: !Sub '${SshSubdomain}.${HostedZoneName}:${SSHHostPort}'
- Name: HTTPD_LISTEN_URL
Value: !Sub 'proxy-https://*:${HTTPContainePort}/'
- Name: CONTAINER_REPLICA
@@ -428,9 +434,47 @@
- '/'
- !GetAtt GerritService.Name
- LoadBalancer:
+ ReplicaHTTPLoadBalancerSG:
+ Type: AWS::EC2::SecurityGroup
+ Properties:
+ VpcId:
+ Fn::ImportValue:
+ !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+ GroupDescription: "Allow public HTTPS traffic to replicas"
+ GroupName: !Sub '${ClusterStackName}-replica-http-sg'
+ SecurityGroupIngress:
+ - IpProtocol: 'tcp'
+ FromPort: !Ref HTTPSPort
+ ToPort: !Ref HTTPSPort
+ CidrIp: '0.0.0.0/0'
+ Description: "HTTPS connections from everywhere (IPv4)"
+ - IpProtocol: 'tcp'
+ FromPort: !Ref HTTPSPort
+ ToPort: !Ref HTTPSPort
+ CidrIpv6: '::/0'
+ Description: "HTTPS connections from everywhere (IPv6)"
+
+ ReplicaHTTPLoadBalancer:
+ Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+ Properties:
+ Name: !Sub '${ClusterStackName}-replica-http'
+ Type: application
+ Scheme: !Ref 'LoadBalancerScheme'
+ SecurityGroups:
+ - !Ref ReplicaHTTPLoadBalancerSG
+ Subnets:
+ - Fn::ImportValue:
+ !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+ - Fn::ImportValue:
+ !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+ Tags:
+ - Key: Name
+ Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'alb']]
+
+ ReplicaSSHLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
+ Name: !Sub '${ClusterStackName}-replica-ssh'
Type: network
Scheme: !Ref 'LoadBalancerScheme'
LoadBalancerAttributes:
@@ -447,13 +491,13 @@
HTTPTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
- DependsOn: LoadBalancer
+ DependsOn: ReplicaHTTPLoadBalancer
Properties:
VpcId:
Fn::ImportValue:
!Join [':', [!Ref 'ClusterStackName', 'VPCId']]
Port: !Ref HTTPHostPort
- Protocol: TCP
+ Protocol: HTTP
HealthCheckPort: !Ref HTTPHostPort
HealthCheckProtocol: HTTP
HealthCheckPath: '/config/server/healthcheck~status'
@@ -461,27 +505,24 @@
TargetGroupAttributes:
- Key: 'stickiness.enabled'
Value: true
- # NLB only supports source_ip. Move this to `lb_cookie` or `app_cookie`
- # when this target group is moved behind an ALB
- Key: 'stickiness.type'
- Value: 'source_ip'
+ Value: 'lb_cookie'
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn: LoadBalancer
Properties:
Certificates:
- CertificateArn: !Ref CertificateArn
DefaultActions:
- Type: forward
TargetGroupArn: !Ref HTTPTargetGroup
- LoadBalancerArn: !Ref LoadBalancer
+ LoadBalancerArn: !Ref ReplicaHTTPLoadBalancer
Port: !Ref HTTPSPort
- Protocol: TLS
+ Protocol: HTTPS
SSHTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
- DependsOn: LoadBalancer
+ DependsOn: ReplicaSSHLoadBalancer
Properties:
VpcId:
Fn::ImportValue:
@@ -495,18 +536,17 @@
SSHListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn: LoadBalancer
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref SSHTargetGroup
- LoadBalancerArn: !Ref LoadBalancer
+ LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
Port: !Ref SSHHostPort
Protocol: TCP
GitTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
- DependsOn: LoadBalancer
+ DependsOn: ReplicaSSHLoadBalancer
Properties:
VpcId:
Fn::ImportValue:
@@ -516,18 +556,17 @@
GitListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn: LoadBalancer
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref GitTargetGroup
- LoadBalancerArn: !Ref LoadBalancer
+ LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
Port: !Ref GitPort
Protocol: TCP
GitSSHTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
- DependsOn: LoadBalancer
+ DependsOn: ReplicaSSHLoadBalancer
Properties:
VpcId:
Fn::ImportValue:
@@ -537,27 +576,38 @@
GitSSHListener:
Type: AWS::ElasticLoadBalancingV2::Listener
- DependsOn: LoadBalancer
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref GitSSHTargetGroup
- LoadBalancerArn: !Ref LoadBalancer
+ LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
Port: !Ref GitSSHPort
Protocol: TCP
- ReplicaDnsRecord:
+ ReplicaSSHDnsRecord:
Type: AWS::Route53::RecordSet
Properties:
- Name: !Sub '${Subdomain}.${HostedZoneName}'
+ Name: !Sub '${SshSubdomain}.${HostedZoneName}'
HostedZoneName: !Sub '${HostedZoneName}.'
- Comment: DNS name for Gerrit Replica.
+ Comment: DNS name for Load Balancer serving SSH requests to gerrit replicas
Type: A
AliasTarget:
- DNSName: !GetAtt 'LoadBalancer.DNSName'
- HostedZoneId: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+ DNSName: !GetAtt 'ReplicaSSHLoadBalancer.DNSName'
+ HostedZoneId: !GetAtt 'ReplicaSSHLoadBalancer.CanonicalHostedZoneID'
EvaluateTargetHealth: False
+ ReplicaHTTPDnsRecord:
+ Type: AWS::Route53::RecordSet
+ Properties:
+ Name: !Sub '${HttpSubdomain}.${HostedZoneName}'
+ HostedZoneName: !Sub '${HostedZoneName}.'
+ Comment: DNS name for Load Balancer serving HTTP requests to gerrit replicas
+ Type: A
+ AliasTarget:
+ DNSName: !GetAtt 'ReplicaHTTPLoadBalancer.DNSName'
+ HostedZoneId: !GetAtt 'ReplicaHTTPLoadBalancer.CanonicalHostedZoneID'
+ EvaluateTargetHealth: False
+
ECSTaskExecutionRoleStack:
Type: AWS::CloudFormation::Stack
Properties:
@@ -565,33 +615,62 @@
TimeoutInMinutes: '5'
Outputs:
- PublicLoadBalancerDNSName:
- Description: The DNS name of the external load balancer
- Value: !GetAtt 'LoadBalancer.DNSName'
+ ########
+ # HTTP #
+ ########
+ ReplicaHTTPLoadBalancerDNSName:
+ Description: The DNS name of the replica HTTP load balancer
+ Value: !GetAtt 'ReplicaHTTPLoadBalancer.DNSName'
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
- CanonicalHostedZoneID:
- Description: Canonical Hosted Zone ID
- Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPLoadBalancerDNSName' ] ]
+ ReplicaHTTPCanonicalHostedZoneID:
+ Description: Canonical Hosted Zone ID of the replica HTTP load balancer
+ Value: !GetAtt 'ReplicaHTTPLoadBalancer.CanonicalHostedZoneID'
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
- PublicLoadBalancerUrl:
- Description: The url of the external load balancer
- Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPCanonicalHostedZoneID' ] ]
+ ReplicaHTTPLoadBalancerUrl:
+ Description: The url of the replica HTTP load balancer
+ Value: !Join ['', ['http://', !GetAtt 'ReplicaHTTPLoadBalancer.DNSName']]
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPLoadBalancerUrl' ] ]
+ #######
+ # SSH #
+ #######
+ ReplicaSSHLoadBalancerDNSName:
+ Description: The DNS name of the replica SSH load balancer
+ Value: !GetAtt 'ReplicaSSHLoadBalancer.DNSName'
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHLoadBalancerDNSName' ] ]
+ ReplicaSSHCanonicalHostedZoneID:
+ Description: Canonical Hosted Zone ID of the replica SSH load balancer
+ Value: !GetAtt 'ReplicaSSHLoadBalancer.CanonicalHostedZoneID'
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHCanonicalHostedZoneID' ] ]
+ ReplicaSSHLoadBalancerUrl:
+ Description: The url of the replica SSH load balancer
+ Value: !Join ['', ['http://', !GetAtt 'ReplicaSSHLoadBalancer.DNSName']]
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHLoadBalancerUrl' ] ]
+ #######
+ # DNS #
+ #######
HostedZoneName:
Description: Route53 Hosted Zone name
Value: !Ref HostedZoneName
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
- Subdomain:
- Description: Service DNS subdomain
- Value: !Ref Subdomain
+ HttpSubdomain:
+ Description: Service DNS subdomain for replicas HTTP traffic
+ Value: !Ref HttpSubdomain
Export:
- Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+ SshSubdomain:
+ Description: Service DNS subdomain for replicas SSH traffic
+ Value: !Ref SshSubdomain
+ Export:
+ Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
CanonicalWebUrl:
Description: Canonical Web URL
- Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+ Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/primary-replica/setup.env.template b/primary-replica/setup.env.template
index 8186090..4aade05 100644
--- a/primary-replica/setup.env.template
+++ b/primary-replica/setup.env.template
@@ -8,8 +8,10 @@
DNS_ROUTING_MONITORING_STACK_NAME:=$(AWS_PREFIX)-monitoring-dns-routing
DASHBOARD_STACK_NAME:=$(AWS_PREFIX)-dashboard
HOSTED_ZONE_NAME:=yourcompany.com
-PRIMARY_SUBDOMAIN:=$(AWS_PREFIX)-primary.gerrit-demo
-REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-replica.gerrit-demo
+HTTP_PRIMARY_SUBDOMAIN:=$(AWS_PREFIX)-http-primary.gerrit-demo
+SSH_PRIMARY_SUBDOMAIN:=$(AWS_PREFIX)-ssh-primary.gerrit-demo
+HTTP_REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-http-replica.gerrit-demo
+SSH_REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-ssh-replica.gerrit-demo
PROMETHEUS_SUBDOMAIN:=$(AWS_PREFIX)-prometheus.gerrit-demo
GRAFANA_SUBDOMAIN:=$(AWS_PREFIX)-grafana.gerrit-demo
DOCKER_REGISTRY_URI:=<yourAccountId>.dkr.ecr.us-east-1.amazonaws.com