kubernetes k8s 云原生技术

本文深入探讨了云原生的关键技术,包括容器化、Kubernetes核心概念和架构,以及调度策略。介绍了容器的进程隔离、镜像、生命周期管理,详细阐述了Kubernetes的服务发现、调度、Pod、Deployment、Job等核心概念,并分析了调度器的工作原理和扩展性。文章还对比了容器与虚拟机的区别,展示了云原生如何最大化利用云能力。
摘要由CSDN通过智能技术生成

云原生

【整理总结自 CNCF × Alibaba 云原生技术公开课

【非全部内容】

【图片看不到,可以去gitee上看】

相关定义和概念

云原生为用户指定了一条低心智负担的、敏捷的、能够以可扩展、可复制的方式最大化地利用云的能力、发挥云的价值的最佳路径。云原生其实是一套指导进行软件架构设计的思想。按照这样的思想而设计出来的软件:首先,天然就“生在云上,长在云上”;其次,能够最大化地发挥云的能力,使得我们开发的软件和“云”能够天然地集成在一起,发挥出“云”的最大价值。

技术范畴

  1. 第一部分是云应用定义与开发流程。这包括应用定义与镜像制作、配置 CI/CD、消息和 Streaming 以及数据库等。
  2. 第二部分是云应用的编排与管理流程。这也是 Kubernetes 比较关注的一部分,包括了应用编排与调度、服务发现治理、远程调用、API 网关以及 Service Mesh
  3. 第三部分是监控与可观测性。这部分所强调的是云上应用如何进行监控、日志收集、Tracing 以及在云上如何实现破坏性测试,也就是混沌工程的概念。
  4. 第四部分就是云原生的底层技术,比如容器运行时、云原生存储技术、云原生网络技术等。
  5. 第五部分是云原生工具集,在前面的这些核心技术点之上,还有很多配套的生态或者周边的工具需要使用,比如流程自动化与配置管理、容器镜像仓库、云原生安全技术以及云端密码管理等。
  6. 最后则是 Serverless。Serverless 是一种 PaaS 的特殊形态,它定义了一种更为“极端抽象”的应用编写方式,包含了 FaaS 和 BaaS 这样的概念。而无论是 FaaS 还是 BaaS,其最为典型的特点就是按实际使用计费(Pay as you go),因此 Serverless 计费也是重要的知识和概念

两个理论

  • 第一个理论基础是:不可变基础设施。这一点目前是通过容器镜像来实现的,其含义就是应用的基础设施应该是不可变的,是一个自包含、自描述可以完全在不同环境中迁移的东西;
  • 第二个理论基础就是:云应用编排理论。当前的实现方式就是 Google 所提出来的“容器设计模式”,这也是本系列课程中的 Kubernetes 部分所需主要讲解的内容。

云原生关键技术点

  1. 如何构建自包含、可定制的应用镜像
  2. 能不能实现应用快速部署与隔离能力;
  3. 应用基础设施创建和销毁的自动化管理
  4. 可复制的管控系统和支撑组件

容器

进程间隔离

操作系统中进程有自己的特点:

  • 进程可以相互看到并通信–》高级权限的进程可以攻击其他进程
  • 进程使用同一个文件系统–》高级权限进程对其他进程数据进行增删改查,破环其正常运行;此外进程与进程之间依赖容易产生冲突
  • 进程会使用相同的资源–》进程与进程之间会存在资源抢占的问题

解决办法:提供一个独立的运行环境

  • chroot:将子目录变成根目录,达到视图级别的隔离;进程在 chroot 的帮助下可以具有独立的文件系统,对于这样的文件系统进行增删改查不会影响到其他进程
  • namespace:实现进程在资源的视图上进行隔离,不让进程相互看见
  • Cgroup :来限制其资源使用率,设置其能够使用的 CPU 以及内存量

