Skip to content

Commit

Permalink
Merge beta features into master (#569)
Browse files Browse the repository at this point in the history
* Upgrade to haproxy 1.8.4 (#552)
* Use haproxy's new master worker, remove old iptables / sleep / lock hacks.
* ‼️ BREAKING CHANGE: you _must_ remove "daemon" form your custom HAPROXY_HEAD templates.
* upgrade libssl to version 1.1
* use the default gpg keyserver
* Error out with legacy HAPROXY_HEAD (daemon and expose-fd listeners)
* Beta state fix (#538)
* Add reload process which writes state file.
* Split out tini build/install
* config archiving (#532) (#550)
* Add LAST_MODIFIED to trigger new docker build (fix security vulns)
* Only add running tasks to backends
* Fix bug in config validation and reduce marathon calls
* Upgrade pip and setuptools
* Work around python3 > dh-python > dkpg-dev > make dependency
* filter by bad states rather than accepting only one good state
* Append reload command only if it doesn't exist already. (#566)
* Change filtering from list to set, push up in the stack so it's not re-created
* Bump label
  • Loading branch information
drewkerrigan authored Apr 12, 2018
1 parent 59b5693 commit 49afb4d
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 175 deletions.
14 changes: 7 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
FROM debian:buster

LABEL LAST_MODIFIED=20180403

# runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
inetutils-syslogd \
iptables \
libcurl3 \
liblua5.3-0 \
libssl1.0.2 \
libssl1.1 \
openssl \
procps \
python3 \
Expand All @@ -17,10 +18,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
make \
&& rm -rf /var/lib/apt/lists/*

ENV TINI_VERSION=v0.13.2 \
ENV TINI_VERSION=v0.16.1 \
TINI_GPG_KEY=595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7

# Multiple gpg --recv-keys are intended to help with flakiness of key servers.
RUN set -x \
&& apt-get update && apt-get install -y --no-install-recommends dirmngr gpg wget \
&& rm -rf /var/lib/apt/lists/* \
Expand All @@ -39,9 +39,9 @@ RUN set -x \
&& apt-get purge -y --auto-remove dirmngr gpg wget


ENV HAPROXY_MAJOR=1.7 \
HAPROXY_VERSION=1.7.6 \
HAPROXY_MD5=8f4328cf66137f0dbf6901e065f603cc
ENV HAPROXY_MAJOR=1.8 \
HAPROXY_VERSION=1.8.4 \
HAPROXY_MD5=540cd21169e8828d5d11894b2fa74ab4

COPY requirements.txt /marathon-lb/

Expand Down
3 changes: 1 addition & 2 deletions Longhelp.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,6 @@ and defaults.
**Default template for `HAPROXY_HEAD`:**
```
global
daemon
log /dev/log local0
log /dev/log local1 notice
spread-checks 5
Expand All @@ -381,7 +380,7 @@ global
ssl-default-bind-options no-sslv3 no-tlsv10 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:!aNULL:!MD5:!DSS
ssl-default-server-options no-sslv3 no-tlsv10 no-tls-tickets
stats socket /var/run/haproxy/socket
stats socket /var/run/haproxy/socket expose-fd listeners
server-state-file global
server-state-base /var/state/haproxy/
lua-load /marathon-lb/getpids.lua
Expand Down
3 changes: 1 addition & 2 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def load(self):
ConfigTemplate(name='HEAD',
value='''\
global
daemon
log /dev/log local0
log /dev/log local1 notice
spread-checks 5
Expand All @@ -56,7 +55,7 @@ def load(self):
DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:\
AES256-SHA256:!aNULL:!MD5:!DSS
ssl-default-server-options no-sslv3 no-tlsv10 no-tls-tickets
stats socket /var/run/haproxy/socket
stats socket /var/run/haproxy/socket expose-fd listeners
server-state-file global
server-state-base /var/state/haproxy/
lua-load /marathon-lb/getpids.lua
Expand Down
70 changes: 0 additions & 70 deletions haproxy_wrapper.py

This file was deleted.

64 changes: 47 additions & 17 deletions marathon_lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from itertools import cycle
from collections import defaultdict
from operator import attrgetter
from shutil import move
from shutil import move, copy
from tempfile import mkstemp

import dateutil.parser
Expand Down Expand Up @@ -367,6 +367,19 @@ def config(apps, groups, bind_http_https, ssl_certs, templater,
sslCerts=" ".join(map(lambda cert: "crt " + cert, _ssl_certs))
)

# This should handle situations where customers have a custom HAPROXY_HEAD
# that includes the 'daemon' flag or does not expose listener fds:
if 'daemon' in config or "expose-fd listeners" not in config:
upgrade_warning = '''\
Error in custom HAPROXY_HEAD template: \
In Marathon-LB 1.12, the default HAPROXY_HEAD section changed, please \
make the following changes to your custom template: Remove "daemon", \
Add "stats socket /var/run/haproxy/socket expose-fd listeners". \
More information can be found here: \
https://docs.mesosphere.com/services/marathon-lb/advanced/#global-template.\
'''
raise Exception(upgrade_warning)

userlists = str()
frontends = str()
backends = str()
Expand Down Expand Up @@ -1214,8 +1227,8 @@ def writeConfigAndValidate(
if validateConfig(haproxyTempConfigFile):
# Move into place
if haproxy_map:
moveTempFile(domain_temp_map_file, domain_map_file)
moveTempFile(app_temp_map_file, app_map_file)
moveTempFile(domain_temp_map_file, domain_map_file, "domain_map")
moveTempFile(app_temp_map_file, app_map_file, "app_map")

# Edit the config file again to point to the actual map paths
with open(haproxyTempConfigFile, 'w') as tempConfig:
Expand All @@ -1224,7 +1237,7 @@ def writeConfigAndValidate(
truncateMapFileIfExists(domain_map_file)
truncateMapFileIfExists(app_map_file)

moveTempFile(haproxyTempConfigFile, config_file)
moveTempFile(haproxyTempConfigFile, config_file, "hap_cfg")
return True
else:
return False
Expand Down Expand Up @@ -1267,8 +1280,18 @@ def validateConfig(haproxy_config_file):
return False


def moveTempFile(temp_file, dest_file):
def moveTempFile(temp_file, dest_file, tmp_filename):
# Replace the old file with the new from its temporary location
for suffix in range(args.archive_versions - 1, 0, -1):
tmp_src_file = "/tmp/" + tmp_filename + "." + str(suffix)
tmp_dest_file = "/tmp/" + tmp_filename + "." + str(suffix + 1)
if os.path.isfile(tmp_src_file):
logger.debug("Copying temp file %s to %s",
tmp_src_file, tmp_dest_file)
copy(tmp_src_file, tmp_dest_file)
logger.debug("Copying temp files %s to %s",
temp_file, "/tmp/" + tmp_filename + ".1")
copy(temp_file, "/tmp/" + tmp_filename + ".1")
logger.debug("moving temp file %s to %s", temp_file, dest_file)
move(temp_file, dest_file)

Expand Down Expand Up @@ -1420,6 +1443,9 @@ def get_apps(marathon, apps=[]):

logger.debug("got apps %s", [app["id"] for app in apps])

excluded_states = {'TASK_KILLING', 'TASK_KILLED',
'TASK_FINISHED', 'TASK_ERROR'}

marathon_apps = []
# This process requires 2 passes: the first is to gather apps belonging
# to a deployment group.
Expand Down Expand Up @@ -1589,6 +1615,13 @@ def get_apps(marathon, apps=[]):
task['id'])
continue

# 'state' will not be present in test cases.
# Should always be present in an actual cluster
if 'state' in task and task['state'] in excluded_states:
logger.warning("Ignoring non-running task " + task['id'] +
" with state " + task['state'])
continue

if marathon.health_check() and 'healthChecks' in app and \
len(app['healthChecks']) > 0:
alive = True
Expand Down Expand Up @@ -1641,7 +1674,6 @@ def regenerate_config(marathon, config_file, groups, bind_http_https,
generated_config = config(apps, groups, bind_http_https, ssl_certs,
templater, haproxy_map, domain_map_array,
app_map_array, config_file, group_https_by_vhost)

(changed, config_valid) = compareWriteAndReloadConfig(
generated_config, config_file, domain_map_array, app_map_array,
haproxy_map)
Expand All @@ -1657,7 +1689,6 @@ def regenerate_config(marathon, config_file, groups, bind_http_https,
app_map_array,
config_file,
group_https_by_vhost)

return apps


Expand Down Expand Up @@ -1696,7 +1727,6 @@ def make_config_valid_and_regenerate(marathon,
app_map_array,
haproxy_map,
group_https_by_vhost)

if not config_valid:
logger.warn(
"invalid configuration caused by app %s; "
Expand Down Expand Up @@ -1858,8 +1888,8 @@ def reload_existing_config(self):

def handle_event(self, event):
if event['eventType'] == 'status_update_event' or \
event['eventType'] == 'health_status_changed_event' or \
event['eventType'] == 'api_post_event':
event['eventType'] == 'health_status_changed_event' or \
event['eventType'] == 'api_post_event':
self.reset_from_tasks()

def handle_signal(self, sig, stack):
Expand All @@ -1879,18 +1909,15 @@ def get_arg_parser():
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--longhelp",
help="Print out configuration details",
action="store_true"
)
action="store_true")
parser.add_argument("--marathon", "-m",
nargs="+",
help="[required] Marathon endpoint, eg. " +
"-m http://marathon1:8080 http://marathon2:8080",
default=["http://master.mesos:8080"]
)
"-m http://marathon1:8080 http://marathon2:8080",
default=["http://master.mesos:8080"])
parser.add_argument("--haproxy-config",
help="Location of haproxy configuration",
default="/etc/haproxy/haproxy.cfg"
)
default="/etc/haproxy/haproxy.cfg")
parser.add_argument("--group",
help="[required] Only generate config for apps which"
" list the specified names. Use '*' to match all"
Expand All @@ -1917,6 +1944,9 @@ def get_arg_parser():
parser.add_argument("--sse", "-s",
help="Use Server Sent Events",
action="store_true")
parser.add_argument("--archive-versions",
help="Number of config versions to archive",
type=int, default=5)
parser.add_argument("--health-check", "-H",
help="If set, respect Marathon's health check "
"statuses before adding the app instance into "
Expand Down
5 changes: 5 additions & 0 deletions reload_haproxy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

socat /var/run/haproxy/socket - <<< "show servers state" > /var/state/haproxy/global

# "sv reload ${HAPROXY_SERVICE}" will be added here by /marathon-lb/run:
5 changes: 4 additions & 1 deletion run
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,18 @@ for arg in "$@"; do
ARGS="$ARGS $escaped"
done

grep -q -F -w "sv reload ${HAPROXY_SERVICE}" /marathon-lb/reload_haproxy.sh || echo "sv reload ${HAPROXY_SERVICE}" >> /marathon-lb/reload_haproxy.sh

cat > $LB_SERVICE/run << EOF
#!/bin/sh
exec 2>&1
sv status /marathon-lb/service/haproxy || exit 1
cd /marathon-lb
exec /marathon-lb/marathon_lb.py \
--syslog-socket $SYSLOG_SOCKET \
--haproxy-config /marathon-lb/haproxy.cfg \
--ssl-certs "${SSL_CERTS}" \
--command "sv reload ${HAPROXY_SERVICE}" \
--command "/marathon-lb/reload_haproxy.sh" \
$ARGS
EOF
chmod 755 $LB_SERVICE/run
Expand Down
Loading

0 comments on commit 49afb4d

Please sign in to comment.