6292 字
31 分钟
01.Kubernetes 学习笔记:基础概念与 Pod 详解

本篇笔记记录 k8s 的核心概念、架构组件,以及 Pod 的详细使用。环境是一主两从的集群,镜像从私有 Harbor 仓库拉取。

环境说明#

集群已提前搭建完成,参考这篇文章

主机IP用途
k8s-master192.168.100.20控制平面节点
k8s-node1192.168.100.21worker 节点
k8s-node2192.168.100.22worker 节点
harbor192.168.100.14私有镜像仓库

Harbor 仓库信息:

  • 域名:reg.westos.org
  • 镜像地址:reg.westos.org/library/

已经提前搭建k8s集群环境,若没有请参考 ../搭建k8s集群

主机ip用途
k8s-master192.168.100.20k8s主节点
k8s-node1192.168.100.21work节点
k8s-node2192.168.100.22work节点
harbor192.168.100.14私有镜像仓库

harbor仓库域名为reg.westos.org 镜像地址为reg.westos.org/library/


一、k8s介绍#

第一部分:K8s是什么,解决了什么问题,设计理念和思想#

1.1 K8s是什么#

Kubernetes(K8s) 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。

  • 名称由来:Kubernetes 源于希腊语,意为”舵手”或”领航员”,缩写K8s是因为K和s之间有8个字母
  • 起源:Google基于其内部容器编排系统Borg的经验,于2014年开源
  • 当前状态:已成为云原生应用编排的事实标准,由CNCF(Cloud Native Computing Foundation)维护

1.2 解决了什么问题#

传统部署方式的痛点:

  1. 资源利用率低

    • 物理机部署:一台服务器只运行一个应用,资源浪费严重
    • 环境隔离差:多个应用共享一台服务器,相互影响
  2. 扩展困难

    • 手动扩容:需要人工介入,响应慢
    • 弹性伸缩难:无法根据负载自动调整
  3. 运维复杂

    • 服务发现困难:需要手动配置IP和端口
    • 负载均衡配置繁琐
    • 应用更新风险高:停机时间长,回滚困难

K8s的解决方案:

  1. 自动化容器编排

    • 自动部署和调度容器到合适的节点
    • 自动重启失败的容器
    • 自动替换和重新调度故障节点上的容器
  2. 服务发现和负载均衡

    • 自动分配DNS名称和IP地址
    • 内置负载均衡,自动分发流量
  3. 自动扩缩容

    • 水平扩展:根据CPU使用率或自定义指标自动增减Pod数量
    • 垂直扩展:调整容器资源限制
  4. 自动化发布和回滚

    • 滚动更新:逐步替换旧版本,零停机
    • 自动回滚:检测到问题自动恢复到上一版本
  5. 存储编排

    • 自动挂载存储系统(本地存储、云存储等)
  6. 自我修复

    • 健康检查:定期检测容器健康状态
    • 自动重启不健康的容器

1.3 设计理念和思想#

核心设计理念:

  1. 声明式API

    • 用户只需要声明”期望状态”(Desired State),无需关心如何实现
    • K8s会持续工作,使”当前状态”(Current State)趋向于”期望状态”
    • 例如:声明需要3个副本,K8s会自动创建、维护这3个副本
  2. 控制器模式(Controller Pattern)

    for {
    实际状态 := 获取集群实际状态()
    期望状态 := 获取用户定义的期望状态()
    if 实际状态 == 期望状态 {
    什么都不做
    } else {
    执行编排动作,将实际状态调整为期望状态
    }
    }
  3. 松耦合架构

    • 各个组件独立运行,通过API Server通信
    • 组件可以独立升级和替换
  4. 资源对象化

    • 一切皆对象:Pod、Service、Deployment等都是资源对象
    • 通过YAML/JSON文件描述资源
    • 统一的API接口管理所有资源
  5. Label和Selector机制

    • Label:键值对标签,附加到资源对象上
    • Selector:通过标签选择器查询和关联资源
    • 实现松耦合的资源关联
  6. 分层架构

    • 应用层:用户应用
    • 编排层:K8s核心功能
    • 资源层:计算、存储、网络
    • 基础设施层:物理机、虚拟机、云服务

