警告
本文最后更新于 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
|
在一个 Pod 中,可以通过这个域名来访问另一个 Pod 中的服务,而无需使用 Pod 的 IP 地址。这个域名如 hello-svc.default.svc.cluster.local:
hello-svc: 服务名称,即服务的 DNS 名称(如果服务未指定名称,则默认为 Kubernetes 中的 Pod 名称)。
default: 命名空间名称,即服务所属的命名空间(如果未指定,则为默认命名空间)。
svc: 服务类型,表示这是一个 Kubernetes 中的服务。
cluster.local: 集群域名,表示该服务所在的 Kubernetes 集群的域名。
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:用于标识应用程序或服务的所有者和维护者。
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
|