一、写在前面

K8S的文章很多人都写过,若要想好好研读,系统的学习,真推荐去看官方文档。但是若是当上下班路上的爽文,可以看下我的笔记,我也会尽力多写点自己的理解进来。

二、K8S为我们提供了怎样的能力

大家都知道Docker,我们可以将自己的应用打包制作成Image,然后通过docker run命令将Image启动成Container对外提供服务。

基于此,K8S不仅能将用户提供的单个容器运行起来,将其对外暴露出去提供服务。还提供了:路由网关、集群监控、灾难恢复,以及应用的水平扩展等能力。

大家常听过一个词:微服务、云原生应用,如何理解这个词自然也是见仁见智。

如下图是SpringCloud的架构图:

在SpringCloud中有不同的组件,诸如提供服务发现能力的:Eureka、提供负载均衡机制的Ribbon、以及微服务的统一入口Zuul, 基于这套框架做过开发的同学都知道,无论是Eureka还是Zuul,无论开发量大小,都需要程序员开发相应的代码,即使这些代码和业务本身并没有什么关系。

而在K8S中,像Eureka的服务发现能力,Zuul的网关能力、以及Ribbon的负载均衡能力,K8S都是原生支持的,开发人员只需要写好自己的业务代码,提供一个可执行的jar包,或者二进制文件即可部署进K8S中就行

当然不仅于此,K8S的服务网格组件如:Istio还提供了流量治理能力,比如按不同的请求头做不同比例的流量分发调度、亦或者是金丝雀发布。

说起容器编排,像Docker的Compose或者是Docker-Swarm都提供了简单的容器编排的能力。

像Docker-Compose或者Docker-Swarm的通病就是过于以Docker核心,提供的能力也过于简单比如定义谁先启动谁后启动。无法满足比较复杂的场景

而K8S的容器编排设计是站在更高的维度,Docker对于K8S而言只是运行它编排产出的介质,K8S针对不同的编排场景提供了不同的编排资源对象,如提供Deployment编排无状态应用,提供了Cronjob编排定时任务,提供了StatefulSet编排ES、Redis集群这种有状态应用等等,这都是前者所不能及的…

三、架构

K8S架构简图如上,分为MasterNode、WorkNode两大部分和五大组件,一开始接触这些概念难免会有些陌生,但是本质上这些组件都是K8S的开发者对各种能力的抽象和封装

3.1、MasterNode

和Redis或者Nginx这种由二进制文件启动后得到一个对外提供服务的守护进程不同,K8S中的MasterNode其实并不是一个二进制文件启动后得到的对外提供服务的守护进程,它本质上是一个抽象的概念。

MasterNode包含3个程序,分别是:

  • ApiServer 提供HTTP Rest接口,是集群中各种核心资源的CRUD的统一入口,是集群中各个组件交互的核心枢纽 集群资源配额的统一入口 提供了完备的集群安全机制
  • ControllerManager 实时监控集群中如Service等各种资源的状态变化,不断尝试将它们的副本数量维持在一个期望的状态。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
  • Scheduler: 负责调度功能,如:为Pod找到一个合适的宿主机器

3.2、WorkerNode

和MasterNode类似,WorkerNode本质也并不是一个独立的应用程序,它包含两个组件,如下

  • kubelet Node节点管理 Pod管理,同容器运行时交互下发容器的创建/关闭命令 容器健康状态检查
  • kube-proxy 通过为Service资源的ClusterIP生成iptable或ipvs规则,实现将K8S内部的服务暴露到集群外面去

既然WorkNode也是抽象的概念,那么若在MasterNode启动kube-proxy和kubelet进程,那么MasterNode也会拥有WorkNode的能力,双重角色,但生产环境不推荐这样搞。

四、核心组件

4.1、ApiServer

4.1.1、概述

APIServer有完备的集群安全验证机制,提供了对K8S中如Pod、Service等资源CRUD等HttpRest接口,是集群中各个组件之间数据交互的核心枢纽。

4.1.2、是集群管理API的统一入口

为了更好的理解这个概念可以看如下图

