Kubernetes 101,第一部分,基础知识

2025-05-25

Kubernetes 101,第一部分,基础知识

很久以来,我一直想坐下来写一些关于Kubernetes 的文章。现在是时候了。

简而言之,Kubernetes是一个用于自动化和管理容器化应用程序的开源系统。Kubernetes的核心就是容器。


如果你不太了解容器是什么,请先阅读我的Docker 101 系列,然后再回来阅读本系列。这样你就能更好地理解 Kubernetes。

免责声明:让我们看看这个“K8s 东西”试图解决的问题。


📦容器管理

假设我们有一个由以下部分组成的复杂系统:

  • 用 Ruby 编写的 Backoffice
  • 运行 PostgreSQL 的各种数据库
  • 用Java编写的报表系统
  • 用 Erlang 编写的聊天应用程序
  • 用 NodeJS 编写的 Frontoffice

好吧,这个架构相当异构,但它满足了本文的目的。此外,我们在容器中运行所有内容

a1

假设我们必须确保“前台”应用的最大可用性和可扩展性,因为最终用户会使用它。此时,系统至少需要运行两个前台容器:

a2

此外,还有另一项功能要求,即聊天应用程序不能长时间停机,并且万一发生故障,我们应该确保它能够重新启动,并具有自我修复能力

a3

现在想象一下我们有几十个甚至几百个容器的架构:

a4

容器管理并不容易,这就是 Kubernetes 的用武之地。


📜 一点历史

在内部运行复杂工作负载 15 年后,谷歌决定公开其之前的容器管理工具“Borg”。

2014年,他们发布了这个工具,并将其命名为“Kubernetes”。该工具开源后,很快就得到了社区的广泛认可。

Kubernetes 是用Golang编写的,最初它只支持 Docker 容器,但后来也支持其他容器运行时,例如containerd 和 CRI-O

☁️ 云原生计算基金会

2015 年,Linux 基金会创建了一个基础分支,旨在支持在云计算中运行和管理容器的开源项目。

随后,云原生计算基金会CNCF)成立。

不到一年后, Kubernetes作为第一个 CNCF 毕业项目推出

目前截至 2023 年,许多公司和大公司都在其基础设施上运行 Kubernetes,例如亚马逊、谷歌、微软、RedHat、VMWare 等等。


Kubernetes 架构

以下是 Kubernetes 架构的简要介绍:

建筑学

在上面的场景中,我们有一个由“4 台机器”(或现在更常见的虚拟机)组成的 k8s 集群,它们是:

  • 1 台称为“控制平面”的机器,集群在其中创建,并负责接受集群上的新机器(或节点)
  • 另外 3 台机器称为节点,其中将包含集群管理的所有容器。

👍 经验法则

所有正在运行的容器建立我们所说的集群状态

在 Kubernetes 中,我们通过向 Kubernetes API 发出 HTTP 请求来声明集群的期望状态,Kubernetes 将“努力”实现期望状态。

然而,为了声明状态而发送简单的 HTTP 请求可能有些繁琐,容易出错,而且很繁琐。不如在命令行中使用 CLI来完成身份验证和发送 HTTP 请求这些繁琐的工作?

认识kubectl

👤 在集群中创建对象

Kubernetes 将集群中的所有内容视为对象,其中对象可以具有不同的类型(种类)。



$ kubectl run nginx --image=nginx
pod/nginx created


Enter fullscreen mode Exit fullscreen mode

下图描述了这种交互,其中我们使用kubectlCLI 向控制平面 API 发出请求:

b1

但是你可能会好奇,Pod 是什么? Pod 是我们可以交互的最小对象单元。

Pod 可能像容器,但是Pod 可以包含多个容器。

b2


🔎 架构流程

现在让我们深入研究创建对象的流程,了解集群如何执行pod 调度和状态更新

这应该是一个简短的架构流程,以便我们可以更好地理解 k8s 架构。

👉 控制平面调度器

