侧边栏壁纸
博主头像
cloudnative-blog博主等级

I can break through the limitations !

  • 累计撰写 23 篇文章
  • 累计创建 12 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

一.k8s简介

周锐豪
2023-11-08 / 0 评论 / 0 点赞 / 77 阅读 / 14239 字 / 正在检测是否收录...

一. k8s简介

1.k8s简介

    Kubernetes(通常称为K8s,K8s是将8个字母“ubernete”替换为“8”的缩写)是一个以容器为中心的基础架构,可以实现在物理集群或虚拟机集群上调度和运行容器,提供容器自动部署、扩展和管理的开源平台。满足了应用程序在生产环境中的一些通用需求:应用实例副本、水平自动扩展、命名与发现、负载均衡、滚动升级、资源监控等。

2.k8s的特点

(1)自我修复

在节点故障时重新启动失败的容器,替换和重新部署,保证预期的副本数量;杀死健康检查失败的容器,并且在未准备好之前不会处理客户端请求,确保线上服务不中断。

(2)弹性伸缩

使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例,保证应用业务高峰并发时的高可用性;业务低峰时回收资源,以最小成本运行服务。

(3)自动部署和回滚

K8S采用滚动更新策略更新应用,一次更新一个Pod,而不是同时删除所有Pod,如果更新过程中出现问题,将回滚更改,确保升级不受影响业务。

(4)服务发现和负载均衡

K8S为多个容器提供一个统一访问入口(内部IP地址和一个DNS名称),并且负载均衡关联的所有容器,使得用户无需考虑容器IP问题。

(5)机密和配置管理

管理机密数据和应用程序配置,而不需要把敏感数据暴露在镜像里,提高敏感数据安全性。并可以将一些常用的配置存储在K8S中,方便应用程序使用。

(6)存储编排

挂载外部存储系统,无论是来自本地存储,公有云(如AWS),还是网络存储(如NFS、GlusterFS、Ceph)
都作为集群资源的一部分使用,极大提高存储使用灵活性。

(7)批处理

提供一次性任务,定时任务;满足批量数据处理和分析的场景。

(8)认证和授权

支持角色访问控制(RBAC)认证授权等策略。

(9)服务编排

通过文件描述部署服务,使得应用程序部署变得更高效。

二.k8s的组件

1.master组件

控制平面,负责集群的决策

Kubectl:客户端命令行工具,作为整个K8s集群的操作入口
Api Server:作为资源操作的唯一入口,它提供了认证、授权、访问控制、API注册和发现等机制。客户端与k8s群集及K8s内部组件的通信,都要通过Api Server这个组件
Controller-manager:负责维护群集的状态,比如故障检测、自动扩展、滚动更新等
Scheduler:负责资源的调度,按照预定的调度策略将pod调度到相应的node节点上
Etcd:负责存储集群中各种资源对象的信息,k/v方式存储,所有的 k8s 集群数据存放在此

2.node组件

数据平面,负责为容器提供运行环境

kubelet:负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器,会按固定频率检查节点健康状态并上报给 APIServer,该状态会记录在 Node 对象的 status 中。
kube-proxy:负责提供集群内部的服务发现和负载均衡,主要就是为 Service 提供服务的,来实现内部从 Pod 到 Service 
和外部 NodePort 到 Service 的访问。
容器:docker或container

image-20240102160322959

三.k8s的核心概念

1.Pod

1.1pod简介

  在 Kubernetes 中,Pod是最小的可部署的单位,它是一个或多个容器的集合,它们共享同一个网络命名空间和存储卷。Pod是Kubernetes中的基本概念,所有的容器化应用都运行在Pod中。

  共享网络命名空间:Pod中的所有容器共享同一个网络命名空间,它们可以使用相同的IP地址和端口号,从而可以轻松地相互通信。
  共享存储卷:Pod中的所有容器共享同一个存储卷,它们可以访问存储卷中的相同数据。这使得在多个容器之间共享数据变得非常容易。
  容器间通信:在同一个Pod中的容器可以使用本地主机通信,从而避免了跨主机网络通信的开销和延迟。