设计思想:

  • 可移植性:跨云平台、跨数据中心运行
  • 可扩展性:支持插件机制,可自定义资源和控制器
  • 自动化:最小化人工干预
  • 高可用:组件冗余,故障自动恢复

第二部分:K8s架构、组件及其关系#

2.1 K8s整体架构#

K8s采用主从架构(Master-Worker),分为控制平面(Control Plane)工作节点(Worker Node)

graph TB subgraph Master["Control Plane (Master)"] API["API Server"] Scheduler["Scheduler"] Controller["Controller Manager"] etcd["etcd"] end subgraph Node1["Worker Node1"] K1["Kubelet"] P1["Kube-proxy"] R1["Container Runtime"] Pods1["Pods"] end subgraph Node2["Worker Node2"] K2["Kubelet"] P2["Kube-proxy"] R2["Container Runtime"] Pods2["Pods"] end subgraph Node3["Worker Node3"] K3["Kubelet"] P3["Kube-proxy"] R3["Container Runtime"] Pods3["Pods"] end Master --> Node1 Master --> Node2 Master --> Node3

2.2 核心组件概览#

Master节点组件(控制平面):

组件作用
API Server集群的统一入口,提供RESTful API
etcd分布式键值存储,保存集群所有数据
Scheduler负责Pod调度到合适的Node节点
Controller Manager运行各种控制器,维护集群状态
Cloud Controller (可选)与云平台交互

Worker节点组件:

组件作用
Kubelet管理Pod和容器的生命周期
Kube-proxy实现Service的网络代理和负载均衡
Container Runtime容器运行时(如Docker、containerd)

附加组件(Add-ons):

组件作用
CoreDNS集群内部DNS服务
DashboardWeb UI管理界面
CNI插件网络插件(如Calico、Flannel)
Metrics Server资源监控

2.3 组件之间的关系和工作流程#

典型的Pod创建流程:

  1. 用户提交

    kubectl create -f pod.yaml
    • kubectl将请求发送到API Server
  2. API Server处理

    • 验证请求合法性
    • 将Pod信息写入etcd
    • 返回确认给用户
  3. Scheduler监听

    • 通过Watch机制监听到新Pod(状态为Pending,未分配节点)
    • 执行调度算法,选择最优节点
    • 将绑定信息(Pod → Node)写回API Server
  4. API Server更新

    • 更新Pod信息,指定运行节点
    • 将数据持久化到etcd
  5. Kubelet监听

    • 对应节点的Kubelet监听到分配给自己的Pod
    • 调用Container Runtime创建容器
    • 定期上报Pod状态给API Server
  6. Controller Manager监控

    • 持续监控Pod状态
    • 如果Pod异常,触发重建流程
  7. Kube-proxy配置

    • 如果Pod属于某个Service,Kube-proxy更新iptables/ipvs规则
    • 实现服务发现和负载均衡

组件通信原则:

  • 所有组件只与API Server通信,不直接互相通信
  • API Server是唯一直接操作etcd的组件
  • 使用List-Watch机制实现事件驱动:
    • List:获取资源列表
    • Watch:监听资源变化

第三部分:各个组件的详细功能和作用#

3.1 API Server(kube-apiserver)#

核心功能:

  1. 集群管理的统一入口

    • 提供RESTful API接口
    • 所有操作都要通过API Server
  2. 认证、授权、准入控制

    • 认证(Authentication):验证用户身份(证书、Token、ServiceAccount)
    • 授权(Authorization):验证操作权限(RBAC、ABAC)
    • 准入控制(Admission Control):修改或拒绝请求(如资源配额检查)
  3. 资源操作接口

    • CRUD操作:创建、读取、更新、删除资源
    • Watch接口:实时监听资源变化
  4. 数据持久化

    • 将资源状态写入etcd
    • 缓存机制提高性能
  5. 集群状态查询

    • 提供集群当前状态的视图

