Kubernetes基础(一)

本文详细介绍了Kubernetes架构的关键组件,如apiserver、scheduler、etcd、node节点的kubelet和kube-proxy,以及它们在集群管理和网络通信中的作用。还涵盖了Deployment、HPA、StatefulSet、DaemonSet、Job和CronJob等高级特性,以及Flannel网络插件的使用。
摘要由CSDN通过智能技术生成

Kubernetes

架构

在这里插入图片描述

高可用集群副本数据最好是>=3的奇数个,方便主节点宕机时进行投票

组件说明

master节点组件说明

master组件概括:
api server:所有服务访问的统一入口
CrontrollerManage:维护副本期望数目
Scheduler:负责接收任务,选择合适的节点进行分配任务
etcd:键值对数据库,储存K8S集群所有重要信息(持久化)

scheduler:调度器,分配服务到node节点(scheduler不直接与node节点进行交互,而是scheduler将任务交给api server,api server将请求写入到etcd,scheduler并不会直接与etcd进行交互)

replication controller:控制器,维护副本的数目,例如想要一个容器维护几个副本,就是有该组件进行控制的;如果一旦副本数不满足我们的期望值了,该组件会将副本数申请到我们的期望值,也就是创建对应的Pod或者删除对应的Pod。

api server:一切服务访问的入口。

Deploymen:指挥 Kubernetes 如何创建和更新应用程序的实例。创建 Deployment 后,Kubernetes master 将应用程序实例调度到集群中的各个节点上。创建应用程序实例后,Kubernetes Deployment 控制器会持续监视这些实例。 如果托管实例的节点关闭或被删除,则 Deployment 控制器会将该实例替换为群集中另一个节点上的实例。 **这提供了一种自我修复机制来解决机器故障维护问题。**创建 Deployment 时,您需要指定应用程序的容器映像以及要运行的副本数。

etcd:键值对数据库,一个重要的存储,存储我们k8s中一些参数信息的,离开该组件整个集群就会瘫掉,该组件起到整个集群的数据持久化方案。etcd的官方将它定位成一个可信赖的分布式键值存储服务,它能够为整个分布式集群存储一些关键数据,协助分布式集群的正常运转。为了让数据持久化,该组件天生支持集群化,并不需要其他的组件参与进来,它就能实现自己的集群化方案,它并不像mysql如果要实现读写分离需要借助中间件,该组件不需要任何中间件,本身就能实现。

etcd有两个版本,一个是V2版本,一个是V3版本,V2版本是将数据存储在内存中,V3版本是借助本地数据卷将数据存储在本地磁盘中,关机后数据不会丢失,推荐在Kubernetes集群中使用etcd V3版,V2版本已经在Kubernetes v1.11中弃用了,这个点要注意一下。如果还有用的古老的集群(v1.11及较老的版本的话就要注意备份etcd了)

在这里插入图片描述

etcd内部架构图:

在这里插入图片描述

etcd内部是使用http的协议进行开发的,和k8s一样。因为http天生支持很多操作方式,如:put、get等等以及授权认证。

Raft:所有的读写信息都存储在Raft中。

WAL:预写日志,为了防止这些信息发生损坏,当有数据进行更改的时候会先生成一个日志,并且会对这些日志进行完成的备份。

Store:Raft会会实时将我们的数据写入到本地Store(本地磁盘)中。

node节点组件说明

node节点需要安装三个组件

1. kubelet
2. kube proxy
3. docker

node组件概括:
Kubelet:直接跟容器引擎交互实现容器的生命周期管理
kube-proxy:负责写入规则至IPTABLES、IPVS实现服务映射访问的

kubelet:会跟我们的跟我的CRI(container容器、runtime运行时环境、interface接口)进行交互,CRI其实就是docker的表现形式,kubelet会跟docker进行交互,操作docker创建对应的容器,kubelet维持我们的Pod的生命周期。

kube proxy:负载组件,实现Pod与Pod之间的访问,包括负载均衡需要借助我们的kube proxy,它的默认操作对象是Firewall防火墙,去实现Pod的映射,新版本中支持IPVS组件。

其他第三方组件
  1. CoreDNS
  2. dashboard
  3. Ingress Controller
  4. Federation
  5. Prometheus

组件说明:

CoreDNS:可以为集群中的SVC创建一个域名IP的对应关系解析

