用户:九千鸦/k8s
概括
[编辑]Kubernetes 与传统的 PaaS 不同,它更多的被称为 容器的PaaS 或者 CaaS(Containers as a service,容器即服务)。[1]
概念
[编辑]Kubernetes 包含一系列抽象概念,这些抽象概念用于表示系统的状态,这包括:已部署的容器化应用和工作负载的抽象概念、与之相关的网络和磁盘资源的抽象、集群运行的其他信息的抽象。[2]
工作节点
|--------------┐
Pod 1 Pod 2
| |
容器1 容器2
容器2 容器3
IP 10.1.0.1 IP 10.1.0.2
Kubernetes API
[编辑]Kubernetes API是REST API,是 Kubernetes 的基础组件。组件间的操作和通信,以及外部用户命令都是通过该API完成的,因此,Kubernetes平台里的任何对象都可以说是该API的执行对象。该API由 API服务器(kube-apiserver)管理。[3]
对象
[编辑]
对象有两个内嵌对象字段:spec
和 status
。 status
用于表示对象的当前状态,通过以下命令可以查看到pod的当前状态:[4]
# 通过以下命令可以获得status
# kubectl get pods
# kubectl describe pods [Pod名称]
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app 1/1 Running 0 20h
spec
表示集群期待的状态(Desired State)。用户可以使用YAML文件部署应用(创建对象),spec
字段则表示要部署的应用有什么特征。[4] 以下YAML文件描述了一个高级对象(Deployment),字段详情可查看该网站。
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment # 对象的类型
metadata: # 该Deployment对象的元数据
name: nginx-deployment
spec:
selector: # Pods的标签选择器。选择哪些Pods受该Deployment管理。
matchLabels:
app: nginx
replicas: 2 # 希望运行2个pod
template:
metadata: # Pods对象的元数据
labels: # Pods对象的标签
app: nginx
spec:
containers:
- name: nginx # Pod的容器名为nginx
image: nginx:1.14.2 # 从Docker Hub拉去的镜像
ports:
- containerPort: 80
基础对象
[编辑]Pod
[编辑]Pod(英语:豆荚)是最小单元(atomic unit)。Pod封装了一个或若干个容器(Docker容器是最常用的容器),各容器可共享同一IP地址和端口、存储资源(存储卷)。但通常,一个Pod只会装载一个容器,除非各容器间需要使用文件系统(存储资源)进行通讯。[5][6]
虽然Pod拥有独立的IP地址,但是该IP地址无法暴露在集群之外。此时,需要 服务 该对象进行帮助。[7]
服务
[编辑]服务(service),可以理解为逻辑上的Pod。通过服务的DNS名称名(DNS name)可以找到服务,再通过服务可以调用Pod。[8] 调用方 通过调用服务的方式,避免了调用方与Pod的耦合,这样当Pod宕机时,也不会影响到调用方,这也可用于负载均衡、服务发现等场景。[9]
选择一个Endpoint进行调用
|-----------| -------- Endpoint 1 -----> [Pod 1 暴露端口:80 IP:10.244.0.25]
| | [10.244.0.25:80]
调用 --> | service | -------- Endpoint 2 -----> [Pod 2 暴露端口:80 IP:10.244.0.26]
|10.96.92.53| [10.244.0.26:80]
|-----------| -------- Endpoint 3 -----> [Pod 3 暴露端口:80 IP:10.244.0.27]
[10.244.0.27:80]
服务也是拥有IP地址(称为cluster IP)[9],通过kubectl get service
可查看到。服务没有通过选择器(selector)选择Pod时,Endpoint对象 将无法被自动生成,服务将无法调用;另外,可通过直接指定 IP和端口 的方式,生成Endpoint对象,从而调用服务。[10] 可通过kubectl get endpoints
的方式查看Endpoint对象。
服务定义文件格式为 YAML(推荐) 和 JSON,示例如下:[7]
apiVersion: v1
kind: Service
metadata:
name: redis-master # DNS名
labels:
app: redis
role: master
tier: backend
spec:
ports:
- port: 6666 # 该服务暴露给外界的端口
targetPort: 6379 # Pods暴露的端口
selector: # 标签选择器,用于服务连接的Pod
app: redis
role: master
tier: backend
标签和选择器
[编辑]标签(label)是键值对,用于存储对象的数据。这些数据是特意展示给用户看,具有意义和标志性。 用户通过 选择器(全称:标签选择器,Label selector)匹配标签,API 将可找到匹配对象。[11]
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
高级对象
[编辑]高级对象 是依赖于控制器 ,而控制器是建立于基础对象之上,并为之添加功能性和方便性。[2]
ReplicationController
[编辑]ReplicationController 用于确保Pod的数量正常。[12]
ReplicaSet
[编辑]ReplicaSet 是 ReplicationController 的升级版本,ReplicaSet 的标签选择器更加灵活。[13]
DaemonSet
[编辑]DaemonSet(Daemon:守护进程) 为了每一个节点分配有且只有一个Pod,使用场景有:[14][15]
- 存储用的守护进程。
- 日志收集的守护进程。
- 节点监控的守护进程。
Deployment
[编辑]Deployment控制器 提供了声明式(使用YAML文件)的方式,更新Pod和ReplicaSet。[16][17][18] Deployment控制器可以管理其 Pod 组件的生命周期,还可以执行横向扩缩以根据需要更改 Pod 的数量。[19]
下例为查看deployment对象:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
frontend 1/1 1 1 5d4h
Job
[编辑]Job控制器用于执行非持续性的任务(即任务是可执行完毕的),例如使用Pod发送一封邮件,发送完毕后Job控制器会被标记完成,失败的话则重新发送一封邮件。Job控制器可创建单个或者多个Pod,如果创建多个Pod的话,将以并行的方式执行。[20]
CronJob
[编辑]CronJob控制器 在特定时间或按特定间隔运行任务,就像Cron工具。[21]
设计
[编辑]开发者使用 Kubernetes 有两种方式:使用命令行工具(如:kubectl 、 kubeadm)、客户端库。而这两种方式均是基于Kubernetes API。[3]
当开发者想要部署 应用,那么需要通过命令行工具等方式要告诉Master,Master将会调度Pod(Pod装载着容器化的应用)到工作节点上。[22]
|-----------------------------------------------------------------------|
| cluster |
| Control Plane Components |
| Master node Work node |
| |------------------------| |--------------------| |
| | kube-apiserver | | kubelet | |
| | kube-scheduler | | kubelet-proxy | |
| | kube-contoller-manager | | Container runtime | |
| | etcd | | [ Pods ] | |
| |------------------------| |--------------------| |
| |
|-----------------------------------------------------------------------|
Control Plane
[编辑]控制平面(英语:Control Plane)位于主节点(Master node),包含主控件组(Master)、etcd。控制平面 通常用于与工作节点进行交互。[23]
Masters
[编辑]由于Master是由三个进程组成的,所以可以翻译为“主控件组”。Master所在的工作节点将会被指定为 主节点。[2]主控组件包含的三个进程分别是:kube-apiserver、kube-controller-manager 和 kube-scheduler。[2]主控组件负责管理集群。[22]
- kube-apiserver(API server), 用于与(集群的)外界进行通讯。API server将会判断接请求是否有效,如果有效就会处理。
kubectl
等命令行实质就是和该组件通讯。[23] - kube-scheduler,用于调度资源。观察是否存在新创建的Pod没有指派到节点,如果存在的话,则将其指派到其中一个节点上。[24]
- kube-controller-manager,通过控制器进行维护集群。从API server接收到的命令,将会修改集群某些对象的期待状态(desired state),控制器观察到这些期待状态的变化,就会将这些对象的当前状态(current state)变为期待状态(desired state)。[25][22][24]
- Node controller:负责监视节点,当节点宕不可用时,进行通知。
- Replication controller:负责维护每一个replication controller对象所关联的Pod数量。
- Endpoints controller:负责填充 Endpoints对象。
- Service Account & Token controllers:创建默认的账号和API访问令牌。
|--------------------|
command--> | kube-apiserver | ---> change object's
|--------------------| desired state
∧
|| watch
|---------------------------|
change object's <--- | kube-contoller-manager |
current state |---------------------------|
etc
[编辑]一致性和高可用的键值存储软件,用于备份k8s的所有集群。[26]
cloud-controller-manager
[编辑]在v1.11版本(2018年),cloud-controller-manager用于云服务提供商
####TODO
工作节点
[编辑]节点(Node)默认表示 工作节点,而不代表 主节点。工作节点 运行着容器化的应用。 工作节点装载着 Pod ,Pod是application workload的构成要素。[27]
- kubelet,作为节点的代理者,用于与 Master 进行通信,并管理着容器。[22][28]
- kube-proxy,一种网络代理,将 Kubernetes 的网络服务代理到每个节点上。
- 容器运行时(Container Runtime),用于操作容器,如:Docker。[22][28]
网络
[编辑]服务
[编辑]服务有五种类型:[29]
- ClusterIP(默认类型):只能在集群里访问服务。
- NodePort:通过每个节点IP的某一特定端口,访问服务(Node=节点,Port=端口)。
- LoadBalancer:通过云服务商的负载均衡器,访问服务。
- ExternalName:该服务 为外部 DNS 名称提供内部别名。内部客户端使用内部 DNS 名称发出请求,然后请求会被重定向到外部名称。[30]
通过节点IP地址进行暴露服务,可使用;通过云服务提供商的负载均衡器暴露服务,则使用LoadBalancer
;[31]而当服务不在集群内,在集群之外,可以使用ExternalName
模式的服务进行重定向。
存储
[编辑]存储方案有很多。托管式的有如:网络附加存储(NAS)、数据库、文件服务器;非托管式的则利用Kubernetes 存储抽象,如:卷。[32]
卷
[编辑]对于应用而言,将数据写入容器中的磁盘文件是最简单的途径,但这种方法存在缺陷。如果容器因其他任何原因崩溃或停止,文件将会丢失。此外,一个容器内的文件不可供同一 Pod 中运行的其他容器访问。 卷(Volume)可以解决这两个问题。[33][34]
临时卷
[编辑]临时卷 与Pod的生命周期一样,随着包裹其的Pod终止或被删除时,该卷也会随之终止或删除。[33][34]
持久性卷
[编辑]持久性卷(Persistent Volumes),在 Pod 被移除时,系统只是卸载该卷,数据将保留,并可将其数据传递到另一个 Pod。[34]
健康检查
[编辑]K8s的对于容器的健康检查(Health Check)有三种:存活探测(Liveness Probe)、就绪探测(Readiness Probe)、启动探测(Startup Probe)。[35][36] 执行顺序如下
启动容器 --> Startup Probe ------> Readiness Probe
|----> Liveness Probe
存活探测
[编辑]存活探测(Liveness Probe):当不符合条件时,容器将会被重启。通常用于遇到Bug,无法进行下去的情况,如:死锁。[36]
常见的存活探测如下:根据命令、根据HTTP返回码、根据TCP是否连接成功。可用于判定命令是否执行成功,当失败且返回值为非0时,容器将会被重启;对于HTTP服务,可通过发送HTTP请求,并根据是否 400>返回码>=200
,判断是否存活;对于TCP连接,则在指定的时间内观察容器是否能连接成功,如果不能则重启容器。[36]
就绪探测
[编辑]就绪探测(Readiness Probe):当符合条件时,容器将被视为已就绪。就绪探测的一个用途:当一个Pod的所有容器就绪后,将会告诉 服务 该Pod可被使用。[36]
通过TCP进行就绪探测,那么会循环进行TCP连接,直到连接成功,容器将会被视为就绪。通过命令行方式进行就绪探测,当返回值为0时,容器将会被视为就绪。[36]
启动探测
[编辑]启动探测(Startup Probe):当符合条件时,容器被视为已启动。当应用需要长时间进行启动时,启动探测 会在一定时间内不断地探测应用是否启动成功,当应用启动成功后,存活探测或就绪探测 可被启动;超过探测时间的话,容器将会被杀死,并且根据 restartPolicy
来做出相应操作。[36] [37]
日志架构
[编辑]容器化应用写入 stdout
和 stderr
的任何数据,都会被容器引擎捕获并被重定向到某个位置。[38] 如:Docker容器 的日志,可以在节点上查找得到。
常见问题
[编辑]连接应用
[编辑]Dashboard
[编辑]Dashboard 是关于Kubernetes用户接口相关操作的网页。通过Dashboard,用户可以对容器化应用进行部署、查看的概览信息、故障排除,以及管理集群资源。
直接连接
[编辑]通常想要在Pod里运行命令,会通过使用 kubectl exec [Pod名字] [命令]
命令,这与Docker一样。[39] 如果想要通过HTTP协议连接Pod(REST API),则可运行代理模式的 kubectl ,[40] 也可以编程的方式去访问 REST API。[41]
控制平面
[编辑]控制平面(Control Plane)管理着集群中的 工作节 和 Pod。在生产环境里,控制平面 经常会 连接(runs across)若干个计算机。[42]
容器编排层暴露出来的
The container orchestration layer that exposes the API and interfaces to define, deploy, and manage the lifecycle of containers.
Control Plane [43]。
控制平面组件 用于对集群进行全局决策(如:调度),并检测和响应集群事件(例如,当不满足部署的 replicas
字段时,启动新的 pod)。虽然 控制平面组件 可在集群中的任何节点上运行,但通常会安装在同一机器上。[42][44]
kube-scheduler
[编辑]kube-controller-manager
[编辑]etcd
[编辑]集群中的工作节点,将会运行着两个进程:[2]
- kubelet,用于与 master节点 进行通信。
- kube-proxy,一种网络代理,将 Kubernetes 的网络服务代理到每个节点上。
其他
[编辑]代理服务器
[编辑]通过 kubectl proxy
该命令将会运行一个反向代理,通过该代理,我们能直接访问 REST API (通过CURL或浏览器访问的方式)。[45] 再通过 http://代理地址/zhwiki/api/v1/namespaces/default/pods/应用地址/proxy
的方式方问
如若想访问应用的其他端口,则应使用 kubectl port-forward
,建立端口转发,如:调试数据库。
设计
[编辑]Kubernetes在设计结构上定义了一系列的构建模块,其目的是为了提供一个可以共同提供部署、维护和扩展应用程序的机制。组成Kubernetes的组件设计概念为松耦合和可扩展的,这样可以使之满足多种不同的工作负载。可扩展性在很大程度上由Kubernetes API提供,此API主要被作为扩展的内部组件以及Kubernetes上运行的容器来使用。[46]
对象
[编辑]Pod
[编辑]Kubernetes的基本调度单元称为“pod”。通过该种抽象类别可以把更高级别的抽象内容增加到容器化组件。一个pod一般包含一个或多个容器,这样可以保证它们一直位于主机上,并且可以共享资源。[46]Kubernetes中的每个pod都被分配一个唯一的(在集群内的)IP地址就可以允许应用程序使用同一端口,而避免了发生冲突的问题。[47] Pod可以定义一个卷,例如本地磁盘目录或网络磁盘,并将其暴露在pod中的一个容器之中。[48]。pod可以通过Kubernetes API手动管理,也可以委托给控制器来实现自动管理。[46]
标签和选择器
[编辑]Kubernetes使客户端(用户或内部组件)将称为“标签”的键值对附加到系统中的任何API对象,如pod和节点。相应地,“标签选择器”是针对匹配对象的标签的查询方法。[46]
标签和选择器是Kubernetes中的主要分组机制,用于确定操作适用的组件。[49]
例如,如果应用程序的Pods具有系统的标签 tier
(比如"front-end
"、"back-end
") 和一个 release_track
(比如"canary
"、"production
"),那么对所有"back-end
" 和 "canary
" 节点的操作可以使用如下所示的标签选择器:[50]
tier=back-end AND release_track=canary
控制器
[编辑]控制器是通过管理一组pod来实现来将实际集群状态转移到所需集群状态的对帐循环机制[51]。一种控制器指的是一组具有相同特征的“复制控制器”,控制器通过在集群中运行指定数量的pod副本来处理复制和缩放。在基础节点出现故障的情况下,它还可以用于处理创建替换pod。[51]其它控制器也是核心Kubernetes系统的一部分,包括“DaemonSet控制器”为每台机器(或机器的一些子集)上运行的单个pod,和用于运行pod的“作业控制器”。[52] 控制器管理的pod组由作为控制器定义的部分的标签选择器来确定。[50]
服务
[编辑]Kubernetes服务本质是一组协同工作的pod,类同多层架构应用中的一层。构成服务的pod组通过标签选择器来定义。[46]Kubernetes通过给服务分配静态IP地址和域名来提供服务发现机制,并且以轮循调度的方式将流量负载均衡到能与选择器匹配的pod的IP地址的网络连接上(即使是故障导致pod从一台机器移动到另一台机器)。[47] 默认情况下,服务任务会暴露在集群中(例如,多个后端pod可能被分组成一个服务,前端pod的请求在它们之间负载平衡);除此以外,服务任务也可以暴露在集群外部(例如,从客户端访问前端pod)。[53]
参考文献
[编辑]- ^ PaaS将吞噬云计算?Kubernetes的市场冲击波-InfoQ. www.infoq.cn. [2020-03-31].
- ^ 2.0 2.1 2.2 2.3 2.4 Concepts. kubernetes.io. [2020-03-31] (英语).
- ^ 3.0 3.1 Kubernetes API Overview. kubernetes.io. [2020-03-31] (英语).
- ^ 4.0 4.1 Understanding Kubernetes Objects. kubernetes.io. [2020-04-08] (英语).
- ^ Pod Overview. kubernetes.io. [2020-04-01] (英语).
- ^ Pod | Kubernetes Engine Documentation. Google Cloud. [2020-04-13] (英语).
- ^ 7.0 7.1 Using a Service to Expose Your App. kubernetes.io. [2020-04-12] (英语).
- ^ DNS for Services and Pods. kubernetes.io. [2020-04-09] (英语).
- ^ 9.0 9.1 Service. kubernetes.io. [2020-04-09] (英语).
- ^ 没有选择器的服务. kubernetes.io. [2020-04-10] (英语).
- ^ Labels and Selectors. kubernetes.io. [2020-04-04] (英语).
- ^ ReplicationController. kubernetes.io. [2020-05-03] (英语).
- ^ ReplicaSet. kubernetes.io. [2020-05-03] (英语).
- ^ DaemonSet. kubernetes.io. [2020-05-03] (英语).
- ^ DaemonSet | Kubernetes Engine Documentation. Google Cloud. [2020-05-03] (英语).
- ^ Using kubectl to Create a Deployment. kubernetes.io. [2020-04-11] (英语).
- ^ kubernetes/kubernetes. GitHub. [2020-04-14] (英语).
- ^ Declarative Management of Kubernetes Objects Using Configuration Files. kubernetes.io. [2020-04-14] (英语).
- ^ Pod | Kubernetes Engine Documentation. Google Cloud. [2020-04-14] (英语).
- ^ Running a job | Kubernetes Engine Documentation. Google Cloud. [2020-05-02] (英语).
- ^ CronJob. kubernetes.io. [2020-05-03] (英语).
- ^ 22.0 22.1 22.2 22.3 22.4 Using Minikube to Create a Cluster. kubernetes.io. [2020-04-11] (英语).
- ^ 23.0 23.1 Introduction to Kubernetes architecture. www.redhat.com. [2020-04-20] (英语).
- ^ 24.0 24.1 Kubernetes Components. kubernetes.io. [2020-04-29] (英语).
- ^ Controllers. kubernetes.io. [2020-04-20] (英语).
- ^ Kubernetes 组件. kubernetes.io. [2020-04-29] (中文).
- ^ Kubernetes Components. kubernetes.io. [2020-03-31] (英语).
- ^ 28.0 28.1 node-components. kubernetes.io. [2020-04-12] (英语).
- ^ Service. kubernetes.io. [2020-05-03] (英语).
- ^ Exposing applications using services | Kubernetes Engine Documentation. Google Cloud. [2020-05-15] (英语).
- ^ publishing-services-service-types. kubernetes.io. [2020-04-12] (英语).
- ^ Storage overview | Kubernetes Engine Documentation. Google Cloud. [2020-04-14] (英语).
- ^ 33.0 33.1 Volumes | Kubernetes Engine Documentation. Google Cloud. [2020-04-13] (英语).
- ^ 34.0 34.1 34.2 Volumes. kubernetes.io. [2020-04-13] (中文).
- ^ Health checks overview | Load Balancing. Google Cloud. [2020-04-17] (英语).
- ^ 36.0 36.1 36.2 36.3 36.4 36.5 Configure Liveness, Readiness and Startup Probes. kubernetes.io. [2020-04-16] (英语).
- ^ Pod Lifecycle. kubernetes.io. [2020-04-17] (英语).
- ^ 日志架构. kubernetes.io. [2020-04-18] (中文).
- ^ Get a Shell to a Running Container. kubernetes.io. [2020-04-02] (英语).
- ^ directly-accessing-the-rest-api. kubernetes.io. [2020-04-02] (英语).
- ^ programmatic-access-to-the-api. kubernetes.io. [2020-04-02] (英语).
- ^ 42.0 42.1 Kubernetes Components. kubernetes.io. [2020-03-31] (英语).
- ^ The container orchestration layer that exposes the API and interfaces to define, deploy, and manage the lifecycle of containers.
- ^ Kubernetes 组件. kubernetes.io. [2020-03-31] (中文).
- ^ Accessing Clusters. kubernetes.io. [2020-04-02] (英语).
- ^ 46.0 46.1 46.2 46.3 46.4 An Introduction to Kubernetes. DigitalOcean. [24 September 2015].
- ^ 47.0 47.1 Langemak, Jon. Kubernetes 101 – Networking. Das Blinken Lichten. 2015-02-11 [2015-11-02].
- ^ Strachan, James. Kubernetes for Developers. Medium (publishing platform). 2015-05-21 [2015-11-02].
- ^ Surana, Ramit. Containerizing Docker on Kubernetes. LinkedIn. 2015-09-16 [2015-11-02].
- ^ 50.0 50.1 Intro: Docker and Kubernetes training - Day 2. Red Hat. 2015-10-20 [2015-11-02]. (原始内容存档于2015-10-29).
- ^ 51.0 51.1 Overview of a Replication Controller. Documentation. CoreOS. [2015-11-02].
- ^ Sanders, Jake. Kubernetes: Exciting Experimental Features. Livewyer. 2015-10-02 [2015-11-02].
- ^ Langemak, Jon. Kubernetes 101 – External Access Into The Cluster. Das Blinken Lichten. 2015-02-15 [2015-11-02].