云原生-Kubernetes
Kubernetes是一个开源容器管理工具,负责容器部署,容器扩缩容以及负载平衡。
作为Google的创意之作,它提供了出色的社区,并与所有云提供商合作。因此,我们可以说Kubernetes不是一个容器化平台,而是一个多容器管理解决方案。
众所周知,Docker提供容器的生命周期管理,Docker镜像构建运行时容器。但是,由于这些单独的容器必须通信,因此使用Kubernetes。因此,我们说Docker构建容器,这些容器通过Kubernetes相互通信。因此,可以使用Kubernetes手动关联和编排在多个主机上运行的容器。
K8S整体架构
K8S组件
https://kubernetes.io/zh-cn/docs/concepts/overview/components/
控制平面组件(Control Plane Components)
控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件。
控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。
- kube-apiserver
API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。
Kubernetes API 服务器的主要实现是 kube-apiserver。 kube-apiserver 设计上考虑了水平扩缩,也就是说,它可通过部署多个实例来进行扩缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。 - etcd
一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库。 - kube-scheduler
负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。
调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。 - kube-controller-manager
负责运行控制器进程。
从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。
这些控制器包括:- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
- 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
- 端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)。
- 服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)。
- cloud-controller-manager
云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。
Node 组件
节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。
- kubelet
kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。
kubelet 接收一组通过各类机制提供给它的 PodSpecs, 确保这些 PodSpecs 中描述的容器处于运行状态且健康。
kubelet 不会管理不是由 Kubernetes 创建的容器。 - kube-proxy
kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。
kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
它的作用是使发往 Service 的流量(通过ClusterIP和端口)负载均衡到正确的后端Pod。 - 容器运行时 container-runtime
负责管理运行容器的软件,比如docker。
插件(Addons)
插件使用 Kubernetes 资源(DaemonSet、 Deployment 等)实现集群功能。 因为这些插件提供集群级别的功能,插件中命名空间域的资源属于 kube-system 命名空间。
- kube-dns
集群 DNS 是一个 DNS 服务器,和环境中的其他 DNS 服务器一起工作,它为 Kubernetes 服务提供 DNS 记录(记录service和为service分配的集群IP的对应关系)。
Kubernetes 启动的容器自动将此 DNS 服务器包含在其 DNS 搜索列表中。 - Ingress Controller
为服务提供k8s集群外网入口 - Heapster
提供资源监控 - Dashboard
提供GUI - Federation
提供跨可用区的集群 - Fluentd-elasticsearch
提供集群日志采集、存储与查询
K8S资源对象
Kubernetes 中的所有内容都被抽象为“资源”,如 Pod、Service、Node 等都是资源。
“对象”就是“资源”的实例,是持久化的实体。如某个具体的 Pod、某个具体的 Node。Kubernetes 使用这些实体去表示整个集群的状态。
对象的创建、删除、修改都是通过 “Kubernetes API”,也就是 “Api Server” 组件提供的 API 接口,这些是 RESTful 风格的 Api,与 k8s 的“万物皆对象”理念相符。命令行工具 “kubectl”,实际上也是调用 kubernetes api。
K8s 中的资源类别有很多种,kubectl 可以通过配置文件来创建这些 “对象”,配置文件更像是描述对象“属性”的文件,配置文件格式可以是 “JSON” 或 “YAML”,常用 “YAML”。
几乎每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:对象 spec(规约) 和 对象 status(状态)。
这里有一个 .yaml
示例文件,展示了 Kubernetes Deployment 的必需字段和对象 spec:
1 | apiVersion: apps/v1 |
在想要创建的 Kubernetes 对象所对应的 .yaml
文件中,需要配置的字段如下:
- apiVersion - 创建该对象所使用的 Kubernetes API 的版本
- kind - 想要创建的对象的类别
- metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
- spec - 你所期望的该对象的状态
资源/对象种类
(工作负载)Workload类对象
Pod
Controllers
Deployment/Statefulset/Daemonset/Job等。Certificate Controller
ClusterRoleAggregation Controller
Node Controller
CronJob Controller
Daemon Controller
Deployment Controller
StatefulSet Controller
Endpoint Controller
Endpointslice Controller
Garbage Collector
Namespace Controller
Job Controller
Pod AutoScaler
PodGC Controller
ReplicaSet Controller
Service Controller
ServiceAccount Controller
Volume Controller
Resource quota Controller
Disruption Controller
Discovery&Loadbalance类对象
Service/Endpoints/IngressWorkload类对象
Configmap/ Secret/ Volume/ PersistentVolumeCluster类对象
Node/Namespace/Role/ClusterRole
基础概念
Cluster、Master、Node
- Cluster
Cluster(集群) 是计算、存储和网络资源的集合,Kubernetes 利用这些资源运行各种基于容器的应用。
最简单的 Cluster 可以只有一台主机(它既是 Mater 也是 Node)。 - Master
Master 是 Cluster 的大脑,它的主要职责是调度,即决定将应用放在哪里运行。
Master 运行 Linux 操作系统,可以是物理机或者虚拟机。
为了实现高可用,可以运行多个 Master。 - Node
Node 的职责是运行容器应用。
Node 由 Master 管理,Node 负责监控并汇报容器的状态,并根据 Master 的要求管理容器的生命周期。
Node 运行在 Linux 操作系统,可以是物理机或者是虚拟机。
Pod
基本概念:
- Pod 是 Kubernetes 的最小工作单元。
- 每个 Pod 包含一个或多个容器。Pod 中的容器会作为一个整体被 Master 调度到一个 Node 上运行。
引入Pod的目的:
- 可管理性: 有些容器天生就是需要紧密联系,一起工作。Pod 提供了比容器更高层次的抽象,将它们封装到一个部署单元中。Kubernetes 以 Pod 为最小单位进行调度、扩展、共享资源、管理生命周期。
- 通信和资源共享: Pod 中的所有容器使用同一个网络 namespace,即相同的 IP 地址和 Port 空间。它们可以直接用 localhost 通信。同样的,这些容器可以共享存储,当 Kubernetes 挂载 volume 到 Pod,本质上是将 volume 挂载到 Pod 中的每一个容器。
Pod的使用方式:
- 运行单一容器:
one-container-per-Pod
是 Kubernetes 最常见的模型,这种情况下,只是将单个容器简单封装成 Pod。即便是只有一个容器,Kubernetes 管理的也是 Pod 而不是直接管理容器。 - 运行多个容器: 对于那些联系非常紧密,而且需要直接共享资源的容器,应该放在一个 Pod 中。比如下面这个 Pod 包含两个容器:一个 File Puller,一个是 Web Server。File Puller 会定期从外部的 Content Manager 中拉取最新的文件,将其存放在共享的 volume 中。Web Server 从 volume 读取文件,响应 Consumer 的请求。这两个容器是紧密协作的,它们一起为 Consumer 提供最新的数据;同时它们也通过 volume 共享数据。所以放到一个 Pod 是合适的。
Controller
基本概念:
Kubernetes 通常不会直接创建 Pod,而是通过 Controller 来管理 Pod 的。Controller 中定义了 Pod 的部署特性,比如有几个副本,在什么样的 Node 上运行等。为了满足不同的业务场景,Kubernetes 提供了多种 Controller,包括 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等。
各个Controller:
- Deployment: Deployment 是最常用的 Controller,比如我们可以通过创建 Deployment 来部署应用的。Deployment 可以管理 Pod 的多个副本,并确保 Pod 按照期望的状态运行。
- ReplicaSet: ReplicaSet 实现了 Pod 的多副本管理。使用 Deployment 时会自动创建 ReplicaSet,也就是说 Deployment 是通过 ReplicaSet 来管理 Pod 的多个副本,我们通常不需要直接使用 ReplicaSet。
- DaemonSet: DaemonSet 用于每个 Node 最多只运行一个 Pod 副本的场景。正如其名称所揭示的,DaemonSet 通常用于运行 daemon。
- StatefuleSet: StatefuleSet 能够保证 Pod 的每个副本在整个生命周期中名称是不变的。而其他 Controller 不提供这个功能,当某个 Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化。同时 StatefuleSet 会保证副本按照固定的顺序启动、更新或者删除。
- Job: Job 用于运行结束就删除的应用。而其他 Controller 中的 Pod 通常是长期持续运行。
Service
K8S 中的 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。
每个 Service 对象定义一个逻辑组的端点(通常这些端点是 Pod)以及如何才能访问这些 Pod 的策略。
- Deployment 可以部署多个副本,每个 Pod 都有自己的 IP。而 Pod 很可能会被频繁地销毁和重启,它们的 IP 会发生变化,用 IP 来访问 Deployment 副本不太现实。
- Service 定义了外界访问一组特定 Pod 的方式。Service 有自己的 IP 和端口,Service 为 Pod 提供了负载均衡。
服务类型
type 确定 Service 的公开方式。默认为 ClusterIP。 有效选项为 ExternalName、ClusterIP、NodePort 和 LoadBalancer。
ClusterIP
ClusterIP Service 类型,用于将一组Pod暴露给集群内部的其他Pod或Service。ClusterIP Service会为这组Pod分配一个虚拟IP地址,其他Pod或Service可以通过这个虚拟IP地址来访问这组Pod。
ClusterIP Service的工作原理如下:
- 当创建一个ClusterIP Service时,Kubernetes会为这个Service分配一个虚拟IP地址,并将这个虚拟IP地址添加到集群内部的DNS(kube-dns)中。
- 当其他Pod或Service需要访问这个Service时,它们可以通过这个虚拟IP地址来访问。
- 当请求到达这个虚拟IP地址时,Kubernetes会将请求转发到这个Service后面的一组Pod中的一个。转发的Pod是根据Service的选择器(Selector)来选择的。
- 如果这个Pod不可用,Kubernetes会将请求转发到另一个可用的Pod中。
- 当Pod的数量发生变化时,Kubernetes会自动更新Service的后端Pod列表,以确保所有的Pod都能够被访问到。
需要注意的是,ClusterIP Service只能在集群内部使用,不能从集群外部访问。如果需要从集群外部访问Service,可以使用NodePort或LoadBalancer类型的Service。
NodePort
在 Kubernetes 中,NodePort Service 允许外部网络通过 Kubernetes 集群中的节点访问 Service。NodePort Service 会在每个节点上打开一个端口,该端口将转发到 Service 的 ClusterIP。这样,外部网络就可以通过节点的 IP 地址和该端口访问 Service。
1 | apiVersion: v1 |
在这个示例中,我们定义了一个名为my-nodeport-service
的 NodePort Service。它的 selector 指定了要将该 Service 与哪些 Pod 关联起来,这里是app: my-app
。它的 ports 定义了要暴露的端口,这里是将 Service 的端口 80 映射到 Pod 的端口 8080。nodePort 指定了要在节点上打开的端口,这里是 30080。
使用 NodePort Service 可以方便地将 Kubernetes 集群中的 Service 暴露给外部网络,但需要注意的是,NodePort Service 的端口是公开的,需要进行适当的安全配置,以避免安全风险。
LoadBalance
暂不支持, 略。
ExternalName
ExternalName Service 将Kubernetes服务映射到集群外部的DNS名称。
ExternalName Service的工作原理是将服务的DNS名称映射到一个CNAME记录,该记录指向集群外部的服务。当集群内的Pod访问该服务时,Kubernetes会将服务的DNS名称解析为CNAME记录,并将请求转发到CNAME记录指向的外部服务。
使用ExternalName Service时,需要在Kubernetes中创建一个Service对象,并将其类型设置为ExternalName。
例如,以下是一个使用ExternalName Service将Kubernetes服务映射到外部DNS名称的示例:
1 | apiVersion: v1 |
在上面的示例中,创建了一个名为my-service的Service对象,并将其类型设置为ExternalName。该服务将Kubernetes服务映射到外部DNS名称my.database.example.com。当集群内的Pod访问my-service时,Kubernetes会将请求转发到my.database.example.com。
特别的Service类型
- 无选择算符的Services [Services Without Selector]
- 无头服务 [Headless Services]
Namaspace
- Namespace 可以将一个物理的 Cluster 逻辑上划分成多个虚拟 Cluster,每个 Cluster 就是一个 Namespace。不同 Namespace 里的资源是完全隔离的。
- Kubernetes 默认创建了两个 Namespace
- default:创建资源时如果不指定,将被放到这个 Namespace 中。
- kube-system:Kubernetes 自己创建的系统资源将放到这个 Namespace 中。