1.2pod的状态

挂起(Pending): apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
运行中(Running): pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
成功(Succeeded): pod中的所有容器都已经成功终止并且不会被重启
失败(Failed): 所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
未知(Unknown): apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致

1.3创建pod过程

(1)客户端提交Pod的配置信息(可以是yaml文件定义好的信息)到kube-apiserver;
(2)Apiserver收到指令后,通知给controller-manager创建一个资源对象;
(3)Controller-manager通过api-server将pod的配置信息存储到ETCD数据中心中;
(4)Kube-scheduler检测到pod信息会开始调度预选,会先过滤掉不符合Pod资源配置要求的节点,然后开始调度调优,主要是挑选出更适合运行pod的节点,然后将pod的资源配置单发送到node节点上的kubelet组件上。
(5)Kubelet根据scheduler发来的资源配置单运行pod,运行成功后,将pod的运行信息返回给scheduler,scheduler将返回的pod运行状况的信息存储到etcd数据中心。

image-20240102160322959

1.4pod镜像拉取策略

IfNotPresent:默认值,镜像在宿主机上不存在才拉取
Always:每次创建Pod都会重新拉取一次镜像
Never:Pod永远不会主动拉取这个镜像

1.5pod重启策略

Always:(默认情况下使用)只要Pod对象终止就将其重启;
OnFailure:仅在Pod对象出现错误时才将其重启;
Never:从不重启;

2.控制器

2.1Deployment

创建Pod和ReplicaSet,并提供对pod的声明性更新以及许多其他的功能
滚动升级和回滚应用
扩容和缩容
暂停和继续Deployment

应用场景:nginx,java程序

2.2Daemonset

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

应用场景:Agent, 例如监控采集工具, 日志采集工具

2.3StatefulSet

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

应用场景: mysql,kafka+zk

2.4Job

负责批量处理短暂的一次性任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束。

应用场景: 离线数据处理, 视频解码等业务

2.5CronJob

定时任务,类似于Linux系统的crontab,在指定的时间周期运行指定的任务

应用场景:通知, 备份

2.6ReplicaSet(RS)

ReplicaSet的主要作用是保证一定数量的pod正常运行,它会持续监听这些Pod的运行状态,一旦Pod发生故障,就会重启或重建。同时它还支持对pod数量的扩缩容和镜像版本的升降级。

3.service

3.1简介

    在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。
    为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。
    Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。

image-20240102162143683

3.2常用类型

3.2.1ClusterIP

默认值,它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问

3.2.2HeadLiness

在某些场景中,开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。

3.2.3NodePort

NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。

3.2.4LoadBalancer

LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。

3.2.5ExternalName

ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。

3.3kube-proxy的模式

3.3.1iptables

    iptables模式下,kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP。该模式下kube-proxy不承担四层负责均衡器的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。

image-20240102163844300

3.3.2ipvs

ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。

支持的算法
    rr:轮询 默认是这个
    lc:最少连接(打开连接数最少)
    dh:目标地址哈希
    sh:源地址哈希
    sed:最短预期延迟
    nq:最少队列

image-20240102163917637

4.name

  由于K8S内部,使用“资源”来定义每一种逻辑概念(功能),所以每种“资源”,都应该有自己的“名称”。
  “资源”有api 版本(apiversion) 、类别(kind) 、元数据(metadata) 、定义清单(spec) 、状态(status) 等配置信息。
  “名称”通常定义在“资源”的“元数据”信息里。在同一个namespace 空间中必须是唯一的。

5.namespace

5.1简介

Kubernetes中的Namespace是一种用于在集群内部组织和隔离资源的机制。一个Namespace可以看作是一个虚拟的集群,它将物理集群划分为多个逻辑部分,每个部分都有自己的一组资源(如Pod、Service、ConfigMap等)。

5.2作用

5.2.1资源隔离