namespace

  • mout namespace。mout namespace 就是保证容器看到的文件系统的视图,是容器镜像提供的一个文件系统,也就是说它看不见宿主机上的其他文件,除了通过 -v 参数 bound 的那种模式,是可以把宿主机上面的一些目录和文件,让它在容器里面可见的。

  • uts namespace,这个 namespace 主要是隔离了 hostname 和 domain

  • pid namespace,这个 namespace 是保证了容器的 init 进程是以 1 号进程来启动的。

  • network namespace,除了容器用 host 网络这种模式之外,其他所有的网络模式都有一个自己的 network namespace 的文件。

  • user namespace,这个 namespace 是控制用户 UID 和 GID 在容器内部和宿主机上的一个映射,不过这个 namespace 用的比较少。

  • IPC namespace,这个 namespace 是控制了进程间通信的一些东西,比方说信号量。

  • cgroup namespace,用 cgroup namespace 带来的一个好处是容器中看到的 cgroup 视图是以根的形式来呈现的,这样的话就和宿主机上面进程看到的 cgroup namespace 的一个视图方式是相同的。另外一个好处是让容器内部使用 cgroup 会变得更安全。

Cgroup(以docker为例)

  • cgroup 主要是做资源限制的,docker 容器有两种 cgroup 驱动:一种是 systemd 的,另外一种是 cgroupfs 的。
    • cgroupfs 比较好理解。比如说要限制内存是多少,要用 CPU share 为多少,其实直接把 pid 写入对应的一个 cgroup 文件,然后把对应需要限制的资源也写入相应的 memory cgroup 文件和 CPU 的 cgroup 文件就可以了。
    • 因为 systemd 本身可以提供一个 cgroup 管理方式,写 cgroup 操作都必须通过 systemd 的接口来完成,不能手动更改 cgroup 的文件
  • docker 常用cgroup
    • CPU,CPU 一般会去设置 cpu share 和 cupset,控制 CPU 的使用率
    • memory,是控制进程内存的使用量。
    • device ,device 控制了你可以在容器中看到的 device 设备。
    • freezer。它和第三个 cgroup(device)都是为了安全的。当你停止容器的时候,freezer 会把当前的进程全部都写入 cgroup,然后把所有的进程都冻结掉,这样做的目的是,防止你在停止的时候,有进程会去做 fork,防止进程逃逸到宿主机上面去,是为安全考虑。
    • blkio,blkio 主要是限制容器用到的磁盘的一些 IOPS(每秒读操作次数) 还有 bps(每秒读取块设备的数据量) 的速率限制。因为 cgroup 不唯一的话,blkio 只能限制同步 io,docker io 是没办法限制的
    • pid, 限制的是容器里面可以用到的最大进程数量

镜像

容器具有一个独立的文件系统,因为使用的是系统的资源,所以在独立的文件系统内不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可,这些容器运行时所需要的所有的文件集合称之为容器镜像。

构建容器镜像

通常情况下,我们会采用 Dockerfile 来构建镜像,这是因为 Dockerfile 提供了非常便利的语法糖,能够帮助我们很好地描述构建的每个步骤,每个构建步骤都会对已有的文件系统进行操作,这样就会带来文件系统内容的变化,我们将这些变化称之为 changeset。

changeset 的分层以及复用特点能够带来几点优势:

  • 第一,能够提高分发效率,对于大的镜像而言,如果将其拆分成各个小块就能够提高镜像的分发效率,这是因为镜像拆分之后就可以并行下载这些数据;

  • 第二,因为这些数据是相互共享的,也就意味着当本地存储上包含了一些数据的时候,只需要下载本地没有的数据即可,举个简单的例子就是 golang 镜像是基于 alpine 镜像进行构建的,当本地已经具有了 alpine 镜像之后,在下载 golang 镜像的时候只需要下载本地 alpine 镜像中没有的部分即可;

  • 第三,因为镜像数据是共享的,因此可以节约大量的磁盘空间,简单设想一下,当本地存储具有了 alpine 镜像和 golang 镜像,在没有复用的能力之前,alpine 镜像具有 5M 大小,golang 镜像有 300M 大小,因此就会占用 305M 空间;而当具有了复用能力之后,只需要 300M 空间即可。

