Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ecs): allow selection of container and port for SRV service discovery records #12798

Merged
merged 34 commits into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
258a37e
feat: add BaseService.addCloudMapService
misterjoshua Feb 1, 2021
2228262
fix: broke backwards-compat of protected variable
misterjoshua Feb 1, 2021
9d97506
implement features in cloudMapOptions
misterjoshua Feb 1, 2021
9f4541b
fix: remove the cdk-integ.out that snuck in
misterjoshua Feb 1, 2021
2e3407d
chore: improve inline docs
misterjoshua Feb 1, 2021
e0e0b87
Merge branch 'master' into ecs-discovery
misterjoshua Feb 1, 2021
ed97aa8
Merge branch 'master' into ecs-discovery
misterjoshua Feb 2, 2021
628263f
add some docs to the readme
misterjoshua Feb 2, 2021
533c120
fix: missing single trailing newline
misterjoshua Feb 2, 2021
c7078f9
fix: port mapping check did not support UDP
misterjoshua Feb 3, 2021
79ee844
Merge branch 'master' into ecs-discovery
misterjoshua Feb 3, 2021
a5ccc4c
Merge branch 'master' into ecs-discovery
misterjoshua Feb 4, 2021
39e8c81
Merge branch 'master' into ecs-discovery
misterjoshua Feb 5, 2021
ba678c2
chore: have the srv test use a non-default container
misterjoshua Feb 5, 2021
5307ce4
empty commit to cause rebuild
misterjoshua Feb 5, 2021
27ce5f2
Merge branch 'master' into ecs-discovery
misterjoshua Feb 8, 2021
e242774
Merge branch 'master' into ecs-discovery
misterjoshua Feb 9, 2021
5647836
Merge branch 'master' into ecs-discovery
misterjoshua Feb 11, 2021
f66086c
Merge branch 'master' into ecs-discovery
misterjoshua Feb 12, 2021
f59059f
Merge branch 'master' into ecs-discovery
SoManyHs Feb 16, 2021
89dc00c
Merge branch 'master' of github.com:aws/aws-cdk into ecs-discovery
misterjoshua Feb 17, 2021
41395c3
fix: README merge conflict was resolved incorrectly
misterjoshua Feb 17, 2021
d33b765
Merge branch 'master' into ecs-discovery
misterjoshua Feb 21, 2021
bceecd5
Merge branch 'master' of github.com:aws/aws-cdk into ecs-discovery
misterjoshua Feb 22, 2021
378e815
refactor: put container/port selection logic in its own function
misterjoshua Feb 22, 2021
9153a1b
Merge branch 'master' into ecs-discovery
misterjoshua Feb 26, 2021
352e8b6
Merge branch 'master' into ecs-discovery
SoManyHs Mar 2, 2021
df0d757
Merge branch 'master' into ecs-discovery
SoManyHs Mar 3, 2021
851babc
refactor: unexpose determineContainerNameAndPort, test public api
misterjoshua Mar 3, 2021
f566a6d
refactor: unexpose DetermineContainerNameAndPortOptions
misterjoshua Mar 3, 2021
2c01801
Merge branch 'master' into ecs-discovery
mergify[bot] Mar 4, 2021
c2a7fff
Update packages/@aws-cdk/aws-ecs/README.md
SoManyHs Mar 4, 2021
a737a4d
Update packages/@aws-cdk/aws-ecs/README.md
SoManyHs Mar 4, 2021
b98b31b
Update packages/@aws-cdk/aws-ecs/README.md
SoManyHs Mar 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,49 @@ taskDefinition.addContainer('TheContainer', {
});
```

## CloudMap Service Discovery

To register your ECS service with a CloudMap Service Registry, you may add the
`cloudMapOptions` property to your service:

```ts
const service = new ecs.Ec2Service(stack, 'Service', {
cluster,
taskDefinition,
cloudMapOptions: {
// Create A records - useful for AWSVPC network mode.
dnsRecordType: cloudmap.DnsRecordType.A,
},
});
```

With `bridge` or `host` network modes, only `SRV` DNS record types are supported.
By default, `SRV` DNS record types will target the default container and default
port. However, you may target a different container and port on the same ECS task:

```ts
// Add a container to the task definition
const specificContainer = taskDefinition.addContainer(...);

