Skip to content

Commit

Permalink
更新容器编排
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Mar 8, 2024
1 parent 51c5532 commit a3674d3
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 23 deletions.
2 changes: 1 addition & 1 deletion architecture/architect.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 1.7 云原生时代对架构师的要求

云原生架构是”优雅的、灵活的、弹性的...“,但云原生技术也过于抽象和复杂。云原生架构中,复杂只是被转移到云基础设施中,并没有无故消失。作为架构师,如果有志构建一个高可用的云原生架构,对能力要求已提升到史无前例的程度。总结来说,在云原生工程实践中除掌握 Docker 和 Kubernetes,还需要知晓以下几个领域,如图 1-39 所示。
云原生架构是”优雅的、灵活的、弹性的...“,但也极度复杂,这些复杂被隐藏在云基础设施中,对业务透明不代表复杂已消失。作为架构师,如果有志构建一个高可用的云原生架构,对能力要求已提升到史无前例的程度。总结来说,在云原生实践中除掌握 Docker 和 Kubernetes,还需要知晓以下几个领域,如图 1-39 所示。

<div align="center">
<img src="../assets/cloud.svg" width = "650" align=center />
Expand Down
65 changes: 43 additions & 22 deletions container/orchestration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,26 @@

那么,容器是本质什么呢?如果吧 Kubernetes 比作云原生时代的操作系统,那么容器就是这个操作系统之内的特殊进程。

特殊之处在于容器利用操作系统内核技术通过约束和修改进程的动态表现,从而为其创造一出一个“边界”。
特殊之处在于容器利用操作系统内核技术通过约束和修改进程的动态表现,从而为其创造一出一个“边界”。实现“边界”的核心技术是 namespace(隔离,)、cgroup(约束能用多少资源,内存/磁盘。cpu等)

容器技术的核心功能,就是。使用 namespace 约束、cgroup(能用多少资源,内存/磁盘。cpu等),chroot 能看到什么文件。

命名空间创建一个几乎隔离的用户空间,并未应用提供专用的系统资源,如文件系统、网络堆栈、进程ID等。

| namespace | 作用 |
|:--|:--|
|UTS | 主机名和域名的隔离。 |
|IPC | 信号量,消息队列和共享内存的隔离。 |
|PID | 用于隔离进程 ID |
|Network | 隔离网络接口,在虚拟的 net namespace 内用户可以拥有自己独立的 IP、路由、端口等 |
|Mount | 文件系统挂载点隔离 |
|User | |
|Time ||
```
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
```

:::tip 沙盒

容器并不是真正的沙盒,也不是轻量化的虚拟机。
:::

cgroup 则控制 CPU、内存、设备和网络等资源。实施对应用的资源限制、优先级、审计和控制。


容器技术是动态的容器、静态的镜像、远程的仓库这三者的组合。

## 容器编排的第一个扩展是进程组

在一个真正的 OS 内,进程并非“孤苦伶仃” 独自运行,而是以进程组,有原则的组织在一起。登录到一台 Linux 机器,展示当前系统中正在运行的进程述状结构,执行如下命令:
在一个真正的 OS 内,进程并非“孤苦伶仃”独自运行,而是以进程组,有原则的组织在一起。登录到一台 Linux 机器,展示当前系统中正在运行的进程述状结构,执行如下命令:

```
$ pstree -g
Expand All @@ -52,21 +43,51 @@ systemd(1)─┬─abrt-dbus(540)─┬─{abrt-dbus}(540)
```
如上,负责Linux日志处理 rsyslogd 的程序,可见rsyslogd的主程序main,和它要用到的内核日志模块imklog等,同属1089进程组。这些进程相互协作,共同完成rsyslogd程序的职责。

对os,这样的进程组更方便管理。Linux操作系统只需将信号,如SIGKILL信号,发给一个进程组,该进程组中的所有进程就都会收到这个信号而终止运行。而 Kubernetes 所做的,其实就是将“进程组”的概念映射到容器技术,并使其成为云原生操作系统“os”内的“一等公民”。
对os,这样的进程组更方便管理。Linux操作系统只需将信号,如 SIGKILL 信号,发给一个进程组,该进程组中的所有进程就都会收到这个信号而终止运行。

