记一次神奇的 pipe 错误

news2025/1/15 16:32:41

1. 写在最前面

笔者负责的服务有一个设计是通过 pipe 在父子进程间传输请求。在物理机上时,父子进程能够正常完成 request 和 response 。但是在上 k8s 后,发现:

  • 父进程在 write 的时候只能写入 4096 字节
  • 子进程在只能读到父进程 write 的 4096 字节,后续读就会读阻塞

如果把服务用 docker 的方式部署又会没有这个问题。简而言之,就是一个非常神奇而又让人抓狂的问题。

2. 问题原因

此问题由两方面导致的:

  • 上 K8s 后,在 pod 内的 pipe 大小,被限制为只能写入 4096 字节

    • 宿主机的 pipe 大小

      在这里插入图片描述

    • 容器内的 pipe 大小

      在这里插入图片描述

  • 服务自身设计问题导致:

    • 笔者负责的服务父进程的 request 的包的大小已经超过了 4096 字节

    • 父进程 write 的时候,使用的非阻塞 write,上 k8s 后写入 pipe 的 buffer 大小为 4096 字节后 buffer 就满了,会到导致写入的数据不完整

3. 解决问题

本着「知其然,还有知其所以然」的精神,先从修改配置「CAP_SYS_RESOURCE」的历史说起吧。

注:CAP_SYS_RESOURCE,忽略资源限制

3.1 CAP 的历史说明

内核从 2.2 开始,Linux 将传统上与超级用户 root 关联的特权划分为不同的单元,称为 CAP。CAP 作为线程的属性存在,每个单元可以独立启用和禁用。

注:Linux 并不真正区分进程和线程

每个进程有三个和能力有关的位图:inheritable(I)、permitted§ 和 effective(E),对应进程描述符 task_struct(include/linux/sched.h) 里的 cap_effective、cap_inheritable、cap_permitted ,所以可以查看 /proc/{PID}/status 来查看进程的能力。

  • cap_effective:当一个进程要进行某个特权操作时,操作系统会检查 cap_effective 的对应的位是否有效
  • cap_permitted:表示进程能够使用的能力,cap_effective 是 cap_permitted 的一个子集
  • cap_inheritable:表示能够被当前进程执行的程序继承的能力

注:笔者之前在物理机上部署的方式是使用特权命令 docker run --privileged,此命令可以继承宿主机大部分的控制权限,有一定的风险性

3.2 CAP 拆分的能力集合说明

  • CAP_CHOWN:修改文件属主的权限
  • CAP_DAC_OVERRIDE:忽略文件的 DAC 访问限制
  • CAP_DAC_READ_SEARCH:忽略文件读及目录搜索的 DAC 访问限制
  • CAP_FOWNER:忽略文件属主 ID 必须和进程用户 ID 相匹配的限制
  • CAP_FSETID:允许设置文件的 setuid 位
  • CAP_KILL:允许对不属于自己的进程发送信号
  • CAP_SETGID:允许改变进程的组 ID
  • CAP_SETUID:允许改变进程的用户 ID
  • CAP_SETPCAP:允许向其他进程转移能力以及删除其他进程的能力
  • CAP_LINUX_IMMUTABLE:允许修改文件的 IMMUTABLE 和 APPEND 属性标志
  • CAP_NET_BIND_SERVICE:允许绑定到小于 1024 的端口
  • CAP_NET_ADMIN:允许执行网络管理任务
  • CAP_NET_RAW:允许使用原始套接字
  • CAP_IPC_LOCK:允许锁定共享内存片段
  • CAP_IPC_OWNER:忽略 IPC 所有权检查
  • CAP_SYS_MODULE:允许插入和删除内核模块
  • CAP_SYS_RAWIO:允许直接访问 /devport、/dev/mem、/dev/kmem 及原始块设备
  • CAP_SYS_CHROOT:允许使用 chroot() 系统调用
  • CAP_SYS_PTRACE:允许跟踪任何进程
  • CAP_SYS_PACCT:允许执行进程的 BSD 使审计
  • CAP_SYS_ADMIN:允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等
  • CAP_SYS_BOOT:允许重新启动系统
  • CAP_SYS_NICE:允许提升优先级以及设置其他进程的优先级
  • CAP_SYS_RESOURCE:忽略资源限制
  • CAP_SYS_TIME:允许改变系统时钟
  • CAP_SYS_TTY_CONFIG:允许配置 TTY 设备
  • CAP_MKNOD:允许使用 mknod() 系统调用
  • CAP_LEASE:允许修改文件锁的 FL_LEASE 标志

3.3 如何知道某个程序的能力集合