特点:

  • 无状态:可以水平扩展多个实例
  • 高可用:通过负载均衡器对外提供服务

3.2 etcd#

核心功能:

  1. 分布式键值存储

    • 存储K8s所有集群数据
    • 保存资源对象的定义和状态
  2. 一致性保证

    • 使用Raft协议保证数据一致性
    • 支持分布式锁
  3. Watch机制

    • 支持高效的事件监听
    • 实现K8s的响应式架构

存储的数据:

  • Pod、Service、Deployment等资源对象
  • 节点信息
  • 配置信息(ConfigMap、Secret)
  • 集群状态

部署建议:

  • 生产环境建议3-5个节点的集群
  • 定期备份数据
  • 使用SSD提高性能

3.3 Scheduler(kube-scheduler)#

核心功能:

  1. Pod调度

    • 为新创建的Pod选择合适的节点
  2. 调度算法

    预选(Predicate): 过滤不符合条件的节点

    • PodFitsResources:节点资源是否充足
    • PodFitsHostPorts:端口是否冲突
    • NodeSelector:节点标签匹配
    • NodeAffinity:节点亲和性

    优选(Priority): 对预选节点打分,选择最优节点

    • LeastRequestedPriority:选择资源使用率最低的节点
    • BalancedResourceAllocation:CPU和内存使用率均衡
    • NodeAffinityPriority:节点亲和性得分
  3. 高级调度策略

    • NodeSelector:指定节点标签
    • NodeAffinity:节点亲和性(硬性/软性要求)
    • PodAffinity:Pod亲和性(将相关Pod调度到一起)
    • PodAntiAffinity:Pod反亲和性(将Pod分散到不同节点)
    • Taints和Tolerations:污点和容忍度(排斥特定Pod)

调度流程:

监听未调度的Pod → 预选过滤节点 → 优选打分排序 → 选择最优节点 → 绑定Pod到节点

3.4 Controller Manager(kube-controller-manager)#

核心功能:

运行多个控制器,每个控制器负责维护特定资源的期望状态。

主要控制器:

  1. Replication Controller / ReplicaSet Controller

    • 确保指定数量的Pod副本运行
    • Pod数量不足时创建,过多时删除
  2. Deployment Controller

    • 管理ReplicaSet,实现声明式更新
    • 支持滚动更新和回滚
  3. StatefulSet Controller

    • 管理有状态应用
    • 提供稳定的网络标识和持久化存储
  4. DaemonSet Controller

    • 确保每个节点运行一个Pod副本
    • 常用于日志收集、监控代理
  5. Job Controller / CronJob Controller

    • Job:运行一次性任务
    • CronJob:定时任务
  6. Service Controller

    • 监听Service对象,创建Endpoint
    • 与云平台交互创建LoadBalancer
  7. Namespace Controller

    • 删除namespace时清理相关资源
  8. Node Controller

    • 监控节点状态
    • 节点异常时驱逐Pod
  9. Endpoint Controller

    • 维护Service和Pod之间的映射关系

工作原理:

控制循环:
监听资源变化 → 比较期望状态和实际状态 → 执行调谐动作 → 更新资源状态

3.5 Kubelet#

核心功能:

  1. Pod生命周期管理

    • 接收API Server分配的Pod
    • 调用Container Runtime创建容器
    • 管理容器的启动、停止、重启
  2. 容器健康检查

    • Liveness Probe:存活探针,检测容器是否运行,失败则重启
    • Readiness Probe:就绪探针,检测容器是否准备好接收流量
    • Startup Probe:启动探针,检测容器应用是否启动
  3. 资源监控

    • 监控Pod和容器的资源使用情况(CPU、内存)
    • 通过cAdvisor收集数据
  4. Volume管理

    • 挂载Volume到容器
    • 支持多种存储类型
  5. 状态上报

    • 定期向API Server上报节点和Pod状态
  6. 镜像管理

    • 拉取镜像
    • 镜像垃圾回收

