pod概念及常用操作

pod概念:什么是pod

一个pod里面最少两个容器:
一个是pause容器,
另一个是指定运行的容器.

Pod是一组紧密关联的容器集合,它们共享PID、 IPC、 Network和UTS namespace, 是Kubernetes调度的基本单位。
Pod的设计理念是支持多个容器在一个Pod中共享网络和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。

k8s为每一个pod都分配唯一的IP地址,称之为pod ip,一个pod中的多个容器共享pod ip地址,Pod可以配置多个IP地址

k8s要求底层网络支持集群内任意两个pod之间网络通信,采用虚拟二层技术实现,比如flanne、 calico、 ovs。 k8s中,一个pod的容器与另外主机上的pod容器能够直接通信。


init容器(初始化容器)

参考: https://www.jianshu.com/p/42afb9d9bfff

在这里插入图片描述
initContainer(初始化容器)会比普通container先启动;会按照定义的顺序启动,而普通的container是并发启动的;执行成功后结束退出,普通容器会一直执行

  • InitContainer先于普通容器启动执行
  • 多个InitContainer的执行是按定义次序串行执行,而多个普通容器是并行执行
  • InitContainer执行成功后就结束退出,而普通容器可以一直执行
  • Pod重启时,InitContainer会再次执行

官方doc-init容器
init容器yaml示例

apiVersion: v1
kind: Pod
metadata:
  name: mydb
  labels:
    app: db
spec:
  # init容器fetch启动完成后,才会启动业务容器mysql
  initContainers:
    - name: fetch
      image: mwendler/wget
      command: ["wget","--no-check-certificate","https://sample-videos.com/sql/Sample-SQL-File-1000rows.sql","-O","/docker-entrypoint-initdb.d/dump.sql"]
      volumeMounts:
        - mountPath: /docker-entrypoint-initdb.d
          name: dump
  containers:
    - name: mysql
      image: mysql
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: "example"
      volumeMounts:
        - mountPath: /docker-entrypoint-initdb.d
          name: dump
  volumes:
    - emptyDir: {}
      name: dump

pause容器(Infra容器)

参考: Pause 容器的作用

在这里插入图片描述
kubernetes中的pause容器主要为每个业务容器 提供以下功能:

PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID。

网络命名空间:Pod中的多个容器能够访问同 一个IP和端口范围。

IPC命名空间:Pod中的多个容器能够使用 SystemV IPC或POSIX消息队列进行通信。

UTS命名空间:Pod中的多个容器共享一个主 机名;Volumes(共享存储卷):

Pod中的各个容器可以访问在Pod级别定义的 Volumes.

每个Pod都有一个特殊的称之为“根容器”的Pause容器。 Pause容器对应的镜像属于k8s平台的一部分,除了Pause容器外,每个Pod还包含一个或多个紧密相关的用户业务容器。他为每个业务容器提供如下功能:
①在pod中担任Linux命名空间共享的基础。
②启用pid命名空间,开启init进程。

引入这种方式的原因:

  1. 一组容器运行的pod中,很难对整体进行判断,引入pasue作为根容器,以它的状态代表整个容器组的状态。
  2. pod中多个容器共享pasue容器的IP,共享pause容器挂载的volume。
    这样简化了密切相连的容器之间的通信,也解决了他们之间文件共享的问题。

pause容器也叫infra容器;
Pod 里面,必然是 Infra container 第一个启动,用来为业务容器提供网络.

pod的IP是配置pause容器上的,pod中的其他容器与pause容器共用网络。
docker ps|grep pause查看,有几个pod,就会有几个pause容器启动.

在这里插入图片描述


修改默认infro容器
# 定义默认infra容器
vim /etc/kubenets/kubelet

在这里插入图片描述


普通pod:

一旦被创建,会被放到etcd中存储,随后被k8s master调度到某个具体的node上并进行绑定,随后该pod被对应的node上的kubelet进程实例化成一组相关的docker容器并启动起来。默认情况下,当pod中的某个容器停止时,
K8s会自动检测到这个问题并重新启动这个pod(重启pod里面的所有容器),如果pod所在的node宕机,则会将这个
node上的所有pod重新调度到其他节点上。