通过查看 /proc/{pid}/status ,然后过滤其中的 Cap 字段属性:

  • CapInh: inheritable 表示能够被当前进程执行的程序继承的能力
  • CapPrm: permitted 表示进程能够使用的能力
  • CapEff: effective 当一个进程要进行某个特权操作时,操作系统会检查 cap_effective 的对应的位是否有效

3.3.1 查看只能写入 4096B 大小的程序能力位图

  • 通过 ps 查询到关心的进程 id
  • /proc/{pid}/status | grep Cap 查看进程的能力位图

在这里插入图片描述

注:通过查看 pipe size 的 shell 工具,可以看到当前 00000000000c25fb 是这个值时,pipe 的大小为 4096B

​ pipe size 检验工具: M=0; while printf A; do >&2 printf “\r$((++M)) B”; done | sleep 999

3.3.2 查看能写入 65536B 大小的能力位图

  • 通过 ps 查询到关心的进程 id
  • /proc/{pid}/status | grep Cap 查看进程的能力位图

在这里插入图片描述

注:注:通过查看 pipe size 的 shell 工具,可以看到当前 00000000010c25fb 是这个值时,pipe 的大小为 65536B

3.3.3 比较两个能力位图

capsh 命令可以将下面两个能力位图转义为可读的格式:

  • 00000000000c25fb -> 4096B

  • 00000000010c25fb -> 65536B

在这里插入图片描述

至此真相大白,需要为 pod 增加 CAP_SYS_RESOURCE 的能力。

3.3.4 为 pod 增加 CAP_SYS_RESOURCE 的方法

要为容器添加或删除 Linux 功能,请在容器的 securityContext 部分中包含 capabilities 字段,详细的 Linux capabilities 见 Linux capabilities:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  containers:
  - name: demo
    image: centos:7
    command: ["tail","-f", "/dev/null"]
    securityContext:
      capabilities:
        add: ["SYS_RESOUCE"]

详细的增加参考见:Set capabilities for a Container

6. 碎碎念

最近真的是忙的各种心力交瘁,想抽出点时间学习新知识都感觉有写困难,希望下个月能够规划好工作和生活。「放弃当然很容易,但是坚持就会很酷吖」

  • 给自己买花 陪自己长大
  • 真正要做的事,对神明都不要讲,你一定要如此,万般如此
  • 希望你拥有想哭就哭、想笑就笑的情绪自由,也希望你不管怎样都能有面对负面情绪的能力和重新开始的勇气。

5. 参考资料

  • pipe(2) — Linux manual page
  • capabilities(7) — Linux manual page
  • How big is the pipe buffer?
  • Linux CAP介绍与k8s下配置使用
  • Linux Capabilities 简介
  • Configure a Security Context for a Pod or Container
  • Linux 的 capability 深入分析
  • Docker特权模式:你应该运行特权Docker容器吗?
  • Set capabilities for a Container

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/24275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字信号处理-4-三角函数合成与傅里叶级数

1 三角函数合成 函数正交(数字信号处理-3-函数的正交),那它们相互之间无法通过组合得出对方的表达式,如:sinx 与 cosx 正交,acosnx 是无法表示 sinx 的。相互正交的各类三角函数是制作许多波形的基本单位。…

KT148A语音芯片按键版本一对一触发播放功能描述_V4

目录 一、简介 KT148A语音芯片--按键版本,支持3个IO口一对一触发 。同时也支持用户自己更换芯片内部的声音文件,方法,参考我们另外一份文档的描述“20220704_KT148A芯片自己更换声音的方法V3”。请留意,需要样品联系客服&#xf…

钡铼EdgeIO边缘计算 I/O 控制器

BL200 系列耦合器是一个数据采集和控制系统,基于强大的 32 位微处理器设计, 采用 Linux 操作系统,支持 Modbus,MQTT,OPC UA,Profinet,EtherCAT,Ethernet/IP, BACnet/IP…

程序员月薪8000,丢人吗?

近日,拉勾招聘数据研究院针对平台的程序员群体开展了深度调研,发布了《拉勾招聘2022程序员群体职场洞察报告》,呈现程序员最新的职场薪资水平。 *数据来源拉勾 从上图中可以看到,74%的00后应届毕业生的月薪在1-3万元区间&#…

C++语言的return语句的说明