Static Pod:

  • Kubelet可以直接管理本地的YAML文件(通常在/etc/kubernetes/manifests/)
  • 不受API Server控制,常用于部署控制平面组件

3.6 Kube-proxy#

核心功能:

  1. Service网络代理

    • 实现Service的虚拟IP(ClusterIP)
    • 将流量转发到后端Pod
  2. 负载均衡

    • 在多个Pod副本之间分发流量
  3. 工作模式

    iptables模式(默认):

    • 通过iptables规则实现
    • 性能好,但规则多时性能下降
    • 随机负载均衡

    ipvs模式(推荐):

    • 使用IPVS内核模块
    • 支持更多负载均衡算法(rr、lc、dh等)
    • 性能更好,适合大规模集群

    userspace模式(已废弃):

    • 在用户空间代理,性能差
  4. Service类型支持

    • ClusterIP:集群内部访问
    • NodePort:通过节点端口暴露服务
    • LoadBalancer:云平台负载均衡器
    • ExternalName:DNS CNAME映射

工作流程:

监听Service和Endpoint变化 → 生成代理规则(iptables/ipvs) → 流量转发到后端Pod

3.7 Container Runtime(容器运行时)#

核心功能:

  1. 容器生命周期管理

    • 创建、启动、停止、删除容器
  2. 镜像管理

    • 拉取、存储、删除镜像

常见运行时:

  • Docker:最早支持,功能完善
  • containerd:Docker的核心组件,轻量级(推荐)
  • CRI-O:专为K8s设计的轻量级运行时

CRI接口:

  • K8s通过CRI(Container Runtime Interface)与运行时通信
  • 解耦K8s和具体的容器实现

3.8 CoreDNS#

核心功能:

  1. 集群内部DNS

    • 为Service提供DNS解析
    • 格式:<service-name>.<namespace>.svc.cluster.local
  2. 服务发现

    • Pod通过Service名称访问服务
    • 无需知道具体IP地址

示例:

# Service: nginx-service 在 default namespace
# 其他Pod可以通过以下方式访问:
nginx-service
nginx-service.default
nginx-service.default.svc.cluster.local

3.9 CNI网络插件#

核心功能:

  1. Pod网络通信

    • 为每个Pod分配IP地址
    • 实现Pod之间的网络互通
  2. 网络策略

    • 实现网络隔离和访问控制

常见网络插件:

  • Flannel:简单易用,适合小规模集群
  • Calico:功能强大,支持网络策略,性能好
  • Weave:易于部署,支持加密
  • Cilium:基于eBPF,高性能

网络模型要求:

  • 所有Pod可以互相通信(无需NAT)
  • 所有Node可以与所有Pod通信
  • Pod看到的自己的IP和其他Pod看到的一致

总结#

K8s核心价值:

  • 自动化容器编排和管理
  • 声明式配置,用户只需关心”要什么”
  • 自我修复,高可用

架构特点:

  • 主从架构,职责清晰
  • 控制器模式,持续调谐
  • 所有组件通过API Server通信

关键组件协作:

用户 → kubectl → API Server ← → etcd
┌──────────────┼──────────────┐
↓ ↓ ↓
Scheduler Controller Manager Kubelet
Container Runtime

通过这些组件的协同工作,K8s实现了强大的容器编排能力,成为云原生时代的基石。

二、Pod详解#

1. Pod设计理念与基本概念#

1.1 Pod是什么#

Pod是Kubernetes中最小的可部署单元,是一组(一个或多个)容器的集合。

核心特点:

  • 共享网络:Pod内的所有容器共享同一个网络命名空间

    • 共享同一个IP地址和端口空间
    • 容器之间可以通过localhost通信
  • 共享存储:Pod内的容器可以共享Volume

    • 实现容器间数据共享
    • 持久化数据存储
  • 生命周期一致:Pod内的容器同生共死

    • 一起调度到同一节点
    • 一起启动和停止

