Kubernetes 从入门到实践

目录

  • [1. Kubernetes 基础](#1. Kubernetes 基础 "#1-kubernetes-%E5%9F%BA%E7%A1%80")
    • [1.1 Kubernetes 架构](#1.1 Kubernetes 架构 "#11-kubernetes-%E6%9E%B6%E6%9E%84")
    • [1.2 集群搭建](#1.2 集群搭建 "#12-%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA")
    • [1.3 kubectl 命令](#1.3 kubectl 命令 "#13-kubectl-%E5%91%BD%E4%BB%A4")
  • [2. 核心对象](#2. 核心对象 "#2-%E6%A0%B8%E5%BF%83%E5%AF%B9%E8%B1%A1")
    • [2.1 Pod](#2.1 Pod "#21-pod")
    • [2.2 Deployment](#2.2 Deployment "#22-deployment")
    • [2.3 Service](#2.3 Service "#23-service")
    • [2.4 Namespace](#2.4 Namespace "#24-namespace")
    • [2.5 Label 和 Selector](#2.5 Label 和 Selector "#25-label-%E5%92%8C-selector")
  • [3. 服务发现和负载均衡](#3. 服务发现和负载均衡 "#3-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E5%92%8C%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1")
    • [3.1 Ingress](#3.1 Ingress "#31-ingress")
    • [3.2 网络](#3.2 网络 "#32-%E7%BD%91%E7%BB%9C")
  • [4. 存储和配置](#4. 存储和配置 "#4-%E5%AD%98%E5%82%A8%E5%92%8C%E9%85%8D%E7%BD%AE")
    • [4.1 ConfigMap 和 Secret](#4.1 ConfigMap 和 Secret "#41-configmap-%E5%92%8C-secret")
    • [4.2 存储](#4.2 存储 "#42-%E5%AD%98%E5%82%A8")

1. Kubernetes 基础

1.1 Kubernetes 架构

Kubernetes(K8s)采用 Master-Worker 架构,将集群分为控制平面和数据平面。

Master 节点(控制平面)

Master 节点也是一台服务器(物理机或虚拟机),但它不运行业务容器,而是专门负责集群的管理和调度决策。可以理解为"指挥中心"------它决定哪个 Pod 跑在哪台 Worker 上、监控集群健康状态、处理所有 API 请求。生产环境通常部署 3 个 Master 实现高可用。

核心组件:

组件 职责
kube-apiserver 集群的统一入口,所有操作都通过 REST API 与它交互
kube-scheduler 监听未调度的 Pod,根据资源需求、亲和性等策略将 Pod 分配到合适的 Worker 节点
kube-controller-manager 运行各种控制器(Deployment、ReplicaSet、Node 控制器等),确保集群实际状态与期望状态一致
etcd 分布式键值存储,保存集群所有配置数据和状态信息,是集群的"数据库"

请求链路 :kubectl → kube-apiserver → 写入 etcd → kube-scheduler 调度 → kubelet 执行

Worker 节点(数据平面)

Worker 节点可以理解为一台服务器(物理机或虚拟机)。每个 Worker 节点就是集群中的一台机器,上面运行着实际的应用容器。一个集群通常由多个 Worker 节点组成,K8s 负责将 Pod 调度到这些"服务器"上运行。

一个 Worker 上可以运行多个 Pod。 Pod 是 K8s 最小的调度单位,每个 Pod 里包含一个或多个容器(通常是一个)。可以简单理解为:

  • Pod ≈ Docker Container 的包装层:大多数情况下 1 个 Pod = 1 个容器,但 Pod 提供了共享网络和存储的能力,允许多个紧密耦合的容器在同一个 Pod 内协作(如 sidecar 模式)。
  • Pod 有自己的 IP 地址,Pod 内的容器共享该 IP 和端口空间。

核心组件:

组件 职责
kubelet 每个 Worker 节点上的代理,负责管理 Pod 生命周期,向 apiserver 汇报节点状态
kube-proxy 每个节点上的网络代理。当外部请求访问 Service 时,kube-proxy 负责将流量合理转发到后端的某个 Pod 上(负载均衡)。它通过维护 iptables/ipvs 规则实现这一点
Container Runtime 容器运行时(如 containerd、CRI-O),负责拉取镜像、启动/停止容器

类比:Worker 节点 = 一台服务器,Pod = 服务器上运行的一个进程/应用,kube-proxy = 这台服务器上的"负载均衡器/路由器"

架构图

graph TB subgraph Master["Master Node(控制平面)"] API[kube-apiserver] SCH[kube-scheduler] CM[kube-controller-manager] ETCD[(etcd)] API --- SCH API --- CM API --- ETCD end subgraph Worker1["Worker Node 1"] K1[kubelet] KP1[kube-proxy] CR1[Container Runtime] P1A[Pod A] P1B[Pod B] K1 --- CR1 CR1 --- P1A CR1 --- P1B end subgraph Worker2["Worker Node 2"] K2[kubelet] KP2[kube-proxy] CR2[Container Runtime] P2A[Pod C] P2B[Pod D] K2 --- CR2 CR2 --- P2A CR2 --- P2B end subgraph Worker3["Worker Node N"] K3[kubelet] KP3[kube-proxy] CR3[Container Runtime] P3A[Pod E] P3B[Pod F] K3 --- CR3 CR3 --- P3A CR3 --- P3B end API -->|调度指令| K1 API -->|调度指令| K2 API -->|调度指令| K3 KP1 -.->|网络规则| P1A KP1 -.->|网络规则| P1B KP2 -.->|网络规则| P2A KP2 -.->|网络规则| P2B KP3 -.->|网络规则| P3A KP3 -.->|网络规则| P3B

1.2 集群搭建

常见搭建方式对比

方式 适用场景 特点
Kind CI/CD、本地测试 用 Docker 容器模拟 K8s 节点,启动快
kubeadm 生产/准生产环境 官方工具,支持多节点集群搭建
云服务 生产环境 EKS(AWS)、AKS(Azure)、GKE(Google)、ACK(阿里云),免运维

在 WSL 环境搭建(Kind)

--name vs control-plane 的区别:

  • --name my-cluster → 集群的名字,给整个集群起个名,方便管理多个集群时区分
  • control-plane → 节点的角色,表示这个节点充当 Master(管理节点)

集群名是标识,节点角色决定职责,两者不是一个层级的概念。

bash 复制代码
# 安装 Kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
sudo install kind /usr/local/bin/kind
rm kind

# 创建集群(--name 是集群名称,默认只创建 1 个 control-plane 节点)
kind create cluster --name my-cluster

# 查看集群名列表
kind get clusters
# 输出:my-cluster

# 查看节点及角色
kubectl get nodes
# NAME                       STATUS   ROLES           AGE
# my-cluster-control-plane   Ready    control-plane   5m   ← Master 节点
# (默认不带配置文件只有 1 个 Master,无 Worker)

# 创建多节点集群(使用配置文件)
# cluster = 整个集群(Master + Worker 的集合)
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane    # Master 节点(管理调度)
- role: worker           # Worker 节点 1(跑业务 Pod)
- role: worker           # Worker 节点 2(跑业务 Pod)
EOF

# 查看多节点集群的节点
kubectl get nodes
# NAME                       STATUS   ROLES           AGE
# my-cluster-control-plane   Ready    control-plane   5m   ← Master
# my-cluster-worker          Ready    <none>          5m   ← Worker 1
# my-cluster-worker2         Ready    <none>          5m   ← Worker 2

# 删除集群
kind delete cluster --name my-cluster

Kind 在 WSL2 中常见问题

创建集群时报错 could not find a log line that matches "Reached target .*Multi-User System.*|detected cgroup v1",通常是 cgroup 配置不兼容导致。

解决方法 :在 Windows 下创建/编辑 C:\Users\<你的用户名>\.wslconfig:

ini 复制代码
[wsl2]
memory=4GB
processors=2
kernelCommandLine=systemd.unified_cgroup_hierarchy=1

然后在 Windows PowerShell 中重启 WSL:

powershell 复制代码
wsl --shutdown

重新进入 WSL 后再创建集群即可。


1.3 kubectl 命令

安装和配置

kubeconfig 文件默认位于 ~/.kube/config,包含集群地址、认证信息和上下文。

命令 说明
kubectl config view 查看 kubectl 配置
kubectl config current-context 查看当前上下文(当前连接的集群)
kubectl config use-context <context-name> 切换上下文
kubectl config get-contexts 查看所有上下文
kubectl config set-context --current --namespace=<ns> 设置默认命名空间

常用命令

资源查看
命令 说明
kubectl get namespaces 查看所有命名空间
kubectl get nodes 查看节点
kubectl get nodes -o wide 查看节点详细信息(IP、OS 等)
kubectl get pods 查看当前命名空间的 Pod
kubectl get pods -n <namespace> 查看指定命名空间的 Pod
kubectl get pods -A 查看所有命名空间的 Pod
kubectl get pods -o wide 显示 Pod 详细信息(节点、IP)
kubectl get pods -w 实时监听 Pod 变化
kubectl get svc 查看 Service
kubectl get deploy 查看 Deployment
kubectl get configmap 查看 ConfigMap
kubectl get ingress 查看 Ingress
kubectl get all -n <namespace> 查看指定命名空间所有资源
kubectl describe pod <pod-name> 查看 Pod 详情
kubectl describe node <node-name> 查看 Node 详情
kubectl describe svc <service-name> 查看 Service 详情
资源创建与管理
命令 说明
kubectl apply -f deployment.yaml 通过 YAML 创建/更新资源
kubectl apply -f ./manifests/ 应用目录下所有 YAML
kubectl delete -f deployment.yaml 删除 YAML 中定义的资源
kubectl delete pod <pod-name> 删除指定 Pod
kubectl delete deploy <deploy-name> 删除指定 Deployment
kubectl create deployment nginx --image=nginx:latest 快速创建 Deployment(不推荐生产使用)
kubectl expose deployment nginx --port=80 --type=NodePort 暴露 Deployment 为 Service
扩缩容
命令 说明
kubectl scale deployment <name> --replicas=3 手动扩缩容
kubectl get hpa 查看 HPA(自动扩缩容)

查看日志

命令 说明
kubectl logs <pod-name> 查看 Pod 日志
kubectl logs -f <pod-name> 实时跟踪日志(类似 tail -f)
kubectl logs --tail=100 <pod-name> 查看最近 100 行
kubectl logs --since=1h <pod-name> 查看最近 1 小时的日志
kubectl logs <pod-name> -c <container-name> 多容器 Pod 指定容器查看日志
kubectl logs <pod-name> --previous 查看上一个已终止容器的日志(排查 CrashLoopBackOff)

进入容器

命令 说明
kubectl exec -it <pod-name> -- /bin/bash 进入容器的 bash
kubectl exec -it <pod-name> -- /bin/sh 进入容器的 sh(无 bash 时使用)
kubectl exec -it <pod-name> -c <container-name> -- /bin/bash 多容器 Pod 指定容器进入
kubectl exec <pod-name> -- cat /etc/nginx/nginx.conf 执行单条命令(不进入交互模式)
kubectl exec <pod-name> -- env 查看环境变量
kubectl exec <pod-name> -- ls /app 查看目录
kubectl cp <pod-name>:/path/file ./local-file 从容器复制文件到本地
kubectl cp ./local-file <pod-name>:/path/file 从本地复制文件到容器

常用排障命令速查

Pod 异常排查流程:

步骤 命令 说明
1 kubectl get pods 查看 Pod 状态
2 kubectl describe pod <pod-name> 查看事件和详情
3 kubectl logs <pod-name> 查看日志
4 kubectl logs <pod-name> --previous 查看上次崩溃日志
5 kubectl exec -it <pod-name> -- /bin/sh 进入容器排查

其他排障命令:

命令 说明
kubectl top nodes 查看节点资源使用(需 metrics-server)
kubectl top pods 查看 Pod 资源使用(需 metrics-server)
kubectl port-forward pod/<pod-name> 8080:80 端口转发 Pod(本地调试)
kubectl port-forward svc/<svc-name> 8080:80 端口转发 Service(本地调试)

2. 核心对象

2.1 Pod

2.1.1 Pod 概念和作用

Pod 是 Kubernetes 中最小的可部署单元。一个 Pod 封装了一个或多个容器(通常是一个),它们共享:

  • 网络 :同一个 Pod 内的容器共享 IP 地址和端口空间,可通过 localhost 互相通信
  • 存储:可以挂载相同的 Volume,实现数据共享
  • 生命周期:Pod 内的容器一起启动、一起销毁

为什么不直接用容器? Pod 提供了容器之上的抽象层,支持多容器协作(sidecar 模式)、共享网络/存储、统一调度等能力。

2.1.2 Pod 创建和管理

通过 YAML 创建 Pod
yaml 复制代码
# nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod           # Pod 名称
  labels:
    app: nginx               # 标签,用于 Service 选择
spec:
  containers:
  - name: nginx              # 容器名称
    image: nginx:1.25        # 镜像
    ports:
    - containerPort: 80      # 容器暴露的端口
操作 命令
创建 Pod kubectl apply -f nginx-pod.yaml
查看 Pod kubectl get pods
查看详情 kubectl describe pod nginx-pod
删除 Pod kubectl delete pod nginx-pod
删除(通过文件) kubectl delete -f nginx-pod.yaml

⚠️ 生产环境中不要直接创建 Pod,应使用 Deployment 来管理,这样才有副本管理、滚动更新等能力。

2.1.3 Pod 生命周期

Pod 从创建到销毁经历以下阶段:

阶段 说明
Pending Pod 已被创建,但容器还未启动(可能在拉取镜像或等待调度)
Running Pod 已绑定到节点,所有容器已启动
Succeeded 所有容器正常执行完毕并退出(常见于 Job)
Failed 至少一个容器以非零状态退出
Unknown 无法获取 Pod 状态(通常是与节点通信失败)

常见异常状态:

状态 原因 排查方式
CrashLoopBackOff 容器反复崩溃重启 kubectl logs <pod> --previous
ImagePullBackOff 镜像拉取失败 检查镜像名、tag、仓库权限
Pending 无可用节点或资源不足 kubectl describe pod <pod> 查看 Events
OOMKilled 内存超出限制 调整 resources.limits.memory

2.1.4 多容器 Pod

一个 Pod 可以包含多个容器,常见模式:

模式 说明 示例
Sidecar 辅助容器增强主容器功能 日志收集器、代理
Ambassador 代理容器处理外部通信 数据库连接代理
Adapter 转换容器输出格式 日志格式转换
yaml 复制代码
# 多容器 Pod 示例(Sidecar 模式)
apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
  - name: app                    # 主容器:业务应用
    image: my-app:1.0
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
  - name: log-collector          # Sidecar:日志收集
    image: fluentd:latest
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
  volumes:
  - name: shared-logs            # 共享 Volume(见下方说明)
    emptyDir: {}

Volume 说明:

  • shared-logs → Volume 的名称(自己定义的,用来在容器中引用)
  • emptyDir → Volume 的类型(决定数据存在哪里、生命周期多长)

emptyDir 类型会在 Worker 节点的磁盘上 创建一个临时目录,不是在 Pod 内部。

特性 说明
存储位置 Worker 节点的文件系统上(如 /var/lib/kubelet/pods/<pod-id>/volumes/)
生命周期 与 Pod 相同,Pod 删除时目录也会被清除
容器重启 Pod 内容器重启时数据不会丢失(因为 Volume 在节点上,不在容器内)
用途 同一 Pod 内多个容器之间共享数据(如上例中主容器写日志,Sidecar 读日志)

其他 Volume 类型对比:

类型 存储位置 生命周期
emptyDir Worker 节点磁盘 随 Pod 销毁
hostPath Worker 节点指定路径 独立于 Pod,节点存在就在。⚠️ Pod 调度到其他节点时无法访问原数据
persistentVolumeClaim 外部存储(云盘、NFS 等) 独立于 Pod 和节点

2.1.5 Init 容器

Init 容器在主容器启动之前运行,用于初始化工作。特点:

  • 按顺序逐个执行,前一个成功后才启动下一个
  • 全部成功后,主容器才会启动
  • 失败则 Pod 重启(遵循 restartPolicy)

常见用途:等待依赖服务就绪、初始化配置文件、数据库迁移

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
  - name: wait-for-db           # 等待数据库就绪
    image: busybox:1.36
    command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for db; sleep 2; done']
  - name: init-config           # 初始化配置
    image: busybox:1.36
    command: ['sh', '-c', 'cp /config-template/* /app/config/']
    volumeMounts:
    - name: config
      mountPath: /app/config
  containers:
  - name: app                   # 主容器(Init 全部成功后才启动)
    image: my-app:1.0
    volumeMounts:
    - name: config
      mountPath: /app/config
  volumes:
  - name: config
    emptyDir: {}

2.2 Deployment

2.2.1 概念和作用

Deployment 是管理 Pod 的高层控制器,提供:

  • 副本管理:确保指定数量的 Pod 始终运行
  • 滚动更新:无停机更新应用版本
  • 回滚:一键回退到之前的版本
  • 自愈:Pod 崩溃后自动重建

层级关系:Deployment → ReplicaSet → Pod。Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod。

运行位置 :Deployment 本身是一份"期望状态"声明,存储在 Master 的 etcd 中,由 kube-controller-manager 管理。真正跑在 Worker 上的是 Deployment 创建出来的 Pod。

例如:Deployment 告诉 Master:"我要 3 个 nginx Pod",Master 的 Scheduler 负责把这 3 个 Pod 分配到不同的 Worker 上运行。

2.2.2 创建 Deployment

yaml 复制代码
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3                    # 副本数
  selector:
    matchLabels:
      app: nginx                 # 选择器,匹配 Pod 标签
  template:                      # Pod 模板
    metadata:
      labels:
        app: nginx               # Pod 标签(必须与 selector 匹配)
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:              # 最低资源需求
            cpu: 100m
            memory: 128Mi
          limits:                # 资源上限
            cpu: 500m
            memory: 256Mi
操作 命令
创建 kubectl apply -f nginx-deployment.yaml
查看 kubectl get deploy
查看详情 kubectl describe deploy nginx-deployment
查看管理的 Pod kubectl get pods -l app=nginx(app=nginx 对应 YAML 中 labels 定义的标签)
删除 kubectl delete deploy nginx-deployment

2.2.3 滚动更新和回滚

滚动更新
bash 复制代码
# 方式1:修改 YAML 中的 image 后重新 apply
kubectl apply -f nginx-deployment.yaml

# 方式2:直接命令行更新镜像
# 格式:kubectl set image deployment/<deployment名称> <容器名称>=<新镜像>
# nginx-deployment → metadata.name,nginx → containers[].name(不是 label)
kubectl set image deployment/nginx-deployment nginx=nginx:1.26

# 查看更新进度
kubectl rollout status deployment/nginx-deployment

更新策略(在 YAML 中配置):

yaml 复制代码
spec:
  strategy:
    type: RollingUpdate          # 滚动更新(默认)
    rollingUpdate:
      maxSurge: 1                # 更新时最多多出 1 个 Pod
      maxUnavailable: 0          # 更新时不允许不可用的 Pod
回滚
操作 命令
查看更新历史 kubectl rollout history deployment/nginx-deployment
回滚到上一个版本 kubectl rollout undo deployment/nginx-deployment
回滚到指定版本 kubectl rollout undo deployment/nginx-deployment --to-revision=2
暂停更新 kubectl rollout pause deployment/nginx-deployment
恢复更新 kubectl rollout resume deployment/nginx-deployment

2.2.4 副本数管理

副本数(replicas)即 Pod 的数量 。replicas: 3 表示 K8s 始终维持 3 个相同的 Pod 运行。扩缩容就是动态调整这个数字。

操作 命令
手动扩缩容 kubectl scale deployment nginx-deployment --replicas=5(将 Pod 数量调整为 5)
查看副本状态 kubectl get deploy nginx-deployment

输出示例:

vbnet 复制代码
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           10m
                   ^^^
                   就绪/期望 副本数

2.3 Service

2.3.1 概念和作用

Service 为一组 Pod 提供稳定的网络访问入口。解决的问题:

  • Pod 的 IP 是动态分配的,Pod 重建后 IP 会变
  • 需要在多个 Pod 之间做负载均衡
  • 需要一个固定的域名/IP 供其他服务访问

类比 :Pod 是后端服务器,Service 就是前面的负载均衡器,提供一个稳定的地址。

Deployment 与 Service 的关系

Deployment 和 Service 是独立对象 ,不是一对一绑定。它们通过 Label 关联:

关系 说明
1 Deployment → 0 Service 内部服务不需要被其他服务访问时
1 Deployment → 1 Service 最常见,一个应用一个访问入口
1 Deployment → 多个 Service 同一应用暴露不同端口/协议(如 HTTP + gRPC)
多个 Deployment → 1 Service 少见,但 Service 只要 label 匹配就能指向多组 Pod

Deployment 创建 Pod 跑在已有的 Worker 上,不会新建 Worker。Pod 由 kube-scheduler 自动调度到合适的节点。

2.3.2 Service 类型

类型 说明 访问范围
ClusterIP 默认类型,分配一个集群内部 IP 仅集群内部访问
NodePort 在每个节点上开放一个固定端口(30000-32767) 集群外部可通过 节点IP:NodePort 访问
LoadBalancer 在 NodePort 基础上,创建云厂商的外部负载均衡器 外部访问(需云环境支持)
ClusterIP(默认)
yaml 复制代码
# cluster-ip-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: ClusterIP               # 默认,可省略
  selector:
    app: nginx                   # 选择标签为 app=nginx 的 Pod
  ports:
  - port: 80                     # Service 端口
    targetPort: 80               # Pod 容器端口
NodePort
yaml 复制代码
# node-port-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - port: 80                     # Service 端口(集群内访问)
    targetPort: 80               # Pod 容器端口
    nodePort: 30080              # 节点端口(外部访问),不指定则自动分配
LoadBalancer
yaml 复制代码
# load-balancer-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-lb
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80

2.3.3 集群内访问 Service(服务发现)

完整示例:Deployment + Service
yaml 复制代码
# nginx-app.yaml(一个文件中包含 Deployment 和 Service,用 --- 分隔)

# ===== Deployment:创建 3 个 nginx Pod =====
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment         # Deployment 名称
  namespace: dev                 # 自定义命名空间(需提前创建:kubectl create namespace dev)
spec:
  replicas: 3                    # 创建 3 个 Pod
  selector:
    matchLabels:
      app: nginx                 # ─┐ 选择器,匹配下方 Pod 的 labels
  template:                      #  │
    metadata:                    #  │
      labels:                    #  │
        app: nginx               # ─┘ Pod 标签(与 selector 和 Service 关联的纽带)
    spec:
      containers:
      - name: nginx              # 容器名称
        image: nginx:1.25
        ports:
        - containerPort: 80      # 容器监听 80 端口
---
# ===== Service:为上面的 Pod 提供统一访问入口 =====
apiVersion: v1
kind: Service
metadata:
  name: nginx-service            # Service 名称(集群内通过此名称访问)
  namespace: dev                 # 与 Deployment 同一命名空间
spec:
  type: ClusterIP                # 仅集群内部可访问
  selector:
    app: nginx                   # ← 通过此标签关联上面 Deployment 创建的 Pod
  ports:
  - port: 80                     # Service 暴露的端口
    targetPort: 80               # 转发到 Pod 的 80 端口
操作 命令
创建命名空间 kubectl create namespace dev
部署 kubectl apply -f nginx-app.yaml
查看 Deployment kubectl get deploy -n dev
查看关联的 Pod kubectl get pods -l app=nginx -n dev
查看 Service kubectl get svc nginx-service -n dev
查看 Service 背后的 Pod IP kubectl get endpoints nginx-service -n dev
集群内访问测试(同命名空间) kubectl run test -n dev --rm -it --image=busybox -- wget -qO- http://nginx-service
集群内访问测试(跨命名空间) kubectl run test --rm -it --image=busybox -- wget -qO- http://nginx-service.dev.svc.cluster.local

关联关系 :Deployment 的 selector.matchLabels 和 Service 的 selector 都通过 app: nginx 这个标签找到同一组 Pod。

集群内的 Pod 可以通过以下方式访问 Service:

方式 格式 示例
同命名空间 <service-name> curl http://nginx-service
跨命名空间 <service-name>.<namespace>.svc.cluster.local curl http://nginx-service.dev.svc.cluster.local

以上方 nginx-app.yaml 为例,各字段对应关系:

完整域名:nginx-service.dev.svc.cluster.local

  • nginx-service → Service 的 metadata.name
  • dev → Service 的 metadata.namespace
  • svc.cluster.local → K8s 固定后缀
  • svc.cluster.local → K8s 固定后缀

K8s 自带 DNS 服务(CoreDNS),自动为每个 Service 创建 DNS 记录。

2.3.4 Endpoints

Endpoints 是 Service 背后实际对应的 Pod IP 列表。Service 通过 selector 匹配 Pod,自动维护 Endpoints。

沿用上方 nginx-app.yaml 部署后,查看 Endpoints:

bash 复制代码
# 查看 nginx-service 的 Endpoints(nginx-service 即 YAML 中 metadata.name)
kubectl get endpoints nginx-service

# 输出示例:
# NAME            ENDPOINTS                                   AGE
# nginx-service   10.244.1.5:80,10.244.2.3:80,10.244.3.7:80  5m
#                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#                 三个 Pod 的实际 IP:端口

当 Pod 被创建/销毁时,Endpoints 会自动更新,流量只会转发到健康的 Pod。


2.4 Namespace

2.4.1 概念和作用

Namespace(命名空间)用于将集群资源划分为多个逻辑隔离的空间。

常见用途:

  • 按环境隔离:dev、staging、production
  • 按团队隔离:team-a、team-b
  • 按项目隔离:project-x、project-y

K8s 默认的 Namespace:

Namespace 说明
default 未指定命名空间时的默认空间
kube-system K8s 系统组件(apiserver、scheduler 等)
kube-public 所有用户可读的公共资源
kube-node-lease 节点心跳相关

沿用上方 nginx-app.yaml(已指定 namespace: dev)进行验证:

操作 命令
查看所有命名空间 kubectl get namespaces
创建命名空间 kubectl create namespace dev
部署资源到 dev kubectl apply -f nginx-app.yaml(YAML 中已指定 namespace: dev)
查看 dev 命名空间的 Pod kubectl get pods -n dev
查看 dev 命名空间所有资源 kubectl get all -n dev
设置默认命名空间(免 -n) kubectl config set-context --current --namespace=dev
删除命名空间(会删除其下所有资源) kubectl delete namespace dev

2.4.2 资源隔离

Namespace 提供的是逻辑隔离,不同命名空间的资源互不可见(同类型下名称可重复)。

如上方 nginx-app.yaml 所示,在 YAML 中通过 metadata.namespace: dev 指定资源归属的命名空间。

⚠️ 注意:

  • Namespace 是逻辑隔离,不是网络隔离。默认情况下,不同 Namespace 的 Pod 之间可以互相通信
  • 需要网络隔离时,需配合 NetworkPolicy 使用
  • Node 和 PersistentVolume 是集群级资源,不属于任何 Namespace

2.5 Label 和 Selector

Label(标签)

Label 是附加到 K8s 对象上的键值对,用于标识和分类资源。

yaml 复制代码
metadata:
  labels:
    app: nginx               # 应用名
    env: production          # 环境
    tier: frontend           # 层级
    version: v1.0            # 版本
操作 命令
给 Pod 添加标签 kubectl label pod nginx-pod env=dev
修改已有标签 kubectl label pod nginx-pod env=staging --overwrite
删除标签 kubectl label pod nginx-pod env-
查看标签 kubectl get pods --show-labels

Selector(选择器)

Selector 用于根据 Label 筛选资源。是 Service、Deployment 等关联 Pod 的核心机制。

命令行使用:

操作 命令
等值筛选 kubectl get pods -l app=nginx
多条件筛选(AND) kubectl get pods -l app=nginx,env=dev
不等于 kubectl get pods -l env!=production
集合筛选 kubectl get pods -l 'env in (dev,staging)'

YAML 中使用(Deployment 通过 selector 关联 Pod):

yaml 复制代码
# Deployment 的 selector 与 Pod 的 labels 必须匹配
spec:
  selector:
    matchLabels:
      app: nginx          # ─┐
  template:               #  │ 必须一致
    metadata:             #  │
      labels:             #  │
        app: nginx        # ─┘

Service 通过 selector 关联 Pod:

yaml 复制代码
# Service 选择所有带 app=nginx 标签的 Pod
spec:
  selector:
    app: nginx            # 匹配 Pod 的 labels
  ports:
  - port: 80

Label + Selector 是 K8s 的核心关联机制:Deployment 通过它管理 Pod,Service 通过它转发流量,NetworkPolicy 通过它控制网络策略。


3. 服务发现和负载均衡

3.1 Ingress

3.1.1 概念和作用

在第 2 章中,Service(NodePort/LoadBalancer)可以将流量从集群外部引入,但存在局限:

方式 局限
NodePort 端口范围有限(30000-32767),每个 Service 占一个端口,不支持域名
LoadBalancer 每个 Service 创建一个云负载均衡器,成本高

Ingress 解决的问题:用一个统一入口管理所有外部访问,支持:

  • 域名路由 :api.example.com → Service A,web.example.com → Service B
  • 路径路由 :example.com/api → Service A,example.com/web → Service B
  • TLS/HTTPS:统一管理 SSL 证书
  • 负载均衡:一个入口分发到多个后端 Service

类比:Service 是每个应用的"后门",Ingress 是整个集群的"前台大门 + 路由器"。

3.1.2 Ingress Controller

Ingress 本身只是一份路由规则的定义 (YAML),不会自动生效。需要部署 Ingress Controller 来实际执行这些规则。

Ingress Controller 说明
Nginx Ingress Controller 最常用,基于 Nginx 反向代理
Traefik 轻量,自动发现服务,适合微服务
HAProxy 高性能,企业级
云厂商 AWS ALB、GCE、阿里云 SLB,与云服务深度集成

关系:Ingress(规则) + Ingress Controller(执行者) = 完整的外部访问方案。类似 Deployment(规则)需要 kubelet(执行者)来创建 Pod。

在 Kind 中安装 Nginx Ingress Controller:

bash 复制代码
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

# 等待 Controller 就绪
kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=90s

3.1.3 Ingress 规则和配置

沿用上方 nginx-app.yaml(Deployment + Service 部署在 dev 命名空间),为其创建 Ingress:

yaml 复制代码
# nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: dev                          # 与 Service 同一命名空间
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /    # URL 重写规则
spec:
  ingressClassName: nginx                 # 指定使用哪个 Ingress Controller
  rules:
  - host: app.example.com                # 域名(匹配请求的 Host 头)
    http:
      paths:
      - path: /                           # 路径匹配
        pathType: Prefix                  # Prefix=前缀匹配,Exact=精确匹配
        backend:
          service:
            name: nginx-service           # ← 转发到的 Service(metadata.name)
            port:
              number: 80                  # ← Service 的端口

nginx-ingress.yaml 是独立文件,与 nginx-app.yaml 分开执行即可。只要满足:

  1. Ingress Controller 已安装
  2. nginx-app.yaml 已部署(Deployment + Service 在 dev 命名空间运行中)
  3. Ingress 的 namespace 与 Service 相同,service.name 与 Service 的 metadata.name 一致
操作 命令
创建 Ingress kubectl apply -f nginx-ingress.yaml
查看 Ingress kubectl get ingress -n dev
查看详情 kubectl describe ingress nginx-ingress -n dev
删除 Ingress kubectl delete ingress nginx-ingress -n dev
本地访问 Ingress(Kind/WSL 环境)

Kind 没有云负载均衡器,Ingress Controller 的 EXTERNAL-IP 会一直显示 <pending>。通过以下步骤在本地访问:

步骤一:配置 hosts

在 WSL 中添加域名映射(Windows 的 hosts 对 WSL 内的 curl 无效):

bash 复制代码
echo "127.0.0.1 app.example.com" | sudo tee -a /etc/hosts

步骤二:端口转发

bash 复制代码
# 方式1:使用非特权端口(无需 sudo)
kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8080:80

# 方式2:使用 80 端口(需指定 kubeconfig,因为 sudo 下 root 的 kubeconfig 不同)
sudo kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 80:80 --kubeconfig=$HOME/.kube/config

步骤三:测试访问(新开一个终端)

bash 复制代码
# 方式1 对应
curl http://app.example.com:8080

# 方式2 对应
curl http://app.example.com

⚠️ port-forward 是前台进程,终端关闭则停止。生产环境不会用此方式,而是通过云负载均衡器或 NodePort 暴露。

3.1.4 域名路由和路径路由

域名路由(多个域名 → 不同 Service)
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
  namespace: dev
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com               # 域名 A
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service            # → 转发到 api-service
            port:
              number: 8080
  - host: web.example.com               # 域名 B
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service            # → 转发到 web-service
            port:
              number: 80
路径路由(同一域名,不同路径 → 不同 Service)
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-based-ingress
  namespace: dev
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /api(/|$)(.*)             # example.com/api/* → api-service
        pathType: ImplementationSpecific
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /web(/|$)(.*)             # example.com/web/* → web-service
        pathType: ImplementationSpecific
        backend:
          service:
            name: web-service
            port:
              number: 80
TLS/HTTPS 配置
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
  namespace: dev
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls-secret           # 存储证书的 Secret 名称
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80

证书通过 kubectl create secret tls app-tls-secret --cert=tls.crt --key=tls.key -n dev 创建。

访问流程总结:

复制代码
用户请求 → Ingress Controller(Nginx) → 根据域名/路径匹配 Ingress 规则 → 转发到 Service → kube-proxy 负载均衡 → Pod

3.2 网络

3.2.1 Kubernetes 网络模型

K8s 网络遵循三条基本原则:

原则 说明
Pod 间通信 所有 Pod 可以直接通过 IP 互相通信,无需 NAT
Pod 与 Service Pod 通过 Service 的 ClusterIP 或 DNS 名称访问其他服务
外部与集群 通过 NodePort、LoadBalancer 或 Ingress 访问集群内服务

四种通信场景:

场景 实现方式
同一 Pod 内容器间 通过 localhost(共享网络命名空间)
同一节点的 Pod 间 通过虚拟网桥(如 cbr0/cni0)直接通信
跨节点的 Pod 间 通过 CNI 插件建立的覆盖网络(Overlay Network)
外部访问 Pod 通过 Service(NodePort/LoadBalancer)或 Ingress

3.2.2 CNI(Container Network Interface)

CNI 是 K8s 的网络插件规范,负责为 Pod 分配 IP、建立跨节点通信。K8s 本身不实现网络,由 CNI 插件完成。

CNI 插件 特点 适用场景
Flannel 简单轻量,配置少 学习、小型集群
Calico 支持网络策略(NetworkPolicy),性能好 生产环境,需要网络隔离
Cilium 基于 eBPF,高性能,可观测性强 大规模生产,安全要求高
Weave 自动发现,加密通信 多云环境

Kind 和 Minikube 默认自带 CNI 插件(kindnet / bridge),学习阶段无需额外安装。

CNI 工作流程:

arduino 复制代码
Pod 创建 → kubelet 调用 CNI 插件 → 分配 IP → 配置网络(veth pair、路由规则) → Pod 可通信

3.2.3 Service Mesh

Service Mesh(服务网格)是在 K8s 网络之上的应用层网络方案,用于管理微服务间的通信。

为什么需要 Service Mesh? K8s 的 Service + kube-proxy 只提供基础的 L4(TCP)负载均衡,缺少:

需求 Service Mesh 提供的能力
流量管理 灰度发布、A/B 测试、流量镜像、熔断、重试
可观测性 分布式链路追踪、指标采集、访问日志
安全 服务间 mTLS 加密、访问控制
策略 限流、超时配置、故障注入

主流 Service Mesh:

方案 说明
Istio 功能最全面,社区最大,学习曲线较陡
Linkerd 轻量级,性能好,易于上手
Consul Connect HashiCorp 出品,与 Consul 服务发现集成

Istio 架构简述:

graph LR subgraph Data Plane["数据平面"] A[Pod A] --- SA[Sidecar Proxy<br/>Envoy] B[Pod B] --- SB[Sidecar Proxy<br/>Envoy] SA <-->|加密通信| SB end subgraph Control Plane["控制平面"] IS[istiod<br/>配置管理/证书/服务发现] end IS -->|下发配置| SA IS -->|下发配置| SB

Service Mesh 通过在每个 Pod 旁注入 Sidecar 代理(如 Envoy),拦截所有进出流量,实现上述能力。业务代码无需修改。

⚠️ Service Mesh 属于进阶内容,小型项目或学习阶段不必使用。


4. 存储和配置

4.1 ConfigMap 和 Secret

ConfigMap

ConfigMap 用于存储非敏感的配置数据(键值对或配置文件),与应用代码解耦。

创建 ConfigMap
bash 复制代码
# 方式1:命令行创建
kubectl create configmap app-config \
  --from-literal=DB_HOST=mysql-service \
  --from-literal=DB_PORT=3306 \
  -n dev

# 方式2:从文件创建
kubectl create configmap nginx-config \
  --from-file=nginx.conf \
  -n dev
yaml 复制代码
# 方式3:YAML 创建
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: dev
data:
  DB_HOST: mysql-service          # 键值对形式
  DB_PORT: "3306"
  app.properties: |               # 文件形式(多行内容)
    server.port=8080
    spring.datasource.url=jdbc:mysql://mysql-service:3306/mydb
使用 ConfigMap

方式1:注入为环境变量

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
  namespace: dev
spec:
  containers:
  - name: app
    image: my-app:1.0
    env:
    - name: DB_HOST                      # 容器中的环境变量名
      valueFrom:
        configMapKeyRef:
          name: app-config               # ConfigMap 名称
          key: DB_HOST                   # ConfigMap 中的 key
    - name: DB_PORT
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: DB_PORT

方式2:挂载为配置文件

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
  namespace: dev
spec:
  containers:
  - name: app
    image: my-app:1.0
    volumeMounts:
    - name: config-volume
      mountPath: /app/config             # 挂载到容器内的路径
  volumes:
  - name: config-volume
    configMap:
      name: app-config                   # ConfigMap 名称
      # ConfigMap 的每个 key 变成 /app/config/ 下的一个文件
操作 命令
查看 ConfigMap kubectl get configmap -n dev
查看内容 kubectl describe configmap app-config -n dev
删除 kubectl delete configmap app-config -n dev

Secret

Secret 用于存储敏感数据(密码、Token、证书等),与 ConfigMap 类似但数据以 Base64 编码存储。

创建 Secret
bash 复制代码
# 方式1:命令行创建
kubectl create secret generic db-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD=p@ssw0rd \
  -n dev
yaml 复制代码
# 方式2:YAML 创建(值需 Base64 编码)
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
  namespace: dev
type: Opaque
data:
  DB_USER: YWRtaW4=               # echo -n 'admin' | base64
  DB_PASSWORD: cEBzc3cwcmQ=       # echo -n 'p@ssw0rd' | base64
使用 Secret
yaml 复制代码
# 注入为环境变量(与 ConfigMap 类似,将 configMapKeyRef 换为 secretKeyRef)
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
  namespace: dev
spec:
  containers:
  - name: app
    image: my-app:1.0
    env:
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: db-secret                # Secret 名称
          key: DB_USER
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: DB_PASSWORD
操作 命令
查看 Secret kubectl get secret -n dev
查看内容(Base64 编码) kubectl get secret db-secret -n dev -o yaml
解码查看 `kubectl get secret db-secret -n dev -o jsonpath='{.data.DB_PASSWORD}'

⚠️ Secret 不是真正的加密,Base64 只是编码,任何人拿到都能解码。生产环境建议配合 RBAC 限制访问权限,或使用外部密钥管理(如 Vault、AWS Secrets Manager)。

ConfigMap vs Secret 对比

对比项 ConfigMap Secret
用途 非敏感配置(数据库地址、端口等) 敏感数据(密码、Token、证书)
存储方式 明文 Base64 编码
大小限制 1MB 1MB
使用方式 环境变量 / 挂载文件 环境变量 / 挂载文件
引用方式 configMapKeyRef secretKeyRef

4.2 存储

Volume(卷)

在 2.1.4 多容器 Pod 中已介绍过 emptyDir。Volume 是 K8s 中为 Pod 提供存储的机制,生命周期与 Pod 绑定或独立于 Pod。

常用 Volume 类型回顾:

类型 存储位置 生命周期 适用场景
emptyDir Worker 节点磁盘 随 Pod 销毁 Pod 内容器间共享临时数据
hostPath Worker 节点指定路径 节点存在就在 访问节点文件(日志、Docker socket)
configMap etcd(通过 ConfigMap) 随 ConfigMap 存在 挂载配置文件
secret etcd(通过 Secret) 随 Secret 存在 挂载敏感配置
persistentVolumeClaim 外部存储 独立于 Pod 和节点 数据库、文件存储等持久化需求

PersistentVolume(PV)和 PersistentVolumeClaim(PVC)

emptyDir 和 hostPath 的数据会随 Pod/节点丢失,不适合需要持久化存储的场景(如数据库)。

K8s 通过 PV + PVC 机制实现持久化存储:

概念 说明 类比
PersistentVolume (PV) 集群中一块预先准备好的存储资源 硬盘
PersistentVolumeClaim (PVC) Pod 对存储的申请("我需要 10Gi 空间") 购买硬盘的订单

流程:管理员创建 PV → 开发者创建 PVC 申请存储 → K8s 自动将 PVC 绑定到匹配的 PV → Pod 挂载 PVC 使用

创建 PV
yaml 复制代码
# pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv                            # PV 是集群级资源,不属于任何 namespace
spec:
  capacity:
    storage: 10Gi                         # 存储容量
  accessModes:
  - ReadWriteOnce                         # 访问模式(见下方说明)
  persistentVolumeReclaimPolicy: Retain   # 回收策略(见下方说明)
  storageClassName: manual                # 存储类名(与 PVC 匹配)
  hostPath:
    path: /data/my-pv                     # 存储在节点上的路径(仅测试用)

访问模式:

模式 简写 说明
ReadWriteOnce RWO 单节点读写
ReadOnlyMany ROX 多节点只读
ReadWriteMany RWX 多节点读写(需存储支持,如 NFS)

回收策略:

策略 说明
Retain PVC 删除后 PV 保留数据,需手动清理
Delete PVC 删除后 PV 和存储一起删除(云盘常用)
Recycle 清除数据后重新可用(已废弃)
创建 PVC
yaml 复制代码
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
  namespace: dev
spec:
  accessModes:
  - ReadWriteOnce                         # 需与 PV 匹配
  resources:
    requests:
      storage: 5Gi                        # 申请 5Gi(PV 需 ≥ 5Gi)
  storageClassName: manual                # 需与 PV 的 storageClassName 匹配
在 Pod 中使用 PVC
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: db-pod
  namespace: dev
spec:
  containers:
  - name: mysql
    image: mysql:8.0
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: DB_PASSWORD
    volumeMounts:
    - name: db-storage
      mountPath: /var/lib/mysql           # MySQL 数据目录
  volumes:
  - name: db-storage
    persistentVolumeClaim:
      claimName: my-pvc                   # 引用 PVC 名称
操作 命令
创建 PV kubectl apply -f pv.yaml
创建 PVC kubectl apply -f pvc.yaml
查看 PV kubectl get pv
查看 PVC kubectl get pvc -n dev
查看绑定状态 PV 和 PVC 的 STATUS 都显示 Bound 表示绑定成功

StorageClass

手动创建 PV 太繁琐。StorageClass 实现动态供给:PVC 创建时自动创建对应的 PV。

yaml 复制代码
# storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-storage
provisioner: kubernetes.io/aws-ebs       # 存储供应商(不同环境不同)
parameters:
  type: gp3                               # 存储类型参数
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer   # 等 Pod 调度后再创建 PV

使用 StorageClass 的 PVC(无需手动创建 PV):

yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: auto-pvc
  namespace: dev
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: fast-storage          # 引用 StorageClass,自动创建 PV

流程对比:

  • 手动:管理员创建 PV → 开发者创建 PVC → 绑定
  • 动态(StorageClass):开发者创建 PVC(指定 StorageClass)→ K8s 自动创建 PV → 自动绑定
操作 命令
查看 StorageClass kubectl get storageclass
查看默认 StorageClass kubectl get sc(带 (default) 标记的)

常见 provisioner:

环境 provisioner
AWS EBS kubernetes.io/aws-ebs 或 ebs.csi.aws.com
GCE PD kubernetes.io/gce-pd
阿里云 diskplugin.csi.alibabacloud.com
NFS nfs-subdir-external-provisioner
本地测试(Kind) rancher.io/local-path(Kind 默认自带)
相关推荐
鬼手点金6 小时前
nanoGPT/nanochat 能做出 DeepSeek/Qwen 这样的大模型吗?
服务器·前端·javascript·bug·openclaw
蛋蛋的就会顺顺的6 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
程序员Sunday7 小时前
TypeScript 的 any、unknown、never 有什么区别?
前端·面试·typescript
朱涛的自习室7 小时前
70 美金的 Beyond Compare,我让 Gemini 4 和 DeepSeek 造个开源免费版(Day 2)
android·前端·人工智能
码艺-Alimjan7 小时前
Tauri 源码备份 · 打包 & 解压 总结,源码收集之路
前端·javascript·vue.js
小马不起床7 小时前
零基础玩转 FastAPI_11:前端后台管理页面
前端·状态模式·fastapi
子非鱼a9 小时前
【文件上传】一个普普通通的edu16
前端
美狐美颜SDK开放平台9 小时前
直播APP如何实现美白滤镜功能?视频美颜SDK技术开发方案详解
前端·数据库·人工智能·音视频·美颜sdk·直播美颜sdk·视频美颜sdk
pride.li10 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
屏什么录10 小时前
电脑如何录屏幕视频和声音?从工具到代码,7 种方案帮你彻底搞定
前端·音视频开发