全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
容器服务

自定义路由-简单示例

更新时间:2017-07-14 15:30:15

此示例会部署一个 acs/proxy 容器,对外通过负载均衡实例(使用 lb 标签)暴露服务,同时在后端挂载一个 nginx,本示例只展示 nginx 的首页,但是会在基本示例的基础上,逐步增加其他功能。

注意:任何两个不同的服务均不能共享使用同一个负载均衡,否则会导致负载均衡后端机器被删除,服务不可用。

基本示例

compose 模板如下所示。

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. appone:
  17. expose: # 被代理的服务一定要使用 expose 或者 ports 告诉 proxy 容器暴露哪个端口
  18. - 80/tcp
  19. image: 'nginx:latest'
  20. labels:
  21. # 此处支持 http/https/ws/wss 协议,必须使用用户自己的域名而不是容器服务提供的测试域名
  22. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  23. restart: always

服务启动成功后,页面如下图所示。

Screen_Shot_2016_09_10_at_2_28_08_PM

开启会话保持

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. appone:
  17. ports:
  18. - 80/tcp
  19. - 443/tcp
  20. image: 'nginx:latest'
  21. labels:
  22. # 此处支持 http/https/ws/wss 协议
  23. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  24. # 此处支持会话保持,使用 cookie 的方式,键为 CONTAINERID
  25. aliyun.proxy.COOKIE: "CONTAINERID insert indirect"
  26. restart: always

自定义 503 页面

当直接输入负载均衡的 VIP 地址而不是域名时,访问的页面如下图所示,返回 503 错误页面。

Screen_Shot_2016_09_10_at_2_31_55_PM

如果希望在 503 页面增加一些提示信息,可以在容器所在的 vm 中增加文件夹 /errors,同时增加文件 /errors/503.http,文件内容如下:

  1. HTTP/1.0 503 Service Unavailable
  2. Cache-Control: no-cache
  3. Connection: close
  4. Content-Type: text/html;charset=UTF-8
  5. <html><body><h1>503 Service Unavailable</h1>
  6. <h3>No server is available to handle this request.</h3>
  7. <h3>如果您看到这个页面,说明您访问服务出现了问题,请按如下步骤排查解决问题:</h3>
  8. <li>如果您是应用的访问者,请寻求应用的维护者解决问题。</li>
  9. <li>如果您是应用的维护者,继续查看下面的信息。</li>
  10. <li>您现在使用的是简单路由服务,整个请求会从SLB -> acsrouting应用容器 -> 您的应用容器, 请按下列步骤排查。</li>
  11. <li>请登录容器服务控制台,在左侧边栏选择"服务",在"服务列表"选择相应的"集群",单击暴露到公网的"服务",查看服务的"访问端点",仔细检查您的访问域名与在相应的服务中配置的域名是否一致。</li>
  12. <li>按照<a href="https://help.aliyun.com/knowledge_detail/42660.html">简单路由服务链路排查</a>进行问题定位和排查。</li>
  13. <li>查看<a href="https://help.aliyun.com/knowledge_detail/42658.html">路由常见问题文档</a>。</li>
  14. <li>如果上面的方式还没有解决您的问题,请<a href="https://workorder.console.aliyun.com/#/ticket/add?productId=1254">提交工单</a>,联系技术人员协助解决,我们会竭诚为您服务。</li>
  15. </body></html>

您可以修改为您需要展示的错误页面。修改 compose 模板如下:

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. EXTRA_FRONTEND_SETTINGS_80: "errorfile 503 /usr/local/etc/haproxy/errors/503.http"
  17. volumes:
  18. - /errors/:/usr/local/etc/haproxy/errors/
  19. appone:
  20. ports:
  21. - 80/tcp
  22. - 443/tcp
  23. image: 'nginx:latest'
  24. labels:
  25. # 配置 URL,支持指定 path,此处支持 http/https/ws/wss 协议
  26. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  27. restart: always

输入负载均衡的 VIP 地址之后,显示的 503 页面如下图所示。

Screen_Shot_2016_09_10_at_2_47_49_PM

支持泛域名

