Skip to content

Commit

Permalink
Merge pull request #15409 from pravisankar/egress-haproxy-mode
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue (batch tested with PRs 15409, 18763).

Support for DNS names in egress routes

Introduced dns-proxy egress router mode that allows specifying DNS name for EGRESS_DESTINATION.
Currently, dns-proxy egress mode implementation is based on HAProxy.
HAProxy 1.6+ version is used to leverage DNS resolution at runtime.

Trello Card: https://trello.com/c/407uoUFz
  • Loading branch information
openshift-merge-robot authored Mar 2, 2018
2 parents 6b73cc1 + 5a94143 commit 65dc8e1
Show file tree
Hide file tree
Showing 6 changed files with 468 additions and 0 deletions.
2 changes: 2 additions & 0 deletions hack/lib/constants.sh
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ readonly OS_ALL_IMAGES=(
openshift/origin-f5-router
openshift/origin-egress-router
openshift/origin-egress-http-proxy
openshift/origin-egress-dns-proxy
openshift/origin-recycler
openshift/origin-cluster-capacity
openshift/origin-service-catalog
Expand Down Expand Up @@ -366,6 +367,7 @@ function os::build::images() {
( os::build::image "${tag_prefix}" images/origin ) &
( os::build::image "${tag_prefix}-egress-router" images/egress/router ) &
( os::build::image "${tag_prefix}-egress-http-proxy" images/egress/http-proxy ) &
( os::build::image "${tag_prefix}-egress-dns-proxy" images/egress/dns-proxy ) &
( os::build::image "${tag_prefix}-federation" images/federation ) &

for i in `jobs -p`; do wait $i; done
Expand Down
1 change: 1 addition & 0 deletions images/egress/dns-proxy/.cccp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
job-id: origin-egress-dns-proxy
23 changes: 23 additions & 0 deletions images/egress/dns-proxy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#
# This is the egress router L4 DNS proxy for OpenShift Origin
#
# The standard name for this image is openshift/origin-egress-dns-proxy

FROM openshift/origin-base

# HAProxy 1.6+ version is needed to leverage DNS resolution at runtime.
RUN INSTALL_PKGS="haproxy18 rsyslog" && \
yum install -y $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
yum clean all && \
mkdir -p /var/lib/haproxy/{run,log} && \
mkdir -p /etc/haproxy && \
setcap 'cap_net_bind_service=ep' /usr/sbin/haproxy && \
chown -R :0 /var/lib/haproxy && \
chmod -R g+w /var/lib/haproxy && \
touch /etc/haproxy/haproxy.cfg

ADD egress-dns-proxy.sh /bin/egress-dns-proxy.sh

ENTRYPOINT /bin/egress-dns-proxy.sh

178 changes: 178 additions & 0 deletions images/egress/dns-proxy/egress-dns-proxy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/bin/bash

# OpenShift egress DNS proxy setup script

set -o errexit
set -o nounset
set -o pipefail

# Default DNS nameserver port
NS_PORT=53
CONF=/etc/haproxy/haproxy.cfg

BLANK_LINE_OR_COMMENT_REGEX="([[:space:]]*$|#.*)"
IPADDR_REGEX="[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+"
PORT_REGEX="[[:digit:]]+"
DOMAINNAME_REGEX="[[:alnum:]][[:alnum:]-]+?\.[[:alnum:].-]+"

function die() {
echo "$*" 1>&2
exit 1
}

function check_prereqs() {
if [[ -z "${EGRESS_DNS_PROXY_DESTINATION}" ]]; then
die "Must specify EGRESS_DNS_PROXY_DESTINATION"
fi
}

function validate_port() {
local port=$1
if [[ "${port}" -lt "1" || "${port}" -gt "65535" ]]; then
die "Invalid port: ${port}, must be in the range 1 to 65535"
fi
}

function generate_haproxy_defaults() {
echo "
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/lib/haproxy/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
defaults
log global
mode tcp
option dontlognull
option tcplog
option redispatch
retries 3
timeout http-request 100s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 100s
timeout check 10s
"
}

function generate_dns_resolvers() {
echo "resolvers dns-resolver"

# Fetch nameservers from /etc/resolv.conf
nameservers=()
nameservers=$(awk '/^nameserver/ {print $2}' /etc/resolv.conf)
n=0
for ns in ${nameservers[@]}; do
n=$(($n + 1))
echo " nameserver ns$n ${ns}:${NS_PORT}"
done

# Set default optional params
echo " resolve_retries 3"
echo " timeout retry 1s"
echo " hold valid 10s"
echo ""
}

function generate_haproxy_frontends_backends() {
local n=0
declare -A used_ports=()

while read dest; do
local port target targetport resolvers

if [[ "${dest}" =~ ^${BLANK_LINE_OR_COMMENT_REGEX}$ ]]; then
continue
fi
n=$(($n + 1))
resolvers=""

if [[ "${dest}" =~ ^${PORT_REGEX}\ +${IPADDR_REGEX}$ ]]; then
read port target <<< "${dest}"
targetport="${port}"
elif [[ "${dest}" =~ ^${PORT_REGEX}\ +${IPADDR_REGEX}\ +${PORT_REGEX}$ ]]; then
read port target targetport <<< "${dest}"
elif [[ "${dest}" =~ ^${PORT_REGEX}\ +${DOMAINNAME_REGEX}$ ]]; then
read port target <<< "${dest}"
targetport="${port}"
resolvers="resolvers dns-resolver"
elif [[ "${dest}" =~ ^${PORT_REGEX}\ +${DOMAINNAME_REGEX}\ +${PORT_REGEX}$ ]]; then
read port target targetport <<< "${dest}"
resolvers="resolvers dns-resolver"
else
die "Bad destination '${dest}'"
fi

validate_port ${port}
validate_port ${targetport}

if [[ "${used_ports[${port}]:-}" == "" ]]; then
used_ports[${port}]=1
else
die "Proxy port $port already used, must be unique for each destination"
fi

echo "
frontend fe$n
bind :${port}
default_backend be$n
backend be$n
server dest$n ${target}:${targetport} check $resolvers
"
done <<< "${EGRESS_DNS_PROXY_DESTINATION}"
}

function setup_haproxy_config() {
generate_haproxy_defaults
generate_dns_resolvers
generate_haproxy_frontends_backends
}

function setup_haproxy_syslog() {
local log_file="/var/lib/haproxy/log/haproxy.log"

cat >> /etc/rsyslog.conf <<EOF
module(load="imudp")
input(type="imudp" port="514")
EOF

echo "local2.* ${log_file}" >> /etc/rsyslog.d/haproxy.conf

/usr/sbin/rsyslogd
touch "${log_file}"
tail -f "${log_file}" &
}

function run() {

check_prereqs

rm -f "${CONF}"
setup_haproxy_config > "${CONF}"

if [[ -n "${EGRESS_DNS_PROXY_DEBUG:-}" ]]; then
setup_haproxy_syslog
fi

echo "Running haproxy with config:"
sed -e 's/^/ /' "${CONF}"
echo ""
echo ""

exec haproxy -f "${CONF}"
}

if [[ "${EGRESS_DNS_PROXY_MODE:-}" == "unit-test" ]]; then
check_prereqs
setup_haproxy_config
exit 0
fi

run
Loading

0 comments on commit 65dc8e1

Please sign in to comment.