如下图所示的 Dockerfile 适用于描述如何构建 golang 应用的。

img

如图所示:

  1. FROM 行表示以下的构建步骤基于什么镜像进行构建,正如前面所提到的,镜像是可以复用的;
  2. WORKDIR 行表示会把接下来的构建步骤都在哪一个相应的具体目录下进行,其起到的作用类似于 Shell 里面的 cd;
  3. COPY 行表示的是可以将宿主机上的文件拷贝到容器镜像内;
  4. RUN 行表示在具体的文件系统内执行相应的动作。当我们运行完毕之后就可以得到一个应用了;
  5. CMD 行表示使用镜像时的默认程序名字

docker Images

  • docker 镜像是基于联合文件系统的。联合文件系统:它允许文件是存放在不同的层级上面的,但是最终是可以通过一个统一的视图,看到这些层级上面的所有文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lH6CZJlG-1623207610981)(云原生.assets/image-20210607112239877.png)]

  • docker 镜像的存储,它的底层是基于不同的文件系统的,所以它的存储驱动也是针对不同的文件系统作为定制的,比如 AUFS、btrfs、devicemapper 还有 overlay。docker 对这些文件系统做了一些相对应的一个 graph driver 的驱动,也就是通过这些驱动把镜像存在磁盘上面。
  • 存储流程 overlay为例
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C88oZo3R-1623207610982)(云原生.assets/image-20210607112403069.png)]
    • lower 层,也就是镜像层,它是一个只读层
    • upper 层,容器的读写层,采用了写时复制的机制,也就是说只有对某些文件需要进行修改的时候才会从 lower 层把这个文件拷贝上来,之后所有的修改操作都会对 upper 层的副本进行修改
    • workdir,它的作用是充当一个中间层的作用。当对 upper 层里面的副本进行修改时,会先放到 workdir,然后再从 workdir 移到 upper 里面去。
    • mergedir,是一个统一视图层。从 mergedir 里面可以看到 upper 和 lower 中所有数据的整合,然后我们 docker exec 到容器里面,看到一个文件系统其实就是 mergedir 统一视图层
  • 文件操作 overlay为例
    • 读,如果 upper 层没有副本,数据都是从 lower 层上读取
    • 写,容器刚创建时,upper 层为控,只有对文件进行写操作时,才会从 lower 层拷贝文件上来,对副本进行操作
    • 删,overlay 里面其实是没有真正的删除操作的。它所谓的删除其实是通过对文件进行标记,然后从最上层的统一视图层去看,看到这个文件如果做标记,认为这个文件是被删掉的,就不会让这个文件显示出来。

容器生命周期

容器的生命周期和 initial 进程的生命周期是一致的, initial 进程退出的时候,所有的子进程也会随之退出

这样会导致有状态数据不能持久化,因此需要有数据卷的存在

数据卷的生命周期是独立于容器的生命周期的,其管理主要有两种方式:

  • 第一种是通过 bind 的方式,直接将宿主机的目录直接挂载到容器内;这种方式比较简单,但是会带来运维成本,因为其依赖于宿主机的目录,需要对于所有的宿主机进行统一管理。
  • 第二种是将目录管理交给运行引擎。

容器项目架构

moby 容器引擎架构

moby 是目前最流行的容器管理引擎,moby daemon 会对上提供有关于容器、镜像、网络以及 Volume的管理。moby daemon 所依赖的最重要的组件就是 containerd,containerd 是一个容器运行时管理引擎,其独立于 moby daemon ,可以对上提供容器、镜像的相关管理。

image-20210601143510308

