redemonbr/simple-load-balancer

By redemonbr

Updated 1 day ago

Image
Artifact
Networking
Developer tools
0

10K+

redemonbr/simple-load-balancer repository overview

Simple Load Balancer

What is this image

This image contains a simple load balancer made on top of Caddy v2 using its reverse_proxy directive. If you are unfamiliar with Caddy webserver, check their website

This image is automatically updated every week and is maintained by ReDemoNBR and rdnxk. It is not maintained by Caddy

The motivation of this project is to create a simple load balancer that can be easily used as a Load Balancer utility in Docker Compose or in CI/CD pipelines.

Source of these images

Environment variables

We have some environment variables that are used for running the load balancer and some that are directly passed to Caddy's reverse_proxy directive configuration.

Simple Load Balancer variables
  • SLB_FROM_HOST: (required). Name of the host that will act as the load balancer distributing the connections over the upstream hosts
  • SLB_TO_UPSTREAMS: (required). Names or addresses of the upstream hosts that will handle the final connections from the load balancer
  • SLB_FORMAT_CADDYFILE: (optional). Format and prettify the generated Caddyfile before starting the load balancer. It is activated if it is set to 1 or true. Default value is 1
  • SLB_VALIDATE_CADDYFILE: (optional). Validate the generated Caddyfile before starting the load balancer. It is activated if it is set to 1 or true. Default value is 1
  • SLB_EXPOSE_PORT: (optional). Port to expose. Default is 9000
Caddy's underlying variables

These variables can be used to customize the underlying Caddy Reverse Proxy behavior. They can be used to change the load balancing policy algorithms, to set active or passive health checks, or to add/remove headers upstream or downstream.

Usage

Docker Compose

Using Simple Load Balancer to balance load for a MinIO (an open-source S3-compliant file storage service) with erasure code on 4 different hosts with 2 disks in each. MinIO will be running the service on port 9000 and the console (web browser) on port 9001. So we will open 2 load balancers, one for the service on port 9000 and another for the console on port 9001

# template for minio services
x-minio-common: &minio-common
  image: minio/minio:latest
  command: ["server", "--address", ":9000", "--console-address", ":9001", "http://minio{1...4}/data{1...2}"]
  environment:
    MINIO_ROOT_USER: root-user
    MINIO_ROOT_PASSWORD: my-sekrit-password
  ports:
    - "9000"
    - "9001"
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
    interval: 30s
    timeout: 20s
    retries: 3

services:
  minio1:
    <<: *minio-common
    volumes:
      - s3-1-1:/data1
      - s3-1-2:/data2
  minio2:
    <<: *minio-common
    volumes:
      - s3-2-1:/data1
      - s3-2-2:/data2
  minio3:
    <<: *minio-common
    volumes:
      - s3-3-1:/data1
      - s3-3-2:/data2
  minio4:
    <<: *minio-common
    volumes:
      - s3-4-1:/data1
      - s3-4-2:/data2
  minio-service-loadbalancer:
    image: redemonbr/simple-load-balancer:latest
    environment:
      SLB_FROM_HOST: ":9000"
      SLB_TO_UPSTREAMS: minio1:9000,minio2:9000,minio3:9000,minio4:9000
      SLB_LB_POLICY: round_robin
      SLB_LB_TRY_DURATION: 1s
      SLB_LB_TRY_INTERVAL: 250ms
      SLB_EXPOSE_PORT: 9000
    depends_on:
      - minio1
      - minio2
      - minio3
      - minio4
    ports:
      - "9000:9000"
  minio-console-loadbalancer:
    image: redemonbr/simple-load-balancer:latest
    environment:
      SLB_FROM_HOST: ":9001"
      SLB_EXPOSE_PORT: 9001
      SLB_TO_UPSTREAMS: minio1:9001,minio2:9001,minio3:9001,minio4:9001
      SLB_LB_POLICY: round_robin
      SLB_LB_TRY_DURATION: 1s
      SLB_LB_TRY_INTERVAL: 250ms
    depends_on:
      - minio1
      - minio2
      - minio3
      - minio4
    ports:
      - "9001:9001"

volumes:
  s3-1-1: {}
  s3-1-2: {}
  s3-2-1: {}
  s3-2-2: {}
  s3-3-1: {}
  s3-3-2: {}
  s3-4-1: {}
  s3-4-2: {}
GitLab-CI (Continuous Integration example)

Using K6 load testing tool for testing an application with 3 replicas that will run on port 5566. Consider that the application will have an endpoint at /health for active healthchecking that returns HTTP status 200 if OK and will be checked at every 500ms. The Simple Load Balancer will be set to run on port 12345 in this example.

load-testing:
  stage: test
  image: 
    - name: loadimpact/k6:0.34.1
      entrypoint: ["/bin/sh", "-c"]
  services:
    - name: my-app-container:latest
      alias: api-replica-1
    - name: my-app-container:latest
      alias: api-replica-2
    - name: my-app-container:latest
      alias: api-replica-3
    - name: redemonbr/simple-load-balancer:latest
      alias: api-lb
  variables:
    SLB_EXPOSE_PORT: 12345
    SLB_FROM_HOST: ":12345" ## it will listen on port "12345"
    SLB_TO_UPSTREAMS: api-replica-1:5566,api-replica-2:5566,api-replica-3:5566
    SLB_LB_POLICY: round_robin
    SLB_HEALTH_URI: /health
    SLB_HEALTH_STATUS: 200
    SLB_HEALTH_INTERVAL: 500ms
  script:
    ## tests with 1000 virtual users for 20s on address "api-lb:12345" which is the load balance address
    - k6 run --vus 1000 --duration 20s --address api-lb:12345 load-test.js
  artifacts:
    name: shiftleft-$CI_COMMIT_SHORT_SHA
    paths:
      - shiftleft.md
    expire_in: 7 days
    public: false

Limitations

As mentioned before, this image has the objective to be a simple load balancer and it is built on top of Caddy v2. So it has some limitations, then please read them below.

Using commas in SLB_TO_UPSTREAMS, SLB_HEALTH_HEADERS, SLB_HEADER_UP and SLB_HEADER_DOWN environment variables

We use comma-separated values in SLB_TO_UPSTREAMS, SLB_HEADER_UP and SLB_HEADER_DOWN environment variables, so the commas are already used as delimiters for the values.
This means that if any of the upstream addresses (or header keys or header values) contain a comma, then the values will be split there and cause an unwanted behavior.

So please, double check if the addresses, header keys or header values contain commas.

Caddy's Admin API

This image disables by default the admin API in Caddy's global options. This is to avoid exposing an API that is able to change the configuration

Caddy's Global options

All other global options remain unchanged, intentionally for loading default configurations. This means that this image does not provide an easy interface for you to:

Caddy's Reverse Proxy unsupported features

The transport and handle_response keywords are not set by this image so they remain with the default behavior. Also, intercepting responses is not supported.

Tag summary

Content type

Unrecognized

Digest

sha256:f81d04ba9

Size

416.7 kB

Last updated

1 day ago

docker pull redemonbr/simple-load-balancer:sha256-eb7f274194e2f16954b227132e28d3d062b50e7c6265dcb60ad3ddc0bf257862.sbom