pod资源限制:

每个pod可以设置限额,目前可以设置CPU和内存, cpu的单位为core的数量,
是一个绝对值而不是相对值。 k8s中是以千分之一为最小单位,一般一个pod
设置为100m到300m,也是就是0.1-0.3个cpu。内存是以MB为单位
k8s设置2个参数:
requests:该资源的最小申请量,系统必须满足的要求
limits:该资源的最大允许使用的量,不能被突破,当容器试图使用超过这个
量的资源时,有可能会被k8s kill并重启。


pod生命周期介绍

Pod 对象在 Kubernetes 中的生命周期。 Pod 生命周期的变化,主要体现在 Pod API 对象的Status 部分。
其中pod.status.phase,就是 Pod 的当前状态,它有如下几种可能的情况:
Pending
Running
Succeeded
Failed
Unknown

在这里插入图片描述


Pending状态

Pending。这个状态意味着, Pod 的 YAML 文件(或通过kubectl命令创建Pod)已经提交给了 Kubernetes, API 对象已
经被创建并保存在 Etcd 当中。但是,这个 Pod 里有些容器因为某种原因而不能被顺利创建。比如,调度不成功。

当Pod处在Pending的时候,可能是由于如下哪个问题造成的。

  • 资源不足,造成无法调度
  • Pod尚未进入调度阶段
  • Pod正在拉取镜像

Running状态

Running。这个状态下, Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都已经创建成功,并且至少有一个正
在运行中。


Succeeded状态

Succeeded。这个状态意味着, Pod 里的所有容器都正常运行完毕,并且已经退出了。这种情况在运行一次性任务时最
为常见。


Failed状态

Failed。这个状态下, Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出。这个状态的出现,意味着你得想办
法 Debug 这个容器的应用,比如查看 Pod 的 Events 和日志。


Unknown状态

Unknown。这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从
节点( Master 和 Kubelet)间的通信出现了问题。


其他字段

更进一步地, Pod 对象的 Status 字段,还可以再细分出一组 Conditions。这些细分状态的值包括: PodScheduled、
Ready、 Initialized,以及 Unschedulable。它们主要用于描述造成当前Status 的具体原因是什么。
比如, Pod 当前的 Status 是 Pending,对应的 Condition 是 Unschedulable,这就意味着它的调度出现了问题。
Pod 的这些状态信息,是我们判断应用运行情况的重要标准,尤其是 Pod 进入了非“Running”状态后,你一定要能迅速
做出反应,根据它所代表的异常情况开始跟踪和定位,而不是去手忙脚乱地查阅文档。


静态pod:

官方文档

静态 Pod(Static Pod) 直接由特定节点上的 kubelet 守护进程管理, 不需要API 服务器看到它们。
无法与我们常用的控制器Deployments或者DaemonSeti进行关联,它由kubeleti进程自己来监控,当pod崩溃时重启该pod,kubelete也无法对他们进行健康检查。静态pod始终绑定在某一个kubelet,并且始终运行在同一个节点上。
Kubelets会自动为每一个静态pod在Kubernetes的apiserver.上创建一个镜像Pod(Mirror Pod),因此我们可以在apiserveri中查询到该pod,但是不能通过apiserver进行控制(例如不能删除)。
静态pod不存储在etcd中,而是存放在某个具体的node上的一个具体文件中,并只在此node上启动运行。
静态Pod名称标识当前节点名称.


在kubelet配置文件中启用静态pod的参数

# 编辑配置文件
vim /var/lib/kubelet/config.yaml

# 添加/查看静态pod路径参数
staticPodPath: /etc/kubernetes/manifests
## 注:将部署的pod yaml放到该目录会由kubelet自动创建。

创建静态pod

官方文档

创建静态Pod有两种方式:配置文件和HTTP两种方式
将静态pod的yaml文件放在/etc/kubernetes/manifests路径下即可.
静态pod的yaml示例

apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP

查看静态pod

[master root ~]# kubectl get po|grep -i static-web
static-web-node   1/1     Running   0          6m10s

pod注意事项

pod不支持apply和edit在线更新
但是可以用apply创建pod


多容器pod重启策略

一个容器出错pod状态就会显示error,会根据重启策略执行重启
在这里插入图片描述