containerd 底层有 containerd shim 模块,其类似于一个守护进程,这样设计的原因有几点:

  • 首先,containerd 需要管理容器生命周期,而容器可能是由不同的容器运行时所创建出来的,因此需要提供一个灵活的插件化管理。而 shim 就是针对于不同的容器运行时所开发的,这样就能够从 containerd 中脱离出来,通过插件的形式进行管理。
  • 其次,因为 shim 插件化的实现,使其能够被 containerd 动态接管。如果不具备这样的能力,当 moby daemon 或者 containerd daemon 意外退出的时候,容器就没人管理了,那么它也会随之消失、退出,这样就会影响到应用的运行。
  • 最后,因为随时可能会对 moby 或者 containerd 进行升级,如果不提供 shim 机制,那么就无法做到原地升级,也无法做到不影响业务的升级,因此 containerd shim 非常重要,它实现了动态接管的能力。
containerd 容器架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GrEpiS5l-1623207610984)(云原生.assets/image-20210607112937753.png)]

两大功能

  1. 对于容器生命周期的管理(左边)
  2. 镜像存储的管理(右边)

一个镜像存储的管理

  • 第一层
    • GRPC,containerd 对于上层来说是通过 GRPC server 的形式来对上层提供服务的
    • Metrics ,这个部分主要是提供 cgroup Metrics 的一些内容
  • 第二层
    • 左边是容器镜像的一个存储
    • 中线 images、containers 下面是 Metadata,这部分 Matadata 是通过 bootfs 存储在磁盘上面的。
    • 右边的 Tasks 是管理容器的容器结构Events 是对容器的一些操作都会有一个 Event 向上层发出,然后上层可以去订阅这个 Event,由此知道容器状态发生什么变化。
  • 第三层
    • Runtimes 层,这个 Runtimes 可以从类型区分,比如说 runC 或者是安全容器之类的
容器流程

start流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9E11ZndY-1623207610985)(云原生.assets/image-20210607113809704.png)]

组成部分:

  • 第一个部分是容器引擎部分,容器引擎可以是 docker,也可以是其它的。
  • 两个虚线框框起来的 containerd 和 containerd-shim,它们两个是属于 containerd 架构的部分。
  • 最下面就是 container 的部分,这个部分是通过一个 runtime 去拉起的,可以认为是 shim 去操作 runC 命令创建的一个容器

流程:

首先它会去创建一个 matadata,然后会去发请求给 task service 说要去创建容器。通过中间一系列的组件,最终把请求下发到一个 shim。containerd 和 shim 的交互其实也是通过 GRPC 来做交互的,containerd 把创建请求发给 shim 之后,shim 会去调用 runtime 创建一个容器出来

exec 流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oo0fZKhy-1623207610986)(云原生.assets/image-20210607113756658.png)]

exec 的操作还是发给 containerd-shim 的。对容器来说,去 start 一个容器和去 exec 一个容器,其实并没有本质的区别。

start 和 exec 区别:

  • exec 的时候,需要把这个进程加入到一个已有的 namespace 里面;
  • start 的时候,容器进程的 namespace 是需要去专门创建。

容器和虚拟机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N1iSaZ0J-1623207610986)(云原生.assets/image-20210601143638048.png)]

VM 利用 Hypervisor 虚拟化技术来模拟 CPU、内存等硬件资源,这样就可以在宿主机上建立一个 Guest OS,这是常说的安装一个虚拟机。

  • 容器是一个进程集合,具有自己独特的视图视角;
  • 镜像是容器所需要的所有文件集合,其具备一次构建、到处运行的特点;
  • 容器的生命周期和 initial 进程的生命周期是一样的;
  • 容器和 VM 相比,各有优劣,容器技术在向着强隔离方向发展。

Kubernetes 概念

