pod详解

一、namespace

  • 通过namespace命令空间将pod资源进行隔离
[root@k-master ~]# kubectl get ns
NAME               STATUS   AGE
calico-apiserver   Active   18h
calico-system      Active   18h
default            Active   18h
kube-node-lease    Active   18h
kube-public        Active   18h
kube-system        Active   18h
tigera-operator    Active   18h

1、切换默认的命名空间

# 查看当前的命名空间
[root@k-master ~]# kubectl config get-contexts 
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

# 切换默认的命名空间
[root@k-master ~]# kubectl config set-context --current --namespace kube-system
Context "kubernetes-admin@kubernetes" modified.

[root@k-master ~]# kubectl get pod 
NAME                               READY   STATUS    RESTARTS      AGE
coredns-5bbd96d687-rsnp6           1/1     Running   2 (56m ago)   18h
coredns-5bbd96d687-svq2d           1/1     Running   2 (56m ago)   18h
etcd-k-master                      1/1     Running   2 (56m ago)   18h
kube-apiserver-k-master            1/1     Running   2 (56m ago)   18h
kube-controller-manager-k-master   1/1     Running   2 (56m ago)   18h
kube-proxy-fgct4                   1/1     Running   3 (56m ago)   18h
kube-proxy-lfsvb                   1/1     Running   2 (56m ago)   18h
kube-proxy-mk56p                   1/1     Running   2 (56m ago)   18h
kube-scheduler-k-master            1/1     Running   2 (56m ago)   18h
metrics-server-7b8674ccdc-fdp29    1/1     Running   0             10m

# 写一个shell脚本,用户输入命令空间就能自动的进行切换

二、pod管理

1、pod怎么创建

1、命令行创建

kubectl run pod名字 --image 镜像 --镜像策略

[root@k-master ~]# kubectl run pod1 --image nginx
pod/pod1 created

[root@k-master ~]# kubectl get pod 
NAME   READY   STATUS              RESTARTS   AGE
pod1   0/1     ContainerCreating   0          18s

# -o 输出 运行在node1上面,并且拉取了nginx镜像
[root@k-master ~]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          24s   10.244.82.140   k-node1   <none>           <none>

2、yaml文件创建

[root@k-master yaml]# kubectl run p1 --image nginx --image-pull-policy IfNotPresent --dry-run=client -o yaml > p1.yaml
[root@k-master yaml]# cat p1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: p1
  name: p1
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: p1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
[root@k-master yaml]# kubectl apply -f p1.yaml 
pod/p1 created
[root@k-master yaml]# kubectl get pod 
NAME   READY   STATUS    RESTARTS   AGE
p1     1/1     Running   0          4s
[root@k-master yaml]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
p1     1/1     Running   0          8s    10.244.82.150   k-node1   <none>           <none>
[root@k-master yaml]# 

2、镜像的下载策略

  • Always 每次都会联网,从网上下载最新的镜像,不管本地有没有镜像

  • Never 从来不联网,在本地寻找镜像

  • IfNotPresent 先从本地进行拉取,如果没有的话,就联网去网上寻找

3、pod重启策略

  • 容器运行的是进程,这个进程是有镜像定义好的

  • restartPolicy

  • always 无论是正常退出还是非正常退出,都重启

  • OnFailure 遇到了错误重启

  • Never 从不重启

4、pod状态

  • pending pod被k8s接受了,但是镜像没有被下载

  • running 容器绑定到了某个节点,正常运行了

  • succeeded pod中所有容器都已成功终止,用于一次性任务

  • failed pod中容器都终止了,至少有一个是不正常退出

  • unknown 无法获取到pod状态,节点通信失败了

  • 其他都是容器内部的状态了

5、初始化容器(init)

  • 在pod创建之前,启动初始化容器提前做一些事情

  • 有一个或者多个初始化容器,所有初始化容器加载之后,最后运行应用容器

  • 案例,修改物理主机内核参数

  • 容器是根据物理机的内核运行的,依靠的

  • 容器默认与物理主机的内核是共享的,因此可以修改,但是需要权限

1、案例1

# 因为跑一个Pod,物理机有些参数不满足,因此需要使用init初始化容器修改物理主机的内核参数

[root@k-master yaml]# cat initpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: initpod
  name: initpod