健康检查

在这里插入图片描述

参考官方文档: https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-lifecycle/#container-probes


存活探针-livenessProbe

Liveness Probe主要面向有状态服务;
指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。


定义探针存活命令

参考: 定义探针存活命令

检查机制


exec存活检查示例
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
    - name: liveness
      image: k8s.gcr.io/busybox
      args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600

      # 配置存活探针
      livenessProbe:
        # 在容器内执行指定命令,如果命令退出时返回码为 0 则认为诊断成功。
        exec:
          command:
            - cat
            - /tmp/healthy
        # 容器初始化延迟秒数(多少秒后开始检查存活)
        initialDelaySeconds: 5
        # 超时秒数 返回结果超时认为不健康
        timeoutSeconds: 1
        # 多少秒执行一次存活指令
        periodSeconds: 5

httpGet存活检查示例
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
    - name: liveness
      image: k8s.gcr.io/liveness
      args:
        - /server

      # 配置存活探针
      livenessProbe:
        # 执行httpget请求
        httpGet:
          # 请求的路径
          path: /healthz
          # 请求的端口
          port: 8080
          # 添加自定义请求头
          httpHeaders:
            # 添加字段
            - name: Custom-Header
              # 添加字段的值
              value: Awesome
        # 容器初始化延迟秒数
        initialDelaySeconds: 3
        # 多少秒检查一次存活
        periodSeconds: 3

就绪探针-readinessProbe

指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。

Readiness Probe在检测失败后会自动从Endpoint摘掉Pod


tcpSocket就绪探针和存活探针示例

tcpSocket的原理有点像telnet ip地址 端口号,检查端口是否开放.

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
    - name: goproxy
      image: k8s.gcr.io/goproxy:0.1
      ports:
        - containerPort: 8080

      # 配置就绪探针
      readinessProbe:
        # 使用tcp端口检查方式配置就绪探针
        tcpSocket:
          # 检查8080端口是否开放
          port: 8080
        # 容器初始化延迟秒数
        initialDelaySeconds: 5
        # 多少秒执行一次就绪检查
        periodSeconds: 10

      # 配置存活探针
      livenessProbe:
        # 使用tcp端口检查方式配置存活探针,类似于telnet
        tcpSocket:
          # 检查8080端口是否开放
          port: 8080
        # 容器初始化延迟秒数
        initialDelaySeconds: 15
        # 多少秒执行一次存活检查
        periodSeconds: 20

启动探针-startupProbe

指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。


服务质量等级(QOS)

参考:

QoS(Quality of Service),大部分译为“服务质量等级”,又译作“服务质量保证”,是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:

Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。
Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。
BestEffort(最低优先级):容器必须没有任何内存或者 CPU 的限制或请求。


最高优先级(Guaranteed)pod

https://www.toutiao.com/a6939507079094731272/?log_from=f50e1823b745_1646033172214

limits和requests两个都配置了且配置的值要一样,就是最高优先级的pod.

# pod内资源分配的配置格式如下:
# 默认可以只配置requests,但根据生产中的经验,建议把limits资源限制也加上,因为对K8s来说,
#只有这两个都配置了且配置的值都要一样,这个pod资源的优先级才是最高的,在node资源不够的情况下,首先是把#没有任何资源分配配置的pod资源给干掉,其次是只配置了requests的,最后才是两个都配置的
      resources:
        limits:   # 限制单个pod最多能使用1核(1000m 毫核)cpu以及2G内存
          cpu: "1"
          memory: 2Gi
        requests: # 保证这个pod初始就能分配这么多资源
          cpu: "1"

将pod中的容器资源限制的独享资源和共享资源设为一样的值,该pod优先级即为最高。如果资源不够时会驱逐其他pod。


pod常用操作


启动一个pod

# 使用nginx镜像启动一个名为test的pod
kubectl run test --image=nginx

# 使用busybox创建一个测试pod
kubectl run bs --imges=busybox:1.28.4 -- sleep 24h

创建一个测试pod

# 使用busybox创建一个测试pod
kubectl run ping --imges=busybox:1.28.4 -- sleep 24h

使用yaml创建pod

