-
Notifications
You must be signed in to change notification settings - Fork 4k
/
fargate-profile.ts
213 lines (187 loc) · 7.51 KB
/
fargate-profile.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import { CustomResource, ITaggable, Lazy, TagManager, TagType } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { Cluster } from './cluster';
import { FARGATE_PROFILE_RESOURCE_TYPE } from './cluster-resource-handler/consts';
import { ClusterResourceProvider } from './cluster-resource-provider';
// v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
// eslint-disable-next-line
import { Construct as CoreConstruct } from '@aws-cdk/core';
/**
* Options for defining EKS Fargate Profiles.
*/
export interface FargateProfileOptions {
/**
* The name of the Fargate profile.
* @default - generated
*/
readonly fargateProfileName?: string;
/**
* The pod execution role to use for pods that match the selectors in the
* Fargate profile. The pod execution role allows Fargate infrastructure to
* register with your cluster as a node, and it provides read access to Amazon
* ECR image repositories.
*
* @see https://docs.aws.amazon.com/eks/latest/userguide/pod-execution-role.html
* @default - a role will be automatically created
*/
readonly podExecutionRole?: iam.IRole;
/**
* The selectors to match for pods to use this Fargate profile. Each selector
* must have an associated namespace. Optionally, you can also specify labels
* for a namespace.
*
* At least one selector is required and you may specify up to five selectors.
*/
readonly selectors: Selector[];
/**
* The VPC from which to select subnets to launch your pods into.
*
* By default, all private subnets are selected. You can customize this using
* `subnetSelection`.
*
* @default - all private subnets used by theEKS cluster
*/
readonly vpc?: ec2.IVpc;
/**
* Select which subnets to launch your pods into. At this time, pods running
* on Fargate are not assigned public IP addresses, so only private subnets
* (with no direct route to an Internet Gateway) are allowed.
*
* @default - all private subnets of the VPC are selected.
*/
readonly subnetSelection?: ec2.SubnetSelection;
}
/**
* Configuration props for EKS Fargate Profiles.
*/
export interface FargateProfileProps extends FargateProfileOptions {
/**
* The EKS cluster to apply the Fargate profile to.
* [disable-awslint:ref-via-interface]
*/
readonly cluster: Cluster;
}
/**
* Fargate profile selector.
*/
export interface Selector {
/**
* The Kubernetes namespace that the selector should match.
*
* You must specify a namespace for a selector. The selector only matches pods
* that are created in this namespace, but you can create multiple selectors
* to target multiple namespaces.
*/
readonly namespace: string;
/**
* The Kubernetes labels that the selector should match. A pod must contain
* all of the labels that are specified in the selector for it to be
* considered a match.
*
* @default - all pods within the namespace will be selected.
*/
readonly labels?: { [key: string]: string };
}
/**
* Fargate profiles allows an administrator to declare which pods run on
* Fargate. This declaration is done through the profile’s selectors. Each
* profile can have up to five selectors that contain a namespace and optional
* labels. You must define a namespace for every selector. The label field
* consists of multiple optional key-value pairs. Pods that match a selector (by
* matching a namespace for the selector and all of the labels specified in the
* selector) are scheduled on Fargate. If a namespace selector is defined
* without any labels, Amazon EKS will attempt to schedule all pods that run in
* that namespace onto Fargate using the profile. If a to-be-scheduled pod
* matches any of the selectors in the Fargate profile, then that pod is
* scheduled on Fargate.
*
* If a pod matches multiple Fargate profiles, Amazon EKS picks one of the
* matches at random. In this case, you can specify which profile a pod should
* use by adding the following Kubernetes label to the pod specification:
* eks.amazonaws.com/fargate-profile: profile_name. However, the pod must still
* match a selector in that profile in order to be scheduled onto Fargate.
*/
export class FargateProfile extends CoreConstruct implements ITaggable {
/**
* The full Amazon Resource Name (ARN) of the Fargate profile.
*
* @attribute
*/
public readonly fargateProfileArn: string;
/**
* The name of the Fargate profile.
*
* @attribute
*/
public readonly fargateProfileName: string;
/**
* Resource tags.
*/
public readonly tags: TagManager;
/**
* The pod execution role to use for pods that match the selectors in the
* Fargate profile. The pod execution role allows Fargate infrastructure to
* register with your cluster as a node, and it provides read access to Amazon
* ECR image repositories.
*/
public readonly podExecutionRole: iam.IRole;
constructor(scope: Construct, id: string, props: FargateProfileProps) {
super(scope, id);
const provider = ClusterResourceProvider.getOrCreate(this, {
adminRole: props.cluster.adminRole,
});
this.podExecutionRole = props.podExecutionRole ?? new iam.Role(this, 'PodExecutionRole', {
assumedBy: new iam.ServicePrincipal('eks-fargate-pods.amazonaws.com'),
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKSFargatePodExecutionRolePolicy')],
});
this.podExecutionRole.grantPassRole(props.cluster.adminRole);
let subnets: string[] | undefined;
if (props.vpc) {
const selection: ec2.SubnetSelection = props.subnetSelection ?? { subnetType: ec2.SubnetType.PRIVATE };
subnets = props.vpc.selectSubnets(selection).subnetIds;
}
if (props.selectors.length < 1) {
throw new Error('Fargate profile requires at least one selector');
}
if (props.selectors.length > 5) {
throw new Error('Fargate profile supports up to five selectors');
}
this.tags = new TagManager(TagType.MAP, 'AWS::EKS::FargateProfile');
const resource = new CustomResource(this, 'Resource', {
serviceToken: provider.serviceToken,
resourceType: FARGATE_PROFILE_RESOURCE_TYPE,
properties: {
AssumeRoleArn: props.cluster.adminRole.roleArn,
Config: {
clusterName: props.cluster.clusterName,
fargateProfileName: props.fargateProfileName,
podExecutionRoleArn: this.podExecutionRole.roleArn,
selectors: props.selectors,
subnets,
tags: Lazy.any({ produce: () => this.tags.renderTags() }),
},
},
});
this.fargateProfileArn = resource.getAttString('fargateProfileArn');
this.fargateProfileName = resource.ref;
// Fargate profiles must be created sequentially. If other profile(s) already
// exist on the same cluster, create a dependency to force sequential creation.
const clusterFargateProfiles = props.cluster._attachFargateProfile(this);
if (clusterFargateProfiles.length > 1) {
const previousProfile = clusterFargateProfiles[clusterFargateProfiles.length - 2];
resource.node.addDependency(previousProfile);
}
// map the fargate pod execution role to the relevant groups in rbac
// see https://github.com/aws/aws-cdk/issues/7981
props.cluster.awsAuth.addRoleMapping(this.podExecutionRole, {
username: 'system:node:{{SessionName}}',
groups: [
'system:bootstrappers',
'system:nodes',
'system:node-proxier',
],
});
}
}