API网关为K8s容器应用集群提供强大的接入能力

1. Kubernetes 集群介绍

Kubernetes(k8s)作为自动化容器操作的开源平台已经名声大噪,目前已经成为容器玩家主流选择。Kubernetes在容器技术的基础上,增加调度和节点集群间扩展能力,可以非常轻松地让你快速建立一个企业级容器应用集群,这个集群主要拥有以下能力:

  • 自动化容器的部署和复制

  • 随时扩展或收缩容器规模

  • 将容器组织成组,并且提供容器间的负载均衡

  • 很容易地升级应用程序容器的新版本

  • 提供容器弹性,如果容器失效就替换它

2. API网关作为Kubernetes集群的接入层架构

我们可以看到Kubernetes集群是可以作为应用服务的,但是Kubernetes集群没有足够的接入能力,特别在大型应用中,它是不能够直接对用户提供服务的,否则会有非常大的安全风险。而API网关作为成熟的云产品,已经集成了非常丰富的接入能力,把API网关放在Kubernetes集群前面作为应用集群的接入服务使用,将大大提高Kubernetes集群的服务能力,可以作为标准的大型互联网应用的标准架构。下面是使用阿里云架构图:

是否启用Ingress Control?

从架构图中我们可以看到,API网关作为Kubernetes集群的桥头堡,负责处理所有客户端的接入及安全工作,API网关和Kubernetes集群中Ingress Control的内网CLB或者服务的内网CLB进行通信。具体什么时候用Ingress Control呢?如果Kubernetes集群内只有一个服务,网关直接和此服务关联的内网CLB进行通信最高效。如果Kubernetes集群内有多个服务,如果使用服务的内网CLB对网关提供服务,将会生成很多CLB,资源管理起来会比较麻烦,此时我们可以使用Ingress Control做Kubernetes中服务发现与七层代理工作,API网关的所有请求发送到Ingress Control关联的内网CLB上,由Ingress Control将请求分发到Kubernetes集群内的容器内,这样我们也只需要一个内网CLB就能将Kubernetes集群内的所有服务暴露出去了。

3. API网关接入能力

读者要问了,接入了API网关具体能为整个架构带来哪些好处呢?下面我们列一下这种架构中,API网关具体能给整个应用带来什么价值。

1.API网关允许客户端和API网关使用多种协议进行通信,其中包括:

* HTTP  
* HTTP2                        

2.API网关使用多种方法保证和客户端之间的通信安全:

* 允许定义API和APP之间的授权关系,只有授权的APP允许调用;
* 全链路通信都使用签名验证机制,包括客户端和API网关之间的通信和API网关和后端服务之间的通信,保证请求在整个链路上不会被篡改;
* 支持用户使用自己的SSL证书进行HTTPS通信;
* 支持OPENID CONNECT;
                        

3.API网关具备iOS/Android/Java三种SDK的自动生成能力,并且具备API调用文档自动生成能力;

4.API网关支持入参混排能力,请求中的参数可以映射到后端请求中的任何位置;

5.API网关提供参数清洗能力,用户定义API的时候可以指定参数的类型,正则等规则,API网关会帮用户确认传输给后端服务的请求是符合规则的数据;

6.API网关支持流量控制能力,支持的维度为用户/APP/API;

7.API网关提供基于请求数/错误数/应答超时时间/流量监控报警能力,所有的报警信息会使用短信或者邮件在一分钟内发出;

8.API网关已经和阿里云的SLS产品打通,用户可以将所有请求日志自动上传到用户自己的SLS中,后继好对访问日志进行统计分析;

9.API网关支持Mock模式,在联调中这个能力非常方便;

10.API网关支持用户配置调用方的IP白名单和黑名单; 12.API网关结合阿里云的云市场,为Provider提供向API使用者收费的能力。

阿里云的API网关是一个上线数年的成熟云产品,在稳定性和性能方面,经过了时间和阿里云的工程师的不断打磨,有高性能需求的用户尽管放马过来。

4. 在阿里云快速配置Kubernetes集群和API网关

阿里云支持快速创建Kubernetes集群,同一个Region内的Kubernetes集群和API网关的集成也非常简单,下面我们来一步一步地在阿里云中配置出本文第二节中架构设计。第二节中的架构设计中,API网关和Kubernetes有两种结合的模式,一种是API网关将请求发送到Ingress Control前的CLB,由Ingress Control将请求路由到Kubernetes对应的节点中,第二种是API网关直接将请求发送到Kubernetes中服务前的CLB,由CLB直接将请求转发到Kubernetes中服务对应的节点中。第一种模式只需要Ingress Control前有一个CLB就可以了,由Ingress Contro做服务发现与路由,第二种模式每个服务前都需要申请一个CLB,适合并发量大的场景。

