最近正在复习准备考试,于是一边复习一遍写成博客,印证自己所学。
从高层看,kubernetes 是由如下东西组成的:
- 一个或多个 master node
- 一个或多个 worker node
- 一个分布式的 key-value 存储,比如
etcd
2FDF2789-F7EA-4EE6-8561-6FE7AD4A79D6
Master Node
Master node 是集群管理者,我们发出的所有请求都是到 master node 的 api server 上。
一个集群可以有多个 master node 做 HA,当有多个 master node 的时候,只有一个会提供服务,剩下的都是 follower。
集群的状态一般存储在 etcd 里面,所有的 master node 都会连接到 etcd。etcd 是一个分布式 k-v 存储。etcd 可以是 master 内部的,也可以是外部的。
Master node 的组件
master node 一般都有如下组件:
API Server
所有的操作都是通过 API Server 去完成的。每个用户 / 操作者通过发送 REST 请求到 api server,然后 api server 先验证然后执行这些操作。在执行完之后把集群的状态存到 etcd 里面。
Scheduler
顾名思义,Scheduler 的作用是调度,Scheduler 拥有所有 worker node 的资源使用情况,同时也知道用户设置的资源需求,比如说一个 disk=ssd 的 label。在调度之前,scheduler 还会考虑到 service requirements,data locality,affinity,anti-affinity 等。scheduler 负责的是 service 和 pod 的调度。
Controller Manager
简单来说,Controller Manager 是负责启动和关闭 pod 的。Controller Manager 的任务是让集群维持在期望的状态上。Controller Manager 知道每个 Pod 的状态应该是什么样,然后会不断检测是否有不达标的 pod。
Worker Node
Worker Node 就是一个被 master node 控制的机器,Pod 一般都是调度到 worker node 里面的。Worker node 会有一些可以运行以及连接容器的工具。Pod 是 kubernetes 里面的调度单元,是一个或多个容器组成的通常一起调度的逻辑上的集合。
D012D35E-5431-411E-AD4A-829A268E0875
Worker Node 组件
一个 worker node 一般会有以下组件:
Contrainer Runtime
不用多说了,运行容器必备的,默认用的是 Docker
kubelet
kubelet 是在每个 worker node 上都会运行的,用来和 master node 通信的。kubelet 从 master 接收 pod 的定义,然后启动里面的容器,并监控容器是否一直正常运行。
kube-proxy
kube-proxy 简单来说,就是对外提供代理服务的。换句话说,没有 kube-proxy,我们要访问其中的 application,就得直接访问到 worker node 上,这显然是不合理的。我们可以通过 kube-proxy 来做 load balancer 等。以前版本的 Service 也借助了 kube-proxy。
用 etcd 来管理状态
在 kubernetes 里面,都是用的 etcd 来管理所有的状态。除了集群的状态之外,还会用来存放一些信息,比如 configmap,secret。
网络需求
为了启动一个全功能的 kubernetes 集群,我们需要先确认以下信息:
- 每个 Pod 有唯一一个独立的 IP
- 每个 Pod 里面的容器可以互相沟通
- Pod 之间可以互相沟通
- 通过设置,在 Pod 里面的 application 可以被外部访问到
这些问题都是需要在部署之前被解决的。
我们一个个看:
给每个 Pod 分配一个独立的 IP
在 kubernetes 里面,每个 Pod 都要有一个独立的 IP。一般容器网络有两种规格:
- Container Network Model (CNM)
- Container Network Interface (CNI)
Kubernetes 用 CNI 来给 Pod 分配 IP
CA97E57F-D3C7-4BF0-BD0F-AB8E83838655
简单来说,容器运行时向 CNI 申请 IP,然后 CNI 通过其下面指定的 plugin 来获取到 IP,并且返回给容器运行时。
容器之间交流
一般基于底层操作系统的帮助,所有的容器运行时都会给每个容器创建一个独立的隔离的网络整体。在 Linux 上,这个整体被称为 Network Namespace,这些 Network Namespace 可以在容器之间共享。
在一个 Pod 里面,容器共享 Network Namespace,所以所有在同一个 Pod 里面的容器可以通过 localhost 来互相访问。
跨 Node 的 Pod 之间访问
在一个集群的环境下,每个 Pod 可以被调度到任何一个 Node 上,我们需要让在不同机器上的 Pod 也可以相互通信,并且任何 Node 都可以访问到任何 Pod。Kubernetes 设定了一个条件:不能有任何的 NAT 转换,我们可以通过以下方式来达成:
- 可路由(Routable)的 Pod 和 Node,通过底层的服务,比如 GCE。
- 通过一些软件定义的网络(Software Defined Networking),比如 flannel,weave,calico 等
更多的信息可以看看 kubernetes 的官方文档。
外网和集群之间的访问
我们可以通过 kube-proxy 来暴露我们的 service,然后就能从外面访问到我们集群里面的应用了。