通过kubectl命令执行创建 kubectl apply -f rs.yaml 创建pod时,经历的流程如上图,大概流程为

  1. apiserver接收kubectl的创建资源的请求
  2. apiserver将创建请求写入ECTD
  3. apiserver接收到etcd的回调事件
  4. apiserver将回调事件发送给ControllerManager
  5. controllerManager中的ReplicationController处理本次请求,创建RS,然后它会调控RS中的Pod的副本数量处于期望值,比期望值小就新创建Pod,于是它告诉ApiServer要创建Pod
  6. apiserver将创建pod的请求写入etcd集群
  7. apiserver接收etcd的创建pod的回调事件
  8. apiserver将创建pod的回调事件发送给scheduler,由它为pod挑选一个合适的宿主node
  9. scheduler告诉apiserver,这个pod可以调度到哪个node上
  10. apiserver将scheduler告诉他的事件写入etcd
  11. apiserver接收到etcd的回调,将更新pod的事件发送给对应node上的kubelet进程
  12. kubelet通过CRI接口同容器运行时(Docker)交互,维护更新对应的容器。

4.1.3、提供了完备的安全认证机制

ApiServer采用https+ca签名证书强制双向认证,也就说是想顺利访问通ApiServer的接口需要持有对应的证书

4.1.4、典型使用场景

比如在K8S内部搭建一个Elasticsearch的集群,每个pod中运行一个Pod,想搭集群的前提是得先知道有哪些运行着ES的Pod的ip地址。获取的途径只有一个:问ApiServer要。

那应用程序怎么知道ApiServer的地址呢?如下:

K8S中的Service占用单独的网段(启用ipvs的前提下,我的service网段为:192.168.0.0)

当我们安装完K8S集群后,在default命名空间中会有个默认的叫kubernetes的Service,这个service使用的service网段的第一个地址,而且 这个service是ApiServer的service,换句话说,通过这个service可以访问到apiserver

可以通过如下命令访问到本地的apiserver

curl --cert /etc/kubernetes/pki/admin.pem \       --key /etc/kubernetes/pki/admin-key.pem \       --cacert /etc/kubernetes/pki/ca.pem https://127..0.1:6443/api/v1/

将回环地址换成名为kubernetes的service的cluster-ip也能访问到api-server

curl --cert /etc/kubernetes/pki/admin.pem  --key /etc/kubernetes/pki/admin-key.pem --cacert /etc/kubernetes/pki/ca.pem https://192.168.0.1:6443/api/v1/

4.1.5、Api Proxy接口

ApiServer提供了一种特殊的Restful接口,它本身不处理这些请求而将请求转发给对应的Kubelet处理

如:关于Node相关的接口

# 查询指定节点上所有的pod信息/api/v1/nodes/{nodename}/proxy/pods# 查询指定节点上物理资源的统计信息/api/v1/nodes/{nodename}/proxy/stats# 查询指定节点上的摘要信息/api/v1/nodes/{nodename}/proxy/spec

更多接口查询官网~

关于Pod的接口

# 访问pod/api/v1/namespace/{namespace-name}/pods/{name}/proxy# 访问pod指定路径/api/v1/namespace/{namespace-name}/pods/{name}/{path:*}

4.2、ControllerManager

借助上图理解Controller的作用,它是K8S自动化管理各类资源的核心组件,所谓的自动化管理,其实就是实时监控集群中各类资源的状态的变化,不断的尝试将各类资源的副本数调整为期望值~

ControllerManager细分为8种Controller,如下

4.2.1、Replication Controller

  1. 确保任何时候ReplicaSet管理的Pod副本数量都为期望值
  2. 实际值高于期望值告诉apisever应该关闭多余的pod,反之亦然
  3. 只有当Pod的重启策略为Always,Replication Controller才会管理
  4. Replication Controller通过标签管理Pod,若pod标签被改,pod将脱离管控
  5. 提供重新调度、弹性扩/缩容、滚动更新能力

4.2.2、Node Controller

我们通过kubectl工具请求K8S的ApiServer获取集群中的Node信息,如下

可以看到集群中所有的节点和它的状态都是Ready

apiserver是如何知道集群中有哪些节点的呢?答案是:kubelet上报给apiserver,再经由watch机制转发Node Controller, 由Node Controller统一实现对集群中Node的管理 。若节点长时间异常,NodeControler会删除该节点,节点上的资源重新调度到正常的节点中~

4.2.3、ResourceQuota Controller

ResourceQuota Controller的功能是确保:指定资源对象数量在任何时候都不要超过指定的最大数量,进而保证由于业务设计的缺陷导致整个系统的紊乱甚至宕机。

使用示例:将ResourceQuota创建到哪个namespace中,便对哪个namespace生效

