前言

Kubernetes 把集群中所有对象全部抽象为资源。我们不去直接操作容器,而是操作各类 K8s 资源对象完成应用部署。

  • Pod:K8s 最小调度单元,里面运行一个或多个容器
  • 控制器(Deployment 等):生产环境不直接裸用 Pod,由控制器代为管理 Pod 生命周期、扩缩容、滚动更新
  • Service:实现 Pod 网络访问与负载均衡
  • 存储资源:负责容器数据持久化

简单理解:容器跑在 Pod 里面,Pod 由控制器管控,Service 负责流量接入。

一.K8s 三种资源管理方式

类型 适用场景 优点 缺点
命令式对象管理 测试环境 操作简单,敲命令即可 无配置文件,无法审计追踪,不适合生产
命令式对象配置 开发环境 YAML 文件保存,可版本管理 项目庞大时配置文件多,操作繁琐
声明式对象配置 生产环境 支持目录批量操作,增量更新 问题排查难度略高

1.1 命令式对象管理

直接执行 kubectl 命令操作集群,适合临时测试。
语法格式:

kubectl [command] [type] [name] [flags]
  • command:动作,get/create/delete/edit
  • type:资源类型 pod/deployment/service
  • name:资源名称
  • flags:扩展参数

示例常用命令:

#查看全部pod
kubectl get pod
#yaml格式输出pod详情
kubectl get pod pod-name -o yaml
#查看集群版本
kubectl version
#查看集群控制平面信息
kubectl cluster-info
#查看帮助文档,学习yaml字段
kubectl explain deployment

1.2 命令式对象配置

基于 yaml 文件执行 create/patch/delete:

kubectl create -f xxx.yaml
kubectl delete -f xxx.yaml

1.3 声明式对象配置(生产主推)

使用apply,自动对比集群当前状态和 yaml 期望状态,增量更新资源:

kubectl apply -f xxx.yaml
#支持整个目录下全部yaml批量执行
kubectl apply -f ./yaml-dir/

小技巧:快速生成 yaml 模板,不需要手写全部字段

kubectl create deployment --image nginx web --dry-run=client -o yaml > web.yaml

1.4 Pod 日常调试命令

#查看pod详细信息(节点IP等)
kubectl get pod -o wide
#查看pod事件,排错神器
kubectl describe pod pod-name
#查看容器日志
kubectl logs pod-name
#进入pod容器交互终端
kubectl exec -it pod-name -- /bin/bash
#本地和pod互相拷贝文件
kubectl cp 本地文件 pod-name:/容器路径
kubectl cp pod-name:/容器路径 本地路径
#给pod打标签
kubectl label pods pod-name app=demo
#覆盖已有标签
kubectl label pods pod-name app=demo-new --overwrite
#删除标签
kubectl label pods pod-name app-

二.pod

Pod 是 Kubernetes 最小的调度、部署单元,K8s 不直接管理容器,容器必须放在 Pod 里面才能运行。

类比:Pod 像豌豆荚,容器就是豌豆。一个豆荚 (Pod) 里面可以装 1 颗或者多颗豌豆 (容器)。
核心特点:

  • 同一个 Pod 内所有容器共享网络命名空间,共用同一个 Pod‑IP,容器之间可以用localhost互相访问。
  • 同一个 Pod 容器共享存储卷,可以读写同一个文件。
  • 一个 Pod 永远只会运行在同一个 Node 节点,不会跨节点拆分。
  • 裸 Pod(直接创建 Pod)生产环境不推荐;生产使用 Deployment 控制器管理 Pod。

注意:不要把不同业务容器放同一个 Pod;只有强耦合、需要紧密协作的容器才放一个 Pod(主容器 + Sidecar 辅助容器)。

三.命令式对象管理(实操)

命名空间管理

