diff --git a/.gitignore b/.gitignore index 9f5ce25e..5de21380 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ dist/ -cdk.out/ \ No newline at end of file +cdk.out/ +cdk.context.json \ No newline at end of file diff --git a/config/app.ts b/config/app.ts deleted file mode 100644 index 0e5100da..00000000 --- a/config/app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { App } from 'cdk8s'; - -import { ArgoSemaphore } from './charts/argo.semaphores'; - -const app = new App(); - -async function main(): Promise { - new ArgoSemaphore(app, 'semaphore', {}); - - app.synth(); -} - -main(); diff --git a/config/cdk.ts b/config/cdk.ts index eea762e4..53286519 100644 --- a/config/cdk.ts +++ b/config/cdk.ts @@ -5,7 +5,7 @@ import { LinzEksCluster } from './eks/cluster'; const app = new App(); async function main(): Promise { - new LinzEksCluster(app, 'Workflows', { env: { region: 'ap-southeast-2' } }); + new LinzEksCluster(app, 'Workflows', { env: { region: 'ap-southeast-2', account: process.env.CDK_DEFAULT_ACCOUNT } }); app.synth(); } diff --git a/config/eks/cluster.ts b/config/eks/cluster.ts index 0c3913e8..8c9c0251 100644 --- a/config/eks/cluster.ts +++ b/config/eks/cluster.ts @@ -1,10 +1,72 @@ -import { Stack, StackProps } from 'aws-cdk-lib'; +import { KubectlV27Layer } from '@aws-cdk/lambda-layer-kubectl-v27'; +import { Duration, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'; +import { InstanceType, IVpc, SubnetType, Vpc } from 'aws-cdk-lib/aws-ec2'; +import { Cluster, ClusterLoggingTypes, IpFamily, KubernetesVersion, NodegroupAmiType } from 'aws-cdk-lib/aws-eks'; +import { Role } from 'aws-cdk-lib/aws-iam'; +import { BlockPublicAccess, Bucket } from 'aws-cdk-lib/aws-s3'; import { Construct } from 'constructs'; interface EksClusterProps extends StackProps {} export class LinzEksCluster extends Stack { + /** Version of EKS to use, this must be aligned to the `kubectlLayer` */ + version = KubernetesVersion.V1_27; + /** Argo needs a temporary bucket to store objects */ + tempBucket: Bucket; + + vpc: IVpc; + + cluster: Cluster; + constructor(scope: Construct, id: string, props: EksClusterProps) { super(scope, id, props); + + this.tempBucket = new Bucket(this, 'Scratch', { + /** linz-workflows-scratch */ + bucketName: `linz-${id.toLowerCase()}-scratch`, + removalPolicy: RemovalPolicy.RETAIN, + blockPublicAccess: BlockPublicAccess.BLOCK_ALL, + lifecycleRules: [ + { + /** All artifacts are deleted after 90 days */ + expiration: Duration.days(90), + /** This bucket is not used for multipart uploads so clean them up quickly */ + abortIncompleteMultipartUploadAfter: Duration.days(3), + }, + ], + }); + + this.vpc = Vpc.fromLookup(this, 'Vpc', { tags: { BaseVPC: 'true' } }); + + this.cluster = new Cluster(this, `Eks${id}`, { + clusterName: id, + version: this.version, + vpc: this.vpc, + defaultCapacity: 0, + vpcSubnets: [{ subnetType: SubnetType.PRIVATE_WITH_EGRESS }], + /** This must align to Cluster version: {@link version} */ + kubectlLayer: new KubectlV27Layer(this, 'KubeCtlLayer'), + /** To prevent IP exhaustion when running huge workflows run using ipv6 */ + ipFamily: IpFamily.IP_V6, + clusterLogging: [ClusterLoggingTypes.API, ClusterLoggingTypes.CONTROLLER_MANAGER, ClusterLoggingTypes.SCHEDULER], + }); + + const nodeGroup = this.cluster.addNodegroupCapacity('ClusterDefault', { + /** + * c6i.large: ~$70/month, t3.small: ~$12/month. + * Compare instance types and costs at https://instances.vantage.sh/ + * Instances are requested in order listed. + * https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html#managed-node-group-capacity-types + **/ + instanceTypes: ['c6i.large', 'c6a.large'].map((f) => new InstanceType(f)), + minSize: 2, + amiType: NodegroupAmiType.BOTTLEROCKET_X86_64, + subnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS }, + }); + this.tempBucket.grantReadWrite(nodeGroup.role); + + // Grant the AWS Admin user ability to view the cluster + const accountAdminRole = Role.fromRoleName(this, 'AccountAdminRole', 'AccountAdminRole'); + this.cluster.awsAuth.addMastersRole(accountAdminRole); } } diff --git a/package-lock.json b/package-lock.json index 011827e3..cd000d8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,10 @@ "version": "0.0.1", "license": "MIT", "devDependencies": { + "@aws-cdk/lambda-layer-kubectl-v27": "^2.0.0", "@linzjs/style": "^5.0.0", - "aws-cdk": "^2.101.1", - "aws-cdk-lib": "^2.101.1", + "aws-cdk": "2.93.x", + "aws-cdk-lib": "2.93.x", "cdk8s": "^2.66.10", "cdk8s-cli": "^2.136.0", "cdk8s-plus-27": "^2.7.34", @@ -48,6 +49,16 @@ "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==", "dev": true }, + "node_modules/@aws-cdk/lambda-layer-kubectl-v27": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/lambda-layer-kubectl-v27/-/lambda-layer-kubectl-v27-2.0.0.tgz", + "integrity": "sha512-BBh4ScPHaD82e7Z3PYXqyLjqfk/3/PRDTJW3x2j4l5f6sHXU041TaXKcFAGBHb1m4aq2UK+fwkIq95mgs3c0dg==", + "dev": true, + "peerDependencies": { + "aws-cdk-lib": "^2.28.0", + "constructs": "^10.0.5" + } + }, "node_modules/@colors/colors": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", @@ -924,9 +935,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.101.1", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.101.1.tgz", - "integrity": "sha512-WS0pLVIhdK7VfNxmBwUhUCDlIvhI0OCd5XWGVAQEFpjnWUCfr8wyw9jnFEY4/qF5lev+uyN10vutde6i01aaHw==", + "version": "2.93.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.93.0.tgz", + "integrity": "sha512-C0o7rzlXbQ3othvQ9uZamRwr741MSX/9eZ74zNJvpkX5Eitx/XoQYwUHeD+cbb4lKHMi7m2SwJfx3yOEkpu9OQ==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -939,9 +950,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.101.1", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.101.1.tgz", - "integrity": "sha512-kKrJ0CcD82IyohjB3TRy34whf22GI6Y2bIrkBmui+fCb2t13+ToJb7zKBRmL6C090OsoiU/q+H6/WIZWOoYDvQ==", + "version": "2.93.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.93.0.tgz", + "integrity": "sha512-kKbcKkts272Ju5xjGKI3pXTOpiJxW4OQbDF8Vmw/NIkkuJLo8GlRCFfeOfoN/hilvlYQgENA67GCgSWccbvu7w==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -979,11 +990,13 @@ }, "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { "version": "1.0.2", + "dev": true, "inBundle": true, "license": "Apache-2.0" }, "node_modules/aws-cdk-lib/node_modules/ajv": { "version": "8.12.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -999,6 +1012,7 @@ }, "node_modules/aws-cdk-lib/node_modules/ansi-regex": { "version": "5.0.1", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1007,6 +1021,7 @@ }, "node_modules/aws-cdk-lib/node_modules/ansi-styles": { "version": "4.3.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1021,6 +1036,7 @@ }, "node_modules/aws-cdk-lib/node_modules/astral-regex": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1029,11 +1045,13 @@ }, "node_modules/aws-cdk-lib/node_modules/balanced-match": { "version": "1.0.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/brace-expansion": { "version": "1.1.11", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1043,6 +1061,7 @@ }, "node_modules/aws-cdk-lib/node_modules/case": { "version": "1.6.3", + "dev": true, "inBundle": true, "license": "(MIT OR GPL-3.0-or-later)", "engines": { @@ -1051,6 +1070,7 @@ }, "node_modules/aws-cdk-lib/node_modules/color-convert": { "version": "2.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1062,26 +1082,31 @@ }, "node_modules/aws-cdk-lib/node_modules/color-name": { "version": "1.1.4", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/concat-map": { "version": "0.0.1", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/emoji-regex": { "version": "8.0.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": { "version": "3.1.3", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { "version": "11.1.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1095,11 +1120,13 @@ }, "node_modules/aws-cdk-lib/node_modules/graceful-fs": { "version": "4.2.11", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/aws-cdk-lib/node_modules/ignore": { "version": "5.2.4", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1108,6 +1135,7 @@ }, "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1116,11 +1144,13 @@ }, "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": { "version": "1.0.0", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/jsonfile": { "version": "6.1.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1132,6 +1162,7 @@ }, "node_modules/aws-cdk-lib/node_modules/jsonschema": { "version": "1.4.1", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1140,11 +1171,13 @@ }, "node_modules/aws-cdk-lib/node_modules/lodash.truncate": { "version": "4.4.2", + "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/lru-cache": { "version": "6.0.0", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -1156,6 +1189,7 @@ }, "node_modules/aws-cdk-lib/node_modules/minimatch": { "version": "3.1.2", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -1167,6 +1201,7 @@ }, "node_modules/aws-cdk-lib/node_modules/punycode": { "version": "2.3.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1175,6 +1210,7 @@ }, "node_modules/aws-cdk-lib/node_modules/require-from-string": { "version": "2.0.2", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1183,6 +1219,7 @@ }, "node_modules/aws-cdk-lib/node_modules/semver": { "version": "7.5.4", + "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -1197,6 +1234,7 @@ }, "node_modules/aws-cdk-lib/node_modules/slice-ansi": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1213,6 +1251,7 @@ }, "node_modules/aws-cdk-lib/node_modules/string-width": { "version": "4.2.3", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1226,6 +1265,7 @@ }, "node_modules/aws-cdk-lib/node_modules/strip-ansi": { "version": "6.0.1", + "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -1237,6 +1277,7 @@ }, "node_modules/aws-cdk-lib/node_modules/table": { "version": "6.8.1", + "dev": true, "inBundle": true, "license": "BSD-3-Clause", "dependencies": { @@ -1252,6 +1293,7 @@ }, "node_modules/aws-cdk-lib/node_modules/universalify": { "version": "2.0.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1260,6 +1302,7 @@ }, "node_modules/aws-cdk-lib/node_modules/uri-js": { "version": "4.4.1", + "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -1268,11 +1311,13 @@ }, "node_modules/aws-cdk-lib/node_modules/yallist": { "version": "4.0.0", + "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/aws-cdk-lib/node_modules/yaml": { "version": "1.10.2", + "dev": true, "inBundle": true, "license": "ISC", "engines": { diff --git a/package.json b/package.json index fe65dc9c..e059ec90 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,10 @@ "format": "npx prettier . -w" }, "devDependencies": { + "@aws-cdk/lambda-layer-kubectl-v27": "^2.0.0", "@linzjs/style": "^5.0.0", - "aws-cdk": "^2.101.1", - "aws-cdk-lib": "^2.101.1", + "aws-cdk": "2.93.x", + "aws-cdk-lib": "2.93.x", "cdk8s": "^2.66.10", "cdk8s-cli": "^2.136.0", "cdk8s-plus-27": "^2.7.34",