apiVersion: v1
kind: Pod
metadata:
  name: ping
  labels:
    name: ping
spec:
  containers:
  - name: ping
    image: busybox:1.28.4
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 12h"]

进入ping这个测试pod

busybox一般用来做网络测试

# busybox不支持bash,要指定sh
kubectl exec -it ping -- sh

pod资源清单yam示例

最小应用部署单元 即应用
pod 需要定义什么 ( 带* 为必填项)

元数据 *
	pod名称 *
	所属namespaces *
	标签  可用于 svc 识别 *
	注释信息 *
规格 *
	调度
	-  容器名称 containers *
		使用镜像  *
		镜像拉取方式 *
		执行参数
		启动参数
		挂载卷使用 对应到容器 目录
		开放端口
		环境变量
		资源配额
		健康检查
	指定挂载卷 硬盘资源
	容忍
	dns策略
	主机模式
	重启策略

pod yaml 范例

apiVersion: v1
kind: Pod
metadata:
  name: test-pod						# pod名称                                       
  namespaces: default					# 所属命名空间
  labels:								# pod 标签列表
    app: test							# 添加标签 (key-value)

  annotations:                          # 注释 列表
    app: test							# 添加注释(key-value)

spec:									# 规格
  nodeSelector:							# 表示将该Pod调度到包含这个label的node上
    nodelabel: node2				# 调度node的标签
  containers:        # 容器规格
  
# 以下为这个containers 的配置
  - name: test
    image: nginx     # 使用镜像源                    (镜像源)
    imagePullPoilcy: {always| Never | ifNotPresent} #镜像拉取方式(always Never ifNotPresent)

# 启动命令 ----------------------------------------
    command:                            # dockers启动后执行命令
    - /bin/sh
    - c
    - sleep 3600                        # 执行命令
# 启动参数 ----------------------------------------
    args:                               # 容器启动 参数列表
    - ["HOSTNAME", "KUBERNETES_PORT"]   # 容器启动参数
    workingdir: /                       # 容器工作目录 linux 目录
# 容器挂载 ----------------------------------------
    volumeMounts:                       # 挂载存储配置
    - name: disk1                       # 挂载存储卷名称
      mountPath:                        # 存储卷挂载位置 绝对路径
      readonly: {true|false}    		    # 是否只读 {true|false}
# 开放端口 ----------------------------------------
    ports:                              # 容器需要暴漏的端口号列表
    - name: http                        # port名称
      containerPort: 80         		    # 监听容器内端口号使用podip可以访问 int
      hostPort: 80                      # 容器将服务映射到宿主机端口 #端口号 int
      # protocol在ports层级下边,只能指定tcp/udp/sctp
      protocol: {tcp|udp}       	   # 端口协议 {tcp | udp}
# 环境变量 ----------------------------------------
    env:
    - name: path						# 环境变量名称 string
      value: xxx						# 环境变量值 string
#---
    - name: configmap                   # 可使用configmap传入变量
      valueFrom:
        configMapKeyRef:
          name: test-cm         		# 使用名为test-cm的configmap
          key: test-cm-testvkey 		#使用test-cm 中的test-cm-testvkey值
# 资源限制 ----------------------------------------
    resources:							# 使用资源限制  (limits 大于 requests)
#---
      limits:							# 封顶资源限制,最大使用的共享资源
        cpu: "1"						# CPU 限制1 核
        memory: 1Gi						# 内存限制 512M  #单位Gi Mi
#----------------------------------------
      requests:							# 请求资源,独享资源
        cpu: "1"						# CPU 限制0.5 核
        memory: 512M					# 内存限制 512M  #单位Gi Mi
# 健康检查 ----------------------------------------
    readinessProbe:					# 健康检查/就绪探针
#----
      exec:								# 命令脚本方式
        command:
        - cat
        - /tmp/health                   # 命令执行返回结果为失败判定为不健康
#----
      tcpSocket:						# 端口健康检测方式-telnet
        port: 80						# 检测tcp80端口 如果为开启 为不健康
#----
      httpGet:							 # http请求方式
        path: /
        port: 80						# http请求 容器地址:port+path 返回状态码结果200~399 为健康
