在容器服务中如何暴露服务到公网并配置负载均衡

在容器服务中,暴露应用提供的服务到公网有两种选择,一种是通过系统默认的路由应用acsrouting暴露服务到公网,适用的场景是:普通且简单的7层协议负载均衡,web页面访问路由服务,容器集群内服务之间7层协议互相访问的通信代理和负载均衡。另外一种是通过自定义SLB方式暴露服务,这种方式是属于较高级的功能,适用的场景是:4层协议负载均衡,自定义各服务的路由,在将传统架构迁移到容器架构过程中非容器集群的服务访问容器集群中容器的服务。下面分别以举例的方式介绍这些暴露服务到公网并配置负载均衡的能力。

如何暴露服务到Internet

通过系统默认acsrouting路由应用暴露服务

暴露HTTP服务

  • 适用场景:普通且简单的7层协议负载均衡,web路由服务,容器集群内服务之间7层协议互相访问的通信代理和负载均衡
  • 如下图所示,当我们新建一个集群的时候,我们会默认给这个集群分配一个slb实例,这个slb实例会将集群中的所有节点加入作为后端,同时前端会暴露80端口,后端所有节点的机器也会暴露80端口,我们会启动一个路由应用,应用的名称叫"acsrouting",是阿里云容器服务路由应用(Aliyun Container Service Routing)的意思,这个路由应用只有一个服务,就是路由服务,该服务是全局(global)的,也就是说每个节点(下面说到的主机和节点都是同一个意思,即ECS的vm实例)都部署了这个服务(或者说镜像)的一个拷贝,也就是容器。每个节点都有这个容器用来路由HTTP服务或者HTTPS服务。如图所示,HTTP服务,SLB前后端端口的映射是"80:80",主机与路由容器之间的端口映射也是"80:80",即路由的容器暴露的也是80端口,其它用作web服务的容器可以暴露任意的端口,只要在容器启动的时候设置主机和容器端口的映射,routing服务就能获取到相应的端口进行请求的路由。暴露HTTP服务完整示例可以参见通过镜像创建Wordpress
    在容器服务中如何暴露服务到公网并配置负载均衡

设置主机和容器端口的映射

  • 通过容器服务管理控制台进行设置

    • 在容器服务控制台左侧边栏选择"服务"选项卡,在"服务列表"中,选择需要暴露的服务,例如该处示例的服务是"spring-boot",选择"spring-boot"服务的"变更配置"
      在容器服务中如何暴露服务到公网并配置负载均衡
    • 在变更配置页面,配置主机和容器端口的映射,如下图所示
    • 如图,主机端口为空,表示随机暴露一个主机的端口(暴露http/https服务时,我们可以不需要知道这个主机暴露的具体端口是什么,而是使用overlay网络或者vpc网络来直接访问容器的端口),容器端口为8080。我们使用spring boot默认暴露web服务的8080端口来提供http服务,使用的协议是tcp协议
    • 如图,路由配置通过域名来暴露服务,须标明要暴露的端口,此处为我们的web服务8080端口。域名字段只填写了域名前缀,如果域名前缀为"XXX",会给到域名"XXX.$cluster_id.$region_id.alicontainer.com"供测试使用,此处我们拿到的域名为"spring-boot.c0cffb4340aee47ccb26dea062cfb0b2e.cn-beijing.alicontainer.com",用户也可以填写自己的域名,需要添加解析到相应的SLB实例IP。关于配置路由的容器端口和http服务的域名,详情见routing标签
      在容器服务中如何暴露服务到公网并配置负载均衡
  • 通过客户端工具进行设置

    • docker help run 查看使用的"-p"选项, 路由配置在容器服务管理控制台进行
    • docker-compose 查看支持的"ports"选项 路由配置规则详情见routing标签

暴露HTTPS服务

  • 与暴露HTTP服务的区别主要在于,暴露HTTPS服务,SLB前后端端口的映射是"443:80"以及证书配置。只需要在SLB这一层前端暴露443端口,后端暴露80端口路由到routing服务,同时上传相应域名的证书,就能够提供https服务了,具体的信息见 slb帮助文档-证书管理

通过自定义SLB方式暴露服务

暴露HTTP协议或者HTTPS协议的服务

  • 推荐使用简单路由服务(即routing)的方式来暴露HTTP服务或者HTTPS协议的服务,如果开发者希望搭建自己的路由链路,可以开通新的内网或者公网SLB实例路由到vm的端口(通过label aliyun.lb.port_$container_port来实现),并设置主机和容器的映射关系来进行请求的路由
  • 适用场景:7层协议负载均衡,自定义各服务的路由,在将传统架构迁移到容器架构过程中非容器集群的服务访问容器集群中容器的服务

