以下是 Kubernetes 架构的简要描述
在上面的场景中,我们有一个由“4台机器”(或更常见的虚拟机)组成的 k8s 集群,它们是:
- 1台名为Control Plane的机器,在其中创建集群并负责接受集群上的新机器(或节点)
- 其他 3 台名为Nodes的机器,其中将包含集群的所有托管容器。
在集群中创建对象
Kubernetes 将集群中的一切都视为对象,其中对象可以有不同的类型(kind)。
$ kubectl run nginx --image=nginx
pod/nginx created
下图描述了我们使用kubectlCLI 执行对控制面板 API 的请求的交互:
那么什么是 Pod? Pod是我们可以交互的最小对象单元。
Pod 像容器一样,但是Pod 可以包含多个容器。
架构流程
现在让我们深入了解创建对象的流程,了解集群如何执行pod 调度和状态更新。
这是一个简短的架构流程,这样我们可以更好地理解 k8s 架构。
控制面板调度器
Control Plane Scheduler寻找下一个可用节点并调度对象/pod。
节点 Kubelet
每个节点都包含一个名为Kubelet的组件,它检查来自Scheduler的对象,并使用安装在节点中的容器运行时(可能是 Docker、containerd 等)在节点中创建对象。
etcd
在 Control Plane 中有一个名为etcd 的组件,它是一个分布式键值存储系统,专为分布式系统和机器集群设计。它非常适合 Kubernetes。
K8s 使用 etcd 来持久化和保持当前状态。
✋ Kubernetes 中的网络
假设我们在集群中有两个 NGINX pod,一个服务器和一个客户端:
$ kubectl run server --image=nginx
pod/server created
$ kubectl run client --image=nginx
pod/client created
假设我们想要访问server。
在容器化应用程序中,默认情况下,容器是隔离的,不共享主机网络。Pod 也是如此。
我们只能在server Pod内部: localhost:80 请求server。
$ kubectl exec server -- curl localhost
<html>
...
它有效,但仅在 pod 内请求时有效。
从client请求 server 怎么样,这可能吗?可以的,因为每个 Pod在集群中拥有一个内部 IP 。
$ kubectl describe pod server | grep IP
IP: 172.17.0.6
可以使用服务器内部 IP执行请求:
$ kubectl exec client -- curl 172.17.0.6
<html>
...
但是,如果我们执行部署,即将旧server Pod 更改为新的 Pod,无法保证新 Pod 将获得与之前相同的 IP。
我们需要某种Pod 发现机制,我们可以在 Kubernetes 中声明一个特别的对象,为给定的 pod命名。 因此,在集群内,我们可以通过名称而不是内部 IP 访问 Pod。
这种特殊对象称为Service。
控制器管理器
控制面板Control Panel还使用了一个名为 Controller Manager的组件。它负责接收对服务等特殊对象的请求,并通过服务发现公开它们。
我们所要做的就是使用kubectl expose完成这项工作。
$ kubectl expose pod server --port=80 --target-port=80
service/server exposed
然后我们可以通过名称而不是其内部 IP访问pod
$ kubectl exec client -- curl server
<html>
...
总结一下总体流程。
首先,命令发出了服务对象kubectl expose的创建:
然后,Controller Manager通过服务发现暴露 Pod:
之后,控制器管理器路由到kube-proxy节点中运行的组件,该组件将为相应的 Pod创建服务对象。 在流程结束时,状态将保存在etcd.
云控制器
控制面板中存在的另一个控制器是Cloud Controller,负责接收创建对象的请求并在需要时与底层云提供商进行交互。
例如,当我们创建一个 Service 类型的对象时LoadBalancer,Cloud Controller 将在底层提供者中创建一个 LB ,无论是 Aliyun、GCP、AWS等
最后的概述
了解完kubernetes的架构,我们把主要的架构流程总结成一张图:
k8s总体架构流程