#----
      initialDelaySeconds:              # 初始检测延迟秒数
      timeoutSeconds: 1         		    # 超时秒数 返回结果超时认为不健康
      periodSeconds: 10                 # 对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
# 挂载目录 ----------------------------------------
  volumes:                  # 设定存储卷 三种模式
  - name: tmp               # 存储卷名称(emptydir模式)临时目录
    emptyDir: {}						# 使用临时存储  容器 重启会数据清空
#--- 将本地目录/disk1,挂载为volumes: host_path
  - name: host_path						# 存储卷名称 (hostpath模式)宿主机文件存储
    hostPath:							# 使用宿主机文件模式 挂载目录=宿主机目录
      path: "/disk1"					# 挂在宿主机目录地址
#--- 将nfs存储挂载为名为nfs的volumes
  - name: nfs							# nfs模式 使用nfs服务器 存储资源
    nfs:
      server: 192.168.1.1               #指定nfs url
# ---- 挂载pvc
  - name: pvc
    persistenVolumeClaim:
      claimName: pvc1					# 已经申请好了的PVC
#--- 将configMap挂载为名为cm的volume
  - name: cm 							# 存储卷名称 (configmap模式)
    configMap:							# 使用configmap模式
    items:
    - key:                              # 使用configmap key
      path:                             # 挂载路径

#  DNS一般不动
  dnsPolicy: {default|clusterFirst|clusterFirstwithHostNet|node}
  hostNetwork: {true|false}				# hostNetwork网络模式
  restartPolicy: {Always|Never}			# 重启策略
# 容忍 ----------------------------------------
  tolerations:
  - key: "节点污点key"
    operator: "Equal"
    value: "节点污点value"
    effect: "NoExecute"
    tolerationSeconds: 3600

镜像拉取策略

在这里插入图片描述
Kubernetes 中的镜像拉取策略(imagePullPolicy)有以下几种:

  1. Always: 每次都尝试拉取镜像,如果本地已经存在该镜像,则会进行覆盖。这是默认的拉取策略。

  2. IfNotPresent: 仅当本地不存在该镜像时才尝试拉取。

  3. Never: 仅使用本地已经存在的镜像,如果本地不存在该镜像,则会报错。

  4. OnFailure: 仅在上一次启动容器失败后才会尝试拉取镜像。

需要注意的是,镜像拉取策略只会影响首次容器启动时的行为,如果容器已经被创建并运行,那么更新镜像需要手动执行“删除-创建”操作。


进入pod执行命令

# 执行pod的date命令,默认使用pod的第一个容器
kubectl exec pod名 date
kubectl exec pod名 -- bash

# 指定pod中的某个容器执行date命令
kubectl exec pod名 -c 容器名 date

# 进入pod中的容器
kubectl exec pod名 -c 容器名 -- bash
kubectl exec pod名 -c 容器名 -- /bin/bash

查看pod的ip地址

# 查看pod的基本信息
kubectl get po test

# 查看pod的常用信息,pod的IP和所属节点
kubectl get pod test -o wide

## 访问pod
crul pod的ip地址

查看pod详情

# 查看pod的详细信息
kubectl describe pods pod名

查看pod资源的labels(标签)

# 查看pod的标签
kubectl get pods --show-labels

# 根据标签查询pod
kubectl get pods -l 标签key=value
kubectl get pods -l app=nginx

查看运行中pod的镜像

# 查看集群中运行着的所有镜像
kubectl get pods -A -o=custom-columns='DATA:spec.containers[*].image'

# 列举 default 名字空间中运行的所有镜像,按 Pod 分组
kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,IMAGE:.spec.containers[*].image"

# 除 "k8s.gcr.io/coredns:1.6.2" 之外的所有镜像
kubectl get pods -A -o=custom-columns='DATA:spec.containers[?(@.image!="k8s.gcr.io/coredns:1.6.2")].image'

# 输出 metadata 下面的所有字段,无论 Pod 名字为何
kubectl get pods -A -o=custom-columns='DATA:metadata.*'

查看pod的日志

# 查看pod日志
kubect logs pod名

# 持续pod中的容器日志
# 查看多容器pod日志
kubectl logs -f pod名 -c 容器名

pod扩容

kubectl scale pod名 --replicas=副本数量

