前端也要懂点k8s-上篇
点击关注公众号,“技术干货” 及时达!前言最近在采用Jenkins实现前端项目自动化部署功能,其中有一个步骤用到了k8s, 这一块知识令我感到比较陌生,看不懂配置文件里的语句含义,以及如何被外部的bash指令串联起来,刚好假期有时间,决定学习一下k8s。学完目标是学完之后要了解k8s常用的操作。现在我们进入今天的主题:
一、Kubernetes 简介Kubernetes(简称 K8s)是一个用于「自动部署、扩展和管理容器化应用程序」的开源系统。下图展示了Kubernetes集群的架构及其与外部系统的交互方式:
1.1 外部系统(External Systems)kubectl: 这是Kubernetes的命令行工具,用户可以通过它与Kubernetes API服务器进行交互,执行各种操作如创建、删除和更新资源。CI/CD Systems: 持续集成/持续部署系统可以使用Kubernetes API来自动化应用的部署和管理。Apps Use SDK to connect to API server: 应用程序可以使用SDK连接到Kubernetes API服务器,以实现更复杂的集成和自动化。1.2 Kubernetes 集群(Kubernetes Cluster)Kubernetes集群采用的是「主从架构(Master-Slave Architecture)」,主要由两个角色组成:
「控制平面(Control Plane)」:负责集群的整体管理和调度。「工作节点(Worker Node)」:负责实际运行应用容器。1.2.1 控制平面(Control Plane)控制平面是 Kubernetes 的“大脑”,主要负责接收用户指令、调度任务、监控运行状态。它包含以下组件:
组件说明「kube-apiserver」Kubernetes API服务器,所有请求的统一入口,提供 HTTP REST 接口,处理认证、授权、通信等「etcd」分布式 Key-Value 数据库,用于持久化存储集群所有状态数据「kube-scheduler」调度器负责将新建 Pod 分配到合适的 Node「kube-controller-manager」控制器管理器执行各种控制逻辑,比如运行多个控制器(副本控制器(ReplicaSet)、节点控制器、Job控制器等)「cloud-controller-manager」云控制器管理器,管理与云服务平台的集成(如负载均衡、存储卷等)所有这些组件通常运行在 Master 节点上。在生产环境中,控制平面可以做高可用部署(即多个 Master 节点):
保证 apiserver 的可用性(通过负载均衡)保证 etcd 的数据冗余与高一致性(通常部署 3 个及以上节点)避免单点故障,增强容灾能力1.2.2 工作节点(Worker Node)每个 Node 是实际运行容器的机器(虚拟机或物理机),其核心组件包括:
组件说明「kubelet」负责与 apiserver 通信,接收任务并在本地启动 Pod「kube-proxy」维护服务与 Pod 之间的网络规则,实现负载均衡「Container Runtime」运行容器的实际引擎,如 Docker、containerd、CRI-O1.2.3 云提供商APIsKubernetes可以通过云提供商APIs与云服务进行集成,例如负载均衡器、存储卷和身份认证等。这使得Kubernetes能够利用云平台提供的各种服务来增强其功能。
1.3 k8s和docker的关系?k8s和docker的用途都含有容器管理,初学者一般都搞不清楚两者之间的关系。可以理解为:「Docker 负责造车,Kubernetes 负责调度车队跑起来并保持秩序」。
名称定义「Docker」是一个「容器引擎」,用于打包、分发和运行容器化应用。「Kubernetes」是一个「容器编排平台」,用于自动化管理大量容器的部署、调度、伸缩和维护。「Docker 管理单个容器,Kubernetes 管理容器的集群」;它们各司其职,共同构成了现代云原生应用的基石。
维度DockerKubernetes类型容器运行时容器编排平台是否依赖对方不依赖早期依赖 Docker,后期依赖 CRI 接口管理粒度单个容器多个服务或容器组成的集群适用场景开发、测试、单机部署企业级生产环境的集群部署1.4 工作流程开发者通过 kubectl 提交 YAML 清单到 apiserver。apiserver 验证请求,并将信息存储到 etcd。scheduler 监听到新 Pod 创建请求,并根据调度算法分配到合适的 Node。对应 Node 上的 kubelet 接收到任务,调用 Container Runtime 启动容器。kube-proxy 设置好服务发现和访问规则,确保内部通信正常。二、搭建 Kubernetes 环境根据使用场景不同,k8s有三种搭建方式。三种搭建方式的优缺点如下:
搭建方式场景优点缺点1. 使用 Minikube 或 kind学习和开发快速启动、资源占用少非真实生产环境2. 使用 kubeadm 自建集群中小型生产环境或测试可控性强、接近生产配置复杂,需自行运维3. 使用云厂商托管服务(如 ACK、GKE、EKS)生产简单可靠、高可用成本较高、依赖厂商由于篇幅所限,本文只演示一下第一种搭建k8s环境的方式(以 macOS / Linux 为例):
2.1 安装 kubectl(Kubernetes 命令行工具)curl -LO"https://dl.k8s.io/release/$(curl -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
kubectl version --client
2.2 安装 Minikubecurl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
2.3 启动 Minikube 集群minikube start
2.4 查看集群节点状态kubectl get nodes
三、常用资源对象介绍Kubernetes 中资源种类很多,常见的有:
类型说明Pod最小部署单元Deployment部署与版本控制Service网络访问入口ConfigMap / Secret配置和密钥PersistentVolume / Claim存储Namespace命名空间管理3.1 Pod:最小部署单元3.1.1 什么是Pod?Pod 是 K8s 中最小的可调度单元。一个 Pod 包含一个或多个「容器(通常是 Docker 容器)」,这些容器共享:
网络(IP 和端口空间)存储(Volume 卷)生命周期(被视为一个整体)Pod 的典型用途是运行一个应用或服务的一个实例。一个 Pod 运行一个容器(最常见场景):
apiVersion:v1
kind:Pod
metadata:
name:nginx-pod
spec:
containers:
-name:nginx
image:nginx:1.24
ports:
-containerPort:80
这个 Pod 会启动一个 Nginx 容器,并暴露 80 端口。
3.1.2 Pod 生命周期Pod 的状态包括:
Pending: 等待调度资源Running: 正在运行Succeeded: 运行成功后退出Failed: 运行失败Unknown: 状态无法获取3.1.3 Pod的创建,查看与删除# 创建
kubectl apply -f nginx-pod.yaml
# 查看所有pod
kubectl get pods
# 查看某个pod
kubectl describe pod nginx-pod
# 删除
kubectl delete pod nginx-pod
上面给出的都是独立的pod的创建与管理方式,虽然你可以手动管理 Pod,但「更推荐使用 Deployment 控制器」,创建Pod,自动管理 Pod 的副本数量、自愈能力和升级策略。
3.2 Deployment:无状态应用的部署控制器Deployment 是 Kubernetes 中最常用的控制器之一,专门用于管理「无状态应用的生命周期」。它确保你的 Pod 副本在集群中始终按预期运行,并具备以下功能:
保证指定数量的 Pod 始终处于运行状态(副本控制)支持应用的滚动升级和回滚支持 declarative 式的配置和更新自动重建失败的 Pod(具备自愈能力)3.2.1 典型 Deployment 示例说明:
replicas: 设置运行的 Pod 数量为 3selector: 用于匹配管理哪些 Podtemplate: 定义 Pod 的内容(镜像、端口等)apiVersion:apps/v1
kind:Deployment
metadata:
name:my-nginx
spec:
replicas:3
selector:
matchLabels:
app:nginx
template:
metadata:
labels:
app:nginx
spec:
containers:
-name:nginx
image:nginx:1.24
ports:
-containerPort:80
3.2.2 Deployment 的工作逻辑寻找所有标签匹配selector.matchLabels的 Pod
如果数量不足replicas,则新建 Pod如果数量过多,则删除多余的 Pod如果标签相同但镜像等配置不同,则更新 PodDeployment 不直接控制 Pod,而是通过创建一个 ReplicaSet,再由 ReplicaSet 具体去创建 Pod,维护副本数量,做滚动更新。3.2.3 Deployment操作命令# 创建 Deployment
kubectl apply -f nginx-deploy.yaml
# 查看状态
kubectl get deployments
kubectl describe deployment nginx-deploy
# 查看管理的 Pod
kubectl get pods -l app=nginx
修改镜像并滚动升级,将nginx从1.24升级到1.25
spec:
containers:
-name:nginx
image:nginx:1.25
# 升级
kubectl apply -f nginx-deploy.yaml
# 查看历史记录
kubectl rollout history deployment nginx-deploy
# 回滚
kubectl rollout undo deployment nginx-deploy
3.3 Service:服务发现与负载均衡在 Kubernetes 中,「Pod 是会变化的」—— 当 Deployment 滚动更新、Pod 重启时,Pod 的 IP 会变。所以不能依赖 Pod 的 IP 地址来通信。
这就是 Service 出场的原因,它为一组 Pod 提供了一个「稳定的网络访问入口」,实现了:
「服务发现」(Pod 动态变动也能找到)「负载均衡」(多个 Pod 间自动分流请求)3.3.1 Service实例实例:为 nginx Pod 暴露一个 Service
apiVersion:v1
kind:Service
metadata:
name:nginx-service
spec:
selector:
app:nginx# 匹配被管理的 Pod(Deployment 创建的)
ports:
-protocol:TCP
port:80 # Service 对外暴露的端口
targetPort:80 # Pod 内部容器监听的端口
type:ClusterIP # 集群内访问(默认)
常见 Service 类型:
类型说明ClusterIP默认类型,仅在集群内部通过虚拟 IP 访问NodePort将 Service 暴露在每个 Node 的某个端口,外部可以通过 IP:Port 访问LoadBalancer云环境下自动创建外部负载均衡器(阿里云、AWS 等)ExternalName把请求重定向到外部 DNS 域名3.3.2 Service 如何做服务发现?Kubernetes 内置「DNS 服务」,会为每个 Service 分配一个 DNS 名称: 例如
http://nginx-service.default.svc.cluster.local
容器中的其他 Pod 只需用这个 DNS 名称就能访问 nginx 服务,完全不需要关心 Pod IP。
3.3.3 创建并访问 Service 示例# 创建 Deployment
kubectl apply -f nginx-deployment.yaml
# 创建 Service
kubectl apply -f nginx-service.yaml
# 查看 Service IP 和端口:
kubectl get svc
# 在集群中访问 Service:
curl http://nginx-service
3.4 Ingress在 Kubernetes 中,Ingress是一种 API 对象,用于管理外部用户如何通过 HTTP 或 HTTPS 访问集群内的服务(Service) 。简而言之,Ingress 提供了一种统一的方式,将域名或路径映射到集群中的服务上,并支持负载均衡、SSL 终端和基于路径/主机的路由。
3.4.1 为什么需要 Ingress?在没有 Ingress 的情况下,集群外部访问服务只能通过:
「NodePort」:每个 Service 暴露一个端口,访问地址为NodeIP:Port,难管理。「LoadBalancer」:为每个服务申请一个云负载均衡器,成本高。「Port-forward / kubectl proxy」:临时调试用,不适合生产。而 Ingress 通过一个统一的入口,根据域名或路径来转发请求,成本低、配置灵活、可维护性强。Ingress 功能点如下:
功能说明域名路由根据主机名将请求转发到不同服务路径路由根据路径将请求转发到不同服务HTTPS 支持可以配置证书,实现 TLS 终端负载均衡多个 Pod 间自动负载均衡支持重定向与重写可以配置 URL 重定向或路径重写身份验证、限速等借助 Ingress Controller 插件可实现更高级功能3.4.2 组成结构Ingress 本身不直接处理请求,它依赖「Ingress Controller」来工作。常见 Ingress Controller:
Controller 类型说明Nginx最流行的开源选择,支持多数功能Traefik轻量级、高性能,支持微服务和自动发现HAProxy高性能、企业级选择Istio Gateway用于服务网格场景AWS/GCP/ALB云平台原生负载均衡集成下面这张图展示了 Ingress 在 Kubernetes 中进行流量转发的完整架构流程
用户访问example.com/web;
Ingress 中定义了/web路径指向my-webService;
Ingress Controller(如 nginx-ingress)读取 Ingress 规则;
Ingress Controller 接收到请求后,将其转发给my-webService;
Service 查找符合条件的 Pod(例如标签为app=web);
请求最终到达 Pod,得到业务响应。
+--------------+
| Internet |
+------+-------+
|
+-------v--------+
| Ingress | ← 配置路由规则的资源
| (定义规则) |
+-------+--------+
|
+--------v---------+
| Ingress Controller| ← 实际负责转发流量
| (如 Nginx, Traefik)|
+--------+---------+
|
+-----v------+
| Kubernetes |
| Services |
+-----+------+
|
+--v--+
| Pod |
+-----+
3.4.3 配置一个简单的 IngressIngress 如何连接 Service? 假设你有一个名为my-web的 Service,监听端口为 80:
service.yaml
apiVersion:v1
kind:Service
metadata:
name:my-web
spec:
selector:
app:web
ports:
-port:80
targetPort:8080
service.yaml对应的my-web-deployment.yaml配置如下:
apiVersion:apps/v1
kind:Deployment
metadata:
name:my-web
spec:
replicas:2
selector:
matchLabels:
app:web
template:
metadata:
labels:
app:web
spec:
containers:
-name:web
image:nginx:1.24
ports:
-containerPort:8080
这个 Service 将流量从端口 80 转发到选中 Pod 的 8080 端口。Ingress 配置如下:
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name:web-ingress
spec:
rules:
-host:example.com
http:
paths:
-path:/web
pathType:Prefix
backend:
service:
name:my-web # 指向 Service 的名字
port:
number:80 # 指向 Service 的 port 字段
?当用户访问http://example.com/web时:
请求被 Ingress Controller 捕获;根据/web路径匹配到规则;将请求转发到my-webService;Service 根据 selector 找到对应的 Pod(如app=web);将请求转发给这些 Pod 的targetPort: 8080。?3.4.4 配置 HTTPS Ingress通过如下命令创建了一个包含 TLS 证书的 Secret:这个 Secret 包含公钥证书(CRT)和私钥(KEY),名称为tls-secret,位于default命名空间中.
kubectl create secret tls tls-secret \
--cert=example.com.crt \
--key=example.com.key \
-n default
在Ingress 配置启用 HTTPS
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name:web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target:/
spec:
tls:
-hosts:
-example.com
secretName:tls-secret# 指向我们预先创建的 TLS Secret
rules:
-host:example.com
http:
paths:
-path:/
pathType:Prefix
backend:
service:
name:my-web
port:
number:80
效果验证:
本地配置 DNS:
echo"INGRESS_IP example.com"| sudo tee -a /etc/hosts
INGRESS_IP是你的 Ingress Controller 的外网 IP 地址。
浏览器访问:
https://example.com/
若配置无误,将自动跳转并看到你部署的 nginx 页面。
3.5 ConfigMap 与 Secret在 Kubernetes 中,「ConfigMap 和 Secret」是用于「配置管理」的两种核心资源类型,它们用于将配置和敏感数据(如密码、API 密钥)与容器解耦,让你的应用部署更加灵活、安全。
特性ConfigMapSecret用途存储普通配置(不敏感)存储敏感数据(如密码、Token)数据是否加密? 否(明文)? 是(Base64 编码,适合加密传输)可挂载到 Pod? 是? 是使用方式环境变量、挂载为文件、命令行参数等环境变量、挂载为文件、命令行参数等推荐用途配置文件、环境变量、命令参数等密码、证书、数据库密钥、Token 等3.5.1 ConfigMap:存储非敏感配置创建 ConfigMap 的方式方法 1:使用kubectl命令行创建
kubectl create configmap my-config --from-literal=color=blue --from-literal=lang=zh
方法 2:使用 YAML 创建
apiVersion:v1
kind:ConfigMap
metadata:
name:my-config
data:
color:blue
lang:zh
使用 ConfigMap 的方式方法 1:作为环境变量注入容器
env:
-name:COLOR
valueFrom:
configMapKeyRef:
name:my-config
key:color
方法 2:挂载为文件
volumeMounts:
-name:config-volume
mountPath:/etc/config
volumes:
-name:config-volume
configMap:
name:my-config
3.5.2 Secret:存储敏感配置Secret 的数据会以 Base64 编码存储(可以结合加密存储后端实现更高安全性)。
创建 Secret 的方式方法 1:命令行直接创建
kubectl create secret generic my-secret --from-literal=password=123456
方法 2:YAML 文件创建(注意 Base64 编码)
apiVersion:v1
kind:Secret
metadata:
name:my-secret
type:Opaque
data:
password:MTIzNDU2# Base64 编码后的 "123456"
可以用如下命令手动编码:
echo-n"123456"| base64
使用 Secret 的方式方法 1:作为环境变量注入
env:
-name:DB_PASSWORD
valueFrom:
secretKeyRef:
name:my-secret
key:password
方法 2:挂载为文件
volumeMounts:
-name:secret-volume
mountPath:/etc/secret
volumes:
-name:secret-volume
secret:
secretName:my-secret
3.6 PersistentVolumeClaimPersistentVolumeClaim(PVC) 是一种资源对象,用于申请持久化存储空间(PersistentVolume,PV) 。简单来说,它是 Pod 与底层存储之间的桥梁,用户通过 PVC 来请求磁盘,而不是直接绑定硬盘资源。
3.6.1 什么是 PersistentVolume 与 PersistentVolumeClaim?「PersistentVolume(PV)」:由管理员创建或自动创建的「存储资源」,类似“硬盘”。「PersistentVolumeClaim(PVC)」:用户申请使用 PV 的方式,类似“租用硬盘”。??? 类比理解:
「PV = 房东提供的房子」「PVC = 租客发出的租房申请」Kubernetes 匹配 PVC 与 PV,实现租房动作?为什么需要 PVC?在容器运行时,容器内的数据是「临时的(临时存储)」,容器重启或迁移后会丢失。如果需要保存数据库、文件上传等数据,就必须使用 PVC 来绑定到稳定的硬盘。
3.6.2 PVC 使用流程管理员配置 StorageClass 或 PV开发者在 Pod 中声明 PVC系统自动匹配合适的 PV 给 PVCPod 使用 PVC 提供的存储挂载路径3.6.3 PVC 使用示例Step1:定义 PVC申请一个 1Gi 的存储空间
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:my-pvc
spec:
accessModes:
-ReadWriteOnce # 只允许一个 Pod 挂载读写
resources:
requests:
storage:1Gi # 请求 1Gi 存储空间
访问模式说明:
模式说明ReadWriteOnce只能被单个 Node 上的一个 Pod 读写(最常用)ReadOnlyMany多个 Pod 可读,但不可写ReadWriteMany多个 Pod 可读写(需特定存储支持,如 NFS)Step 2:Pod 中使用 PVCapiVersion:v1
kind:Pod
metadata:
name:nginx-with-pvc
spec:
containers:
-name:nginx
image:nginx
volumeMounts:
-mountPath:"/usr/share/nginx/html"
name:web-data
volumes:
-name:web-data
persistentVolumeClaim:
claimName:my-pvc
这样,Pod 就能把/usr/share/nginx/html目录的数据存储到持久化卷中。也可以用 PVC 搭配 StorageClass,让 K8s 自动向云厂商(如 AWS、GCP)动态创建磁盘资源,无需管理员手动创建 PV。
3.7 Namespace「Namespace(命名空间)」是一种用于对集群中的资源进行「逻辑隔离和分组管理」的机制。可以把它理解为集群中的「虚拟子集群」,用于将资源划分为多个相互独立的空间。并非所有的资源都可以用命名空间进行隔离。
特性是否作用于 NamespacePod、Service? 是,属于某个命名空间Node、PV? 否,全局资源Role、Quota? 是,作用于指定命名空间ClusterRole? 否,作用于全集群顺便说一下Node和Pod的区别:
类目「Node(节点)」「Pod」「定义」集群中的一台工作机器(物理机或虚拟机)Kubernetes 中可调度的最小计算单元(通常是一个或多个容器)「层级关系」Node 是运行 Pod 的宿主机Pod 运行在 Node 上「数量」集群中通常只有少数几个 Node(如3个、5个)可以调度成千上万个 Pod「作用」提供计算资源(CPU、内存、网络)封装应用容器及其运行环境「组成部分」kubelet、kube-proxy、容器运行时(如 containerd)一个或多个容器、共享网络和存储卷通俗理解「Node 是宿舍楼」,里面住着多个「Pod(宿舍间)」一个 Node 可以运行多个 Pod,但 Pod 不能脱离 Node 独立存在。
3.7.1 Namespace 有什么用?1.「资源隔离」每个 Namespace 里的资源彼此隔离,互不干扰。比如你在dev和prod中分别部署了两个nginx,它们不会冲突,因为在各自的命名空间中是唯一的。2.「权限控制(RBAC)」可以基于 Namespace 分配不同的权限,比如:
张三只能管理dev命名空间;李四只能查看prod命名便于企业多团队协作时的权限边界管理。
3.「资源配额限制(ResourceQuota)」可以为不同 Namespace 设置资源配额限制,比如:
devNamespace 最多使用 4 个 CPU、8G 内存;prodNamespace 可以使用更多资源;这样可以避免某个项目“吃光”整个集群资源。
4.「便于环境分离」常见实践:按环境划分 Namespace:
dev:开发环境test:测试环境prod:生产环境在一个集群中部署多套系统而互不干扰。此外Kubernetes 默认提供了几个内置命名空间:
命名空间用途default默认命名空间,用户不指定时资源会创建在这里kube-systemKubernetes 系统组件运行的地方(如 kube-dns)kube-public所有人都可访问,主要用于公开信息kube-node-lease节点状态心跳相关3.7.2 创建命名空间并部署资源示例# 创建命名空间
kubectl create namespace dev
# 在 dev 命名空间部署 nginx
kubectl run nginx --image=nginx -n dev
# 查看 dev 命名空间下的 Pod
kubectl get pods -n dev
命名空间的逻辑隔离:
+------------------------+
| Kubernetes 集群 |
| |
| +--------+ +--------+ |
| | dev | | prod | |
| | | | | |
| | nginx | | nginx | |
| | redis | | mysql | |
| +--------+ +--------+ |
+------------------------+
3.8 RBAC「RBAC(基于角色的访问控制,Role-Based Access Control)」是一种权限管理机制,用来控制「谁可以对哪些资源执行哪些操作」。RBAC 就像公司中的权限系统:不同的岗位(角色)有不同的权限,不同的员工(用户)只能做他们被授权的事情。
3.8.1 RBAC 的核心组件RBAC 一共由 4 个关键对象组成:
对象说明「Role」定义在某个 Namespace 中能进行哪些操作(比如:可以查看 Pod)「ClusterRole」类似 Role,但作用于所有命名空间或集群级资源(如节点、存储等)「RoleBinding」将 Role 绑定到具体用户、组或 ServiceAccount(限某命名空间)「ClusterRoleBinding」将 ClusterRole 绑定到用户、组或服务账号(全局作用)常见的操作:
动作含义get获取资源list列出资源列表watch监听资源变化create创建资源update更新资源delete删除资源3.8.2 创建一个只读角色创建 Role:只能查看 Pod 和 Service
apiVersion:rbac.authorization.k8s.io/v1
kind:Role
metadata:
name:pod-reader
namespace:dev
rules:
-apiGroups:[""]
resources:["pods","services"]
verbs:["get","list","watch"]
创建 RoleBinding:把这个权限绑定给某个用户
apiVersion:rbac.authorization.k8s.io/v1
kind:RoleBinding
metadata:
name:read-pods-binding
namespace:dev
subjects:
-kind:User
name:alice
apiGroup:rbac.authorization.k8s.io
roleRef:
kind:Role
name:pod-reader
apiGroup:rbac.authorization.k8s.io
表示:用户alice在dev命名空间内,可以读取 Pod 和 Service,但不能创建、删除、修改。
常用命令:
# 查看所有 ClusterRole
kubectl get clusterroles
# 查看绑定关系
kubectl get rolebindings -n dev
# 授予某用户集群管理员权限(示例)
kubectl create clusterrolebinding admin-binding \
--clusterrole=cluster-admin \
--user=alice@example.com
3.9 CronJob「CronJob」是用来按计划周期性运行任务的资源类型,类似于 Linux 中的crontab。它适用于那些需要定时执行的任务,例如数据库备份、定期数据清理、定时邮件发送等。
配置字段说明:
名称说明CronJob按时间调度,周期性运行任务JobCronJob 每次触发都会生成一个 Job,它是一次性任务PodJob 创建的 Pod 执行任务脚本restartPolicy通常设置为OnFailure,失败时重试suspend可设为true暂停 CronJob 执行示例:每天午夜运行一次任务
apiVersion:batch/v1
kind:CronJob
metadata:
name:hello-cronjob
spec:
schedule:"0 0 * * *"# crontab 格式:每天0点
jobTemplate:
spec:
template:
spec:
containers:
-name:hello
image:busybox
args:
-/bin/sh
--c
-echo"Hello from CronJob at $(date)"
restartPolicy:OnFailure
schedule使用的是类 Unix 的 cron 表达式,格式如下:
分 时 日 月 星期
示例含义*/5 * * * *每 5 分钟执行一次0 0 * * *每天午夜 0 点执行0 9 * * 1每周一早上 9 点执行CronJob 的执行过程:
时间触发器 (schedule)
↓
+-----------+
| CronJob | ← 负责按照 schedule 触发 Job
+-----------+
↓
+-----------+
| Job | ← 一次性任务(控制器)
+-----------+
↓
+-----------+
| Pod | ← 实际执行任务的容器
+-----------+
常用命令:
# 获取集群中所有CronJob资源的列表
kubectl get cronjob
# 查看名为 hello-cronjob 的 CronJob 资源的详细信息
kubectl describe cronjob hello-cronjob
# 列出所有的 Job 资源
kubectl getjobs
# 查看与指定 Job 相关的 Pod 的日志
kubectl logs job-created-pod-name
四、自动伸缩(HPA)「HPA(Horizontal Pod Autoscaler,水平 Pod 自动扩缩容)」是一个控制器,它会根据CPU、内存或自定义指标,自动调整 Pod 的副本数量,确保应用在不同负载情况下都能平稳运行。
4.1 HPA 的工作原理HPA 监测目标 Pod 资源使用情况(默认监测 CPU)。如果 CPU 或其他指标高于设定阈值,就自动「增加」Pod 副本数。如果 CPU 或其他指标低于设定阈值,就自动「减少」Pod 副本数。4.2 如何使用 HPA?4.2.1 确保 Metrics Server 已安装HPA 需要metrics-server提供 Pod 资源使用数据。可以使用以下命令检查:
kubectl get apiservices | grep metrics
如果metrics.k8s.io没有运行,需要安装:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
4.2.2 创建一个 DeploymentapiVersion:apps/v1
kind:Deployment
metadata:
name:php-apache
spec:
replicas:1
selector:
matchLabels:
app:php-apache
template:
metadata:
labels:
app:php-apache
spec:
containers:
-name:php-apache
image:k8s.gcr.io/hpa-example
ports:
-containerPort:80
resources:
requests:
cpu:200m
limits:
cpu:500m
注意:HPA 需要resources.requests.cpu进行判断,因此 Pod 必须指定cpu requests值,否则 HPA 不会生效。
4.2.3 创建 HPA 规则(基于 CPU 自动扩缩)apiVersion:autoscaling/v2
kind:HorizontalPodAutoscaler
metadata:
name:php-apache-hpa
spec:
scaleTargetRef:
apiVersion:apps/v1
kind:Deployment
name:php-apache # 关联的 Deployment
minReplicas:1 # 最少 1 个副本
maxReplicas:10 # 最多 10 个副本
metrics:
-type:Resource
resource:
name:cpu
target:
type:Utilization
averageUtilization:50# CPU 使用率超过 50% 时扩容
4.2.4 应用与查看 HPA 规则kubectl apply -f hpa.yaml
kubectl get hpa
示例输出:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache-hpa Deployment/php-apache 60%/50% 1 10 3 5m
TARGETS 60%/50%:当前 CPU 使用率 60%,HPA 目标是 50%。REPLICAS 3:HPA 自动扩展了 3 个 Pod。4.2.5 模拟高负载(测试 HPA)可以使用busybox持续压测 Pod 的 CPU:
kubectl run -i --tty busybox --image=busybox -- sh
# 在 BusyBox 终端里执行
whiletrue;dowget -q -O- http://php-apache;done
观察 HPA 变化:
kubectl get hpa -w
4.2.6 进阶-基于自定义指标扩缩容HPA 也可以基于「内存使用量」或「Prometheus 自定义指标」进行扩缩容,例如:
metrics:
-type:Resource
resource:
name:memory
target:
type:Utilization
averageUtilization:70# 当内存使用率超过 70% 时扩容
或者基于「Prometheus 监控指标」进行扩容:
metrics:
-type:External
external:
metric:
name:requests_per_second
target:
type:AverageValue
averageValue:1000# 每秒请求超过1000次扩容
4.3 怎么解决资源不足问题?HPA 扩展的 Pod 所需的硬件资源,来自集群中已有的 Node(节点)资源池。如果 Node上没有足够资源容纳新的 Pod,Pod 会「处于 Pending 状态」,直到有资源调度。举例说明:
集群中有 3 个 Node,每个 Node 有 2 核 CPU 和 4G 内存。每个 Pod 要求cpu: 500m。初始状态运行了 6 个 Pod,正好占满资源(理论上最多能运行「12 个 Pod」,但我们说「6 个 Pod 就占满资源」,是因为现实中不能这么理想化计算,系统组件也占资源,再预留一些 buffer 来应对波动、调度策略等,6~8 个 Pod 就可能接近极限了)。负载升高,HPA 触发扩容为 8 个 Pod。结果:新创建的 2 个 Pod 会「Pending(等待)」,因为没有 Node 有足够资源运行它们。
怎么解决资源不足问题?有两种方式:
4.3.1 手动添加节点(扩容集群)如果你使用的是物理机或虚拟机搭建的集群,可以手动加入更多 Node。
# 添加新节点后,kubelet 会将其注册进集群
kubectl get nodes
4.3.2 使用 Cluster Autoscaler(集群自动扩容)?Cluster Autoscaler 是 Kubernetes 官方提供的「自动添加/移除 Node 的组件」。
?当 Pod 无法调度时,Cluster Autoscaler 会自动向云服务申请添加 Node。当某些 Node 上没有运行任何 Pod 并维持一段时间,自动释放这些 Node。支持的云平台:
GKE(Google)EKS(AWS)AKS(Azure)阿里云、腾讯云等也有类似组件4.3.3 最佳方案最佳实践:HPA + Cluster Autoscaler 联用 是生产环境最常见做法:
HPA 根据 CPU/内存/自定义指标自动调整 Pod 数量。如果资源不足,Cluster Autoscaler 自动申请节点,保障 Pod 正常运行。类别HPACluster Autoscaler控制对象Pod 副本数量Node 数量(硬件资源)是否自动是是(需配置)是否立即生效快速云平台资源申请略慢解决问题应对应用层负载变化应对物理资源不足结语肚子有点饿,今天先写到这里,下篇明天再续写。
关注更多AI编程资讯请去AI Coding专区:https://juejin.cn/aicoding
点击"阅读原文"了解详情~
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线