HaProxy 透明代理到 AWS S3 静态网站页面
HaProxy Transparent Proxy To AWS S3 Static Website Page
我正在使用 haproxy 来平衡服务器集群。我正在尝试向 haproxy 配置添加维护页面。我相信我可以通过在后端使用 'backup' 修饰符定义服务器声明来做到这一点。我的问题是,如何使用远程托管在 AWS S3 存储桶(静态网站)上的维护页面而不实际将用户重定向到该页面(即 haproxy 服务器 'redir' 定义)。
如果我有服务器:a、b、c。所有服务器都停机维护,然后我希望所有请求都通过服务器定义 d(标有 'backup')解析到 S3 上的静态地址。请注意,我不希望路径在 s3 上延续和评估,它应该始终呈现静态维护页面。
这绝对有可能。
首先,声明一个备份服务器,只有在 non-backup 服务器宕机时才会使用。
server s3-fallback example.com.s3-website-us-east-1.amazonaws.com:80 backup
以下配置条目用于修改请求或响应仅当我们使用备用路径时。我们在以下示例中使用了两个测试:
# { nbsrv le 1 } -- if the number of servers in this backend is <= 1
# (and)
# { srv_is_up(s3-fallback) } -- if the server named "s3-fallback" is up; "server name" is the arbitrary name we gave the server in the config file
# (which would mean it's the "1" server that is up for this backend)
所以,既然我们有了 backup
back-end,我们还需要一些其他指令。
无论请求路径如何,强制路径为 /
。
http-request set-path / if { nbsrv le 1 } { srv_is_up(s3-fallback) }
如果您使用的是一个带有错误文档的基本为空的存储桶,那么这并不是真正需要的,因为任何请求路径都会产生相同的错误。
接下来,我们需要在传出请求中设置Host:
header来匹配bucket的名称。如果存储桶的名称与我们从浏览器收到的请求中已经存在的 Host:
header 的名称相同,这在技术上是不需要的,但这可能仍然是一个好主意。如果存储桶名称不同,则需要转到此处。
http-request set-header host example.com if { nbsrv le 1 } { srv_is_up(s3-fallback) }
如果存储桶名称不是有效的 DNS 名称,那么您应该在此处包括整个网站端点。对于名为 "example" --
的存储桶
http-request set-header host example.s3-website-us-east-1.amazonaws.com if { nbsrv le 1 } { srv_is_up(s3-fallback) }
如果您的客户向您发送他们的 cookie,则无需将这些转发到 S3。如果客户端是 HTTPS 而 S3 连接是 HTTP,你肯定要去掉这些。
http-request del-header cookie if { nbsrv le 1 } { srv_is_up(s3-fallback) }
现在,处理响应...
您可能不希望浏览器缓存来自此备用 back-end 的响应。
http-response set-header cache-control no-cache if { nbsrv le 1 } { srv_is_up(s3-fallback) }
您可能也不希望 return 对这些响应“200 OK”,因为从技术上讲,您正在显示一个错误页面,并且您不希望搜索引擎尝试将这些内容编入索引.在这里,我选择了“503 服务不可用”,但任何有效的响应代码都可以使用...例如 500 或 502。
http-response set-status 503 if { nbsrv le 1 } { srv_is_up(s3-fallback) }
而且,你已经知道了——使用 S3 存储桶网站端点作为备份后端,其行为与任何其他后端没有区别。没有浏览器重定向。
您还可以将对 S3 的请求配置为使用 HTTPS,但由于您只是获取静态内容,所以这似乎没有必要。如果浏览器使用 HTTPS 连接到代理,那部分连接仍然是安全的,尽管您确实需要清除浏览器请求中的任何敏感内容,因为它会以未加密的方式转发到 S3(参见上面的 "cookie," ).
此解决方案已在 HAProxy 1.6.4 上进行测试。
请注意,默认情况下,S3 端点的 DNS 查找只会在 HAProxy 重新启动时完成。如果该 IP 地址发生变化,HAProxy 将看不到变化,无需额外配置——这超出了本问题的范围,但请参阅配置手册的 the resolvers
section。
我确实在几个不同的系统中使用 S3 作为 HAProxy 后面的 back-end 服务器,我发现这是解决许多不同问题的绝佳解决方案。
但是,如果您需要的话,有一种更简单的方法可以在所有后端都关闭时使用自定义错误页面。
errorfile 503 /etc/haproxy/errors/503.http
这个指令通常可以在全局配置中找到,但它在后端也有效——所以这个原始文件将被代理自动 returned 用于任何试图使用这个 [=87] 的请求=],如果此 back-end 中的所有服务器都不健康。
该文件是原始 HTTP 响应。它本质上只是写给客户端,因为它存在于磁盘上,处理为零,因此您必须包含所需的响应 header,包括 Connection: close
。 header 的每一行和 header 之后的每一行都必须以 \r\n
结尾才能成为有效的 HTTP 响应。您也可以只复制其中一个,然后根据需要进行修改。
这些文件受到响应缓冲区大小的限制,我相信 是 tune.bufsize,默认为 16,384 字节...所以它非常好对于小文件。
HTTP/1.0 503 Service Unavailable\r\n
Cache-Control: no-cache\r\n
Connection: close\r\n
Content-Type: text/plain\r\n
\r\n
This site is offline.
最后,请注意,尽管您想要 "transparently proxy a request,",但我认为短语 "transparent proxy" 不适合您要执行的操作,因为 "transparent proxy" 意味着客户端或服务器或两者都会在连接上看到彼此的 IP 地址,并认为他们正在直接通信,中间没有代理,因为代理 and/or 网络基础设施以隐藏代理在路径中的存在。这不是你要找的。
我正在使用 haproxy 来平衡服务器集群。我正在尝试向 haproxy 配置添加维护页面。我相信我可以通过在后端使用 'backup' 修饰符定义服务器声明来做到这一点。我的问题是,如何使用远程托管在 AWS S3 存储桶(静态网站)上的维护页面而不实际将用户重定向到该页面(即 haproxy 服务器 'redir' 定义)。
如果我有服务器:a、b、c。所有服务器都停机维护,然后我希望所有请求都通过服务器定义 d(标有 'backup')解析到 S3 上的静态地址。请注意,我不希望路径在 s3 上延续和评估,它应该始终呈现静态维护页面。
这绝对有可能。
首先,声明一个备份服务器,只有在 non-backup 服务器宕机时才会使用。
server s3-fallback example.com.s3-website-us-east-1.amazonaws.com:80 backup
以下配置条目用于修改请求或响应仅当我们使用备用路径时。我们在以下示例中使用了两个测试:
# { nbsrv le 1 } -- if the number of servers in this backend is <= 1
# (and)
# { srv_is_up(s3-fallback) } -- if the server named "s3-fallback" is up; "server name" is the arbitrary name we gave the server in the config file
# (which would mean it's the "1" server that is up for this backend)
所以,既然我们有了 backup
back-end,我们还需要一些其他指令。
无论请求路径如何,强制路径为 /
。
http-request set-path / if { nbsrv le 1 } { srv_is_up(s3-fallback) }
如果您使用的是一个带有错误文档的基本为空的存储桶,那么这并不是真正需要的,因为任何请求路径都会产生相同的错误。
接下来,我们需要在传出请求中设置Host:
header来匹配bucket的名称。如果存储桶的名称与我们从浏览器收到的请求中已经存在的 Host:
header 的名称相同,这在技术上是不需要的,但这可能仍然是一个好主意。如果存储桶名称不同,则需要转到此处。
http-request set-header host example.com if { nbsrv le 1 } { srv_is_up(s3-fallback) }
如果存储桶名称不是有效的 DNS 名称,那么您应该在此处包括整个网站端点。对于名为 "example" --
的存储桶http-request set-header host example.s3-website-us-east-1.amazonaws.com if { nbsrv le 1 } { srv_is_up(s3-fallback) }
如果您的客户向您发送他们的 cookie,则无需将这些转发到 S3。如果客户端是 HTTPS 而 S3 连接是 HTTP,你肯定要去掉这些。
http-request del-header cookie if { nbsrv le 1 } { srv_is_up(s3-fallback) }
现在,处理响应...
您可能不希望浏览器缓存来自此备用 back-end 的响应。
http-response set-header cache-control no-cache if { nbsrv le 1 } { srv_is_up(s3-fallback) }
您可能也不希望 return 对这些响应“200 OK”,因为从技术上讲,您正在显示一个错误页面,并且您不希望搜索引擎尝试将这些内容编入索引.在这里,我选择了“503 服务不可用”,但任何有效的响应代码都可以使用...例如 500 或 502。
http-response set-status 503 if { nbsrv le 1 } { srv_is_up(s3-fallback) }
而且,你已经知道了——使用 S3 存储桶网站端点作为备份后端,其行为与任何其他后端没有区别。没有浏览器重定向。
您还可以将对 S3 的请求配置为使用 HTTPS,但由于您只是获取静态内容,所以这似乎没有必要。如果浏览器使用 HTTPS 连接到代理,那部分连接仍然是安全的,尽管您确实需要清除浏览器请求中的任何敏感内容,因为它会以未加密的方式转发到 S3(参见上面的 "cookie," ).
此解决方案已在 HAProxy 1.6.4 上进行测试。
请注意,默认情况下,S3 端点的 DNS 查找只会在 HAProxy 重新启动时完成。如果该 IP 地址发生变化,HAProxy 将看不到变化,无需额外配置——这超出了本问题的范围,但请参阅配置手册的 the resolvers
section。
我确实在几个不同的系统中使用 S3 作为 HAProxy 后面的 back-end 服务器,我发现这是解决许多不同问题的绝佳解决方案。
但是,如果您需要的话,有一种更简单的方法可以在所有后端都关闭时使用自定义错误页面。
errorfile 503 /etc/haproxy/errors/503.http
这个指令通常可以在全局配置中找到,但它在后端也有效——所以这个原始文件将被代理自动 returned 用于任何试图使用这个 [=87] 的请求=],如果此 back-end 中的所有服务器都不健康。
该文件是原始 HTTP 响应。它本质上只是写给客户端,因为它存在于磁盘上,处理为零,因此您必须包含所需的响应 header,包括 Connection: close
。 header 的每一行和 header 之后的每一行都必须以 \r\n
结尾才能成为有效的 HTTP 响应。您也可以只复制其中一个,然后根据需要进行修改。
这些文件受到响应缓冲区大小的限制,我相信 是 tune.bufsize,默认为 16,384 字节...所以它非常好对于小文件。
HTTP/1.0 503 Service Unavailable\r\n
Cache-Control: no-cache\r\n
Connection: close\r\n
Content-Type: text/plain\r\n
\r\n
This site is offline.
最后,请注意,尽管您想要 "transparently proxy a request,",但我认为短语 "transparent proxy" 不适合您要执行的操作,因为 "transparent proxy" 意味着客户端或服务器或两者都会在连接上看到彼此的 IP 地址,并认为他们正在直接通信,中间没有代理,因为代理 and/or 网络基础设施以隐藏代理在路径中的存在。这不是你要找的。