那么现在的问题是如果把上面的进程用容器跑起来,你该怎么做?自然的解法启动一个 Docker 容器,里面运行四个进程,可是这样会有一个问题:容器里面 PID=1 的进程该是谁?这个核心问题在于容器的设计本身是一种“单进程”模型,不是说容器里只能起一个进程,而是容器的应用等于进程,Docker 只能通过监视 PID 为 1 的进程的运行状态来判断容器的工作状态是否正常。

再或者把进程 PID = 1 的进程改为可以管理进程应用(例如 supervisord)。但改成 supervisord 的问题容器生命周期不再是工作进程的生命周期(而是supervisord),工作进程是否正常也无法在直接知道。

如果现在我们把容器与进程在概念上对应起来,那容器编排的第一个扩展点,就是要找到容器领域中与“进程组”相对应的概念,这是实现容器从隔离到协作的第一步,在 Kubernetes 的设计里,这个对应物叫作 Pod
如果现在我们把容器与进程在概念上对应起来,那容器编排的第一个扩展点,就是要找到容器领域中与“进程组”相对应的概念,这是实现容器从隔离到协作的第一步。

## 容器设计模式
## 超亲密容器组

进程组的实现在 Kubernetes 中叫做 Pod。

容器的本质是对 cgroups 和 namespaces 所提供的隔离能力的一种封装,在 Docker 提倡的单进程封装的理念影响下,容器蕴含的隔离性也多了仅针对于单个进程的额外局限,然而 Linux 的 cgroups 和 namespaces 原本都是针对进程组而不仅仅是单个进程来设计的,同一个进程组中的多个进程天然就可以共享着相同的访问权限与资源配额。
容器之间原本是被 Linux Namespace 和 cgroups 隔开的,Pod 第一个要解决的问题是怎么去打破这个隔离,让 Pod 内的容器可以像进程组一样天然的共享资源和数据(例如网络和存储)。

Kubernetes 中使用 Infra Container 解决这个问题。Infra Container 是整个 Pod 中第一个启动的容器,只有几百 KB 大小,Pod 中的其他容器都会以 Infra Container 作为父容器,UTS、IPC、网络等名称空间实质上都是来自 Infra Container 容器。

:::tip 额外知识

Infra Container 启动之后,永远处于 Pause 状态,所以也常被称为“pause 容器”
:::


<div align="center">
<img src="../assets/infra-container.svg" width = "350" align=center />
<p>图 Kubernetes 架构</p>
<img src="../assets/infra-container.svg" width = "350" align=center />
<p>图 Kubernetes 架构</p>
</div>

此时,Infra Container 中的进程将作为 PID 1 进程,Infra Container 来负责进程管理(譬如清理僵尸进程)、感知状态和传递状态,整个 Pod 的生命周期是等同于 Infra container 的生命周期。


这个 volume 叫做 shared-data,它是属于 Pod level 的,所以在每一个容器里可以直接声明:要挂载 shared-data 这个 volume,只要你声明了你挂载这个 volume,你在容器里去看这个目录,实际上大家看到的就是同一份。这个就是 Kubernetes 通过 Pod 来给容器共享存储的一个做法。


## Pod 是原子调度单位

比如说在 Mesos 里面,它会做一个事情,叫做资源囤积(resource hoarding):即当所有设置了 Affinity 约束的任务都达到时,才开始统一调度,这是一个非常典型的成组调度的解法。

在 Mesos 里面,他们不会立刻调度,而是等两个容器都提交完成,才开始统一调度。这样也会带来新的问题,首先调度效率会损失,因为需要等待。由于需要等还会有外一个情况会出现,就是产生死锁,就是互相等待的一个情况。

另一个做法是Google Omega 系统中的做法, https://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/41684.pdf

如果将运行资源的需求声明定义在 Pod 上,直接以 Pod 为最小的原子单位来实现调度的话,Pod与Pod之间也不存在什么超亲密关系,复杂的协同的调度问题在 Kubernetes 中就直接消失了。

## 容器的设计模式



## Kubernetes 系统架构
Expand Down

0 comments on commit a3674d3

Please sign in to comment.