Skip to content

Commit

Permalink
feat: add haproxy module for load balancing
Browse files Browse the repository at this point in the history
  • Loading branch information
jhandguy committed Jul 7, 2023
1 parent e489ea1 commit 1eefbce
Show file tree
Hide file tree
Showing 24 changed files with 239 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -215,5 +215,5 @@ jobs:
- name: Run all tests
env:
ENVIRONMENT: redis
ENVIRONMENT: haproxy
run: make rust_ci
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
.DS_STORE
.idea

**/.terraform/*
**/terraform.tfvars

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ update_terraform:
update:
make update_terraform ENVIRONMENT=consul
make update_terraform ENVIRONMENT=nginx
make update_terraform ENVIRONMENT=redis
make update_terraform ENVIRONMENT=haproxy
make -j update_s3 update_dynamo update_gateway update_cli

update_%:
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,28 @@ brew install protobuf protoc-gen-go protoc-gen-go-grpc kind terraform k6
| Consul | `make setup ENVIRONMENT=consul` |
| Nginx | `make setup ENVIRONMENT=nginx` |
| Nginx (ArgoRollouts) | `make setup ENVIRONMENT=nginx TF_VAR_argorollouts_enabled=true` |
| Redis | `make setup ENVIRONMENT=redis` |
| HAProxy | `make setup ENVIRONMENT=haproxy` |

## Run Tests

| Environment | Command |
|-------------------------|------------------------------------|
| Consul | `make go_test ENVIRONMENT=consul` |
| Nginx | `make go_test ENVIRONMENT=nginx` |
| Redis | `make rust_test ENVIRONMENT=redis` |
| Environment | Command |
|-------------|--------------------------------------|
| Consul | `make go_test ENVIRONMENT=consul` |
| Nginx | `make go_test ENVIRONMENT=nginx` |
| HAProxy | `make rust_test ENVIRONMENT=haproxy` |

## Run Load Tests

| Environment | Command |
|-------------------------|------------------------------------|
| Consul | `make go_load ENVIRONMENT=consul` |
| Nginx | `make go_load ENVIRONMENT=nginx` |
| Redis | `make rust_load ENVIRONMENT=redis` |
| Environment | Command |
|-------------|--------------------------------------|
| Consul | `make go_load ENVIRONMENT=consul` |
| Nginx | `make go_load ENVIRONMENT=nginx` |
| HAProxy | `make rust_load ENVIRONMENT=haproxy` |

## Destroy Infrastructure

| Environment | Command |
|-------------------------|------------------------------------|
| Consul | `make teardown ENVIRONMENT=consul` |
| Nginx | `make teardown ENVIRONMENT=nginx` |
| Redis | `make teardown ENVIRONMENT=redis` |
| Environment | Command |
|-------------|-------------------------------------|
| Consul | `make teardown ENVIRONMENT=consul` |
| Nginx | `make teardown ENVIRONMENT=nginx` |
| HAProxy | `make teardown ENVIRONMENT=haproxy` |
3 changes: 2 additions & 1 deletion sql/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ test:
cargo test --features $(FEATURE) -- --include-ignored

load: export SQL_TOKEN=$(shell terraform -chdir=$(CHDIR) output -json sql_$(FEATURE)_token | jq -r .)
load: export SQL_URL=$(shell terraform -chdir=$(CHDIR) output -json sql_$(FEATURE)_url | jq -r .)
load: export SQL_HOST=$(shell terraform -chdir=$(CHDIR) output -json sql_$(FEATURE)_ingress_host | jq -r .)
load: export SQL_URL=$(shell terraform -chdir=$(CHDIR) output -json sql_$(FEATURE)_ingress_url | jq -r .)
load:
k6 run k6/script.js

Expand Down
28 changes: 28 additions & 0 deletions sql/helm/templates/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{- with .Values.ingress }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $.Release.Name }}
namespace: {{ $.Release.Namespace }}
labels:
app: {{ $.Release.Name }}
annotations:
cert-manager.io/issuer: {{ $.Release.Name }}
spec:
rules:
- host: {{ .host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ $.Release.Name }}
port:
name: http
tls:
- secretName: {{ $.Release.Name }}-tls
hosts:
- {{ .host }}
{{- end }}
8 changes: 8 additions & 0 deletions sql/helm/templates/issuer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
spec:
selfSigned: {}
8 changes: 4 additions & 4 deletions sql/helm/values.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
replicas: 1
resources:
limits:
cpu: 50m
memory: 75Mi
cpu: 75m
memory: 100Mi
requests:
cpu: 25m
memory: 75Mi
cpu: 50m
memory: 100Mi
horizontalPodAutoscaler:
minReplicas: 1
maxReplicas: 2
Expand Down
8 changes: 5 additions & 3 deletions sql/k6/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import {check, sleep} from 'k6';
import {randomItem, randomString, uuidv4} from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';