spec:
  containers:
  - image: nginx
    name: initpod
    resources: {}
  initContainers:
  - name: initpod2
    image: alpine
    imagePullPolicy: IfNotPresent
    command: ["/sbin/sysctl","-w","vm.swappiness=35"]
    securityContext:
      privileged: true # 提权为root 就能修改主机上的内核参数了
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# 如果不提权的话,就不能修改主机上的内核参数了

# 发现被修改了
[root@k-node2 ~]# sysctl -a | grep vm.swap
vm.swappiness = 35

2、案例2

  • 提前挂载

  • 宿主机上面的文件挂载到初始化容器上面,然后挂载到应用容器上面即可,这样创建的pod就会

  • 使用一个临时目录创建一个文件夹,然后挂载到初始化容器中,写入了一个文件,因此临时目录也写入了这个文件

  • 然后挂载到应用容器里面/test中,因此/test中也有写入的文件

[root@k-master yaml]# cat vpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: vpod
  name: vpod
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: vpod
    resources: {}
    volumeMounts:
    - name: testdir
      mountPath: /test
  initContainers:
  - name: vinitpod
    image: alpine
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","echo 123 > /initest/test.txt"]
    volumeMounts:
    - name: testdir
      mountPath: /initest
  dnsPolicy: ClusterFirst
  restartPolicy: Always
  volumes:
  - name: testdir  # 起的挂载的名字,需要保持一致
    emptyDir: {}  # 宿主机随机创建一个临时目录
status: {}

6、静态pod

  • 有一个问题,kube-system中有很多个pod,那么就是pod先起来,集群就创建好了还是集群创建好了,pod然后再创建,就是一个典型的先有鸡还是先有蛋的问题了

  • 静态就是写好yaml就会自动的生成,删除了yaml就删除了pod

  • 集群的核心pod都是静态的

[root@k-master ~]# cd /etc/kubernetes/
[root@k-master kubernetes]# ls
admin.conf               kubelet.conf  pki
controller-manager.conf  manifests     scheduler.conf
[root@k-master kubernetes]# cd manifests/
[root@k-master manifests]# ls
etcd.yaml            kube-controller-manager.yaml
kube-apiserver.yaml  kube-scheduler.yaml
  • 在maifests里面创建一个yaml文件,会自动的生成pod,移走这个yaml或者删除这个yaml这个pod就会消失
[root@k-master manifests]# kubectl get pod 
NAME           READY   STATUS    RESTARTS      AGE
centos8-demo   1/1     Running   5 (44m ago)   3d18h
[root@k-master manifests]# mv /root/p1.yaml  .
[root@k-master manifests]# kubectl get pod 
NAME           READY   STATUS    RESTARTS      AGE
centos8-demo   1/1     Running   5 (44m ago)   3d18h
p1-k-master    1/1     Running   1 (14s ago)   1s

7、pod调度策略和标签

1、scheduler机制

  • pod是怎么进行调度根据scheduler组件调整

  • scheduler工作流程

    • 首先是过滤掉污点的主机

    • 然后对剩余的主机进行打分,评测,然后把pod进行调度到主机上即可

2、设置标签(根据主机上的标签进行调度pod)

  • 指定哪个节点上运行pod,是通过标签来实现的

  • 标签格式为键值对

# 给k-node2打上一个标签,然后创建一个带有node2标签的pod,进行调度上去即可

[root@k-master yaml]# kubectl label nodes k-node2 hehe=666
node/k-node2 labeled

[root@k-master yaml]# cat p1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: pod
spec:
  nodeSelector:  # 标签选择器
    hehe: "666"  # 选择主机标签为 hehe=666的主机
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: p1
status: {}

[root@k-master yaml]# kubectl get pod pod -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP              NODE      NOMINATED NODE   READINESS GATES
pod    1/1     Running   0          2m47s   10.244.108.28   k-node2   <none>           <none>

3、给主机标签的一些操作

  • 修改标签
# 修改原有的标签的话,需要覆盖即可
[root@k-master yaml]# kubectl label nodes k-node2 hehe=qqq --overwrite 


  • 删除标签
# 格式为 键- 就能删除标签了
[root@k-master yaml]# kubectl label  nodes k-node2 hehe-
node/k-node2 unlabeled

  • 当然给pod打上标签也可以

