前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >容器中的ulimit

容器中的ulimit

作者头像
有点技术
发布2020-07-13 11:20:10
6.6K1
发布2020-07-13 11:20:10
举报
文章被收录于专栏:有点技术有点技术

背景

使用的是公有云,最近要对k8s版本进行升级,在升级之后发发现从我们的web terminal 进入到容器, 拥有sudo权限的用户无法进行sudo命令,即使使用root通过docker exec 进入到容器,依旧无法sudo

代码语言:javascript
复制
sudo: pam_open_session: Permission denied
sudo: policy plugin failed session initialization

定位

进入到容器中我们查看ulimit -a 如下

代码语言:javascript
复制
core file size          (blocks, -c) 5242880
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3806
max locked memory       (kbytes, -l) 82000
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1048576
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

我们基础镜像里面的/etc/security/limits.conf配置如下

代码语言:javascript
复制
* soft core unlimited
* hard core unlimited
* soft nofile 1048576
* hard nofile 1048576
root soft nofile 1048576
root hard nofile 1048576
* soft nproc 102400
* hard nproc 102400

可见我们在/etc/security/limits.conf配置文件中的配置并未生效, 查看psp,公有云也未做psp相关的初始配置,通过docker inspect查看,并没有相关ulimit设置, 最终查看systemd发现docker.service配置多了一行

代码语言:javascript
复制
LimitCORE=5368709120

这里的值是单位是字节 和 内部ulimit看到的有所差异,ulimit看到的是block数

systemd 中有关limit的配置对照表如下

指令

等价的ulimit 命令

单位

LimitCPU

ulimit -t

LimitFSIZE=

ulimit -f

字节

LimitDATA=

ulimit -d

字节

LimitSTACK=

ulimit -s

字节

LimitCORE=

ulimit -c

字节

LimitRSS=

ulimit -m

字节

LimitNOFILE=

ulimit -n

文件描述符的数量

LimitAS=

ulimit -v

字节

LimitNPROC=

ulimit -u

进程的数量

LimitMEMLOCK=

ulimit -l

字节

LimitLOCKS=

ulimit -x

锁的数量

LimitSIGPENDING=

ulimit -i

信号队列的长度(排队的信号数量)

LimitMSGQUEUE=

ulimit -q

字节

LimitNICE=

ulimit -e

谦让度

LimitRTPRIO=

ulimit -r

实时优先级

LimitRTTIME=

不存在

微秒

由此可见最终生效的是systemd下core file size 的值,那为什么会出现上面的报错呢?

pam_limits.so

查看linux sudo pam 配置如下

代码语言:javascript
复制
#%PAM-1.0
auth       include      system-auth
account    include      system-auth
password   include      system-auth
session    optional     pam_keyinit.so revoke
session    required     pam_limits.so

可以看到sudo加载了pamlimits.so模块,而limits.conf 文件实际是 Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pamlimits.so 的配置文件

有关pam类型如下

由此可知当我们执行sudo时触发了pamlimits.so模块的某些限制,导致执行失败, 实际上pamlimits.so的实现主要包括以下步骤:

  • 解析配置文件 /etc/security/limits.conf及/etc/security/limits.d下的*.conf文件
  • setup_limits调用setrlimits生效配置

parm_limits 的说明文档

setrlimit和getrlimit系统调用

pam_limits.so进行了setrlimit和getrlimit系统调用,setrlimit和getrlimit的定义如下

代码语言:javascript
复制
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);

在linux系统中,Resouce limit指在一个进程的执行过程中,它所能得到的资源的限制,比如进程的core file的最大值,虚拟内存的最大值等。Resouce limit的大小可以直接影响进程的执行状况。其有两个最重要的概念:soft limit 和 hard limit。

soft limit和hard limit概念如下:

  • soft limit是指内核所能支持的资源上限。对于RLIMIT_COREsoft limit最大能是unlimited。
  • hard limit在资源中只是作为soft limit的上限,当你设置hard limit后,你以后设置的soft limit只能小于hard limit。
代码语言:javascript
复制
struct rlimit {
  rlim_t rlim_cur;  //soft limit
  rlim_t rlim_max;  //hard limit
};

根据man文档在进行setrlimit系统调用时操作系统会检查新的值是否超过当前hard limit,对于root没有这种限制

返回错误码如下 EFAULT:rlim指针指向的空间不可访问 EINVAL:参数无效 EPERM:增加资源限制值时,权能不允许

EPERM对应的返回为:Operation not permitted 这和我们手动执行ulimit的返回一致

setrlimit man文档

容器内的root如何突破限制

在docker没有添加 CAPSYSRESOURCE 时,才可以突破内核上限,所以docker内部的root并不是真正的root

代码语言:javascript
复制
docker run --cap-add CAP_SYS_RESOURCE
# 或者
docker run --privileged

这样容器内部的root用户就可以突破该ulimit限制

容器ulimit设置原则

  • dockerd和容器都设置为unlimited
  • 容器设置的limit比宿主机小
  • 为容器添加CAPSYSRESOURCE capability
  • 容器开启privileged(不推荐)
  • 不设置,以dockerd为准
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有点技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 定位
  • pam_limits.so
  • setrlimit和getrlimit系统调用
  • 容器内的root如何突破限制
  • 容器ulimit设置原则
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档