Kubernetes(K8s)学习笔记
2026-03-11 15:07:34 # 云安全

Kubernetes (K8s) 学习笔记

一、Kubernetes 是什么

  • 定义:Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩缩容和管理容器化应用。
  • 核心能力:声明式配置、自动调度、自愈、服务发现与负载均衡、密钥与配置管理、存储编排、批量执行等。
  • 简称:K8s(K 与 s 之间有 8 个字母)。

二、核心基础概念

2.1 Cluster(集群)

  • 含义:由一组**控制平面节点(Master)和若干工作节点(Node)**组成的整体。
  • 作用:在集群内统一调度、运行和管理容器化应用。
  • 关系:一个集群 = 1 个控制平面 + N 个 Node。

2.2 Node(节点)

  • 含义:集群中的一台机器(物理机或虚拟机),是 Pod 实际运行的地方。

  • 分类

    • Control Plane Node(控制平面节点):运行集群控制逻辑,不跑业务 Pod(也可配置为可调度)。
    • Worker Node(工作节点):运行业务 Pod,受控制平面管理。
  • 组件:每个 Node 上通常有 kubelet、kube-proxy、容器运行时(如 containerd/CRI-O)。

  • 云服务器和 Node / Pod 的关系(常见误解)
    在 AWS、阿里云、腾讯云、Google Cloud 等买的云服务器(如 EC2、ECS、CVM、GCE 实例),是虚拟机(VM)或物理机,不是 K8s 的 Pod。云厂商卖给你的是“一台机器”这种计算单元,和 K8s 无关。

    • 若你自己用这些云服务器搭建 K8s:每台云服务器在集群里就是 Node(控制平面或工作节点),Pod 是跑在这些 Node 上的,由 K8s 调度、创建、销毁。
    • 若你使用云厂商的托管 K8s(如 EKS、ACK、TKE、GKE):云厂商负责控制平面,你购买或挂载的“节点”仍然是 VM/实例,在 K8s 里对应 Node;你的业务跑在 Pod 里,Pod 跑在这些 Node 上。
      总结:云服务器 ≈ 机器(VM)→ 在 K8s 里是 Node;Pod 是 K8s 在 Node 上创建的运行单元,不是云厂商“分配给你的那一台服务器”。

2.3 Pod

  • 含义:K8s 中最小可部署单元,由一个或多个容器组成,共享网络和存储。
  • 一个 Pod 里可以有几个容器?
    • 单容器 Pod:最常见,一个 Pod 只跑一个业务容器,多数 Deployment 都是这种。
    • 多容器 Pod:一个 Pod 里可以定义多个容器,它们共享同一 Network Namespace(同一 IP、同一 localhost,用不同端口区分)和挂载的 Volume,且总是被一起调度到同一台节点上。典型用法是 Sidecar(边车):主容器跑业务,另一个容器跑日志采集、代理或监控等,需要与主容器紧密配合、共享网络或磁盘时,就放在同一个 Pod 里。
  • 特点
    • 同一 Pod 内容器共享 Network Namespace(同一 IP、端口空间)和 Volume。(Volume 即“一块存储/目录”;挂载即把这块存储接到容器里某个路径,容器内通过该路径读写文件;同一 Pod 里多个容器可挂载同一 Volume,从而共享文件。)
    • Pod 是短暂的,会被调度、迁移、重建;一般不直接创建裸 Pod,而是通过 Deployment 等控制器管理。
  • 用途:单容器时就是普通应用;多容器时用于把强耦合、需要紧密协作的容器放在一个 Pod 里(如应用 + 边车)。

2.4 Namespace(命名空间)

  • 含义:集群内的逻辑隔离,用于多租户、多环境(dev/test/prod)划分资源。
  • 作用:资源名称在 Namespace 内唯一,不同 Namespace 下可以有同名资源;可配合 RBAC 做权限隔离。(RBAC = Role-Based Access Control,基于角色的访问控制:通过 Role/ClusterRole 定义“能对哪些资源做哪些操作”,通过 RoleBinding/ClusterRoleBinding 把角色绑定到用户或服务账号,从而限制谁能在哪个 Namespace 里做什么。)
  • 常见defaultkube-systemkube-publickube-node-lease 等,也可自建。

2.5 Label(标签)与 Selector(选择器)

  • Label:键值对,挂在 Pod、Node、Service 等对象上,用于标识和分类(如 env=prodapp=web)。
  • Selector:按 Label 筛选资源。例如 Deployment(见 2.7)用 selector 指定要管理的 Pod;Service(见 2.8)用 selector 指定后端 Pod。
    • Deployment:一种控制器,负责维护一组 Pod 的副本数、做滚动更新/回滚,常用于无状态应用。
    • Service:为 Pod 提供固定访问入口(稳定 IP/DNS)和负载均衡,通过 Label Selector 找到要转发的 Pod。
  • 常用matchLabelsmatchExpressions(支持 In、NotIn、Exists、DoesNotExist)。

2.6 Annotation(注解)

  • 含义:键值对,用于存非标识性元数据(说明、配置、工具用信息),不参与对象选择。
  • 与 Label 区别:Label 用于选择和分组;Annotation 用于记录信息,可存较大或结构化数据。

2.7 Controller(控制器)与声明式 API

  • 声明式:用户描述“期望状态”(如 3 个副本、用某镜像),控制器负责让当前状态不断逼近期望状态
  • 常见控制器
    • Deployment:无状态应用,支持滚动更新、回滚。Deployment 创建并管理 ReplicaSet 来控制 Pod 的部署和扩展。
    • ReplicaSet:只做一件事——维护 Pod 副本数量(例如“始终保持 3 个带某 Label 的 Pod”)。通常不直接写 ReplicaSet,而是写 Deployment;Deployment 会创建并管理一个或多个 ReplicaSet,由 ReplicaSet 去创建/删除 Pod。可以理解为:Deployment = 上层(负责版本、更新策略),ReplicaSet = 下层(负责具体维持多少个 Pod)。
    • StatefulSet:有状态应用,稳定网络标识和持久化存储。
    • DaemonSet:每个 Node 上跑一个 Pod(如日志采集、网络插件)。
    • Job:执行一次性任务,任务完成后 Pod 自动终止。
    • CronJob:按 cron 表达式定期执行 Job。

2.8 Service(服务)

  • 含义:为 Pod 提供稳定的访问入口(固定 ClusterIP/DNS 名),做服务发现与负载均衡
  • 原因:Pod IP 会变,不能直接依赖;Service 通过 Label Selector 找到后端 Pod,并做负载均衡。
  • 类型
    • ClusterIP:集群内访问,默认类型。
    • NodePort:在每个 Node 上开端口,从集群外通过 NodeIP:NodePort 访问。
    • LoadBalancer:对接云厂商负载均衡器,对外暴露。
    • ExternalName:把 Service 映射到外部 DNS 名。

2.9 Ingress 与 Ingress Controller

Ingress(Ingress 资源)

  • 是什么:K8s 里的一种 API 资源,用 YAML 描述“HTTP/HTTPS 流量怎么路由”——按主机名(如 a.example.com)、路径(如 /api)把请求转发到不同的 Service
  • 作用:用一个入口(一个对外 IP/域名)暴露多个后端服务,可做 TLS 终结(在入口处 HTTPS 解密)、虚拟主机(按域名区分)、路径路由(如 /web → web-svc,/api → api-svc)。注意:Ingress 只是“路由规则”的声明,本身不会处理流量,需要由 Ingress Controller 来具体实现。

Ingress Controller(Ingress 控制器)

  • 是什么:集群里真正干活的组件,一般以 Deployment + Pod 的形式运行。它会监听集群中的 Ingress 资源,根据规则去配置并驱动一个反向代理(如 Nginx、Traefik、Envoy),由这个代理接收外部 HTTP/HTTPS 流量并按 Ingress 规则转发到对应 Service(再经 Service 到 Pod)。
  • 常见实现Nginx Ingress ControllerTraefikHAProxy IngressIstio Gateway 等;不同实现支持的注解(annotation)和高级功能略有差异。
  • 与 Ingress 的关系Ingress = 你写的“路由规则”(声明式);Ingress Controller = 读取这些规则并配置反向代理的程序。没有安装并运行 Ingress Controller,创建 Ingress 资源也不会生效。

小结

概念 角色
Ingress 声明“哪个主机/路径 → 转发到哪个 Service”的 K8s 资源
Ingress Controller 监听 Ingress、配置反向代理并实际转发流量的控制器程序

2.10 ConfigMap 与 Secret

  • ConfigMap:存非敏感配置(如配置文件、环境变量),以键值或文件形式挂到 Pod。
  • Secret:存敏感数据(密码、证书、Token),以 Base64 或加密形式存储,挂到 Pod;生产建议配合加密或外部 Secret 方案。

2.11 Volume(卷)与持久化

  • Volume 与挂载(通俗理解)Volume 就是 Pod 里的一块“存储/目录”。挂载是指把这块存储接到容器内的某个路径(如 /data),容器里访问这个路径就是在读写这块存储。同一 Pod 里多个容器可以把同一 Volume 挂载到各自路径,从而共享同一份文件;Pod 重建或迁移后,若用的是持久化 Volume,数据仍可保留。
  • Volume:Pod 内挂载的存储,生命周期可与 Pod 绑定(emptyDir)或独立(PVC)。
  • PV(PersistentVolume):集群级存储资源,由管理员或动态供给创建。
  • PVC(PersistentVolumeClaim):用户“申请”一块存储,绑定到 PV;Pod 通过 PVC 使用持久化存储。
  • StorageClass:定义动态供给的“存储类型”,按 PVC 自动创建 PV(如云盘、NFS)。

三、控制平面组件(Control Plane)

控制平面负责集群的全局决策与协调,通常部署在 Master 节点(或高可用多节点)。

3.1 kube-apiserver(API 服务器)

  • 作用:K8s 集群的唯一入口,所有组件都通过 REST API 与 apiserver 交互。
  • 功能:认证、鉴权、校验、持久化资源到 etcd;提供 Watch 机制供控制器和调度器感知变更。
  • 特点:无状态、可水平扩展,高可用时多副本 + 负载均衡。

3.2 etcd

  • 作用:分布式键值存储,保存集群的全部状态数据(Pod、Service、ConfigMap 等)。
  • 特点:强一致性、高可用(多副本);只有 apiserver 直接读写 etcd,其他组件不直接访问。
  • 注意:需定期备份,并做好资源与网络隔离。