HPA自动水平伸缩pod

参考: https://www.toutiao.com/a6939507079094731272/?log_from=f50e1823b745_1646033172214
需要依赖kubectl top
需要pod配置预设资源

# 为deployment资源web创建hpa,pod数量上限3个,最低1个,在pod平均CPU达到50%后开始扩容
kubectl  autoscale deployment web --max=3 --min=1 --cpu-percent=50

滚动更新pod

kubectl set image pod名 容器名=镜像名:v镜像版本号

强制删除pod

从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 TerminatingUnknown 状态

kubectl delete po ${pod_name} --grace-period=0 --force

用yaml强制更新pod

强制更新 pod(运行时只能修改部分内容)

kubectl replace -f manual-schedule.yaml --force

pod亲和(podAffinity)

华为云-pod亲和
官方doc-pod亲和示例
Pod和Pod之间的亲和,例如将应用的前端和后端部署在一起,从而减少访问延迟
在这里插入图片描述

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  # 亲和
  affinity:
    # pod亲和
    podAffinity:
      # 硬策略
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          # 带有security=S1标签的pod尽量运行在同一node上
          - key: security
            operator: In
            values:
            - S1
        # 用主机名来作为拓扑域
        topologyKey: topology.kubernetes.io/zone
    
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0

pod反亲和(podAntiAffinity)

参考:

官方doc-避免同一个node上放置多个带有同标签的副本

华为云-pod反亲和

pod间亲和性和反亲和性

PodAntiAffinityrequiredDuringSchedulingIgnoredDuringExecution

雪花啤酒的面试官问了个问题: deployment如何在每个node上运行一个pod? 当时一时想不起来pod反亲和硬策略可以实现.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  # 副本数3
  replicas: 3
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        # pod反亲和
        podAntiAffinity:
          # 硬需求/硬策略
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              # 禁止在同一node上部署多个标签为app=strore的副本
              - key: app
                operator: In
                values:
                - store
            # 用主机名来作为拓扑域
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine

网络测试pod

参考: 容器网络调试工具 netshoot
netshoot镜像工具表

# 使用nicolaka/netshoot镜像创建一个网络调试用的临时pod
kubectl run ping --rm -ti --image=nicolaka/netshoot -- bash

pod抓包

  • 问题场景:
    某pod业务访问k8s外部业务网络不通,怎么抓pod网络的包

  • 解决办法:
    容器中一般是没有tcpdump命令的,可以通过node上的nsenter命令进入podnamespace进行抓包.

# 确认pod所在的node节点
kubectl get pod -owide -n 指定namespace | grep pod名

在这里插入图片描述
在这里插入图片描述

# 进入node节点
ssh node_ip
## 在node上安装nsenter命令
yum install -y util-linux

查询pod的容器pid

# 方法1:查询该pod的某容器的pid
## 查询pod的容器名|容器id
docker ps | grep pod名

## 通过容器id查询该容器的pid
## --format "{{.State.Pid}}" 指定获取Pid字段
docker inspect --format "{{.State.Pid}}" 容器id

进入指定pid的网络命名空间(network namespace)

Linux系统的6种类型的命名空间

  • Process ID (pid)
  • Mount (mnt)
  • Network (net)
  • InterProcess Communication (ipc)
  • UTS
  • User ID (user)
    例如:
  • pid命名空间内的进程只能看到同一命名空间中的进程
  • mnt命名空间,可以将进程附加到自己的文件系统(如chroot)。
  • 在本文中,只关注网络命名空间 Network (net)

https://developer.aliyun.com/article/272172

# 进入指定容器的网络命名空间(network namespace)
## -t 指定的pid
## -n 表示切换网络命名空间(network namespace)
nsenter -t 容器在宿主机上的pid -n 

在这里插入图片描述


在node上通过tcpdump对该容器抓包

# 对dst抓包
tcpdump -i eth0 dst <destination-ip-address>

# 对src抓包
tcpdump -i eth0 src <source-ip-address>

退出网络命名空间(network namespace)

抓包完成后退出当前终端会话,就回到node的OS默认网络命名空间。
在这里插入图片描述

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

识途老码

赞赏是第一生产力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值