核心功能
  • 服务的发现与负载的均衡

  • 容器的自动装箱,我们也会把它叫做 scheduling,就是“调度”,把一个容器放到一个集群的某一个机器上,Kubernetes 会帮助我们去做存储的编排,让存储的声明周期与容器的生命周期能有一个连接;

  • Kubernetes 会帮助我们去做自动化的容器的恢复。在一个集群中,经常会出现宿主机的问题或者说是 OS 的问题,导致容器本身的不可用,Kubernetes 会自动地对这些不可用的容器进行恢复;

  • Kubernetes 会帮助我们去做应用的自动发布与应用的回滚,以及与应用相关的配置密文的管理;

  • 对于 job 类型任务,Kubernetes 可以去做批量的执行

  • 为了让这个集群、这个应用更富有弹性,Kubernetes 也支持水平的伸缩

架构

Kubernetes 架构是一个比较典型的二层架构和 server-client 架构。Master 作为中央的管控节点,会去与 Node 进行一个连接。

image-20210601150729856

所有 UI 的、clients、这些 user 侧的组件,只会和 Master 进行连接,把希望的状态或者想执行的命令下发给 Master,Master 会把这些命令或者状态下发给相应的节点,进行最终的执行。

image-20210601151450930
  • **API Server:**顾名思义是用来处理 API 操作的,Kubernetes 中所有的组件都会和 API Server 进行连接,组件与组件之间一般不进行独立的连接,都依赖于 API Server 进行消息的传送;

  • **Controller:**是控制器,它用来完成对集群状态的一些管理。比如刚刚我们提到的两个例子之中,第一个自动对容器进行修复、第二个自动进行水平扩张,都是由 Kubernetes 中的 Controller 来进行完成的;

  • **Scheduler:**是调度器,“调度器”顾名思义就是完成调度的操作,就是我们刚才介绍的第一个例子中,把一个用户提交的 Container,依据它对 CPU、对 memory 请求大小,找一台合适的节点,进行放置;

  • **etcd:**是一个分布式的一个存储系统,API Server 中所需要的这些原信息都被放置在 etcd 中,etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。

Kubernetes 的 **Node 是真正运行业务负载的,每个业务负载会以 Pod 的形式运行。等一下我会介绍一下 Pod 的概念。**一个 Pod 中运行的一个或者多个容器,真正去运行这些 Pod 的组件的是叫做 kubelet,也就是 Node 上最为关键的组件,它通过 API Server 接收到所需要 Pod 运行的状态,然后提交到我们下面画的这个 Container Runtime 组件中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4Z1ygJG-1623207610987)(云原生.assets/image-20210601205016872.png)]

在 OS 上去创建容器所需要运行的环境,最终把容器或者 Pod 运行起来,也需要对存储跟网络进行管理。Kubernetes 并不会直接进行网络存储的操作,他们会靠 Storage Plugin 或者是网络的 Plugin 来进行操作。用户自己或者云厂商都会去写相应的 Storage Plugin 或者 Network Plugin,去完成存储操作或网络操作。

在 Kubernetes 自己的环境中,也会有 Kubernetes 的 Network,它是为了提供 Service network 来进行搭网组网的。(等一下我们也会去介绍“service”这个概念。)真正完成 service 组网的组件的是 Kube-proxy,它是利用了 iptable 的能力来进行组建 Kubernetes 的 Network,就是 cluster network,以上就是 Node 上面的四个组件。

Kubernetes 的 Node 并不会直接和 user 进行 interaction,它的 interaction 只会通过 Master。而 User 是通过 Master 向节点下发这些信息的。Kubernetes 每个 Node 上,都会运行我们刚才提到的这几个组件

核心概念

Pod

Pod 是 Kubernetes 的一个。用户可以通过 Kubernetes 的 Pod API 生产一个 Pod,让 Kubernetes 对这个 Pod 进行调度,也就是把它放在某一个 Kubernetes 管理的节点上运行起来。一个 Pod 简单来说是对一组容器的抽象,它里面会包含。

  • 最小调度以及资源单元
  • 一个或多个容器组成
  • 定义容器运行的方式(Command、环境变量)
  • 提供给容器共享的运行环境(网络、进程空间)
image-20210601211002736

Volume

  • 声明Pod中容器可访问的文件目录
  • 可以被挂载在Pod中一个(或者多个)容器的指定路径下
  • 支持多种后端存储抽象:分布式、本地、云存储