3.3 kube-scheduler(调度器)

  • 作用:为未调度的 Pod 选择合适的 Node 并完成绑定。
  • 流程:过滤(Filter):筛掉不满足条件的节点;打分(Score):对剩余节点打分,选最优。
  • 考虑因素:资源请求/限制、亲和/反亲和、污点与容忍、拓扑等;可扩展与二次开发。

3.4 kube-controller-manager(控制器管理器)

  • 作用:运行多种内置控制器,通过 apiserver 监听资源变化,驱动“当前状态”向“期望状态”收敛。
  • 包含:Node Controller、Replication Controller、Deployment Controller、Endpoints Controller、Service Account & Token Controller 等。
  • 形式:多控制器在同一进程中,通过 goroutine 并发运行。

3.5 cloud-controller-manager(云控制器管理器,可选)

  • 作用:与云厂商 API 对接,处理与云相关的逻辑(如节点生命周期、负载均衡、存储)。
  • 目的:把云相关代码从 kube-controller-manager 中拆出,便于云厂商定制和 K8s 核心升级。

四、节点组件(Node Components)

运行在每个工作节点上,负责维护 Pod 生命周期与网络。

4.1 kubelet

  • 作用:节点上的代理,负责:
    • 向 apiserver 注册本节点;
    • 接收 Pod 清单(来自 apiserver 或静态 Pod 配置);
    • 拉取镜像、启动/停止容器、执行探针;
    • 汇报 Pod 与节点状态。
  • 特点:不通过 apiserver 创建的容器,kubelet 不会管理;是节点上最核心的组件。

4.2 kube-proxy

  • 作用:在节点上实现 Service 的负载均衡与转发(如 ClusterIP 到后端 Pod 的流量)。
  • 模式:iptables 或 ipvs,将访问 Service VIP 的流量转发到对应 Pod;支持会话亲和等。

4.3 容器运行时(Container Runtime)

  • 作用:在节点上真正拉取镜像、创建/运行容器
  • 接口:通过 CRI(Container Runtime Interface) 与 kubelet 对接。
  • 常见:containerd、CRI-O;Docker 作为运行时已被弃用,但镜像仍通用。

五、附加组件(Add-ons)

常以 Pod 形式部署在集群内,提供扩展能力。

  • DNS:CoreDNS 等,为 Service/ Pod 提供集群内 DNS(如 svc-name.namespace.svc.cluster.local)。
  • 网络插件:Calico、Flannel、Cilium 等,实现 Pod 网络(CNI)与可选网络策略。
  • Ingress Controller:如 Nginx Ingress、Traefik,实现 Ingress 规则并转发流量。
  • Dashboard:Web UI,可视化管理集群(需配合鉴权与网络策略)。

六、请求流转小结(便于记忆)

  1. 用户通过 kubectl 或 API 向 kube-apiserver 提交 YAML(如创建 Deployment)。
  2. apiserver 校验并写入 etcd,其他组件通过 Watch 感知变更。
  3. kube-controller-manager 中的 Deployment 等控制器创建 ReplicaSet/Pod 等资源。
  4. kube-scheduler 为未调度的 Pod 选 Node,写回 apiserver(Pod 的 nodeName)。
  5. 目标 Node 上的 kubelet 从 apiserver 拿到 Pod 清单,通过 容器运行时 拉镜像、起容器。
  6. kube-proxy网络插件 提供 Service 访问与 Pod 网络;DNS 提供集群内解析。

七、进阶知识点

7.1 RBAC(基于角色的访问控制)

  • 目的:控制能对哪些资源执行哪些操作(get、list、create、delete、patch 等),实现细粒度权限与多租户隔离。
  • 核心资源
    • Role:定义一组权限,作用范围限定在某个 Namespace(如对 pods 的 get/list)。
    • ClusterRole:同上,但作用范围是集群级(如对所有 ns 的 Pod 只读,或对节点、PV 等集群资源的权限)。
    • RoleBinding:把某个 Role/ClusterRole 绑定到用户、组或 ServiceAccount仅在该 Namespace 内生效
    • ClusterRoleBinding:把 ClusterRole 绑定到主体,集群范围内生效
  • 常用:为不同团队绑定不同 Namespace 的 Role;为 Pod 使用的 ServiceAccount 绑定最小权限的 Role,供应用访问 K8s API 或某 ns 内资源。

7.2 网络策略(Network Policy)

  • 目的:在集群内做Pod 间/入站/出站流量的访问控制(类似防火墙规则),实现“默认拒绝”或“仅允许某 Pod 访问某服务”。
  • 前提:需要网络插件支持 NetworkPolicy(如 Calico、Cilium、Weave 等);仅创建 NetworkPolicy 资源而插件不支持则无效。
  • 常见用法:按 Namespace 或 Label 选择 Pod,规定 Ingress(谁可以访问我)/ Egress(我可以访问谁)的规则(协议、端口、对端 Pod/命名空间或 IP 段)。
  • 注意:默认多数集群“全通”;一旦某 Namespace 存在一条 NetworkPolicy,该 NS 内未匹配到任何规则的流量通常会被拒绝,需显式放行。

7.3 调度策略(亲和 / 反亲和、污点与容忍)

  • 节点亲和(Node Affinity):在 Pod 上声明“优先或必须”调度到带某 Label 的节点(如 node-type=GPUzone=cn-hangzhou),用于把负载放到特定机型或可用区。
  • Pod 亲和 / 反亲和(Pod Affinity / Anti-Affinity):根据“已运行的 Pod”所在节点做调度,例如:同一应用的 Pod 尽量打散到不同节点(反亲和),或与某缓存 Pod 尽量同节点(亲和)。
  • 污点与容忍(Taint & Toleration):在节点上打 Taint(如 dedicated=app:NoSchedule),只有带对应 Toleration 的 Pod 才能被调度上去;用于“专用节点”(如只跑 GPU 任务、只跑 Ingress),避免普通 Pod 被调度到这些节点。
  • 小结:亲和/反亲和表达“想和谁在一起/分开”;污点与容忍表达“只有符合条件的 Pod 才能上这类节点”。