C语言的return语句的说明 为了完成某一功能的程序指令(语句)的集合,称为函数。在程序中,编写函数的主要目的是将一个需要很多行代码的复杂问题分解为一系列简单的任务来解决,而且,同一个任务(函…

Qt5开发从入门到精通——第十一篇三节(Qt5 事件处理及实例——事件过滤及实例)

提示:欢迎小伙伴的点评✨✨,相互学习c/c应用开发。🍳🍳🍳 博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩‍🚀 文…

WPF XAML介绍

一、XAML 简介 XAML是一种声明性标记语言,它简化了为.NET Framework应用程序创建UI的过程。在声明性XAML标记中创建可见的UI元素,可以折叠隐藏代码,使程序界面编程更加简单和简洁。 XAML直接以程序集中定义的一组特定后备类型表示对象的实例化…

Oracle Primavera Unifier组合管理器(Portfolio Manager)

目录 一:前言 二:介绍​​​​​​​ 一:前言 Oracle Primavera Unifier uDesigner Portfolio Manager 项目组合管理器是公司的预算员/计划工程师可以收集项目(计划和执行中)的成本和进度信息,并对“假设…

Webpack 5 超详细解读(六)

51.TerserPlugin 压缩 JS webapck中提供了压缩 js 代码的方式,可以移除无用代码、替换变量名等,减少编译后文件体积,提升加载速度。 不同mode 在 webpack配置文件 webpack.config.js中通过将 mode设置为 development或者 production,会对代码进行不同的处理。 可以发现,…

使用阿里云发送短信验证码

目录 一、用户注册登录流程 二、使用阿里云发送短信验证码 ⭐生成密钥 ⭐将密钥配置到项目中 ⚪新建properties文件并填入相应信息 ⚪pom配置 ​⚪ 测试代码 ⚪添加签名 ​⚪添加短信发送的模板 💧验证码防盗刷监控 一、用户注册登录流程 二、使用阿里…

Linux服务器更改ssh连接端口

更改ssh连接端口 输入vim /etc/ssh/sshd_config编辑sshd配置 在键盘上按“I”键,进入编辑状态 添加新的远程服务端口,以 222 端口为例。在Port 22下面添加输入Port 222 建议:不要直接修改 22 端口,把Port 22前面的注释符号#删除…

股票买卖Ⅴ

题目描述 给定一个长度为 NNN 的数组,数组中的第 iii 个数字表示一个给定股票在第 iii 天的价格。 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 你不能同时参与多笔交…

高精地图_语义地图_众包地图相关论文笔记

1.20220618_LT-mapper: A Modular Framework for LiDAR-based Lifelong Mapping 20213d-Lidar构建long-term地图分为 SLAM模块(每个session的点云地图通过关键帧构建,对不同session的关键帧进行anchor node检测,基于anchor帧构建的闭环因子实…

VSCode中Java程序入口的数据输入流的常用形式

1.前言 VSCode需要配置好Java环境,配置链接按官网教程即可:Getting Started with Java in Visual Studio Code VSCode目录./vscode下文件说明如下: setting.json : 配置vscode编辑器特性配置,同时基础Java Project中…

如何避免缓存穿透、缓存击穿、缓存雪崩?

缓存雪崩: 缓存雪崩是指缓存同⼀时间⼤⾯积的失效,所以,后⾯的请求都会落到数据库上,造成数据库短时间内承受⼤量请求⽽崩掉。解决方案: 缓存数据的过期时间设置随机,防⽌同⼀时间⼤量数据过期现象发⽣。…

微信小程序接入火山引擎埋点数据

1,文档中心-火山引擎 2,文档中心-火山引擎 3,文档中心-火山引擎 上面的链接是三个最重点的部分。 首先按照1的步骤安装SDK。npm install datarangers/sdk-mp 配置合法域名将https://mcs.volceapplog.com添加到小程序后台的“request合法域…

你能懂的 Reflect 反射

你能懂得 JS 之 Reflect 反射 上一篇文章《Proxy 代理对象使用详解即原理总结》我们详细介绍了 Proxy 代理对象的使用及其工作原理(不了解的同学可以去看看哦),今天我们来聊聊它的好兄弟 Reflect 反射。 特点 Reflect 是一个内置全局对象&a…

[go学习笔记.第十六章.TCP编程] 4.项目-海量用户即时通讯系统-显示在线用户列表,群聊

1.实现功能-完成登录时能返回当前在线用户 用户登录后,可以得到当前在线用户列表 示意图如下: 步骤: (1).编写了server/processBlock/userManager.go package processBlockimport ("fmt" )//因为UserManager实例在服务器中有且只有一个,并且在很多地方都要使用,因…

博客系统前端页面

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 博客系统 前言 一.预期效果 博客列表页效果 博客正文页效果 博客登录页效果 博客编辑页效果 二.实现博客列表页 实现导航栏 实现版心 实现个人信息 …

【DELM分类】基于matlab麻雀搜索算法改进深度学习极限学习机数据分类【含Matlab源码 2235期】

⛄一、麻雀搜索算法改进深度学习极限学习机数据分类 1 深度极限学习机 深度极限学习机算法(Deep Extreme Learning Machine, DELM)又称多层极限学习机.存在N个训练样本,其中 2 麻雀搜索算法(SSA) 2020年,薛建凯等人提出了麻雀搜索算法.麻雀搜索算法是一…