2 min read

构建一个基于Haproxy的7层代理

构建一个基于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_PLACEHOLDER

Dockerfile内容如下:

#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 构建好的镜像