@raindancers/raindancers-crew 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +1026 -3
- package/API.md +1459 -326
- package/README.md +58 -0
- package/docs/spec-ecs-crew-construct.md +200 -0
- package/lib/crew-backup-bucket.js +1 -1
- package/lib/crew-webhook-ingress.d.ts +104 -0
- package/lib/crew-webhook-ingress.js +111 -0
- package/lib/ecs-crew-host.d.ts +247 -0
- package/lib/ecs-crew-host.js +383 -0
- package/lib/fargate-crew-base.js +1 -1
- package/lib/fargate-crew.js +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +3 -1
- package/lib/remote-crew-instance.js +1 -1
- package/package.json +2 -2
- package/src/assets/ecs-host-bootstrap.sh +205 -0
- package/src/crew-webhook-ingress.ts +175 -0
- package/src/ecs-crew-host.ts +616 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as autoscaling from 'aws-cdk-lib/aws-autoscaling';
|
|
2
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
3
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
4
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
5
|
+
import { Construct } from 'constructs';
|
|
6
|
+
import { FargateCrew } from './fargate-crew';
|
|
7
|
+
import { FargateCrewBase } from './fargate-crew-base';
|
|
8
|
+
import { CrewArchitecture, ICrewBackupBucket } from './remote-crew-instance-props';
|
|
9
|
+
/**
|
|
10
|
+
* How a per-crew durable EBS volume is exposed to the host and its container.
|
|
11
|
+
*
|
|
12
|
+
* The device name the construct asks for (for example `/dev/sdf`) is NOT the
|
|
13
|
+
* kernel device name on Nitro/Graviton, where every EBS volume surfaces as an
|
|
14
|
+
* unpredictable `/dev/nvmeXn1`. The bootstrap therefore resolves each volume by
|
|
15
|
+
* a stable filesystem LABEL, never by the device path.
|
|
16
|
+
*/
|
|
17
|
+
export interface CrewDataVolume {
|
|
18
|
+
/** The crew this volume belongs to. */
|
|
19
|
+
readonly crew: string;
|
|
20
|
+
/** The block device name requested at attach time (a hint, not the kernel name). */
|
|
21
|
+
readonly deviceName: string;
|
|
22
|
+
/** The stable filesystem label the bootstrap resolves and mounts by. */
|
|
23
|
+
readonly label: string;
|
|
24
|
+
/** The host mount path the container bind-mounts for `~/.kiro/crew`. */
|
|
25
|
+
readonly mountPath: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Properties for {@link EcsCrewHost}.
|
|
29
|
+
*/
|
|
30
|
+
export interface EcsCrewHostProps {
|
|
31
|
+
/**
|
|
32
|
+
* VPC to run in. Passed in, never created here.
|
|
33
|
+
*
|
|
34
|
+
* The construct consumes a two-subnet host-NAT topology it does not build:
|
|
35
|
+
* one PUBLIC subnet (host ENI + Elastic IP + IGW route) and one PRIVATE
|
|
36
|
+
* subnet (task ENIs, `0.0.0.0/0` -> the host ENI, no IGW route). Select them
|
|
37
|
+
* with {@link hostSubnets} and {@link taskSubnets}.
|
|
38
|
+
*/
|
|
39
|
+
readonly vpc: ec2.IVpc;
|
|
40
|
+
/**
|
|
41
|
+
* ARN of an IAM permissions boundary applied to the host instance role.
|
|
42
|
+
*
|
|
43
|
+
* The host runs a prompt-injectable agent per crew, so its role MUST carry a
|
|
44
|
+
* boundary that caps blast radius. Required, not optional, matching
|
|
45
|
+
* {@link RemoteCrewInstanceProps.permissionsBoundaryArn}. Any valid managed-
|
|
46
|
+
* policy ARN is accepted here (this is the EC2/host boundary).
|
|
47
|
+
*
|
|
48
|
+
* The per-crew task/execution roles take {@link crewPermissionsBoundaryArn},
|
|
49
|
+
* which is validated separately against the `kirocrew-crew-boundary` pattern
|
|
50
|
+
* the crew roles require.
|
|
51
|
+
*/
|
|
52
|
+
readonly permissionsBoundaryArn: string;
|
|
53
|
+
/**
|
|
54
|
+
* ARN of the pre-created shared crew permissions boundary
|
|
55
|
+
* (`arn:aws:iam::<account>:policy/kirocrew-crew-boundary`), applied to every
|
|
56
|
+
* per-crew task and execution role.
|
|
57
|
+
*
|
|
58
|
+
* Separate from {@link permissionsBoundaryArn} because the crew roles enforce
|
|
59
|
+
* the `kirocrew-crew-boundary` policy name (a different boundary from the
|
|
60
|
+
* host's), and validating them together would force one ARN to satisfy two
|
|
61
|
+
* distinct patterns. Optional, mirroring {@link FargateCrew}'s declared
|
|
62
|
+
* degraded mode: omit it only when no crew-boundary creator exists yet.
|
|
63
|
+
*
|
|
64
|
+
* @default - no crew boundary (declared degraded mode; see FargateCrew)
|
|
65
|
+
*/
|
|
66
|
+
readonly crewPermissionsBoundaryArn?: string;
|
|
67
|
+
/**
|
|
68
|
+
* EC2 instance type for the single ECS-registered host.
|
|
69
|
+
*
|
|
70
|
+
* The type STAYS a settable prop: the 55minutes consumer passes
|
|
71
|
+
* `new ec2.InstanceType('m9g.xlarge')`. Never hardcoded to one family.
|
|
72
|
+
*
|
|
73
|
+
* @default - m7g.2xlarge (arm64) / m7i.2xlarge (x86_64), matching
|
|
74
|
+
* RemoteCrewInstance
|
|
75
|
+
*/
|
|
76
|
+
readonly instanceType?: ec2.InstanceType;
|
|
77
|
+
/**
|
|
78
|
+
* CPU architecture of the host and the crew container images. Must match
|
|
79
|
+
* {@link instanceType} when that is set.
|
|
80
|
+
*
|
|
81
|
+
* @default CrewArchitecture.ARM64
|
|
82
|
+
*/
|
|
83
|
+
readonly architecture?: CrewArchitecture;
|
|
84
|
+
/**
|
|
85
|
+
* Number of Kiro Crew instances to host, each one ECS task/service.
|
|
86
|
+
*
|
|
87
|
+
* DEFAULT 1 — identical to today's single-crew behaviour, so existing
|
|
88
|
+
* consumers gain nothing new. The 55minutes consumer passes 3. Validated
|
|
89
|
+
* 1..8: awsvpc gives each task its own ENI, and (crewCount + 1) ENIs (the
|
|
90
|
+
* host ENI plus one per task) must fit the instance type's ENI budget.
|
|
91
|
+
*
|
|
92
|
+
* @default 1
|
|
93
|
+
*/
|
|
94
|
+
readonly crewCount?: number;
|
|
95
|
+
/**
|
|
96
|
+
* Explicit crew names. Each must match the {@link FargateCrew} regex
|
|
97
|
+
* `^[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?$`; the log group, roles, and secret
|
|
98
|
+
* namespace are derived from it. When omitted, names are generated as
|
|
99
|
+
* `crew-1`..`crew-<crewCount>`. When set, the list length must equal
|
|
100
|
+
* {@link crewCount}.
|
|
101
|
+
*
|
|
102
|
+
* @default - crew-1 .. crew-<crewCount>
|
|
103
|
+
*/
|
|
104
|
+
readonly crews?: string[];
|
|
105
|
+
/**
|
|
106
|
+
* Subnet selection for the host ENI. This is the PUBLIC subnet (IGW-routed,
|
|
107
|
+
* carries the Elastic IP), because the host does the NAT for the tasks.
|
|
108
|
+
*
|
|
109
|
+
* @default - one public subnet in the VPC
|
|
110
|
+
*/
|
|
111
|
+
readonly hostSubnets?: ec2.SubnetSelection;
|
|
112
|
+
/**
|
|
113
|
+
* Subnet selection for the crew task ENIs. This is the PRIVATE subnet whose
|
|
114
|
+
* `0.0.0.0/0` route points at the host ENI (no IGW route). Tasks get no
|
|
115
|
+
* public IP.
|
|
116
|
+
*
|
|
117
|
+
* @default - the VPC's private-with-egress subnets
|
|
118
|
+
*/
|
|
119
|
+
readonly taskSubnets?: ec2.SubnetSelection;
|
|
120
|
+
/**
|
|
121
|
+
* gp3 root volume size in GiB for the host. Always encrypted.
|
|
122
|
+
*
|
|
123
|
+
* @default 60
|
|
124
|
+
*/
|
|
125
|
+
readonly rootVolumeSizeGb?: number;
|
|
126
|
+
/**
|
|
127
|
+
* Per-crew durable EBS data volume size in GiB. Always encrypted, always
|
|
128
|
+
* `deleteOnTermination: false` (a crew's `~/.kiro/crew` learnings must
|
|
129
|
+
* outlive an instance replacement, matching the CrewBackupBucket RETAIN
|
|
130
|
+
* intent).
|
|
131
|
+
*
|
|
132
|
+
* @default 20
|
|
133
|
+
*/
|
|
134
|
+
readonly crewDataVolumeSizeGb?: number;
|
|
135
|
+
/**
|
|
136
|
+
* Per-crew EBS volume type.
|
|
137
|
+
*
|
|
138
|
+
* @default ec2.EbsDeviceVolumeType.GP3
|
|
139
|
+
*/
|
|
140
|
+
readonly crewDataVolumeType?: ec2.EbsDeviceVolumeType;
|
|
141
|
+
/**
|
|
142
|
+
* SOFT memory reservation (MiB) per crew container. ECS uses it for
|
|
143
|
+
* placement; a crew may burst above it when the host has spare RAM, so idle
|
|
144
|
+
* crews cost little.
|
|
145
|
+
*
|
|
146
|
+
* @default 1024
|
|
147
|
+
*/
|
|
148
|
+
readonly crewMemoryReservationMiB?: number;
|
|
149
|
+
/**
|
|
150
|
+
* HARD memory cap (MiB) per crew container. A crew is OOM-killed at this
|
|
151
|
+
* ceiling, so no single crew can consume the whole host. Set the SUM of hard
|
|
152
|
+
* caps at or below (physical RAM minus host + ECS-agent headroom) for a hard
|
|
153
|
+
* cross-crew guarantee — see the host-OOM caution in the README.
|
|
154
|
+
*
|
|
155
|
+
* @default 2048
|
|
156
|
+
*/
|
|
157
|
+
readonly crewMemoryHardLimitMiB?: number;
|
|
158
|
+
/**
|
|
159
|
+
* Optional SOFT CPU shares per crew container (1024 = one vCPU). Omit to
|
|
160
|
+
* leave CPU unconstrained (crews share the host CPU fairly under contention).
|
|
161
|
+
*
|
|
162
|
+
* @default - unset (shared CPU)
|
|
163
|
+
*/
|
|
164
|
+
readonly crewCpuShares?: number;
|
|
165
|
+
/**
|
|
166
|
+
* ARN of the private ECR repository holding the crew image. Leave unset when
|
|
167
|
+
* the image is pulled from a public registry. When set, each per-crew
|
|
168
|
+
* execution role gets a pull grant scoped to this one repository.
|
|
169
|
+
*
|
|
170
|
+
* @default - public registry; no pull grant
|
|
171
|
+
*/
|
|
172
|
+
readonly ecrRepositoryArn?: string;
|
|
173
|
+
/**
|
|
174
|
+
* Container image reference for the crew task. When {@link ecrRepositoryArn}
|
|
175
|
+
* is set this is typically the repo URI with a tag; otherwise a public
|
|
176
|
+
* registry reference.
|
|
177
|
+
*
|
|
178
|
+
* @default 'public.ecr.aws/kirocrew/crew:latest'
|
|
179
|
+
*/
|
|
180
|
+
readonly crewImage?: string;
|
|
181
|
+
/**
|
|
182
|
+
* Days a crew's task logs are kept. One of the CloudWatch retention values
|
|
183
|
+
* (see {@link FargateCrew}).
|
|
184
|
+
*
|
|
185
|
+
* @default 30
|
|
186
|
+
*/
|
|
187
|
+
readonly logRetentionDays?: number;
|
|
188
|
+
/**
|
|
189
|
+
* An S3 backup bucket. When set, each per-crew TASK role is granted write so
|
|
190
|
+
* the running container pushes its own snapshots off-box.
|
|
191
|
+
*
|
|
192
|
+
* @default - no off-box backup
|
|
193
|
+
*/
|
|
194
|
+
readonly backupBucket?: ICrewBackupBucket;
|
|
195
|
+
/**
|
|
196
|
+
* Discovery tag value written as `kirocrew:ecs-host`. Must match
|
|
197
|
+
* `[a-zA-Z0-9-]{1,51}`. The cluster is named `kirocrew-crew-<stackTag>`.
|
|
198
|
+
*
|
|
199
|
+
* @default 'kirocrew'
|
|
200
|
+
*/
|
|
201
|
+
readonly stackTag?: string;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* One self-provisioned EC2 host running the ECS agent, hosting `crewCount`
|
|
205
|
+
* Kiro Crew instances as ECS-on-EC2 container tasks.
|
|
206
|
+
*
|
|
207
|
+
* The host registers to the {@link FargateCrewBase} cluster and does the NAT
|
|
208
|
+
* for the crew tasks itself, so the tasks stay fully private with no public
|
|
209
|
+
* IPs and no NAT Gateway, fck-nat, VPC endpoints, or ALB. Each task runs in
|
|
210
|
+
* awsvpc mode with its own ENI and private VPC IP; each crew keeps its durable
|
|
211
|
+
* `~/.kiro/crew` state on its own encrypted EBS volume that survives instance
|
|
212
|
+
* replacement.
|
|
213
|
+
*
|
|
214
|
+
* Isolation is container-level (shared kernel), accepted as sufficient:
|
|
215
|
+
* Graviton Nitro protects the box from other AWS tenants, containers cover
|
|
216
|
+
* crew-to-crew separation. See the host-OOM caution: hard per-task memory caps
|
|
217
|
+
* bound each crew's ceiling but a busy crew can still pressure siblings when
|
|
218
|
+
* the sum of actual usage exceeds physical RAM.
|
|
219
|
+
*
|
|
220
|
+
* `crewCount` defaults to 1, identical to the single-crew shape, so a plain
|
|
221
|
+
* instantiation with no new props gains no extra resources.
|
|
222
|
+
*/
|
|
223
|
+
export declare class EcsCrewHost extends Construct {
|
|
224
|
+
/** The shared ECS scaffolding (cluster + egress-only task SG). */
|
|
225
|
+
readonly base: FargateCrewBase;
|
|
226
|
+
/** The size-1 Auto Scaling Group holding the single ECS-registered EC2 host. */
|
|
227
|
+
readonly autoScalingGroup: autoscaling.AutoScalingGroup;
|
|
228
|
+
/** The capacity provider registering the host with the cluster. */
|
|
229
|
+
readonly capacityProvider: ecs.AsgCapacityProvider;
|
|
230
|
+
/** The host instance's IAM role (carries the permissions boundary). */
|
|
231
|
+
readonly role: iam.Role;
|
|
232
|
+
/** The host's SSM-only security group (no inbound). */
|
|
233
|
+
readonly hostSecurityGroup: ec2.SecurityGroup;
|
|
234
|
+
/** The per-crew scaffolding (roles + log group), one per crew. */
|
|
235
|
+
readonly crews: FargateCrew[];
|
|
236
|
+
/** The per-crew EC2 services. */
|
|
237
|
+
readonly services: ecs.Ec2Service[];
|
|
238
|
+
/** The per-crew durable data volumes (device/label/mount metadata). */
|
|
239
|
+
readonly dataVolumes: CrewDataVolume[];
|
|
240
|
+
/** The discovery tag value written as `kirocrew:ecs-host`. */
|
|
241
|
+
readonly stackTag: string;
|
|
242
|
+
/** The resolved crew names. */
|
|
243
|
+
readonly crewNames: string[];
|
|
244
|
+
constructor(scope: Construct, id: string, props: EcsCrewHostProps);
|
|
245
|
+
/** The region the host runs in (read from the stack env, never a prop). */
|
|
246
|
+
get region(): string;
|
|
247
|
+
}
|