【问题标题】:rolling deployment for docker containers behind load balancer在负载均衡器后面滚动部署 docker 容器
【发布时间】:2015-08-18 15:07:17
【问题描述】:

我在负载均衡器后面滚动部署 docker 容器时遇到问题。

这是我的 docker compose yml 文件内容。

nginx:
    image: nginx_image
    links:
        - node1:node1
        - node2:node2
        - node3:node3
    ports:
        - "80:80"
node1:
    image: nodeapi_image
    ports:
        - "8001"
node2:
    image: nodeapi_image
    ports:
        - "8001"
node3:
    image: nodeapi_image
    ports:
        - "8001"

这里是我的nginx.conf

worker_processes 4;

events { worker_connections 1024; }

http {

  upstream node-app {
        least_conn;
        server node1:8001 weight=10 max_fails=3 fail_timeout=30s;
        server node2:8001 weight=10 max_fails=3 fail_timeout=30s;
        server node3:8001 weight=10 max_fails=3 fail_timeout=30s;
  }

  server {
        listen 80;
        listen 443 ssl;

        # ssl    on;
        ssl_certificate     /etc/nginx/ssl/imago.io.chain.crt;
        ssl_certificate_key /etc/nginx/ssl/imago.io.key;

        location / {
          proxy_pass http://node-app;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        }
  }
}

如果我要部署一个新构建的映像,我必须停止一个节点容器,将其删除并使用新映像重新创建它。这里的问题是新容器将获得一个新 IP,而 nginx 容器不知道该新 IP,因此,如果我在重新创建最后一个容器后重新创建负载均衡器后面的 3 个容器,则应用程序将不再提供服务,因为所有 IP在 nginx 机器中 /etc/hosts 和环境变量不再是最新的。

我可以通过 SSH 连接到每个容器,通过从 git 存储库中提取来更新其代码并重新启动该过程,但这对我来说似乎是错误的。这样做的正确方法是什么?

【问题讨论】:

标签: deployment docker docker-compose


【解决方案1】:

有一种更简单的方法可以实现这一点,以下面的 docker-compose.yml 文件为例:

lb:
    image: tutum/haproxy
    links:
        - app
    ports:
        - "80:80"
app:
    image: tutum/hello-world

这个 docker compose 文件描述了两个服务:

  • lb:使用tutum/haproxy 映像的负载平衡器
  • app:监听 80 端口的示例 webapp

如果您天真地使用 docker-compose up -d 启动这些服务,您最终将只得到 2 个容器(负载均衡器和 Web 应用程序)。

但是如果你运行 docker-compose scale app=3 然后再次运行 docker-compose up -d,你最终会得到 4 个负载均衡的容器。

这里的关键角色是tutum/haproxy docker 镜像,它能够发现它链接到的不同容器。


类似的解决方案是使用Jason Wilder's nginx-proxy 图像,它的优点是可以实时发现新节点;这样您就不必重新启动 lb 服务。

lb:
    image: jwilder/nginx-proxy
    volumes:
        - /var/run/docker.sock:/tmp/docker.sock:ro
    ports:
        - "80:80"
app:
    image: tutum/hello-world
    environment:
        VIRTUAL_HOST: www.mysite.com

VIRTUAL_HOST 环境变量必须设置为解析为 docker 主机 IP 地址的域名。


另一种是使用Traefik

lb:
  image: traefik
  command: --docker
  ports:
    - "80:80"
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock

app:
  image: tutum/hello-world
  labels:
    traefik.frontend.rule: Host:www.mysite.com

traefik.frontend.rule 标签必须定义一个 Traefik rule 设置为解析为您的 docker 主机 IP 地址的域名。

Traefik 还提供不同的load balancing strategiescircuit breakers

【讨论】:

  • 好的,我明白了。虽然我喜欢你的回答,但似乎 tutum/haproxy 容器只有在你使用 tutum 时才能工作。另一种方法看起来不错,我会试一试。与此同时,我编写了一些代码,通过更新负载均衡器上的 /etc/hosts 并在完成后重新加载 nginx 或 haproxy 来解决问题。
  • tutum/haproxy 无处不在。不同之处在于它只有在托管在 tutum 托管服务上时才会实时更新。
  • 您只需运行docker-compose up -d lb,负载均衡器容器将被重新创建并会注意到新的应用程序容器
  • 好的,但这违背了在不停机的情况下运行部署的目的。它基本上等于杀死一切并重新创建它。
  • 是的,停机时间短,但仍然是停机时间。如果您使用jwilder/nginx-proxy 的解决方案,则无需停机
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多