image-20210601211020100

Deployment

  • 定义一组Pod的副本数目、版本等
  • 通过控制器(Controller)维持Pod的数目
    • 自动恢复失败的Pod
  • 通过控制器以指定的策略控制版本
    • 滚动升级、重新生成、回滚等
image-20210601211035202

Service

  • Service 提供了一个或者多个 Pod 实例的稳定访问地址

  • 实现 Service 有多种方式,

    • Kubernetes 支持 Cluster IP,上面我们讲过的 kuber-proxy 的组网,
    • 它也支持 nodePort、 LoadBalancer 等其他的一些访问的能力
image-20210601211140644

Namespace

  • 一个集群内部的逻辑隔离的,它包括鉴权、资源管理等
  • Kubernetes 的每个资源,比如刚才讲的 Pod、Deployment、Service 都属于一个 Namespace,
  • 同一个 Namespace 中的资源需要命名的唯一性
  • 不同的 Namespace 中的资源可以重名。
image-20210601211350011
API相关

结构

  • 从 high-level 上看,Kubernetes API 是由 HTTP+JSON 组成的:用户访问的方式是 HTTP,访问的 API 中 content 的内容是 JSON 格式的
  • 可以通过 kubectl、 UI、curl访问
image-20210601211510254

对于这个 Pod 类型的资源,它的 HTTP 访问的路径,就是 API,然后是 apiVesion: V1, 之后是相应的 Namespaces,以及 Pods 资源,最终是 Podname,也就是 Pod 的名字

Label

这个 label 可以是一组 KeyValuePair

  • 可以被selector查询
  • 资源集合的默认表达形式

Pod

具体概念

在 kubernetes 里面,Pod 实际上正是 kubernetes 项目为你抽象出来的一个可以类比为进程组的概念

进程组

  • 一个应用一般由多个进程组成,进程之间会共享一些资源和文件。

  • 由于容器实际上是一个“单进程”模型,所以如果你在容器里启动多个进程,只有一个可以作为 PID=1 的进程,而这时候,如果这个 PID=1 的进程挂了,或者说失败退出了,那么其他三个进程就会自然而然的成为孤儿,没有人能够管理它们,没有人能够回收它们的资源,这是一个非常不好的情况

  • 容器的设计本身是一种“单进程”模型,不是说容器里只能起一个进程,由于容器的应用等于进程,所以只能去管理 PID=1 的这个进程,其他再起来的进程其实是一个托管状态。

    • 除非,服务应用进程本身就具有“进程管理”的能力
    • 或者使用systemd,用它来管理其他所有的进程,但会导致我们实际上没办法直接管理我的应用了,因为我的应用被 systemd 给接管了,那么这个时候应用状态的生命周期就不等于容器生命周期

pod在k8s

  • Pod 在 Kubernetes 里面只有一个逻辑单位,没有一个真实的东西对应说这个就是 Pod
  • 真正起来在物理上存在的东西,就是四个容器。这四个容器,或者说是多个容器的组合就叫做 Pod
  • Pod 是 Kubernetes 分配资源的一个单位,因为里面的容器要共享某些资源,所以 Pod 也是 Kubernetes 的原子调度单位。
  • 组合资源需求避免应用调度失败。Task co-scheduling 问题

超亲密关系

亲密关系是一定可以通过调度来解决的,超亲密关系来说,有一个问题,即它必须通过 Pod 来解决。

超亲密关系大概分为以下几类:

  • 比如说两个进程之间会发生文件交换,前面提到的例子就是这样,一个写日志,一个读日志;
  • 两个进程之间需要通过 localhost 或者说是本地的 Socket 去进行通信,这种本地通信也是超亲密关系;
  • 这两个容器或者是微服务之间,需要发生非常频繁的 RPC 调用,出于性能的考虑,也希望它们是超亲密关系;
  • 两个容器或者是应用,它们需要共享某些 Linux Namespace。最简单常见的一个例子,就是我有一个容器需要加入另一个容器的 Network Namespace。这样我就能看到另一个容器的网络设备,和它的网络信息。
