Skip to content

Commit 2b3e02e

Browse files
authored
Merge pull request #7 from dnks0/feature/dbx-proxy
* multi instance support * haproxy maxconn override and automatic default calculation (conservative) * introduced deployment-modes in terraform stack: bootstrap, proxy-only * dbx-proxy now uses arm based compute
2 parents 3f79c1b + ada5c35 commit 2b3e02e

32 files changed

Lines changed: 819 additions & 357 deletions

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ Include the module in your Terraform stack:
2323
```hcl
2424
module "dbx_proxy" {
2525
26-
source = "github.com/dnks0/dbx-proxy//terraform/aws?ref=v0.1.0"
26+
source = "github.com/dnks0/dbx-proxy//terraform/aws?ref=v<release>"
2727
2828
# aws config
2929
region = "eu-central-1"
3030
tags = {}
3131
...
3232
3333
# dbx-proxy config
34-
dbx_proxy_image_version = "0.1.0"
34+
dbx_proxy_image_version = "<release>"
3535
dbx_proxy_health_port = 8080
3636
3737
# Example: forward TCP/443 to a private target in your VPC
@@ -58,6 +58,8 @@ More details about the Terraform module and configurations can be found [here](t
5858

5959
You will still need to configure the Databricks-side objects like NCC, private endpoint rules and accept the connection on your endpoint-service.
6060

61+
By default the module runs in `deployment_mode = "bootstrap"` and can create networking and the NLB/endpoint service. If you already have networking use `deployment_mode = "bootstrap"` and provide `vpc_id`, and `subnet_ids`. If you already have networking/NLB, set `deployment_mode = "proxy-only"` and provide `vpc_id`, `subnet_ids`, and `nlb_arn` (see Terraform docs for details).
62+
6163
### Troubleshooting
6264

6365
To validate that the proxy is up and reachable,run the following from a serverless notebook:

terraform/README.md

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,19 @@ This repository provides a **Terraform module** for deploying `dbx-proxy` across
1313

1414
**Always deployed (AWS implementation):**
1515
- **Compute**: EC2 Launch Template + Auto Scaling Group (ASG) running `dbx-proxy`
16-
- **Load balancing**: internal **Network Load Balancer (NLB)**
17-
- **Private connectivity**: **VPC Endpoint Service (PrivateLink)** backed by the NLB
1816
- **Networking & security**: Security Group, IAM Role + Instance Profile
1917

20-
**Conditionally deployed:**
21-
- VPC, private subnets
22-
- Optional IGW + public subnet + NAT gateway (internet connectivity needed to pull images, etc.!)
23-
- Route tables + associations
18+
**Deployment-mode dependent:**
19+
- **Load balancing**
20+
- `bootstrap`: creates an internal **Network Load Balancer (NLB)**
21+
- `proxy-only`: attaches listeners/target groups to an existing NLB
22+
- **Private connectivity**
23+
- `bootstrap`: creates a **VPC Endpoint Service (PrivateLink)** backed by the NLB
24+
- `proxy-only`: uses the existing endpoint service (if any) outside this module
25+
- **Networking (when bootstrapping)**
26+
- VPC, private subnets
27+
- Optional IGW + public subnet + NAT gateway (internet connectivity needed to pull images, etc.!)
28+
- Route tables + associations
2429

2530
---
2631

@@ -36,15 +41,15 @@ In your existing Terraform stack, add:
3641

3742
```hcl
3843
module "dbx_proxy" {
39-
source = "github.com/dnks0/dbx-proxy//terraform/aws?ref=v0.1.0"
44+
source = "github.com/dnks0/dbx-proxy//terraform/aws?ref=v<release>"
4045
4146
# AWS config
4247
region = "eu-central-1"
4348
tags = {}
4449
...
4550
4651
# dbx-proxy config
47-
dbx_proxy_image_version = "0.1.0"
52+
dbx_proxy_image_version = "<release>"
4853
dbx_proxy_health_port = 8080
4954
dbx_proxy_listener = []
5055
}
@@ -57,7 +62,7 @@ terraform init
5762
terraform apply
5863
```
5964

60-
After apply, use the output `vpc_endpoint_service_name` when creating Databricks private endpoint rules (see Databricks guide linked above).
65+
After apply, use the output `load_balancer.vpc_endpoint_service_name` when creating Databricks private endpoint rules (see Databricks guide linked above).
6166
Also, make sure to add a domain of your choice as private endpoint rule on your NCC that you could use for [troubleshooting](../README.md#troubleshooting) purposes.
6267

6368
---
@@ -72,9 +77,11 @@ These variables define what the proxy should do (listeners, health port, image t
7277

7378
| Variable | Type | Default | Description |
7479
|---|---:|---:|---|
75-
| `dbx_proxy_image_version` | `string` | `"0.1.0"` | Docker image tag/version of `dbx-proxy` to deploy. |
80+
| `dbx_proxy_image_version` | `string` | `"0.2.0"` | Docker image tag/version of `dbx-proxy` to deploy. |
7681
| `dbx_proxy_health_port` | `number` | `8080` | Health port exposed by `dbx-proxy` (HTTP `GET /status`). Also used for NLB target group health checks. |
82+
| `dbx_proxy_max_connections` | `number` | `null` | Optional HAProxy `maxconn` override. If unset, the AWS module derives a value from vCPU and memory of the selected instance-type. |
7783
| `dbx_proxy_listener` | `list(object)` | `[]` | Listener configuration (ports/modes/routes/destinations). See **Listener configuration** below. |
84+
| `deployment_mode` | `string` | `"bootstrap"` | Controls whether the module bootstraps networking/NLB (`bootstrap`) or attaches to existing infrastructure (`proxy-only`). See **Deployment mode behavior** below. |
7885

7986
#### AWS-specific variables (`terraform/aws`)
8087

@@ -83,26 +90,54 @@ These variables define what the proxy should do (listeners, health port, image t
8390
| `region` | `string` | (required) | AWS region to deploy to. |
8491
| `prefix` | `string` | `null` | Optional naming prefix. A randomized suffix is always appended to avoid collisions. |
8592
| `tags` | `map(string)` | `{}` | Extra tags applied to AWS resources (also used as provider default tags). |
86-
| `instance_type` | `string` | `"t3.medium"` | EC2 instance type for proxy nodes. |
87-
| `vpc_id` | `string` | `null` | Existing VPC ID. If `null`, the module bootstraps a VPC. |
88-
| `subnet_ids` | `list(string)` | `[]` | Existing private subnet IDs for the NLB + ASG. If empty, subnets are created. |
89-
| `vpc_cidr` | `string` | `"10.0.0.0/16"` | VPC CIDR (only used when creating a VPC). |
90-
| `subnet_cidrs` | `list(string)` | `["10.0.1.0/24","10.0.2.0/24"]` | Private subnet CIDRs (only used when creating subnets). |
91-
| `enable_nat_gateway` | `bool` | `true` | Whether to create NAT (and related IGW/public subnet) for outbound internet access (only when creating networking). |
92-
| `public_subnet_cidr` | `string` | `"10.0.0.0/24"` | Public subnet CIDR for the NAT gateway (only used when creating networking). |
93+
| `instance_type` | `string` | `"t4g.medium"` | EC2 instance type for proxy instances. |
94+
| `min_capacity` | `number` | `1` | Minimum number of dbx-proxy instances. |
95+
| `max_capacity` | `number` | `1` | Maximum number of dbx-proxy instances. |
96+
| `vpc_id` | `string` | `null` | Existing VPC ID. Required for `proxy-only` mode. If `null`, a VPC can be bootstrapped in `bootstrap` mode. |
97+
| `subnet_ids` | `list(string)` | `[]` | Existing private subnet IDs for the NLB + ASG. Required for `proxy-only` mode. If empty, subnets can be created in `bootstrap` mode. |
98+
| `vpc_cidr` | `string` | `"10.0.0.0/16"` | VPC CIDR (only used when creating a VPC in `bootstrap`). |
99+
| `subnet_cidrs` | `list(string)` | `["10.0.1.0/24","10.0.2.0/24"]` | Private subnet CIDRs (only used when creating subnets in `bootstrap` mode). |
100+
| `enable_nat_gateway` | `bool` | `true` | Whether to create IGW + NAT for outbound internet access (only when creating networking in `bootstrap` mode). |
101+
| `nat_subnet_cidr` | `string` | `"10.0.0.0/24"` | Public subnet CIDR for the NAT gateway (only used when creating networking in `bootstrap` mode). |
102+
| `nlb_arn` | `string` | `null` | Existing NLB ARN to attach listeners/target groups to in `proxy-only` mode. |
103+
104+
#### Deployment mode behavior
105+
106+
- **`bootstrap`** (default)
107+
- Creates an internal NLB and a PrivateLink endpoint service.
108+
- If **`vpc_id` + `subnet_ids` are provided**, the module uses existing networking.
109+
- If **`vpc_id` and `subnet_ids` are not provided**, the module creates a VPC + subnets (and optionally IGW/NAT based on `enable_nat_gateway`).
110+
- **`proxy-only`**
111+
- Requires **`vpc_id` + `subnet_ids`** and **`nlb_arn`**.
112+
- Does **not** create a new NLB or PrivateLink endpoint service; it attaches listeners/target groups to the existing NLB and deploys the proxy only (ec2, security-group, NLB listener & target-groups)
93113

94114
---
95115

96116
### Outputs (AWS)
97117

98-
- `nlb_arn`: ARN of the internal NLB
99-
- `vpc_endpoint_service_name`: **input** for Databricks private endpoint rules
100-
- `vpc_endpoint_service_arn`: ARN of the endpoint service
101-
- `nlb_dns_name`: internal NLB DNS name
102-
- `nlb_zone_id`: Route53 hosted zone id for NLB aliases
103-
- `autoscaling_group_name`: ASG name
104-
- `security_group_id`: Security group ID attached to the proxy instances
105-
- `target_group_arns`: listener target groups keyed by listener name
118+
- `networking`: object with
119+
- `vpc_id`
120+
- `subnet_ids`
121+
- `subnet_cidrs`
122+
- `internet_gateway_id`
123+
- `nat_gateway_id`
124+
- `nat_subnet_id`
125+
- `nat_subnet_cidr`
126+
- `load_balancer`: object with
127+
- `nlb_arn`
128+
- `nlb_dns_name`
129+
- `nlb_target_group_arns`
130+
- `vpc_endpoint_service_arn`
131+
- `vpc_endpoint_service_name`
132+
- `proxy`: object with
133+
- `iam_role_name`
134+
- `iam_role_arn`
135+
- `instance_profile_name`
136+
- `instance_profile_arn`
137+
- `security_group_id`
138+
- `autoscaling_group_name`
139+
- `launch_template_name`
140+
- `dbx_proxy_cfg`
106141

107142
---
108143

terraform/aws/.tfvars

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ prefix="dnks"
22
region="eu-central-1"
33
tags={}
44

5+
deployment_mode="bootstrap"
6+
57
# AWS resources
6-
instance_type="t3.medium"
8+
instance_type="t4g.medium"
79

810
# dbx-proxy configuration
9-
dbx_proxy_image_version="0.1.0"
11+
dbx_proxy_image_version="0.1.1"
1012
dbx_proxy_health_port=8080
1113
dbx_proxy_listener=[]

terraform/aws/local.tf

Lines changed: 6 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,13 @@ locals {
99
var.tags,
1010
)
1111

12-
vpc_id = var.vpc_id != null ? var.vpc_id : aws_vpc.this[0].id
13-
subnet_ids = length(var.subnet_ids) > 0 ? var.subnet_ids : [for s in aws_subnet.this : s.id]
14-
subnet_cidr_blocks = length(var.subnet_ids) > 0 ? [for s in values(data.aws_subnet.this) : s.cidr_block] : [for s in aws_subnet.this : s.cidr_block]
12+
bootstrap_networking = var.deployment_mode == "bootstrap" && (var.vpc_id == null && length(var.subnet_ids) == 0)
13+
bootstrap_load_balancer = var.deployment_mode == "bootstrap"
1514

16-
allowed_principals = [
17-
"arn:aws:iam::565502421330:role/private-connectivity-role-${var.region}"
18-
]
15+
vpc_id = module.networking.vpc_id
16+
subnet_ids = module.networking.subnet_ids
17+
subnet_cidrs = module.networking.subnet_cidrs
1918

20-
cloud_config = {
21-
write_files = [
22-
{
23-
path = "/dbx-proxy/conf/dbx-proxy.cfg"
24-
owner = "root:root"
25-
permissions = "0644"
26-
content = module.common.dbx_proxy_cfg
27-
},
28-
{
29-
path = "/dbx-proxy/docker-compose.yaml"
30-
owner = "root:root"
31-
permissions = "0644"
32-
content = module.common.docker_compose
33-
},
34-
{
35-
path = "/etc/systemd/system/dbx-proxy.service"
36-
owner = "root:root"
37-
permissions = "0644"
38-
content = <<-EOT
39-
[Unit]
40-
Description=dbx-proxy (docker compose)
41-
Requires=docker.service
42-
After=docker.service network-online.target
43-
Wants=network-online.target
19+
nlb_target_group_arns = module.load_balancer.nlb_target_group_arns
4420

45-
[Service]
46-
Type=oneshot
47-
RemainAfterExit=yes
48-
WorkingDirectory=/dbx-proxy
49-
ExecStart=/usr/bin/docker compose --file /dbx-proxy/docker-compose.yaml up --detach
50-
ExecStop=/usr/bin/docker compose --file /dbx-proxy/docker-compose.yaml down
51-
TimeoutStartSec=0
52-
53-
[Install]
54-
WantedBy=multi-user.target
55-
EOT
56-
},
57-
]
58-
runcmd = [
59-
[
60-
"bash",
61-
"-c",
62-
"set -euxo pipefail; sudo dnf update -y || sudo yum update -y || sudo apt-get update -y",
63-
],
64-
[
65-
"bash",
66-
"-c",
67-
"set -euxo pipefail; (sudo dnf install -y docker || sudo yum install -y docker || sudo apt-get install -y docker.io)",
68-
],
69-
[
70-
"bash",
71-
"-c",
72-
"set -euxo pipefail; sudo systemctl enable docker; sudo systemctl start docker",
73-
],
74-
[
75-
"bash",
76-
"-c",
77-
"set -euxo pipefail; sudo mkdir -p /usr/libexec/docker/cli-plugins; sudo curl -sSL \"https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)\" -o /usr/libexec/docker/cli-plugins/docker-compose; sudo chmod +x /usr/libexec/docker/cli-plugins/docker-compose; sudo systemctl restart docker",
78-
],
79-
[
80-
"bash",
81-
"-c",
82-
"set -euxo pipefail; sudo systemctl daemon-reload; sudo systemctl enable --now dbx-proxy.service",
83-
],
84-
]
85-
}
8621
}

terraform/aws/main.tf

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,62 @@ resource "random_string" "this" {
44
length = 10
55
}
66

7-
# Common config module: renders docker-compose.yaml
8-
module "common" {
9-
source = "../common"
7+
module "networking" {
8+
source = "./modules/networking"
9+
10+
bootstrap_networking = local.bootstrap_networking
11+
12+
prefix = local.prefix
13+
tags = local.tags
14+
15+
vpc_id = var.vpc_id
16+
vpc_cidr = var.vpc_cidr
17+
18+
subnet_ids = var.subnet_ids
19+
subnet_cidrs = var.subnet_cidrs
20+
21+
nat_subnet_cidr = var.nat_subnet_cidr
22+
enable_nat_gateway = var.enable_nat_gateway
23+
24+
}
25+
26+
module "load_balancer" {
27+
source = "./modules/load-balancer"
28+
29+
bootstrap_load_balancer = local.bootstrap_load_balancer
30+
31+
prefix = local.prefix
32+
region = var.region
33+
tags = local.tags
34+
35+
nlb_arn = var.nlb_arn
36+
37+
vpc_id = local.vpc_id
38+
subnet_ids = local.subnet_ids
1039

11-
dbx_proxy_image_version = var.dbx_proxy_image_version
1240
dbx_proxy_health_port = var.dbx_proxy_health_port
1341
dbx_proxy_listener = var.dbx_proxy_listener
42+
43+
}
44+
45+
module "proxy" {
46+
source = "./modules/proxy"
47+
48+
prefix = local.prefix
49+
tags = local.tags
50+
51+
vpc_id = local.vpc_id
52+
subnet_ids = local.subnet_ids
53+
subnet_cidrs = local.subnet_cidrs
54+
55+
instance_type = var.instance_type
56+
min_capacity = var.min_capacity
57+
max_capacity = var.max_capacity
58+
nlb_target_group_arns = local.nlb_target_group_arns
59+
60+
dbx_proxy_image_version = var.dbx_proxy_image_version
61+
dbx_proxy_health_port = var.dbx_proxy_health_port
62+
dbx_proxy_max_connections = var.dbx_proxy_max_connections
63+
dbx_proxy_listener = var.dbx_proxy_listener
64+
1465
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
data "aws_lb" "this" {
2+
count = var.bootstrap_load_balancer == false ? 1 : 0
3+
arn = var.nlb_arn
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
locals {
2+
3+
nlb_arn = var.bootstrap_load_balancer ? aws_lb.this[0].arn : data.aws_lb.this[0].arn
4+
nlb_dns_name = var.bootstrap_load_balancer ? aws_lb.this[0].dns_name : data.aws_lb.this[0].dns_name
5+
nlb_zone_id = var.bootstrap_load_balancer ? aws_lb.this[0].zone_id : data.aws_lb.this[0].zone_id
6+
7+
allowed_principals = [
8+
"arn:aws:iam::565502421330:role/private-connectivity-role-${var.region}"
9+
]
10+
11+
}

0 commit comments

Comments
 (0)