k8s的管理及控制器管理

0. 实验环境与准备

0.1 集群与镜像清单

本文用到的镜像(仓库里 library 项目需提前准备好):

镜像 用途
myapp:v1 / myapp:v2 基于 nginx 的演示镜像,访问返回 Hello MyApp | Version: vX
busybox / busyboxplus 轻量调试容器
nginx:latest 通用 Web 容器
mysql:8.0 + phpmyadmin:latest 多容器 Pod 演示
perl:5.34.0 Job 批处理演示

如果镜像在本地 tar 包里,先导入并推到私有仓库(以 myapp 为例):

bash 复制代码
docker load -i myapp.tar.gz
docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
docker push reg.timinglee.org/library/myapp:v1
docker tag timinglee/myapp:v2 reg.timinglee.org/library/myapp:v2
docker push reg.timinglee.org/library/myapp:v2

0.2 两种操作风格:命令式 vs 声明式

风格 例子 特点
命令式 kubectl run, kubectl create, kubectl expose 一行搞定,快;但不留"底稿",难回滚、难版本管理
声明式 kubectl apply -f xxx.yaml 把期望状态写进 YAML,可纳入 Git,是生产环境的标准做法

1. 实验一:Pod 基础与 kubectl 命令

1.1 命名空间管理

命名空间(Namespace)用来给资源分组隔离,默认都在 default

bash 复制代码
kubectl get namespaces          # 查看所有命名空间
kubectl create namespace timinglee   # 创建
kubectl delete namespace timinglee   # 删除(会一并删掉里面的资源,谨慎!)

预期输出(创建后):

bash 复制代码
NAME              STATUS   AGE
default           Active   4h20m
kube-flannel      Active   3h31m
kube-node-lease   Active   4h20m
kube-public       Active   4h20m
kube-system       Active   4h20m
timinglee         Active   5s

1.2 创建第一个 Pod 与排错

bash 复制代码
kubectl run lee --image nginx:latest
kubectl get pods -o wide
bash 复制代码
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
lee    1/1     Running   0          25s   10.244.1.10   k8s-node1   <none>           <none>

故意创建一个拉不到的镜像,看K8s 怎么报错:

bash 复制代码
kubectl run error --image lee:v1
kubectl get pods -o wide
bash 复制代码
NAME    READY   STATUS             RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
error   0/1     ImagePullBackOff   0          38s   10.244.2.3    k8s-node2   <none>           <none>

describe 看详细原因

bash 复制代码
kubectl describe pods error

在 Events 里你会看到:

bash 复制代码
Warning  Failed   kubelet  Failed to pull image "lee:v1": docker.io/library/lee:v1: not found
Warning  Failed   kubelet  Error: ErrImagePull
Normal   BackOff  kubelet  Back-off pulling image "lee:v1"
Warning  Failed   kubelet  Error: ImagePullBackOff

清理:

bash 复制代码
kubectl delete pods error
kubectl delete pods --all     # 删除 default 命名空间下所有 Pod

1.3 核心 kubectl 命令逐一练

create ------ 创建 Deployment 并管理副本

bash 复制代码
kubectl create deployment webcluster --replicas 2 --image myapp:v1
kubectl get deployments.apps
kubectl delete deployments.apps webcluster

edit ------ 在线修改(会打开默认编辑器)

bash 复制代码
kubectl create deployment webcluster --image myapp:v1
kubectl edit deployments.apps webcluster   # 把 replicas 改成 2 保存
kubectl get pods                           # 会发现多了一个 Pod

patch ------ 不改文件,直接命令行打补丁

bash 复制代码
kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":1}}'
kubectl get pods                           # 又变回 1 个

expose ------ 把 Deployment 暴露成 Service(集群内可访问)

bash 复制代码
kubectl expose deployment webcluster --port 80 --target-port 80
kubectl get service
curl 10.97.61.108/hostname.html            # 多次访问会轮询到不同 Pod

logs / exec / cp ------ 查日志、进容器、拷文件

bash 复制代码
kubectl logs pods/webcluster-xxxxx          # 看日志
kubectl exec -it pods/testpod -c testpod -- /bin/bash   # 进容器
kubectl cp testpod:/usr/share/nginx/html/index.html /mnt/test   # 拷出来
echo timinglee > /mnt/index.html
kubectl cp /mnt/index.html testpod:/usr/share/nginx/html/index.html   # 拷回去
curl <pod-ip>                               # 返回 timinglee

rollout ------ 发布状态与重启

bash 复制代码
kubectl rollout status deployment webcluster
kubectl rollout restart deployment webcluster   # 滚动重启(Pod 会一批批换新)

scale ------ 扩缩容

bash 复制代码
kubectl scale deployment webcluster --replicas 4
kubectl scale deployment webcluster --replicas 1

label ------ 标签是 K8s 的"身份证"

bash 复制代码
kubectl get pods --show-labels
kubectl label pods webcluster-xxxxx app-            # 删除标签
kubectl label pods webcluster-xxxxx app=webcluster  # 加回标签

2. 实验二:用 YAML 声明式玩转 Pod

