Blue-Green
Load balancing across two services.
Images are clickable.
Manifests
services:
blue:
image: hashicorp/http-echo
deploy:
labels:
- "millau.enabled=true"
- "millau.hosts=company.com blue.local company.local"
- "millau.cert=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRVENDQWlrQ0ZIemVjY3FYaVg0V0ZNRXZUWklvUHdSUXQvZktNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GMHgKQ3pBSkJnTlZCQVlUQWtSRk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbApjbTVsZENCWGFXUm5hWFJ6SUZCMGVTQk1kR1F4RmpBVUJnTlZCQU1NRFdOdmJYQmhibmt1Ykc5allXd3dIaGNOCk1qVXdOVEEwTVRZd09ERXpXaGNOTWpZd05UQTBNVFl3T0RFeldqQmRNUXN3Q1FZRFZRUUdFd0pFUlRFVE1CRUcKQTFVRUNBd0tVMjl0WlMxVGRHRjBaVEVoTUI4R0ExVUVDZ3dZU1c1MFpYSnVaWFFnVjJsa1oybDBjeUJRZEhrZwpUSFJrTVJZd0ZBWURWUVFEREExamIyMXdZVzU1TG14dlkyRnNNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DCkFROEFNSUlCQ2dLQ0FRRUFsa01mMzRsZitjM1BtS2dvM09LbkN5L3Fjc0FSK1YxNVZQS1pUeU1id1VGQ0FLVGIKOUpic2Jha3pNWnAyVHlQTU53MmF5WXkyVGFtZ3JSNW92bUQzWlk3WmNSU2xKZVdIRXR6ZHN1OWkyc1dWeHFRaQpqWEtZa1ZqaXBSRE1RdERnWWlLN1Z1d25pNmFKWFlFNlAwN05ISVVYbVdRL1NyMERSL2ZRVkxJSzVqWFVidktoCmNYbnZsZWk3ck5takpxRXJ1Q3ppc1Q2dTBDWW1kdGlBZUxRbEdRZkt3bzBMVUh5bllVcmlQK3BiT05FRFF2eWEKTWgydThPdW1LUGdFaVI0czloZlFGNkFDL1BGaUhVQVd5R0dRS3BYMDJKK0R3eG5hc1hSbkwzMmNXYkFaanlkZgpTOVF5QUo3WWsvSUl2cDVSSzdKK05aaUxCbjZEYlNKNU03ZVJPUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBCkE0SUJBUUJLTW56QTkrU0FOVTFZNHdmR2FoK2MrTWpVSTA3UzZ6dHVWd3EvbEY3ZUxBVFNpUDc1cEJYOUUwR1AKd3dhMjY1SEVWUXFnVStmUHVLSlM4MFc5VUtxZGJxYVhQRHNlZng0MzBVc3cvUVVJYnhxTUVLTXZUcUpwcWk1NApMUlBjWHJCZTdvNzgyczFDUkF5UHpqNWJiRE1jeHlCVVdPeFFiQndZZ3UwY3ZnVFpTclRGWW1vbTRucnpiMCtmClA4eWZZMHRsTXFCYmo0Nm96Y0xaUU1JTFhLTWJVZlB2djZWVWlnYmoySFZ4aml3REQyL1B2elBwYnlsbnl5OXgKS1FlR1E5bU0xdm5wbm8valpCVjRqREg1OTV1UmNGNnFpY1JZYnNmdlZVWWwvNzhiREpxdXVmNHpwMHNIaks2egpCYlhHN29GV3pkQlJkQzBud0VXMGE4Q1FjVC9jCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
- "millau.key=LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ1dReC9maVYvNXpjK1kKcUNqYzRxY0xMK3B5d0JINVhYbFU4cGxQSXh2QlFVSUFwTnYwbHV4dHFUTXhtblpQSTh3M0RackpqTFpOcWFDdApIbWkrWVBkbGp0bHhGS1VsNVljUzNOMnk3MkxheFpYR3BDS05jcGlSV09LbEVNeEMwT0JpSXJ0VzdDZUxwb2xkCmdUby9UczBjaFJlWlpEOUt2UU5IOTlCVXNncm1OZFJ1OHFGeGVlK1Y2THVzMmFNbW9TdTRMT0t4UHE3UUppWjIKMklCNHRDVVpCOHJDalF0UWZLZGhTdUkvNmxzNDBRTkMvSm95SGE3dzY2WW8rQVNKSGl6MkY5QVhvQUw4OFdJZApRQmJJWVpBcWxmVFluNFBER2RxeGRHY3ZmWnhac0JtUEoxOUwxRElBbnRpVDhnaStubEVyc240MW1Jc0dmb050Cklua3p0NUU1QWdNQkFBRUNnZ0VBQlBUQjA1SjEvTHdZUi84ZGdGSC80SG5JNmRab3dWd0ZndC9EK0ZhazZJTGoKVHppSE5ZVStjTEsxbFk3YXJvVEJXUytCc0VkWXFNY2F0elNuOWl4Wll3RytZSzRNQ3RKWTJpNXJqbG02S3BOOAorNVVYN3FqUTlkUHFURGQ1bnRxT2NucjhZdHpEOTR3QjJLdXZTMWRDMWorVDh1TkFYL2hNQWM3ZmVEaDZVNDEyCkJvZFhpL1g3L0VnV05BQko3d3BBWXFheGNaN1ZneUMvMVZkYzNRcUlPL2d3dDdPYzFpVHhUYkh5R1VRUnZaTFAKSkJaY2N4OUN4MzM1YWdHNFN1anJKUEZTa0pab1FHWkZQMFpBbUw3UkxPTlI1WFJXeGNzSGdQejNNTi9lVlhOeApzUSszRTJxYUc5eC81UDUrWnBaQ2M4YUxUSll4a0htL3d2TldkRkxHWVFLQmdRQzgwTFQzMFZZQ3R5UzZRbWRnClJUREtEa2xiQm41ZGxjamJjK1lFQzF0dnQzc2V6aDM2eTJ0Ym5aOXdDSWYreFcxVUEvOEN6bE9MbGtDRjdsT3EKMWV3MEFuZlU4OGdGaE4vMitNZXg4djVNcTk3Z1dOOTFPRHk2RCtyNk9LYTU5NEpKL0ZuRkZSS1VzcEtSYlV2MQpHOFdqSjFJaFQrU1JOY1gwYUlqbzB6NUlRd0tCZ1FETHVwallhczZwVlVoYWoyTEhPVDdOcVF6c0R5WEwrV0xSCkJGNXNYaEhJZ2ViaHlGYW14Q1Z5ZkpyOEtjUzZuekRwWEVjOU5PemZxaW9xZHJmSTgwbmptbW81Y2Z6WFZXQ0cKVnpmTEZrTXp0U0o1bURhK3RGYUgvczMvNG54bTl1Z3VLZGxWb0h0cTVLclFpeFJXSFJWaCt2a3phRVlaL3lIaQorVDRRVW43VzB3S0JnQ0RIMDBOYkVxV3lDaXhVTHdKbHdNeXpva1N0WWU3NWZEK3RaWGU2U1F1aVBUdmg2UTZMCmxuMzNaYURidWxDZkVoWU9BNDRIS0RZSnhmWDZwSWY2VCtIUHMrSkMySzBzbm4yUVA0dERkcWIxQitMSFN6UmMKcVI1Y2VSMHNETFlvcEhRWDNiWDdySmdvVUkzeS9jYjJKVi9vQ2JoQzJKbmxUaExhdXpwQXdvVmxBb0dCQUx1OApMNnorZjRJN1BIbDNPQ2N0OFZuRE5rMHhpRHIyak1EZnJjTmV6RFJnd0VtL08xcGgxY0F5WXYrTDNlVzdYRzh1CndkYjlObXJGZkNXMVVKYTAycG9LYVdpV1NkQ0V0SFlYV1Nxa1VUa002Yi96TEQrQUgxMGl5T0hMNjZkV1Q0NTYKc2ZQZDl0MEI2d1pSbzJQWFdTVDVDVHIrRTl0UTZBRW9mTEM5MUhSUkFvR0FlR3dCWU9xUmxvTkprNk12dkxNdgpQZVBueXNQVkp5UmFQeFkremJObWZxa283ZldaSjRLOWRZc2ZQRkhybEVQVVpoN0E3YUFVQnQ0d3dRU2EyM2RXCml2Z1hmd2Nic05oWTZUckxBRDdTWHJwUkFHeDlkOTN5aXRTWnZLdmo3Sm9qUkljVytUNjVNVFNVeXJva29lU2YKS0t0dlVCenpTZklQY3Z3aFFoZDRWTU09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
- "millau.port=9000"
- "millau.path=/api/"
command: ["-listen=:9000", "-text=blue"]
ports:
- "9000"
networks:
- millau
green:
image: hashicorp/http-echo
deploy:
labels:
- "millau.enabled=true"
- "millau.hosts=company.com green.local company.local"
- "millau.cert=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRVENDQWlrQ0ZIemVjY3FYaVg0V0ZNRXZUWklvUHdSUXQvZktNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1GMHgKQ3pBSkJnTlZCQVlUQWtSRk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbApjbTVsZENCWGFXUm5hWFJ6SUZCMGVTQk1kR1F4RmpBVUJnTlZCQU1NRFdOdmJYQmhibmt1Ykc5allXd3dIaGNOCk1qVXdOVEEwTVRZd09ERXpXaGNOTWpZd05UQTBNVFl3T0RFeldqQmRNUXN3Q1FZRFZRUUdFd0pFUlRFVE1CRUcKQTFVRUNBd0tVMjl0WlMxVGRHRjBaVEVoTUI4R0ExVUVDZ3dZU1c1MFpYSnVaWFFnVjJsa1oybDBjeUJRZEhrZwpUSFJrTVJZd0ZBWURWUVFEREExamIyMXdZVzU1TG14dlkyRnNNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DCkFROEFNSUlCQ2dLQ0FRRUFsa01mMzRsZitjM1BtS2dvM09LbkN5L3Fjc0FSK1YxNVZQS1pUeU1id1VGQ0FLVGIKOUpic2Jha3pNWnAyVHlQTU53MmF5WXkyVGFtZ3JSNW92bUQzWlk3WmNSU2xKZVdIRXR6ZHN1OWkyc1dWeHFRaQpqWEtZa1ZqaXBSRE1RdERnWWlLN1Z1d25pNmFKWFlFNlAwN05ISVVYbVdRL1NyMERSL2ZRVkxJSzVqWFVidktoCmNYbnZsZWk3ck5takpxRXJ1Q3ppc1Q2dTBDWW1kdGlBZUxRbEdRZkt3bzBMVUh5bllVcmlQK3BiT05FRFF2eWEKTWgydThPdW1LUGdFaVI0czloZlFGNkFDL1BGaUhVQVd5R0dRS3BYMDJKK0R3eG5hc1hSbkwzMmNXYkFaanlkZgpTOVF5QUo3WWsvSUl2cDVSSzdKK05aaUxCbjZEYlNKNU03ZVJPUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBCkE0SUJBUUJLTW56QTkrU0FOVTFZNHdmR2FoK2MrTWpVSTA3UzZ6dHVWd3EvbEY3ZUxBVFNpUDc1cEJYOUUwR1AKd3dhMjY1SEVWUXFnVStmUHVLSlM4MFc5VUtxZGJxYVhQRHNlZng0MzBVc3cvUVVJYnhxTUVLTXZUcUpwcWk1NApMUlBjWHJCZTdvNzgyczFDUkF5UHpqNWJiRE1jeHlCVVdPeFFiQndZZ3UwY3ZnVFpTclRGWW1vbTRucnpiMCtmClA4eWZZMHRsTXFCYmo0Nm96Y0xaUU1JTFhLTWJVZlB2djZWVWlnYmoySFZ4aml3REQyL1B2elBwYnlsbnl5OXgKS1FlR1E5bU0xdm5wbm8valpCVjRqREg1OTV1UmNGNnFpY1JZYnNmdlZVWWwvNzhiREpxdXVmNHpwMHNIaks2egpCYlhHN29GV3pkQlJkQzBud0VXMGE4Q1FjVC9jCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
- "millau.key=LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ1dReC9maVYvNXpjK1kKcUNqYzRxY0xMK3B5d0JINVhYbFU4cGxQSXh2QlFVSUFwTnYwbHV4dHFUTXhtblpQSTh3M0RackpqTFpOcWFDdApIbWkrWVBkbGp0bHhGS1VsNVljUzNOMnk3MkxheFpYR3BDS05jcGlSV09LbEVNeEMwT0JpSXJ0VzdDZUxwb2xkCmdUby9UczBjaFJlWlpEOUt2UU5IOTlCVXNncm1OZFJ1OHFGeGVlK1Y2THVzMmFNbW9TdTRMT0t4UHE3UUppWjIKMklCNHRDVVpCOHJDalF0UWZLZGhTdUkvNmxzNDBRTkMvSm95SGE3dzY2WW8rQVNKSGl6MkY5QVhvQUw4OFdJZApRQmJJWVpBcWxmVFluNFBER2RxeGRHY3ZmWnhac0JtUEoxOUwxRElBbnRpVDhnaStubEVyc240MW1Jc0dmb050Cklua3p0NUU1QWdNQkFBRUNnZ0VBQlBUQjA1SjEvTHdZUi84ZGdGSC80SG5JNmRab3dWd0ZndC9EK0ZhazZJTGoKVHppSE5ZVStjTEsxbFk3YXJvVEJXUytCc0VkWXFNY2F0elNuOWl4Wll3RytZSzRNQ3RKWTJpNXJqbG02S3BOOAorNVVYN3FqUTlkUHFURGQ1bnRxT2NucjhZdHpEOTR3QjJLdXZTMWRDMWorVDh1TkFYL2hNQWM3ZmVEaDZVNDEyCkJvZFhpL1g3L0VnV05BQko3d3BBWXFheGNaN1ZneUMvMVZkYzNRcUlPL2d3dDdPYzFpVHhUYkh5R1VRUnZaTFAKSkJaY2N4OUN4MzM1YWdHNFN1anJKUEZTa0pab1FHWkZQMFpBbUw3UkxPTlI1WFJXeGNzSGdQejNNTi9lVlhOeApzUSszRTJxYUc5eC81UDUrWnBaQ2M4YUxUSll4a0htL3d2TldkRkxHWVFLQmdRQzgwTFQzMFZZQ3R5UzZRbWRnClJUREtEa2xiQm41ZGxjamJjK1lFQzF0dnQzc2V6aDM2eTJ0Ym5aOXdDSWYreFcxVUEvOEN6bE9MbGtDRjdsT3EKMWV3MEFuZlU4OGdGaE4vMitNZXg4djVNcTk3Z1dOOTFPRHk2RCtyNk9LYTU5NEpKL0ZuRkZSS1VzcEtSYlV2MQpHOFdqSjFJaFQrU1JOY1gwYUlqbzB6NUlRd0tCZ1FETHVwallhczZwVlVoYWoyTEhPVDdOcVF6c0R5WEwrV0xSCkJGNXNYaEhJZ2ViaHlGYW14Q1Z5ZkpyOEtjUzZuekRwWEVjOU5PemZxaW9xZHJmSTgwbmptbW81Y2Z6WFZXQ0cKVnpmTEZrTXp0U0o1bURhK3RGYUgvczMvNG54bTl1Z3VLZGxWb0h0cTVLclFpeFJXSFJWaCt2a3phRVlaL3lIaQorVDRRVW43VzB3S0JnQ0RIMDBOYkVxV3lDaXhVTHdKbHdNeXpva1N0WWU3NWZEK3RaWGU2U1F1aVBUdmg2UTZMCmxuMzNaYURidWxDZkVoWU9BNDRIS0RZSnhmWDZwSWY2VCtIUHMrSkMySzBzbm4yUVA0dERkcWIxQitMSFN6UmMKcVI1Y2VSMHNETFlvcEhRWDNiWDdySmdvVUkzeS9jYjJKVi9vQ2JoQzJKbmxUaExhdXpwQXdvVmxBb0dCQUx1OApMNnorZjRJN1BIbDNPQ2N0OFZuRE5rMHhpRHIyak1EZnJjTmV6RFJnd0VtL08xcGgxY0F5WXYrTDNlVzdYRzh1CndkYjlObXJGZkNXMVVKYTAycG9LYVdpV1NkQ0V0SFlYV1Nxa1VUa002Yi96TEQrQUgxMGl5T0hMNjZkV1Q0NTYKc2ZQZDl0MEI2d1pSbzJQWFdTVDVDVHIrRTl0UTZBRW9mTEM5MUhSUkFvR0FlR3dCWU9xUmxvTkprNk12dkxNdgpQZVBueXNQVkp5UmFQeFkremJObWZxa283ZldaSjRLOWRZc2ZQRkhybEVQVVpoN0E3YUFVQnQ0d3dRU2EyM2RXCml2Z1hmd2Nic05oWTZUckxBRDdTWHJwUkFHeDlkOTN5aXRTWnZLdmo3Sm9qUkljVytUNjVNVFNVeXJva29lU2YKS0t0dlVCenpTZklQY3Z3aFFoZDRWTU09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
- "millau.port=9000"
- "millau.path=/api/"
command: ["-listen=:9000", "-text=green"]
ports:
- "9000"
networks:
- millau
red:
image: hashicorp/http-echo
deploy:
labels:
- "millau.enabled=false"
- "millau.hosts=company.com company.local"
- "millau.port=9000"
- "millau.path=/api/"
command: ["-listen=:9000", "-text=red"]
ports:
- "9000"
networks:
- millau
other:
image: hashicorp/http-echo
command: ["-listen=:9000", "-text=other"]
ports:
- "9000"
networks:
millau:
external: true
Features
Load Balancing
curl -i -H 'Host: company.com' localhost:8080/api/
returns HTTP 200
and responds from the blue
or green
services due to multiple host matching.
No Load Balancing
The service red
excluded from the load balancing. The service other
is not controlled by Millau at all.
Host and Path Matching
curl -i -H 'Host: green.local' localhost:8080/api/
returns HTTP 200
and responds from the green
service only due to single host matching.
curl -i -H 'Host: blue.local' localhost:8080/api/
returns HTTP 200
and responds from the blue
service only due to single host matching.
No Matching
curl -i -H 'Host: company.locall' localhost:8080
returns HTTP 502 No matching services found
because there is no matching host.
curl -i -H 'Host: company.local' localhost:8080/apii/
returns HTTP 502 No matching services found
because there is no matching path.
TLS Termination
curl -k --resolve company.local:8443:127.0.0.1 --connect-to company.local:8443 -H 'Host: company.local' https://company.local:8443/api/
curl -k --http2 --resolve company.local:8443:127.0.0.1 --connect-to company.local:8443 -H 'Host: company.local' https://company.local:8443/api/
returns HTTP 200
and responds from the blue
or green
services due to multiple host matching.
This HTTPS request uses s self-signed TLS certificate issued to company.local
.
The labels millau.cert
and millau.key
contain the certificate components encoded in base64
.