Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCP Health Checks Draining & PROXY #748

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion jobs/haproxy/templates/drain.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,27 @@ echo "disable frontend health_check_http_url" | /usr/local/bin/socat stdio unix-
<%- if p("ha_proxy.expect_proxy_cidrs", []).size > 0 -%>
echo "disable frontend health_check_http_url_proxy_protocol" | /usr/local/bin/socat stdio unix-connect:${sockfile}
<%- end -%>
<%- end -%>
<%
tcp = p("ha_proxy.tcp")
if_link("tcp_backend") do |tcp_backend|
tcp << {
"name" => tcp_backend.instances.first.name || "link",
"backend_servers" => tcp_backend.instances.map(&:address),
"backend_servers_local" => tcp_backend.instances.select{ |n| n.az == spec.az }.map(&:address),
"port" => tcp_backend.p("port", p("ha_proxy.tcp_link_port")),
"backend_port" => tcp_backend.p("backend_port", p("ha_proxy.tcp_link_port")),
"health_check_http" => tcp_backend.p("health_check_http", p("ha_proxy.tcp_link_health_check_http", nil))
}
end -%>
<%- tcp.each do |tcp_proxy| -%>
echo "disable frontend health_check_http_tcp-<%= tcp_proxy["name"] %>" | /usr/local/bin/socat stdio unix-connect:${sockfile}
<%- end -%>

<%- if p("ha_proxy.enable_health_check_http") || tcp.size > 0 -%>
echo "$(date): triggering grace period for process ${haproxy_master_pid}" >> ${logfile}
sleep <%= p("ha_proxy.drain_frontend_grace_time") %>
<%- end -%>
<% end %>

touch ${lockfile}
kill -USR1 "${haproxy_master_pid}"
Expand Down
12 changes: 12 additions & 0 deletions jobs/haproxy/templates/haproxy.config.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1040,8 +1040,20 @@ listen health_check_http_tcp-<%= tcp_proxy["name"] %>
bind :<%= tcp_proxy["health_check_http"] %>
mode http
monitor-uri /health
<%- if p("ha_proxy.accept_proxy") && !p("ha_proxy.disable_health_check_proxy") -%>
tcp-request connection expect-proxy layer4 unless LOCALHOST
<%- end -%>
acl tcp-<%= tcp_proxy["name"] %>-routers_down nbsrv(tcp-<%= tcp_proxy["name"] %>) eq 0
monitor fail if tcp-<%= tcp_proxy["name"] %>-routers_down

<%- if p("ha_proxy.expect_proxy_cidrs", []).size > 0 -%>
listen health_check_http_tcp-<%= tcp_proxy["name"] %>_proxy_protocol
bind :<%= tcp_proxy["health_check_http"] + 1 %> accept-proxy
mode http
monitor-uri /health
acl tcp-<%= tcp_proxy["name"] %>-routers_down nbsrv(tcp-<%= tcp_proxy["name"] %>) eq 0
monitor fail if tcp-<%= tcp_proxy["name"] %>-routers_down
<%- end -%>
<%- end -%>
<% end -%>

Expand Down
44 changes: 44 additions & 0 deletions spec/haproxy/templates/drain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
describe 'bin/drain' do
let(:template) { haproxy_job.template('bin/drain') }

let(:backend_tcp_link) do
Bosh::Template::Test::Link.new(
name: 'tcp_backend',
instances: [Bosh::Template::Test::LinkInstance.new(address: 'postgres.backend.com', name: 'postgres')]
)
end

describe 'ha_proxy.drain_enable' do
context 'when enabled' do
it 'includes drain logic' do
Expand Down Expand Up @@ -32,6 +39,43 @@
expect(drain).to include('socat')
end

context 'when tcp backends are defined' do
it 'includes drain and grace logic' do
drain = template.render(
{
'ha_proxy' => {
'drain_enable' => true,
'tcp' => [{
'name' => 'redis',
'port' => 6379,
'backend_servers' => ['10.0.0.1', '10.0.0.2'],
'health_check_http' => 2223
}]
}
}
)
expect(drain).not_to include('drain is disabled')
expect(drain).to include('socat')
expect(drain).to include('disable frontend health_check_http_tcp-redis')
end
end

context 'when tcp backends consumed via link' do
it 'includes drain and grace logic' do
drain = template.render(
{
'ha_proxy' => {
'drain_enable' => true,
'tcp_link_port' => 5432
}
}, consumes: [backend_tcp_link]
)
expect(drain).not_to include('drain is disabled')
expect(drain).to include('socat')
expect(drain).to include('disable frontend health_check_http_tcp-postgres')
end
end

context 'when PROXY CIDRs are provided' do
it 'includes the PROXY frontend in drain logic' do
drain = template.render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@
'name' => 'redis',
'port' => 6379,
'backend_servers' => ['10.0.0.1', '10.0.0.2'],
'ssl' => true
'ssl' => true,
'health_check_http' => 9095
}, {
'name' => 'mysql',
'port' => 3306,
Expand Down Expand Up @@ -135,6 +136,10 @@
expect(frontend_tcp_mysql).to include('bind :3306')
expect(frontend_tcp_mysql).to include('tcp-request connection expect-proxy layer4 if { src -f /var/vcap/jobs/haproxy/config/expect_proxy_cidrs.txt }')
end

it 'adds a _proxy_protocol health check' do
expect(haproxy_conf['listen health_check_http_tcp-redis_proxy_protocol']).to include('bind :9096 accept-proxy')
end
end
end

Expand Down