实现机制

Pod 要解决这个问题,核心就在于如何让一个 Pod 里的多个容器之间最高效的共享某些资源和数据。

具体的解法分为两个部分:网络和存储

共享网络

  • 会在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的 Network Namespace。
  • Infra container 是一个非常小的镜像,大概 100~200KB 左右,是一个汇编语言写的、永远处于“暂停”状态的容器。由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中
  • 一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP地址、Mac地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。也就是所有容器共享这个 infra 的 IP 地址。
  • 整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。所以 k8s 可以单独更新一个 Pod 里的一个镜像。

共享存储

通过yaml文件声明共享存储名字以及对应mountPath就行。

sidecar容器设计模式

在 Pod 里面,可以定义一些专门的容器,来执行主业务容器所需要的一些辅助工作

其它有哪些操作呢?比如说:

  • 原本需要在容器里面执行 SSH 需要干的一些事情,可以写脚本、一些前置的条件,其实都可以通过像 Init Container 或者另外像 Sidecar 的方式去解决;

  • 当然还有一个典型例子就是我的日志收集,日志收集本身是一个进程,是一个小容器,那么就可以把它打包进 Pod 里面去做这个收集工作;

  • 还有一个非常重要的东西就是 Debug 应用,实际上现在 Debug 整个应用都可以在应用 Pod 里面再次定义一个额外的小的 Container,它可以去 exec 应用 pod 的 namespace;

  • 查看其他容器的工作状态,这也是它可以做的事情。不再需要去 SSH 登陆到容器里去看,只要把监控组件装到额外的小容器里面就可以了,然后把它作为一个 Sidecar 启动起来,跟主业务容器进行协作,所以同样业务监控也都可以通过 Sidecar 方式来去做。

辅助功能从我的业务容器解耦了,所以我就能够独立发布 Sidecar 容器,并且更重要的是这个能力是可以重用的,即同样的一个监控 Sidecar 或者日志 Sidecar,可以被全公司的人共用的

应用场景

  1. tomcat + war 部署

  2. 应用与日志收集

    业务容器将日志写在一个 Volume 里面,而由于 Volume 在 Pod 里面是被共享的,所以日志容器 —— 即 Sidecar 容器一定可以通过共享该 Volume,直接把日志文件读出来,然后存到远程存储里面,或者转发到另外一个例子

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6301Im5k-1623207610988)(云原生.assets/image-20210602110338980.png)]

  3. 代理容器

    • 单独写一个这么小的 Proxy,用来处理对接外部的服务集群,它对外暴露出来只有一个 IP 地址就可以了。所以接下来,业务容器主要访问 Proxy,然后由 Proxy 去连接这些服务集群,这里的关键在于 Pod 里面多个容器是通过 localhost 直接通信的,因为它们同属于一个 network Namespace,网络视图都一样,所以它们俩通信 localhost,并没有性能损耗

    • 代理容器除了做了解耦之外,并不会降低性能,更重要的是,像这样一个代理容器的代码就又可以被全公司重用了

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKmyZGyJ-1623207610988)(云原生.assets/image-20210602110513271.png)]

  4. 适配器容器

    • 业务容器暴露出来的监控接口是 /metrics,访问这个这个容器的 metrics 的这个 URL 就可以拿到了。可是现在,这个监控系统升级了,它访问的 URL 是 /health,我只认得暴露出 health 健康检查的 URL,才能去做监控,metrics 不认识
    • 额外写一个 Adapter,用来把所有对 health 的这个请求转发给 metrics 就可以了,所以这个 Adapter 对外暴露的是 health 这样一个监控的 URL

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oE27RfzX-1623207610988)(云原生.assets/image-20210602110657160.png)]

编排和管理

资源元信息

Labels

  • 资源标签是一种
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值