What about the Classic Load Balancer (CLB) and Network Load Balancer (NLB)?
Note that the Classic Load Balancer
(sometimes known by its original name of "ELB") and Network Load
Balancers are usually simple enough
that it is best defined as part of the Terraform template that needs it, so there are currently no plans to define a
standalone "elb" module.
To deploy a network load balancer, you can use the aws_lb terraform
resource with the load_balancer_type input set to "network".
You can refer to the after_migration terraform module in our
NLB module migration guide for an example of how to configure an NLB using the terraform resources.
Removed modules
The nlb module was removed in version v0.15.0. When Terraform introduced for_each and dynamic sub blocks in
v0.12.0, it no longer made sense to maintain the NLB module which thinly wrapped the aws_lb resource to provide
dynamic subnet mappings blocks.
At Gruntwork, we've taken the thousands of hours we spent building infrastructure on AWS and
condensed all that experience and code into pre-built packages or modules. Each module is a battle-tested,
best-practices definition of a piece of infrastructure, such as a VPC, ECS cluster, or an Auto Scaling Group. Modules
are versioned using Semantic Versioning to allow Gruntwork clients to keep up to date with the
latest infrastructure best practices in a systematic way.
To use a module in your Terraform templates, create a module resource and set its source field to the Git URL of
this repo. You should also set the ref parameter so you're fixed to a specific version of this repo, as the master
branch may have backwards incompatible changes (see module
sources).
For example, to use v1.0.8 of the ecs-cluster module, you would add the following:
module"ecs_cluster" {
source = "git::git@github.com:gruntwork-io/module-ecs.git//modules/ecs-cluster?ref=v1.0.8"# set the parameters for the ECS cluster module
}
Note: the double slash (//) is intentional and required. It's part of Terraform's Git syntax (see module
sources).
See the module's documentation and vars.tf file for all the parameters you can set. Run terraform get -update to
pull the latest version of this module from this repo before runnin gthe standard terraform plan and
terraform apply commands.
Using scripts & binaries
You can install the scripts and binaries in the modules folder of any repo using the Gruntwork
Installer. For example, if the scripts you want to install are
in the modules/ecs-scripts folder of the https://github.com/gruntwork-io/module-ecs repo, you could install them
as follows:
See the docs for each script & binary for detailed instructions on how to use them.
Background
What exactly is a load balancer?
A load balancer is usually the public-facing part of your infrastructure, receives incoming requests, makes a decision
on which backend service to route them to, and forwards the request.
Load balancers can forward any kind of IP traffic, including TCP, UDP, HTTP, and HTTPS requests.
Why is a load balancer sometimes called a reverse proxy?
A "forward proxy" is a server that forwards incoming requests to an external party on your behalf. For example, a "web
proxy" is a forward proxy that makes HTTP requests on your behalf and forwards you the results. This might be useful if
you want to hide your IP address from websites you request, or if your organization wants to scan all web traffic.
A "reverse proxy" works in the opposite way. An external party makes an inbound request meant for a server, but instead
of hitting that server directly, the request hits the "reverse proxy", which then forwards that request to some unknown
backend service, gets the result, and returns it to a client.
It's conceptually identical to a load balancer, so "load balancer" and "reverse proxy" are synonyms.
Why are load balancers needed?
The simplest way to expose a service is to run a single server that runs your service. Users would then make requests
directly to this server.
This has the benefit of simplicity, but many drawbacks, too:
It lacks "High Availability." If this server goes down, your app loses availability. You could just add more servers,
but users tend to access one IP address only.
Your app server is in the public subnet, making it a much easier target for hackers.
There may be cases when you want to route requests to a service other than this app server.
You may want "out of the box" TLS/SSL connections and/or static asset caching, both of which reduce CPU load on your
app server.
A load balancer helps achieve all these properties:
If a single backend service can fail, the load balancer can just route requests to a healthy one. For this reason, a
load balancer usually includes a health check feature to determine if a backend service can receive requests and a way
to register multiple backend service instances.
A load balancer might sit in a public subnet, but backend services can reside in a private subnet, giving them
additional network isolation.
A load balancer can inspect the network request it has received and make routing decisions based on its contents.
A load balancer can terminate your TLS/SSL connection, cache static assets, and generally reduce load on your app server.
And there are more benefits beyond this. A load balancer can be locked down more than an app server because it doesn't
need access to your data stores, it doesn't change very often (i.e. you don't deploy a new version of it every day like
you do with app code), and it doesn't typically need file-system access.
Does the load balancer itself need to be High Availability?
Yes! Many clients make network requests using a DNS address like service.acme.com. If that DNS name resolves to a
single IP address, then this IP address now becomes a single point of failure.
There are typically two techniques for mitigating this. First, you can make sure that the DNS name service.acme.com
resolves to two different IP addresses. Not all network clients will respond to two IP addresses in the same way, but
most browsers will immediately try the "second" IP address if the first one fails.
Second, most networking today is Software-Defined Networking,
which means that a single IP Address can be dynamically re-assigned to a server. Amazon supports this functionality
through the concept of an Elastic IP Address.
In fact, an Elastic IP Address can typically be re-assigned to an EC2 Instance in as little as 7 seconds, though Amazon
doesn't officially guarantee this fast a transition.
But implementing a dynamic Elastic IP Address failover is highly non-trivial. Fortunately, Amazon's managed load
balancers, the Application Load Balancer
and Classic Load Balancer, already
implement High Availability by including automatic failover under the hood. Amazon's managed load balancers also include
auto-scaling for when your load increases, though there are limits to how fast this can happen.
In general, you should not be configuring your own load balancer (e.g. Nginx or HAProxy) unless you can make the case
that an existing managed load balancer solution will not meet your needs.
Developing a module
Versioning
We follow the principles of Semantic Versioning. During initial development, the major
version is to 0 (e.g., 0.x.y), which indicates the code does not yet have a stable API. Once we hit 1.0.0, we will
follow these rules:
Increment the patch version for backwards-compatible bug fixes (e.g., v1.0.8 -> v1.0.9).
Increment the minor version for new features that are backwards-compatible (e.g., v1.0.8 -> 1.1.0).
Increment the major version for any backwards-incompatible changes (e.g. 1.0.8 -> 2.0.0).
The version is defined using Git tags. Use GitHub to create a release, which will have the effect of adding a git tag.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"b5e1291ae1401db97210b139665cb59a39817d65"}]},{"name":".gitignore","path":".gitignore","sha":"be548d345e99887d4ccc3163bf552ee9c337b48d"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"643742985da88d2f6805e0db41d0794232a8bd1a"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"154ea4429924fda533b20544c7a19d8949fc82cf"},{"name":"README.md","path":"README.md","sha":"c0b8bcd48e3b5dd33f77e9191c82e1a4ea64a84f","toggled":true},{"name":"_docs","children":[{"name":"migration_guides","children":[{"name":"nlb_to_0.15.0","children":[{"name":"README.md","path":"_docs/migration_guides/nlb_to_0.15.0/README.md","sha":"2a86c02a985b27782134cc30539455ecbd81046d"},{"name":"after_migration","children":[{"name":"main.tf","path":"_docs/migration_guides/nlb_to_0.15.0/after_migration/main.tf","sha":"9afc43a772b630798ab7d0b7a58fdbff9b0379b8"},{"name":"outputs.tf","path":"_docs/migration_guides/nlb_to_0.15.0/after_migration/outputs.tf","sha":"d967d0daa27477b626b7b28911d10b2f18fe6f76"},{"name":"vars.tf","path":"_docs/migration_guides/nlb_to_0.15.0/after_migration/vars.tf","sha":"b8c8af94a7ed9e5db9bd522bf69e0fe304efddee"}]},{"name":"before_migration","children":[{"name":"main.tf","path":"_docs/migration_guides/nlb_to_0.15.0/before_migration/main.tf","sha":"69345f63220752b9d3c83418ea9e31b1c91530a4"},{"name":"outputs.tf","path":"_docs/migration_guides/nlb_to_0.15.0/before_migration/outputs.tf","sha":"dc162b85fc673c12a9d166a1f58021eb142ac447"},{"name":"vars.tf","path":"_docs/migration_guides/nlb_to_0.15.0/before_migration/vars.tf","sha":"b8c8af94a7ed9e5db9bd522bf69e0fe304efddee"}]}]}]}]},{"name":"examples","children":[{"name":"acm-tls-certificate","children":[{"name":"README.md","path":"examples/acm-tls-certificate/README.md","sha":"0a7892a8b5d327254c91a96276273fcc975821ca"},{"name":"dependencies.tf","path":"examples/acm-tls-certificate/dependencies.tf","sha":"1ee97179c136a9e1c895a0ffcf6cda27cbc3171a"},{"name":"main.tf","path":"examples/acm-tls-certificate/main.tf","sha":"fe57e29d748ae0fdf206cc35c5e5209f02013d22"},{"name":"outputs.tf","path":"examples/acm-tls-certificate/outputs.tf","sha":"30ed2e66238dd38df2c80171079dd2de400efe33"},{"name":"vars.tf","path":"examples/acm-tls-certificate/vars.tf","sha":"94bef46856306d7823e1acb28307c45a3bed9a52"}]},{"name":"alb-with-logs","children":[{"name":"README.md","path":"examples/alb-with-logs/README.md","sha":"b46a1aef114340b80c6742b9344c52f1a952a7a4"},{"name":"main.tf","path":"examples/alb-with-logs/main.tf","sha":"fda10cfbaff280954eea67815fc9ecf82a8a6561"},{"name":"outputs.tf","path":"examples/alb-with-logs/outputs.tf","sha":"518914d6b608ea2d2996cbaa9361c370bd9c9fa1"},{"name":"vars.tf","path":"examples/alb-with-logs/vars.tf","sha":"a11d7589f3fb838585e7035023e8b6a90e8b0fd4"}]},{"name":"alb","children":[{"name":"README.md","path":"examples/alb/README.md","sha":"202d51dd9238a27061a6277a4632dce37706a3f9"},{"name":"main.tf","path":"examples/alb/main.tf","sha":"8f9fc9db2bf91716e2e9814018841cd97751622f"},{"name":"outputs.tf","path":"examples/alb/outputs.tf","sha":"3ab937d31bc4423aa1e17150a40e966fc6cd81da"},{"name":"vars.tf","path":"examples/alb/vars.tf","sha":"df7382a9da55c16fc34fd396653fafd9250679af"}]}]},{"name":"modules","children":[{"name":"acm-tls-certificate","children":[{"name":"README.md","path":"modules/acm-tls-certificate/README.md","sha":"b9c612bd69247dfce080057a3838f13c7ebb04ce"},{"name":"dependencies.tf","path":"modules/acm-tls-certificate/dependencies.tf","sha":"897b000a07205676c96c6bcf19d7a736383ac737"},{"name":"main.tf","path":"modules/acm-tls-certificate/main.tf","sha":"12e26a93d8c6c7c072d286469825af4285458e1d"},{"name":"outputs.tf","path":"modules/acm-tls-certificate/outputs.tf","sha":"89948a85af1e9ed87be4a5cb7124677634cbc249"},{"name":"vars.tf","path":"modules/acm-tls-certificate/vars.tf","sha":"1243bd0da4c6bb3b0a012b1300aa5798e121e0d2"},{"name":"wait-until-tls-cert-not-in-use.sh","path":"modules/acm-tls-certificate/wait-until-tls-cert-not-in-use.sh","sha":"705efd62d0ba101b7fdc32dd24a505825cf56400"}]},{"name":"alb","children":[{"name":"README.md","path":"modules/alb/README.md","sha":"4e01a3a6bde17643eb77b4c2a5c0268f68bb684d"},{"name":"main.tf","path":"modules/alb/main.tf","sha":"caf8cdfab632760b46dbd005fec2fbd5d1b618c1"},{"name":"outputs.tf","path":"modules/alb/outputs.tf","sha":"e09679db5915f4de6fbe4c639de0ef9ac058ac28"},{"name":"vars.tf","path":"modules/alb/vars.tf","sha":"d5aee0ed653986b6d18e290694d16d1aa7dcb394"}]},{"name":"nlb","children":[{"name":"README.md","path":"modules/nlb/README.md","sha":"76f6d2c4608d3270a5de8d4e633b0501803d21b0"}]}]},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"ded6aae1d95e6fca858a0ef196d3ecf30d4bf5f2"},{"name":"acm_tls_certificate_test.go","path":"test/acm_tls_certificate_test.go","sha":"61b423bab92ef2f9bc04e1e6d066d1f7b9e05dee"},{"name":"go.mod","path":"test/go.mod","sha":"bdd5ccc0d7f206398ef3101af0acf957f827e457"},{"name":"go.sum","path":"test/go.sum","sha":"743b71888b540b16983df40982433e2a306606a0"},{"name":"lb_test.go","path":"test/lb_test.go","sha":"a1847684d9e0478301d513902b2cdd772736fc8f"}]}]},"detailsContent":"<p><img src=\"https://img.shields.io/badge/tf-%3E%3D0.12.0-blue.svg\" alt=\"Terraform Version\" class=\"preview__body--diagram\"></p>\n<h1 class=\"preview__body--title\" id=\"load-balancer-modules\">Load Balancer Modules</h1><div class=\"preview__body--border\"></div><p>This repo contains Gruntwork Modules for running a load balancer in AWS. The modules are:</p>\n<ul>\n<li><strong><a href=\"/repos/v0.16.2/module-load-balancer/modules/alb\" class=\"preview__body--description--blue\">alb</a>:</strong> Deploy an <a href=\"http://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html\" class=\"preview__body--description--blue\" target=\"_blank\">Application Load Balancer</a> for use with any <a href=\"http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html\" class=\"preview__body--description--blue\" target=\"_blank\">ALB Target\nGroup</a>.</li>\n</ul>\n<h2 class=\"preview__body--subtitle\" id=\"what-about-the-classic-load-balancer-clb-and-network-load-balancer-nlb\">What about the Classic Load Balancer (CLB) and Network Load Balancer (NLB)?</h2>\n<p>Note that the <a href=\"http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/introduction.html\" class=\"preview__body--description--blue\" target=\"_blank\">Classic Load Balancer</a>\n(sometimes known by its original name of "ELB") and <a href=\"http://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html\" class=\"preview__body--description--blue\" target=\"_blank\">Network Load\nBalancers</a> are usually simple enough\nthat it is best defined as part of the Terraform template that needs it, so there are currently no plans to define a\nstandalone "elb" module.</p>\n<p>To deploy a classic load balancer, you can use the <a href=\"https://www.terraform.io/docs/providers/aws/r/elb.html\" class=\"preview__body--description--blue\" target=\"_blank\">aws_elb terraform\nresource</a>.</p>\n<p>To deploy a network load balancer, you can use the <a href=\"https://www.terraform.io/docs/providers/aws/r/lb.html\" class=\"preview__body--description--blue\" target=\"_blank\">aws_lb terraform\nresource</a> with the <code>load_balancer_type</code> input set to <code>"network"</code>.\nYou can refer to <a href=\"/repos/v0.16.2/module-load-balancer/_docs/migration_guides/nlb_to_0.15.0/after_migration\" class=\"preview__body--description--blue\">the <code>after_migration</code> terraform module</a> in our\nNLB module migration guide for an example of how to configure an NLB using the terraform resources.</p>\n<h2 class=\"preview__body--subtitle\" id=\"removed-modules\">Removed modules</h2>\n<p>The <code>nlb</code> module was removed in version <code>v0.15.0</code>. When Terraform introduced <code>for_each</code> and dynamic sub blocks in\n<code>v0.12.0</code>, it no longer made sense to maintain the NLB module which thinly wrapped the <code>aws_lb</code> resource to provide\ndynamic subnet mappings blocks.</p>\n<p>Refer to <a href=\"/repos/v0.16.2/module-load-balancer/_docs/migration_guides/nlb_to_0.15.0\" class=\"preview__body--description--blue\">the migration guide</a> for information on how to update your\nusage.</p>\n<h2 class=\"preview__body--subtitle\" id=\"what-is-a-module\">What is a module?</h2>\n<p>At <a href=\"http://www.gruntwork.io\" class=\"preview__body--description--blue\" target=\"_blank\">Gruntwork</a>, we've taken the thousands of hours we spent building infrastructure on AWS and\ncondensed all that experience and code into pre-built <strong>packages</strong> or <strong>modules</strong>. Each module is a battle-tested,\nbest-practices definition of a piece of infrastructure, such as a VPC, ECS cluster, or an Auto Scaling Group. Modules\nare versioned using <a href=\"http://semver.org/\" class=\"preview__body--description--blue\" target=\"_blank\">Semantic Versioning</a> to allow Gruntwork clients to keep up to date with the\nlatest infrastructure best practices in a systematic way.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-do-you-use-a-module\">How do you use a module?</h2>\n<p>Most of our modules contain either:</p>\n<ol>\n<li><a href=\"https://www.terraform.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Terraform</a> code</li>\n<li>Scripts & binaries</li>\n</ol>\n<h4 id=\"using-a-terraform-module\">Using a Terraform Module</h4>\n<p>To use a module in your Terraform templates, create a <code>module</code> resource and set its <code>source</code> field to the Git URL of\nthis repo. You should also set the <code>ref</code> parameter so you're fixed to a specific version of this repo, as the <code>master</code>\nbranch may have backwards incompatible changes (see <a href=\"https://www.terraform.io/docs/modules/sources.html\" class=\"preview__body--description--blue\" target=\"_blank\">module\nsources</a>).</p>\n<p>For example, to use <code>v1.0.8</code> of the ecs-cluster module, you would add the following:</p>\n<pre><span class=\"hljs-keyword\">module</span> <span class=\"hljs-string\">\"ecs_cluster\"</span> {\n source = <span class=\"hljs-string\">\"git::git@github.com:gruntwork-io/module-ecs.git//modules/ecs-cluster?ref=v1.0.8\"</span>\n\n <span class=\"hljs-comment\"># set the parameters for the ECS cluster module</span>\n}\n</pre>\n<p><em>Note: the double slash (<code>//</code>) is intentional and required. It's part of Terraform's Git syntax (see <a href=\"https://www.terraform.io/docs/modules/sources.html\" class=\"preview__body--description--blue\" target=\"_blank\">module\nsources</a>).</em></p>\n<p>See the module's documentation and <code>vars.tf</code> file for all the parameters you can set. Run <code>terraform get -update</code> to\npull the latest version of this module from this repo before runnin gthe standard <code>terraform plan</code> and\n<code>terraform apply</code> commands.</p>\n<h4 id=\"using-scripts-binaries\">Using scripts & binaries</h4>\n<p>You can install the scripts and binaries in the <code>modules</code> folder of any repo using the <a href=\"/repos/gruntwork-installer\" class=\"preview__body--description--blue\">Gruntwork\nInstaller</a>. For example, if the scripts you want to install are\nin the <code>modules/ecs-scripts</code> folder of the https://github.com/gruntwork-io/module-ecs repo, you could install them\nas follows:</p>\n<pre><span class=\"hljs-string\">gruntwork-install </span><span class=\"hljs-built_in\">--module-name</span> <span class=\"hljs-string\">\"ecs-scripts\"</span> <span class=\"hljs-built_in\">--repo</span> <span class=\"hljs-string\">\"https://github.com/gruntwork-io/module-ecs\"</span> <span class=\"hljs-built_in\">--tag</span> <span class=\"hljs-string\">\"0.0.1\"</span>\n</pre>\n<p>See the docs for each script & binary for detailed instructions on how to use them.</p>\n<h2 class=\"preview__body--subtitle\" id=\"background\">Background</h2>\n<h4 id=\"what-exactly-is-a-load-balancer\">What exactly is a load balancer?</h4>\n<p>A load balancer is usually the public-facing part of your infrastructure, receives incoming requests, makes a decision\non which backend service to route them to, and forwards the request.</p>\n<p>Load balancers can forward any kind of IP traffic, including TCP, UDP, HTTP, and HTTPS requests.</p>\n<h4 id=\"why-is-a-load-balancer-sometimes-called-a-reverse-proxy\">Why is a load balancer sometimes called a reverse proxy?</h4>\n<p>A "forward proxy" is a server that forwards incoming requests to an external party on your behalf. For example, a "web\nproxy" is a forward proxy that makes HTTP requests on your behalf and forwards you the results. This might be useful if\nyou want to hide your IP address from websites you request, or if your organization wants to scan all web traffic.</p>\n<p>A "reverse proxy" works in the opposite way. An external party makes an inbound request meant for a server, but instead\nof hitting that server directly, the request hits the "reverse proxy", which then forwards that request to some unknown\nbackend service, gets the result, and returns it to a client.</p>\n<p>It's conceptually identical to a load balancer, so "load balancer" and "reverse proxy" are synonyms.</p>\n<h4 id=\"why-are-load-balancers-needed\">Why are load balancers needed?</h4>\n<p>The simplest way to expose a service is to run a single server that runs your service. Users would then make requests\ndirectly to this server.</p>\n<p>This has the benefit of simplicity, but many drawbacks, too:</p>\n<ul>\n<li>It lacks "High Availability." If this server goes down, your app loses availability. You could just add more servers,\nbut users tend to access one IP address only.</li>\n<li>Your app server is in the public subnet, making it a much easier target for hackers.</li>\n<li>There may be cases when you want to route requests to a service other than this app server.</li>\n<li>You may want "out of the box" TLS/SSL connections and/or static asset caching, both of which reduce CPU load on your\napp server.</li>\n</ul>\n<p>A load balancer helps achieve all these properties:</p>\n<ul>\n<li>If a single backend service can fail, the load balancer can just route requests to a healthy one. For this reason, a\nload balancer usually includes a health check feature to determine if a backend service can receive requests and a way\nto register multiple backend service instances.</li>\n<li>A load balancer might sit in a public subnet, but backend services can reside in a private subnet, giving them\nadditional network isolation.</li>\n<li>A load balancer can inspect the network request it has received and make routing decisions based on its contents.</li>\n<li>A load balancer can terminate your TLS/SSL connection, cache static assets, and generally reduce load on your app server.</li>\n</ul>\n<p>And there are more benefits beyond this. A load balancer can be locked down more than an app server because it doesn't\nneed access to your data stores, it doesn't change very often (i.e. you don't deploy a new version of it every day like\nyou do with app code), and it doesn't typically need file-system access.</p>\n<h4 id=\"does-the-load-balancer-itself-need-to-be-high-availability\">Does the load balancer itself need to be High Availability?</h4>\n<p>Yes! Many clients make network requests using a DNS address like <code>service.acme.com</code>. If that DNS name resolves to a\nsingle IP address, then this IP address now becomes a single point of failure.</p>\n<p>There are typically two techniques for mitigating this. First, you can make sure that the DNS name <code>service.acme.com</code>\nresolves to two different IP addresses. Not all network clients will respond to two IP addresses in the same way, but\nmost browsers will immediately try the "second" IP address if the first one fails.</p>\n<p>Second, most networking today is <a href=\"https://www.opennetworking.org/sdn-resources/sdn-definition\" class=\"preview__body--description--blue\" target=\"_blank\">Software-Defined Networking</a>,\nwhich means that a single IP Address can be dynamically re-assigned to a server. Amazon supports this functionality\nthrough the concept of an <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html\" class=\"preview__body--description--blue\" target=\"_blank\">Elastic IP Address</a>.\nIn fact, an Elastic IP Address can typically be re-assigned to an EC2 Instance in as little as 7 seconds, though Amazon\ndoesn't officially guarantee this fast a transition.</p>\n<p>But implementing a dynamic Elastic IP Address failover is highly non-trivial. Fortunately, Amazon's managed load\nbalancers, the <a href=\"http://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html\" class=\"preview__body--description--blue\" target=\"_blank\">Application Load Balancer</a>\nand <a href=\"http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/introduction.html\" class=\"preview__body--description--blue\" target=\"_blank\">Classic Load Balancer</a>, already\nimplement High Availability by including automatic failover under the hood. Amazon's managed load balancers also include\nauto-scaling for when your load increases, though there are limits to how fast this can happen.</p>\n<p>In general, you should not be configuring your own load balancer (e.g. Nginx or HAProxy) unless you can make the case\nthat an existing managed load balancer solution will not meet your needs.</p>\n<h2 class=\"preview__body--subtitle\" id=\"developing-a-module\">Developing a module</h2>\n<h4 id=\"versioning\">Versioning</h4>\n<p>We follow the principles of <a href=\"http://semver.org/\" class=\"preview__body--description--blue\" target=\"_blank\">Semantic Versioning</a>. During initial development, the major\nversion is to 0 (e.g., <code>0.x.y</code>), which indicates the code does not yet have a stable API. Once we hit <code>1.0.0</code>, we will\nfollow these rules:</p>\n<ol>\n<li>Increment the patch version for backwards-compatible bug fixes (e.g., <code>v1.0.8 -> v1.0.9</code>).</li>\n<li>Increment the minor version for new features that are backwards-compatible (e.g., <code>v1.0.8 -> 1.1.0</code>).</li>\n<li>Increment the major version for any backwards-incompatible changes (e.g. <code>1.0.8 -> 2.0.0</code>).</li>\n</ol>\n<p>The version is defined using Git tags. Use GitHub to create a release, which will have the effect of adding a git tag.</p>\n<h4 id=\"tests\">Tests</h4>\n<p>See the <a href=\"/repos/v0.16.2/module-load-balancer/test\" class=\"preview__body--description--blue\">test</a> folder for details.</p>\n<h2 class=\"preview__body--subtitle\" id=\"license\">License</h2>\n<p>Please see <a href=\"/repos/v0.16.2/module-load-balancer/LICENSE.txt\" class=\"preview__body--description--blue\">LICENSE.txt</a> for details on how the code in this repo is licensed.</p>\n","repoName":"module-load-balancer","repoRef":"v0.16.2","serviceDescriptor":{"serviceName":"Elastic Load Balancer (ELB)","serviceRepoName":"module-load-balancer","serviceRepoOrg":"gruntwork-io","cloudProviders":["aws"],"description":"Deploy the Application Load Balancer (ALB) for load balancing HTTP and HTTPS, with support for routing rules and WebSockets.","imageUrl":"elastic.png","licenseType":"subscriber","technologies":["Terraform"],"compliance":[],"tags":[""]},"serviceCategoryName":"Networking","fileName":"README.md","filePath":"","title":"Repo Browser: Elastic Load Balancer (ELB)","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}