4、特殊标签

[root@k-master ~]# kubectl get node --show-labels  k-master 
NAME       STATUS   ROLES           AGE     VERSION   LABELS
k-master   Ready    control-plane   4d22h   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=

# control-plane这个标签,可以修改的

# 主机加载的是node-role.kubernetes.io/control-plane=  = 可以给值,也可以不给, 起作用的是 control-plane

[root@k-master ~]# kubectl label nodes k-master node-role.kubernetes.io/control-plane-
node/k-master unlabeled
[root@k-master ~]# kubectl label nodes k-master node-role.kubernetes.io/master=
node/k-master labeled

[root@k-master ~]# kubectl get node k-master 
NAME       STATUS   ROLES    AGE     VERSION
k-master   Ready    master   4d22h   v1.26.0


8、pod注释信息

[root@k-master ~]# kubectl annotate pod p2 aaa=kk

# 然后describe可以查看到

9、pod和控制器

  • 之前创建的单个pod,都不是控制器控制的

  • 因此删除pod就真的删除了,而不能再生了

  • 控制器控制的pod,删除了这个pod的话,会自动的再次生成一个pod,这样就是一个高可用

  • 控制器有很多种,deployment,daemoset,rs,job

三、污点

  • pod调度是根据scheduler调度算法完成的,如果有多个节点,其中有一个节点需要进行维护或者检查,就设置一个污点,新创建的pod就不会被调度在这个节点上了

1、设置节点不可用(cordon)

  • 新创建的pod不会被调度在这个上面
[root@k-master ~]# kubectl get node
NAME       STATUS   ROLES    AGE     VERSION
k-master   Ready    master   4d23h   v1.26.0
k-node1    Ready    <none>   4d23h   v1.26.0
k-node2    Ready    <none>   4d23h   v1.26.0
[root@k-master ~]# kubectl cordon k-node1 
node/k-node1 cordoned
[root@k-master ~]# kubectl get node 
NAME       STATUS                     ROLES    AGE     VERSION
k-master   Ready                      master   4d23h   v1.26.0
k-node1    Ready,SchedulingDisabled  <none>   4d23h   v1.26.0
k-node2    Ready                      <none>   4d23h   v1.26.0

# SchedulingDisabled 调度被禁用了

# 取消cordon操作
[root@k-master ~]# kubectl get node 
NAME       STATUS                     ROLES    AGE     VERSION
k-master   Ready                      master   4d23h   v1.26.0
k-node1    Ready,SchedulingDisabled   <none>   4d23h   v1.26.0
k-node2    Ready                      <none>   4d23h   v1.26.0
[root@k-master ~]# kubectl uncordon k-node1 
node/k-node1 uncordoned
[root@k-master ~]# kubectl get node 
NAME       STATUS   ROLES    AGE     VERSION
k-master   Ready    master   4d23h   v1.26.0
k-node1    Ready    <none>   4d23h   v1.26.0
k-node2    Ready    <none>   4d23h   v1.26.0

2、drain操作

  • 驱除所有pod

  • 默认情况下,daemon-set的pod不会被删除

  • 驱除所有pod然后节点不可用,不能被调度在上面

  • 如果是单个pod就是删除

  • 如果是deployment的话,那么就是不在这个节点上面创建,在其他允许的节点上面创建,因为是deployment是控制器

[root@k-master ~]# kubectl drain k-node1 
node/k-node1 already cordoned
error: unable to drain node "k-node1" due to error:[cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): calico-system/calico-node-rtbfq, calico-system/csi-node-driver-qzcwr, kube-system/kube-proxy-mk56p, cannot delete Pods declare no controller (use --force to override): default/centos8-demo, default/p2], continuing command...
There are pending nodes to be drained:
 k-node1
cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): calico-system/calico-node-rtbfq, calico-system/csi-node-driver-qzcwr, kube-system/kube-proxy-mk56p
cannot delete Pods declare no controller (use --force to override): default/centos8-demo, default/p2