如果希望 nginx 的后端支持泛域名,即 appone.example.com 能访问到 nginx 首页,*.example.com 也能访问到 nginx 的首页,修改配置如下即可。

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. EXTRA_FRONTEND_SETTINGS_80: "errorfile 503 /usr/local/etc/haproxy/errors/503.http"
  17. volumes:
  18. - /errors/:/usr/local/etc/haproxy/errors/
  19. appone:
  20. ports:
  21. - 80/tcp
  22. - 443/tcp
  23. image: 'nginx:latest'
  24. labels:
  25. # 配置 URL,支持指定 path,此处支持 http/https/ws/wss 协议
  26. aliyun.proxy.VIRTUAL_HOST: "http://*.example.com"
  27. restart: always

绑定 host,输入域名 www.example.com 之后,显示 nginx 首页如下图所示。

Screen_Shot_2016_09_10_at_3_01_49_PM

配置默认的后端

如果希望直接通过 IP 也能访问到后端的 nginx,把 URL 配置去掉,修改配置如下即可。

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*" 表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. # 返回 503 时,指定错误页面
  17. EXTRA_FRONTEND_SETTINGS_80: "errorfile 503 /usr/local/etc/haproxy/errors/503.http"
  18. volumes:
  19. # 从主机挂载错误页面到容器内部
  20. - /errors/:/usr/local/etc/haproxy/errors/
  21. appone:
  22. ports:
  23. - 80/tcp
  24. - 443/tcp
  25. image: 'nginx:latest'
  26. labels:
  27. # 表明该服务需要通过 proxy 来代理
  28. aliyun.proxy.required: "true"
  29. restart: always

输入负载均衡的 VIP 之后,显示 nginx 首页如下图所示。

Screen_Shot_2016_09_10_at_2_55_59_PM

根据 URL 参数值选择后端

您也可以根据 URL 参数值的不同来代理不同的后端。

以下示例将通过 http://www.example.com?backend=appone 访问服务 appone,即 nginx 首页,通过 http://www.example.com?backend=apptwo 访问服务 apptwo,即 hello world 首页。应用模板代码如下所示。

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. # 获取 URL 中参数名称为 backend 的参数值,同时将 HOST header 修改为要匹配的后端的域名
  17. EXTRA_FRONTEND_SETTINGS_80: " http-request set-header HOST %[urlp(backend)].example.com"
  18. appone:
  19. ports:
  20. - 80/tcp
  21. - 443/tcp
  22. image: 'nginx:latest'
  23. labels:
  24. # 配置 URL,支持指定 path,此处支持 http/https/ws/wss 协议
  25. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  26. restart: always
  27. apptwo:
  28. ports:
  29. - 80/tcp
  30. image: 'registry.cn-hangzhou.aliyuncs.com/linhuatest/hello-world:latest'
  31. labels:
  32. # 配置 URL,支持指定 path,此处支持 http/https/ws/wss 协议
  33. aliyun.proxy.VIRTUAL_HOST: "http://apptwo.example.com"
  34. restart: always

绑定 host,输入链接 http://www.example.com?backend=appone,显示服务 appone 的 nginx 首页,如下所示。

Screen_Shot_2016_09_10_at_3_40_04_PM

绑定 host,输入链接 http://www.example.com?backend=apptwo,显示服务 apptwo 的 hello world 首页,如下所示。

Screen_Shot_2016_09_10_at_3_40_20_PM

记录访问日志

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. restart: always
  6. labels:
  7. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  8. aliyun.custom_addon: "proxy"
  9. # 每台 vm 部署一个该镜像的容器
  10. aliyun.global: "true"
  11. # 前端绑定负载均衡
  12. aliyun.lb.port_80: tcp://proxy_test:80
  13. environment:
  14. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  15. ADDITIONAL_SERVICES: "*"
  16. EXTRA_DEFAULT_SETTINGS: "log rsyslog local0,log global,option httplog"
  17. links:
  18. - rsyslog:rsyslog
  19. rsyslog:
  20. image: registry.cn-hangzhou.aliyuncs.com/linhuatest/rsyslog:latest
  21. appone:
  22. ports:
  23. - 80/tcp
  24. - 443/tcp
  25. image: 'nginx:latest'
  26. labels:
  27. # 此处支持 http/https/ws/wss 协议
  28. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  29. restart: always

日志会直接打到 rsyslog 容器的标准输出中,通过 docker logs $rsyslog_container_name 即能看到自定义路由的访问日志。

