原创 去伪存真 2025-05-23 08:31 重庆
点击关注公众号,“技术干货” 及时达!
点击关注公众号,“技术干货” 及时达!
前言
最近在采用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-O |
1.2.3 云提供商APIs
Kubernetes可以通过云提供商APIs与云服务进行集成,例如负载均衡器、存储卷和身份认证等。这使得Kubernetes能够利用云平台提供的各种服务来增强其功能。
1.3 k8s和docker的关系?
k8s和docker的用途都含有容器管理,初学者一般都搞不清楚两者之间的关系。可以理解为:「Docker 负责造车,Kubernetes 负责调度车队跑起来并保持秩序」。
名称 | 定义 |
---|---|
「Docker」 | 是一个「容器引擎」,用于打包、分发和运行容器化应用。 |
「Kubernetes」 | 是一个「容器编排平台」,用于自动化管理大量容器的部署、调度、伸缩和维护。 |
「Docker 管理单个容器,Kubernetes 管理容器的集群」;它们各司其职,共同构成了现代云原生应用的基石。
维度 | Docker | Kubernetes |
---|---|---|
类型 | 容器运行时 | 容器编排平台 |
是否依赖对方 | 不依赖 | 早期依赖 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 kubectlsudo mv kubectl /usr/local/bin/kubectl version --client
2.2 安装 Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64sudo 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: v1kind:Podmetadata:name:nginx-podspec: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# 查看所有podkubectl get pods# 查看某个podkubectl 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/v1kind:Deploymentmetadata:name:my-nginxspec:replicas:3selector: matchLabels: app:nginxtemplate: metadata: labels: app:nginx spec: containers: -name:nginx image:nginx:1.24 ports: -containerPort:80
3.2.2 Deployment 的工作逻辑
selector.matchLabels
的 Podreplicas
,则新建 Pod如果数量过多,则删除多余的 Pod
如果标签相同但镜像等配置不同,则更新 Pod
Deployment 不直接控制 Pod,而是通过创建一个 ReplicaSet,再由 ReplicaSet 具体去创建 Pod,维护副本数量,做滚动更新。
3.2.3 Deployment操作命令
# 创建 Deploymentkubectl apply -f nginx-deploy.yaml# 查看状态kubectl get deploymentskubectl describe deployment nginx-deploy# 查看管理的 Podkubectl 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: v1kind:Servicemetadata:name:nginx-servicespec: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 名称: 例如
容器中的其他 Pod 只需用这个 DNS 名称就能访问 nginx 服务,完全不需要关心 Pod IP。
3.3.3 创建并访问 Service 示例
# 创建 Deploymentkubectl apply -f nginx-deployment.yaml# 创建 Servicekubectl 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 的情况下,集群外部访问服务只能通过:
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
;/web
路径指向my-web
Service;Ingress Controller(如 nginx-ingress)读取 Ingress 规则;
my-web
Service;app=web
);请求最终到达 Pod,得到业务响应。
+--------------+ | Internet | +------+-------+ | +-------v--------+ | Ingress | ← 配置路由规则的资源 | (定义规则) | +-------+--------+ | +--------v---------+ | Ingress Controller| ← 实际负责转发流量 | (如 Nginx, Traefik)| +--------+---------+ | +-----v------+ | Kubernetes | | Services | +-----+------+ | +--v--+ | Pod | +-----+
3.4.3 配置一个简单的 Ingress
my-web
的 Service,监听端口为 80:service.yaml
apiVersion: v1kind:Servicemetadata:name:my-webspec:selector: app:webports: -port:80 targetPort:8080
service.yaml对应的my-web-deployment.yaml配置如下:
apiVersion: apps/v1kind:Deploymentmetadata:name:my-webspec:replicas:2selector: matchLabels: app:webtemplate: metadata: labels: app:web spec: containers: -name:web image:nginx:1.24 ports: -containerPort:8080
这个 Service 将流量从端口 80 转发到选中 Pod 的 8080 端口。Ingress 配置如下:
apiVersion: networking.k8s.io/v1kind:Ingressmetadata:name:web-ingressspec:rules: -host:example.com http: paths: -path:/web pathType:Prefix backend: service: name:my-web # 指向 Service 的名字 port: number:80 # 指向 Service 的 port 字段
❝❞
请求被 Ingress Controller 捕获;
根据/web
路径匹配到规则;将请求转发到my-web
Service;Service 根据 selector 找到对应的 Pod(如app=web
);将请求转发给这些 Pod 的targetPort: 8080
。
3.4.4 配置 HTTPS Ingress
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/v1kind:Ingressmetadata:name:web-ingressannotations: nginx.ingress.kubernetes.io/rewrite-target:/spec:tls: -hosts: -example.com secretName:tls-secret# 指向我们预先创建的 TLS Secretrules: -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 地址。浏览器访问:
若配置无误,将自动跳转并看到你部署的 nginx 页面。
3.5 ConfigMap 与 Secret
在 Kubernetes 中,「ConfigMap 和 Secret」 是用于「配置管理」的两种核心资源类型,它们用于将配置和敏感数据(如密码、API 密钥)与容器解耦,让你的应用部署更加灵活、安全。
特性 | ConfigMap | Secret |
---|---|---|
用途 | 存储普通配置(不敏感) | 存储敏感数据(如密码、Token) |
数据是否加密 | ❌ 否(明文) | ✅ 是(Base64 编码,适合加密传输) |
可挂载到 Pod | ✅ 是 | ✅ 是 |
使用方式 | 环境变量、挂载为文件、命令行参数等 | 环境变量、挂载为文件、命令行参数等 |
推荐用途 | 配置文件、环境变量、命令参数等 | 密码、证书、数据库密钥、Token 等 |
3.5.1 ConfigMap:存储非敏感配置
创建 ConfigMap 的方式
kubectl
命令行创建kubectl create configmap my-config --from-literal=color=blue --from-literal=lang=zh
方法 2:使用 YAML 创建
apiVersion: v1kind: ConfigMapmetadata: name: my-configdata: color: blue lang: zh
使用 ConfigMap 的方式
方法 1:作为环境变量注入容器
env: - name: COLOR valueFrom: configMapKeyRef: name: my-config key: color
方法 2:挂载为文件
volumeMounts: - name: config-volume mountPath: /etc/configvolumes: - 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: v1kind: Secretmetadata: name: my-secrettype: Opaquedata: 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/secretvolumes: - name: secret-volume secret: secretName: my-secret
3.6 PersistentVolumeClaim
PersistentVolumeClaim(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 给 PVC
Pod 使用 PVC 提供的存储挂载路径
3.6.3 PVC 使用示例
Step1:定义 PVC
申请一个 1Gi 的存储空间
apiVersion: v1kind:PersistentVolumeClaimmetadata:name:my-pvcspec:accessModes: -ReadWriteOnce # 只允许一个 Pod 挂载读写resources: requests: storage:1Gi # 请求 1Gi 存储空间
访问模式说明:
模式 | 说明 |
---|---|
ReadWriteOnce | 只能被单个 Node 上的一个 Pod 读写(最常用) |
ReadOnlyMany | 多个 Pod 可读,但不可写 |
ReadWriteMany | 多个 Pod 可读写(需特定存储支持,如 NFS) |
Step 2:Pod 中使用 PVC
apiVersion: v1kind:Podmetadata:name:nginx-with-pvcspec:containers: -name:nginx image:nginx volumeMounts: -mountPath:"/usr/share/nginx/html" name:web-datavolumes: -name:web-data persistentVolumeClaim: claimName:my-pvc
/usr/share/nginx/html
目录的数据存储到持久化卷中。也可以用 PVC 搭配 StorageClass,让 K8s 自动向云厂商(如 AWS、GCP)动态创建磁盘资源,无需管理员手动创建 PV。3.7 Namespace
「Namespace(命名空间)」 是一种用于对集群中的资源进行「逻辑隔离和分组管理」的机制。可以把它理解为集群中的「虚拟子集群」,用于将资源划分为多个相互独立的空间。并非所有的资源都可以用命名空间进行隔离。
特性 | 是否作用于 Namespace |
---|---|
Pod、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 设置资源配额限制,比如:
dev
Namespace 最多使用 4 个 CPU、8G 内存;prod
Namespace 可以使用更多资源;这样可以避免某个项目“吃光”整个集群资源。
4. 「便于环境分离」
常见实践:按环境划分 Namespace:
dev
:开发环境test
:测试环境prod
:生产环境在一个集群中部署多套系统而互不干扰。此外Kubernetes 默认提供了几个内置命名空间:
命名空间 | 用途 |
---|---|
default | 默认命名空间,用户不指定时资源会创建在这里 |
kube-system | Kubernetes 系统组件运行的地方(如 kube-dns) |
kube-public | 所有人都可访问,主要用于公开信息 |
kube-node-lease | 节点状态心跳相关 |
3.7.2 创建命名空间并部署资源示例
# 创建命名空间kubectl create namespace dev# 在 dev 命名空间部署 nginxkubectl run nginx --image=nginx -n dev# 查看 dev 命名空间下的 Podkubectl 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/v1kind:Rolemetadata:name:pod-readernamespace:devrules:-apiGroups:[""] resources:["pods","services"] verbs:["get","list","watch"]
创建 RoleBinding:把这个权限绑定给某个用户
apiVersion: rbac.authorization.k8s.io/v1kind:RoleBindingmetadata:name:read-pods-bindingnamespace:devsubjects:-kind:User name:alice apiGroup:rbac.authorization.k8s.ioroleRef:kind:Rolename:pod-readerapiGroup:rbac.authorization.k8s.io
alice
在dev
命名空间内,可以读取 Pod 和 Service,但不能创建、删除、修改。常用命令:
# 查看所有 ClusterRolekubectl 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 | 按时间调度,周期性运行任务 |
Job | CronJob 每次触发都会生成一个 Job,它是一次性任务 |
Pod | Job 创建的 Pod 执行任务脚本 |
restartPolicy | 通常设置为 OnFailure ,失败时重试 |
suspend | 可设为 true 暂停 CronJob 执行 |
示例:每天午夜运行一次任务
apiVersion: batch/v1kind:CronJobmetadata:name:hello-cronjobspec: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 get jobs# 查看与指定 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 已安装
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 创建一个 Deployment
apiVersion: apps/v1kind:Deploymentmetadata:name:php-apachespec:replicas:1selector: matchLabels: app:php-apachetemplate: 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
resources.requests.cpu
进行判断,因此 Pod 必须指定cpu requests
值,否则 HPA 不会生效。4.2.3 创建 HPA 规则(基于 CPU 自动扩缩)
apiVersion: autoscaling/v2kind:HorizontalPodAutoscalermetadata:name:php-apache-hpaspec:scaleTargetRef: apiVersion:apps/v1 kind:Deployment name:php-apache # 关联的 DeploymentminReplicas: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.yamlkubectl get hpa
示例输出:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGEphp-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 终端里执行while true; do wget -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 内存。
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 正常运行。
类别 | HPA | Cluster Autoscaler |
---|---|---|
控制对象 | Pod 副本数量 | Node 数量(硬件资源) |
是否自动 | 是 | 是(需配置) |
是否立即生效 | 快速 | 云平台资源申请略慢 |
解决问题 | 应对应用层负载变化 | 应对物理资源不足 |
结语
肚子有点饿,今天先写到这里,下篇明天再续写。
关注更多AI编程资讯请去AI Coding专区:https://juejin.cn/aicoding
点击"阅读原文"了解详情~