控制平面调度程序查找下一个可用节点并将对象/pod调度到该节点。

c1

👉 节点 Kubelet

每个节点都包含一个名为Kubelet的组件,它接受来自 Scheduler 的对象,并使用安装在节点上的容器运行时(可以是 Docker、containerd 等)在节点中创建对象。

c2

👉 etcd

在控制平面中,有一个名为etcd的组件,它是一个分布式键值存储,在分布式系统和机器集群中运行良好。它非常适合 Kubernetes。

K8s 使用 etcd 来持久化并保持当前状态。

c3

✋ Kubernetes 中的一些网络知识

假设集群中有两个 NGINX pod,一个服务器和一个客户端



$ kubectl run server --image=nginx
pod/server created

$ kubectl run client --image=nginx
pod/client created


Enter fullscreen mode Exit fullscreen mode

假设我们想要访问server,我们如何访问端口 80 中的这样的 pod?

在容器化应用中,默认情况下,容器是隔离的,不共享主机网络。Pod也是如此

我们只能在Podlocalhost:80内部请求server。那么如何在正在运行的 Pod 中执行命令呢?



$ kubectl exec server -- curl localhost

<html>
...


Enter fullscreen mode Exit fullscreen mode

它可以工作,但只能在 pod 内发出请求

那么从客户端请求服务器 怎么样?可以吗?可以,因为每个 Pod在集群中都会收到一个内部 IP 。



$ kubectl describe pod server | grep IP
IP: 172.17.0.6


Enter fullscreen mode Exit fullscreen mode

client现在,我们可以使用服务器内部 IP向服务器发出请求:



$ kubectl exec client -- curl 172.17.0.6

<html>
...


Enter fullscreen mode Exit fullscreen mode

但是,如果我们执行部署,即将旧serverPod 更改为较新的 Pod则无法保证新 Pod 将获得相同的先前 IP

我们需要某种Pod 发现机制,在 Kubernetes 中声明一个特殊的对象,为指定的 Pod 命名。这样,在集群内部,我们就可以通过 Pod 的名称而不是内部 IP 来访问它们了。

这种特殊的对象被称为服务

👉 控制器管理器

控制平面还使用一个名为Controller Manager 的组件。它负责接收对服务等特殊对象的请求,并通过服务发现将其公开。

我们所要做的就是发布kubectl expose,然后控制平面就会完成这项工作。



$ kubectl expose pod server --port=80 --target-port=80

service/server exposed


Enter fullscreen mode Exit fullscreen mode

然后我们就可以通过 pod 的名称来访问server它,而不是通过它的内部 IP:



$ kubectl exec client -- curl server

<html>
...


Enter fullscreen mode Exit fullscreen mode

让我们看看架构流程中发生了什么。首先,命令发出了Service 对象kubectl expose的创建

c4

然后,控制器管理器通过服务发现公开 Pod:

c5

之后,控制器管理器会路由kube-proxy节点中正在运行的组件,该组件将为相应的 Pod创建 Service 对象。该过程结束时,状态将持久化到 中etcd

c6

👉 云控制器

控制平面中存在的另一个控制器是云控制器,负责接收创建对象的请求并在需要时与底层云提供商进行交互

例如,当我们创建类型的服务对象时LoadBalancer云控制器 在底层提供商(AWS、GCP、Azure 等)中创建一个 LB

c7


💯 最终概述

了解了kubernetes架构之后,我们用一张图来总结一下主要的架构流程:

概述


这篇文章是对 Kubernetes 的介绍以及其主要架构的概述。

我们还了解了一些构建块对象,例如Pod 和服务

在即将发布的文章中,我们将看到有关 Kubernetes工作负载、配置和网络的更详细的视图。

敬请关注!

文章来源:https://dev.to/leandronsp/kubernetes-101-part-i-the-fundamentals-23a1
PREV
如何用 CSS 制作 Cyber​​punk 2077 按钮
NEXT
结对编程模式