apiVersion: v1kind: ResourceQuotametadata:  name: object-countsspec:  hard:      # ==对象数量配额==    # 最多创建的cm数    configmaps: "10"    # 最多创建的pvc数    persistentvolumeclaims: "4"    # 最多启动的pod数    pods: "4"    # 在该命名空间中允许存在的 ReplicationController 总数上限。    replicationcontrollers: "20"    # 最多创建的secret数    secrets: "10"    # 最多创建的service数    services: "10"    # 在该命名空间中允许存在的 LoadBalancer 类型的 Service 总数上限。    services.loadbalancers: "2"    # 在该命名空间中允许存在的 NodePort 类型的 Service 总数上限。    services.nodeports: 2            # ==存储型==    # 所有 PVC,存储资源的需求总量不能超过该值。    requests.storage: 40Gi    # 在命名空间的所有 Pod 中,本地临时存储请求的总和不能超过此值。    requests.ephemeral-storage: 512Mi    # 在命名空间的所有 Pod 中,本地临时存储限制值的总和不能超过此值。    limits.ephemeral-storage: 40Gi    # ephemeral-storage    与 requests.ephemeral-storage 相同。            # ==cpu、memory==    # 所有非终止状态的 Pod,其 CPU 限额总量不能超过该值。    limits.cpu: 1    # 所有非终止状态的 Pod,其内存限额总量不能超过该值。    limits.memory: 16Gi    # 所有非终止状态的 Pod,其 CPU 需求总量(pod中所有容器的request cpu)不能超过该值。    requests.cpu: 0.5    # 所有非终止状态的 Pod,其内存需求总量(pod中所有容器的request cpu)不能超过该值。    requests.memory: 512Mi    # cpu: 0.5       和requests.cpu相同    # memory: 512Mi  和 requests.memory相同

目前支持的资源配额如下

  • 容器级别 限制容器的CPU、内存
  • Pod级别 对Pod中所有的容器的可用之和资源统一限制
  • Namespace级别 Pod数量 RC的数量 Service数量 ResourceQuota的数量 Secret数量 可持有的PV的数量等

感兴趣自己去了解LimitRange资源对象,LimitRange的配额自动为Pod添加Cpu和Memory的配置,这里不再展开

4.2.4、Namespace Controller

用户通过apiserver创建namespace,apiserver会将namespace的信息存储入etcd中。

namespaceController通过apiserver读取维护这些namespace的信息,若ns被标记为删除状态,namespaceController会将其状态改为Terminating

然后会删除它里面的ServiceAccount、RC、Pod等一切资源对象。

4.2.5、Service Controller - Endpoint Controller

Service Controller 会监听维护Service的状态、变化

Service、Pod、Endpoint之间的关系如下图:Service通过标签选择器找到并代理对应的pod,pod的ip维护和Service同名的Endpoint中~

Endpoint Controller的作用是:监听Service和他对应的pod的变化

  • 当Service被删除时,同步删除和Service同名的Endpoint对象
  • 新建/更新Service时,同步更新对应Endpoint的ip:port列表信息

endpoint对象由每个node上的kube-proxy的进程使用,下文会说

4.3、Scheduler

负责接收ApiServer创建Pod的请求,为Pod选择一个合适的Node,由该Node上的kubelet启动Pod中的相应容器

调度流程分两大步

  • 预选策略 初步筛选出符合条件的Node
  • 优选策略 在第一步的基础上选择更合适的Node

4.4、Kubelet

4.4.1、Node管理

通过设置启动参数 register-node 参数开启kubelet向apiserver注册自己的信息,apiserver会将数据

注册之后通过kubectl如下命令可用查看到集群中的所有node 的信息

若Node有问题,可以看到Status被标记为NotReady

4.4.2、Pod管理

最终管理员下发的创建Pod的请求由Kubelet转发给它所在节点的容器运行时(Docker)处理

4.4.3、容器健康检查

容器的livenessProbe探针(httpGet、tcpSocket、ExecAction)用于判断容器的健康状态。

kubelet会定期调用这些探针来判断容器是否存活~

httpGet

向容器发送Http Get请求,调用成功(通过Http状态码判断)则确定Pod就绪;

使用方式:

livenessProbe:  httpGet:    path: /app/healthz    port: 80

exec

在容器内执行某命令,命令执行成功(通过命令退出状态码为0判断)则确定Pod就绪;

使用方式:

livenessProbe:  exec:    command:    - cat     - /app/healthz

tcpSocket

打开一个TCP连接到容器的指定端口,连接成功建立则确定Pod就绪。

使用方式:

livenessProbe:  tcpSocket:    port: 80

