Nginx 代理运行在不同 CoreOS 节点上的许多容器

Nginx 代理运行在不同 CoreOS 节点上的许多容器

在网上,我找到了很多关于使用 Nginx/Confd(或 Haproxy 或 Vulcand)代理到同一主机上运行的不同 Docker 容器的教程。然而,我需要做的是不同的。以下是我的基础设施概述:

  • 一个有 5 个节点的在线 CoreOS 集群,所有节点都运行 etcd
  • 在集群的每个节点上都使用 fleet 启动不同的 Docker 容器(运行 WordPress 应用程序的 Nginx 网络服务器),无需暴露端口并在 etcd 上写入它们的 ips(使用 docker inspect 获取的 Docker ip)。
  • 如果某个节点发生故障,我的服务将自动转移到另一个可用节点

现在,我需要做的是,假设有一个 Nginx 代理,根据 vhost 将我的流量路由到各种容器。以下是示例:

Nginx(使用公共 IP)接收请求xxx.domain.com--> node-1-->container使用自动分配的 IP(监听端口 80)

Nginx(使用公共 IP)接收请求yyy.domain.com--> node-2-->container使用自动分配的 IP(监听端口 80)

这是我的问题:

  • 我的设想正确吗?我的想法有误吗?
  • 我的 Nginx 代理必须位于 CoreOS 集群之外?还是必须在每个 CoreOS 节点上运行它?
  • 我如何实现此配置?最好的方法是什么?

先感谢您!

答案1

您需要某种类型的服务发现,以便 nginx 能够“找到”节点上运行的容器。您可以在容器启动时将记录写入 etcd,并在退出时删除,然后让 nginx 检查这些记录。

对于移动服务,您可以查看车队以进行简单的调度。

答案2

我不知道我是否理解正确。但我的做法如下:

在集群外部放置一个负载均衡器(HAProxy、Nginx、Amazon ELB(如果您使用 EC2))来路由集群内部的每个流量。

在里面你可以尝试 Gogeta: https://github.com/arkenio/gogeta

它是一个全局运行(在每个节点上)的反向代理,并根据 etcd 中的域条目将流量路由到特定的容器。然后,您可以设置您的服务文件,向 gogeta 监控的 etcd 添加和删除它们的存在。

ExecStart=<do something>    
ExecStartPost=/usr/bin/etcdctl set /services/<your_service>/%i/location '{\"host\": "%H", \"port\": <your containers exposed port>}'

ExecStop=/usr/bin/docker stop <your service>
ExecStopPost=/usr/bin/etcdctl rm --recursive /services/<your_service>/%i

它工作正常,并使用轮询策略平衡请求负载。不过我提交了一个问题https://github.com/arkenio/gogeta/issues/10

这对你有帮助吗?

答案3

您可以使用 nginx、etcd 和 confd 三者来完成此操作。有一篇很棒的博客文章,标题为“使用 CoreOS、confd 和 nginx 进行负载平衡“引导您运行三个容器。

  1. 您需要一个共享的“数据”容器,您可以在其中存储动态生成的 nginx 配置
  2. 你需要一个运行的容器confd,它将读取来自etcd并为您动态生成 nginx 配置(这保存在共享“数据”容器的卷中)
  3. 最后,您将需要 nginx,它仅使用共享的“数据”卷进行配置。

关键是让每个 HTTP 后端通过 etcd 宣布自己,然后 confd 将获取更改并动态重新配置 nginx。这个过程与 @Julian 在上一个回答中提到的非常接近:

ExecStart=<do something>    
ExecStartPost=/usr/bin/etcdctl set /services/<your_service>/%i/location '{\"host\": "%H", \"port\": <your containers exposed port>}'

ExecStop=/usr/bin/docker stop <your service>
ExecStopPost=/usr/bin/etcdctl rm --recursive /services/<your_service>/%i

查看confd 模板文档欲了解更多示例,但您将获得大致如下的内容:

{{range $dir := lsdir "/services/web"}}
upstream {{base $dir}} {
    {{$custdir := printf "/services/web/%s/*" $dir}}{{range gets $custdir}}
    server {{$data := json .Value}}{{$data.IP}}:80;
    {{end}}
}

server {
    server_name {{base $dir}}.example.com;
    location / {
        proxy_pass {{base $dir}};
    }
}
{{end}}

需要注意的是,您只需要运行其中一个“三重奏”,除非您想要更高可用性的设置,在这种情况下您将需要两个或更多。当您使用 HA 时,您可能希望在它们前面放置一个 ELB 实例。

相关内容