Kubernetes(k8s)的核心设计介绍

2022年8月28日20:52:42云计算与大数据评论158 views字数 4379阅读模式

得益于 docker 的特性,服务的创建和销毁变得非常快速、简单。Kubernetes 正是以此为基础,实现了集群规模的管理、编排方案,使应用的发布、重启、扩缩容能够自动化。本篇介绍 Kubernetes 的核心设计。

目录

    • 1. 编排抽象
      • Pod 对象
      • Service 对象
    • 2. 声明式 API
    • 3. 开放插件

 

总结 Kubernetes 核心设计主要概况为如下三点:

1. 编排抽象

容器平台核心点不在于创建和调度容器,而是在上层架构抽象出各种对象,便于去统一管理。Kubernetes 创造性的抽象出了各个编排的关系,例如亲密关系 (Pod 对象)、访问关系(Service 对象)等。

Pod 对象

Pod 直译是豆荚,可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起就是豆荚(一个 Pod)。在 k8s 中我们不会直接操作容器,而是把容器包装成 Pod 再进行管理。
Kubernetes(k8s)的核心设计介绍

Kubernetes 在对象抽象方面,核心创新在于 Pod 对象的设计。
Pod 是 Kubernetes 项目中最小的 API 对象。换句话说 Pod 是 Kubernetes 最基本的操作单元,包含一个或多个紧密相关的容器,一个 Pod 可以被一个容器化的环境看作应用层的 “逻辑宿主机”;
一个 Pod 中的多个容器应用通常是紧密耦合的,Pod 在 Node 上被创建、启动或者销毁;
每个 Pod 里运行着一个特殊的被称之为 Pause 的容器,其他容器则为业务容器,这些业务容器共享 Pause 容器的网络栈和 Volume 挂载卷,因此他们之间通信和数据交换更为高效,在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个 Pod 中。同一个 Pod 里的容器之间仅需通过 localhost 就能互相通信。
一个 Pod 中的应用容器共享同一组资源:

  • PID 命名空间:Pod 中的不同应用程序可以看到其他应用程序的进程 ID;
  • 网络命名空间:Pod 中的多个容器能够访问同一个 IP 和端口范围;
  • IPC 命名空间:Pod 中的多个容器能够使用 SystemV IPC 或 POSIX 消息队列进行通信;
  • UTS 命名空间:Pod 中的多个容器共享一个主机名;
  • Volumes(共享存储卷):Pod 中的各个容器可以访问在 Pod 级别定义的 Volumes;

Pod 的生命周期通过 Replication Controller 来管理;通过模板进行定义,然后分配到一个 Node 上运行,在 Pod 所包含容器运行结束后,Pod 结束(其中, pod.status.phase,就是 Pod 的当前状态,它有如下几种可能的情况:PendingRunningSucceededFailedUnknown)。

POD 操作示例:
–创建一个 nginx pod

kubectl run ng --image=nginx:1.9 --port=80

–状态检查

kubectl  get pod name
kubectl  describe pod name
kubectl  logs name

–通过 yaml 创建 pod,通过–dry-run 来生成一个 yaml 文件

kubectl run ng --image=nginx:1.9 --port=80 --dry-run=client -o yaml >ng.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ng
  name: ng
spec:
  containers:
  - image: nginx:1.9
    name: ng
    ports:
    - containerPort: 80
    resources: {
   }
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {
   }

–一个 pod 运行多个容器

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ng01
  name: multi-pod
spec:
  containers:
    - image: nginx:1.9
      name: ng01
      ports:
        - containerPort: 80
      resources: {
    }
    - image: tomcat:8.0.41-jre8-alpine
      name: tomcat8-1
      ports:
        - containerPort: 8080
      resources: {
    }
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {
    }

这个容器运行了两个容器 nginx 和 tomcat,执行 kubectl apply -f multi.yaml 后,查看 pod。

–删除 pod

kubectl delete pod ng

Service 对象

Kubernetes 编排抽象的另一个核心对象是 Service 对象。
在 Kubernetes 的世界里,虽然每个 Pod 都会被分配一个单独的 IP 地址,但这个 IP 地址会随着 Pod 的销毁而消失,这就引出一个问题:如果有一组 Pod 组成一个集群来提供服务,那么如何来访问它呢?
Service!一个 Service 可以看作一组提供相同服务的 Pod 的对外访问接口,Service 作用于哪些 Pod 是通过 Label Selector 来定义的。
下图是 kube-proxy 通过 iptables 模式来实现 Service 的过程,Service 对象有一个虚拟 clusterIP,集群内请求访问 clusterIP 时,会由 iptables 规则负载均衡到后端 endpoints。
Kubernetes(k8s)的核心设计介绍

服务编排通俗地说就是将一个服务在合适的时间放在一个合适的地方,让其按照规划的方式运行。

  • 合适的时间:当实际服务状态和预期状态不相符的时候;
  • 合适的地方:资源最充足的地方;
  • 规划的方式:满足用户的需求;