export const options = {
setupTimeout: '2m',
stages: [
{target: 20, duration: '20s'},
{target: 20, duration: '20s'},
{target: 0, duration: '20s'},
{target: 20, duration: '40s'},
{target: 20, duration: '40s'},
{target: 0, duration: '40s'},
],
thresholds: {
'checks': ['rate>0.9'],
Expand All @@ -20,6 +21,7 @@ const url = `http://${__ENV.SQL_URL}`;
const params = {
headers: {
'Authorization': `Bearer ${__ENV.SQL_TOKEN}`,
'Host': __ENV.SQL_HOST,
'Content-Type': 'application/json',
'X-Redis-Enabled': __ENV.REDIS_ENABLED,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

| Name | Source | Version |
|------|--------|---------|
| <a name="module_certmanager"></a> [certmanager](#module\_certmanager) | ../../modules/certmanager | n/a |
| <a name="module_haproxy"></a> [haproxy](#module\_haproxy) | ../../modules/haproxy | n/a |
| <a name="module_kind"></a> [kind](#module\_kind) | ../../modules/kind | n/a |
| <a name="module_loki"></a> [loki](#module\_loki) | ../../modules/loki | n/a |
| <a name="module_metrics"></a> [metrics](#module\_metrics) | ../../modules/metrics | n/a |
Expand All @@ -36,6 +38,8 @@
| [random_pet.mysql_user](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [random_pet.postgres_database](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [random_pet.postgres_user](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [random_pet.sql_mysql_host](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [random_pet.sql_postgres_host](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |

## Inputs

Expand All @@ -57,8 +61,12 @@ No inputs.
| <a name="output_prometheus_url"></a> [prometheus\_url](#output\_prometheus\_url) | Prometheus URL |
| <a name="output_redis_password"></a> [redis\_password](#output\_redis\_password) | Redis password |
| <a name="output_redis_url"></a> [redis\_url](#output\_redis\_url) | Redis URL |
| <a name="output_sql_mysql_ingress_host"></a> [sql\_mysql\_ingress\_host](#output\_sql\_mysql\_ingress\_host) | SQL MySQL Ingress host |
| <a name="output_sql_mysql_ingress_url"></a> [sql\_mysql\_ingress\_url](#output\_sql\_mysql\_ingress\_url) | SQL MySQL Ingress URL |
| <a name="output_sql_mysql_token"></a> [sql\_mysql\_token](#output\_sql\_mysql\_token) | SQL MySQL token |
| <a name="output_sql_mysql_url"></a> [sql\_mysql\_url](#output\_sql\_mysql\_url) | SQL MySQL URL |
| <a name="output_sql_postgres_ingress_host"></a> [sql\_postgres\_ingress\_host](#output\_sql\_postgres\_ingress\_host) | SQL Postgres Ingress host |
| <a name="output_sql_postgres_ingress_url"></a> [sql\_postgres\_ingress\_url](#output\_sql\_postgres\_ingress\_url) | SQL Postgres Ingress URL |
| <a name="output_sql_postgres_token"></a> [sql\_postgres\_token](#output\_sql\_postgres\_token) | SQL Postgres token |
| <a name="output_sql_postgres_url"></a> [sql\_postgres\_url](#output\_sql\_postgres\_url) | SQL Postgres URL |
<!-- END_TF_DOCS -->
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module "kind" {
source = "../../modules/kind"

cluster_name = "redis"
cluster_name = "haproxy"
node_ports = [
"postgresql",
"mysql",
Expand All @@ -13,6 +13,9 @@ module "kind" {
"prometheus",
"alertmanager",
"grafana",
"haproxy_http",
"haproxy_https",
"haproxy_stat",
]
}

Expand Down Expand Up @@ -49,9 +52,11 @@ module "sql_postgres" {
source = "../../modules/sql"

feature = "postgres"
ingress_host = random_pet.sql_postgres_host.id
node_ip = module.kind.node_ip
node_ports = [module.kind.node_ports["sql_postgres_http"], module.kind.node_ports["sql_postgres_metrics"]]
prometheus_enabled = true
replicas = 2
secrets = {
"database_url" = module.postgresql.cluster_url
"database_user" = module.postgresql.user_name
Expand All @@ -69,9 +74,11 @@ module "sql_mysql" {
source = "../../modules/sql"

feature = "mysql"
ingress_host = random_pet.sql_mysql_host.id
node_ip = module.kind.node_ip
node_ports = [module.kind.node_ports["sql_mysql_http"], module.kind.node_ports["sql_mysql_metrics"]]
prometheus_enabled = true
replicas = 2
secrets = {
"database_url" = module.mysql.cluster_url
"database_user" = module.mysql.user_name
Expand Down Expand Up @@ -115,3 +122,17 @@ module "metrics" {
depends_on = [module.kind]
source = "../../modules/metrics"
}

module "haproxy" {
depends_on = [module.prometheus]
source = "../../modules/haproxy"

node_ip = module.kind.node_ip
node_ports = [module.kind.node_ports["haproxy_http"], module.kind.node_ports["haproxy_https"], module.kind.node_ports["haproxy_stat"]]
prometheus_enabled = true
}

module "certmanager" {
depends_on = [module.kind]
source = "../../modules/certmanager"
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ output "sql_postgres_token" {
sensitive = true
}

output "sql_postgres_ingress_url" {
value = module.haproxy.url
description = "SQL Postgres Ingress URL"
}

output "sql_postgres_ingress_host" {
value = random_pet.sql_postgres_host.id
description = "SQL Postgres Ingress host"
}

output "sql_mysql_url" {
value = module.sql_mysql.url
description = "SQL MySQL URL"
Expand All @@ -63,6 +73,16 @@ output "sql_mysql_token" {
sensitive = true
}

output "sql_mysql_ingress_url" {
value = module.haproxy.url
description = "SQL MySQL Ingress URL"
}

output "sql_mysql_ingress_host" {
value = random_pet.sql_mysql_host.id
description = "SQL MySQL Ingress host"
}

output "prometheus_url" {
value = module.prometheus.prometheus_url
description = "Prometheus URL"
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ resource "random_password" "sql_mysql_token" {
length = 32
special = false
}

resource "random_pet" "sql_postgres_host" {
length = 3
separator = "."
}
resource "random_pet" "sql_mysql_host" {
length = 3
separator = "."
}
38 changes: 38 additions & 0 deletions terraform/modules/haproxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_helm"></a> [helm](#provider\_helm) | n/a |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [helm_release.haproxy](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_node_ip"></a> [node\_ip](#input\_node\_ip) | Node ip | `string` | n/a | yes |
| <a name="input_node_ports"></a> [node\_ports](#input\_node\_ports) | Node ports | `tuple([number, number, number])` | n/a | yes |
| <a name="input_prometheus_enabled"></a> [prometheus\_enabled](#input\_prometheus\_enabled) | Enable Prometheus | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_cluster_url"></a> [cluster\_url](#output\_cluster\_url) | Cluster URL |
| <a name="output_url"></a> [url](#output\_url) | URL |
<!-- END_TF_DOCS -->
34 changes: 34 additions & 0 deletions terraform/modules/haproxy/helm_releases.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
resource "helm_release" "haproxy" {
name = "haproxy"
namespace = "haproxy"
repository = "https://haproxytech.github.io/helm-charts"
chart = "kubernetes-ingress"
create_namespace = true
wait = true
version = "1.32.0"

values = [
<<-EOF
controller:
replicaCount: 1
ingressClassResource:
default: true
config:
ssl-redirect: "false"
%{if var.prometheus_enabled}
serviceMonitor:
enabled: true
extraLabels:
release: prometheus
%{endif}
service:
type: NodePort
nodePorts:
http: ${var.node_ports.0}
https: ${var.node_ports.1}
stat: ${var.node_ports.2}
defaultBackend:
enabled: true
EOF
]
}
9 changes: 9 additions & 0 deletions terraform/modules/haproxy/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "url" {
value = "${var.node_ip}:${var.node_ports.0}"
description = "URL"
}

output "cluster_url" {
value = "${helm_release.haproxy.name}-kubernetes-ingress.${helm_release.haproxy.namespace}.svc.cluster.local:80"
description = "Cluster URL"
}
8 changes: 8 additions & 0 deletions terraform/modules/haproxy/requirements.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_version = "~> 1"
required_providers {
helm = {
source = "hashicorp/helm"
}
}
}
Loading

0 comments on commit 1eefbce

Please sign in to comment.