4.1 Ingress Control模式的配置方式

4.1.1 创建Kubernetes集群

首先我们来通过控制台创建一个具备Ingress Control组件的Kubernetes集群。

1.进入Kubernetes集群管理控制台界面:https://cs.console.aliyun.com/#/k8s/cluster/list

2.单击右上角创建集群按钮。

3.在创建Kubernetes集群页面选择不同规格的,具体创建选项和常规创建参数一致,在组件配置子页面,需要注意勾选创建Ingress组件。

4.创建成功后可以在Kubernetes列表页面看到刚才创建的集群。

4.1.2 在集群内创建一个多容器的服务

现在集群有了,我们需要在集群内创建一个服务,这个服务由2个容器组成,每个容器都由最新的Tomcat镜像生成。容器的端口是8080,Ingress Control提供服务的端口是80。

1.进入Kubernetes集群管理控制台界面:https://cs.console.aliyun.com/#/k8s/cluster/list。

2.进入Kubernetes集群的控制台页面后,单击左边菜单栏的工作负载菜单下的无状态按钮,进入应用列表页面后,单击右上角的使用YAML创建资源按钮进入创建页面。

3.进入创建页面后,输入下面的资源编排文本单击上传按钮进行创建。

apiVersion: apps/v1 
kind: Deployment
metadata:
  name: tomcat-demo
  labels:
    app: tomcat
spec:
  replicas: 2
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat:latest
        ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat
  sessionAffinity: None
  type: NodePort
                        

对这段编排模板创建文本做下解释:使用最新的Tomcat镜像创建两个容器的意思,容器的服务端口是8080,并且创建一个命名为tomcat-service的服务,对外服务的端口为80,映射到容器8080的端口;

好了,目前为止,我们已经创建了一个Kubernetes集群,并且在这个集群下面创建了两个容器,每个容器上面跑着一个最新的Tomcat。这两个容器组成一个无状态应用,并且组成了一个命名为tomcat-service的服务。我们可以进入无状态应用详情页面看到整个应用的运行情况。目前我们的API网关没有办法访问到这个服务,需要我们在Ingress Control上建立一条到这个服务的路由才能把全链路打通

4.1.3 在Ingress Control上给服务加上路由

现在我们有应用了,还需要在Ingress Control上为这个应用建立一个服务,然后在服务上建立一条路由,这样API网关将请求发送给Ingress Control时,Ingress Control会根据配置的路由信息将请求代理到对应的应用节点上。

1.在集群控制台上单击网络菜单下的路由按钮,单击右上角的创建按钮;

2.在创建路由页面填写服务对应的域名,所监听的端口等。

4.1.4 对Ingress Control的内网CLB授权

API网关如果要访问Ingress Control的内网CLB,需要增加VPC网络的授权,首先我们需要准备VPC的标识和内网CLB的实例ID,我们可以在CLB控制台获取。

1.在Kubernetes管理控制台的网络菜单下单击服务菜单,进入服务管理页面后,选择命名空间为"所有命名空间"后可以在列表中看到Ingress Control的内网CLB地址。

