Enable ALB Ingress¶
By default, in AWS, Grove uses an NGINX Ingress. This ingress is backed by AWS ELB load balancers. That Ingress setup works for most use cases, but in case you need to use a feature that is only supported by the Application Load Balancer type, such as a WAF, you can configure it with the following setup:
1. Grove Configuration¶
The ALB ingress controller requires some extra permissions added to the Kubernetes cluster.
You can declare a policy that provides those permissions by adding the following statements
to a terraform file inside the infrastructure
folder:
variable "cluster_self_managed_node_groups" {}
resource "aws_iam_policy" "alb_policy" {
name = "alb-policy"
description = "Policy required for alb creation."
policy = file("${path.module}/alb-role.json")
}
# Optional policy that makes it posible to use ALB ingress
resource "aws_iam_policy_attachment" "alb-policy-attachment" {
name = "${var.cluster_name}-alb-attachment"
roles = [var.cluster_self_managed_node_groups["worker_group"].iam_role_name]
policy_arn = aws_iam_policy.alb_policy.arn
}
resource "helm_release" "alb_controller" {
name = "aws-load-balancer-controller"
repository = "https://aws.github.io/eks-charts"
chart = "aws-load-balancer-controller"
version = "1.7.2"
namespace = "kube-system"
depends_on = [
aws_iam_policy_attachment.alb-policy-attachment
]
set {
name = "clusterName"
value = var.cluster_name
}
set {
name = "region"
value = var.provider_region
}
set {
name = "vpcId"
value = var.vpc_id
}
}
You'll also need to download the iam policy role json definition into the infrastructure/alb-role.json
from here.
2. Declare Ingress¶
Now you can declare an ALB Ingress in the infrastructure
folder. Here's an example of one:
resource "kubernetes_manifest" "alb_ingress" {
depends_on = [helm_release.alb_controller]
manifest = {
"apiVersion" = "networking.k8s.io/v1"
"kind" = "Ingress"
"metadata" = {
"annotations" = {
"alb.ingress.kubernetes.io/scheme" = "internet-facing"
"alb.ingress.kubernetes.io/target-type": "ip"
}
"labels" = {
"app.kubernetes.io/part-of" = "openedx"
}
"name" = "alb-ingress"
"namespace" = "<INSTANCE-NAMESPACE>"
}
"spec" = {
"ingressClassName" = "alb"
"rules" = [
# Repeat this rule for all the hostnames you'll point to this ingress.
{
"host" = "<HOSTNAME>"
"http" = {
"paths" = [
{
"backend" = {
"service" = {
"name" = "caddy"
"port" = {
"number" = 80
}
}
}
"path" = "/"
"pathType" = "Prefix"
},
]
}
}
]
}
}
}
3. Setup DNS¶
The last step is adding a CNAME record pointing to the ALB domain for any domain you want to configure. You can find the ALB domain in the AWS console. You may also want to remove any records pointing to the old NGINX Ingress.
Optional: Disable default Ingress¶
In order to avoid having double the ammount of Load Balancers, you can disable the default load balancer as needed in the harmony helm values file
Optional: Enable WAF¶
An example of a resource that requires ALB is Amazon's Web Application Firewall (WAF).
Once you have completed the above setup you can either add a WAF manually to the generated ingress
in the AWS console, or declare it in the infrastructure
directory with the following terraform code:
resource "aws_wafv2_web_acl" "alb_waf" {
name = "alb-waf"
scope = "REGIONAL"
default_action {
allow {}
}
# This is an example rule. Create one based on your needs.
rule {
name = "RateLimit"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
aggregate_key_type = "IP"
limit = 500
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimit"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "alb-waf"
sampled_requests_enabled = false
}
}
You also need to update your ingress tags:
resource "kubernetes_manifest" "alb_ingress" {
manifest = {
"apiVersion" = "networking.k8s.io/v1"
"kind" = "Ingress"
"metadata" = {
"annotations" = {
"alb.ingress.kubernetes.io/scheme" = "internet-facing"
"alb.ingress.kubernetes.io/target-type": "ip"
"alb.ingress.kubernetes.io/wafv2-acl-arn": aws_wafv2_web_acl.alb_waf.arn
NOTE: If you set up WAF manually you need disable the contoller's WAF capabilities by setting controller command line flags
--enable-waf=false
or--enable-wafv2=false
. If the controller is also managing WAF, it'll make sure that the annotation matches exactly the waf acl linked to the Load Balancer. This means that it will delete the waf acl if it doesn't match with the Ingress annotations.