7.4 Helm

  • 是什么:K8s 的包管理工具,把一组 YAML(Deployment、Service、ConfigMap 等)打包成 Chart,支持参数化(变量、环境区分)和版本管理。
  • 作用:一键安装/升级/回滚复杂应用(如 MySQL、Redis、Prometheus);通过 values.yaml 覆盖默认配置,避免手改大量 YAML。
  • 核心概念Chart(应用包)→ Release(在集群中安装后的实例,有名字和版本);helm installhelm upgradehelm rollbackhelm uninstall
  • 常用:使用官方或社区 Chart(如 helm repo add bitnami https://charts.bitnami.com/bitnami),或为公司内部应用编写私有 Chart。

7.5 Operator

  • 是什么:一种扩展 K8s 的方式:用自定义资源(CRD)+ 控制器来管理“有状态或复杂逻辑”的应用,把运维知识编码成代码,通过声明式资源驱动(如创建一个 MySQLCluster 资源,Operator 自动创建 StatefulSet、Service、备份等)。
  • 与普通控制器的区别:Operator 针对特定应用/中间件(如 etcd、Prometheus、MySQL、Kafka),不仅管 Pod 数量,还管配置、扩缩容、升级、备份恢复等领域逻辑
  • 常见:Prometheus Operator、ETCD Operator、MySQL Operator、Kafka Operator 等;也可用 Operator SDKKubeBuilder 自研 Operator。
  • 价值:把“人肉运维”变成“声明式 + 自动化”,更贴近“K8s 原生”的使用方式。

八、Kubernetes Goat 靶场环境探索

8.1 环境搭建

Kubernetes Goat 是一个故意设计的安全漏洞靶场环境,专门用于学习和实践 Kubernetes 安全概念。

环境搭建方式

方式一:在已有集群上部署(推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 确保集群正常运行
kubectl cluster-info
kubectl get nodes

# 2. 下载并部署 Kubernetes Goat
cd kubernetes-goat
chmod +x setup-kubernetes-goat.sh
bash setup-kubernetes-goat.sh

# 3. 等待所有 Pod 就绪
kubectl get pods -A -w

# 4. 启动访问服务
bash access-kubernetes-goat.sh
方式二:一键建集群并部署
1
2
3
# 直接在 Kind 中创建集群并部署 Goat
cd kubernetes-goat/platforms/kind-setup
bash setup-kind-cluster-and-goat.sh

环境验证

1
2
3
4
5
6
7
8
9
10
11
# 查看集群状态
kubectl cluster-info

# 查看节点状态
kubectl get nodes

# 查看所有 Pod
kubectl get pods -A

# 测试访问
curl http://localhost:1234

8.2 核心基础概念

8.2.1 Cluster(集群)

含义:由一组**控制平面节点(Master)和若干工作节点(Node)**组成的整体。

在 Goat 环境中的体现

1
2
# 查看集群信息
kubectl cluster-info

image-20260308235313819

1
2
# 查看节点状态
kubectl get nodes -o wide

image-20260308235403489

当前集群状态:

  • 控制平面节点:1个 (my-k8s-lab-control-plane)
  • 工作节点:1个 (my-k8s-lab-worker)
  • 版本:v1.35.0

8.2.2 Node(节点)

含义:集群中的一台机器(物理机或虚拟机),是 Pod 实际运行的地方。

控制面板节点
1
2
# 查看 控制平面节点 详情
kubectl describe node my-k8s-lab-control-plane

image-20260309003531515

image-20260309003845487

控制平面节点 (my-k8s-lab-control-plane):

  • 角色:control-plane

  • 污点node-role.kubernetes.io/control-plane:NoSchedule(阻止业务Pod调度)

  • 容量:10 CPU核心,8GB内存,最多110个Pod

  • 架构:ARM64,运行Debian 12

  • 容器运行时:containerd 2.2.0

  • Pod网络:10.244.0.0/24

  • 当前负载:9个系统Pod,CPU使用9%,内存使用3%

  • 运行组件:API Server、etcd、Scheduler、Controller Manager等

工作节点
1
2
# 查看 工作节点 详情 
kubectl describe node my-k8s-lab-worker

image-20260309004907659

image-20260309005001807

工作节点 (my-k8s-lab-worker):

  • 角色(纯工作节点)
  • 污点:无(可以正常调度业务Pod)
  • 容量:10 CPU核心,8GB内存,最多支持110个Pod
  • 架构:ARM64,运行Debian 12
  • 容器运行时:containerd 2.2.0
  • Pod网络:10.244.1.0/24
  • 当前负载:13个Pod,CPU使用率3%,内存使用率6%
  • 运行组件:kubelet、kube-proxy、kindnet(网络插件)
  • 业务Pod:运行所有kubernetes-goat应用组件(主页、构建服务、健康检查、代理、数据库等)
节点标签和状态
1
2
# 查看节点标签和状态
kubectl get nodes --show-labels

image-20260309005508339

节点标签是键值对,用于标识节点的特性,在Pod调度和节点选择中发挥重要作用:

当前集群节点标签详解:

控制平面节点 (my-k8s-lab-control-plane) 标签:

  • beta.kubernetes.io/arch=arm64:Beta版本架构标签,表示ARM64架构
  • beta.kubernetes.io/os=linux:Beta版本OS标签,表示Linux操作系统
  • kubernetes.io/arch=arm64:稳定版架构标签,标识节点CPU架构
  • kubernetes.io/hostname=my-k8s-lab-control-plane:节点主机名
  • kubernetes.io/os=linux:稳定版OS标签,标识操作系统
  • node-role.kubernetes.io/control-plane=:节点角色标签,标识为控制平面节点
  • node.kubernetes.io/exclude-from-external-load-balancers=:排除外部负载均衡器标签

工作节点 (my-k8s-lab-worker) 标签:

  • beta.kubernetes.io/arch=arm64:Beta版本架构标签
  • beta.kubernetes.io/os=linux:Beta版本OS标签
  • kubernetes.io/arch=arm64:稳定版架构标签
  • kubernetes.io/hostname=my-k8s-lab-worker:节点主机名
  • kubernetes.io/os=linux:稳定版OS标签

标签作用说明:

  • 架构标签 (kubernetes.io/arch):用于调度需要特定CPU架构的Pod
  • OS标签 (kubernetes.io/os):用于调度需要特定操作系统的Pod
  • 角色标签 (node-role.kubernetes.io/*):标识节点类型,影响调度策略
  • 主机名标签 (kubernetes.io/hostname):节点唯一标识,可用于节点亲和性
  • Beta标签:Kubernetes的Beta API标签,可能在未来版本中移除

这些标签可以被Pod的nodeSelector、nodeAffinity等调度策略使用,实现精细化的Pod placement控制。

8.2.3 Pod

含义:K8s 中最小可部署单元,由一个或多个容器组成,共享网络和存储。

在 Goat 环境中的体现

1
2
# 查看所有 Pod
kubectl get pods -A -o wide

image-20260309010634958

当前集群中的单容器Pod示例:

  • metadata-db (default):数据库服务,IP 10.244.1.2
  • build-code-deployment (default):构建服务,IP 10.244.1.4
  • health-check-deployment (default):健康检查服务,IP 10.244.1.6
  • poor-registry-deployment (default):镜像仓库服务,IP 10.244.1.10
  • system-monitor-deployment (default):系统监控服务,IP 10.244.1.11
  • kubernetes-goat-home-deployment (default):主页服务,IP 10.244.1.9
  • batch-check-job (default):批处理任务,IP 10.244.1.3
  • hidden-in-layers (default):隐藏层服务,IP 10.244.1.12
  • hunger-check-deployment (big-monolith):饥饿检查服务,IP 10.244.1.7
  • cache-store-deployment (secure-middleware):缓存存储服务,IP 10.244.1.5

多容器Pod示例:

  • internal-proxy-deployment (default):内部代理服务,包含2个容器,IP 10.244.1.8
单容器Pod

大部分应用服务都是单容器Pod,例如:

1
2
# 查看特定 Pod 详情
kubectl describe pod kubernetes-goat-home-deployment-cd46cd955-xsz9c -n default

image-20260309010744926

image-20260309010806976

kubernetes-goat-home Pod 示例:

  • Pod名称:kubernetes-goat-home-deployment-cd46cd955-xsz9c
  • 命名空间:default
  • 状态:Running(运行中)
  • 调度节点:my-k8s-lab-worker (172.19.0.2)
  • 标签:app=kubernetes-goat-home, pod-template-hash=cd46cd955
  • 容器信息
    • 容器名:kubernetes-goat-home
    • 镜像:madhuakula/k8s-goat-home
    • 端口:80/TCP
    • 资源配置:CPU 30m/30m, 内存 50Mi/50Mi (Guaranteed QoS)
  • 控制器:由ReplicaSet/kubernetes-goat-home-deployment-cd46cd955管理
  • 网络:Pod IP 10.244.1.9
  • 存储:挂载service account token卷用于API访问
  • 容忍:默认容忍节点not-ready和unreachable状态
多容器Pod

internal-proxy-deployment (default):多容器Pod示例

1
2
# 查看多容器 Pod
kubectl describe pod -l app=internal-proxy -n default

image-20260309010947071

image-20260309011033180

  • Pod名称:internal-proxy-deployment-c59c45d94-sqnpw
  • 状态:Running(运行中)
  • 调度节点:my-k8s-lab-worker (172.19.0.2)
  • 网络:Pod IP 10.244.1.8
  • 容器详情
    • internal-api容器
      • 镜像:madhuakula/k8s-goat-internal-api
      • 端口:3000/TCP
      • 资源:CPU 30m/50m, 内存 40Mi/60Mi
    • info-app容器
      • 镜像:madhuakula/k8s-goat-info-app
      • 端口:5000/TCP
      • 资源:CPU 30m/30m, 内存 40Mi/50Mi
  • QoS等级:Burstable(资源请求 < 限制)
  • 共享存储:两个容器都挂载service account token卷
  • 控制器:由ReplicaSet/internal-proxy-deployment-c59c45d94管理

这个多容器Pod展示了Sidecar模式:两个容器共享同一网络命名空间和存储卷,但提供不同的功能服务。

8.2.4 Namespace(命名空间)

含义:集群内的逻辑隔离,用于多租户、多环境划分资源。

所有命令空间
1
2
# 查看所有命名空间
kubectl get namespaces

image-20260309013056906

7个命名空间:

  • default:默认命名空间,所有未指定命名空间的资源所在
  • kube-system:Kubernetes系统组件命名空间
  • kube-public:公共资源命名空间,所有用户可读
  • kube-node-lease:节点租约,用于节点心跳检测
  • big-monolith:大型单体应用命名空间
  • secure-middleware:安全中间件命名空间
  • local-path-storage:本地存储组件命名空间

所有命名空间状态均为Active,运行时间约9小时。

命名空间的资源分布
1
2
# 查看各命名空间的资源分布
kubectl get all --all-namespaces | grep -v kube-system

image-20260309013203203

image-20260309013230780

Goat 环境的命名空间架构:

  • default (10个Pod, 8个Deployment, 8个ReplicaSet, 7个Service, 2个Job):

    • 主应用命名空间,包含大部分业务服务
    • 包括主页、构建服务、健康检查、数据库、注册表等核心组件
    • 还有批处理任务和隐藏服务
  • big-monolith (1个Pod, 1个Deployment, 1个ReplicaSet, 1个Service):

    • 大型单体应用命名空间,模拟传统应用架构
    • 包含饥饿检查(hunger-check)服务
  • secure-middleware (1个Pod, 1个Deployment, 1个ReplicaSet, 1个Service):

    • 安全中间件命名空间,包含缓存存储服务
    • 提供Redis风格的缓存功能
  • local-path-storage (1个Pod, 1个Deployment, 1个ReplicaSet):

    • 本地存储组件命名空间
    • 运行local-path-provisioner提供本地持久化存储
  • kube-system:系统组件命名空间(包含API Server、etcd、CoreDNS等)

  • kube-public:公共资源命名空间

  • kube-node-lease:节点租约命名空间

8.2.5 Label(标签)与 Selector(选择器)

Label:键值对,挂在 Pod、Node、Service 等对象上,用于标识和分类

Selector:按 Label 筛选资源。

Pod标签
1
2
# 查看 Pod 标签
kubectl get pods --all-namespaces --show-labels

image-20260309103347894

展示了Pod标签的丰富多样性:

Deployment管理的Pod标签模式:

  • app=<service-name>:应用标识标签,如 app=kubernetes-goat-home
  • pod-template-hash=<hash>:模板哈希,用于版本控制,如 pod-template-hash=cd46cd955

Job管理的Pod标签模式:

  • batch.kubernetes.io/job-name=<name>:作业名称,如 batch.kubernetes.io/job-name=batch-check-job
  • batch.kubernetes.io/controller-uid=<uid>:控制器UID,用于唯一标识
  • job-name=<name>:简化作业名称标签

系统组件标签模式:

  • component=<component-name>:组件类型,如 component=etcd
  • tier=control-plane:层级标识,标记控制平面组件
  • k8s-app=<app-name>:Kubernetes应用标识,如 k8s-app=kube-dns
  • app=<app-name>:应用名称,如 app=kindnet

Helm管理的Pod标签(metadata-db):

  • app.kubernetes.io/instance=<release-name>:Helm发布实例名
  • app.kubernetes.io/name=<chart-name>:Helm Chart名称

这些标签构成了Kubernetes资源管理的基石,支持服务发现、负载均衡、滚动更新等核心功能。

Deployment 的选择器
1
2
# 查看 Deployment 的选择器
kubectl describe deployment kubernetes-goat-home-deployment -n default

image-20260309133738838

kubernetes-goat-home-deployment 的选择器: app=kubernetes-goat-home

通过这个选择器,Deployment 能够找到并管理所有带有 app=kubernetes-goat-home 标签的 Pod。这个选择器确保了 Deployment 只管理属于主页应用的 Pod 实例。

Service 的选择器
1
2
# 查看 Service 的选择器
kubectl describe svc kubernetes-goat-home-service -n default

image-20260309141511565

kubernetes-goat-home-service 的选择器: app=kubernetes-goat-home

  • 服务类型:ClusterIP (集群内部访问)
  • 服务IP:10.96.38.30
  • 端口映射:80/TCP → 80/TCP
  • 后端端点:10.244.1.9:80 (匹配的Pod IP和端口)
  • 会话亲和性:None (不保持会话粘性)

通过选择器 app=kubernetes-goat-home,Service 能够发现并负载均衡到所有带有此标签的 Pod。

Goat环境中的实际标签模式:

业务应用标签:

  • app=kubernetes-goat-home:主页应用标识
  • app=build-code:构建服务标识
  • app=health-check:健康检查服务标识
  • app=internal-proxy:内部代理服务标识
  • app=metadata-db:数据库服务标识
  • app=poor-registry:镜像仓库服务标识
  • app=system-monitor:系统监控服务标识
  • app=hunger-check:饥饿检查服务标识 (big-monolith命名空间)
  • app=cache-store:缓存存储服务标识 (secure-middleware命名空间)

控制器生成标签:

  • pod-template-hash=<hash>:Deployment/ReplicaSet生成的Pod模板哈希
  • batch.kubernetes.io/job-name=<name>:Job生成的Pod作业名称
  • controller-uid=<uid>:控制器实例唯一标识

8.2.6 Annotation(注解)

含义:键值对,用于存非标识性元数据,不参与对象选择。

Pod注解
1
2
# 查看 Pod 注解
kubectl describe pod kubernetes-goat-home-deployment-cd46cd955-xsz9c -n default | grep -A 10 Annotations

image-20260309143200919

kubernetes-goat-home Pod 的注解: 无注解 (<none>)

这个 Pod 没有配置任何注解,这在简单的应用部署中是常见的。注解通常用于存储非标识性元数据,如配置信息、工具说明等。

Deployment注解
1
2
# 查看 Deployment 注解
kubectl describe deployment metadata-db -n default | grep -A 10 Annotations

image-20260309143223269

metadata-db Deployment 的注解:

  • deployment.kubernetes.io/revision: 1:Kubernetes 自动生成的部署版本号,表示这是第1个版本
  • meta.helm.sh/release-name: metadata-db:Helm Chart 的发布名称
  • meta.helm.sh/release-namespace: default:Helm Chart 发布的命名空间

这些注解提供了部署版本控制和 Helm 管理的元数据信息。

8.2.7 Controller(控制器)与声明式 API

声明式:用户描述"期望状态",控制器负责让"当前状态"不断逼近"期望状态"。

Deployment
1
2
# 查看所有 Deployment(最常见的控制器)
kubectl get deployments -A

image-20260309143248902

共 11 个 Deployment,分布在 5 个命名空间中:

  • default: 7个(kubernetes-goat-home、build-code、health-check、internal-proxy、metadata-db、poor-registry、system-monitor)
  • big-monolith: 1个(hunger-check)
  • secure-middleware: 1个(cache-store)
  • kube-system: 1个(coredns)
  • local-path-storage: 1个(local-path-provisioner)

控制器主要作用:

  1. 状态调谐:持续监控实际状态与期望状态的差异
  2. 自动修复:当Pod异常退出时,自动创建新的Pod维持期望副本数
  3. 声明式管理:用户只需声明"期望状态",控制器负责实现
  4. 扩展伸缩:支持动态调整Pod副本数量
  5. 滚动更新:支持应用版本的无缝升级和回滚

控制器是Kubernetes实现自动化和自愈能力的核心组件。

ReplicaSet
1
2
# 查看 Deployment 管理的 ReplicaSet
kubectl get rs -A

image-20260309143324874

ReplicaSet 详解:

共 11 个 ReplicaSet,全都由 Deployment 自动创建和管理:

  • 10个单副本 RS:每个维护1个Pod实例(DESIRED=1, CURRENT=1, READY=1)
  • 1个双副本 RS:coredns 维护2个Pod实例(DESIRED=2, CURRENT=2, READY=2)

ReplicaSet 主要作用:

  1. 副本保证:确保指定数量的Pod副本始终运行,即使节点故障或Pod异常退出
  2. 自动修复:当Pod失败时,立即在合适节点创建新的Pod替换
  3. 扩缩容支持:通过修改期望副本数实现Pod的动态伸缩
  4. 标签管理:通过标签选择器精确匹配和管理目标Pod
  5. 版本控制:每个Deployment版本对应一个ReplicaSet,支持回滚

ReplicaSet 是实现 Kubernetes 自愈和弹性伸缩的核心控制器。

Job
1
2
# 查看 Job(一次性任务控制器)
kubectl get jobs -A

image-20260309143352878

2个 Job,用于执行一次性批处理任务:

  • batch-check-job:运行中,0/1 完成,持续运行31小时
  • hidden-in-layers:运行中,0/1 完成,持续运行31小时

Job 主要作用:

  1. 一次性执行:运行完成后自动终止,不像Deployment那样持续运行
  2. 完成保证:确保任务至少执行一次,失败时自动重试
  3. 并行处理:支持同时运行多个Pod实例处理同一任务
  4. 资源清理:任务完成后自动删除关联的Pod,节省资源
  5. 定时任务基础:CronJob 通过定期创建Job来实现定时执行

Job 适用于数据处理、备份、迁移等需要执行一次就结束的任务。

8.2.8 Service(服务)

含义:为 Pod 提供稳定的访问入口,做服务发现与负载均衡

所有服务
1
2
# 查看所有服务
kubectl get svc -A

image-20260309143536949

共 12 个 Service,提供稳定的网络访问:

  • 11个 ClusterIP 服务:集群内部访问(默认类型)
  • 1个 NodePort 服务:通过节点端口从外部访问
  • 1个系统 DNS 服务:kube-dns 提供域名解析

Service 主要作用:

  1. 网络抽象:为Pod组提供稳定的虚拟IP和DNS名,屏蔽Pod的动态变化
  2. 负载均衡:自动将请求分发到多个Pod实例,实现高可用
  3. 服务发现:通过DNS或环境变量让应用找到其他服务
  4. 流量控制:支持会话亲和性、端口映射等高级功能
  5. 多访问方式:ClusterIP(内)、NodePort(外)、LoadBalancer(云)

Service 是 Kubernetes 实现微服务通信和网络抽象的核心组件。

服务详情
1
2
# 查看服务详情
kubectl describe svc kubernetes-goat-home-service -n default

image-20260309143602753

kubernetes-goat-home-service 详情分析:

Service 详情包含以下主要内容:

基本信息:

  • 名称和命名空间:kubernetes-goat-home-service / default
  • 标签和注解:用于标识和存储元数据

核心配置:

  • 选择器app=kubernetes-goat-home - 用于匹配后端Pod
  • 服务类型:ClusterIP - 集群内部访问
  • 虚拟IP:10.96.38.30 - 服务稳定访问地址

端口配置:

  • 服务端口:80/TCP - 外部访问端口
  • 目标端口:80/TCP - Pod内容器端口

后端状态:

  • 端点:10.244.1.9:80 - 实际Pod的IP和端口
  • 会话亲和性:None - 不保持会话粘性

Service 通过选择器找到匹配的Pod,并提供稳定的网络访问端点。

服务端点
1
2
# 查看服务端点
kubectl get endpoints -A

image-20260309143632662

共 12 个 Endpoints,记录 Service 后端 Pod 的实际地址:

Endpoints 是 Service 的"地址簿",记录了所有匹配 Pod 的 IP 和端口:

Endpoints 主要作用:

  1. 地址记录:维护 Service 选择器匹配到的所有 Pod 的 IP:Port
  2. 动态更新:当 Pod 启动、停止或重启时,自动更新端点列表
  3. 负载均衡基础:Service 使用 Endpoints 信息进行流量分发
  4. 健康过滤:只包含 Ready 状态的 Pod 端点
  5. 网络桥梁:连接 Service 的虚拟 IP 与 Pod 的实际地址

示例分析:

  • kubernetes-goat-home-service10.244.1.9:80(单个Pod)
  • kube-dns → 多个端点(2个Pod提供DNS服务)
  • kubernetes172.19.0.3:6443(API Server端点)

Endpoints 确保 Service 始终知道如何找到可用的后端 Pod。

Goat 环境中的服务类型统计:

ClusterIP (11个):集群内部访问的默认服务类型

  • 所有业务应用服务:主页、构建、健康检查、数据库、注册表等
  • 系统服务:kubernetes (API Server)、kube-dns (DNS服务)

NodePort (1个):通过节点端口从外部访问

  • internal-proxy-info-app-service:端口映射 5000→30003

服务类型说明:

  • ClusterIP:只在集群内部访问,提供稳定的虚拟IP
  • NodePort:在每个节点上开放端口,允许外部访问
  • LoadBalancer:在云环境中自动创建负载均衡器(当前环境未使用)

8.2.9 Ingress 与 Ingress Controller

Ingress:描述 HTTP/HTTPS 流量路由规则的 K8s 资源。

Ingress Controller:实际处理流量的控制器。

Ingress资源
1
2
# 查看 Ingress 资源
kubectl get ingress -A

image-20260309143657298

Goat环境中没有使用Ingress,而是通过以下方式进行流量路由:

主要流量路由方式:

  1. Service直接暴露

    • ClusterIP:11个服务通过集群内部虚拟IP访问
    • NodePort:1个服务通过节点端口30003暴露给外部
  2. 端口转发

    • 使用kubectl port-forwardbash access-kubernetes-goat.sh脚本
    • 将集群内部服务映射到本地端口(如1234)
  3. 应用层路由

    • 某些服务在应用内部实现自己的路由逻辑
    • 如internal-proxy服务处理多个端口的流量分发
Ingress Controller(如果存在)
1
2
# 查看 Ingress Controller(如果存在)
kubectl get pods -n kube-system | grep ingress

image-20260309143727197

**当前状态:**Goat 环境未配置 Ingress,主要是通过 NodePort 和端口转发访问。

8.2.10 ConfigMap 与 Secret

ConfigMap:存非敏感配置

Secret:存敏感数据

ConfigMap
1
2
# 查看所有 ConfigMap
kubectl get configmaps -A

image-20260309143804182

共 15 个 ConfigMaps,分布在 6 个命名空间中:

ConfigMaps 主要作用:

  1. 配置存储:以键值对形式存储非敏感配置数据
  2. 环境变量注入:将配置传递给Pod作为环境变量
  3. 挂载为文件:将配置挂载到Pod的文件系统中
  4. 应用配置管理:管理应用的配置文件、环境设置等

ConfigMap 分类:

系统ConfigMaps (12个):

  • kube-root-ca.crt:Kubernetes根证书,在每个命名空间都有
  • cluster-info:集群连接信息
  • coredns:DNS服务配置
  • kube-proxy:代理服务配置
  • kubelet-config:节点代理配置
  • local-path-config:本地存储配置

业务ConfigMaps (3个):

  • extension-apiserver-authentication:扩展API认证配置
  • kubeadm-config:集群初始化配置
  • kube-apiserver-legacy-service-account-token-tracking:服务账户令牌跟踪配置

ConfigMaps 提供了将配置与应用代码分离的最佳实践方式。

Secret
1
2
# 查看所有 Secret
kubectl get secrets -A

image-20260309143824831

共 4 个 Secrets,存储敏感数据:

Secrets 主要作用:

  1. 敏感数据存储:以Base64编码形式存储密码、密钥、证书等敏感信息
  2. 安全传递:将敏感数据安全地传递给Pod,避免明文暴露
  3. 访问控制:通过RBAC控制Secrets的访问权限
  4. 加密存储:在etcd中加密存储,支持密钥轮换

Secrets vs ConfigMaps:

  • Secrets:存储敏感数据,Base64编码,在内存中解密
  • ConfigMaps:存储非敏感配置,明文存储

当前Secrets详解:

  • goatvault (default): 应用密钥存储
  • vaultapikey (big-monolith): API密钥
  • webhookapikey (big-monolith): Webhook密钥
  • sh.helm.release.v1.metadata-db.v1 (default): Helm发布信息

Secrets 提供了在Kubernetes中管理敏感数据的安全机制。

Secret详情
1
2
# 查看特定 Secret 详情
kubectl describe secret goatvault -n default

image-20260309143847778

goatvault Secret 的详情分析:

Secret 详情包含以下主要信息:

基本信息:

  • 名称:goatvault
  • 命名空间:default
  • 类型:Opaque(通用类型Secret)
  • 标签和注解:无(未设置标识信息)

数据内容:

  • 密钥名称:k8sgoatvaultkey
  • 数据大小:41字节(Base64编码后的长度)
  • 实际值:出于安全考虑,describe命令不显示明文值

安全特性:

  • 编码存储:数据以Base64格式存储
  • 访问控制:需要适当的RBAC权限才能访问
  • 运行时解密:Pod内使用时才解密为明文

Secret详情提供了元数据信息,但出于安全考虑不显示敏感数据内容。

Secret 数据(Base64 编码)
1
2
# 查看 Secret 数据(Base64 编码)
kubectl get secret goatvault -n default -o yaml

image-20260309143925696

查看Secret完整数据(YAML格式):

Secret 的完整YAML结构包含以下内容:

资源元数据 (metadata):

  • name:Secret名称 (goatvault)
  • namespace:所属命名空间 (default)
  • annotations:注解信息,包括kubectl的应用配置历史
  • creationTimestamp:创建时间戳
  • resourceVersion:资源版本号
  • uid:全局唯一标识符

规范信息 (spec):

  • type:Secret类型 (Opaque - 通用类型)
  • data:Base64编码的敏感数据
    • k8sgoatvaultkey: azhzLWdvYXQtY2QyZGEyNzIyNDU5MWRhMmI0OGVmODM4MjZhOGE2YzM=

解码后的实际值:

1
2
echo "azhzLWdvYXQtY2QyZGEyNzIyNDU5MWRhMmI0OGVmODM4MjZhOGE2YzM=" | base64 -d
# 输出: k8s-goat-cd2da27224591da2b48ef83826a8a6c3

当前环境的关键Secret:

  • goatvault:存储k8s-goat-cd2da27224591da2b48ef83826a8a6c3密钥
  • vaultapikey:API访问密钥
  • webhookapikey:Webhook认证密钥

8.2.11 Volume(卷)与持久化

Volume:Pod 内的存储抽象。

PV/PVC:持久化存储资源。

持久卷声明
1
2
# 查看持久卷声明
kubectl get pvc -A

image-20260309143945260

PVC (PersistentVolumeClaim) 不存在。

PVC 全称:PersistentVolumeClaim(持久卷声明)

PVC 的作用

  1. 存储请求:Pod向Kubernetes请求持久化存储空间
  2. 自动绑定:根据请求条件自动绑定合适的PersistentVolume(PV)
  3. 抽象层:为Pod提供存储抽象,屏蔽底层存储细节
  4. 生命周期管理:独立于Pod生命周期,数据持久保存

为什么 Goat 环境中没有 PVC?

  1. 应用特性:大部分服务是无状态应用,无需持久化存储

  2. 数据存储方式

    • 内存存储:数据存储在Pod内存中,随Pod重启而丢失
    • 数据库服务:数据存储在metadata-db容器中(但未配置外部持久卷)
    • 临时存储:可能使用emptyDir卷提供容器内临时存储
  3. 环境设计:作为安全靶场环境,重点在于安全漏洞演示而非数据持久化

  4. 存储策略:使用local-path-provisioner但未创建实际的PVC请求

PVC 使用示例

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-storage
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 1Gi

PVC 是 Kubernetes 持久化存储的核心抽象,但在 Goat 环境中被有意省略以简化架构。

持久卷
1
2
# 查看持久卷
kubectl get pv -A

image-20260309143958796

PV (PersistentVolume) 为空。

PV 全称:PersistentVolume(持久卷)

PV 的作用

  1. 存储资源:集群级别的存储卷,代表实际的物理存储
  2. 生命周期管理:独立于Pod存在,可被多个PVC绑定和释放
  3. 存储抽象:屏蔽底层存储实现的差异(NFS、本地磁盘、云存储等)
  4. 容量管理:定义存储容量、访问模式和回收策略

为什么 Goat 环境中 PV 为空?

  1. 没有PVC请求:PV是由PVC动态创建或静态预创建的,没有PVC就不会有PV
  2. 应用无需持久化:大部分服务是无状态的,不需要持久卷
  3. 存储策略:虽然配置了local-path-provisioner,但没有实际的PVC来触发PV创建

PV 创建方式:

  • 动态创建:通过StorageClass + PVC自动创建
  • 静态创建:管理员预先创建PV供PVC绑定

PV 状态:

  • Available:可用,等待PVC绑定
  • Bound:已绑定到PVC
  • Released:PVC删除后进入释放状态
  • Failed:创建或绑定失败

PV 是 Kubernetes 存储系统的物理存储层,在 Goat 环境中被省略以简化架构。

存储类
1
2
# 查看存储类
kubectl get storageclass

image-20260309144016567

StorageClass 详解:

StorageClass 是什么?
StorageClass 是 Kubernetes 的存储类,定义了如何自动创建存储卷的"模板"。

核心作用:

  1. 存储供应:定义存储卷的创建方式和参数
  2. 动态供应:PVC请求时自动创建对应的PV
  3. 存储抽象:屏蔽不同存储系统的差异
  4. 策略控制:定义回收策略、绑定模式等行为

当前环境StorageClass配置:

属性 说明
名称 standard (default) 默认存储类,标有(default)标识
供应器 rancher.io/local-path 使用本地路径供应器
回收策略 Delete PVC删除时自动删除PV和数据
绑定模式 WaitForFirstConsumer 延迟绑定,等待Pod使用时再绑定
卷扩展 false 不支持动态扩展存储容量

工作原理:

  1. PVC请求存储时指定storageClassName
  2. StorageClass根据配置自动创建PV
  3. PV与PVC绑定,Pod即可使用存储

StorageClass 让存储管理变得声明式和自动化。

存储配置:

  • StorageClass:standard (local-path) - 已配置但未使用
  • PVC:0个 - Goat环境中没有持久卷声明
  • PV:0个 - 没有PVC请求,自然没有持久卷

存储设计决策:

  • 采用无状态架构设计,大部分应用无需持久化存储
  • 数据存储在容器内存服务抽象层
  • 虽然配置了local-path-provisioner,但没有实际PVC触发PV创建
  • 这种设计有利于快速重建环境简化,但数据在Pod重启后会丢失

8.3 控制平面组件(Control Plane)

控制平面负责集群的全局决策与协调。

8.3.1 kube-apiserver(API 服务器)

作用:K8s 集群的唯一入口,所有组件都通过 REST API 与 apiserver 交互。

API Server状态
1
2
# 查看 API Server状态
kubectl get pods -n kube-system | grep apiserver

image-20260309144302393

API Server 运行状态:正常运行

API Server 详解:

API Server 是什么?
kube-apiserver 是 Kubernetes 控制平面的核心组件,是整个集群的"大脑"和统一入口。

核心功能:

  1. 统一入口:所有集群操作的唯一入口点
  2. API 提供:提供RESTful API供kubectl、控制器、调度器等访问
  3. 认证授权:验证请求身份和权限
  4. 数据校验:验证和处理API请求的数据合法性
  5. 状态存储:将资源状态写入etcd并提供读取服务
  6. Watch机制:支持实时监听资源变化

当前状态:

  • Pod名称:kube-apiserver-my-k8s-lab-control-plane
  • 状态:1/1 Running(1个容器,正常运行)
  • 重启次数:0(运行稳定)
  • 运行时间:32小时

工作原理:

  1. 接收kubectl或其他客户端的请求
  2. 进行身份认证和权限检查
  3. 验证请求数据的合法性
  4. 将资源状态写入etcd
  5. 通过Watch机制通知相关组件

API Server 是 Kubernetes 集群的控制中枢,所有操作都要通过它进行。

测试API连接
1
2
# 测试 API 连接
kubectl cluster-info

image-20260309144529915

查看 API Server 端点
1
2
# 查看 API Server 端点
kubectl get endpoints kubernetes -n default

image-20260309144551367

API Server 端点详解:

端点是什么?
API Server端点是kubernetes服务的实际访问地址,记录了API Server Pod的IP和端口。

端点的作用:

  1. 服务发现:告诉集群内部组件如何访问API Server
  2. 负载均衡:支持多个API Server实例时的负载分发
  3. 网络连接:提供稳定的网络访问点
  4. 健康检查:Endpoints会自动更新,确保只指向健康的Pod

当前端点信息:

  • 服务名称:kubernetes
  • 端点地址:172.19.0.3:6443
  • 协议:HTTPS (6443是标准Kubernetes API端口)
  • 运行时间:32小时

访问方式对比:

  • 内部访问:通过端点IP (172.19.0.3:6443)
  • 外部访问:通过kubectl proxy或端口转发 (https://127.0.0.1:64040)

重要性:
Endpoints确保了集群组件能够可靠地找到并连接到API Server,是集群通信的基础设施。

8.3.2 etcd

作用:分布式键值存储,保存集群的全部状态数据

etcd状态
1
2
# 查看 etcd 状态
kubectl get pods -n kube-system | grep etcd

image-20260309144615055

etcd 运行状态:正常运行

etcd 详解:

etcd 是什么?
etcd 是 Kubernetes 的分布式键值存储系统,是集群的"记忆数据库"。

核心功能:

  1. 数据存储:保存集群的所有状态信息(Pod、Service、ConfigMap等)
  2. 高可用:支持多节点复制,确保数据不丢失
  3. 一致性保证:使用Raft算法确保数据一致性
  4. Watch机制:支持实时监听数据变化
  5. 原子操作:支持事务和条件更新

当前状态:

  • Pod名称:etcd-my-k8s-lab-control-plane
  • 状态:1/1 Running(正常运行)
  • 重启次数:0(运行稳定)
  • 运行时间:42小时

etcd 的作用机制:

  1. API Server写入:所有集群状态变更都通过API Server写入etcd
  2. 数据持久化:etcd将数据写入磁盘,确保重启后数据不丢失
  3. 数据复制:在多节点etcd集群中同步数据
  4. 读取服务:API Server从etcd读取集群状态
  5. 变更通知:通过Watch API通知控制器和调度器状态变化

为什么重要?

  • 单一数据源:集群状态的唯一权威来源
  • 故障恢复:支持集群重启后状态恢复
  • 性能保障:高效的读写性能支撑大规模集群
  • 安全存储:支持数据加密存储

etcd 是 Kubernetes 集群状态的"中央大脑",没有etcd集群就无法正常工作。

etcd端点
1
2
# 查看 etcd 端点
kubectl describe pod etcd-my-k8s-lab-control-plane -n kube-system | grep -A 5 "Containers"

image-20260309144643250

etcd 容器配置详解:

容器信息:

  • 镜像registry.k8s.io/etcd:3.6.6-0
  • 端口:2381/TCP(etcd客户端端口,用于集群内部通信)
  • 探针端口:2381(用于健康检查)

存储配置:

  • 证书卷:etcd-certs (HostPath类型)
  • 挂载路径:/etc/kubernetes/pki/etcd
  • 用途:存储etcd的TLS证书和密钥

工作机制:

  1. 数据存储:etcd将集群状态以键值对形式存储
  2. 证书认证:使用TLS证书保证通信安全
  3. 集群通信:通过2381端口与其他etcd节点通信
  4. API访问:API Server通过本地连接访问etcd

安全特性:

  • TLS加密:所有通信都经过TLS加密
  • 证书验证:双向证书认证确保通信安全
  • 访问控制:只有API Server能直接访问etcd

etcd 是集群状态的加密、安全存储后端。

8.3.3 kube-scheduler(调度器)

作用:为未调度的 Pod 选择合适的 Node 并完成绑定。

调度器状态
1
2
# 查看调度器状态
kubectl get pods -n kube-system | grep scheduler

image-20260309144710578

调度策略
1
2
# 查看调度决策
kubectl describe pod kubernetes-goat-home-deployment-cd46cd955-xsz9c -n default | grep -A 5 "Status"

image-20260309144739795

调度器状态:正常运行

Kubernetes 调度策略详解:

调度器是什么?
kube-scheduler 是 Kubernetes 的调度组件,负责将Pod分配到合适的节点上运行。

调度流程:

  1. 过滤阶段(Predicate):筛选出满足Pod要求的节点
  2. 打分阶段(Priority):对候选节点进行打分排序
  3. 选择阶段:选择得分最高的节点进行绑定

主要调度策略:

1. 资源调度:

  • CPU/内存请求:确保节点有足够资源
  • 资源限制:考虑Pod的资源上限
  • QoS等级:Guaranteed > Burstable > BestEffort

2. 亲和性调度:

  • 节点亲和性:Pod偏好某些节点特征
  • Pod亲和性:Pod间相互吸引或排斥
  • Pod反亲和性:避免Pod在同一节点

3. 污点与容忍:

  • 污点:节点拒绝某些Pod调度
  • 容忍:Pod声明能接受的污点

4. 其他策略:

  • 拓扑约束:跨区域/可用区的分布
  • 优先级:高优先级Pod优先调度
  • 抢占:为高优先级Pod释放资源

当前调度结果分析:

  • Pod状态:PodScheduled=True(已成功调度)
  • 调度节点:my-k8s-lab-worker(工作节点)
  • 控制关系:通过ReplicaSet间接调度
  • 网络分配:自动分配Pod IP (10.244.1.9)

调度器确保了Pod被分配到满足所有要求的节点上,实现集群资源的合理利用。

8.3.4 kube-controller-manager(控制器管理器)

作用:运行多种内置控制器,驱动"当前状态"向"期望状态"收敛。

控制器管理器是实现Kubernetes声明式API和自愈能力的关键组件。

控制器管理器状态
1
2
# 查看控制器管理器状态
kubectl get pods -n kube-system | grep controller-manager

image-20260309144801556

控制器管理的资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看控制器管理的资源(修正后的命令)
# 注意:混合资源类型不支持排序,需要分开查看

# 查看所有Deployment
kubectl get deployments -A

# 查看所有ReplicaSet
kubectl get replicasets -A

# 查看所有Pod(按状态排序)
kubectl get pods -A --sort-by=.status.phase

# 查看最近创建的资源(使用时间排序)
kubectl get pods -A --sort-by=.metadata.creationTimestamp | tail -10

控制器管理器状态:正常运行

控制器管理器详解:

kube-controller-manager 是什么?
它是 Kubernetes 控制平面的核心组件,运行多个内置控制器来维护集群状态。

核心功能:

  1. 状态调谐:持续监控当前状态与期望状态的差异
  2. 自动修复:发现偏差时自动执行操作纠正状态
  3. 多控制器集成:在一个进程中运行多种控制器

包含的主要控制器:

  • Deployment Controller:管理Deployment和ReplicaSet
  • ReplicaSet Controller:管理Pod副本
  • Service Controller:维护Service和Endpoints
  • Node Controller:管理节点状态
  • PV Controller:管理持久卷绑定
  • Job Controller:管理一次性任务

当前状态:

  • Pod名称:kube-controller-manager-my-k8s-lab-control-plane
  • 状态:1/1 Running(正常运行)
  • 重启次数:0(运行稳定)
  • 运行时间:42小时

工作机制:
控制器管理器通过API Server的Watch机制监听资源变化,当检测到当前状态偏离期望状态时,自动执行修正操作,确保集群始终处于期望状态。

8.4 节点组件(Node Components)

运行在每个工作节点上,负责维护 Pod 生命周期与网络。

8.4.1 kubelet

作用:节点上的代理,负责 Pod 生命周期管理。

1
2
3
# 查看 kubelet 进程(需要在节点上执行)
# 在宿主机上:
ps aux | grep kubelet

image-20260310152159093

1
2
# 查看节点状态
kubectl describe node my-k8s-lab-worker

image-20260310152345775

image-20260310152438120

工作节点状态详解:

节点基本信息:

  • 名称:my-k8s-lab-worker
  • 角色(纯工作节点)
  • 污点:无(可正常调度Pod)
  • 状态:Ready(节点正常运行)

资源容量:

  • CPU:10核
  • 内存:8GB (8024852Ki)
  • 存储:60GB (ephemeral-storage)
  • Pod容量:最多110个Pod

当前资源使用:

  • CPU分配:320m 请求 / 340m 限制 (3% 使用率)
  • 内存分配:490Mi 请求 / 520Mi 限制 (6% 使用率)
  • 运行Pod数:13个

网络配置:

  • Pod网络段:10.244.1.0/24
  • 节点IP:172.19.0.2 (内部)

健康状态:

  • MemoryPressure:False(内存充足)
  • DiskPressure:False(磁盘空间充足)
  • PIDPressure:False(进程数正常)
  • Ready:True(节点就绪)

系统信息:

  • OS:Debian GNU/Linux 12 (bookworm)
  • 架构:ARM64
  • 内核:6.12.54-linuxkit
  • 容器运行时:containerd 2.2.0
  • Kubelet版本:v1.35.0

节点运行正常,资源充足,可继续调度新的Pod。

1
2
# 查看 Pod 状态
kubectl get pods -A -o wide

**当前状态:**每个节点都有 kubelet 运行,负责管理该节点的 Pod

8.4.2 kube-proxy

作用:在节点上实现 Service 的负载均衡与转发。

在 Goat 环境中的体现

1
2
# 查看 kube-proxy 状态
kubectl get pods -n kube-system | grep proxy

image-20260310165439926

1
2
# 查看 Service 网络规则
kubectl get svc -A

image-20260310165519609

1
2
# 测试服务访问
kubectl run test-pod --image=busybox --rm -it -- wget -qO- http://kubernetes-goat-home-service.default.svc.cluster.local

kube-proxy 详解:

当前状态:

  • 工作节点:kube-proxy-462gh (1/1 Running)
  • 控制平面:kube-proxy-hmzh6 (1/1 Running)
  • 职责:每个节点都有kube-proxy,负责该节点的Service流量转发

kube-proxy 的核心作用:

  1. Service实现:将Service的虚拟IP/端口映射到实际Pod
  2. 负载均衡:在多个Pod间分发请求,实现高可用
  3. 网络规则管理:维护iptables/ipvs规则进行流量转发

与Service的关系:

Service定义网络抽象:

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- port: 80 # Service端口
targetPort: 8080 # Pod端口

kube-proxy实现具体转发:

  • 监听Service和Endpoints变化
  • 创建本地网络规则(iptables/ipvs)
  • 将到达Service IP:Port的流量转发到Pod IP:targetPort

流量路径:

1
客户端 → Service ClusterIP:Port → kube-proxy规则 → 选择Pod → Pod IP:targetPort

kube-proxy 是Service网络功能的实际执行者,确保了服务的可靠访问。

8.4.3 容器运行时(Container Runtime)

作用:真正拉取镜像、创建/运行容器。

在 Goat 环境中的体现

1
2
3
4
5
6
7
8
9
10
11
# 进入 Kind 节点容器检查容器运行时

# 1. 查看 Kind 节点容器
docker ps | grep kind

# 2. 进入控制平面节点(推荐使用这个节点,因为它运行更多组件)
# 注意:这里的"节点"是Kind创建的Docker容器,不是K8s Pod
docker exec -it my-k8s-lab-control-plane bash

# 3. 在节点容器内检查(crictl已预装)
crictl ps

image-20260310171435835

1
2
3
4
5
6
7
8
# 4. 查看容器镜像
crictl images | head -10

# 5. 检查第一个容器的详细信息
crictl inspect $(crictl ps -q | head -1)

# 6. 退出节点容器
exit

image-20260310171712946

为什么选择控制平面节点?

  • 运行 API Server、etcd、scheduler 等核心组件
  • 容器数量更多,代表性更强
  • 可以同时观察系统组件和业务容器的运行时状态

命令详解:

crictl ps

  • 显示当前正在运行的容器(包括pause容器和业务容器)
  • 显示容器ID、镜像、状态、创建时间、Pod归属等

crictl images

  • 显示节点本地缓存的所有容器镜像
  • 显示镜像仓库、标签、ID、大小等信息

crictl inspect <container-id>

  • 显示容器的完整配置和运行时信息
  • 包含环境变量、挂载卷、网络配置、资源限制等
    **当前状态:**使用 containerd 作为容器运行时,支持 CRI 接口

8.5 附加组件(Add-ons)

常以 Pod 形式部署在集群内,提供扩展能力。

8.5.1 DNS 服务

作用:为 Service/Pod 提供集群内 DNS 解析。

在 Goat 环境中的体现

1
2
3
4
5
6
7
8
# 查看 DNS 服务
kubectl get svc -n kube-system | grep dns

# 查看 DNS Pod
kubectl get pods -n kube-system | grep coredns

# 测试 DNS 解析
kubectl run test-dns --image=busybox --rm -it -- nslookup kubernetes-goat-home-service.default.svc.cluster.local

**当前状态:**CoreDNS 正常运行,提供集群内 DNS 服务

8.5.2 网络插件

作用:实现 Pod 间通信和网络策略。

在 Goat 环境中的体现

1
2
3
4
5
6
7
8
9
10
# 查看网络插件(实际使用的是 kindnet)
kubectl get pods -n kube-system | grep kindnet

# 查看网络策略
kubectl get networkpolicies -A

# 测试 Pod 间通信
kubectl exec kubernetes-goat-home-deployment-cd46cd955-xsz9c -n default -- nc -zv metadata-db.default.svc.cluster.local 80
kubectl exec kubernetes-goat-home-deployment-cd46cd955-xsz9c -n default -- wget -qO- --timeout=5 http://metadata-db.default.svc.cluster.local:80

image-20260310180711596

当前网络通信详解:

使用的网络插件:kindnet

  • kindnet:Kind 集群默认的简单网络插件
  • 运行位置:每个节点都有一个 kindnet Pod
  • 功能:提供基本的 Pod 间通信能力
  • 特点:轻量级,适合开发测试环境

网络架构:

  • Pod 网络段:10.244.1.0/24(工作节点)
  • Pod 网络段:10.244.0.0/24(控制平面)
  • Service 网络:10.96.0.0/12
  • 通信方式:通过 CNI (Container Network Interface) 实现

8.5.3 存储插件

作用:提供持久化存储能力。

在 Goat 环境中的体现

1
2
3
4
5
6
7
8
# 查看存储插件
kubectl get pods -n local-path-storage

# 查看存储类
kubectl get storageclass

# 查看存储卷
kubectl get pv,pvc -A

image-20260311005843205

**当前状态:**配置了 local-path-provisioner 但未实际使用。

存储配置详情:

  • 供应器Podlocal-path-provisioner-67b8995b4b-24xtc (运行中)
  • StorageClassstandard (default) 使用 rancher.io/local-path 供应器
  • 回收策略:Delete(PVC删除时自动清理PV)
  • 绑定模式:WaitForFirstConsumer(延迟绑定,等待Pod使用时再分配)
  • 卷扩展:false(不支持运行时扩容)
  • 实际使用:0个PV,0个PVC(Goat环境的所有应用都是无状态的,无需持久存储)

8.6 环境安全分析

8.6.1 RBAC 权限检查

查看角色定义
1
2
# 查看角色定义
kubectl get roles,clusterroles -A | grep -v system

image-20260311101052123

Goat环境的RBAC角色配置:

Role(命名空间级别角色):

  • big-monolith/secret-reader:允许读取big-monolith命名空间的Secret
  • kube-public/kubeadm:bootstrap-signer-clusterinfo:kubeadm引导签名角色
  • local-path-storage/local-path-provisioner-role:本地存储供应器角色

ClusterRole(集群级别角色):

  • admin:管理员角色,具有命名空间内大部分资源的管理权限
  • cluster-admin:集群管理员,拥有集群级别的完全权限
  • edit:编辑者角色,可以修改大部分资源但不能管理角色
  • view:查看者角色,只读权限
  • kindnet:网络插件kindnet的角色
  • kubeadm:get-nodes:kubeadm获取节点信息的角色
  • local-path-provisioner-role:本地存储供应器的集群角色

RBAC配置分析:

  • Goat环境配置了基本的RBAC角色,但主要是为系统组件和存储供应器服务
  • 没有看到专门为Goat业务应用配置的自定义角色
  • 安全检查时需要验证是否有过度权限的角色绑定
查看角色绑定
1
2
# 查看角色绑定
kubectl get rolebindings,clusterrolebindings -A | grep -v system

image-20260311101156810

查看服务账户
1
2
# 查看服务账户
kubectl get serviceaccounts -A

image-20260311101321228

Goat环境的角色绑定配置:

RoleBinding(命名空间级别绑定):

  • big-monolith/secret-reader-bindingRole/secret-reader

    • 绑定对象:big-monolith命名空间
    • 权限范围:读取该命名空间的Secret
  • kube-public/kubeadm:bootstrap-signer-clusterinfoRole/kubeadm:bootstrap-signer-clusterinfo

    • 绑定对象:kube-public命名空间
    • 权限范围:kubeadm引导签名权限
  • local-path-storage/local-path-provisioner-bindRole/local-path-provisioner-role

    • 绑定对象:local-path-storage命名空间
    • 权限范围:本地存储供应权限

ClusterRoleBinding(集群级别绑定):

  • cluster-adminClusterRole/cluster-admin (多个绑定)

    • 绑定对象:集群管理员权限
    • 权限范围:集群完全控制权限
  • kindnetClusterRole/kindnet

    • 绑定对象:网络插件kindnet
    • 权限范围:网络配置和管理权限
  • kubeadm:get-nodesClusterRole/kubeadm:get-nodes

    • 绑定对象:kubeadm工具
    • 权限范围:获取节点信息权限
  • local-path-provisioner-bindClusterRole/local-path-provisioner-role

    • 绑定对象:本地存储供应器
    • 权限范围:集群级存储供应权限

安全分析:

  • Goat环境主要为系统组件和服务配置了必要的权限
  • cluster-admin权限被多个对象绑定,可能存在权限过大的风险
  • 业务应用(如big-monolith)的权限相对受限,符合安全原则

Goat环境的服务账户配置:

服务账户分类:

系统服务账户 (kube-system):

  • 控制器相关:deployment-controller, replicaset-controller, job-controller等(41个)
  • 网络相关:kindnet, kube-proxy
  • 存储相关:persistent-volume-binder, pvc-protection-controller
  • 安全相关:service-account-controller, token-cleaner
  • DNS相关:coredns

业务应用服务账户:

  • big-monolith/big-monolith-sa:big-monolith命名空间的专用服务账户
  • big-monolith/default:big-monolith命名空间的默认服务账户
  • secure-middleware/default:secure-middleware命名空间的默认服务账户

默认服务账户:

  • 每个命名空间都有一个default服务账户,供未指定serviceAccount的Pod使用

服务账户作用:

  1. 身份认证:Pod使用服务账户身份访问Kubernetes API
  2. 权限控制:通过RBAC绑定角色获得特定权限
  3. Secret管理:自动关联API访问令牌和CA证书
  4. 安全隔离:不同应用使用不同服务账户实现权限隔离

安全检查要点:

  • 检查default服务账户是否绑定了过多权限
  • 验证专用服务账户是否遵循最小权限原则
  • 监控服务账户令牌的使用情况

8.6.2 安全上下文审计

查找特权容器
1
2
# 查找特权容器
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.containers[*].securityContext.privileged}{"\n"}{end}' | grep -E "(true|null)$"

image-20260311113539463

命令解析:

  • 数据提取:使用JSONPath从Pod spec中提取privileged字段
  • 格式化输出:Pod名称 → 命名空间 → 特权状态
  • 条件筛选:只显示privileged=true或null的容器

安全分析:

  • 系统组件特权(合理):kube-proxy需要配置iptables规则,必需的网络权限
  • 业务应用特权(潜在风险):health-check和system-monitor作为Goat靶场应用,可能故意设置为特权以演示安全漏洞
  • 安全影响:特权容器可以访问宿主机文件系统、内核功能,可能导致容器逃逸
查找主机路径挂载
1
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.volumes[*].hostPath.path}{"\n"}{end}' | grep -v "^\s*$"

image-20260311113749532

主机路径挂载检查结果:

发现以下Pod使用了hostPath卷挂载(存在安全风险):

高风险挂载:

  • system-monitor-deployment (default): 挂载整个根目录 /

    • 安全风险:可以访问所有宿主机文件,潜在的容器逃逸风险
    • 可能用途:作为Goat靶场故意设置的安全漏洞演示
  • health-check-deployment (default): 挂载containerd socket /run/containerd/containerd.sock

    • 安全风险:可以通过containerd API控制容器运行时
    • 可能用途:健康检查功能需要访问容器运行时状态

系统组件挂载(合理):

  • etcd: /etc/kubernetes/pki/etcd /var/lib/etcd - 证书和数据存储
  • kube-apiserver: 多个证书和配置路径 - API服务所需
  • kube-proxy: /run/xtables.lock /lib/modules - 网络规则配置
  • kindnet: CNI配置和内核模块 - 网络插件所需

安全分析:

  • hostPath卷允许Pod访问宿主机文件系统
  • 过度挂载可能导致容器逃逸或数据泄露
  • 应遵循最小权限原则,只挂载必需的路径
查找未设置资源限制的容器
1
2
# 查找未设置资源限制的容器
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.containers[*].resources}{"\n"}{end}' | grep -E "(\{\}|\{\s*\})"

image-20260311124143868

未设置资源限制的容器分析

从输出可以看到以下容器未设置资源限制(resources字段为空 {}):

发现的未设置资源限制容器:

  • hunger-check-deployment-5488f8b86c-6tkmh (big-monolith命名空间)
  • batch-check-job-5hbfj (default命名空间)
  • hidden-in-layers-rh6pp (default命名空间)
  • kube-proxy-* (kube-system命名空间)
  • local-path-provisioner-* (local-path-storage命名空间)
  • cache-store-deployment-* (secure-middleware命名空间)

安全风险分析:

  • 资源耗尽攻击:恶意容器可能消耗大量CPU/内存,导致节点资源耗尽
  • DoS攻击:单个容器可能影响整个节点的稳定性
  • 服务质量下降:其他正常Pod因资源竞争而性能下降
  • 成本控制缺失:无法限制资源使用,可能导致云资源费用超支

推荐防护措施:

  • 为所有容器设置 resources.limitsresources.requests
  • 使用ResourceQuota限制命名空间总资源使用
  • 实施LimitRange设置默认资源限制
  • 监控资源使用情况,及时发现异常消耗

8.6.3 网络安全检查

查看网络策略
1
2
# 查看网络策略
kubectl get networkpolicies -A

image-20260311135518281

原因解释:

  • No resources found 表示集群中没有配置任何网络策略(Network Policies)
  • 这是Kubernetes的默认行为:默认允许所有Pod间通信

安全风险:

  • 横向移动攻击:攻击者可以从受感染的Pod访问其他所有服务
  • 数据泄露:Pod之间没有任何网络边界限制
  • 服务枚举:攻击者可以轻松发现和访问内部服务

配置建议:

  • 为敏感应用配置网络策略,只允许必要的通信
  • 使用 default deny 策略作为安全基线
  • 考虑结合服务网格实现更细粒度的流量控制

这个检查结果实际上暴露了一个重要的安全问题:在没有网络策略的情况下,整个集群的Pod网络是完全开放的,这为攻击者提供了极大的活动空间。

分析服务暴露情况
1
kubectl get svc -A | grep -E "(NodePort|LoadBalancer)"

image-20260311135649898

从输出可见,当前集群发现了一个通过 NodePort 类型暴露的服务:

  • internal-proxy-info-app-servicedefault 命名空间)
  • Service 类型为 NodePort
  • 集群内服务端口为 5000
  • 对外暴露的节点端口为 30003

这说明该服务不仅可以被集群内部访问,还可以通过任意工作节点的 IP 加上端口 30003 进行访问(前提是节点网络和防火墙规则允许该端口连通)。例如,外部用户可能通过 http://<节点IP>:30003 访问到该服务。

安全含义:

  • NodePort 会把服务暴露到每个节点的指定端口上,扩大服务可达范围
  • 如果该服务本应仅供集群内部调用,那么这种暴露方式会增加被扫描、探测和攻击的可能性
  • 一旦服务本身存在认证缺陷、信息泄露或命令执行类漏洞,攻击者就可能直接从节点入口发起利用

风险分析:

  • 攻击面扩大:服务从“仅集群内部可见”变成“可能被外部网络直接访问”
  • 敏感接口暴露:如果这是内部代理、信息查询或管理类服务,暴露后更容易泄露内部结构和业务信息
  • 横向渗透入口:攻击者可将该服务作为进入集群业务面的初始落点
检查 Pod间网络隔离
1
2
# 检查 Pod 间网络隔离
kubectl run test-network --image=busybox --rm -it -- wget -qO- http://internal-proxy-info-app-service.default.svc.cluster.local:5000

8.6.4 配置安全审计

检查Secret内容
1
2
# 检查 Secret 内容
kubectl get secrets -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.type}{"\n"}{end}'

image-20260311140047848

从输出可以看到,当前集群中发现了以下 Secret

  • vaultapikeybig-monolith 命名空间),类型为 Opaque
  • webhookapikeybig-monolith 命名空间),类型为 Opaque
  • goatvaultdefault 命名空间),类型为 Opaque
  • sh.helm.release.v1.metadata-db.v1default 命名空间),类型为 helm.sh/release.v1

这说明集群里既存在业务相关的敏感数据,也存在 Helm 发布过程自动生成的元数据。

类型说明:

  • Opaque 是最常见的通用类型 Secret,通常用于保存 API Key、密码、Token、证书片段等自定义敏感信息
  • helm.sh/release.v1 是 Helm 在安装或升级 Chart 时自动创建的发布记录,里面主要保存 Helm Release 的元数据,不一定直接是业务凭据,但同样不应被随意暴露

结合名称进行分析:

  • vaultapikeywebhookapikey 这类名称明显带有 apikey,说明其中很可能保存的是访问外部系统或内部服务所需的认证凭据
  • goatvault 名称表明它也可能保存了某类机密配置或凭据
  • 这些对象虽然叫做 Secret,但 Kubernetes 默认只是以 Base64 编码存储,并不是强加密;如果拥有足够权限,仍然可以被读取和解码

安全含义:

  • 一旦攻击者获得读取 Secret 的 RBAC 权限,就可能直接获取 API Key、Token 或密码
  • 如果应用把这些 Secret 挂载进环境变量或文件系统,容器被入侵后也可能进一步导致凭据泄露
  • 命名清晰的 Secret 往往会帮助攻击者快速定位高价值目标

审计建议:

  • 继续检查这些 Secret 是否被业务 Pod 使用,以及以什么方式挂载
  • 审查哪些 ServiceAccount、用户或角色具备读取 Secret 的权限
  • 对高敏感 Secret 启用更严格的访问控制,并考虑结合外部密钥管理系统
  • 避免在日志、镜像、ConfigMap 或环境变量中重复暴露同一份敏感信息
分析 ConfigMap内容
1
2
# 分析 ConfigMap 内容
kubectl get configmaps -A

image-20260311140213614

从输出可以看到,当前集群中的 ConfigMap 主要以 Kubernetes 系统组件自动生成的配置为主,暂时没有看到明显的业务自定义配置项大量暴露出来。

主要发现如下:

  • 多个命名空间中都存在 kube-root-ca.crt,如 big-monolithdefaultkube-systemlocal-path-storagesecure-middleware
  • kube-public 命名空间中存在 cluster-info
  • kube-system 命名空间中存在 corednsextension-apiserver-authenticationkube-proxykubeadm-configkubelet-config 等系统级配置
  • local-path-storage 命名空间中存在 local-path-config

内容说明:

  • kube-root-ca.crt 通常用于向 Pod 提供集群 CA 证书,属于正常的系统配置
  • cluster-info 一般保存集群访问信息,常用于集群初始化或公开发现
  • corednskube-proxykubeadm-configkubelet-config 等都属于 Kubernetes 控制面或基础设施组件依赖的配置
  • local-path-config 则与本地存储供应器的工作方式有关,也属于基础设施配置

安全审计意义:

  • 这类 ConfigMap 大多不是直接的凭据存储位置,但它们可能泄露集群架构、网络配置、DNS 规则、代理行为或节点参数
  • 攻击者在获得读取权限后,可以利用这些配置信息更快理解集群内部结构,辅助后续横向移动或权限提升
  • 尤其像 kubeadm-configkubelet-configcoredns 这类对象,往往可以帮助攻击者了解控制面部署方式、DNS 解析策略和节点运行参数

需要注意的一点:

  • ConfigMap 适合保存普通配置,不适合存放密码、Token、API Key 等敏感数据
  • 如果在审计中发现业务把密钥、口令或证书私钥放进 ConfigMap,应视为高风险问题,应该迁移到 Secret 或外部密钥管理系统
检查环境变量中的敏感信息
1
2
# 检查环境变量中的敏感信息
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.containers[*].env[*].name}{"\n"}{end}' | grep -i -E "(key|secret|password|token)"

image-20260311142357351

从输出可以看到,当前命中了一个疑似敏感环境变量:

  • Pod:system-monitor-deployment-866f697c75-2wzd4
  • 命名空间:default
  • 环境变量名:K8S_GOAT_VAULT_KEY

这个变量名中包含 KEY,并且带有 VAULT 字样,说明它很可能用于保存访问某个密钥库、保险库服务或内部敏感资源所需的认证信息。即使这里只看到了变量名,没有直接看到变量值,也已经足以说明该 Pod 中存在高价值凭据或敏感配置入口。

安全含义:

  • 把密钥类信息放入环境变量是常见做法,但如果容器被入侵,攻击者往往可以直接读取进程环境变量
  • 某些调试命令、错误日志、崩溃转储或应用配置输出,也可能意外泄露环境变量内容
  • 如果该变量实际对应的是 API Key、访问令牌或解密密钥,那么泄露后可能进一步导致数据访问、横向移动或权限提升

为什么要重点关注:

  • 环境变量名本身已经暴露了用途,攻击者可以据此快速定位关键配置
  • 与挂载文件相比,环境变量更容易在运行时被应用、脚本或诊断工具直接读取
  • 如果该变量来源于 Secret,还需要继续确认其挂载方式是否合理;如果它是明文直接写在 Pod 配置中,则风险更高

8.7 授权安全评估常用审计命令

这一节主要面向 Kubernetes 安全学习和授权测试场景,重点不是“如何利用”,而是当某个工作负载已经失陷时,如何从防守和评估角度快速判断风险会不会进一步扩大到命名空间、节点甚至整个集群。

建议按以下几个方向进行检查:

  • 当前 Pod 或命名空间具备什么身份和权限
  • 是否暴露了 Secret、环境变量、挂载文件等敏感信息
  • 是否存在 privilegedhostPath、容器运行时 socket 等高危配置
  • 网络策略、服务暴露、RBAC 是否会导致横向风险扩大
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
# 1. 环境快速概览:查看所有工作负载和服务分布
kubectl get all -A

# 2. 查看 Pod 使用的 ServiceAccount
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.serviceAccountName}{"\n"}{end}'

# 3. 检查是否自动挂载 ServiceAccount Token
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.automountServiceAccountToken}{"\n"}{end}'

# 4. 审计高危 Pod 配置:privileged 和 hostPath
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.containers[*].securityContext.privileged}{"\t"}{.spec.volumes[*].hostPath.path}{"\n"}{end}'

# 5. 检查 hostNetwork、hostPID、hostIPC 等高风险配置
kubectl get pods -A -o yaml | grep -E "hostNetwork:|hostPID:|hostIPC:"

# 5.2 结构化查看 Pod 是否启用了主机级命名空间
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.hostNetwork}{"\t"}{.spec.hostPID}{"\t"}{.spec.hostIPC}{"\n"}{end}'

# 6. 检查敏感环境变量名称
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.containers[*].env[*].name}{"\n"}{end}' | grep -i -E "(key|secret|password|token)"

# 7. 查看 Secret 类型分布
kubectl get secrets -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.type}{"\n"}{end}'

# 8. 查看 ConfigMap 分布,识别是否有业务配置被暴露
kubectl get configmaps -A

# 9. 查看网络策略是否缺失
kubectl get networkpolicies -A

# 10. 查看对外暴露的服务
kubectl get svc -A | grep -E "(NodePort|LoadBalancer)"

# 11. 查看角色绑定和集群角色绑定
kubectl get rolebindings,clusterrolebindings -A

# 12. 验证某个 ServiceAccount 的权限边界
kubectl auth can-i --as=system:serviceaccount:<namespace>:<serviceaccount> --list -n <namespace>

风险判断思路:

  • 如果业务 Pod 暴露了 Secret、敏感环境变量或 ServiceAccount Token,说明已经具备进一步信息收集的基础
  • 如果该身份对应的 RBAC 权限过大,例如可以读取 secrets、创建 pods、修改 deployments,风险就可能从单个 Pod 扩大到整个命名空间
  • 如果同时存在 privilegedhostPathhostNetwork、运行时 socket 挂载等问题,则需要重点关注是否会扩大到节点层面
  • 如果集群中没有 NetworkPolicy,并且存在不必要的 NodePort / LoadBalancer,那么东西向和南北向的攻击面都会明显增加

审计建议:

  • 先识别“身份材料”与“权限边界”,再看运行时配置和网络暴露
  • 重点关注系统命名空间、基础设施组件、监控组件和中间件命名空间
  • 把发现的问题按“凭据暴露、权限过大、运行时高危配置、网络暴露”四类进行整理,便于后续复盘和加固

参考