TKE集群,一次磁盘挂载问题处理
1. 导语
随着云原生概念的普及,越来越多的企业,已经将业务迁移到容器平台上,以充分利用容器、Kubernetes、服务网格来完成基础架构的转型升级。
然而,在业务上云过程中,不可避免的遇到使用上的问题。这里,我们以腾讯云容器服务TKE为例,分析一次PVC卷挂载异常的处理过程。
2. 背景介绍
Kubernetes 官方层面,支持多种存储形式的挂载,常见的类型有:
- hostPath:挂载host 机器上的一个文件,或者目录到业务pod内部。对大部分业务pod 来说,不需要此种配置。
- emptyDir:在pod运行前,预先创建。其生命周期,伴随Pod;如果Pod被删除,内部数据将会永远消失,但是Pod重启不会清除对应数据。一个使用场景,即在业务Crash后,作为数据还原点。
- secret:常用来存储一些敏感数据,如密码——需要事先创建,然后挂载到Pod内部。
- nfs:支持网络文件系统挂载,可以被多个Pod共同挂载,从而实现数据文件在Pod间的共享。
- csi:容器存储接口,可以向容器编排系统暴露任意类型的存储,进而挂载到业务Pod内,其使用形式目前多基于PVC。
- downwardApi:可以环境变量或者volume file 形式,暴露pod或者容器自身的信息,到业务容器内部。
- pvc:可以用来挂载一个持久化存储卷PersistentVolume,使用过程中,可以屏蔽底层的存储类型,如磁盘、文件存储等。
- configMap:将配置数据放在配置集中,后续可以作为volume 挂载到Pod内,也可以作为容器内部的环境变量——需要事先创建,使用较为广泛。
腾讯云TKE,针对以上大部分类型,已有对应的支持。这里,我们来看一个PVC挂载使用报错的问题。
业务异常:
查看事件报错:kubectl get ev -n ***, 发现如下异常:
比较明显的,可以看出业务Pod 运行前,磁盘挂载操作失败。对应的磁盘,依然占用未被释放。
3. 场景分析
(1)查看Pod 挂载的 pvc:
kubectl describe pod *** -n *** |grep -3 -i persis
(2)查看PVC对应PV:
kubectl get pvc vol-****-c0woyfk2ycw0-22 -n ****
业务Pod PVC 绑定的volume 即:pvc-65273f8d-64f8-11ea-b2dc-525400e94be5
(3)查看PV对应的磁盘信息:
kubectl get pv pvc-65273f8d-64f8-11ea-b2dc-525400e94be5 -o yaml |grep -3 -i disk
(4)查看磁盘挂载的CVM信息:
在云服务器控制台,云硬盘模块,键入对应的磁盘ID,即可过滤出特定的磁盘信息。然后,点击进入,查询该磁盘所属的CVM实例信息。
(5)登陆CVM,排查异常,检查磁盘是否依然被占用;
登陆CVM过程,此处忽略,首先查看磁盘对应信息:
查看磁盘设备信息
#ls /dev/disk/by-id
然后,使用lsof 命令排查对应磁盘是否被进程占用:
#以 vdb 磁盘为例
#lsof /dev/vdb
如果是,kill 释放;反之,尝试手动umount在CVM内部卸载,随后在CVM控制台卸载对应磁盘。
4. 解决处理
参考相关资料,磁盘挂载的过程,有遵循以下流程,即:
Provision -> Attach -> Mount; Unmount -> Detach -> Delete
- Provision: 创建磁盘
- Attach:绑定磁盘到CVM机器
- Mount:挂载磁盘到特定路径下
- UnMount:卸载磁盘设备
- Detach:解除磁盘跟CVM的绑定
- Delete:删除磁盘
所以,参考磁盘挂载流程及上述场景分析,在特定CVM上排查处理即可:
(1)lsof 排查未未释放进程,手动kill
(2)将已经mount 的磁盘,进行unmount , 然后在CVM 控制台上卸载对应磁盘。
至此:挂盘问题修复-》新Pod挂载PVC成功-》业务Pod运行起来。
5. 参考资料
https://kubernetes.io/docs/concepts/storage/volumes
- 写一个BASIC认证的https协议
- java发送邮件功能,以发送qq邮件为例
- spring boot加载复杂的yml文件获取不到值的问题
- JUC包下的CountDownLatch,CyclicBarrier,Semaphore
- java队列,ArrayBlockingQueue
- 多线程使用wait和notify做生产者消费者模型导致线程全部假死
- 偏执的iOS逆向研究员:收集全版本的macOS iOS+越狱+内核调试
- java 多线程暂停与恢复:suspend,resume
- ArrayList底层实现
- Master-work模式
- Condition控制线程通信:java三个线程循环打印ABC
- java根据wait,notify,synchronize关键字自定义队列
- ActiveMQ几个重要的配置文件
- TiDB 在 Ping++ 金融聚合支付业务中的实践
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 在 Linux 系统中手动滚动日志的方法
- Linux进程管理工具supervisor安装配置教程
- Linux执行可执行文件提示No such file or directory的解决方法
- 详解bash中的脚本调试机制
- 在 Linux 上查看和配置密码时效的方法
- CentOS7中使用shell脚本安装python3.8环境(推荐)
- linux定时任务的一些相关操作汇总
- Linux nohup命令原理及实例解析
- 基于centos7快速安装mysql5.7教程解析
- Centos8下django项目部署 nginx+uwsgi的教程
- 3分钟短文:Laravel把数据验证的手伸向“请求体”
- 「Redis」字符串
- Elasticsearch:pipeline aggregation 介绍
- Qt音视频开发32-Onvif网络设置
- 3分钟短文:说说Laravel模型关联关系最单纯的“一对一”