暴露TCP协议或者UDP协议的服务

  • 目前如果要暴露TCP协议的服务,需要用户自行设置SLB实例或者公网IP,并配置好主机端口与容器端口的映射(通过label aliyun.lb.port_$container_port来实现)
  • 适用场景:4层协议的负载均衡,自定义各服务的路由,在将传统架构迁移到容器架构过程中非容器集群的服务访问容器集群中容器的服务
  • 示例:通过自定义SLB的方式来将容器集群内的redis服务暴露给容器集群外的python应用

    • 首先在SLB官网控制台,购买创建一个用于路由的SLB,这里选择的是公网实例,用户可以根据自己的需要选择公网或者内网
      在容器服务中如何暴露服务到公网并配置负载均衡
    • 然后给刚刚购买创建的SLB实例命名为slb_redis_app,容器服务会通过该名称来引用这个SLB
      在容器服务中如何暴露服务到公网并配置负载均衡
    • 选择一个已有的集群,创建一个名称为redis-demo的应用,点击使用镜像创建
      在容器服务中如何暴露服务到公网并配置负载均衡
    • 选择redis镜像,注意,此处redis镜像只是开通了容器的6379端口,为了让我们创建的SLB路由到这个容器端口,我们必须知道redis镜像的主机:端口映射,这里我们勾选publish,选择使用的协议是TCP协议,同时指定主机端口为6379,主机端口6379即为SLB绑定的后端主机端口。
      在容器服务中如何暴露服务到公网并配置负载均衡
    • 为了配置自定义SLB,需要让redis服务知道使用的SLB的信息,这些信息是通过向服务注入一个标签来实现的,标签格式如下,带$的变量为占位符

      aliyun.lb.port_$container_port:$scheme://$[slb_name|slb_id]:$front_port

$container_port表示容器要暴露的端口,$scheme表示SLB监听端口支持的协议,可能的值为tcphttphttpsudp$[slb_name|slb_id]表示可以填写slb实例的名称或者Id,$front_port表示slb实例要暴露的前端端口。更多详情见aliyun.lb.port_$container_port

  • 创建应用页面,点击更多设置,找到自定义SLB表单。这里设置我们要配置的SLB实例的信息,如下图配置所示,对应的标签内容为aliyun.lb.port_6379: tcp://slb_redis_app:6379。 标签设置我们要路由到的容器端口为6379,引用前面创建的SLB名称slb_redis_app,与上面主机:容器端口映射设置的TCP协议相呼应,这里我们设置监听端口的协议为TCP协议,同时设置SLB的前端端口为6379,点击添加按钮。至此,我们在容器服务中引用了刚刚创建的SLBslb_redis_app,同时将SLB的前端端口,后端端口(即主机的端口),容器端口均设置为了6379(用户可以根据自己的需要设置不同的前端端口和主机端口)
    在容器服务中如何暴露服务到公网并配置负载均衡
  • 点击创建并部署,redis应用即开始创建了。redis应用在创建的过程中会自动将名称为slb_redis_app的SLB实例绑定到部署了redis镜像的后端主机。
  • 当应用处于就绪状态后,查看名为slb_redis_app的SLB实例的状态。由健康状态可见,SLB已经正确地绑定到了redis的后端了,除了SLB绑定的后端和监听的6379端口外,用户此时可以根据自己的需要修改名为slb_redis_app的SLB实例的属性。
    在容器服务中如何暴露服务到公网并配置负载均衡
  • 查询到SLB实例的IP地址为120.25.129.150,用户可以使用命令行工具telnet 120.25.129.150 6379来检查端口的可访问性。
  • 示例起见,在本地起一个简单的python应用来通过slb_redis_appSLB实例访问容器集群内的redis,注意redis主机地址是SLB的地址120.25.129.150

app.py

    from flask import Flask
    from redis import Redis
    app = Flask(__name__)
    redis = Redis(host='120.25.129.150', port=6379)

    @app.route('/')
    def hello():
        redis.incr('hits')
        return 'Hello World! I have been seen %s times.' % redis.get('hits')

    if __name__ == "__main__":
        app.run(host="0.0.0.0", debug=True)

requirements.txt

    flask
    redis

shell

    $ pip install -r requirements.txt
    $ python app.py
    Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    Restarting with stat
    Debugger is active!
    Debugger pin code: 243-626-653
  • 访问结果如下图所示
    在容器服务中如何暴露服务到公网并配置负载均衡
上一篇:阿里云授权服务中心解答阿里云备案相关疑问


下一篇:.netcore 3.1高性能微服务架构:为什么要采用.netcore3.1作为微服务技术栈