dashboard:给K8S集群提供一个B/S结构访问体系

Ingress Controller:官方只能实现四层代理,Ingress可以实现七层代理

Federation:提供一个可以跨集群中心多K8S统一管理功能

Prometheus:提供K8S集群的监控能力

ELK:提供K8S集群日志统一分析介入平台

Pod概念

在同一个Pod里边容器的服务端口不能冲突,因为一个Pod内所有容器都共享的是pause容器的网络栈,在内部用在同一个Pod里边所有容器即共享网络又共享容器圈,当运行Pod时,pause容器会随之运行,容器在Pod内部互相访问用的是pause的 lo 网卡

在这里插入图片描述

控制器

ReplicationController 用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来代替;如果异常多出来的容器也会自动回收。在新版Kubernetes中建议使用ReplicaSet来取代ReplicationController

ReplicaSet跟ReplicationController 没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的selector

虽然ReplicaSet可以独立使用,但是一般还是会建议使用Deployment来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但deployment支持)

deployment工作原理

当deployment创建出来以后,它会去创建出来一个RS(ReplicaSet),RS不是我们自己定义的,而是deployment定义的,deployment在去创建我们Pod,如:v1

在这里插入图片描述

如果需要回滚更新,将Pod v1版本更新到v2版本,它会再创建一个RS,如RS-1,然后创建一个v2容器停掉一个v1容器,在再创建一个v2容器停掉一个v1容器…,总体数量保持不变,这样就达到一个滚动跟新的效果了;如果发现升级到v2版本有bug,则需要回滚,原理是当deployment创建出来RS-1的时候,并不会删除原来的RS,而是停掉RS,然后启动原来的RS,然后创建容器v1

在这里插入图片描述

HPA(HorizontalPodAutoScale)工作原理

Horizontal Pod AutoScale仅适用于Deployment和ReplicaSet,在V1版本中仅支持根据Pod的CPU利用率扩所容,在vlalpha版本中,支持根据内存和用户自定义的metric扩缩容。也就是根据Pod的CPU利用率进行平滑扩展。
在这里插入图片描述

HPA会去监控Pod(v2)的CPU利用率,当CPU利用率达到80的时候,HPA就会创建新的Pod,直到CPU小于80,最多创建10个,当CPU利用率过低时就会回收Pod,最少保留2个。

StatefullSet

StatefullSet 是为了解决有状态服务的问题(对应Deployment和ReplicaSets 是为无状态服务而设计),其应用场景包括:

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标志,即Pod重新调度后其 PodName 和 HostName 不变,基于Headless Service(即没有Cluster IP 的 Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是 running 和 Ready 状态),基于 init containers 来实现
  • 有序收缩,有序删除(即从N-1 到 0)

有状态服务典型的是mysql,无状态服务典型的是apache;有序部署例如:生产环境部署了nginx、Apache、mysql,启动顺序应该是先启动mysql,然后启动Apache,最后启动nginx,如果先启动nginx的话,nginx会找不到Apache,因为此时Apache还未启动,同理,Apache在启动后会去找mysql,此时mysql还没有启动,Apache是找不到mysql或者报错的。

DaemonSet

DaemonSet 确保全部(或者一些)Node 上运行一个Pod的副本。当有Node加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群中移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有Pod

使用 DaemonSet 的一些典型用法:

  • 运行集群存储 daemon ,例如在每个 Node 上运行 glusterd、ceph 。
  • 在每个 Node 上运行日志收集 daemon ,例如fluentd、logstash 。
  • 在每个 Node 上运行监控 daemon ,例如 Prometheus Node Exporter 。

Job ,Cronjob

Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或者多个Pod成功结束

Cron Job 管理基于时间的 Job,即:

  • 在给定时间点只运行一次
  • 周期性的在给定时间点运行

服务发现

在这里插入图片描述

当客户端需要访问服务时,访问service,service代理Pod,这里的Pod必须是一组,或者打着相同标签的Pod,这里边还有有个RR (Round Robin)的轮询算法在里边,例如轮询Pod
在这里插入图片描述

网络通讯方式

Kubernetes 的网络模型假定了所有 Pod 都在一个可以直接连通的扁平的网络空间中,这在GCE (Google Compute Engine)里边是现成的网络模型,Kubernetes 假定这个网络已经存在。而在私有云里搭建 Kubernetes 集群,就不能既定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker 容器之间的互相访问先打通,然后运行Kubernetes