# 取消的操作与之前的一样
[root@k-master ~]# kubectl get node 
NAME       STATUS                     ROLES    AGE     VERSION
k-master   Ready                      master   4d23h   v1.26.0
k-node1    Ready,SchedulingDisabled   <none>   4d23h   v1.26.0
k-node2    Ready                      <none>   4d23h   v1.26.0
[root@k-master ~]# kubectl uncordon k-node1 
node/k-node1 uncordoned
[root@k-master ~]# kubectl get node 
NAME       STATUS   ROLES    AGE     VERSION
k-master   Ready    master   4d23h   v1.26.0
k-node1    Ready    <none>   4d23h   v1.26.0
k-node2    Ready    <none>   4d23h   v1.26.0

  • 上面的这些做法有点不合理,如果检查的时候,需要一个pod调度在这个节点上面,但是这个策略不允许调度在上面,就需要下面的污点了

2、设置节点或者pod污点

  • 污点的等级

    • NoSchedule 新创建的pod不允许被调度在这个节点上面,已经存在的pod不会被删除

    • PreferNoSchedule 所有节点都不符合的话,最后调度在这个节点上面即可

    • NoExecute 新创建的pod不能调度在这个节点和已经存在的pod都被删除

1、查看节点污点

# 因为master上面有污点,所以默认情况下,不会调度在master上面
[root@k-master ~]# kubectl describe nodes k-master | grep -i taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

2、给节点打上污点和删除污点


[root@k-master ~]# kubectl taint node k-node1 qqq:NoSchedule
node/k-node1 tainted
[root@k-master ~]# kubectl describe nodes k-node1|grep -i taint
Taints:             qqq:NoSchedule

# 这样的话被调度的pod就不能调度在这个节点上面了


[root@k-master ~]# kubectl describe node k-node1 |grep -i taint
Taints:             qqq:NoSchedule
# 删除污点
[root@k-master ~]# kubectl taint node k-node1 qqq-
node/k-node1 untainted
[root@k-master ~]# kubectl describe node k-node1 |grep -i taint
Taints:             <none>

3、容忍度

  • 就是这个节点上面即使有污点,也能被容忍,从而进行调度pod
[root@k-master ~]# kubectl describe node k-node1 | grep -i taint
Taints:             qqq:NoSchedule


[root@k-master ~]# cat 1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod
  labels:
    aa: qq
spec:
  tolerations:  # 容忍度
  - key: qqq  # key
    operator: Exists  # 没有value的话,就使用Exists,而不是使用Equal
    effect: NoSchedule  # 污点的级别
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: p2


4、污点和cordon的区别

  • 污点通过容忍这个污点的操作,可以调度pod

  • 但是cordon的话,pod不能被调度

四、pod和命名空间

  • 创建的pod默认是在default命名空间下创建的

  • 如果一个pod里面有多个容器的话,这些容器都是共享这个网络空间的(ip地址,端口)

  • 比如一个pod里面不能创建2个nginx,因为有一个监听到80端口了,除非改变另外一个监听的端口

  • 创建多个pod的话,都是隔离的,不影响

  • 创建了一个pod,里面的容器就共享一个名称空间1,这样的操作

[root@k-master yaml]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP              NODE      NOMINATED NODE   READINESS GATES
pod    2/2     Running   0          5m36s   10.244.82.156   k-node1   <none>           <none>


# 这个pod的2个容器地址都是10.244.82.156


  • 一个default空间下面的多个pod ,default/p1 default/p2 , p1和p2互不干扰,

  • 当p1就相当于是一个虚拟主机,有多个nginx容器的话,就不能创建成功,因为都是监听的80端口,一个虚拟主机上面只有一个80端口

四、pod创建过程

img

  • 用户提交创建pod请求

  • api-server 处理用户请求,先存储pod数据到etcd中,写入成功,api-server将成功信息返回给客户端

  • scheduler通过watch机制监听到有新的pod后,会根据选出一个节点来进行调度到上面去

  • scheduler将成功绑定的信息写回到api-server,api-server将其写入到etcd中进行永久存储

  • kubelet接管pod创建,运行在目标节点上的kubelet监听pod资源中的变化

  • 创建成功后kubelet返回信息给api-server,然后存入到etcd中

  • 就是这样反复的一个写入过程

  • 创建的pod在其他节点上面,就会运行相对应的容器,查看这个容器的相关信息也是可以的

posted @ 2025-07-25 15:43  乔的港口  阅读(30)  评论(0)    收藏  举报