1.2 为什么需要Pod#

设计原因:

  1. 容器间紧密协作

    • 某些应用需要多个容器协同工作
    • 例如:主应用容器 + 日志收集容器 + 配置代理容器
  2. 简化网络通信

    • Pod内容器通过localhost通信,无需复杂的网络配置
    • 对外呈现为一个整体,只有一个IP地址
  3. 资源共享

    • 容器间可以共享文件、IPC、网络等资源

Pod的两种使用模式:

  1. 单容器Pod(最常见)

    Pod
    ├── Container (应用容器)
  2. 多容器Pod(Sidecar模式)

    Pod
    ├── Container 1 (主应用容器)
    ├── Container 2 (Sidecar容器 - 日志收集)
    └── Container 3 (Sidecar容器 - 配置同步)

1.3 Pod的组成#

一个Pod包含以下部分:

Pod
├── Pause容器(基础容器/根容器)
│ └── 负责创建网络命名空间,维护Pod的网络
├── Init容器(可选)
│ └── 初始化容器,在主容器启动前运行,用于初始化工作
└── 应用容器(一个或多个)
├── 主容器
└── Sidecar容器(可选)

Pause容器:

  • 每个Pod都有一个隐藏的Pause容器(也叫Infra容器)
  • 占用极少资源,镜像很小(几百KB)
  • 作用:
    • 创建并持有网络命名空间
    • 其他容器加入到这个网络命名空间
    • 即使应用容器重启,Pod的IP也不会变

2. Pod的创建过程、状态、生命周期和探针#

2.1 Pod的创建过程#

完整流程:

1. 用户提交Pod定义
kubectl apply -f pod.yaml
2. API Server接收请求
- 验证YAML格式和权限
- 写入etcd(状态:Pending)
3. Scheduler调度
- 选择合适的Node节点
- 更新Pod信息(绑定Node)
4. Kubelet创建Pod
- 拉取镜像
- 创建Pause容器
- 运行Init容器(如果有)
- 运行主容器
5. 容器运行(状态:Running)
- 执行健康检查
- 上报状态到API Server
6. Pod完成或失败(状态:Succeeded/Failed)

2.2 Pod的生命周期#

Pod Phase(阶段):

阶段说明
PendingPod已创建,但容器还未运行(可能在拉取镜像或调度中)
RunningPod已绑定到节点,所有容器已创建,至少一个容器在运行
SucceededPod中所有容器成功终止,且不会重启
FailedPod中所有容器终止,至少一个容器异常退出
Unknown无法获取Pod状态(通常是节点通信问题)

容器状态(Container State):

状态说明
Waiting容器等待中(拉取镜像、等待Init容器等)
Running容器正在运行
Terminated容器已终止

重启策略(RestartPolicy):

策略说明适用场景
Always容器终止后总是重启(默认策略)长期运行的服务
OnFailure容器异常终止时才重启(退出码非0)批处理任务
Never容器终止后不重启一次性任务

2.3 容器探针(Probe)#

探针是Kubelet对容器执行的定期诊断,用于检测容器的健康状况。

三种探针类型:

  1. Liveness Probe(存活探针)

    • 作用:检测容器是否存活
    • 失败处理:重启容器
    • 使用场景:检测应用是否死锁、无响应
    • 示例:应用进程存在但卡死,需要重启恢复
  2. Readiness Probe(就绪探针)

    • 作用:检测容器是否准备好接收流量
    • 失败处理:从Service的Endpoint列表中移除该Pod
    • 使用场景:应用启动慢,需要预热;临时过载,暂时无法处理请求
    • 示例:数据库连接初始化中、缓存加载中
  3. Startup Probe(启动探针)

    • 作用:检测容器应用是否已启动
    • 失败处理:重启容器
    • 使用场景:启动慢的应用(避免Liveness探针过早杀死容器)
    • 示例:Java应用启动需要几分钟

探测方式:

方式说明示例
exec在容器内执行命令,退出码为0表示成功执行cat检查文件是否存在
httpGet发送HTTP GET请求,状态码200-399表示成功访问/health端点
tcpSocketTCP连接测试,能连接表示成功检测MySQL 3306端口是否可连接
grpc (新增)调用gRPC健康检查服务gRPC应用的健康检查

探针参数配置:

livenessProbe:
httpGet:
path: /health # 检查路径
port: 8080 # 端口
initialDelaySeconds: 30 # 容器启动后多久开始探测
periodSeconds: 10 # 探测间隔
timeoutSeconds: 5 # 探测超时时间
successThreshold: 1 # 成功阈值(连续成功多少次才算成功)
failureThreshold: 3 # 失败阈值(连续失败多少次才算失败)

探针使用建议:

  • Liveness:谨慎使用,避免频繁重启
  • Readiness:推荐使用,优雅地处理流量
  • Startup:对启动慢的应用必须配置

2.4 Init容器#

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

特点:

  • 顺序执行:多个Init容器按顺序依次运行
  • 必须成功:所有Init容器成功后,主容器才会启动
  • 独立镜像:可以使用不同的镜像

使用场景:

  1. 等待依赖服务启动(如等待数据库就绪)
  2. 初始化配置文件
  3. 下载依赖或数据
  4. 设置权限

示例:

initContainers:
- name: init-mysql
image: busybox
command: ['sh', '-c', 'until nslookup mysql; do echo waiting for mysql; sleep 2; done']

3. YAML资源清单与Pod创建#

3.1 YAML资源清单基础#

YAML文件结构:

apiVersion: v1 # API版本
kind: Pod # 资源类型
metadata: # 元数据
name: my-pod # Pod名称
labels: # 标签
app: nginx
spec: # 规格/期望状态
containers: # 容器列表
- name: nginx # 容器名称
image: nginx:1.20 # 镜像
ports: # 端口
- containerPort: 80

四个核心字段:

字段说明必需
apiVersionAPI版本(如v1、apps/v1)
kind资源类型(如Pod、Deployment)
metadata元数据(name、labels、namespace等)
spec规格说明(期望状态)

3.2 简单Pod示例#

最简单的Pod:

apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.20

带探针的Pod:

apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-with-probe
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 3

多容器Pod:

apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: app
image: myapp:1.0
ports:
- containerPort: 8080
- name: sidecar-log
image: busybox
command: ['sh', '-c', 'tail -f /var/log/app.log']
volumeMounts:
- name: log-volume
mountPath: /var/log
volumes:
- name: log-volume
emptyDir: {}

4. 实操:构建镜像并部署Pod#

4.1 准备测试环境#

在harbor机器上配置kubectl远程管理K8s集群

我们使用harbor机器(192.168.100.14)作为远程管理节点,而不是直接在master上操作,这是生产环境的最佳实践。

步骤:

  1. 在master节点上获取kubeconfig

    Terminal window
    # 在k8s-master上执行
    cat ~/.kube/config
  2. 在harbor机器上安装kubectl

    Terminal window
    # 下载kubectl
    curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
    # 安装
    chmod +x kubectl
    mv kubectl /usr/local/bin/
    # 验证
    kubectl version --client
  3. 配置kubeconfig

    Terminal window
    # 创建.kube目录
    mkdir -p ~/.kube
    # 将master的config内容复制到harbor机器
    vi ~/.kube/config
    # 粘贴master节点的config内容,修改server地址为master的IP
    # server: https://192.168.100.20:6443
    # 设置权限
    chmod 600 ~/.kube/config
    #设置k8s命令补齐
    echo "source <(kubectl completion bash)" >> ~/.bashrc
    source ~/.bashrc
  4. 测试连接

    Terminal window
    kubectl get nodes
    kubectl cluster-info

4.2 准备应用镜像#

准备两个镜像:

  1. nginx前端:连接数据库测试
  2. mysql数据库:MySQL 8.0

项目目录结构:

/root/k8s-demo/
├── nginx/
│ ├── Dockerfile
│ └── index.php
└── mysql/
└── Dockerfile

1. 创建MySQL镜像

Terminal window
mkdir -p /root/k8s-demo/mysql
cd /root/k8s-demo/mysql

Dockerfile:

FROM mysql:8.0
# 设置环境变量
ENV MYSQL_ROOT_PASSWORD=Westos123
ENV MYSQL_DATABASE=testdb
# 暴露端口
EXPOSE 3306

构建并推送:

Terminal window
# 构建镜像
docker build -t reg.westos.org/library/mysql:8.0 .
# 推送到私有仓库
docker push reg.westos.org/library/mysql:8.0

2. 创建Nginx+PHP镜像

Terminal window
mkdir -p /root/k8s-demo/nginx
cd /root/k8s-demo/nginx

Dockerfile:

FROM php:7.4-apache
# 安装mysqli扩展
RUN docker-php-ext-install mysqli
# 复制测试页面
COPY index.php /var/www/html/
# 暴露端口
EXPOSE 80
# 启动Apache
CMD ["apache2-foreground"]

index.php:

<?php
header('Content-Type: text/plain; charset=utf-8');
echo "Nginx-PHP Container\n";
echo "Hostname: " . gethostname() . "\n";
echo "Server IP: " . $_SERVER['SERVER_ADDR'] . "\n";
echo "\n";
// 数据库连接信息(稍后手动修改)
$db_host = "DB_HOST_HERE"; // 稍后替换为MySQL Pod的IP
$db_user = "root";
$db_pass = "Westos123";
$db_name = "testdb";
// 尝试连接数据库
$conn = new mysqli($db_host, $db_user, $db_pass, $db_name);
if ($conn->connect_error) {
echo "Database connection failed: " . $conn->connect_error . "\n";
} else {
echo "Database connected successfully!\n";
echo "MySQL Version: " . $conn->server_info . "\n";
}
$conn->close();
?>

构建并推送:

Terminal window
# 构建镜像
docker build -t reg.westos.org/library/nginx-php:v1 .
# 推送到私有仓库
docker push reg.westos.org/library/nginx-php:v1

4.3 创建Pod资源清单#

创建YAML文件目录:

Terminal window
mkdir -p /root/k8s-yaml
cd /root/k8s-yaml

1. mysql-pod.yaml

apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
labels:
app: mysql
spec:
containers:
- name: mysql
image: reg.westos.org/library/mysql:8.0
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "Westos123"
- name: MYSQL_DATABASE
value: "testdb"
livenessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- sh
- -c
- "mysqladmin ping -h localhost -pWestos123"
initialDelaySeconds: 10
periodSeconds: 5

2. nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-php
image: reg.westos.org/library/nginx-php:v1
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 3

4.4 部署和测试#

1. 创建MySQL Pod

Terminal window
# 创建Harbor认证Secret(如果library仓库是私有的,不配置拉取镜像会出现ImagePullBackOff错误。)
kubectl create secret docker-registry harbor-auth \
--docker-server=reg.westos.org \
--docker-username=admin \
--docker-password=12345 \
--docker-email=admin@westos.org
#认证绑定命名空间,自动授权
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-auth"}]}'
# 创建Pod
kubectl apply -f mysql-pod.yaml
# 查看Pod状态
kubectl get pods -o wide
# 查看Pod详细信息
kubectl describe pod mysql-pod
# 查看日志
kubectl logs mysql-pod

2. 获取MySQL Pod的IP地址

Terminal window
# 获取IP
kubectl get pod mysql-pod -o wide
# 假设输出:
# NAME READY STATUS RESTARTS AGE IP NODE
# mysql-pod 1/1 Running 0 1m 10.244.1.10 k8s-node1

3. 创建Nginx Pod

Terminal window
# 创建Pod
kubectl apply -f nginx-pod.yaml
# 查看状态
kubectl get pods -o wide
# 获取nginx-pod的IP(假设是10.244.2.15)