[root@master ~]# kubectl  get namespace  #查看命令空间
NAME              STATUS   AGE
default           Active   5d3h
kube-flannel      Active   5d2h
kube-node-lease   Active   5d3h
kube-public       Active   5d3h
kube-system       Active   5d3h
metallb-system    Active   21h
[root@master ~]# kubectl  create namespace timinglee  #创建命名空间
namespace/timinglee created
[root@master ~]# kubectl  get namespaces
NAME              STATUS   AGE
default           Active   5d3h
kube-flannel      Active   5d2h
kube-node-lease   Active   5d3h
kube-public       Active   5d3h
kube-system       Active   5d3h
metallb-system    Active   21h
timinglee         Active   3s
[root@master ~]# kubectl delete  namespaces  timinglee  #删除命令空间
namespace "timinglee" deleted
[root@master ~]# kubectl  get namespaces
NAME              STATUS   AGE
default           Active   5d3h
kube-flannel      Active   5d2h
kube-node-lease   Active   5d3h
kube-public       Active   5d3h
kube-system       Active   5d3h
metallb-system    Active   21h

pod管理

#查看pod的运行情况和运行在哪里
[root@master ~]# kubectl  get pods -o wide
No resources found in default namespace.



#创建pod
[root@master ~]# kubectl  run xia --image myapp:v1
pod/xia created
[root@master ~]# kubectl  get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
xia    1/1     Running   0          5s    10.244.1.138   node1   <none>           <none>


#当pod创建出现问题
[root@master ~]# kubectl  run error --image xia:v1
pod/error created
[root@master ~]# kubectl  get pods -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
error   0/1     ContainerCreating   0          3s    <none>         node2   <none>           <none>
xia     1/1     Running             0          53s   10.244.1.138   node1   <none>           <none>