服务间的负载均衡

以下模板创建一个负载均衡服务 lb 和一个应用服务 appone,整体对外提供域名为 appone.example.com 的服务。

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. hostname: proxy # 指定该服务的域名为 proxy,即 proxy 会解析到所有部署了该镜像的容器
  4. ports:
  5. - '80:80'
  6. restart: always
  7. labels:
  8. # addon 使得 proxy 镜像有订阅注册中心的能力,动态加载服务的路由
  9. aliyun.custom_addon: "proxy"
  10. # 每台 vm 部署一个该镜像的容器
  11. aliyun.global: "true"
  12. # 前端绑定负载均衡
  13. aliyun.lb.port_80: tcp://proxy_test:80
  14. environment:
  15. # 支持加载路由的后端容器的范围,"*"表示整个集群,默认为应用内的服务
  16. ADDITIONAL_SERVICES: "*"
  17. appone:
  18. ports:
  19. - 80/tcp
  20. - 443/tcp
  21. image: 'nginx:latest'
  22. labels:
  23. # 此处支持 http/https/ws/wss 协议
  24. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  25. restart: always

以下模板作为一个客户端,访问应用服务 appone,但是它的访问路径是请求访问负载均衡服务 lb,然后再反向代理到应用服务 appone 的。

  1. restclient: # 模拟 rest 服务消费者
  2. image: registry.aliyuncs.com/acs-sample/alpine:3.3
  3. command: "sh -c 'apk update; apk add curl; while true; do curl --head http://appone.example.com; sleep 1; done'" #访问 rest 服务,测试负载均衡
  4. tty: true
  5. external_links:
  6. - "proxy:appone.example.com" #指定 link 的服务的域名,以及该域名的别名

在服务 restclient 的容器中,您会发现域名 appone.example.com 是解析到负载均衡服务 lb 的所有容器 IP 的。

  1. / # drill appone.example.com
  2. ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 60917
  3. ;; flags: qr rd ra ; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
  4. ;; QUESTION SECTION:
  5. ;; appone.example.com. IN A
  6. ;; ANSWER SECTION:
  7. appone.example.com. 600 IN A 172.18.3.4
  8. appone.example.com. 600 IN A 172.18.2.5
  9. appone.example.com. 600 IN A 172.18.1.5
  10. ;; AUTHORITY SECTION:
  11. ;; ADDITIONAL SECTION:
  12. ;; Query time: 0 msec
  13. ;; SERVER: 127.0.0.11
  14. ;; WHEN: Mon Sep 26 07:09:40 2016
  15. ;; MSG SIZE rcvd: 138

配置监控页面示例

  1. lb:
  2. image: registry.aliyuncs.com/acs/proxy:0.5
  3. ports:
  4. - '80:80'
  5. - '127.0.0.1:1935:1935' # 监控页面对公网暴露的端口,有安全风险,请谨慎配置
  6. restart: always
  7. labels:
  8. aliyun.custom_addon: "proxy"
  9. aliyun.global: "true"
  10. aliyun.lb.port_80: tcp://proxy_test:80
  11. environment:
  12. ADDITIONAL_SERVICES: "*"
  13. STATS_AUTH: "admin:admin" # 监控时用于登录的账号和密码,可以自定义
  14. STATS_PORT: "1935" # 监控使用的端口,可以自定义
  15. appone:
  16. expose:
  17. - 80/tcp
  18. image: 'nginx:latest'
  19. labels:
  20. aliyun.proxy.VIRTUAL_HOST: "http://appone.example.com"
  21. restart: always

登录到自定义路由镜像所在的每一台机器(每一台机器都可能接收请求,不管应用容器在哪台机器上),请求 acs/proxy 健康检查页面。

注意:按照应用模版的 STATS_AUTH 环境变量配置正确的用户名和密码。

  1. root@c68a460635b8c405e83c052b7c2057c7b-node2:~# curl -Ss -u admin:admin 'http://127.0.0.1:1935/' &> test.html

将页面 test.html 拷贝到有浏览器的机器,用浏览器打开本地文件 test.html,查看 stats 监控统计页面,显示为绿色,表示 acs/proxy 容器到后端容器的网络是连通的,在正常工作;显示为其他颜色则为异常。

本文导读目录