Docker资源隔离(namespace,cgroups)
nanshan 2024-10-30 02:54 29 浏览 0 评论
一、概述
Docker容器的本质是宿主机上的一个进程。Docker通过namespace实现了资源隔离,通过cgroups实现了资源限制,通过写时复制机制(copy-on-write)实现了高效的文件操作。
二、Linux内核的namespace机制
- namespace 机制提供一种资源隔离方案。
- PID,IPC,Network等系统资源不再是全局性的,而是属于某个特定的Namespace.
- 每个namespace下的资源对于其它的namespace下的资源是透明的,不可见的。
- Linux内核实现namespace的一个主要目的就是实现轻量级虚拟化(容器)服务,在同一个namespace下的进程可以感知彼此的变化,而对外界的进程一无所知,以达到独立和隔离的目的。
三、namespace(命名空间)可以隔离哪些?
- 文件系统需要是被隔离的
- 网络也是需要被隔离的
- 进程间的通信也要被隔离
- 针对权限,用户和用户组也需要隔离
- 进程内的PID也需要与宿主机中的PID进行隔离
- 容器也要有自己的主机名
有了以上的隔离,我们认为一个容器可以与宿主机和其他容器是隔离开的。 恰巧Linux 的namespace可以做到这些。
namespace | 隔离内容 | 系统调用参数 |
UTS | 主机名与域名 | CLONE_NEWUTS |
IPC | 信号量、消息队列和共享内存 | CLONE_NEWIPC |
Network | 网络设备、网络栈、端口等 | CLONE_NEWNET |
PID | 进程编号 | CLONE_NEWPID |
Mount | 挂载点(文件系统) | CLONE_NEWNS |
User | 用户和用户组 | CLONE_NEWUSER |
3.1、namespace的操作
- namespace的API包括clone() setns() unshare() 还有/proc下的部分文件
- 为了确定隔离的是那些namespace,需要指定以下6个参数的一个或多个 |进行分隔。6个参数就是上面表中提到的CLONE_NEWUTS、CLONE_NEWIPC、CLONE_NEWPID、CLONE_NEWNET、CLONE_NEWUSER
3.2、clone()
- 使用clone() 来创建一个独立namespace的进程,是最常见的做法,也是Docker使用namespace最基本的方法。
- clone() 是 Linux 系统调用fork() 的一种更通用的实现方式,可以通过flags来控制使用多少功能。
3.3、/proc/[pid]/ns
用户可以在/proc/[pid]/ns文件下看到指向不同namespace的文件。
$ docker ps
$ docker exec -it host2-c10 hostname
# f057b4b03eb8就是docker ID
$ ps -ef|grep f057b4b03eb8
$ ls -l /proc/3571/ns
中括号内的为namespace号。如果两个进程指向的namespace号相同,那么说明它们在同一个namespace。
设置link的作用是,即便该namespace下的所有进程都已经结束,这个namespace也会一直存在,后续的进程可以加入进来。
3.4、setns()
- Docker中 使用 docker exec命令在已经运行着的命令执行一个新的命令就需要使用setns() 。
- 通过setns()系统调用,进程从原来的的namespace加入某个已经存在的namespace
- 通常为了不影响进程的调用者,也为了使新加入的pid namespace生效,会在setns()函数执行后使用clone()创建子进程继续执行命令,让原先的进程结束运行。
int setns(int fd, in nstype);
#fd 表示要加入namespace的文件描述符。是一个指向/proc/[pid]/ns目录的文件描述符,打开目录链接可以获得
#nstype 调用者可以检查fd指向的namespace类型是否符合实际要求,该参数为0则不检查
为了把新加入的namespace利用起来,需要引入execve()系列函数,该函数可以执行用户命令,常用的就是调用/bin/bash并接受参数。
3.5、unshare()
- 通过unshare() 在原先的进程上namespace隔离
- unshare与clone很像,unshare不需要新启动一个进程,在原有的进程上就可以进行使用。但是docker并没有使用
3.6、fork() 系统调用
fork并不属于namespace的API
3.7、使用Namespace进行容器的隔离有什么缺点呢?
- 最大的缺点就是隔离不彻底,其它进程会跟docker抢占资源,虽然可以通过cgroups限制docker使用的资源,但是限制不了其它进程使用docker的资源。
- 在Linux内核中,有很多资源和对象是不能被Namespace化的,最典型的例子是:时间即如果某个容器修改了时间,那整个宿主机的时间都会随之修改
四、通过Linux的 cgroups控制docker进程资源
1)cgroups简介
cgroups是Linux的另外一个强大的内核工具,有了cgroups,不仅可以限制被namespace隔离起来的资源,还可以为资源设置权重、计算使用量、操控任务(进程或县城)启停等。说白了就是:cgroups可以限制、记录任务组所使用的物理资源(包括CPU,Memory,IO等),是构建Docker等一系列虚拟化管理工具的基石。
2)查看docker cgroups
$ ls -l /sys/fs/cgroup/*/docker -d
3)cgroups子系统介绍
cpu 子系统,主要限制进程的 cpu 使用率。
cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
memory 子系统,可以限制进程的 memory 使用量。
blkio 子系统,可以限制进程的块设备 io。
devices 子系统,可以控制进程能够访问某些设备。
net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace。
4)cgroups 的作用
1、资源限制
cgroups可以对任务使用的资源(内存,CPU,磁盘等资源)总额进行限制。
如 设定应用运行时使用的内存上限,一旦超过配额就发出OOM提示
2、优先级分配
通过分配的CPU时间片数量以及磁盘IO带宽大小,实际上就相当于控制了任务运行的优先级
3、资源统计
cgroups可以统计系统的资源使用量
如CPU使用时长,内存用量等,这个功能非常适用于计费
4、任务控制
cgroups 可以对任务进行挂起、恢复等操作
5)使用stress工具压测CPU和内存
使用Dockerfile来创建一个基于Centos的stress工具镜像
$ mkdir -p /opt/stress
$ vi /opt/stress/Dockerfile
FROM centos:7
MAINTAINER chen "liugp@tom.com"
RUN yum install -y wget
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install -y stress
新建镜像
$ cd /opt/stress/
$ docker build -t centos:stress .
1、内存限制
CPU 限制相关参数
选项 | 描述 |
--cpuset-cpus="" | 允许使用的 CPU 集,值可以为 0-3,0,1 |
-c,--cpu-shares=0 | CPU 共享权值(相对权重) |
cpu-period=0 | 限制 CPU CFS 的周期,范围从 100ms~1s,即[1000, 1000000] |
--cpu-quota=0 | 限制 CPU CFS 配额,必须不小于1ms,即 >= 1000 |
--cpuset-mems="" | 允许在上执行的内存节点(MEMs),只对 NUMA 系统有效 |
其中--cpuset-cpus用于设置容器可以使用的 vCPU 核。-c,--cpu-shares用于设置多个容器竞争 CPU 时,各个容器相对能分配到的 CPU 时间比例。--cpu-period和--cpu-quata用于绝对设置容器能使用 CPU 时间。
1)创建容器的CPU权重控制
- 默认情况下,每个docker容器的cpu份额都是1024,单独一个容器的份额是没有意义的,只有在同时运行多个容器时,容器cpu的加权效果才能体现出现。
- cgroups只在容器分配的资源紧缺时,即需要对容器使用的资源进行限制时,才会生效。因此,无法单纯的根据某个容器的cpu份额来确定有多少cpu资源分配给它,可以通过cpu share参数可以设置容器使用cpu的优先级,比如启动了两个容器及运行查看cpu的cpu的使用百分比
创建两个容器,分别制定不同的权重比
# --cpu-shares 指定使用cpu的权重
# stress -c 指定产生子进程的个数
$ docker run -itd --name cpu512 --cpu-shares 512 centos:stress stress -c 10
$ docker run -itd --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10
# 查看
$ docker exec -it cpu512 top
$ docker exec -it cpu1024 top
分别进入cpu512和cpu1024之后可以看到,%cpu的比例是1:2,符合我们设置的–cpu-shares参数。
2)cpu core控制
对于多核cpu的服务器,docker还可以控制容器运行使用那些cpu内核,以及使用–cpuset-cpus参数,这对于具有多cpu服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置。
执行以下命令需要宿主机为双核,表示创建的容器只能使用两个内核/使用哪几个CPU,最终生成cgroup的cpu内核配置如下:
$ docker run -itd --name cpu1 --cpus=2 centos:stress
# 指定使用哪几个cpu(0和3)
$ docker run -itd --name cpu1 --cpuset-cpus="0,3" centos:stress
# 指定使用哪几个cpu(0,1,2),只执行这个行
$ docker run -itd --name cpu1 --cpuset-cpus="0-2" centos:stress
查看
$ docker exec -it cpu1 bash
$ cat /sys/fs/cgroup/cpuset/cpuset.cpus
# 上面是登录到容器上查,其实也可以在宿主机上查,找到容器对应的容器ID
$ docker ps --no-trunc
$ cat /sys/fs/cgroup/cpuset/docker/7ca231149ecb0e06cbabda944697c0787c9a9e1f77565fd001aa978f4b3adede/cpuset.cpus
2、内存限制
与操作系统类似,容器可使用的内存包括两部分:物理内存和swap;Docker 默认容器交换分区的大小和内存相同;若没有设置memory和memory-swap选项,则该容器可以使用主机的所有内存,没有限制。
内存限制相关的参数
选项 | 描述 |
-m,--memory | 内存限制,格式是数字加单位,单位可以为 b,k,m,g。最小为 4M |
--memory-swap | 内存+交换分区大小总限制。格式同上。必须必-m设置的大 |
--memory-reservation | 内存的软性限制。格式同上 |
--oom-kill-disable | 是否阻止 OOM killer 杀死容器,默认没设置 |
--oom-score-adj | 容器被 OOM killer 杀死的优先级,范围是[-1000, 1000],默认为 0 |
--memory-swappiness | 用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数 |
--kernel-memory | 核心内存限制。格式同上,最小为 4M |
1)允许容器最多使用200M的内存和300M的swap
$ docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
#--vm 1 ,代表启动一个内存工作线程
#--vm-bytes 280 M ,代表每个线程可以分配280M内存
2)容器中的进程最多能使用 500M 内存,在这 500M 中,最多只有 50M 核心内存。
docker run -it -m 500M --kernel-memory 50M ubuntu:16.04 /bin/bash
核心内存
核心内存和用户内存不同的地方在于核心内存不能被交换出。不能交换出去的特性使得容器可以通过消耗太多内存来堵塞一些系统服务。
3、磁盘IO配额控制
相对于CPU和内存的配额控制,docker对磁盘IO的控制相对不成熟,大多数都必须在有宿主机设备的情况下使用。主要包括以下参数:
选项 | 描述 |
–device-read-bps | 限制此设备上的读速度(bytes per second),单位可以是kb、mb或者gb。 |
–device-read-iops | 通过每秒读IO次数来限制指定设备的读速度。 |
–device-write-bps | 限制此设备上的写速度(bytes per second),单位可以是kb、mb或者gb。 |
–device-write-iops | 通过每秒写IO次数来限制指定设备的写速度。 |
–blkio-weight | 容器默认磁盘IO的加权值,有效值范围为10-100。 |
–blkio-weight-device | 针对特定设备的IO加权控制。其格式为DEVICE_NAME:WEIGHT |
1)Block IO的限制
默认情况下,所有容器平等地读写磁盘,可以通过设置–blkio-weight参数来改变容器block IO的优先级。
$ docker run -it --name container_A --blkio-weight 600 centos:stress
$ cat /sys/fs/cgroup/blkio/blkio.weight
相关推荐
- ssh终端xshell日志查看命令(xshell怎么看日志)
-
现在我们云服务器运维较多用的是SSH工具,其中常用的包括PUTTY、XSHELL等,其实大同小异界面UI稍微不同,但是都可以进入远程连接。这里有朋友提到如何查看服务器的日志文件,这个其实和是否使用XS...
- 使用 Fail Ban 日志分析 SSH 攻击行为
-
通过分析`fail2ban`日志可以识别和应对SSH暴力破解等攻击行为。以下是详细的操作流程和关键分析方法:---###**一、Fail2ban日志位置**Fail2ban的日志路径因系统配置...
- 如何高效读取Linux日志文件?这些命令要熟记于心!
-
在Linux系统中,日志文件通常存储在/var/log目录下。比如,/var/log/syslog(或/var/log/messages,视发行版而定)记录系统整体事件,/var/log/a...
- Windows服务器远程登录日志查询方法,linux查看登录日志方法
-
概述本文介绍Windows、Linux服务器查询系统的远程登录日志方法。根据服务器所使用的操作系统不同,有以下两种查询方法。Linux操作系统的登录日志查询通过远程连接登录Linux服务器,使用roo...
- iptables防火墙如何记录日志(防火墙日志查看)
-
例如:记录所有ssh服务的登录的日志首先,我们需要了解如何将所有的iptables的INPUT链数据包记录到/var/log/messages中。如果你已经有一些iptables规则了,那么将记录日志...
- 如何安全管理SSH密钥以防止服务器被入侵
-
SSH密钥安全管理实施指南(2025年更新版)一、密钥生成与存储规范高强度密钥生成bashCopyCodessh-keygen-ted25519-a100#生成ED25519算法密钥(比...
- 在CentOS上安装nginx服务器(centos搭建代理服务器)
-
一、环境描述1.虚拟机配置CPU:单核内存:2GB硬盘:120GBIP:10.24.17.1082.操作系统版本:CentOS6.6x86_64安装方式:Minimal3.虚拟化环境VM...
- CentOS7安全加固的一份整理规划建议
-
◆更新系统:及时更新CentOS7操作系统版本和安全补丁,确保系统以最新状态运行。◆关闭不必要的服务:在运行系统时,应关闭不需要的服务和端口,以减少系统暴露的攻击面。◆安装防火墙:使用iptables...
- 第四十七天-二叉树,centOS安装tomcat,Maven,vsftpd
-
学习笔记:1.Maven是Apache下的一个纯Java开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。Maven...
- Linux远程桌面连接使用教程 Widows终端远程连接Linux服务器
-
一、前言为什么不是远程连接Linux服务器?因为我不会,远程连接window我就用电脑自带的“远程桌面连接”。以下所述都是在CentOS操作系统下的。服务器刚换成Linux的时候很迷茫,感觉无从下手...
- CentOS 安全加固操作,保护你的操作系统
-
系统加固是保障系统安全的重要手段,对于维护企业数据安全、用户隐私以及系统稳定运行具有重要意义。加固后的系统更加健壮和稳定,能够有效减少因安全问题导致的系统故障和停机时间,提高系统的可用性和可靠性。通过...
- Dockerfile部署Java项目(docker如何部署java项目)
-
1、概述本文主要会简单介绍什么是Docker,什么是Dockerfile,如何安装Docker,Dockerfile如何编写,如何通过Dockerfile安装jar包并外置yaml文件以及如何通过do...
- CentOS7云主机部署Fail2ban阻断SSH暴力破解
-
关于Fail2banFail2ban可以监视你的系统日志,然后匹配日志的错误信息(正则式匹配)执行相应的屏蔽动作(一般情况下是调用防火墙屏蔽)例如:当有人在试探你的HTTP、SSH、SMTP、FTP密...
- 在CentOS7上用源码编译安装PostgreSQL
-
1、新建postgres用户#useraddpostgres&&passwdpostgres2、安装依赖包#yum-yinstallmakegccgcc-c++readline...
- pure-ftpd 使用(ftp prompt命令)
-
pure-ftpd是一个免费的ftp软件,其他介绍就不多说了。我们直接开始主题安装centosyuminstallepel-releaseyuminstallpure-ftpd配置备份原配置...
你 发表评论:
欢迎- 一周热门
-
-
如何在安装前及安装后修改黑群晖的Mac地址和Sn系列号
-
爱折腾的特斯拉车主必看!手把手教你TESLAMATE的备份和恢复
-
[常用工具] OpenCV_contrib库在windows下编译使用指南
-
Ubuntu系统Daphne + Nginx + supervisor部署Django项目
-
WindowsServer2022|配置NTP服务器的命令
-
WIN11 安装配置 linux 子系统 Ubuntu 图形界面 桌面系统
-
解决Linux终端中“-bash: nano: command not found”问题
-
NBA 2K25虚拟内存不足/爆内存/内存占用100% 一文速解
-
Linux 中的文件描述符是什么?(linux 打开文件表 文件描述符)
-
K3s禁用Service Load Balancer,解决获取浏览器IP不正确问题
-
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)