// Add a port mapping
specificContainer.addPortMappings({
containerPort: 7600,
protocol: ecs.Protocol.TCP,
});

new ecs.Ec2Service(stack, 'Service', {
cluster,
taskDefinition,
cloudMapOptions: {
// Create SRV records - useful for bridge networking
dnsRecordType: cloudmap.DnsRecordType.SRV,
// Targets port TCP port 7600 `specificContainer`
container: specificContainer,
containerPort: 7600,
},
});
```

## Capacity Providers

Currently, only `FARGATE` and `FARGATE_SPOT` capacity providers are supported.
Expand Down
65 changes: 59 additions & 6 deletions packages/@aws-cdk/aws-ecs/lib/base/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import * as cloudmap from '@aws-cdk/aws-servicediscovery';
import { Annotations, Duration, IResolvable, IResource, Lazy, Resource, Stack } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { LoadBalancerTargetOptions, NetworkMode, TaskDefinition } from '../base/task-definition';
import { ContainerDefinition, Protocol } from '../container-definition';
import { ICluster, CapacityProviderStrategy } from '../cluster';
import { Protocol } from '../container-definition';
import { CfnService } from '../ecs.generated';
import { ScalableTaskCount } from './scalable-task-count';

Expand Down Expand Up @@ -572,10 +572,12 @@ export abstract class BaseService extends Resource
}
}

// If the task definition that your service task specifies uses the AWSVPC network mode and a type SRV DNS record is
// used, you must specify a containerName and containerPort combination
const containerName = dnsRecordType === cloudmap.DnsRecordType.SRV ? this.taskDefinition.defaultContainer!.containerName : undefined;
const containerPort = dnsRecordType === cloudmap.DnsRecordType.SRV ? this.taskDefinition.defaultContainer!.containerPort : undefined;
const { containerName, containerPort } = determineContainerNameAndPort({
taskDefinition: this.taskDefinition,
dnsRecordType: dnsRecordType!,
container: options.container,
containerPort: options.containerPort,
});

const cloudmapService = new cloudmap.Service(this, 'CloudmapService', {
namespace: sdNamespace,
Expand Down Expand Up @@ -799,7 +801,19 @@ export interface CloudMapOptions {
*
* NOTE: This is used for HealthCheckCustomConfig
*/
readonly failureThreshold?: number,
readonly failureThreshold?: number;

/**
* The container to point to for a SRV record.
* @default - the task definition's default container
*/
readonly container?: ContainerDefinition;

/**
* The port to point to for a SRV record.
* @default - the default port of the task definition's default container
*/
readonly containerPort?: number;
}

/**
Expand Down Expand Up @@ -885,3 +899,42 @@ export enum PropagatedTagSource {
*/
NONE = 'NONE'
}

/**
* Options for `determineContainerNameAndPort`
*/
interface DetermineContainerNameAndPortOptions {
dnsRecordType: cloudmap.DnsRecordType;
taskDefinition: TaskDefinition;
container?: ContainerDefinition;
containerPort?: number;
}

/**
* Determine the name of the container and port to target for the service registry.
*/
function determineContainerNameAndPort(options: DetermineContainerNameAndPortOptions) {
// If the record type is SRV, then provide the containerName and containerPort to target.
// We use the name of the default container and the default port of the default container
// unless the user specifies otherwise.
if (options.dnsRecordType === cloudmap.DnsRecordType.SRV) {
// Ensure the user-provided container is from the right task definition.
if (options.container && options.container.taskDefinition != options.taskDefinition) {
throw new Error('Cannot add discovery for a container from another task definition');
}

const container = options.container ?? options.taskDefinition.defaultContainer!;

// Ensure that any port given by the user is mapped.
if (options.containerPort && !container.portMappings.some(mapping => mapping.containerPort === options.containerPort)) {
throw new Error('Cannot add discovery for a container port that has not been mapped');
}

return {
containerName: container.containerName,
containerPort: options.containerPort ?? options.taskDefinition.defaultContainer!.containerPort,
};
}

return {};
}
Loading