##查看pod运行的详细信息
[root@master ~]# kubectl  describe pods error
Name:             error
Namespace:        default
Priority:         0
Service Account:  default
Node:             node2/172.25.254.20
Start Time:       Tue, 25 Aug 2026 14:03:58 +0800
Labels:           run=error
Annotations:      <none>
Status:           Pending
IP:
IPs:              <none>
Containers:
  error:
    Container ID:
    Image:          xia:v1
    Image ID:
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-sc4ng (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   False
  Initialized                 True
  Ready                       False
  ContainersReady             False
  PodScheduled                True
Volumes:
  kube-api-access-sc4ng:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    Optional:                false
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  18s   default-scheduler  Successfully assigned default/error to node2
  Normal ulling    17s   kubelet            spec.containers{error}: Pulling image "xia:v1"
#你的 node1 上 Pod xia 是 Running,镜像 xia:v1 只存在 node1,node2 机器上没有这个镜像!




#删除 
[root@master ~]# kubectl  delete  pods error
pod "error" deleted from default namespace
[root@master ~]# kubectl  get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE    IP             NODE    NOMINATED NODE   READINESS GATES
xia    1/1     Running   0          2m1s   10.244.1.138   node1   <none>           <none>
[root@master ~]# kubectl  delete pods --all
pod "xia" deleted from default namespace

四.kubectl 命令实操

上传实验镜像到仓库library中

[root@master ~]# docker load  -i myapp.tar.gz
[root@master ~]# docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
[root@master ~]# docker push  reg.timinglee.org/library/myapp:v1
[root@master ~]# docker tag timinglee/myapp:v2 reg.timinglee.org/library/myapp:v2
[root@master ~]# docker push  reg.timinglee.org/library/myapp:v2

生成实验所需yml文件

[root@master ~]# kubectl  create deployment replica --replicas 2 --image myapp:v1 --dry-run=client -o yaml > replica.yml
[root@master ~]# vim replica.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  labels:
    app: replica	#设定控制器标签
  name: replica
spec:
  replicas: 2		#启动pod数量
  selector:
    matchLabels:
      app: replica	#控制器标签选择器
  template:
    metadata:
      labels:
        app: replica	#开启pod的属性模板
    spec:
      containers:
      - image: myapp:v1
        name: myapp

kubectl命令使用方法

子命令 功能说明
create 命令式创建 K8s 各类资源对象
edit 直接在线编辑集群上已存在的资源,保存后实时生效
patch 以补丁方式局部修改资源,仅更新指定字段,无需完整 YAML
expose 基于 Pod/Deployment 创建 Service 资源,对外暴露网络访问端口
logs 获取容器的标准输出、标准错误日志
attach 附加到容器内正在运行的主进程,直接查看进程输出流
exec 在 Pod 容器内部新建一个进程,执行指定命令
cp 实现宿主机与 Pod 容器之间双向文件拷贝
rollout 管控 Deployment 等资源的版本,管理更新历史、重启、版本回退
scale 调整 Deployment/StatefulSet 的副本数量,完成扩缩容
label 为资源添加、修改、删除标签,用于资源筛选、调度匹配

高可用性和可靠性

  • 自动故障恢复:如果一个 Pod 失败或被删除,控制器会自动创建新的 Pod 来维持期望的副本数量。确保应用始终处于可用状态,减少因单个 Pod 故障导致的服务中断。

  • 健康检查和自愈:可以配置控制器对 Pod 进行健康检查(如存活探针和就绪探针)。如果 Pod 不健康,控制器会采取适当的行动,如重启 Pod 或删除并重新创建它,以保证应用的正常运行。

可扩展性

  • 轻松扩缩容:可以通过简单的命令或配置更改来增加或减少 Pod 的数量,以满足不同的工作负载需求。例如,在高流量期间可以快速扩展以处理更多请求,在低流量期间可以缩容以节省资源。

  • 水平自动扩缩容(HPA):可以基于自定义指标(如 CPU 利用率、内存使用情况或应用特定的指标)自动调整 Pod 的数量,实现动态的资源分配和成本优化。

版本管理和更新

  • 滚动更新:对于 Deployment 等控制器,可以执行滚动更新来逐步替换旧版本的 Pod 为新版本,确保应用在更新过程中始终保持可用。可以控制更新的速率和策略,以减少对用户的影响。

  • 回滚:如果更新出现问题,可以轻松回滚到上一个稳定版本,保证应用的稳定性和可靠性。

声明式配置

  • 简洁的配置方式:使用 YAML 或 JSON 格式的声明式配置文件来定义应用的部署需求。这种方式使得配置易于理解、维护和版本控制,同时也方便团队协作。

  • 期望状态管理:只需要定义应用的期望状态(如副本数量、容器镜像等),控制器会自动调整实际状态与期望状态保持一致。无需手动管理每个 Pod 的创建和删除,提高了管理效率。

服务发现和负载均衡

  • 自动注册和发现:Kubernetes 中的服务(Service)可以自动发现由控制器管理的 Pod,并将流量路由到它们。这使得应用的服务发现和负载均衡变得简单和可靠,无需手动配置负载均衡器。

  • 流量分发:可以根据不同的策略(如轮询、随机等)将请求分发到不同的 Pod,提高应用的性能和可用性。

多环境一致性

  • 一致的部署方式:在不同的环境(如开发、测试、生产)中,可以使用相同的控制器和配置来部署应用,确保应用在不同环境中的行为一致。这有助于减少部署差异和错误,提高开发和运维效率。

create

[root@master ~]#  kubectl create deployment web  --replicas 2 --image myapp:v1 deployment.apps/web created
[root@master ~]# kubectl  get deployments.apps
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web    2/2     2            2           40s
[root@master ~]# kubectl  get pods
NAME                   READY   STATUS    RESTARTS   AGE
web-67f5ccd5b4-7hhbw   1/1     Running   0          46s
web-67f5ccd5b4-kbqcn   1/1     Running   0          46s
[root@master ~]# kubectl delete deployments.apps web
deployment.apps "web" deleted from default namespace
[root@master ~]# kubectl  get pods
No resources found in default namespace.

edit

[root@master ~]# kubectl  get pods
NAME                    READY   STATUS    RESTARTS   AGE
xixi-6df7c6bbbb-5h6rm   1/1     Running   0          4s
[root@master ~]# kubectl  edit deployments.apps xixi
replicas: 2

deployment.apps/xixi edited
[root@master ~]# kubectl  get pods
NAME                    READY   STATUS    RESTARTS   AGE
xixi-6df7c6bbbb-5h6rm   1/1     Running   0          54s
xixi-6df7c6bbbb-lpdfz   1/1     Running   0          5s
xixi-6df7c6bbbb-v29jg   1/1     Running   0          5s

patch

[root@master ~]# kubectl  patch  deployments.apps xixi -p '{ "spec": { "replicas":2 }}'
deployment.apps/xixi patched
[root@master ~]# kubectl  get pods
NAME                    READY   STATUS    RESTARTS   AGE
xixi-6df7c6bbbb-lpdfz   1/1     Running   0          2m47s
xixi-6df7c6bbbb-v29jg   1/1     Running   0          2m47s

expose

[root@master ~]# kubectl  expose deployment xixi --port 80 --target-port 80    service/xixi exposed
[root@master ~]# kubectl  get service
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP         PORT(S)   AGE
extrnalname   ExternalName   <none>           www.timinglee.org   <none>    17h
kubernetes    ClusterIP      10.96.0.1        <none>              443/TCP   5d3h
xixi          ClusterIP      10.109.253.188   <none>              80/TCP    12s
[root@master ~]# kubectl  get svc xixi
NAME   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
xixi   ClusterIP   10.109.253.188   <none>        80/TCP    30s
[root@master ~]# kubectl  describe  svc xixi
Name:                     xixi
Namespace:                default
Labels:                   app=xixi
Annotations:              <none>
Selector:                 app=xixi
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.109.253.188
IPs:                      10.109.253.188
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.1.142:80,10.244.2.95:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>
[root@master ~]# kubectl  get pods
NAME                    READY   STATUS    RESTARTS   AGE
xixi-6df7c6bbbb-gspgm   1/1     Running   0          3m14s
xixi-6df7c6bbbb-wwr2f   1/1     Running   0          3m4s
[root@master ~]#  curl  10.109.253.188/hostname.html
xixi-6df7c6bbbb-wwr2f
[root@master ~]#  curl  10.109.253.188/hostname.html
xixi-6df7c6bbbb-gspgm
[root@master ~]#  curl  10.109.253.188/hostname.html
xixi-6df7c6bbbb-wwr2f
[root@master ~]#  curl  10.109.253.188/hostname.html
xixi-6df7c6bbbb-gspgm

logs

[root@master ~]# kubectl  get pods
NAME                    READY   STATUS    RESTARTS   AGE
xixi-6df7c6bbbb-gspgm   1/1     Running   0          3m14s
xixi-6df7c6bbbb-wwr2f   1/1     Running   0          3m4s
[root@master ~]# kubectl  logs xixi-6df7c6bbbb-gspgm
10.244.0.0 - - [25/Aug/2026:06:29:38 +0000] "GET /hostname.html HTTP/1.1" 200 22 "-" "curl/7.76.1" "-"
10.244.0.0 - - [25/Aug/2026:06:29:48 +0000] "GET /hostname.html HTTP/1.1" 200 22 "-" "curl/7.76.1" "-"

attach

[root@master ~]# docker load  -i busybox-latest.tar.gz
Loaded image: busybox:latest
[root@master ~]# docker tag busybox:latest  reg.timinglee.org/library/busybox:latest

[root@master ~]# kubectl run -it xia --image busybox:latest
All commands and output from this session will be recorded in container logs, including credentials and sensitive information passed through the command prompt.
If you don't see a command prompt, try pressing enter.
/ #
/ #
/ #      #ctrl+pq

[root@master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
xia                       1/1     Running   0          55s

[root@master ~]# kubectl attach pods/testpod -it
All commands and output from this session will be recorded in container logs, including credentials and sensitive information passed through the command prompt.
If you don't see a command prompt, try pressing enter.
/ #
/ #
/ #

exec

[root@master ~]# kubectl run  testpod --image  nginx:latest
pod/testpod created
[root@k8s-master ~]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
testpod   1/1     Running   0          4s
root@master ~]# kubectl exec -it pods/testpod -c testpod -- /bin/bash
root@testpod:/#

cp

[root@master mnt]# kubectl  cp xia:/usr/share/nginx/html /mnt/test
[root@master mnt]# cd /mnt/test
[root@master test]# ls
50x.html  index.html
[root@master test]# echo happy everyday you > /mnt/test/index.html
[root@master test]#  kubectl cp /mnt/test/index.html xia:/usr/share/nginx/html/index.html
[root@master test]# kubectl get pods  -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
xia    1/1     Running   0          4m44s   10.244.1.143   node1   <none>           <none>
[root@master test]# curl 10.244.1.143
happy everyday you

rollout

[root@master test]# kubectl  create deployment rollout --image myapp:v1 --replicas 2 --dry-run=client -o yaml > rollout.yml
[root@master test]# vim rollout.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: rollout
  name: rollout
spec:
  replicas: 2
  selector:
    matchLabels:
      app: rollout
  template:
    metadata:
      labels:
        app: rollout
    spec:
      containers:
      - image: myapp:v1
        name: myapp
[root@master test]# kubectl  apply -f rollout.yml
deployment.apps/rollout created
[root@master test]#  kubectl get deployments.apps
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
rollout   2/2     2            2           6s
[root@master test]#  kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
rollout-566b6d4bbf-5cvl5   1/1     Running   0          15s
rollout-566b6d4bbf-nn7p9   1/1     Running   0          15s
[root@master test]# kubectl rollout status  deployment rollout
deployment "rollout" successfully rolled out
[root@master test]# kubectl rollout  restart   deployment rollout
deployment.apps/rollout restarted
[root@master test]#  kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
rollout-6db775d4d6-52lbv   1/1     Running   0          5s
rollout-6db775d4d6-pfxg6   1/1     Running   0          4s
[root@master test]# kubectl rollout  restart   deployment rollout
deployment.apps/rollout restarted
[root@master test]#  kubectl get pods
NAME                       READY   STATUS              RESTARTS   AGE
rollout-6db775d4d6-52lbv   1/1     Running             0          2m11s
rollout-6db775d4d6-pfxg6   0/1     Completed           0          2m10s
rollout-756f779d5-f9r69    1/1     Running             0          1s
rollout-756f779d5-knsgs    0/1     ContainerCreating   0          0s

scale

[root@master test]# kubectl scale deployment  rollout  --replicas 4
deployment.apps/rollout scaled
[root@master test]#  kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
rollout-756f779d5-f9r69   1/1     Running   0          2m47s
rollout-756f779d5-knsgs   1/1     Running   0          2m46s
rollout-756f779d5-nlqjc   1/1     Running   0          3s
rollout-756f779d5-nwcxj   1/1     Running   0          3s
[root@master test]# kubectl scale deployment  rollout  --replicas 1
deployment.apps/rollout scaled
[root@master test]#  kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
rollout-756f779d5-knsgs   1/1     Running   0          2m56s

label

[root@master test]#  kubectl get pods --show-labels
NAME                      READY   STATUS    RESTARTS   AGE     LABELS
rollout-756f779d5-knsgs   1/1     Running   0          3m40s   app=rollout,pod-template-hash=756f779d5
[root@master test]#  kubectl get deployments.apps rollout  --show-labels
NAME      READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
rollout   1/1     1            1           7m57s   app=rollout
[root@master test]# kubectl  label pods rollout-756f779d5-knsgs app-
pod/rollout-756f779d5-knsgs unlabeled
[root@master test]# kubectl  label pods rollout-756f779d5-knsgs app=qiu
pod/rollout-756f779d5-knsgs labeled
[root@master test]#  kubectl get pods --show-labels
NAME                      READY   STATUS    RESTARTS   AGE     LABELS
rollout-756f779d5-5fb5r   1/1     Running   0          17s     app=rollout,pod-template-hash=756f779d5
rollout-756f779d5-knsgs   1/1     Running   0          5m52s   app=qiu,pod-template-hash=756f779d5

五.利用控制器实现版本更替

建立控制器

在做以下实验时harbor仓库中的library项目中必须有myapp:v1和myapp:v2两个镜像

[root@master test]# kubectl create deployment webcluster --image myapp:v1 --replicas 2 --dry-run=client -o yaml > webcluster.yml
[root@master test]#  kubectl apply -f webcluster.yml
deployment.apps/webcluster created
[root@master test]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-77c87d9946-h8hzq   1/1     Running   0          74s
webcluster-77c87d9946-nk6pd   1/1     Running   0          74s
[root@master test]#  kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION  CHANGE-CAUSE
1         <none>

[root@master test]# kubectl expose deployment webcluster --port 80 --target-port 80 --type NodePort
service/webcluster exposed
service "xixi" deleted from default namespace
[root@master test]#  kubectl get svc
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP         PORT(S)        AGE
extrnalname   ExternalName   <none>           www.timinglee.org   <none>         18h
kubernetes    ClusterIP      10.96.0.1        <none>              443/TCP        5d4h
webcluster    NodePort       10.103.215.189   <none>              80:36423/TCP   28s

更新业务版本

[root@master test]#  kubectl set image deployments webcluster myapp=myapp:v2
deployment.apps/webcluster image updated
[root@master test]# kubectl annotate deployment webcluster kubernetes.io/change-cause="myappv2" --overwrite #为此次更新设定标签
deployment.apps/webcluster annotated
[root@master test]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-6c8b4bb9d7-kpwqv   1/1     Running   0          93s
webcluster-6c8b4bb9d7-wkm5c   1/1     Running   0          95s
[root@master test]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION  CHANGE-CAUSE
1         <none>
2         myappv2

#验证

版本回退

[root@master test]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION  CHANGE-CAUSE
1         <none>
2         myappv2

[root@master test]# kubectl rollout undo deployment webcluster --to-revision 1
deployment.apps/webcluster rolled back

#验证

六.利用yaml文件声明资源

在pod中运行多容器

[root@master test]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
  - image: busyboxplus:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
[root@master test]# kubectl apply -f testpod.yaml
pod/testpod created
[root@master test]#  kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
testpod   2/2     Running   0          53s
[root@master test]#  kubectl exec -it pods/testpod -c busybox -- /bin/sh
/bin/sh: shopt: not found
[ root@testpod:/ ]$ curl 127.0.0.1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[ root@testpod:/ ]$



在pod运行主机中暴漏端口

[root@master test]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
    ports:
    - name: http
      containerPort: 80			#pod内部容器端口
      hostPort: 80				#pod所在节点端口
      protocol: TCP				#端口所用协议
pod "testpod" deleted from default namespace
^C[root@master test]# kubectl delete pod testpod --force
[root@master test]# kubectl apply -f testpod.yaml
pod/testpod created
[root@master test]# kubectl get pods   -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
testpod   1/1     Running   0          7s    10.244.1.152   node1   <none>           <none>
[root@master test]# curl  node1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

在pod中指定变量

[root@master test]# kubectl run mysql --image mysql:8.0 --port=80 --dry-run=client -o yaml > mysql.yml
[root@master test]# vim mysql.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: mysql
  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
[root@master test]# kubectl apply -f mysql.yml
pod/mysql created
[root@master test]#  kubectl get pods  -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
mysql   2/2     Running   0          7s    10.244.2.102   node2   <none>           <none>

#在浏览器中访问 node下面看到的主机ip(我是node2的IP)

选择运行节点

[root@master test]# vim mysql.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: mysql
  name: mysql
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-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
      protocol: TCP
[root@master test]# kubectl apply -f mysql.yml
pod/mysql created
[root@master test]# kubectl get pods  -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
mysql   0/2     ContainerCreating   0          9s    <none>   node1   <none>           <none>

共享宿主机网络

[root@master test]# vim test.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
[root@master test]# kubectl apply -f test.yaml
pod/testpod created
[root@master test]# kubectl exec -it pods/testpod -c busybox -- /bin/sh
/ #
/ # ifconfig
cni0      Link encap:Ethernet  HWaddr B2:97:FB:3B:7D:9D
          inet addr:10.244.1.1  Bcast:10.244.1.255  Mask:255.255.255.0
          inet6 addr: fe80::b097:fbff:fe3b:7d9d/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:202 errors:0 dropped:0 overruns:0 frame:0
          TX packets:71 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:14373 (14.0 KiB)  TX bytes:5670 (5.5 KiB)

docker0   Link encap:Ethernet  HWaddr A2:CC:B1:74:A4:D5
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:2 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth0      Link encap:Ethernet  HWaddr 00:0C:29:97:47:60
          inet addr:172.25.254.10  Bcast:172.25.254.255  Mask:255.255.255.0
          inet6 addr: fe80::c70a:fdb1:6db0:e292/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1037655 errors:0 dropped:0 overruns:0 frame:0
          TX packets:80574 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1507369595 (1.4 GiB)  TX bytes:7007572 (6.6 MiB)

flannel.1 Link encap:Ethernet  HWaddr F2:38:9E:7E:A8:27
          inet addr:10.244.1.0  Bcast:0.0.0.0  Mask:255.255.255.255
          inet6 addr: fe80::f038:9eff:fe7e:a827/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:34 errors:0 dropped:0 overruns:0 frame:0
          TX packets:25 errors:0 dropped:16 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2171 (2.1 KiB)  TX bytes:3172 (3.0 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:16133 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16133 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1335375 (1.2 MiB)  TX bytes:1335375 (1.2 MiB)

资源优先级

资源限制会影响pod的Qos Class资源优先级,资源优先级分为Guaranteed > Burstable > BestEffort

QoS(Quality of Service)即服务质量

资源设定 优先级类型
资源限定未设定 BestEffort(尽力服务)
资源限定设定且最大和最小不一致 Burstable(突发型)
资源限定设定且最大和最小一致 Guaranteed(保证型)

BestEffort没有做任何资源限制,资源使用优先级最低

[root@master pod]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000


[root@master pod]# kubectl describe pods  testpod  | grep "QoS Class:"
QoS Class:                   BestEffort

Burstable 设定了资源限制,但是期望值和限制值不同,资源使用优先级次之

[root@master pod]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
	resources:
      limits:
        cpu: 700m
        memory: 200M
      requests:
        cpu: 500m
        memory: 100M

[root@master pod]# kubectl apply -f testpod.yaml
pod/testpod unchanged

[root@k8s-master pod]# kubectl describe pods  testpod  | grep "QoS Class:"
QoS Class:                   Burstable

Guaranteed期望值和最大使用限制相同,优先级最高

[root@master pod]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000
	resources:
      limits:
        cpu: 500m
        memory: 100M
      requests:
        cpu: 500m
        memory: 100M
        
[root@master pod]# kubectl apply -f testpod.yaml
pod/testpod created
[root@k8s-master pod]# kubectl describe pods  testpod  | grep "QoS Class:"
QoS Class:                   Guaranteed

七.Pod 生命周期(Init 容器 + 健康探针)

Pod 完整生命周期流程:Init 容器执行 → 主应用容器启动 → 探针持续健康检查 → Pod 终止。

 Init 初始化容器

Init 容器是 Pod 启动最先执行的容器集合,串行执行,必须全部成功退出,主业务容器才会启动。
特点:

  • Init 容器顺序执行,上一个成功结束,下一个才运行;
  • Init 失败,pod 会反复重启直到执行成功;restartPolicy=Never 除外;
  • Init 没有就绪探针;

典型场景:等待外部服务就绪、初始化配置文件、下载业务依赖资源。

[root@master k8s]# vim  init.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: init
spec:
  initContainers:
  - name: busybox
    image: busybox:latest
    command:
      - /bin/sh
      - -c
      - "until test -e /testfile;do echo wating for myservice; sleep 2;done"
  containers:
  - image: myapp:v1
    name: webserver
  restartPolicy: Always


[root@master k8s]# kubectl  apply -f init.yml
pod/init created

#我没有这个文件,所以容器一直在重启

#监控程序
[root@k8s-master pod]# watch -n 1 kubectl get pods  -o wide

#创建文件
[root@master k8s]# kubectl exec -it pods/init -c busybox -- /bin/sh
/ # touch /testfile
/ # command terminated with exit code 137
[root@master k8s]#

7.2 三大探针(Probe)

探针是由 kubelet 对容器执行的定期诊断:

  • ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。

每次探测都将获得以下三种结果之一:

  • 成功:容器通过了诊断。
  • 失败:容器未通过诊断。
  • 未知:诊断失败,因此不会采取任何行动。

Kubelet 可以选择是否执行在容器上运行的三种探针执行和做出反应:

  • livenessProbe:指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为 Success。
  • readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure。如果容器不提供就绪探针,则默认状态为 Success。
  • startupProbe: 指示容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet 将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功Success。

ReadinessProbe 与 LivenessProbe 的区别

  • ReadinessProbe 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除。
  • LivenessProbe 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施
  • StartupProbe 与 ReadinessProbe、LivenessProbe 的区别
  • 如果三个探针同时存在,先执行 StartupProbe 探针,其他两个探针将会被暂时禁用,直到 pod 满足 StartupProbe 探针配置的条件,其他 2 个探针启动,如果不满足按照规则重启容器。
  • 另外两种探针在容器启动后,会按照配置,直到容器消亡才停止探测,而 StartupProbe 探针只是在容器启动后按照配置满足一次后,不在进行后续的探测。

livenessProbe 存活探针

判断容器进程是否卡死。探测失败 → kubelet 杀死容器,依据重启策略重启 Pod。
适用场景:进程死锁、内存泄漏卡死,进程还在但是服务不可用。

#没有存活指针时

[root@master k8s]# kubectl run  webserver --image  myapp:v1  --dry-run=client -o yaml > livness.yaml
[root@k8s-master pod]# vim livness-example.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  containers:
  - image: myapp:v1
    name: webserver
    command:
    - /bin/sh
    - -c
    - "nginx -g 'daemon off;' & sleep 10000000"
  restartPolicy: Always

[root@master k8s]# kubectl apply -f livness-example.yaml
#测试操作:
[root@master k8s]# kubectl exec  -it  pods/webserver -c webserver  -- /bin/sh
# nginx -s stop

#查看pod的状态仍然是runing,但是访问此pod时访问失败

[root@master k8s]# vim liveness.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
    command:
      - /bin/sh
      - -c
      - "nginx -g 'daemon off;' & sleep 10000000"
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 1
      timeoutSeconds: 1
  restartPolicy: Always




[root@master k8s]# kubectl apply -f  liveness.yml
pod/webserver created

#当我们停掉容器后,会自动重启,把旧容器从后端移除,换新的 容器工作

[root@master k8s]# kubectl exec -it pods/webserver -c webserver -- /bin/sh
/ # nginx -s stop
2026/08/25 08:46:02 [notice] 15#15: signal process started
/ # exec attach failed: error on attach stdin: read escape sequence
command terminated with exit code 126
[root@master k8s]#  curl  10.244.1.155
curl: (7) Failed to connect to 10.244.1.155 port 80: 拒绝连接
[root@master k8s]#  curl  10.244.1.155
curl: (7) Failed to connect to 10.244.1.155 port 80: 拒绝连接
[root@master k8s]#  curl  10.244.1.155
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

dinessProbe 就绪探针

判断应用是否准备接收流量。探测失败 → 把 pod 从 service 后端 endpoint 列表剔除,不再转发流量,不会杀死容器。
适用场景:应用启动慢,需要加载数据预热,没就绪不能接收请求。

#无探针时

[root@master k8s]#vim readness-example.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
  restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: webserver


[root@master k8s]#  kubectl apply -f readness-example.yml
pod/webserver created
service/webserver created
[root@master k8s]# kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.99.35.53
IPs:                      10.99.35.53
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.1.157:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>
#删除默认发布文件
[root@k8s-master ~]# kubectl exec -it pods/webserver -c webserver -- /bin/sh
/ # cd /usr/share/nginx/
/usr/share/nginx # ls
html
/usr/share/nginx # cd html/
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # rm -fr index.html
/usr/share/nginx/html # ls
50x.html
/usr/share/nginx/html #

#验证是否在访问service时endpoints中被下架
[root@k8s-master pod]# kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.99.35.53
IPs:                      10.99.35.53
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.1.157 			#还在
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>


#业务问题
[root@k8s-master pod]# curl  10.244.1.157 
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>

#有探针时

[root@master k8s]#vim readness-example.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 2
      timeoutSeconds: 1
  restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: webserver


[root@master k8s]#  kubectl apply -f readness-example.yml
pod/webserver created
service/webserver created
[root@master k8s]# kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.99.35.53
IPs:                      10.99.35.53
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.1.157:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>

#业务问题

[root@master k8s]# kubectl exec -it pods/webserver -c webserver -- /bin/sh
/ # cd /usr/share/nginx/
/usr/share/nginx # cd html/
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # rm -rf index.html
/usr/share/nginx/html # ls
50x.html
[root@master k8s]# kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.99.35.53
IPs:                      10.99.35.53
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>

#修复

[root@master k8s]# kubectl exec -it pods/webserver -c webserver -- /bin/sh
/ # echo timinglee > /usr/share/nginx/html/index.html

感谢各位耐心看完这篇博客。写作过程也是自我梳理复盘的过程,难免会有考虑不周的地方,欢迎大家批评指正。希望这篇内容能够对你有所帮助,我们下篇博文再会。

更多推荐