k8s之管理pod
创建完pod后, 如果不指定命名空间,默认都是创建到default的命令空间,可以通过dashborad中的namespace中查看default命令空间中的pod情况
例如:pod定义模板nginx.yaml,如图:

删除pod:
1、首先查询pod信息:在管理节点执行命令如下:
kubectl get pod -n sf-one

可看出命名空间sf-one中有一个Pod的2个副本,sf-one表示命名空间,此内容为在yaml文件中定义的,如果不指定就是默认的default命名空间
2、通过如下命令查询控制器deployment的名称为gongguan,执行命令如下:
kubectl get deployment -n sf-one

从上图中也可以看出,此控制器目前管理了一个pod并且名称为gongguan,但是目前只有一个副本启动,另外一个副本没有启动,如果要删除此Pod,需要先将控制器中的pod删除,否则控制器还是会根据策略重新创建Pod
3、执行如下命令删除控制器deployment中的名称,如下:
kubectl delete deployment gongguan -n sf-one

删除之后,再次执行命令查看pod信息,发现此Pod 已经成功删除,如图:

注意:-n sf-one表示指定命令空间
pod扩容
1、首先通过命令查询控制器deployment中的pod信息,如图:

从上图中可以看出,名称为Nginx的deploy控制器管理的pod副本数量为2个
2、使用scale命令,对其中的pod进行扩容,如图:

3、再次执行查询命令,可以看到pod副本数量已经变成了3个,如图:

注意:如果要缩容,那么还是通过scale命令进行,修改replicas的数量即可
pod更新
deployment控制器支持两种镜像更新策略,重建更新和滚动更新(默认),可以通过strategy进行配置
strategy: 指定新的pod替换旧的pod的策略,支持两个属性:
type: 指定策略类型,支持两种策略
Recreate:在创建新Pod之前先杀掉已经存在的pod
RollingUpdate:滚动更新,杀死一部分就启动一部分,更新过程中存在两个版本的pod
rollingUpdate: 当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性
maxUnavailable:用于指定升级过程中不可用Pod最大数量,默认为25%
maxSurage: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%
一、重建更新:
1、编辑pod定义文件yaml,在spec下添加更新策略,如图:

2、执行下面命令变更镜像:
kubectl set image deployment pod名称 容器名称:版本 -n 命名空间
3、执行下面命令可以查看更新过程:
kubectl get pod -n 命名空间 -w
通过set image方式更新镜像适合于本地有镜像,如果从仓库拉取那么会出现错误
二、滚动更新(默认即为滚动更新)
1、例如:在nginx.yaml中未定义更新策略,如图:

- 纠正:第4行中的name表示的是deployment的名称,非pod名称
2、通过kubectl describe deployment nginx 查看pod情况,可以看到默认的更新策略即为滚动更新,如图:

3、通过kubectl edit 命令来修改deployment的配置,将 将spec.template.spec.containers[0].image 的值进行更改实现更新,如图:

直接修改下方的版本号即可,如图:

通过命令kubectl rollout status deployment/nginx可以查看更新过程,如图:

再次查看镜像版本情况,发现已经更新了,如图:

注意: Deployment的更新操作是在Deployment进行部署(Rollout)时被触发的,这意味着当且仅当Deployment的Pod模板(即spec.template )被更改时才会创建新的修订版本,例如更新模板标签或容器镜像。其他更新操作(如扩展副本数)将不会触发Deployment的更新操作,这也意味着我们将Deployment回滚到之前的版本时,只有Deployment的Pod模板部分会被修改。
pod回滚
将上面发布的版本进行回滚,执行命令如下:

回滚到指定的版本,使用–to-revision,如图:

查看更新历史
执行命令如下:
kubectl rollout history deployment nginx

revision表示版本号,可以看到CHANGE-CAUSE为none,如果在创建deployment时指定–record参数, 就可以在CHANGECAUSE列看到每个版本使用的命令了,例如:kubectl create -f nginx.yaml –record
注意:deployment/nginx 和deployment nginx相同
查看特定版本的信息命令如下:
kubectl rollout history deployment nginx –revision=3
pod调度策略
通过deployment创建完Pod后,此Pod会被随机分配到集群中的任意一个节点(包括master节点),此时属于自动调度策略,如果想要pod只工作在指定的节点,如:只工作在worker节点,可以通过手动设置调度策略的方式,几种策略方式如下:
一、 NodeSelector:定向调度:
可以通过Node的标签(Label)和Pod的nodeSelector属性相匹配来达到调度目的
1、 首先通过kubectl label命令给目标Node打上一些标签:

上图表示将worker1节点和worker2节点都打上标签zone=one
通过命令kubectl describe nodes 加节点名可以查看标签情况,如图:

2、在资源定义文件nginx.yaml中,添加节点标签信息,如图:

3、用命令kubect create -f nginx.yaml创建Pod,创建完成后通过kubectl get pods -o wide查看pod在哪个节点上,如图:

从上图中的内容可以看出此pod已经运行在两个worker节点上,当其中一个节点出现故障时,上面的pod会被调度到另一个节点上,从而保证副本数量不变。
二、 NodeAffinity:Node亲和性调度:
NodeAffinity意为Node亲和性的调度策略,是用于替换NodeSelector的全新调度策略。 目前有两种节点亲和性表达。
1、 RequiredDuringSchedulingIgnoredDuringExecution:必须满足指定的规则才可以调度Pod到 Node上(功能与nodeSelector很像,但是使用的是不同的语法),相当于硬限制。
2、 PreferredDuringSchedulingIgnoredDuringExecution:强调优先满足指定规则,调度器会尝试调度Pod到Node上,但并不强求,相当于软限制。多个优先级规则还可以设置权重(weight)值,以定义执行的先后顺序。
注意: IgnoredDuringExecution的意思是:如果一个Pod所在的节点在Pod运行期间标签发生 了变更,不再符合该Pod的节点亲和性需求,则系统将忽略Node上Label的变化,该Pod能继续在该节点运行。
下面的例子设置了NodeAffinity调度的如下规则:
requiredDuringSchedulingIgnoredDuringExecution要求只运行在amd64的节点上(beta.kuber netes.io/arch In amd64)
preferredDuringSchedulingIgnoredDuringExecution的要求是尽量运行在磁盘类型为ssd(disk -type In ssd)的节点上 ,如图:

从上面的配置中可以看到In操作符,NodeAffinity语法支持的操作符包括In、NotIn、Exists、DoesNotExist、Gt、Lt。虽然没有节点排斥功能,但是用NotIn和DoesNotExist就可以实现排斥的功能了。
NodeAffinity规则设置的注意事项如下:
- 如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都得到满足,Pod才能最终运行在指定的Node上。
- 如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
- 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpre ssions才能运行该Pod。
暂停和恢复Deployment 的部署操作,以完成复杂的修改
由于每一次修改deployment之后都会重新触发更新, 为了避免频繁触发Deployment的更新操作, 可以先暂停Deployment的更新操作,然后进行配置修改,再恢复Deployment,一次性触发完整的更新操作,就可以避免不必要的Deployment更新操作了。
例如:还是用之前创建的nginx为例子,先暂停此pod,如图:

然后通过kubectl set image或者kubectl edit deployment nginx修改配置文件,例如版本更新:

查看Deployment的历史记录,发现并没有触发新的Deployment部署操作:

最后,恢复这个Deployment的部署操作:

进行验证,发现版本已经升级成功。
通过kubectl describe deployment nginx可以看到升级过程,如图:

Pod容器共享Volume
同一个Pod中的多个容器能够共享Pod级别的存储卷Volume。Volume可以被定义为各种类型,多个容器各自进行挂载操作,将一个Volume挂载为容器内部需要的目录,如图:

1、下面的yaml文件中包含两个容器,tomcat和busybox,在Pod级别设置Volume“app-logs”,用于tomcat容器向其中写日志文件,busybox容器从中读日志文件,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: tomcat-busybox
spec:
containers:
- name: tomcat
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
volumeMounts:
- name: app-logs
mountPath: /usr/local/tomcat/logs
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh","-c","tail -f /logs/catalina*.log"]
volumeMounts:
- name: app-logs
mountPath: /logs
volumes:
- name: app-logs
emptyDir: {}

说明:设置的Volume名称为app-logs,类型为emptyDir(也可以设置其他类型),挂载到tomcat容器内的/usr/local/tomcat/logs目录下,同时挂载到busybox容器内的/logs目录,tomcat 容 器 在 启 动 后 会 向 /usr/local/tomcat/logs 目 录 写 文 件,busybox容器就可以读取其中的文件了
2、创建pod,kubectl apply -f tomcat-busybox.yaml,然后执行命令查看日志,如图:

执行命令进入容器内部也可以看到日志,命令如下:
kubectl exec -it tomcat-busybox -c tomcat -- tail -n 50 /usr/local/tomcat/logs/catalina.2022-01-05.log
#-c tomcat表示指定pod内的tomcat容器,因此pod里有两个容器
Pod的创建过程如下:
- 用户通过kubectl或者其他的API客户端提交PodSpec给API Server
- API Server 将pod的信息存入到etcd中,并返回确认信息给客户端
- Schedule(调度器) 通过其wardher监测到API Server创建了新的Pod对象,为该Pod对象挑选一个工作节点,并将结果信息更新至API Server
- 调度结果由API Server更新至etcd存储系统,并同步给Schedule
- 相应节点的kubelet监测到由调度器绑定到本节点的pod后会读取其配置信息,并由本地容器运行时创建相应的容器,启动pod后将结果返回给API Server
- API Server将kubelet发来的pod状态信息存入etcd系统中,并将确认信息发给kubelet
Pod的删除过程如下:
- 用户发送删除Pod的命令
- API 服务器中的Pod对象随着时间推移而更新,在宽限期(默认30s)内,Pod被视为dead
- 将Pod标记为Terminating状态
- kubelet同时监测到pod转变为Termination后,同时启动Pod关闭过程
- 端点控制器同时监控到Pod对象的关闭行为,将其从所有匹配到此端点的service资源从端点列表移除
- 如果当前的Pod对象定义了preStop钩子句柄,在其标记为terminating后会以同步方式启动执行,若宽限期结束后,preStop仍未执行完,则重新执行第二步,并获取一个时长为2s的宽限期
- pod对象中的容器收到TERM信号(以正常方式中止容器)
- 宽限期结束后,如果还存在一个运行的进程,此时Pod对象会收到SIGKILL信号(强制中断)
- kubelet请求API Server将其pod的宽限期设置为0,从而删除操作,同时对用户不可见
一个 Pod 中的应用容器共享五种资源:
- PID 命名空间:Pod 中的不同应用程序可以看到其他应用程序的进程 ID
- network命名空间:Pod 中的多个容器能够访问同一个IP和端口范围
- IPC 命名空间:Pod 中的多个容器能够使用 SystemV IPC 或 POSIX 消息队列进行通信
- UTS 命名空间:Pod 中的多个容器共享一个主机名(uts: linux的命名空间子系统,主要用来完成对容器HOSTNAME和domain的隔离,使得用户在容器中查看到的信息是当前容器的系统、版本,不同于主机)
- Volumes(共享存储卷):Pod 中的各个容器可以访问在 Pod 级别定义的 Volumes


