构建一个基于Haproxy的7层代理
背景
某XX容器云平台不能使用Configmap与Secret,但是能传入环境变量。基于该条件,使用haproxy来构建一个通用的代理服务。
实现
创建docker-entrypoint.sh文件
#!/usr/bin/env bash
set -e
export LISTEN_PORT="${LISTEN_PORT:-8080}"
export SERVERS="${SERVERS:-localhost:8080}"
export CLIENT_TIMEOUT="${CLIENT_TIMEOUT:-10s}"
export LOAD_BALANCE_ALGORITHM="${LOAD_BALANCE_ALGORITHM:-roundrobin}"
export HEALTH_CHEK_URI="${HEALTH_CHECK_URI:-/healthz}"
export HEALTH_CHECK_INTERVAL="${HEALTH_CHECK_INTERVAL:-5s}"
export HEALTH_CHEK_CODE="${HEALTH_CHEK_CODE:-200}"
export HEALTH_CHECK_PORT="${HEALTH_CHECK_PORT:-8080}"
SERVERS_CONFIG=""
if [ -n "$SERVERS" ]; then
IFS=',' read -ra SERVER_LIST <<< "$SERVERS"
for i in "${!SERVER_LIST[@]}"; do
SERVERS_CONFIG+=" server s$((i+1)) ${SERVER_LIST[i]} check\n"
done
else
SERVERS_CONFIG=" server s1 localhost:8080 check\n"
fi
# 使用 envsubst 替换模板中的变量
envsubst < /usr/local/etc/haproxy/haproxy.cfg.tmpl | \
awk -v servers="$SERVERS_CONFIG" '{gsub(/# SERVERS_PLACEHOLDER/, servers); print}' > /usr/local/etc/haproxy/haproxy.cfg
# 启动 haproxy
exec haproxy -d -f /usr/local/etc/haproxy/haproxy.cfg "$@"创建haproxy模板文件 -- haproxy.cfg.tmpl
global
daemon
log stdout format raw local0 info
maxconn 10000
defaults
mode http
timeout connect 5s
timeout client 60s
timeout server 60s
log global
frontend health_frontend
bind *:10254
option dontlognull
monitor-uri /healthz
monitor fail if { nbsrv(servers) eq 0 }
frontend http
bind *:${LISTEN_PORT}
mode http
timeout client ${CLIENT_TIMEOUT}
default_backend servers
backend servers
mode http
# 启用 HTTP 健康检查
option httpchk
http-check send meth GET uri ${HEALTH_CHEK_URI} ver HTTP/1.1
http-check expect status ${HEALTH_CHEK_CODE}
default-server inter ${HEALTH_CHECK_INTERVAL} fall 3 rise 2
default-server check port ${HEALTH_CHECK_PORT}
# 负载均衡算法
balance ${LOAD_BALANCE_ALGORITHM}
# SERVERS_PLACEHOLDERDockerfile内容如下:
#FROM haproxy:3.2.10-alpine
FROM registry.cn-shenzhen.aliyuncs.com/shuhui/haproxy:3.2.10-alpine
LABEL maintainer="Qiu Shuhui<shuhui@vqiu.cn>" \
version="1.32.10"
USER root
COPY haproxy.cfg.tmpl /usr/local/etc/haproxy/haproxy.cfg.tmpl
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN set -xe \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
&& apk update upgrade \
&& apk add --no-cache procps tzdata bash gettext procps curl \
&& cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& rm -rf /var/cache/apk/* \
&& chmod +x /docker-entrypoint.sh \
&& chown haproxy:haproxy -R /usr/local/etc/haproxy/
USER haproxy
ENTRYPOINT ["/docker-entrypoint.sh"]使用docker运行个简单实例
# docker run -it -e SERVERS=172.20.10.11:8080,172.20.10.12:8080 -e HEALTH_CHEK_URI=/health 构建好的镜像