同一个 Pod 内多个容器之间:lo

各 Pod 之间的通讯:Overlay Network

Pod 与 Service 之间的通讯:各节点的 IPtables 规则

集群外部与Service间的通信

Kubernetes + Flannel

Flannel 是 coreOS 团队针对 Kubernetes 设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚IP地址。而且它还能在这些 IP 地址之间建立一个覆盖网络 (Overlay Network),通过这个覆盖网络,将数据包原封不动的传递到目标容器内。

在这里插入图片描述

这里边运行了4个 Pod 分别是APP1、APP2、APP3、Backend,正常一个请求先到达 Backend,然后 Backend 在和 APP1-APP3 进行通讯,然而 Backend 和APP3 通讯是不同的 Pod 之间的通讯,而 Backend 和 APP1 通讯则是跨主机进行通讯。

在我们真实的服务器上我们会去安装一个 Flanneld 的守护进程,这个进程会监听一个端口,这个端口就是后期转发数据包的服务端口,这个 Flanneld 一旦启动后它会开启一个网桥叫 Flannel0 ,这个网桥 Flannel0 专门去收集 Docker0 转发出来的数据报文,然后这个Docker0 会分配自己的 IP 到对应的 Pod 上,如果是同一台主机的不同 Pod 之间的访问,它走的其实是 Docker0 的网桥,因为大家都是在同一个网桥下不同的子 IP 。

APP2 和 Backend 进行通讯,流程为:原地址写自己的 10.1.15.2 目标写 10.1.20.3 ,目标网段和自己不是同网段,所以 APP2 要发到它的网关 Docker0 ,Docker0里边会有对应的钩子函数将报文抓到 Flannel0 里,Flannel0 中有一堆路由表记录,这些路由表是从我们的etcd中获取到的,数据包从 Flannel0 到 Flanneld ,到 Flanneld 后它会对这个数据报文进行封装,第一层是我们的mac部分,第二层写的是当前物理机的 IP ,第三层写的是目标物理主机的 IP 192.168.66.12 ,第四层封装是 UDP 的报文,也就意味着 Flanneld 使用的是 UDP 的数据报文来转发这些数据包的,第五层又进行了封装,原是 10.1.15.2 目标是10.1.20.3 最外层封装了数据包实体–payload 。因为第三层中写的目标物理主机是 192.168.66.12 ,所有数据会被 192.168.66.12 主机的Flanneld所截获,截获之后 Flanneld 会拆封,拆封完后转发道 Flannel0 ,Flannel0 会转发到 Docker0 ,Docker0 会路由到 Backend 。

注意:为什么第三层中它会知道目标 Pod 对应的主机 IP呢,是因为 Flannel 会监控每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表。

etcd 之 Flannel 提供说明:

存储管理 Flannel 可分配的 IP 地址段资源

监控 etcd 中每个 Pod 的实际地址,并在内存中建立维护 Pod 节点路由表

Flannel 在启动后会向 etcd 中插入 可以被分配的网段,并且把哪个网段分配给哪台机器了,它会记录上。防止已分配的网段在被 Flannel 利用分配给其他的Node节点,这样可以防止 IP 冲突,

不同情况下网络通信方式

同一个 Pod 内部通讯:同一个 Pod 共享同一个网络命名空间,共享同一个 linux 协议栈

Pod1 至 Pod2

第一种情况:Pod1 与 Pod2 不在同一台主机,Pod的地址是与 docker0 在同一个网段的,但 docker0 网段与宿主机网卡是两个完全不同的 IP 网段,并且不同 Node 之间的通信只能通过宿主机的物理网卡进行。将 Pod 的 IP 和所在 Node 的 IP 关联起来,通过这个关联让 Pod 可以互相访问。

第二种情况:Pod1 与 Pod2 在同一台机器,由 Docker0 网桥直接转发请求至 Pod2 ,不需要经过Flannel

Pod 至 Service 的网络:目前基于性能考虑,全部为 LVS 维护和准发

Pod 到外网: Pod 向外网发请求,查找路由表,转发数据包到宿主机的网卡,宿主网卡完全成路由选择后,iptables 执行 Masquerade ,把源 IP 更改为宿主网卡的 IP,然后向外网服务器发送请求,也就是 Pod 想上网通过 snat 动态转换进行上网。