4. 进入Nginx容器修改数据库连接

Terminal window
# 进入nginx容器
kubectl exec -it nginx-pod -- bash
# 修改index.php文件,替换数据库IP
sed -i 's/DB_HOST_HERE/10.244.169.133/' /var/www/html/index.php
# 验证修改
cat /var/www/html/index.php | grep db_host
# 退出容器
exit

5. 在集群内测试连接

Terminal window
#准备busybox镜像
docker pull busybox:1.30.1
docker tag busybox:1.30.1 reg.westos.org/library/busybox:1.30.1
docker push reg.westos.org/library/busybox:1.30.1
# 从任意节点或Pod内测试
kubectl run test-pod --image=reg.westos.org/library/busybox:1.30.1 --rm -it -- sh
# 在test-pod中测试
wget -q -O- http://10.244.2.15
# 应该看到连接成功的消息
# 或者在master节点直接curl
curl http://10.244.2.15

预期输出:

Nginx-PHP Container
Hostname: nginx-pod
Server IP: 10.244.2.15
Database connected successfully!
MySQL Version: 8.0.44

4.5 常用Pod管理命令#

Terminal window
# 查看所有Pod
kubectl get pods
kubectl get pods -o wide # 显示更多信息(IP、节点等)
kubectl get pods -A # 查看所有命名空间的Pod
# 查看Pod详情
kubectl describe pod <pod-name>
# 查看日志
kubectl logs <pod-name>
kubectl logs <pod-name> -f # 实时查看
kubectl logs <pod-name> -c <container> # 多容器Pod指定容器
# 进入容器
kubectl exec -it <pod-name> -- bash
kubectl exec -it <pod-name> -c <container> -- sh # 多容器指定容器
# 删除Pod
kubectl delete pod <pod-name>
kubectl delete -f pod.yaml
# 编辑Pod(部分字段不可修改)
kubectl edit pod <pod-name>
# 查看Pod的YAML
kubectl get pod <pod-name> -o yaml
# 查看Pod事件
kubectl get events --field-selector involvedObject.name=<pod-name>

4.6 验证和排错#

检查清单:

  1. Pod状态检查

    Terminal window
    kubectl get pods
    # 正常应显示:Running,READY 1/1
  2. 如果Pod状态为Pending

    • 检查节点资源是否充足
    • 检查镜像是否能正常拉取
    Terminal window
    kubectl describe pod <pod-name>
    # 查看Events部分的错误信息
  3. 如果Pod状态为ImagePullBackOff

    • 检查镜像名称是否正确
    • 检查私有仓库认证(后续会讲Secret)
    Terminal window
    kubectl logs <pod-name>
  4. 如果Pod状态为CrashLoopBackOff

    • 容器启动后立即崩溃
    • 查看日志定位问题
    Terminal window
    kubectl logs <pod-name> --previous # 查看上一次运行的日志
  5. 测试网络连通性

    Terminal window
    # 从任意节点或Pod内测试
    kubectl run test-pod --image=reg.westos.org/library/busybox:1.30.1 --rm -it --restart=Never -- sh
    # 在test-pod中测试
    wget -q -O- http://<pod-ip>
    # 应该看到连接成功的消息
    # 或者在master节点直接curl
    curl http://<pod-ip>

常见问题:

问题原因解决方法
ImagePullBackOff镜像拉取失败检查镜像名称、仓库地址、网络连接
CrashLoopBackOff容器启动后崩溃检查日志、检查启动命令、检查依赖服务
Pending无法调度(资源不足、节点异常等)检查节点状态、资源配额
ErrorPod启动失败查看describe和logs
0/1 Ready容器未通过就绪探针检查探针配置、应用启动状态

01.Kubernetes 学习笔记:基础概念与 Pod 详解
https://dev-null-sec.github.io/posts/01-k8s学习笔记-基础概念与pod详解/
作者
DevNull
发布于
2024-11-09
许可协议
CC BY-NC-SA 4.0