K8s 编排服务工作流程:

  1. 客户端提交创建请求;
  2. API Server 筛选合适的节点;
  3. API Server 向指定节点 Kubelet 下发创建任务;
  4. Kubelet 创建 Pod;
  5. Kubelet 上报节点状态。

2. 声明式 API

声明式 API 是整个系统自动化的核心要点,kubernetes 提供了以声明式 API 的方式将抽象对外暴露,同时也方便了用户管理对象。

Declarative(声明式设计)指的是一种软件设计理念和编程方式,描述了目标状态,由工具自行判断当前状态并执行相关操作至目标状态。声明式强调 What,目标是什么。而 Imperative (命令式) 需要用户描述一系列详细指令来达到期望的目标状态。命令式强调 How,具体如何做。

kubernetes 的一大核心设计就是采用了声明式 API,利用该设计思想有效的实现了系统的自动化运行。Kubernetes 声明式 API 指定了集群期望的运行状态,集群控制器会通过 List&Watch 机制来获取当前状态,并根据当前状态自动执行相应的操作至目标状态。
Kubernetes(k8s)的核心设计介绍

Kubernetes 中,用户通过提交定义好的 API 对象来声明期望状态,系统允许有多个 API 写端,以 PATCH 方式对 API 对象进行修改。Kubectl 工具支持三种对象管理方式:命令式命令行、命令式对象配置 (yaml)、声明式对象配置 (yaml)。举例如下:

  • 命令式命令行:
    特点:仅需一步就对集群做了修改。示例:创建一个 deployment 类型的 object
kubectl run nginx --image nginx

kubectl create deployment nginx --image nginx
  • 命令式对象配置:命令式对象配置:
kubectl create –f nginx.yaml
kubectl replace –f nginx.yaml
  • 声明式对象配置:声明式对象配置:
    特点:
    1)便捷性:不必添加大量的参数到命令行中执行命令。
    2)灵活性:YAML 可以创建比命令行更加复杂的结构。
    3)可维护性:YAML 文件可以通过源头控制,跟踪每次操作;并且对象配置可以存储在源控制系统中(比如 Git);对象配置同时也提供了用于创建对象的模板。
    kubectl apply –f nginx.yaml

Kubernetes 推荐使用:声明式对象配置 (YAML)。

3. 开放插件

支持系统资源插件化(比如计算、存储、网络);同时也支持用户自定义 CRD 和开发 Operator。

Kubernetes 的设计初衷就是支持可插拔的架构,解决 PaaS 平台不好用、不能用、需要定制化等问题。为了便于系统的扩展,K8S 集成了插件、附加组件、服务和接口来扩展平台的核心功能。附加组件被定义为与环境的其他部分无缝集成的组件,提供类似本机的特性,并扩展集群管理员可用的组件,扩展还可以用于添加自定义软硬件的支持;服务和接口提供了看似繁琐和冗余的设计(比如我们常见的 PV、PVC、SC),实际上为开发人员提供了更多的可扩展性。

Kubernetes 作为云原生应用的的基础调度平台,相当于云原生的操作系统,为了便于系统的扩展,Kubernetes 中开放的以下接口可对系统资源(计算、网络、存储)插件进行扩展,可分别对接不同的后端来实现自己的业务逻辑。
Kubernetes(k8s)的核心设计介绍

  • 网络插件 CNI
    CNI(Container Network Interface):容器网络接口,提供网络资源。
    跨主机容器间的网络互通已经成为基本要求,K8S 网络模型要求所有容器都可以直接使用 IP 地址与其他容器通信,而无需使用 NAT;所有宿主机都可以直接使用 IP 地址与所有容器通信,而无需使用 NAT。反之亦然。容器自己的 IP 地址,和别人(宿主机或者容器)看到的地址是完全一样的。K8S 提供了一个插件规范,称为容器网络接口 (CNI),只要满足 K8S 的基本需求,第三方厂商可以随意使用自己的网络栈,通过使用 overlay 网络来支持多子网或者一些个性化使用场景,所以出现很多优秀的 CNI 插件被添加到 Kubernetes 集群中。
  • 容器运行时 CRI
    CRI(Container Runtime Interface):容器运行时接口,提供计算资源。
    CRI 接口设计的一个重要原则是只关注接口本身,而不关心具体实现,kubelet 就只需要跟这个接口打交道。而作为具体的容器项目,比如 Docker、rkt、containerd、kata container 它们就只需要自己提供一个该接口的实现,然后对 kubelet 暴露出 gRPC 服务即可。简单来说,CRI 主要作用就是实现了 kubelet 和容器运行时之间的解耦。
  • 存储接口 CSI
    CSI(Container Storage Interface):容器存储接口,提供存储资源。
    K8S 将存储体系抽象出了外部存储组件接口,第三方存储厂商可以发布和部署公开的存储插件,无需接触 Kubernetes 核心代码,同时为 Kubernetes 用户提供了更多的存储选项。例如:AWS、NFS、Ceph。

小结:无论多么复杂的应用程序,Kubernetes 都可以很好的支持,这使得基于 K8S 的 PaaS 平台非常健壮,并且能够更有效地应对现代云计算带来的挑战。

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/yunda/27491.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定