外网访问 Pod:Service (Node port)

组件通讯示意图

在这里插入图片描述

k8s 一共有三成网络,只有节点网络才是真实的网络,Pod 网络和 Service 网络都是虚拟网络,也是内部网络。

典型的K8S Runtime架构

从最常见的Docker说起,kubelet和Docker的集成方案图如下:

在这里插入图片描述

当kubelet要创建一个容器时,需要以下几步:

  1. Kubelet 通过 CRI 接口(gRPC)调用 dockershim,请求创建一个容器。CRI 即容器运行时接口(Container Runtime Interface),这一步中,Kubelet 可以视作一个简单的 CRI Client,而 dockershim 就是接收请求的 Server。目前 dockershim 的代码其实是内嵌在 Kubelet 中的,所以接收调用的凑巧就是 Kubelet 进程;
  2. dockershim 收到请求后,转化成 Docker Daemon 能听懂的请求,发到 Docker Daemon 上请求创建一个容器。
  3. Docker Daemon 早在 1.12 版本中就已经将针对容器的操作移到另一个守护进程——containerd 中了,因此 Docker Daemon 仍然不能帮我们创建容器,而是要请求 containerd 创建一个容器;
  4. containerd 收到请求后,并不会自己直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让 containerd-shim 去操作容器。这是因为容器进程需要一个父进程来做诸如收集状态,维持 stdin 等 fd 打开等工作。而假如这个父进程就是 containerd,那每次 containerd 挂掉或升级,整个宿主机上所有的容器都得退出了。而引入了 containerd-shim 就规避了这个问题(containerd 和 shim 并不是父子进程关系);
  5. 我们知道创建容器需要做一些设置 namespaces 和 cgroups,挂载 root filesystem 等等操作,而这些事该怎么做已经有了公开的规范了,那就是 OCI(Open Container Initiative,开放容器标准)。它的一个参考实现叫做 runC。于是,containerd-shim 在这一步需要调用 runC 这个命令行工具,来启动容器;
  6. runC 启动完容器后本身会直接退出,containerd-shim 则会成为容器进程的父进程,负责收集容器进程的状态,上报给 containerd,并在容器中 pid 为 1 的进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程。

详细文档请参考:浅析 k8s 容器运行时演进

核心组件

配置存储中心

主控(master)节点

- kube-apiserver服务
- kube-controller-manager服务
- kube-scheduler服务

运算(node)节点

- kube-kubelet服务
- kube-proxy服务

CLI客户端

- kubectl

核心附件

- CNI网络插件-->flannel/calico
- 服务发现用插件-->coredns
- 服务暴露用插件-->traefik
- GUI管理插件-->Dashboard

apiserver

- 提供了集群管理的REST API接口(包括鉴权、数据校验以及集群状态变更)
- 负责其他模块之间的数据交互,承担通信枢纽功能
- 是资源配额控制的入口
- 提供完备的集群安全机制

controller-manager

- 由一系列控制器组成,通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态
- Node Controller
- Deployment Controller
- Service Controller
- Volume Controller
- Endpoint Controller
- Garbage Controller
- Namespace Controller
- Job Controller
- Resource quta Controller
- ......

scheduler

- 主要功能是接收调度pod到适合的运算节点上
- 预算策略(predict)
- 优选策略(priorities)

kubelet

- 简单的说,kubelet的主要功能就是定时从某个地方获取节点上pod的期望状态(运行什么容器、运行的副本数量、网络或者存储如何配置等等),并调用对应的容器平台接口达到这个状态
- 定时汇报当前节点的状态给apiserver,以供调度的时候使用
- 镜像和容器的清理工作,保证节点上镜像不会占满磁盘空间,退出的容器不会占用太多资源

kube-proxy

- 是k8s在每个节点上运行网络代理,service资源的载体
- 建立了pod网络和集群网络的关系(clusterrip-->podip)
  • 常用三种流量调度模式
    • Userspace(废弃)
      • Iptables(濒临废弃)
      • Ipvs(推荐)
  • 负责建立和删除包括更新调度规则、通知apiserver自己的更新,或者从apiserver哪里获取其他kube-proxy的调度规则变化来更新自己的。
  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值