2.1 一个 Pod 里跑多个容器

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: testpod
  labels:
    run: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
  - image: busyboxplus:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 10000"]
bash 复制代码
kubectl apply -f testpod.yaml
kubectl get pods            # READY 列显示 2/2
kubectl exec -it pods/testpod -c busybox -- /bin/sh
/ # curl 127.0.0.1          # 从 busybox 访问同 Pod 里的 myapp

2.2 hostPort:把容器端口暴露到节点

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
    ports:
    - name: http
      containerPort: 80
      hostPort: 80        # Pod 所在节点的 80 端口会转发进来
      protocol: TCP
bash 复制代码
kubectl apply -f testpod.yaml
kubectl get pods -o wide   # 记下 NODE 列,比如 k8s-node2
curl k8s-node2             # 直接访问节点 IP:80

2.3 用环境变量给容器传配置

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mysql
spec:
  containers:
  - image: mysql:8.0
    name: mysql8
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: lee
  - image: phpmyadmin:latest
    name: mysqladmin
    env:
    - name: PMA_ARBITRARY
      value: "1"
    ports:
    - name: phpadminport
      containerPort: 80
      hostPort: 80
      protocol: TCP
bash 复制代码
kubectl apply -f mysql.yaml
kubectl get pods -o wide   # 浏览器访问该节点的 80 端口即可进 phpMyAdmin

2.4 nodeSelector:指定 Pod 落在哪个节点

先看节点有哪些标签:

bash 复制代码
kubectl get nodes --show-labels
bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mysql
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-node2   # 只调度到 node2
  containers:
  - image: mysql:8.0
    name: mysql8
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: lee
  - image: phpmyadmin:latest
    name: mysqladmin
    env:
    - name: PMA_ARBITRARY
      value: "1"
    ports:
    - name: phpadminport
      containerPort: 80
      hostPort: 80
bash 复制代码
kubectl apply -f mysql.yaml
kubectl get pods -o wide   # NODE 一定是 k8s-node2

2.5 hostNetwork:让 Pod 共享宿主机网络

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 10000"]


kubectl apply -f testpod.yaml
kubectl exec -it pods/testpod -c busybox -- /bin/sh
/ # ifconfig     # 看到的是宿主机的 eth0,而不是 Pod 自己的网络

2.6 QoS 三档:资源优先级

当节点资源紧张时,K8s 按 QoS 决定先杀谁。三档由 resources 的配置决定:

级别 条件 优先级
BestEffort 完全不设 requests/limits 最低,最先被驱逐
Burstable 设了限制,但 requests ≠ limits 中间
Guaranteed requests == limits(且都设了) 最高,最后才被驱逐

BestEffort:

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: qos-besteffort
spec:
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 10000"]

Burstable(requests < limits):

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: qos-burstable
spec:
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 10000"]
    resources:
      requests:
        cpu: 500m
        memory: 100Mi
      limits:
        cpu: 700m
        memory: 200Mi

Guaranteed(requests == limits):

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: qos-guaranteed
spec:
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 10000"]
    resources:
      requests:
        cpu: 500m
        memory: 100Mi
      limits:
        cpu: 500m
        memory: 100Mi

验证:

bash 复制代码
kubectl describe pods qos-besteffort  | grep "QoS Class:"   # BestEffort
kubectl describe pods qos-burstable  | grep "QoS Class:"   # Burstable
kubectl describe pods qos-guaranteed | grep "QoS Class:"   # Guaranteed

2.7 重启策略:Always / OnFailure / Never

restartPolicy 决定容器退出后 K8s 怎么办:

策略 行为 典型场景
Always 不管什么原因退出都重启 长期运行的服务(默认)
OnFailure 非正常退出才重启 允许正常结束的批处理
Never 退出后绝不重启 任务只跑一次,结果靠查日志
bash 复制代码
# Always 示例(容器命令 sleep 60,结束后会被立刻拉起)
apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  restartPolicy: Always
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 60"]



# Never 示例(sleep 30 结束后 Pod 变 Completed,不再重启)
apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  restartPolicy: Never
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh", "-c", "sleep 30"]
相关推荐
SCandL1521 小时前
k8s service
linux·容器·kubernetes
众人皆醒我独醉3 小时前
InferenceGraph:把多个推理服务编排成 DAG
面试·kubernetes·gpu
众人皆醒我独醉3 小时前
LLMService:KServe 面向 LLM 的下一步
面试·kubernetes·gpu
aaaBsBsBsB4 小时前
k8s pod管理
运维·docker·容器
阿里云云原生4 小时前
解决 AI Agent 可观测性难题:eBPF 技术在 Serverless 容器场景下的落地应用
云原生
Doep_key5 小时前
Kubenetes控制器
运维·docker·容器
做一个AK梦6 小时前
论基于云原生数据库的企业信息系统架构设计
数据库·云原生
梦想不只是梦与想7 小时前
Docker Compose文件
docker·容器·docker compose
分布式存储与RustFS7 小时前
在自己的机器上复现 RustFS 性能基准:warp 压测实操
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准