Docker Swarm部署中,如何让Apache访问客户端对应的Java应用服务器副本?
问题解答
我们先明确场景:Docker Swarm中运行2个Java应用服务器副本、2个带GSSAPI的Apache副本,通过Traefik做反向代理,需要实现Kerberos SSO的会话一致性(Apache认证后必须代理到客户端最初访问的那个应用实例)。
1. 能否将Apache实例与同节点的应用服务器实例配对访问?
可行。可以通过Docker Swarm的节点亲和性约束实现实例配对部署:
- 先给Swarm节点打标签,比如给运行app实例的节点分别打上
app-pair=1和app-pair=2; - 在
app和apache服务的deploy.placement.constraints中添加约束,让每个apache实例和对应的app实例调度到同一节点:# app服务的约束示例 placement: constraints: - node.labels.app-pair == 1 # apache服务对应节点的约束 placement: constraints: - node.labels.app-pair == 1 - 配对后,apache可以通过节点内部IP或者Docker Swarm的服务DNS+节点约束访问同节点的app实例(比如
http://app:8080会自动解析到同节点的app实例,因为Swarm内部DNS在同节点优先返回本地实例)。
2. 能否通过Traefik的粘性Cookie获取初始访问的主机信息?
可行,但需要额外配置。Traefik的粘性Cookie本身用于绑定会话到特定后端,但不会主动暴露主机信息,可通过以下方式实现:
- 配置Traefik在转发请求时,添加自定义请求头传递后端实例标识,比如在app服务的Traefik标签中添加:
- "traefik.http.middlewares.add-instance-header.headers.customrequestheaders.X-App-Instance={{.Name}}" - "traefik.http.routers.app.middlewares=add-instance-header@docker" - 当客户端首次访问app时,Traefik会把后端实例的名称(或IP)通过
X-App-Instance头传递给app;app重定向到/LogIn.form时,可以把这个实例标识附加到重定向URL的参数中(比如/LogIn.form?instance=app-1234); - Apache接收到请求后,解析URL参数获取实例标识,再代理到对应的app实例。
- 另外,确保app和apache服务的Traefik粘性Cookie配置完全一致(名称都是
AppCookie),这样客户端的Cookie会让Traefik把apache的请求也路由到同一节点/实例。
3. 能否配置Apache通过Traefik访问正确的应用服务器?
可行,核心是传递粘性Cookie保证路由一致性:
- 在Apache的配置中,启用
mod_proxy、mod_proxy_http和mod_headers模块; - 配置代理规则,将认证后的请求转发到Traefik的内部地址,同时传递客户端的
AppCookie:<Location /LogIn.form> # 这里省略Kerberos GSSAPI认证配置 ProxyPass http://traefik:80 ProxyPassReverse http://traefik:80 # 传递客户端的粘性Cookie给Traefik RequestHeader set Cookie "AppCookie=%{HTTP_COOKIE}e" # 保留Host头,确保Traefik匹配到正确的路由规则 ProxyPreserveHost On </Location> - 这样Traefik会根据接收到的
AppCookie,把请求路由到客户端最初访问的那个app实例,保证会话一致性。 - 注意:需要确保Traefik和Apache在同一个Docker网络(比如
traefik-public)中,Apache能解析到Traefik的服务名。
内容的提问来源于stack exchange,提问作者kab00m
相关产品推荐
相关产品推荐

