由于最近在进一步梳理和学习云原生解决方案的相关资料,所以没有搞清楚的是kubernetes中的网络和服务暴露方式。最近为了进一步研究,查了资料。业务场景描述前面我们在谈到DevOps解决方案的时候,提到了一个完整的DevOps持续集成和交付流程,需要与容器云集成,实现自动部署、动态弹性伸缩、环境迁移等能力。一个DevOps支撑平台离不开与容器化PaaS平台的集成,即最终编译构建的内容形成一个镜像,放到镜像仓库中。后续的部署、环境迁移、资源扩容都基于镜像仓库进行快速复制复制。对于Docker容器,一般与K8S结合,实现资源的动态调度和集群管理能力。原来的讲,我们只讲了通过K8s进行资源的部署和动态扩展。以后会提供一个VIP虚拟地址给应用模块访问使用,这里不展开。今天主要是根据场景来进一步讲解。场景描述:举个例子,整个应用其实有两个微服务模块,一个是UserMgr微服务,一个是OrderMgr订单管理微服务。这两个微服务通过k8s自动部署到容器云环境中。同时,我们假设每个微服务动态扩展两个副本Pod,即形成三个Pod节点。这样的话,我们是不可能直接访问到PodIP的。一是PodIP本身会动态变化,二是集群扩容后,同一个微服务已经存在多份PodIP。所以我们需要通过Service来访问它。Kubernetes服务定义了这样一个抽象:Pod的逻辑分组,以及访问它们的策略——通常称为微服务。Service可以访问这组Pod,通常是通过LabelSelector。比如上面的UserMgr微服务,我们可以给它打上一个UserMgr标签,然后同一个标签自动聚合成一个Service逻辑分组。内部模块之间的服务访问——ClusterIP我们刚刚提到整个业务场景中有两个微服务UserMgr和OrderMgr,所以这两个微服务之间的访问属于Kubernetes集群内部访问。在这种集群内部访问场景下,使用Service的ClusterIP就足够了。注意ClusterIP本身是一个虚拟IP,无法ping通。对该IP的访问请求,实际上是根据IPTables路由表和KubeProxy路由到具体的Pod实例节点。即:Request-》ClusterIP-》IPTables+KubeProxy-》PodInstance如下图所示:iptables代理模式下,对于每个Service,都会安装iptables规则,捕获到达的clusterIP(虚拟IP)和端口请求Service,然后将请求重定向到Service的一组后端之一。对于每个Endpoints对象,它还安装了选择后端Pod的iptables规则。默认策略是随机选择一个后端。提供外部服务-NodePortmethod如果需要对外提供服务,其实有NodePort、LoadBalancer和Ingress方法,下面分别介绍这几个方法,NodePort方法主要通过每个节点IP加端口的形式暴露端口,任意节点IP都可以访问(前提是没有指定节点调度策略),端口暴露范围可以通过apiserver的配置文件看到,比如上面两个微服务模块部署后,8001端口可以被配置为访问微服务模块UserMgr。即:10.0.0.1:8001、10.0.0.1:8002、10.0.0.1:8003。对于NodePort方式,其实还是将请求转发给Service,再通过Service路由到具体的Pod实例节点。唯一的区别是NodeIP是一个可访问的IP地址。这三个地址都可以访问用户管理微服务。注意一个端口映射到一个微服务,比如8001映射到UserMgr微服务,8002映射到8002微服务。以上三个地址都可以对外访问。如果客户端想统一访问,连接类似Ngnix的反向代理就可以了。但是这种方式有一个问题,就是如果增加了一个新的Node节点,我们需要在集群或者负载均衡上增加新的配置信息。其次,Node本身是依附于虚拟机的。如果重启了整个IaaS环境中的虚拟机,IP地址可能会发生变化,那么此时需要重新手动配置。对外提供服务-LoadBalancer方式这种方式主要是利用其他第三方LB暴露服务,比如阿里云或者亚马逊LB等。这种方式需要注意的是每个微服务都会消耗一个IP,所以可能会导致公共云成本问题。其次,不易形成统一的服务接入口。这样,来自外部负载均衡器的流量将直接进入后端pod,但它们的实际工作方式取决于云提供商。在这些情况下,负载均衡器将根据用户设置的loadBalancerIP创建。对外提供服务——Ingress模式Ingress资源对象用于将不同URL的访问请求转发到后端的不同服务,实现HTTP层的业务路由机制。Kubernetes使用一个Ingress策略定义和一个特定的IngressController,它们结合起来实现一个完整的Ingress负载均衡器。IngressController会根据Ingress规则将客户请求直接转发给Service对应的后端Endpoint,这样会跳过kube-proxy的转发功能,kube-proxy将不再起作用。对于Ingress,可以理解为整个Kubernetes集群的网关或者代理出口。理解为外部API网关是没有问题的。每个微服务都可以通过Ingress访问和注册。可以通过微服务的IP访问地址的含义来区分通过不同的路径和url路由到哪个微服务。Ingress网关的选择可以参考:https://www.cnblogs.com/upyun/p/12372107.html本文给出对比图如下:可以看到,目前的KongAPI网关本身也有一个Kurbernetes插件最后形成了KongIngress,它不仅满足集群节点的对外暴露,还包含了KongGateway的一些核心能力,包括服务注册发现、限流熔断、安全等能力,可以满足API管理的日常需求。简单来说,如果你是将内部微服务的API接口暴露给前端APP,那么使用KongIngress应该是一个不错的选择。同时,KongIngress也有非常大的优势。它提供了一些API和服务定义,将其抽象成K8SCRD,因此可以很方便地通过K8SIngress配置并同步到Kong集群。参考:https://github.com/Kong/kubernetes-ingress-controller/tree/main/docsDevOps集成可以做什么?关于APIGateway和DevOps的协同,我思考了一下,整理如下。我们先看看什么时候需要API网关参与进来。在我们最初的概念中,当一个业务应用需要对外发布API接口服务能力时,这个对外发布可能是其他外部伙伴使用的,也可能是我们自己的APP前端。使用,只要存在这种场景,往往都会涉及到API网关的使用。一个大型项目的多团队协作下,可以看出如果全部采用微服务架构,其实我们推荐的是每个团队都是自己独立的微服务注册中心,负责多个微服务之间的API团队内部模块接口调用,这些API接口调用可以到注册中心。但是涉及到跨团队协作的API接口服务,则需要注册到API网关进行统一管理。简单来说,对外发布API或者调用跨团队的API接口,都需要涉及到API的注册和接入网关管理。微服务模块与API网关的协作包括提供API接口服务注册和访问网关,以及从网关调用API接口服务消费。所以需要从API注册接入和API消费调用两个方面来谈协作。整个DevOps流程中都可以看到API的注册接入。底层是Docker容器+K8s资源调度。我们在安排流水线的时候,涉及到编译、构建、打包、部署等各种动作。其实可以看到,自动部署完成后,接口服务会暴露一个k8s提供的动态ip访问地址。我们要做的就是向网关注册并访问这个ip地址提供的访问接口。弄清楚整个流程后,我其实可以通过两种方式来处理API注册访问。在部署节点上,添加自定义脚本编写,通过自定义运行脚本完成API接口服务的注册。添加接口注册流水线编排节点。部署节点完成后,安排注册节点,在API注册节点定义接口注册内容。由于整个DevOps流水线的设计和执行都是由开发者来完成的,可见第一种方式往往更加灵活。唯一的就是在定义某个pipeline的时候,需要预先规划好需要访问和注册的接口内容。DevOps支撑平台虽然不需要完整的API网关控制功能,但是最好增加一个功能,就是能够查询到DevOps支撑平台上当前注册访问了哪些接口服务,注册后提供代理服务和访问。地址是多少,注册了哪个微服务模块来访问服务等基本的服务目录信息。基于之前的思路,未来会考虑实现KongIngress和K8s集群的融合。对于需要注册的接口服务,先编写配置文件,在K8s部署微服务或扩展动态节点时通过API调用接口。服务自动注册到API网关上,实现对外访问。API消费调用注意采用API网关带来的好处之一是API网关本身提供的API访问地址IP是固定的,不会随着各个微服务模块的自动构建和部署而动态变化。对于API网关,我们会提前部署到测试环境和生产环境,部署好网关之后再开始对各个微服务模块的持续集成和部署。因此,一个微服务模块需要访问其他微服务模块的哪些接口,一种方法是每次调用服务注册中心查询具体的服务访问地址,一种方法是将访问地址存储在本地配置文件中。更好的方法是:先调用服务注册中心,获取服务访问地址,保存在本地配置文件中。发现本地配置文件已经有服务访问地址后,不再从服务注册中心调用,除非收到地址变更消息注意到这一点确认后,其实就是微服务模块本身的构建、打包和部署和原来一样,没有和API网关配合,只是配置文件的访问地址固定为API网关提供的地址。如何知道API网关提供了哪些地址,也就是我们可以在API网关的管控平台上查询,或者在DevOps平台提供的服务目录查询功能上查询。
