@ariestools/cli 0.1.16 → 0.1.18
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/README.md +51 -11
- package/dist/bin/aries.mjs +95560 -254131
- package/dist/bin/daemons/chain-server.mjs +9862 -12
- package/dist/bin/daemons/dapp-server.mjs +55 -56
- package/dist/bin/daemons/datalake-dev.mjs +10967 -4724
- package/dist/node/datalake.mjs +7 -5
- package/dist/terraform/cluster-aws/cluster.tf +61 -0
- package/dist/terraform/cluster-aws/encryption.tofu.example +37 -0
- package/dist/terraform/cluster-aws/iam.tf +81 -0
- package/dist/terraform/cluster-aws/irsa_ebs_csi.tf +37 -0
- package/dist/terraform/cluster-aws/kubeconfig.tf +49 -0
- package/dist/terraform/cluster-aws/network.tf +108 -0
- package/dist/terraform/cluster-aws/nodegroup.tf +42 -0
- package/dist/terraform/cluster-aws/outputs.tf +80 -0
- package/dist/terraform/cluster-aws/providers.tf +7 -0
- package/dist/terraform/cluster-aws/terraform.tfvars.example +21 -0
- package/dist/terraform/cluster-aws/variables.tf +120 -0
- package/dist/terraform/cluster-aws/versions.tf +18 -0
- package/dist/terraform/cluster-azure/cluster.tf +83 -0
- package/dist/terraform/cluster-azure/encryption.tofu.example +37 -0
- package/dist/terraform/cluster-azure/identity.tf +9 -0
- package/dist/terraform/cluster-azure/kubeconfig.tf +18 -0
- package/dist/terraform/cluster-azure/network.tf +23 -0
- package/dist/terraform/cluster-azure/outputs.tf +69 -0
- package/dist/terraform/cluster-azure/providers.tf +16 -0
- package/dist/terraform/cluster-azure/terraform.tfvars.example +24 -0
- package/dist/terraform/cluster-azure/variables.tf +126 -0
- package/dist/terraform/cluster-azure/versions.tf +14 -0
- package/dist/terraform/cluster-gcp/cluster.tf +71 -0
- package/dist/terraform/cluster-gcp/encryption.tofu.example +35 -0
- package/dist/terraform/cluster-gcp/kubeconfig.tf +47 -0
- package/dist/terraform/cluster-gcp/network.tf +47 -0
- package/dist/terraform/cluster-gcp/outputs.tf +70 -0
- package/dist/terraform/cluster-gcp/providers.tf +14 -0
- package/dist/terraform/cluster-gcp/terraform.tfvars.example +17 -0
- package/dist/terraform/cluster-gcp/variables.tf +86 -0
- package/dist/terraform/cluster-gcp/versions.tf +14 -0
- package/dist/terraform/serverless-aws/alb.tf +127 -0
- package/dist/terraform/serverless-aws/database.tf +70 -0
- package/dist/terraform/serverless-aws/dns.tf +80 -0
- package/dist/terraform/serverless-aws/ecr.tf +63 -0
- package/dist/terraform/serverless-aws/ecs.tf +199 -0
- package/dist/terraform/serverless-aws/encryption.tofu.example +38 -0
- package/dist/terraform/serverless-aws/iam.tf +68 -0
- package/dist/terraform/serverless-aws/network.tf +190 -0
- package/dist/terraform/serverless-aws/outputs.tf +64 -0
- package/dist/terraform/serverless-aws/providers.tf +19 -0
- package/dist/terraform/serverless-aws/storage.tf +51 -0
- package/dist/terraform/serverless-aws/terraform.tfvars.example +19 -0
- package/dist/terraform/serverless-aws/variables.tf +151 -0
- package/dist/terraform/serverless-aws/versions.tf +14 -0
- package/package.json +23 -20
package/dist/node/datalake.mjs
CHANGED
|
@@ -368,10 +368,12 @@ function clearDefaultDatalake() {
|
|
|
368
368
|
const filePath = getDefaultDatalakePath();
|
|
369
369
|
if (existsSync(filePath)) unlinkSync(filePath);
|
|
370
370
|
}
|
|
371
|
-
function
|
|
371
|
+
function extractRequestBase(urlWithPossiblePath) {
|
|
372
372
|
try {
|
|
373
373
|
const parsed = new URL(urlWithPossiblePath);
|
|
374
|
-
|
|
374
|
+
const markerIndex = parsed.pathname.indexOf(`/v1/datalakes`);
|
|
375
|
+
const prefix = markerIndex === -1 ? parsed.pathname.replace(/\/$/, "") : parsed.pathname.slice(0, markerIndex);
|
|
376
|
+
return `${parsed.protocol}//${parsed.host}${prefix}`;
|
|
375
377
|
} catch {
|
|
376
378
|
return urlWithPossiblePath.replace(/\/$/, "");
|
|
377
379
|
}
|
|
@@ -380,9 +382,9 @@ var RestPayloadsClient = class {
|
|
|
380
382
|
authToken;
|
|
381
383
|
datalakeId;
|
|
382
384
|
fetchImpl;
|
|
383
|
-
|
|
385
|
+
requestBase;
|
|
384
386
|
constructor(options) {
|
|
385
|
-
this.
|
|
387
|
+
this.requestBase = extractRequestBase(options.baseUrl);
|
|
386
388
|
this.datalakeId = options.datalakeId;
|
|
387
389
|
this.authToken = options.authToken;
|
|
388
390
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
@@ -451,7 +453,7 @@ var RestPayloadsClient = class {
|
|
|
451
453
|
headers["content-type"] = "application/json";
|
|
452
454
|
init.body = JSON.stringify(options.body);
|
|
453
455
|
}
|
|
454
|
-
const response = await this.fetchImpl(`${this.
|
|
456
|
+
const response = await this.fetchImpl(`${this.requestBase}${path4}`, init);
|
|
455
457
|
if (response.status === 204) return {
|
|
456
458
|
data: void 0,
|
|
457
459
|
headers: response.headers
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
resource "aws_security_group" "cluster" {
|
|
2
|
+
name = "${local.name_prefix}-cluster"
|
|
3
|
+
description = "EKS cluster control-plane SG"
|
|
4
|
+
vpc_id = aws_vpc.main.id
|
|
5
|
+
|
|
6
|
+
egress {
|
|
7
|
+
description = "All egress"
|
|
8
|
+
from_port = 0
|
|
9
|
+
to_port = 0
|
|
10
|
+
protocol = "-1"
|
|
11
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
tags = { Name = "${local.name_prefix}-cluster-sg" }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
resource "aws_eks_cluster" "main" {
|
|
18
|
+
name = local.cluster_name
|
|
19
|
+
version = var.k8s_version
|
|
20
|
+
role_arn = aws_iam_role.cluster.arn
|
|
21
|
+
|
|
22
|
+
vpc_config {
|
|
23
|
+
subnet_ids = concat(
|
|
24
|
+
[for s in aws_subnet.public : s.id],
|
|
25
|
+
[for s in aws_subnet.private : s.id],
|
|
26
|
+
)
|
|
27
|
+
endpoint_public_access = var.endpoint_public_access
|
|
28
|
+
endpoint_private_access = true
|
|
29
|
+
public_access_cidrs = var.endpoint_public_access_cidrs
|
|
30
|
+
security_group_ids = [aws_security_group.cluster.id]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Plug control-plane logs into CloudWatch so the SRE team isn't blind on day 1.
|
|
34
|
+
enabled_cluster_log_types = [
|
|
35
|
+
"api",
|
|
36
|
+
"audit",
|
|
37
|
+
"authenticator",
|
|
38
|
+
"controllerManager",
|
|
39
|
+
"scheduler",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# EKS uses the cluster role + the worker node groups' instance profiles
|
|
43
|
+
# for default permissions. Additional access entries (e.g. promoting the
|
|
44
|
+
# human running `aries cluster aws up` to cluster admin) are wired below
|
|
45
|
+
# via aws_eks_access_entry / access_policy_association.
|
|
46
|
+
|
|
47
|
+
access_config {
|
|
48
|
+
authentication_mode = "API"
|
|
49
|
+
bootstrap_cluster_creator_admin_permissions = true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
depends_on = [
|
|
53
|
+
aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy,
|
|
54
|
+
aws_iam_role_policy_attachment.cluster_AmazonEKSVPCResourceController,
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
resource "aws_cloudwatch_log_group" "cluster" {
|
|
59
|
+
name = "/aws/eks/${local.cluster_name}/cluster"
|
|
60
|
+
retention_in_days = 30
|
|
61
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# OpenTofu state encryption — opt-in.
|
|
2
|
+
#
|
|
3
|
+
# Encrypts `terraform.tfstate` and any saved plan files at rest using
|
|
4
|
+
# AES-GCM with a key derived from `var.tfstate_passphrase` via PBKDF2.
|
|
5
|
+
#
|
|
6
|
+
# To enable:
|
|
7
|
+
# 1. cp encryption.tofu.example encryption.tofu (in the working dir)
|
|
8
|
+
# 2. export TF_VAR_tfstate_passphrase='at-least-16-characters'
|
|
9
|
+
# 3. tofu init -reconfigure
|
|
10
|
+
#
|
|
11
|
+
# Notes:
|
|
12
|
+
# - This file uses the `.tofu` extension so Terraform does NOT load it.
|
|
13
|
+
# Only OpenTofu engages encryption. Terraform users skip this block.
|
|
14
|
+
# - If you lose the passphrase, the state is unrecoverable — keep it in
|
|
15
|
+
# a password manager / Secrets Manager / etc.
|
|
16
|
+
# - State encryption matters more here than in compute-aws because the
|
|
17
|
+
# EKS state file contains the cluster CA bundle and OIDC issuer URL.
|
|
18
|
+
|
|
19
|
+
terraform {
|
|
20
|
+
encryption {
|
|
21
|
+
key_provider "pbkdf2" "default" {
|
|
22
|
+
passphrase = var.tfstate_passphrase
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
method "aes_gcm" "default" {
|
|
26
|
+
keys = key_provider.pbkdf2.default
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
state {
|
|
30
|
+
method = method.aes_gcm.default
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
plan {
|
|
34
|
+
method = method.aes_gcm.default
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# --- EKS cluster role -------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
data "aws_iam_policy_document" "cluster_assume" {
|
|
4
|
+
statement {
|
|
5
|
+
actions = ["sts:AssumeRole"]
|
|
6
|
+
principals {
|
|
7
|
+
type = "Service"
|
|
8
|
+
identifiers = ["eks.amazonaws.com"]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
resource "aws_iam_role" "cluster" {
|
|
14
|
+
name = "${local.name_prefix}-cluster"
|
|
15
|
+
assume_role_policy = data.aws_iam_policy_document.cluster_assume.json
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSClusterPolicy" {
|
|
19
|
+
role = aws_iam_role.cluster.name
|
|
20
|
+
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSVPCResourceController" {
|
|
24
|
+
role = aws_iam_role.cluster.name
|
|
25
|
+
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# --- Managed node group role ------------------------------------------------
|
|
29
|
+
|
|
30
|
+
data "aws_iam_policy_document" "node_assume" {
|
|
31
|
+
statement {
|
|
32
|
+
actions = ["sts:AssumeRole"]
|
|
33
|
+
principals {
|
|
34
|
+
type = "Service"
|
|
35
|
+
identifiers = ["ec2.amazonaws.com"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
resource "aws_iam_role" "node" {
|
|
41
|
+
name = "${local.name_prefix}-node"
|
|
42
|
+
assume_role_policy = data.aws_iam_policy_document.node_assume.json
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
resource "aws_iam_role_policy_attachment" "node_AmazonEKSWorkerNodePolicy" {
|
|
46
|
+
role = aws_iam_role.node.name
|
|
47
|
+
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
resource "aws_iam_role_policy_attachment" "node_AmazonEKS_CNI_Policy" {
|
|
51
|
+
role = aws_iam_role.node.name
|
|
52
|
+
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
resource "aws_iam_role_policy_attachment" "node_AmazonEC2ContainerRegistryReadOnly" {
|
|
56
|
+
role = aws_iam_role.node.name
|
|
57
|
+
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
resource "aws_iam_role_policy_attachment" "node_AmazonSSMManagedInstanceCore" {
|
|
61
|
+
role = aws_iam_role.node.name
|
|
62
|
+
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# --- IRSA (IAM Roles for Service Accounts) ----------------------------------
|
|
66
|
+
#
|
|
67
|
+
# EKS exposes an OIDC issuer URL; pairing it with an IAM OIDC provider lets
|
|
68
|
+
# pods assume IAM roles via a service-account annotation. The service plane
|
|
69
|
+
# (service-datalake) uses this to grant the data-plane pod S3 access on the
|
|
70
|
+
# archive-tier bucket without storing AWS credentials anywhere.
|
|
71
|
+
|
|
72
|
+
data "tls_certificate" "cluster_oidc" {
|
|
73
|
+
url = aws_eks_cluster.main.identity[0].oidc[0].issuer
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
resource "aws_iam_openid_connect_provider" "cluster" {
|
|
77
|
+
url = aws_eks_cluster.main.identity[0].oidc[0].issuer
|
|
78
|
+
client_id_list = ["sts.amazonaws.com"]
|
|
79
|
+
thumbprint_list = [data.tls_certificate.cluster_oidc.certificates[0].sha1_fingerprint]
|
|
80
|
+
tags = { Name = "${local.name_prefix}-oidc" }
|
|
81
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# IRSA role for the EBS CSI driver. The addon needs to attach EBS volumes
|
|
2
|
+
# to nodes (CreateVolume, AttachVolume, etc.) — those permissions belong
|
|
3
|
+
# to a per-cluster role tied to the cluster's OIDC issuer.
|
|
4
|
+
#
|
|
5
|
+
# Created here (not in service-datalake) because EBS CSI is cluster-level
|
|
6
|
+
# infra: PVCs of any kind require it. `aries cluster addons install`
|
|
7
|
+
# passes the role ARN below into `aws eks create-addon`.
|
|
8
|
+
|
|
9
|
+
data "aws_iam_policy_document" "ebs_csi_assume" {
|
|
10
|
+
statement {
|
|
11
|
+
actions = ["sts:AssumeRoleWithWebIdentity"]
|
|
12
|
+
principals {
|
|
13
|
+
type = "Federated"
|
|
14
|
+
identifiers = [aws_iam_openid_connect_provider.cluster.arn]
|
|
15
|
+
}
|
|
16
|
+
condition {
|
|
17
|
+
test = "StringEquals"
|
|
18
|
+
variable = "${replace(aws_iam_openid_connect_provider.cluster.url, "https://", "")}:sub"
|
|
19
|
+
values = ["system:serviceaccount:kube-system:ebs-csi-controller-sa"]
|
|
20
|
+
}
|
|
21
|
+
condition {
|
|
22
|
+
test = "StringEquals"
|
|
23
|
+
variable = "${replace(aws_iam_openid_connect_provider.cluster.url, "https://", "")}:aud"
|
|
24
|
+
values = ["sts.amazonaws.com"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
resource "aws_iam_role" "ebs_csi" {
|
|
30
|
+
name = "${local.name_prefix}-ebs-csi"
|
|
31
|
+
assume_role_policy = data.aws_iam_policy_document.ebs_csi_assume.json
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
resource "aws_iam_role_policy_attachment" "ebs_csi" {
|
|
35
|
+
role = aws_iam_role.ebs_csi.name
|
|
36
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy"
|
|
37
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Render a standard EKS kubeconfig into the working dir. The `exec` block
|
|
2
|
+
# delegates auth to the user's local `aws` CLI (`aws eks get-token`), so
|
|
3
|
+
# the kubeconfig itself carries no long-lived secrets — perfect for
|
|
4
|
+
# checking in to ~/.aries/cluster/<name>/ alongside cluster.yaml.
|
|
5
|
+
|
|
6
|
+
locals {
|
|
7
|
+
kubeconfig_yaml = yamlencode({
|
|
8
|
+
apiVersion = "v1"
|
|
9
|
+
kind = "Config"
|
|
10
|
+
current-context = "aries-${local.cluster_name}"
|
|
11
|
+
clusters = [{
|
|
12
|
+
name = aws_eks_cluster.main.arn
|
|
13
|
+
cluster = {
|
|
14
|
+
server = aws_eks_cluster.main.endpoint
|
|
15
|
+
"certificate-authority-data" = aws_eks_cluster.main.certificate_authority[0].data
|
|
16
|
+
}
|
|
17
|
+
}]
|
|
18
|
+
contexts = [{
|
|
19
|
+
name = "aries-${local.cluster_name}"
|
|
20
|
+
context = {
|
|
21
|
+
cluster = aws_eks_cluster.main.arn
|
|
22
|
+
user = aws_eks_cluster.main.arn
|
|
23
|
+
}
|
|
24
|
+
}]
|
|
25
|
+
users = [{
|
|
26
|
+
name = aws_eks_cluster.main.arn
|
|
27
|
+
user = {
|
|
28
|
+
exec = {
|
|
29
|
+
apiVersion = "client.authentication.k8s.io/v1beta1"
|
|
30
|
+
command = "aws"
|
|
31
|
+
args = [
|
|
32
|
+
"--region", var.region,
|
|
33
|
+
"--profile", var.aws_profile,
|
|
34
|
+
"eks", "get-token",
|
|
35
|
+
"--cluster-name", local.cluster_name,
|
|
36
|
+
"--output", "json",
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}]
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
resource "local_sensitive_file" "kubeconfig" {
|
|
45
|
+
filename = "${path.cwd}/kubeconfig"
|
|
46
|
+
content = local.kubeconfig_yaml
|
|
47
|
+
file_permission = "0600"
|
|
48
|
+
directory_permission = "0700"
|
|
49
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
data "aws_availability_zones" "available" {
|
|
2
|
+
state = "available"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
locals {
|
|
6
|
+
azs = slice(data.aws_availability_zones.available.names, 0, var.availability_zone_count)
|
|
7
|
+
|
|
8
|
+
public_subnet_cidrs = [for i, _ in local.azs : cidrsubnet(var.vpc_cidr, 8, i)]
|
|
9
|
+
private_subnet_cidrs = [for i, _ in local.azs : cidrsubnet(var.vpc_cidr, 8, i + 16)]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
resource "aws_vpc" "main" {
|
|
13
|
+
cidr_block = var.vpc_cidr
|
|
14
|
+
enable_dns_support = true
|
|
15
|
+
enable_dns_hostnames = true
|
|
16
|
+
|
|
17
|
+
tags = { Name = "${local.name_prefix}-vpc" }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
resource "aws_internet_gateway" "main" {
|
|
21
|
+
vpc_id = aws_vpc.main.id
|
|
22
|
+
tags = { Name = "${local.name_prefix}-igw" }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# Public subnets host the NAT gateway and external LBs (when the service
|
|
26
|
+
# plane installs ingress controllers later). EKS requires the
|
|
27
|
+
# `kubernetes.io/role/elb` tag for AWS Load Balancer Controller to pick
|
|
28
|
+
# the subnet for public ALBs/NLBs.
|
|
29
|
+
resource "aws_subnet" "public" {
|
|
30
|
+
for_each = { for i, az in local.azs : az => i }
|
|
31
|
+
|
|
32
|
+
vpc_id = aws_vpc.main.id
|
|
33
|
+
availability_zone = each.key
|
|
34
|
+
cidr_block = local.public_subnet_cidrs[each.value]
|
|
35
|
+
map_public_ip_on_launch = true
|
|
36
|
+
|
|
37
|
+
tags = {
|
|
38
|
+
Name = "${local.name_prefix}-public-${each.key}"
|
|
39
|
+
Tier = "public"
|
|
40
|
+
"kubernetes.io/role/elb" = "1"
|
|
41
|
+
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Private subnets host the EKS managed node group + internal LBs. The
|
|
46
|
+
# `kubernetes.io/role/internal-elb` tag lets the LB controller place
|
|
47
|
+
# internal NLBs/ALBs here.
|
|
48
|
+
resource "aws_subnet" "private" {
|
|
49
|
+
for_each = { for i, az in local.azs : az => i }
|
|
50
|
+
|
|
51
|
+
vpc_id = aws_vpc.main.id
|
|
52
|
+
availability_zone = each.key
|
|
53
|
+
cidr_block = local.private_subnet_cidrs[each.value]
|
|
54
|
+
|
|
55
|
+
tags = {
|
|
56
|
+
Name = "${local.name_prefix}-private-${each.key}"
|
|
57
|
+
Tier = "private"
|
|
58
|
+
"kubernetes.io/role/internal-elb" = "1"
|
|
59
|
+
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
resource "aws_eip" "nat" {
|
|
64
|
+
domain = "vpc"
|
|
65
|
+
tags = { Name = "${local.name_prefix}-nat" }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
resource "aws_nat_gateway" "main" {
|
|
69
|
+
allocation_id = aws_eip.nat.id
|
|
70
|
+
subnet_id = aws_subnet.public[local.azs[0]].id
|
|
71
|
+
|
|
72
|
+
tags = { Name = "${local.name_prefix}-nat" }
|
|
73
|
+
depends_on = [aws_internet_gateway.main]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
resource "aws_route_table" "public" {
|
|
77
|
+
vpc_id = aws_vpc.main.id
|
|
78
|
+
|
|
79
|
+
route {
|
|
80
|
+
cidr_block = "0.0.0.0/0"
|
|
81
|
+
gateway_id = aws_internet_gateway.main.id
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
tags = { Name = "${local.name_prefix}-public-rt" }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
resource "aws_route_table" "private" {
|
|
88
|
+
vpc_id = aws_vpc.main.id
|
|
89
|
+
|
|
90
|
+
route {
|
|
91
|
+
cidr_block = "0.0.0.0/0"
|
|
92
|
+
nat_gateway_id = aws_nat_gateway.main.id
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
tags = { Name = "${local.name_prefix}-private-rt" }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
resource "aws_route_table_association" "public" {
|
|
99
|
+
for_each = aws_subnet.public
|
|
100
|
+
subnet_id = each.value.id
|
|
101
|
+
route_table_id = aws_route_table.public.id
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
resource "aws_route_table_association" "private" {
|
|
105
|
+
for_each = aws_subnet.private
|
|
106
|
+
subnet_id = each.value.id
|
|
107
|
+
route_table_id = aws_route_table.private.id
|
|
108
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
resource "aws_eks_node_group" "default" {
|
|
2
|
+
cluster_name = aws_eks_cluster.main.name
|
|
3
|
+
node_group_name = "${local.cluster_name}-default"
|
|
4
|
+
node_role_arn = aws_iam_role.node.arn
|
|
5
|
+
subnet_ids = [for s in aws_subnet.private : s.id]
|
|
6
|
+
|
|
7
|
+
instance_types = var.node_instance_types
|
|
8
|
+
capacity_type = var.node_capacity_type
|
|
9
|
+
disk_size = var.node_disk_size_gb
|
|
10
|
+
|
|
11
|
+
scaling_config {
|
|
12
|
+
desired_size = var.node_desired_size
|
|
13
|
+
min_size = var.node_min_size
|
|
14
|
+
max_size = var.node_max_size
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
update_config {
|
|
18
|
+
max_unavailable_percentage = 33
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# Default labels make it easy for Helm charts / NetworkPolicies to pin
|
|
22
|
+
# workloads to the shared pool. Phase 2b adds an `aries-tier=large`
|
|
23
|
+
# taint + dedicated node group for large-tier datalakes.
|
|
24
|
+
labels = {
|
|
25
|
+
"aries.xylabs.com/pool" = "shared"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
tags = {
|
|
29
|
+
Name = "${local.cluster_name}-default"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
depends_on = [
|
|
33
|
+
aws_iam_role_policy_attachment.node_AmazonEKSWorkerNodePolicy,
|
|
34
|
+
aws_iam_role_policy_attachment.node_AmazonEKS_CNI_Policy,
|
|
35
|
+
aws_iam_role_policy_attachment.node_AmazonEC2ContainerRegistryReadOnly,
|
|
36
|
+
aws_iam_role_policy_attachment.node_AmazonSSMManagedInstanceCore,
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
lifecycle {
|
|
40
|
+
ignore_changes = [scaling_config[0].desired_size]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
output "cluster_name" {
|
|
2
|
+
description = "EKS cluster name."
|
|
3
|
+
value = aws_eks_cluster.main.name
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
output "cluster_arn" {
|
|
7
|
+
description = "EKS cluster ARN."
|
|
8
|
+
value = aws_eks_cluster.main.arn
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
output "cluster_endpoint" {
|
|
12
|
+
description = "EKS API server endpoint."
|
|
13
|
+
value = aws_eks_cluster.main.endpoint
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
output "cluster_certificate_authority_data" {
|
|
17
|
+
description = "Base64-encoded cluster CA cert (for clients that don't use the rendered kubeconfig)."
|
|
18
|
+
value = aws_eks_cluster.main.certificate_authority[0].data
|
|
19
|
+
sensitive = true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
output "oidc_provider_arn" {
|
|
23
|
+
description = "IAM OIDC provider ARN; bind workload IAM roles to this via IRSA."
|
|
24
|
+
value = aws_iam_openid_connect_provider.cluster.arn
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
output "oidc_provider_url" {
|
|
28
|
+
description = "OIDC issuer URL (without the leading `https://`) for IRSA trust policies."
|
|
29
|
+
value = replace(aws_eks_cluster.main.identity[0].oidc[0].issuer, "https://", "")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
output "ebs_csi_role_arn" {
|
|
33
|
+
description = "IRSA role ARN for the EBS CSI driver addon. Pass to `aws eks create-addon --service-account-role-arn` so PVCs can attach EBS volumes."
|
|
34
|
+
value = aws_iam_role.ebs_csi.arn
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
output "vpc_id" {
|
|
38
|
+
description = "Dedicated VPC the cluster runs in."
|
|
39
|
+
value = aws_vpc.main.id
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
output "private_subnet_ids" {
|
|
43
|
+
description = "Subnets the managed node group runs in."
|
|
44
|
+
value = [for s in aws_subnet.private : s.id]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
output "public_subnet_ids" {
|
|
48
|
+
description = "Public subnets (host NAT and external LBs)."
|
|
49
|
+
value = [for s in aws_subnet.public : s.id]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
output "node_security_group_id" {
|
|
53
|
+
description = "Primary security group EKS attached to worker nodes."
|
|
54
|
+
value = aws_eks_cluster.main.vpc_config[0].cluster_security_group_id
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
output "kubeconfig_path" {
|
|
58
|
+
description = "Path to the rendered kubeconfig (relative to the working dir)."
|
|
59
|
+
value = local_sensitive_file.kubeconfig.filename
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
output "region" {
|
|
63
|
+
description = "AWS region the cluster lives in."
|
|
64
|
+
value = var.region
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# The Tier-3 service plane reads this to construct its `ServiceTarget(kubernetes)`.
|
|
68
|
+
output "service_target" {
|
|
69
|
+
description = "Tier-2 → Tier-3 hand-off shape. The CLI projects this into ~/.aries/cluster/<name>/cluster.yaml."
|
|
70
|
+
value = {
|
|
71
|
+
kind = "kubernetes"
|
|
72
|
+
cloud = "aws"
|
|
73
|
+
cluster_name = aws_eks_cluster.main.name
|
|
74
|
+
region = var.region
|
|
75
|
+
namespace = "aries-datalake"
|
|
76
|
+
ingress_class = "nginx"
|
|
77
|
+
storage_class = "gp3"
|
|
78
|
+
kubeconfig = local_sensitive_file.kubeconfig.filename
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
region = "us-west-2"
|
|
2
|
+
aws_profile = "xylabs-datalake"
|
|
3
|
+
environment = "staging"
|
|
4
|
+
project = "aries-datalake"
|
|
5
|
+
|
|
6
|
+
# cluster_name defaults to `${project}-${environment}` when empty.
|
|
7
|
+
# cluster_name = "aries-datalake-staging"
|
|
8
|
+
|
|
9
|
+
# k8s_version = "1.31"
|
|
10
|
+
|
|
11
|
+
# vpc_cidr = "10.43.0.0/16" # must not overlap compute-aws (10.42.0.0/16)
|
|
12
|
+
|
|
13
|
+
# node_instance_types = ["t3.medium"]
|
|
14
|
+
# node_desired_size = 2
|
|
15
|
+
# node_min_size = 1
|
|
16
|
+
# node_max_size = 4
|
|
17
|
+
# node_capacity_type = "ON_DEMAND" # or "SPOT" for ~70% cheaper non-prod
|
|
18
|
+
# node_disk_size_gb = 50
|
|
19
|
+
|
|
20
|
+
# endpoint_public_access = true
|
|
21
|
+
# endpoint_public_access_cidrs = ["203.0.113.4/32"] # tighten to your office IP for prod
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
variable "region" {
|
|
2
|
+
type = string
|
|
3
|
+
description = "AWS region to deploy the EKS cluster into."
|
|
4
|
+
default = "us-west-2"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
variable "aws_profile" {
|
|
8
|
+
type = string
|
|
9
|
+
description = "Local AWS CLI profile the IaC engine should use. Must already be configured via `aws configure` or `aws sso login`."
|
|
10
|
+
default = "xylabs-datalake"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
variable "environment" {
|
|
14
|
+
type = string
|
|
15
|
+
description = "Environment name (staging, prod, etc.). Goes into resource tags + names."
|
|
16
|
+
default = "staging"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
variable "project" {
|
|
20
|
+
type = string
|
|
21
|
+
description = "Project name; goes into resource tags."
|
|
22
|
+
default = "aries-datalake"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
variable "cluster_name" {
|
|
26
|
+
type = string
|
|
27
|
+
description = "EKS cluster name. Defaults to `${var.project}-${var.environment}`."
|
|
28
|
+
default = ""
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
variable "k8s_version" {
|
|
32
|
+
type = string
|
|
33
|
+
description = "Kubernetes version for the EKS control plane."
|
|
34
|
+
default = "1.31"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
variable "vpc_cidr" {
|
|
38
|
+
type = string
|
|
39
|
+
description = "CIDR block for the dedicated VPC. Must not overlap any existing VPC you intend to peer with — and must not overlap the compute-aws VPC if both stacks live in the same account."
|
|
40
|
+
default = "10.43.0.0/16"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
variable "availability_zone_count" {
|
|
44
|
+
type = number
|
|
45
|
+
description = "Number of AZs to span (>= 2 required by EKS)."
|
|
46
|
+
default = 2
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
variable "node_instance_types" {
|
|
50
|
+
type = list(string)
|
|
51
|
+
description = "EC2 instance types for the managed node group. The first type is preferred; subsequent types are fallbacks when capacity is scarce."
|
|
52
|
+
default = ["t3.medium"]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
variable "node_desired_size" {
|
|
56
|
+
type = number
|
|
57
|
+
description = "Desired number of worker nodes."
|
|
58
|
+
default = 2
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
variable "node_min_size" {
|
|
62
|
+
type = number
|
|
63
|
+
description = "Minimum number of worker nodes."
|
|
64
|
+
default = 1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
variable "node_max_size" {
|
|
68
|
+
type = number
|
|
69
|
+
description = "Maximum number of worker nodes."
|
|
70
|
+
default = 4
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
variable "node_disk_size_gb" {
|
|
74
|
+
type = number
|
|
75
|
+
description = "Root EBS volume size per node."
|
|
76
|
+
default = 50
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
variable "node_capacity_type" {
|
|
80
|
+
type = string
|
|
81
|
+
description = "`ON_DEMAND` or `SPOT`. Spot is dramatically cheaper but EKS will replace nodes on reclamation."
|
|
82
|
+
default = "ON_DEMAND"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
variable "endpoint_public_access" {
|
|
86
|
+
type = bool
|
|
87
|
+
description = "Whether the EKS API server is reachable from the public internet. Required for `aws eks update-kubeconfig` from a developer laptop. Phase 4 (PrivateLink) flips this to false."
|
|
88
|
+
default = true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
variable "endpoint_public_access_cidrs" {
|
|
92
|
+
type = list(string)
|
|
93
|
+
description = "CIDRs allowed to reach the public EKS API endpoint. Defaults to anywhere; tighten to your office IP for prod."
|
|
94
|
+
default = ["0.0.0.0/0"]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
variable "tfstate_passphrase" {
|
|
98
|
+
type = string
|
|
99
|
+
description = "Passphrase for OpenTofu state encryption. See encryption.tofu.example."
|
|
100
|
+
default = ""
|
|
101
|
+
sensitive = true
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
variable "scope_tags" {
|
|
105
|
+
type = map(string)
|
|
106
|
+
description = "Tags applied to every resource via the AWS provider's default_tags. Populated by the `aries compute add --infra ...` flow with the infra-uid + managed-by tag set; left empty when the legacy `aries cluster aws ...` commands invoke the module."
|
|
107
|
+
default = {}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
locals {
|
|
111
|
+
cluster_name = length(var.cluster_name) > 0 ? var.cluster_name : "${var.project}-${var.environment}"
|
|
112
|
+
name_prefix = "${var.project}-${var.environment}-cluster"
|
|
113
|
+
|
|
114
|
+
common_tags = merge({
|
|
115
|
+
Project = var.project
|
|
116
|
+
Environment = var.environment
|
|
117
|
+
Component = "cluster"
|
|
118
|
+
ManagedBy = "opentofu"
|
|
119
|
+
}, var.scope_tags)
|
|
120
|
+
}
|