Kubernetes学习笔记
本文部分概念解释可能会使用AI进行总结
一些基本认知
-
Kubernetes也叫K8s,是因为K和s中间有8个字母。
-
K8s是一个基于容器技术的分布式架构方案,是容器云的平台型方案,各大云厂商都有基于K8s的容器服务,是新一代基于容器技术的PaaS平台的重要底层框架。利用K8s,可以方便的在各大云平台和本地服务器上实现迁移。
-
K8s是一个完备的分布式系统支撑平台,具备完善的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制,以及多粒度的资源配额管理能力。
-
K8s提供了完善的管理工具,这些工具涵盖了开发,部署,测试,运维监控等各个环节。
重要概念
资源对象
- Node(节点):
节点是Kubernetes中的工作机,可以是虚拟机或物理机,它负责运行容器应用。每个节点包括Kubelet(管理节点和与集群通信的代理)、容器运行时(如Docker或containerd),以及用于网络通信的代理。 - Pod(容器组):
Pod是Kubernetes中的基本部署单元,也是可以创建和管理的最小可部署实体。一个Pod可以包含一个或多个容器,这些容器共享存储、网络和其他资源。 - Service(服务):
Service是一个抽象层,它为运行在一个或多个Pod上的应用提供了一个统一的访问接口。这使得外部访问Pod提供的服务更加容易,且不受单个Pod生命周期的影响。 - Volume(卷):
卷是一个可以被Pod中一个或多个容器访问的数据存储区域。它是一种抽象出来的存储资源,用于解决容器和Pod的数据持久化问题。 - Label(标签):
标签是附加到资源如Pods、Services等上的键值对,用于组织、选择和执行资源上的操作。通过标签,用户可以非常灵活地管理群集中的资源组。 - Annotation(注解):
注解也是键值对,用于存储额外的非标识信息,以帮助客户端如工具和库处理资源,但它们不用于标识和选择资源。 - Namespace(命名空间):
命名空间是对一组资源和对象的逻辑分组,它可以帮助不同的项目、团队或客户在同一个物理集群中隔离运行。 - Deployment(部署):
Deployment是对Pod和ReplicaSet(管理Pod副本的控制器)的声明式更新。它能够定义应用的生命周期,如更新、回滚等操作。 - HPA(Horizontal Pod Autoscaler):
水平Pod自动扩缩器自动根据CPU使用率或其他选择的度量标准调整Pod的数量。它提高了应用的可扩展性和资源效率。 - PVC(Persistent Volume Claim,持久卷申领):
PVC是用户对存储资源的请求。用户可以请求特定大小和访问模式的存储资源,而无需关心后端存储技术的具体细节。
集群类
- Master(包含kube-apiserver, kube-controller-manager, kube-scheduler,etcd服务)
- Node(kubelet,kube-proxy, docker)与Master一样,Node可以是一台物理主机,也可以是一台虚拟机。一台虚拟机只能部署一个Node。
应用类
- Service与Pod:
Service是一个定义了如何访问一组Pod的规则的抽象。它允许通过一个固定的IP地址和端口访问后端的一个或多个Pod。Service通过选择器来选择它要代理流量的Pods。这样,即使后台Pod的数量或实例发生变化,Service提供的访问点仍然保持不变。 - Label 标签选择器:
标签选择器用于选择一组通过标签(key-value对)标记的资源。在Kubernetes中,这通常用于Service选择它要路由流量的Pods,或者在Deployment中指定哪些Pods应该被纳入管理范围。通过标签选择器,用户可以非常灵活地管理群集中的资源。 - Pod与Deployment:
Pod是运行容器的最小单元,而Deployment是管理Pod的生命周期的一种方式,如创建、更新和删除。Deployment使用模板定义Pod的期望状态,并确保任何时候都有指定数量的Pod副本在运行。如果Pod失败,Deployment将自动替换它,保证系统的可用性和稳定性。 - Service的ClusterIP地址:
ClusterIP是Service的一种类型,它为Service提供了一个集群内部的虚拟IP,只能从集群内部访问。这是实现Pod之间通信的标准方法,例如,后端数据库服务和前端应用服务之间的通信。 - Service的外网访问:
若要使Service能够从外部网络访问,可以使用类型为NodePort或LoadBalancer的Service。NodePort打开每个节点上的一个端口,使得外部请求可以通过任何节点的此端口访问Service。LoadBalancer类型使用云提供商的负载均衡器来分配外部流量到后端Pods。 - 有状态的应用集群:
有状态应用(如数据库)需要持久化存储和唯一的网络标识。StatefulSets是Kubernetes中的一个API对象,用于管理有状态应用。它保证了Pod的部署和扩展顺序,并且可以保持Pod的身份不变,即使它们被重新调度到其他节点上。 - 批处理应用:
对于需要执行一次性任务或批处理工作的应用,可以使用Kubernetes的Job资源。Job保证批处理任务可以运行到完成,如果任务失败,它可以重新启动容器直到任务成功完成。 - 应用的配置问题:
应用配置通常通过ConfigMaps和Secrets来管理。ConfigMaps用于存储非机密的配置数据,如配置文件和环境变量。Secrets用于存储敏感信息,如密码和API密钥。这些资源可以被Pods在运行时访问,以便根据配置来调整其行为。 - 应用的运维问题:
Kubernetes提供了多种监控和日志记录工具来帮助运维。例如,使用Metrics Server收集集群性能数据,使用Elasticsearch、Fluentd和Kibana(EFK)堆栈进行日志聚合和分析。此外,Prometheus和Grafana常用于监控Kubernetes集群的性能并提供实时可视化。
存储类
- emptyDir:
emptyDir 是一个在Pod的生命周期内存在的临时目录。当一个Pod被分配到一个节点上时,会为该Pod创建一个emptyDir卷。emptyDir在Pod运行期间一直存在,无论容器崩溃与否。但是,当Pod从节点上删除时,emptyDir的内容也会被永久删除。emptyDir适合临时存储,如缓存数据和工作文件。 - hostPath:
hostPath 卷用于将节点文件系统上的文件或目录挂载到你的Pod中。这允许Pod直接访问到节点的文件系统,可以用于运行需要访问特定系统文件的应用,或者从Kubernetes集群外部存储数据。然而,使用hostPath需要小心,因为它可以影响节点的稳定性,并且与Pod的可移植性和安全性相冲突。 - 公有云Volume:
在公有云(如AWS, Azure, Google Cloud)环境中,Kubernetes支持使用云提供商的存储资源作为卷。例如,AWS上的EBS(Elastic Block Store)、Google Cloud的Persistent Disk和Azure的Disk Storage。这些卷类型支持持久存储,可以在Pod重启或迁移后保持数据不丢失。使用云卷可以利用云平台的高可用性和备份功能。 - 其他类型的Volume:
- NFS(Network File System):允许你将一个NFS(网络文件系统)服务器挂载到你的Pod上。NFS卷可以由多个Pod同时读写。
ConfigMap 和 Secret:用于在Pod中注入配置数据和敏感数据。ConfigMap 用于存储非敏感配置选项,而Secret用于存储密码、密钥等敏感信息。 - PersistentVolume (PV) 和 PersistentVolumeClaim (PVC):用于设置Pods使用的持久化存储。PersistentVolume 是集群中的一个存储资源,而PersistentVolumeClaim 是用户对存储资源的请求。
- CSI (Container Storage Interface):标准化的存储接口,使存储供应商可以开发一个插件,该插件能在多种容器编排系统中工作,包括Kubernetes。
安全类
Kubectl命令行
可以查看这位大佬的文章
kubectl命令大全
- 注意可以添加一些常用别名
- 自动补齐命令
yum -y install bash-completion
bash
source <(kubectl completion bash)
- 删除dev命名空间下所有处于Terminal状态的Pod(充分理解awk和xargs命令)
kubectl get pod -n dev | awk '{print $1}' | xargs -i kubectl delete pod {} --force --grace-period=0 -n dev
Pod
本节会介绍Pod的应用,配置,调度,升级和扩缩容,主要包括Pod和容器的使用,应用配置管理,pod的控制和调度管理,pod升级和回滚,以及pod的扩缩容机制。
Yaml文件
- 大小写敏感
- 使用缩进表示层级关系(缩进时不允许使用Tal键,只允许使用空格,缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- ”#” 表示注释,从这个字符一直到行尾,都会被解析器忽略
- 在Kubernetes中,只需要知道两种结构类型即可:Lists,Maps
- Deployment 管理的是replicaset-controller,RC会创建Pod。Pod自身会下载镜像并启动镜像。
- RC(replicaset-controller)主要功能:保持副本数量,扩容和缩容,滚动更新。
- 一般我们使用deployment而不是RC,因为Deployment 提供了更高级的功能,如声明式的更新(滚动更新和回滚)、暂停/恢复更新、状态检查等。
- 一个Pod里可以有多个容器,属于同一个Pod的多个容器之间互相访问只需要通过localhost就可以通信。
- 同一个Pod中的多个容器能共享Pod级别的存储卷Volume。
- ConfigMap生成容器的环境变量,设置容器启动命令的启动参数。
- ConfigMap 是一种用于存储配置信息的资源,允许你将非敏感数据(如配置文件、命令行参数等)以键值对的形式分离到容器应用之外,这样可以在不改动容器镜像的情况下调整应用的配置。
- ConfigMap必须在Pod之前创建,Pod才能引用。
- 一个Pod里可以有多个容器,属于同一个Pod的多个容器之间互相访问只需要通过localhost就可以通信。
- 同一个Pod中的多个容器能共享Pod级别的存储卷Volume。
副本的作用
- 高可用性:通过设置多个副本,即使在某些副本失败的情况下,应用程序也能继续运行。Kubernetes 的控制平面会监控集群中的 Pod,并在 Pod 数量少于预期时自动重启或创建新的 Pod。
- 负载均衡:副本允许在多个 Pod 实例之间分配流量,这有助于负载均衡和提高应用程序的处理能力。
- 滚动更新:在更新应用程序时,Kubernetes 可以控制更新过程中运行的不同版本的数量,从而实现零停机部署。例如,可以设置滚动更新策略,逐步替换旧版本的 Pod,直到所有副本都已更新到新版本。
- 弹性伸缩:基于当前负载,Kubernetes 可以自动调整 Pod 的数量。如果应用程序接收到的流量增加,可以增加副本数量;如果流量减少,可以减少副本数量。
- 资源管理:副本控制器(ReplicationController)、副本集(ReplicaSet)或部署(Deployment)等资源可以确保始终有指定数量的 Pod 运行。这些资源还提供了其他功能,如滚动更新和回滚。
创建Pod的YAML及其解释
apiVersion: v1
# 指定 Kubernetes API 的版本,这里使用的是 v1。
kind: Pod
# 定义要创建的资源类型,这里是 Pod。
metadata:
#metadata 字段用于存储关于 Kubernetes 资源的元数据。
name: test-pod
# Pod 的名称,在同一个命名空间中必须是唯一的。
namespace: my-namespace # 指定资源所属的命名空间
labels:
k8s-app: apache
version: v1
kubernetes.io/cluster-service: "true"
# 标签是键值对,用于组织和选择对象的子集。
annotations:
example.com/my-annotation: "some-value"
# annotations 用于存储额外的元数据,这些元数据用于存放一些不会用于标识和选择资源的信息。
#注解可以用于工具、库和客户端API,
#它们可以包含比 labels 更大的、非标识性的元信息,可以是任意的非结构化数据。
#注解的常见用途包括:
#1. 说明资源的修补或更改的信息
#2. 工具的配置选项,如构建、部署工具
#3. 对资源的描述,如使用该资源的人的电话信息等
#4. 管理操作记录,如日志、监控、分析等
spec:
#spec 字段定义了 Kubernetes 对象的期望状态。这包括了资源需要运行的详细配置
restartPolicy: Always
# Pod 的重启策略。"Always"表示如果 Pod 崩溃,将自动重启。
nodeSelector:
zone: node1
# 调度约束,指定 Pod 可以调度到哪些节点,基于节点的标签。
containers:
- name: test-pod
# Pod 中容器的名称。
image: 10.192.21.18:5000/test/chat:latest
# 容器使用的镜像。
imagePullPolicy: Never
# 拉取镜像的策略。"Never" 表示假定镜像已经存在于本地。
command: ['sh']
# 覆盖镜像默认的 ENTRYPOINT 的命令。
args: ["$(str)"]
# 传递给命令的参数。
env:
- name: str
value: "/etc/run.sh"
# 容器中的环境变量。
resources:
requests:
cpu: 0.1
memory: 32Mi
# 容器运行所需的最小资源。如果不满足,容器将不会启动。
limits:
cpu: 0.5
memory: 1000Mi
# 容器可以使用的最大资源。超过可能会导致容器重启或被杀死。
ports:
- containerPort: 80
name: httpd
protocol: TCP
# 容器监听的网络端口。
livenessProbe:
httpGet:
path: /
port: 80
scheme: HTTP
# 用于检查容器健康的探针。如果失败,容器将被重启。
initialDelaySeconds: 180
#这里时间如果过短,pod还没起来的话可能会导致pod反复重启
timeoutSeconds: 5
periodSeconds: 15
# 活跃探针的初始延迟、超时和检查周期。
lifecycle:
postStart:
exec:
command:
- 'sh'
- 'yum upgrade -y'
# 容器启动后执行的命令。
preStop:
exec:
command: ['service httpd stop']
# 容器停止前执行的命令。
volumeMounts:
- name: volume
mountPath: /data
readOnly: True
# 指定挂载到容器的卷。
volumes:
- name: volume
hostPath:
path: /opt
# 定义一个卷,它将主机的路径挂载到容器中。
创建Deployment的Yaml文件
apiVersion: apps/v1 # 指定 Kubernetes API 的版本,这里使用 apps/v1 是因为 Deployment 属于 apps 组
kind: Deployment # 资源类型为 Deployment
metadata:
name: example-deployment # Deployment 的名称
namespace: default # 指定 Deployment 所属的命名空间,如果省略则默认为 default
labels:
app: myapp # 自定义标签,用于标识相关的资源组
annotations:
example.com/info: "This is a sample deployment" # 注解,用来存放额外的说明信息,不用于选择器
spec:
replicas: 3 # 副本数量,指定希望运行的 Pod 副本数
selector:
matchLabels:
app: myapp # 选择器,指定这个 Deployment 管理的 Pod 必须拥有的标签
strategy:
type: RollingUpdate # 更新策略为滚动更新
rollingUpdate:
maxSurge: 1 # 更新过程中最多可以超出的 Pod 数量
maxUnavailable: 0 # 更新过程中最多有多少个 Pod 不可用
template: # 模板,定义 Pods 的规格
metadata:
labels:
app: myapp # Pod 模板的标签,被上面的选择器使用
spec:
containers:
- name: my-container # 容器的名称
image: nginx:1.17 # 容器使用的镜像
ports:
- containerPort: 80 # 容器需要暴露的端口号
resources:
requests:
cpu: "100m" # 容器请求的 CPU 资源量
memory: "200Mi" # 容器请求的内存资源量
limits:
cpu: "200m" # 容器的 CPU 资源上限
memory: "400Mi" # 容器的内存资源上限
#CPU 资源的单位是核(cores)。m 代表毫核(milli-cores),即千分之一核。
env:
- name: ENV_VAR_NAME # 环境变量的名称
value: "value" # 环境变量的值
livenessProbe:
httpGet:
path: /health # 健康检查路径
port: 80 # 使用的端口
initialDelaySeconds: 15 # 容器启动后延迟多久开始健康检查
periodSeconds: 20 # 健康检查的间隔时间
readinessProbe:
httpGet:
path: /ready # 就绪检查路径
port: 80 # 使用的端口
initialDelaySeconds: 5 # 容器启动后延迟多久开始就绪检查
periodSeconds: 10 # 就绪检查的间隔时间
创建Service的YAML及其解释
apiVersion: v1 # Kubernetes API 版本,Service 属于 v1 版本
kind: Service # 资源类型是 Service
metadata:
name: my-service # Service 的名称
namespace: default # Service 所在的命名空间
labels:
app: myapp # 标签,用于标识 Service
annotations:
description: "Sample service" # 注解,用来提供有关 Service 的更多信息
spec:
type: LoadBalancer # Service 类型,LoadBalancer 为外部访问提供负载均衡
selector:
app: myapp # 选择器,用于选择哪些 Pods 将被此 Service 管理
ports:
- name: http # 端口配置的名称
protocol: TCP # 通信协议,常用的是 TCP 或 UDP
port: 80 # Service 对外暴露的端口
targetPort: 8080 # Pod 内部的端口,流量将被转发到此端口
nodePort: 30000 # 当 type 为 NodePort 时使用,定义节点上的端口
sessionAffinity: None # 会话亲和性,控制是否将来自同一客户端的请求路由到同一 Pod
externalTrafficPolicy: Cluster # 定义如何路由外部流量到 Service,"Cluster" 或 "Local"
loadBalancerIP: 192.168.0.1 # 指定负载均衡器的 IP,一般用于特定云服务提供商
externalName: my-service.example.com # 当 Service 类型为 ExternalName 时使用,定义外部服务的引用
healthCheckNodePort: 30200 # 用于健康检查的节点端口,仅在某些类型的 Service 如 LoadBalancer 时使用
publishNotReadyAddresses: true # 是否允许流量到达未准备好的地址,通常用于在服务启动时的特殊情况
创建ConfigMap的Yaml文件
apiVersion: v1 # 指定API版本
kind: ConfigMap # 资源类型是ConfigMap
metadata:
name: example-configmap # ConfigMap的名称
namespace: default # ConfigMap所在的命名空间,默认为"default"
data:
key1: value1 # 数据项1,键名为key1,值为value1
key2: value2 # 数据项2,键名为key2,值为value2
binaryData:
key3: dmFsdWUz # 二进制数据项,键名为key3,值为value3的base64编码
Pod调度
- 默认调度:
调度器选择:Kubernetes的默认调度器会根据一系列调度算法(例如,预选和优选)来决定Pod应该被调度到哪个节点。
预选阶段:这一阶段,调度器会过滤出那些资源不足以运行Pod的节点,例如CPU或内存不足。
优选阶段:在符合条件的节点中,调度器会根据一系列的优先级规则,选择最优的节点。例如,可能会选择负载较低的节点,或是网络延迟较小的节点。
亲和性与反亲和性调度: - 节点亲和性(Node Affinity):允许你指定Pod应该被调度到满足特定规则的节点。例如,你可以指定Pod只能在具有特定标签的节点上运行。
Pod亲和性与反亲和性(Pod Affinity/Anti-Affinity):允许你指定Pod之间的亲和性或反亲和性。亲和性可以用来将相关的Pod部署到靠近彼此的节点上,而反亲和性则用来确保某些Pod不会被调度到相同的节点。 - 污点和容忍度(Taints and Tolerations):
污点:可以被添加到节点上,表示该节点可能不适合运行某些Pod。只有当Pod具有匹配的容忍度时,它才能被调度到带有特定污点的节点。
容忍度:是设置在Pod上的,允许Pod忍受一个或多个污点,从而能在带有这些污点的节点上运行。 - 守护进程集(DaemonSets):
特殊调度方式,用于需要在每个或某些特定节点上运行的服务。例如,日志收集器或监控代理。DaemonSet确保每个选定的节点上都运行一个Pod副本,而无需显式的调度指令。 - 优先级和抢占:
Pod可以被赋予优先级,高优先级的Pod可以抢占低优先级的Pod,以确保重要的应用能够获得所需的资源。 - Job:批处理调度
通过Job资源对象来定义并启动一个批处理任务。批处理任务通常并行(或者串行)启动多个计算进程去处理一批工作项,处理完成后,整个批处理任务结束。 - Cronjob:定时任务
Pod的升级和回滚
- 通过kubectl set image来为Deployment设置新的镜像名。
kubectl set image deployment/nginx-deployment nginx=nginx:1.2.2
- 也可以直接使用edit来编辑deployment的yaml文件修改镜像版本
kubectl edit deployment/nginx-deployment
- 镜像名一旦发生更改,将触发系统完成deployment所有运行pod的滚动升级操作,可以用以下命令查看更新过程
kubectl rollout status deployment/nginx-deployment
kubectl get pods
- 本质上是通过ReplicaSet来更新。更新时会先创建一个新的rs,新的rs有一个副本,然后旧的rs减一;一个pod副本创建好后,新的rs增加一,旧的rs减一,以此类推。
- Deployment的定义中,可以通过spec,strategy来指定pod更新策略,目前可以指定Recreate(更新时先杀掉正在运行的Pod,然后创建)和RollingUpdate(滚动更新)。
Service
Kubernetes(K8s)中的 Service 是一个抽象概念,它定义了一种访问应用程序容器的方法,并将此访问方式与容器的具体运行实例分离开来。简单来说,Service 允许通过一个固定的 IP 地址和端口来访问一组动态变化的 Pod 实例。这样即使后端 Pod 实例发生变化,前端服务的访问地址和方式仍然保持不变。
Service 的主要类型有:
- ClusterIP:这是默认的 Service 类型,它为 Service 在内部集群中分配一个内部 IP 地址,使得 Service 可以在集群内部被访问,但不能从集群外部访问。
- NodePort:这种类型的 Service 在 ClusterIP 基础上为 Service 在所有节点的一个指定端口上提供访问,从而可以从集群外部访问 Service。
- LoadBalancer:这种类型的 Service 使用云提供商的负载均衡器,可以从外部访问一个分配给 Service 的固定公共 IP 地址。
- ExternalName:通过返回一个任意的名称(通常是可以解析的外部域名),这种类型的 Service 允许 Service 作为集群内部的代理到一个外部服务。
Service的YAML文件
apiVersion: v1 # 指定 Kubernetes API 版本,v1 是大多数核心资源的 API 版本
kind: Service # 指定资源类型为 Service
metadata:
name: my-service # Service 的名字
labels:
app: MyApp # 标签可以用来组织、选择和分类资源
spec:
type: LoadBalancer # 指定 Service 类型,LoadBalancer 使服务通过外部负载均衡器可访问
selector:
app: MyApp # 选择器,用于选择哪些 Pod 将被此 Service 的流量所访问
tier: frontend # 可以使用多个标签来更精细地控制选择的 Pod
ports:
- protocol: TCP # 指定使用的协议,通常是 TCP 或 UDP
port: 80 # Service 上的端口,外部通信到此端口
targetPort: 9376 # Pod 上的端口,流量将被转发到此端口
nodePort: 30007 # 当类型为 NodePort 时,这是集群外部可用来访问 Service 的端口
sessionAffinity: ClientIP # 会话亲和性设置为基于客户端 IP,确保来自同一客户端的请求被发送到同一 Pod
externalTrafficPolicy: Local # 控制是否保留外部流量的源 IP,设置为 Local 时只有本地节点上的 Pod 会处理流量
healthCheckNodePort: 30234 # 当设置外部流量策略并使用 LoadBalancer 时,用于健康检查的节点端口
loadBalancerIP: 192.0.2.1 # 指定负载均衡器的 IP 地址
loadBalancerSourceRanges:
- 192.0.2.0/24 # 限制哪些 IP 地址范围可以访问 LoadBalancer
externalName: my.external.example.com # 当 Service 类型为 ExternalName 时,指定服务请求应该被解析和转发到的外部域名
Sercive的负载均衡机制
kube-proxy代理
- userspace模式
- iptables模式
- ipvs模式
持续更新中