警告
本文最后更新于 2021-07-06 ,文中内容可能已过时。
Kubernetes 的主节点和工作节点都是集群中非常重要的组件。下面我们来更加详细地介绍一下它们的工作职能。
主节点:
API Server :作为 Kubernetes 的中央控制中心,API Server 负责所有组件之间的通信。API Server 接收到客户端的请求后,会将请求转发给相应的组件处理。
集群存储:集群存储是整个控制层中唯一有状态(stateful)的部分,它持久化地存储了整个集群的配置与状态。集群存储在 Kubernetes 中扮演着至关重要的角色,可以为集群中的其他组件提供高效的存储和读取服务。
Controller 管理器 :Controller 管理器是 Kubernetes 中的后台控制循环,它监控整个集群的状态,并根据预定义的操作执行相关的任务。Controller 管理器可以通过 API Server 与其他组件通信,以便更好地管理整个集群。
调度器 :Kubernetes 调度器的主要职责是监听 API Server 并启动新的工作任务,将任务分配到适合且正常运行的节点上。调度器可以根据容器的资源需求、亲和力、反亲和力等因素进行调度,并确保整个集群的负载均衡。
工作节点:
Kubelet :是每个工作节点上的重要代理端,它负责与主节点中的 API Server 通信,并根据主节点的指示来管理工作节点上的容器。Kubelet 还可以对容器的运行状况进行监控,并在容器故障时采取相应的措施。
容器运行时 :Kubelet 需要一个容器运行时(container runtime)来执行依赖容器才能执行的任务,例如拉取镜像并启动或停止容器。Docker 是 Kubernetes 最常用的容器运行时,但也可以使用其他容器运行时,例如 CRI-O、containerd 等。
kube-proxy :kube-proxy 是 Kubernetes 中用于管理网络代理的组件,它在每个工作节点上运行。kube-proxy 负责实现 Kubernetes 中的服务发现功能,为集群中的容器提供本地网络代理服务。
Deployment 是 Kubernetes 用来进行应用部署和更新的 API 对象之一,通过它可以控制 Pod 的副本数量、容器的升级等等。Deployment 对象通过定义 Pod 模板来创建管理 ReplicaSet,能够保证所需的 Pod 副本数与运行的 Pod 副本数保持一致。
ReplicaSet 是 Kubernetes 中用于控制 Pod 副本数量,保证用户指定的副本数始终已在集群中运行的 API 对象之一。一般情况下,我们使用 Deployment 来提供 ReplicaSet 和管理 Pod 的配置,而不会直接使用 ReplicaSet。这样,在 Deployment 进行滚动更新时,对应 ReplicaSet 也会自动更新 Pod 配置和个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion : apps/v1 #旧版 K8s 使用 apps/v1beta1
kind : Deployment
metadata :
name : hello-deploy
namespace : dev
spec :
replicas : 2
selector : # Pod 所必须具备的标签
matchLabels :
app : hello-world
minReadySeconds : 10
strategy : # Pod 的更新操作
type : RollingUpdate
rollingUpdate :
maxUnavailable : 1 # 不允许出现比期望状态指定的 Pod 数量少超过一个的情况
maxSurge : 1 # 不允许出现比期望状态指定的 Pod 数量多超过一个的情况
template : # 管理的 Pod 模板
metadata :
labels :
app : hello-world # 这个 Label 与 Service 的 Label 筛选器是匹配的
spec :
containers :
- name : hello-pod
image : nginx:latest
ports :
- containerPort : 80
volumeMounts :
- mountPath : "/usr/share/nginx/html"
name : nginx-pv-storage
volumes :
- name : nginx-pv-storage
persistentVolumeClaim :
claimName : nfs-pvc
metadata
中的 labels
是用于标记和标识 Kubernetes 资源对象,Kubernetes 元数据。
template
中的 labels
则是用于标记和标识部署对象所创建的 Pod,Pod 元数据。
1
2
3
4
5
6
7
8
9
10
11
kubectl apply -f deploy.yml --record
kubectl rollout status deployment hello-deploy
kubectl get deploy
# 查看历史记录
kubectl rollout history deployment hello-deploy
# 回滚到版本1
kubectl rollout undo deployment hello-deploy --to-revision=1
每个工作节点中都运行相应服务的实例
主要用于部署有状态应用,如MySQL。
部署前需要 StorageClass
和 headless Service
。
部署的应用之间是点对点发现的。
sts.spec.volumeClaimTemplates
在每次创建一个新的 Pod 副本的时候,自动创建一 个 PVC。
删除 Pod, PVC会保留,恢复后会绑定原来的PVC。
sts.spec.podManagementPolicy
:控 Pod 的启动和停止的顺序。
sts.spec.updateStrategy
:升级操作总是从索引号最大的 Pod 开始,每次更新一个 Pod,直至最小索引号的 Pod。
kubectl scale sts tkb-sts --replicas=0
:依次删除Pod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
apiVersion : apps/v1
kind : StatefulSet
metadata :
name : tkb-sts
spec :
replicas : 3
selector :
matchLabels :
app : web
serviceName : "dullahan" # 与 handless Service 绑定
template :
metadata :
labels :
app : web
spec :
terminationGracePeriodSeconds : 10
containers :
- name : ctr-web
image : nginx:latest
ports :
- containerPort : 80
name : web
volumeMounts :
- name : webroot
mountPath : /usr/share/nginx/html
volumeClaimTemplates : # 用于在每次创建一个新的 Pod 副本的时候,自动创建一 个 PVC。
- metadata :
name : webroot
spec :
accessModes : [ "ReadWriteOnce" ]
storageClassName : "flash"
resources :
requests :
storage : 1Gi
1
2
3
# StatefulSet 的应用是点对点发现的
# tkb-sts-0.dullahan.default.svc.cluster.local
<object-name>.<Service-name>.<namespace>.svc.cluster.local
不定期运行的临时任务则由定时任务
ClusterIP Service :拥有固定的 IP 地址和端口号,并且仅能够从集群内部访问得到。(默认类型)
NodePort Service :在 ClusterIP 的基础上增加 了从集群外部访问的可能。
LoadBalancer Service :能够与诸如 AWS、Azure、DO、IBM 云和 GCP 等云服务商提供的负载均衡服务集成。
ExternalName Service :能够将流量路由至 Kubernetes 集群之外的系统中去(所有其他类 型的 Service 都是在集群内部进行流量的路由)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion : v1
kind : Service
metadata :
name : hello-svc # 集群 DNS 中注册的名称
labels :
app : hello-world
spec :
type : NodePort
ports :
- port : 8080
nodePort : 30001
protocol : TCP
selector :
app : hello-world # # Service 查找带有 app=hello-world 的 Pod
1
2
3
4
5
6
7
8
# 查看 service
kubectl get svc
# 查看 service 后面的 endpoints
kubectl get ep
# 命令式方法部署Service
kubectl expose deployment web-deploy --name= hello-svc --target-port= 8080 --type= NodePort
Post到API server
给SVC分配ClusterIP
存储到ETCD
EndPoint创建
CoreDNS发现新得SVC
创建DNS记录
kube-proxy拉取SVC配置
创建IPVS规则
在一个 Pod 中,可以通过这个域名来访问另一个 Pod 中的服务,而无需使用 Pod 的 IP 地址。这个域名如 hello-svc.default.svc.cluster.local
:
hello-svc
: 服务名称,即服务的 DNS 名称(如果服务未指定名称,则默认为 Kubernetes 中的 Pod 名称)。
default
: 命名空间名称,即服务所属的命名空间(如果未指定,则为默认命名空间)。
svc
: 服务类型,表示这是一个 Kubernetes 中的服务。
cluster.local
: 集群域名,表示该服务所在的 Kubernetes 集群的域名。
A 请求DNS解析
A 获取 B 的 ClusterIP
A 发送数据到 B 的 ClusterIP
发送到网关
通过三层路由转发到对应 B 节点
被 B 节点内核处理
通过 IPVS 规则处理, 目标 ClusterIP 改为 PodIP
headless Service 就是一个将 spec.clusterIP
设置为 None 的常规 Kubernetes Service 对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Headless Service for StatefulSet Pod DNS names
apiVersion : v1
kind : Service
metadata :
name : dullahan # 与 StatefulSet 的 ServiceName 关联
labels :
app : web
spec :
ports :
- port : 80
name : web
clusterIP : None
selector :
app : web
各种 Label 的组合
app
、zone
、ver
:应用名称,环境(测试,生产),版本
app
、component
、tier
:用于区分应用程序中的不同组件和层次。
app=web
、component=frontend
、tier=web
用于前端应用程序
app=web
、component=backend
、tier=api
用于 API 服务。
env
、stage
:用于标识不同的环境和阶段。
env=dev
、stage=test
用于开发测试环境
env=prod
、stage=prod
用于生产环境。
owner
、team
、contact
:用于标识应用程序或服务的所有者和维护者。
owner=devops
、team=infra
、contact=devops@example.com
用于 DevOps 团队维护的基础设施服务。
release
、git-commit
:用于标识应用程序或服务的版本和发布信息。
release=1.0.0
、git-commit=abc123
用于标识应用程序的版本和发布信息。
region
、zone
、datacenter
:用于标识服务或资源所在的区域、区域的子区域以及数据中心。
region=us-west-2
、zone=a
、datacenter=dc1
用于标识服务或资源所在的区域、区域的子区域以及数据中心。
cost-center
、budget
、service-level
:用于标识服务或资源的成本、预算和服务级别。
cost-center=12345
、budget=100000
、service-level=gold
用于标识服务或资源的成本、预算和服务级别。
容器存储接口(The Container Storage Interface, CSI)是 存储 和 Kubernetes 的中间层。
持久化卷(Persistent Volume,PV),持久化卷申请(Persistent Volume Claim,PVC),存储类(Storage Class,SC)是 Kunbernetes 的 持久化卷子系统。
PV 代表的是 Kubernetes 中的存储;
PVC 就像许可证,赋予 Pod 访问 PV 的 权限;
CS 则使分配过程是动态的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion : v1
kind : PersistentVolume
metadata :
name : nfs-pv
labels :
release : stable
spec :
capacity :
storage : 1024Gi
volumeMode : Filesystem
accessModes :
- ReadWriteMany
persistentVolumeReclaimPolicy : Retain
storageClassName : nfs
mountOptions :
- hard
- nfsvers=4.1
nfs :
path : "/data/k8s_data"
server : 192.168.0.100
readOnly : false
---
apiVersion : v1
kind : PersistentVolumeClaim
metadata :
name : nfs-pvc
spec :
storageClassName : nfs
accessModes :
- ReadWriteMany
resources :
requests :
storage : 1024Gi
spec.accessModes
定义了 PV 是如何被挂载的。
ReadWriteOnce(RWO)
:限制一个 PV 只能以读写方式被挂载或绑定到一个 PVC。尝试将其绑定到多个 PVC 的话会失败。块存储通常只支持 RWO。
ReadWriteMany(RWM)
:允许一个 PV 能够以读写方式被绑定到多个 PVC 上。这种模式通常只支持诸如 NFS 这样的文件或对象存储。
ReadOnlyMany(ROM)
:允许 PV 以只读方式绑定到多个 PVC。
如果 PV 和 PVC 需要绑定 accessModes
,storageClassName
,storage
需要一致。
spec.persistentVolumeReclaimPolicy
定义在 PVC 被释放 之后,如何处理对应的 PV
在 Kubernetes 中,存储类(Storage Class)是一种抽象层,用于定义 Kubernetes 中的不同存储技术,例如本地存储、网络存储和云存储等。通过使用存储类,可以将存储资源动态分配给 Kubernetes 集群中的不同应用程序和服务,并且可以根据应用程序和服务的需求进行灵活配置和管理。
存储类定义了动态存储分配策略,包括存储资源的类型、容量、访问模式和重试策略等。它们还可以定义存储类参数,例如数据复制策略、数据恢复选项和 QoS 类型等,以确保存储资源的高可用性和性能。
开发只需要创建PVC(只关心容量和速度),存储工程师只需要定义 SC(设置各种存储参数),PV 根据 PVC 和 SC 关联自动创建,这样就做到了存储工程师和开发工程师之间的分离。
StorageClass:对象是不可变的,这意味着它在部署之后无法进行修改。
metadata.name:应当是有意义的,因为其他对象可能会使用它来代指某个存储类。
provisioner 和 plugin 两个术语可以互相替换使用。
parameters:定义了与插件相关的值,每个插件可以支持其特有的一组参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
kind : StorageClass
apiVersion : storage.k8s.io/v1
metadata :
name : slow # 由 PVC 引用
annotations :
storageclass.kubernetes.io/is-default-class : "true"
provisioner : kubernetes.io/gce-pd
parameters :
type : pd-standard
reclaimPolicy : Retain
---
apiVersion : v1
kind : PersistentVolumeClaim
metadata :
name : pv-ticket # 由 PodSpec 引用
spec :
accessModes :
- ReadWriteOnce
storageClassName : slow # 匹配 SC 名称
resources :
requests :
storage : 25Gi
---
apiVersion : v1
kind : Pod
metadata :
name : class-pod
spec :
volumes :
- name : data
persistentVolumeClaim :
claimName : pv-ticket # 匹配 PVC 名称
containers :
- name : ubuntu-ctr
image : ubuntu:latest
command :
- /bin/bash
- "-c"
- "sleep 60m"
volumeMounts :
- mountPath : /data
name : data
删除操作
1
2
3
4
# 删除顺序为 Pod,PVC,SC
kubectl delete Pod class-Pod
kubectl delete pvc pv-ticket
kubectl delete sc slow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 通过命令创建 configMap
kubectl create cm testmap1 \
--from-literal shortname = msb.com \
--from-literal longname = magicsandbox.com
kubectl create cm testmap2 --from-file cmfile.txt
# 通过声明创建 configMap
kind: ConfigMap
apiVersion: v1
metadata:
name: test-conf
data:
test.conf: |
env = plex-test
endpoint = 0.0.0.0:31001
char = utf8
vault = PLEX/test
log-size = 512M
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion : v1
kind : Pod
metadata :
labels :
chapter : configmaps
name : envpod
spec :
restartPolicy : OnFailure
containers :
- name : ctr1
image : busybox
# 通过作为容器启动命令的参数
command : [ "/bin/sh" , "-c" , "echo First name $(FIRSTNAME) last name $(LASTNAME)" ]
env :
- name : FIRSTNAME
valueFrom :
configMapKeyRef :
name : multimap
key : given
- name : LASTNAME
valueFrom :
configMapKeyRef :
name : multimap
key : family