可为不同的团队/用户(或项目)提供虚拟的集群空间,共享同一个Kubernetes集群的资源。比如可以为前端项目创建一个Namespace view,前端的项目部署在view命名空间中,后端项目创建另一个Namespace server,后端的项目部署运行在命名空间server中,或者为开发、测试、生产环境创建不同的Namespace,以做到彼此之间相互隔离,互不影响。我们可以使用 ResourceQuota 与 Resource LimitRange 来指定与限制 各个namesapce的资源分配与使用

5.2.2权限控制

权限控制:可以指定一个namespace的资源是否能够访问另一个namespace中的资源,比如:pod

6.label

   标签,是 K8S 特色的管理方式,便于分类管理资源对象。Label 可以附加到各种资源对象上,例如 Node、Pod、Service、RC 等,用于关联对象、查询和筛选。
   一个 Label 是一个 key-value 的键值对,其中 key 与 value 由用户自己制定。
   如果pod,node,service,ingress,hpa等资源的label一致的话,那么这些资源将会进行关联

四.k8s的部署

1.k8s的三种部署方式

(1)minikube

Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,仅用于尝试
Kubernetes或日常开发的用户使用。
部署地址:https://kubernetes.io/docs/setup/minikube/

(2)kubeadm

Kubeadm也是一个工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。
部署地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/

(3)二进制包

推荐,从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
下载地址:https://github.com/kubernetes/kubernetes/releases

五.k8s网络

1.coredns

    Service 通过虚拟ip或者节点端口为用户应用提供访问入口,然尔这些和端口都是动态分配的,如果用户重建一个服务,其分配的clusterip和nodeport都是会发生变化的,与通常的互联网应用类似,用户自定义的服务会获得一个域名,无论服务重建多少次,只要服务名不变,对应的域名也不会发生变化
    CoreDNS 包含一个内存态DNS,CoreDNS的实现原理是控制器监听service和endpoint的变化并配置DNS,客户端pod在进行域名解析时,从CoreDNS中查询服务对应的地址记录。
最终的目的是让k8s获得一个固定的可访问的域名地址

示例: nginx.default.svc.cluster.local:80
     podname.namespcae.svc.cluster.local:port

六.k8s的网络模型

1.Kubernetes网络模型设计基本要求

一个Pod一个IP
每个Pod独立IP,Pod内所有容器共享网络(同一个IP)
所有容器都可以与所有其他容器通信
所有节点都可以与所有容器通信

2.Calico

2.1简介

Calico是一个纯三层的网络插件,calico的bgp模式类似于flannel的host-gw
calico方便集成 OpenStack这种 IaaS云架构,为openstack虚拟机、容器、裸机提供多主机间通信。

2.2calico原理

    Calico把每个操作系统的协议栈认为是一个路由器,然后把所有的容器认为是连在这个路由器上的网络终端,在路由器之间跑标准的路由协议——BGP的协议,然后让它们自己去学习这个网络拓扑该如何转发。所以Calico方案其实是一个纯三层的方案,也就是说让每台机器的协议栈的三层去确保两个容器,跨主机容器之间的三层连通性。

2.3calico架构

image-20240104172328085

(1)Felix

calico的核心组件,运行在每个节点上。主要的功能有接口管理、路由规则、ACL规则和状态报告:
    接口管理: Felix为内核编写一些接口信息,以便让内核能正确的处理主机endpoint的流量。特别是主机之间的ARP请求和处理ip转发。
    路由规则: Felix负责主机之间路由信息写到linux内核的FIB(Forwarding Information Base)转发信息库,保证数据包可以在主机之间相互转发。
    ACL规则: Felix负责将ACL策略写入到linux内核中,保证主机endpoint的为有效流量不能绕过calico的安全措施。
    状态报告: Felix负责提供关于网络健康状况的数据。特别是,它报告配置主机时出现的错误和问题。这些数据被写入etcd,使其对网络的其他组件和操作人员可见。

(2)etcd

etcd保证数据一致性的数据库,存储集群中节点的所有路由信息。为保证数据的可靠和容错建议至少三个以上etcd节点。

