pod基本概念
最小部署单元
可以包含多个容器
一个pod中的容器可以共享网络命名空间
pod是短暂的(可能做一次滚动更新,IP就可能发生变化)
适合放在一个pod中的应用
两个应用之间发生文件交互
比如有两个应用需要共享数据,那么如果通过外部存储共享的方式,受到网络之类的影响,性能较差,可以用到pod中的数据卷进行数据交互
两个应用需要通过127.0.0.1或者socket通信(比如:nginx+php)
两个应用需要发生频繁的调用
Pod常用命令
查看pod
kubectl get po
-o wide 显示较详细信息
-n 指定命名空间
查看service
kubectl get service
删除pod命令
kubectl delete pod {pod名称}
删除当前目录下所有yaml文件生成的pod
kubectl delete -f .
kubectl delete -f {yaml文件名}:删除该yaml文件生成的pod,不会删除yaml文件
如果pod反复重启无法删除,则删除对应控制器
如:kubectl get deployment 获取对应pod的name
kubectl delete {控制器类型} {name前缀}
删除service
kubectl delete service {service名称}
查看pod创建、启动的信息
kubectl describe pod TYPE/NAME
如:kubectl describe pod web-deployment-667d4bd8df-tv2c9
查看容器日志,观察有没有异常的日志
kubectl logs TYPE/NAME
如:kubectl logs web-deployment-667d4bd8df-tv2c9
如果有两个容器:
最后指定[-c CONTAINER]
如:kubectl logs web-deployment-667d4bd8df-tv2c9 -c web2
如果一个pod中有多个容器,想进入不同的容器或看不同容器的日志,使用-c指定
kubectl exec -ti {pod名称} -c {容器名称} -- sh
kubectl logs {pod名称} -c {容器名称}
容器的名称在yaml文件中查看
pod已经启动,进入调试应用
kubectl exec POD [-c CONTAINER] -- COMMAND [args...]
pod中的容器分类
Infrastructure Container:基础容器
维护整个Pod网络空间
InitContainers:初始化容器
先于业务容器开始执行,最先启动的容器
Containers:业务容器
并行启动
Pod 的实现原理
Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume,其实就是一组共享了某些资源的容器
容器的本质是进程,Pod,实际上是在扮演传统基础设施里“虚拟机”的角色;而容器,则是这个虚拟机里运行的用户程序。
Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume,其实就是一组共享了某些资源的容器
容器的本质是进程,Pod,实际上是在扮演传统基础设施里“虚拟机”的角色;而容器,则是这个虚拟机里运行的用户程序。
pod文件释义
apiVersion: apps/v1 kind: Deployment metadata: name: web-deployment annotations: kubernetes.io/change-cause: "django.v1" #记录到revision中的内容,方便回滚 spec: # 副本数,一个副本代表启一个容器,如果一个pod挂了,那么会在其他副本再启一个 replicas: 3 selector: matchLabels: # 标签选择器,一般写两个,上面项目名,下面应用名 project: blog app: django template: metadata: labels: project: blog app: django spec: # 打标签,资源调度使用 nodeSelector: disktype: "ssd" containers: - name: web image: django# 镜像拉取策略 imagePullPolicy: IfNotPresent # 资源限制 resources: # 容器最大使用资源,pod内存如果超出limits,会被k8s kill掉 # 最好都设置资源限制和请求资源值,因为没有限制pod会超出当前node承载能力的话,会造成资源争抢 limits: # 1000m表示一核,500m表示0.5核 cpu: 1000m memory: 512M # 请求的资源值,k8s会根据这个值调度到能容纳的node requests: cpu: 900m memory: 500M # 存活健康检查 livenessProbe: exec: command: - cat - /tmp/healthy # 启动容器后多长时间做健康检查,单位秒 initialDelaySeconds: 5 # 检查周期间隔 periodSeconds: 5 # 就绪健康检查 readinessProbe: exec: command: - cat - /tmp/healthy ports: - containerPort: 80 # 设置容器内的变量 env: - name: ABC value: 123 # 重启策略 restartPolicy: Always # 如果要启动第二个容器,下面继续写 - name: web2 image: nginx # 如果是私有镜像仓库,必须要登陆,这个为了指定登陆私有镜像仓库的凭据 imagePullSecrets: -name: myregistrykey
镜像拉取策略
IfNotPresent:镜像在宿主机上不存在时才拉取
Always:默认值,每次创建Pod都会重新拉取一次镜像(即使镜像已经在宿主机上)
Never:Pod永远不会主动拉取这个镜像
一般都会选择Always
资源限制
为了让k8s稳定的运行,防止某一个pod占用资源过大导致连接挂掉
CPU
2 = 2000m
1 = 1000m
0.5 = 500m
0.25 = 250m
重启策略(restartPolicy)
Always:当容器终止退出后,总是重启容器,默认策略(比如nginx、mysql等需要使用)
OnFailure:当容器异常退出口(退出码为非0),才重启容器
Never:当容器终止退出,从不重启容器(短期运行的应用)
健康检查(Probe)
Probe有两种类型
存活检查(livenessProbe)
如果检查失败,将杀死容器,根据Pod的重启策略来操作
就绪检查(readinessProbe)
如果检查失败,k8s会把Pod从service endpoints中剔除
在生产环境中一般两个检查会一起配置,两个检查除了名称不一样以外,其他都是一样的
Probe支持一下三种检查方法(一般通过查进程,端口来判断)
httpGet
发送HTTP请求,返回200-400范围状态码为存活
# 健康检查 livenessProbe: httpGet: path: /index.html port: 80 # 启动容器后多长时间做健康检查,单位秒 initialDelaySeconds: 5 # 检查周期间隔 periodSeconds: 5
exec
执行Shell命令返回状态码是0为成功
tcpSocket
发起TCP Socket建立成功
pod提供数据卷和infra container解决共享存储和网络
共享存储
比如有A、B两个容器,都需要读写同一个存储设备,那么一般会用到共享存储,但共享存储设备可能不在同一个空间内,会消耗过多的网络资源等,这时可以将两个容器部署在同一个Pod内,使用本地的磁盘来做数据交换,比如利用k8s提供的数据卷,A、B两个容器都读写同一个目录文件完成数据交换
共享网络
k8s在创建一个pod的时候,会默认创建一个负责网络的容器(infra container),该容器会有自己的网络命名空间,这时候把容器A、B加入到这个容器中,就打通了A、B两个容器的网络
nodeName
用于将Pod调度到指定的Node上,因为不经过调度器(scheduler ),所以针对污点之类的,nodeName还是可以分配到已设置污点的node上
apiVersion: v1 kind: Pod metadata: name: pod-example labels: app: nginx spec: # 指定分配到k8s-node2节点 nodeName: k8s-node2 containers: - name: nginx image: nginx:1.15
影响pod调度的因素
1、根据request的值查找有足够资源的node来调度此node
2、nodeSelector:用于将pod调度到匹配Label的node上
给node打标签
kubectl label nodes {node名称} key=value
如:kubectl label nodes k8s-node1 disktype=ssd
查看node的标签
kubectl get node --show-labels
删除node标签(最后横杠,别忘记)
kubectl label nodes k8s-node2 {标签键名}-
如:kubectl label nodes k8s-node1 disktype-
apiVersion: v1 kind: Pod metadata: name: pod-example spec: # 调度到标签为ssd的node上 nodeSelector: disktype: "ssd" containers: - name: nginx image: nginx:1.15
3、nodeAffinity:类似于nodeSelector,可以根据节点上的标签来约束Pod可以调度到哪些节点
相比nodeSelector:
匹配有更多的逻辑组合,不只是字符串的完全相等
调度分为软策略和硬策略,而不是硬性要求
硬: 必须满足,否则启动不成功
软:尝试满足,不保证
操作符:In、Notln、Exists、DoesNotExist、Gt、Lt
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: #硬性要求,如果没有满足标签的node,那么无法启动 requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: # gpu是键 - key: gpu # 意思是哪个node节点含有这个键值,就会调度到哪个node operator: In values: # 这是值 - nvidia-tesla #软性要求 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: group operator: In values: - ai containers: - name: web image: nginx
4、污点(Taint)
避免pod调度到特定的node上
应用场景:
专用节点
配备了特殊硬件的节点
基于污点的驱逐
设置污点:
kubtctl taint node {node名称} key=value:effect
如:kubtctl taint node k8s-node1 gpu=yes:NoSchedule
其中[effect]可取值为:
NoSchedule: 一定不能被调度
PreferNoSchedule:尽量不要调度
NoExecute: 不仅不会调度,还会驱逐node上已有的pod,被驱逐的oid自 动分配至别的node
删除污点:
kubtctl taint node {node名称} key:[effect]-
查看污点:
kubectl describe node | grep -i taint
污点容忍(Tolerations)
apiVersion: v1 kind: Pod metadata: name: pod-taints spec: containers: - name: pod-taints image: busybox:latest # 可以容忍污点等于no的污点类型,并且污点类型为NoSchedule tolerations: - key: "key" operator: "Equal" value: "no" effect: "NoSchedule"
当node设置了污点以后,配置相同的污点容忍就可以分配到该node上
给Pod设置环境变量:
1、自定义变量
2、来自Pod字段,pod本身会携带一些属性值,比如pod名称,分配到哪个节点等,可以从pod中引用这个变量,在容器中使用,比如容器有个程序想知道pod运行在哪个节点上,可以用这个实现
3、来自secret、configmap
具体可查看以下链接