一般就绪探针会在启动容器一段时间后才开始第一次的就绪探测,之后做周期性探测。所以在定义就绪指针时,会给以下几个参数:

  • initialDelaySeconds :在初始化容器多少秒后开始第一次就绪探测;
  • timeoutSeconds :如果该次就绪探测超过多少秒后还未成功,判定为超时,该次探测失败,Pod不就绪。默认值1,最小值1;
  • periodSeconds :如果Pod未就绪,则每隔多少秒周期性的做就绪探测。默认值10,最小值1;
  • failureThreshold :如果容器之前探测成功,后续连续几次探测失败,则确定容器未就绪。默认值3,最小值1;
  • successThreshold :如果容器之前探测失败,后续连续几次探测成功,则确定容器就绪。默认值1,最小值1。

4.5、KubeProxy

K8S原生的支持通过Service的方式代理一组Pod暴露到集群外部对外提供服务,创建Service时会这个Service创建一个Cluster-IP。而kubeproxy本质上就是这个Service的cluster-ip的负载均衡器。

在k8s的不同版本中,kubeproxy负载均衡Service的ClusterIp的方式不尽相同,主要如下

4.5.1、k8s1.2版本前

如上图这个版本的KubeProxy的更像是一个TCP/UDP代理,最明显的特征是:外部用户访问cluster:port过来的流量真实的经过了KubeProxy的处理和转发,即流量经过了userspace中。

4.5.2、k8s1.2~1.7版本

在这个版本KubeProxy端明显特征是:用户的流量不再由kubeproxy负责转发负载均衡。kubeproxy仅负责通过apiserver获取service和它对应的endpoint,然后根据这些数据信息生成iptables的规则,用户的流量通过iptables找到最终的pod。

4.5.3、k8s1.8版本及之后

和上一个版本的区别是支持了ipvs模块。

两者的定位不同:虽然iptables和ipvs都是基于netfilter实现的,但是iptables为防火墙而设计,而ipvs的定位是高性能的负载均衡。

在数据结构层面实现不同:iptables是链式结构,流量流经iptables要过所谓的四表五链,当集群中中的pod数量剧增,iptables会变得十分臃肿,效率下降。而ipvs是基于hash表实现的,理论上支持无限扩张,且寻址快。

ipvs也有不足,比如不支持包过滤、地址伪装、SNAT,在使用Nodeport类型的Service时,依然需要和iptables搭配使用。

五、网络组件

5.1、CoreDNS

CoreDNS是K8S的服务发现机制(有DNS能力),实现了通过解析service-name解析出cluster-ip的能力。而且service被重新创建时cluter-ip是可能发生变化的,但是server-name不会改变。

我们是以POD的形式将CoreDNS部署进K8S的,如下查看CoreDNS的service

这里的kube-dns的ip地址通常可以在安装coredns的配置文件中指定: coredns.yaml

验证下kube-dns解析外网域名的DNS能力

[root@master01 ~]# yum -y install bind-utils[root@master01 ~]# dig -t A www.baidu.com @192.168.0.10  +shortwww.a.shifen.com.39.156.66.1839.156.66.14

验证下kube-dns解析service名的DNS能力

# ${serviceName}.${名称空间}.svc.cluster.local.[root@master01 ~]# dig -t A kubernetes.default.svc.cluster.local. @192.168.0.10 +short192.168.0.1

5.2、CNI网络插件

像Calico或者flanel等,都是符合CNI规范的网络插件,作用如下:

  • 保证集群中的pod生成集群内全局唯一的IP地址。
  • 为K8S集群提供了一个扁平化的集群网络(service网络)意思就是说,它实现了集群内的Pod跨node也能直接互通。

注意点:flanel不支持NetworkPolicy资源对象定义的网络策略,而Calico支持。

什么是网络策略?如下

  • 只有来自IngressController的流量才能访问带有role=frontend标签的pod
  • 只有namespaceA的pod不能访问其他namespace的pod
  • 只有源ip地址在某个网段的请求才能访问Project-A
  • 从ProjectB出去的流量指定访问指定网段的Pod