(3)Orchestrator plugin

协调器插件负责允许kubernetes或OpenStack等原生云平台方便管理Calico,可以通过各自的API来配置Calico网络实现无缝集成。如kubernetes的cni网络插件。

(4)Bird

BGP客户端,Calico在每个节点上的都会部署一个BGP客户端,它的作用是将Felix写入内核的路由信息,通过BGP协议在集群中分发。当Felix将路由插入到Linux内核FIB中时,BGP客户端将获取这些路由并将它们分发到部署中的其他节点。这可以确保在部署时有效地路由流量。

(5)BGP Router Reflector

大型网络仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,所有节点需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。

(6)Calicoctl

calico 命令行管理工具

2.4calico的网络模式

(1) IPIP

流量:tunl0设备封装数据,形成隧道,承载流量。
适用网络类型:适用于互相访问的pod不在同一个网段中,跨网段访问的场景。外层封装的ip能够解决跨网段的路由问题。
效率:流量需要tunl0设备封装,效率略低。

image-20240104174205060

(2) BGP

流量:使用主机路由表信息导向流量
适用网络类型:适用于互相访问的pod在同一个网段,适用于大型网络。
效率:原生hostGW,效率高。

image-20240104174223633

3.flannel

3.1简介

    Flannel 由CoreOS开发,用于解决docker集群跨主机通讯的覆盖网络(overlay network),它的主要思路是:预先留出一个网段,每个主机使用其中一部分,然后每个容器被分配不同的ip;让所有的容器认为大家在同一个直连的网络,底层通过UDP/VxLAN/Host-GW等进行报文的封装和转发。
    Flannel实质上是一种“覆盖网络(overlaynetwork)”,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等数据转发方式, 默认的节点间数据通信方式是UDP转发。
    它的功能是 让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
    Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得同属一个内网且不重复的IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。 

3.2flannel原理

    集群中的不同节点上,创建的Pod具有全集群唯一的虚拟IP地址。
    建立一个覆盖网络(overlay network),通过这个覆盖网络,将数据包原封不动的传递到目标容器。覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后,将其解封装。
    创建一个新的虚拟网卡flannel0接收docker网桥的数据,通过维护路由表,对接收到的数据进行封包和转发(vxlan)。
    etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化,实时感知集群中node的变化。

3.3组件

(1) cni0

网桥设备,每创建一个pod都会创建一对 veth pair。其中一段是pod中的eth0,另一端是cni0网桥中的端口。

(2) flannel.1

vxlan网关设备,用户 vxlan 报文的解包和封包。不同的 pod 数据流量都从overlay设备以隧道的形式发送到对端。flannel.1不会发送arp请求去获取目标IP的mac地址,而是由Linux kernel将一个"L3 Miss"事件请求发送到用户空间的flanneld程序,flanneld程序收到内核的请求事件后,从etcd中查找能够匹配该地址的子网flannel.1设备的mac地址,即目标pod所在host中flannel.1设备的mac地址。

(3) flanneld

在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库,为flannel.1设备提供封装数据时必要的mac,ip等网络数据信息。

3.4网络模式

(1) udp

使用设备flannel.0进行封包解包,不是内核原生支持,上下文切换较大,性能非常差

(2) vxlan

流量:flannel.1设备封装数据,形成隧道,承载流量。
适用网络类型:适用于互相访问的pod不在同一个网段中,跨网段访问的场景。隧道转发能够解决跨网段的路由问题。
效率:使用flannel.1进行封包解包,内核原生支持,性能损失在20%~30%左右

image-20240108161627874

(3) host-gw

流量:采用纯静态路由的方式,要求所有宿主机都在一个局域网内,跨局域网无法进行路由
适用网络类型:适用于互相访问的pod在同一个网段,跨局域网无法进行路由。
效率:无需flannel.1这样的中间设备,直接宿主机当作子网的下一跳地址,性能损失大约在10%左右

image-20240108161610357

0

评论区