架构图

k8s架构 - 图1

pod创建流程

k8s架构 - 图2 1)、用户提交创建Pod的请求,可以通过API Server的REST API,也可用Kubectl命令行工具

2)、API Server处理用户请求,存储Pod数据到etcd

3)、Schedule通过和API Server的watch机制,查看到新的Pod,尝试为Pod绑定Node

4)、过滤主机:调度器用一组规则过滤掉不符合要求的主机,比如Pod指定了所需要的资源,那么就要过滤掉资源不够的主机

5)、主机打分:对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等

6)、选择主机:选择打分最高的主机,进行binding操作,结果存储到etcd中

7)、Kubelet根据调度结果执行Pod创建操作: 绑定成功后,会启动container,Scheduler会调用API在数据库etcd中创建一个bound pod对象,描述在一个工作节点上绑定运行的所有Pod信息。运行在每个工作节点上的Kubelet也会定期与etcd同步bound pod信息,一旦发现应该在该工作节点上运行的bound pod对象没有更新,则调用Docker API创建并启动Pod内的容器

在这期间,Control Manager同时会根据K8S的mainfiles文件执行RC Pod的数量来保证指定的Pod副本数。而其他的组件,比如Scheduler负责Pod绑定的调度,从而完成整个Pod的创建

工作负载(部署服务)

Service 简介

Kubernetes Service定义了这样一种抽象: Service是一种可以访问 Pod逻辑分组的策略, Service通常是通过 Label Selector访问 Pod组。

  1. Service能够提供负载均衡的能力,但是在使用上有以下限制:只提供 4 层负载均衡能力,而没有 7 层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的。

Service的类型

ClusterIp(集群内部使用)

默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP(VIP)。

NodePort(对外暴露应用)

在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodeIP:NodePort访问来访问该服务。 端口范围:30000~32767

LoadBalancer(对外暴露应用,适用于公有云)

在NodePort的基础上,借助Cloud Provider创建一个外部负载均衡器,并将请求转发到NodePort。

ExternalName

创建一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用。通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容。这只有 Kubernetes 1.7或更高版本的kube-dns才支持。

Service 工作流程

  1. 客户端访问节点时通过 iptables实现的
  2. iptables规则是通过 kube-proxy写入的
  3. apiserver通过监控 kube-proxy去进行对服务和端点的监控
  4. kube-proxy通过 pod的标签( lables)去判断这个断点信息是否写入到 Endpoints里

    Endpoints简介

    endpoint是k8s集群中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址。service配置selector,endpoint controller才会自动创建对应的endpoint对象;否则,不会生成endpoint对象。

kubernetes中的port

  1. nodePort是外部访问k8s集群中service的端口,通过nodeIP: nodePort可以从外部访问到某个service。
  2. port是k8s集群内部访问service的端口,即通过clusterIP: port可以访问到某个service。
  3. targetPort是pod的端口,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
  4. containerPort是pod内部容器的端口,targetPort映射到containerPort。

Kubernetes 暴露服务的方式

  1. NodePort:后期维护困难,不支持虚拟路径
  2. LoadBlancer:需要云厂商支持,有局限性
  3. ClusterIP:只能在集群内部访问
  4. Ingress:灵活,无依赖

前三种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部它不断跟踪pod变化,更新endpoint中对应的pod的对象,提供IP不断变化的pod的服务发现机制;对集群外部,它类似负载均衡器,可以在集群内外对pod进行访问。但是单独使用service暴露服务的方式,在实际生产环境中不太适应。 而ingress相当于service的service,可以将外部请求通过不同规则的筛选后转发到不同的service

配置方式

  1. Deployment+LoadBalancer模式的Service 如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露
  2. Deployment+NodePort模式的Service 同样用deployment模式部署ingress-controller,并创建对应的服务,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。 NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响
  3. DaemonSet+HostNetwork+nodeSelector 用DaemonSet结合nodeselector来部署ingress-controller到特定的node上(也可结合affinity亲和性部署到多个节点),然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。比较适合大并发的生产环境使用。

工作流程

一个 Service 由一组 backend Pod 组成。这些 Pod 通过 endpoints 暴露出来。 Service Selector 将持续评估,结果被 POST 到一个名称为 Service-hello 的 Endpoint 对象上。 当 Pod 终止后,它会自动从 Endpoint 中移除,新的能够匹配上 Service Selector 的 Pod 将自动地被添加到 Endpoint 中。 检查该 Endpoint,注意到 IP 地址与创建的 Pod 是相同的。现在,能够从集群中任意节点上使用 curl 命令请求 hello Service :

kube-proxy简介

kube-proxy负责为Service提供cluster内部的服务发现和负载均衡,它运行在每个Node计算节点上,负责Pod网络代理, 它会定时从etcd服务获取到service信息来做相应的策略,维护网络规则和四层负载均衡工作。在K8s集群中微服务的负载均衡是由Kube-proxy实现的,它是K8s集群内部的负载均衡器,也是一个分布式代理服务器,在K8s的每个节点上都有一个,这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的Kube-proxy就越多,高可用节点也随之增多。

  1. service是一组pod的服务抽象,相当于一组pod的负载均衡,负责将请求分发给对应的pod。service会为这个负载均衡提供一个IP,一般称为cluster IP。kube-proxy的作用主要是负责service的实现,具体来说,就是实现了内部从pod到service和外部的从node port向service的访问。
  2. kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。 kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也成为Cluster IP, 集群内通过访问这个Cluster IP:Port就能访问到集群内对应的serivce下的Pod。
  3. service是通过Selector选择的一组Pods的服务抽象,其实就是一个微服务,提供了服务的LB和反向代理的能力,而kube-proxy的主要作用就是负责service的实现。
    1. service另外一个重要作用是,一个服务后端的Pods可能会随着生存灭亡而发生IP的改变,service的出现,给服务提供了一个固定的IP,而无视后端Endpoint的变化。