讲明白——K8S各核心架构组件相关推荐

  1. 还不懂K8S各核心架构组件?来白嫖啊~

    文章目录 一.写在前面 二.K8S为我们提供了怎样的能力 三.架构 3.1.MasterNode 3.2.WorkerNode 四.核心组件 4.1.ApiServer 4.1.1.概述 4.1.2. ...

  2. 阿里P8大牛用实例跟你讲明白“Java 微服务架构实战”

    全文一共十五章,核心内容为SpringBoot.SpringCloud.Docker.RabbitMQ消息组件.其中,SpringBoot是SpringMVC 技术的延伸,使用它进行程序开发会更简单, ...

  3. 通过大头儿子和小头爸爸,给女朋友讲明白了vue中父子组件的传值

    写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字.我热爱技术.热爱开源.热爱编程.技术是开源的.知识是共享的. 这博客是对自己学习的一点点总结及记录,如果您对 Java.算法 感兴 ...

  4. 4天搞定Docker和k8s核心架构,稳拿35k不是问题?

    随着云原生时代的到来,各大厂纷纷上云,甚至有人说,未来的软件就是生在云上,长在云上的.在这种云原生时代大势下,衍生出来的 Kubernetes 工程师.云原生工程师的薪资也水涨船高,大厂不惜花重金聘请 ...

  5. 什么是架构?网络架构中都有什么?终于有人讲明白了

    导读:理解架构这个词的意思是十分重要的.它可能被过度使用,并且使用在各种环境中.如果缺少一致的理解,将会有交流失败的风险.那么架构这个词到底是什么意思呢? 作者:大卫·D.克拉克(David D. C ...

  6. 架构师日记|一次性讲透K8S,服务网格,服务治理这些概念

    随着云原生时代的到来,各大厂纷纷上云,甚至有人说,未来的软件就是生在云上,长在云上的.在这种云原生时代大势下,衍生出来的 Kubernetes 工程师.云原生工程师的薪资也水涨船高,大厂不惜花重金聘请 ...

  7. 终于有人把大数据架构讲明白了

    导读:如何存储.如何利用大规模的服务器集群处理计算才是大数据技术的核心. 作者:李智慧 来源:大数据DT(ID:hzdashuju) 大数据技术其实是分布式技术在数据处理领域的创新性应用,其本质和此前 ...

  8. 一句话讲明白 WebAssembly、微前端等技术背后的核心

    一句话讲明白 WebAssembly.微前端等技术背后的核心 WebAssembly 是在浏览器端可执行的字节码,主要解决的问题是性能.编辑器能把 C.C++.Go.TS 等语言编译成 WebAsse ...

  9. javaweb k8s_K8S微服务核心架构学习指南 ASP.NET Core微服务基于K8S 架构师必备Kubernetes教程...

    K8S微服务核心架构学习指南 ASP.NET Core微服务基于K8S 架构师必备Kubernetes教程 课程内容是关于Kubernetes微服务架构学习课程,基于K8S开展ASP.NET核心进行微 ...

最新文章

  1. 只要你一句话,马斯克就得留扫把头,项目已开源丨Adobe等出品
  2. boost::multiprecision模块float128相关的测试程序
  3. TeamToy - 创新团队的效率工具 一个好用的 团队协作软件
  4. 深度学习之基于Tensorflow2.0实现AlexNet网络
  5. ArcGIS个人数据库(mdb)中矢量字段无法删除
  6. [读书笔记]TCP/IP详解V1读书笔记-3
  7. 在使用 Elasticsearch 时要注意什么?
  8. 自定义滚动条,可解决火狐滚动条默认样式修改不了问题
  9. 一份超详细的MySQL高性能优化实战总结
  10. android接推流sdk,Android——直播推流SDK
  11. python表达式3and5_python3 中 and 和 or 运算规律
  12. CSS显示:内联vs内联块[重复]
  13. 基于Starling移动项目开发准备工作
  14. 15.explain
  15. 《信号与系统》(吴京)部分课后习题答案与解析——第二章(PART3)
  16. 利用“微PE”自制PE可引导iso
  17. Eclipse中将package,folder,source folder相互转换
  18. obj文件(1):obj文件用txt打开并且了解v,f,vn,vt的含义
  19. 队列 front rear
  20. Mac上Elasticsearch 安装及PHP使用

热门文章

  1. 光学红外雨量IFR202型传感器应用于智慧灌溉智能家居地质灾害等行业
  2. Stream流-分组操作
  3. 【RocketMQ】
  4. 数字手写体识别python实现(全连接神经网络)
  5. 福昕阅读器自定义快捷键
  6. Linux 分区、挂盘
  7. 二级路由dhcp关闭连不上wifi_路由器的使用小技巧!
  8. 微信气泡主题设置_微信气泡主题设置方法
  9. java里面的scanner怎么关闭_作业。scanner怎么不能关闭
  10. 中国巡游帆船行业市场供需与战略研究报告