2.登录CLB控制台(https://slb.console.aliyun.com/),找到刚才创建Kubernetes服务时自动创建的VPC,单击进去查看详情,我们可以在这个页面看到VPC的标识。

好了,目前我们已经获取到了VPC的ID和CLB的实例ID,下面我们来创建API网关的授权:

3.进入API网关授权页面:https://apigateway.console.aliyun.com/#/cn-beijing/vpcAccess/list ,单击右上角的创建授权按钮,弹出创建VPC授权的小页面,将刚才查询到的VPC标识和CLB实例ID填入到对应的内容中,单击确认按钮后,授权关系就创建好了,需要记住刚才填写的授权名称。

4.1.5 创建API

在API网关控制台创建API的时候,后端服务这块,有两点需要注意的:

1.我们需要填写刚才创建的VPC授权名称;

2.在创建API页面的常量参数添加一个名字为host,位置header的参数,参数值设置为4.1.3节中设置的路由中填写的域名。

4.1.6 调用测试

API建立好了以后,我们把API发布到线上就可以使用API网关的测试工具进行测试,看看能否将请求发送到刚才创建的Kubernetes集群中去。 我们进入刚才创建好的API的详情页面,单击左侧菜单中的调试API,进入调试页面。在调试页面填写好相应的参数,单击“发起请求”按钮。

我们可以看到,请求发送到了Kubernetes的集群中的容器中,并且收到了容器中tomcat的404的应答(因为没有配置对应的页面)。

4.2 Kubernetes服务内网CLB结合模式的配置

通过Kubernetes服务的CLB结合API网关与Kubernetes的模式的配置方式与前一节中通过Ingress Control结合模式的配置方式有两点不同:1.申请Kubernetes中的容器服务时,需要指定生成内网CLB,2.找到这个CLB的VPC ID与CLB ID,使用这两个ID到API网关去进行授权即可。上一节中描述的创建Kubernetes集群的步骤,本节不再冗余描述。本节主要描述创建携带内网CLB的Kubernetes服务,并且找到这个内网CLB的IP地址。在找到CLB的IP地址后,具体授权方法和4.1.4中描述的一致,本节也不再重复描述。

4.2.1 生成携带内网CLB的Kubernetes服务

在4.1.1操作之后,我们有了一个Kubernetes集群,现在我们通过资源编排文本在这个集群中创建带有内网CLB的服务。我们注意下,本段资源编排代码和4.1.2中的资源编排代码不同的是,我们把最后一行的Type变成了LoadBalancer,并且指定了这个CLBLoadBalancer为内网:

apiVersion: apps/v1 
kind: Deployment
metadata:
  name: tomcat-demo
  labels:
    app: tomcat
spec:
  replicas: 2
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat:latest
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
  annotations:
    service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  selector:
    app: tomcat
  type: LoadBalancer
                        

对这段编排模板创建文本做下解释:使用最新的Tomcat镜像创建两个容器的意思,容器的服务端口是8080,并且创建一个命名为tomcat-service的服务,这个服务前有一个内网CLB,对外服务的端口为80,映射到容器8080的端口。

4.2.2 在Kubernetes控制台找到服务的内网CLB地址

现在我们成功创建了一个携带内网CLB的服务,我们可以在Kubernetes控制台的网络菜单的服务子页面找到这个内网CLB的内网IP。

找到内网CLB之后,就可以像4.1.4中一样,去CLB的控制台找到这个CLB的VPC ID和CLB ID,并且使用这个CLB的VPC ID和CLB ID到API网关去授权了。

5 总结

让我们总结一下本文的内容,在前三节中,我们描述了Kubernetes集群和API网关的各项能力,并且画出了结合它俩作为后端应用服务生产的架构图。我们结合API网关+Kubernetes集群的架构,让系统具备了动态伸缩,动态路由,支持多协议接入,SDK自动生成等各项能力,成为可用性更高,更灵活,更可靠的一套架构。

5.1 配置总结

在最后一节,我们描述了在阿里云的公有云如何创建一整套API网关加Kubernetes的流程,关键点在于Kubernetes集群通过Ingress Control组件服务发现,在API网关对Ingress Control组件的内网CLB进行授权后,将所有请求发送到CLB上。下面我们再总结一下通过Ingress结合API网关与Kubernetes的步骤:

  1. 创建一个带有Ingress Control组件的Kubernetes的集群;

  2. 使用资源编排命令,在Kubernetes集群中创建两个运行这最新版本的Tomcat的容器,并且基于这两个容器创建对应的服务;

  3. 在控制台上给Ingress Control加上一条服务路由;

  4. 到CLB控制台找到Ingress Control内网CLB的实例ID,在API网关创建一个VPC授权;

  5. 在API网关创建API,后端服务使用刚才创建的VPC授权,并且设定一个名为host的参数,参数值使用Ingress Control服务路由设置的域名。API的请求将发送到Kubernetes集群的Ingress Control的CLB上,由Ingress Control将请求路由到容器内部的Tomcat服务上。

在高并发场景或者只有一个服务的场景,我们可以跳过Ingress Control,直接在服务前面架设一个内网CLB,并且将这个内网CLB授权给API网关,供API网关进行访问。

5.2 Ingress Control和CLB两种方案对比

1. 使用CLB+Ingress Control。Ingress Control可以做Kubernetes集群的服务发现和七层代理工作,如果Kubernetes集群中有多个服务,可以统一使用Ingress Control进行路由,同时只需要一个内网CLB就可以对外暴露多个服务。便于运维管理和Kubernetes集群的服务扩充。推荐使用此种方式。

2. 直接使用CLB。如果集群中某个服务的业务压力很大,可以考虑为此服务单独建立一个CLB,API网关直接连接此CLB,从而达到更高的通信效率。此种方式的弊端也比较明显,如果Kubernetes集群内有多个服务,需要为每个服务配置一个CLB,因此给运维管理带来较大工作量。