1.Docker底层实现讲解
2.深入学习docker -- 资源限制Cgroups
3.用docker部署x-ui面板
4.容器原理之cgroup
5.(6)笔记:Docker容器的源码资源控制之CPU(上)
6.Dockerçcgroup讲解
Docker底层实现讲解
Docker底层实现的关键技术主要体现在Linux的命名空间(namespace)、控制组(cgroup)和联合文件系统(union FS)上。源码这些技术解决了程序运行环境的源码隔离和资源管理问题,使得Docker能够提供高效、源码安全的源码容器化环境。
命名空间在内核级别实现了进程、源码ai源码搜集网络和资源的源码独立,每个容器都有自己的源码隔离空间,避免了服务之间的源码相互干扰。例如,源码通过namespace,源码可以为每个容器分配独立的源码网络接口和IP地址,同时确保宿主机的源码安全性。
控制组则用于管理容器的源码物理资源,如CPU、源码内存和磁盘I/O,防止一个容器的资源过度占用影响其他容器的性能。通过cgroupfs文件系统,可以创建和监控多个由相同标准和参数限制的进程组。
联合文件系统(UFS)解决了镜像的只读问题,镜像被设计为多个可读层叠,每个命令执行都会创建新的层,容器在运行时添加可写层。这使得镜像和容器之间具有明确的区别,镜像为只读,容器为镜像加上可写层。
Docker的架构包括客户端、服务器和仓库,客户端执行常用命令如docker run来创建和管理容器,服务器负责容器的运行和管理,仓库则存储镜像。Docker通过这些底层技术,实现了快速部署、隔离和资源管理,从而解决了传统开发和运维中的挑战,如版本不一致和环境配置问题。
要了解更多资源,可以访问整理的Linux学习资料,包括视频、电子书和PPT,演示站推广源码无需套路,直接领取。通过Docker,我们能够更好地控制程序运行环境,提升开发和运维效率。
深入学习docker -- 资源限制Cgroups
在深入学习 Docker 的过程中,我们探索了如何用 Namespace 实现“伪容器”,但遗憾的是,Namespace 仅能提供一个虚拟环境,无法控制资源使用,甚至可能影响宿主机上的其他进程。为解决这一问题,我们引入了 Cgroups(Linux 控制组)的概念。
Cgroups 允许限制一个进程组能使用的资源上限,包括 CPU、内存、磁盘、网络等。通过 Cgroups,我们可以更精确地控制进程的资源使用,实现资源隔离和限制。下面,我们将详细探讨如何利用 Cgroups 限制 CPU 使用。
限制 CPU 使用时,关键参数包括 CPU 配额(cfs_quotaus)和 CPU 股权(cpu.shares)。下面我们将通过实例演示如何实现单个进程 CPU 使用率的限制,并探讨控制组内部资源的分配。
首先,创建一个 CPU 控制组,然后启动消耗 CPU 的程序。程序运行后,我们观察到 CPU 使用率接近 2 个核心,即大约 %。接着,我们将 CPU 使用率设置为 %,并检查新进程的 CPU 使用率。可见,通过设置 cfs_quotaus 参数,我们成功实现了单个进程 CPU 使用率的广东麻将源码免费限制。
然而,限制并非仅适用于单个进程。控制组内的子组也影响资源分配。我们通过改变子组的 cpu.shares 参数,调整了资源的分配比例,使进程 CPU 使用率更加均衡或集中。
在实际应用中,Cgroups 的 v1 和 v2 版本在控制组与资源的关系上有所差异。v1 版本更为传统,v2 版本则试图解决资源分配的局限性。在 Kubernetes 环境中,每个容器都会在 CPUCgroup 子系统中创建一个控制组,并将容器进程写入其中。资源限制如 CPU 和内存,则通过 cfs_quotaus 和 memory.limit_in_bytes 等参数来实现。
总结而言,Cgroups 为 Docker 中资源管理提供了强大的工具,通过设置合理的参数,我们可以实现进程间资源的隔离和限制,为容器化应用提供更灵活、安全的运行环境。未来我们将继续探索 Docker 中的其他关键技术,如 OverlayFS,以更全面地理解容器化生态。
用docker部署x-ui面板
使用Docker部署x-ui面板的详细步骤
首先,你需要基于enwaiax/x-ui的docker镜像来构建你的环境。镜像中的面板默认端口为,但你可以根据需求自由设置服务端口,例如,使用以下命令将容器端口映射到宿主机的-范围:-p -:-/tcp -p -:-/udp 对于一些固定配置,如临时文件系统的挂载,可以使用`--tmpfs`选项,如`--tmpfs /tmp --tmpfs /run --tmpfs /run/lock`。同时,为了数据持久化,可以挂载目录,例如`-v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /home/x-ui:/etc/x-ui`。 在容器启动时,面板的vue生成的源码默认账号和密码均为"admin"。如果你遇到vless连接问题,可能需要检查7.5版本是否适用,或尝试其他方法直接在面板中进行切换。 接下来,对于nginx面板的访问,你需要在nginx配置中实现WebSocket的反向代理。具体的配置步骤根据你的nginx版本和需求来调整,确保设置正确后,即可完成面板的访问配置。 最终,按照以上步骤进行设置,你的x-ui面板部署就会顺利进行,完成全部配置后,你便可以成功访问并管理你的系统了。容器原理之cgroup
轻量便携的container,如docker,使得应用打包和发布变得非常简便。本系列文章将分析container所使用的核心技术,包括Linux namespace,cgroups,overlayfs等,帮助读者手动创建类似container的环境。
cgroup(control group)是Linux内核的一个特性,用于限制、统计、隔离一组进程的资源,如CPU、内存、磁盘、网络等。需要注意的是,“cgroup”一词的首字母不应当大写。
Google工程师于年首次提出这一特性,最初名为“process containers”,为避免歧义,在年更名为“control group”,并于年1月发布的Linux Kernel 2.6.版本中合并到主线分支。随后,在此特性基础上,源码投资投资了又增加了一系列特性,如kernfs(伪文件系统,用于向用户导出内核的设备模型)、firewalling(基于预定义的安全规则管理网络流量)和unified hierarchy。在Linux Kernel 4.5版本中,cgroup v2的实现代码被合并。
在云原生场景下,cgroups可以用于限制每个容器可以使用的资源,例如,在kubernetes中,它可以用来决定是否将pod调度到某个节点,以确保每个容器中的应用都有足够的可用资源。
cgroup的主要功能包括:
目前,cgroups有两个版本:cgroup V1和cgroup V2。V1功能相对零散,不便维护,V2是未来的演进方向。在这种情况下,节点存在以下三种cgroups模式:
在containerd中,可以通过以下方式判断当前处于哪种模式:
也可以通过以下命令判断:
可以通过修改Linux启动参数来更改cgroups模式。例如,使用unified模式(注意cgroup_no_v1=all):
使用legacy模式:
使用hybrid模式:
cgroup v1主要包括以下几个概念:
cgroup v1支持以下资源类型:
Cgroup子系统运行在内核态,不能直接与用户交互,因此需要通过文件系统提供与终端用户的接口。在Linux中,表现为Cgroup子系统挂载的文件系统目录,用户操作这些目录就可以直接与内核中的Cgroup对象交互。
不同的子系统对应的文件系统目录包含不同的文件,但以下文件是所有子系统都有的:
控制子cgroup是否继承父cgroup的配置,仅对cpuset子系统有效,并在cgroup v2中已移除。
位于当前cgroup的TGID(线程组ID),TGID是进程组中第一个进程的PID。该文件是可写的,向该文件写入TGID即表示将对应线程组加入cgroup,但不保证文件中的TGID有序和不重复。
位于当前cgroup中task的TID(线程ID),即进程组中的所有线程的ID。该文件是可写的,将任务的TID写入该文件表示将其加入对应cgroup,如果该任务的TGID在另一个cgroup,会在cgroup.procs记录该任务的TGID,进程组中的其他task不受影响。不保证文件中的TID有序和不重复。
⚠️注意:如果向cgroup.procs写入TGID,系统会自动更新tasks文件中的内容为该线程组中所有任务的TID。
向tasks文件中写入TID,cgroup.procs中的值也会更新为对应TGID,但这并不影响该线程组中的其他任务。
是否开启release agent,如果该文件中的值为1,当cgroup中不包含任何task时(tasks中的TID被全部移除),kernel会执行release_agent文件(位于root cgroup的release_agent文件,例如/sys/fs/cgroup/memory/release_agent)的内容。所有非root cgroup从父cgroup继承该值。
在cgroup v2中,去掉了层级(hierarchy)的概念,只有一个层级,所有cgroup在该层级中以树形方式组织,每个cgroup可以管理多种资源。
cgroup v2不需要单独挂载每个子系统。
在cgroup v2中,每个cgroup目录下都有一个名为cgroup.controllers的可读文件,记录了当前cgroup启用的controller。根目录下的cgroup.controllers文件内容记录了当前系统支持的所有controller。
新建子cgroup时,cgroup.controllers继承父cgroup的cgroup.subtree_control值,子cgroup的cgroup.subtree_control为空,表示在该子cgroup下再次创建子cgroup时,默认不会启用controller。
创建一个testcgroup,此时,cgroup.subtree_control的值为空:
cgroup.controllers的值与父cgroup的cgroup.subtree_control值相同:
在test下再创建一个子cgroup child,此时,child的cgroup.controllers的内容为空:
子cgroupchild中的文件:
修改父cgroup的cgroup.subtree_control,增加cgroup controller:
删除子cgroup中的controller,也通过修改父cgroup的cgroup.subtree_control实现:
对一个cgroup,如果cgroup.procs的值不为空,不能设置cgroup.subtree_control的值。
此时,需要将cgroup中的进程移动到其他子cgroup,确保当前cgroup中cgroup.procs的值为空:
未开启任何controller时,cgroup中包含以下文件:
populated:如果当前cgroup和子层级中没有存活的进程,populated值为0,否则为1。值改变时会触发poll和notify事件。考虑以下cgroup层级(括号中的数字代表cgroup中的进程数量):
A,B和C的populated值为1,D的populated值为0,如果C中对进程退出,则B和C中的populated值将变为0,并且会生成cgroup.events文件被修改的事件。
frozen:如果当前cgroup处于frozen状态,值为1,否则为0。
cgroup.max.depth和cgroup.max.descendants的区别:
cgroup.max.descendants限制当前cgroup下所有子cgroup的总和(包括所有子cgroup)。
cgroup.max.depth限制cgroup树的深度。
向cgroup.procs中写入PID后,cgroup会向cgroup.threads文件中追加进程中所有线程的TID。
nr_descendants:当前cgroup下子cgroup的总数。
nr_dying_descendants:当前cgroup下正在被删除的子cgroup数量。
当前cgroup中存在进程时,写入不会成功:
写入当前cgroup没有启用的controller时,不会成功:
当同时写入多个controller时,要么全成功,要么全失败,不存在部分成功的情况:
虽然启用memory controller可以成功,但是启用cpu controller的时候失败了,所以memory controller也没有启用。
“domain”:正常的有效domain cgroup,默认类型。
“domain threaded”:threaded类型domain cgroup,作为threaded子树的根结点。
“domain invalid”:无效的cgroup,不能启用controller,不能加入进程。可以转换为threaded类型的cgroup。
“threaded”:threaded类型cgroup,位于threaded子树中。
当前cgroup的CPU压力情况,基于PSI(Pressure Stall Information)实现,这是kernel引入的一种评估系统压力的机制。内容如下:
pressure值分为两行,avg、avg、avg分别表示s、s、s时间周期内阻塞(stall)时间的百分比。total是累计时间,单位ms。
some行表示只有一个任务在cpu资源上阻塞。full行表示所有非idle状态任务同时在cpu资源上阻塞,此时,cpu资源完全浪费,严重影响性能。
在以下示例中,每个格子代表s,有颜色的格子代表在这段时间(为了方便,以s为单位)内cpu处于阻塞状态。
some阻塞时间的百分比为s/s=%,full阻塞时间的百分比为/=%。
和cpu.pressure类似,表示当前cgroup内io资源阻塞时间的占比。
和cpu.pressure类似,表示当前cgroup内memory资源阻塞时间的占比。
usage_usec:总的cpu时间。
user_usec:用户态进程占用cpu的时间。
system_usec:内核态进程占用cpu的时间。
(6)笔记:Docker容器的资源控制之CPU(上)
Docker通过cgroup实现容器的资源配额控制,包括CPU、内存和磁盘IO。cgroup是Linux内核中的一种机制,用于限制、监控和隔离进程组的资源使用。LXC(Linux Container)则在此基础上提供更轻量级的虚拟化,以隔离进程和资源。
资源限制很重要,可以避免单个容器过度占用硬件资源,影响其他容器的正常运行。例如,通过设置`cpu-shares`,可以为容器分配CPU份额,如给一个容器分配的权重。然而,这并不是绝对的CPU数量,而是一个权重值,实际分配取决于所有容器的份额总和和容器内部进程的运行状况。
实验开始时,单独运行容器难以观察到资源使用情况,但当多个容器同时运行,资源配额的生效才能显现。`cpu-affinity`技术允许更精确地控制进程在特定CPU核心上的运行,可以提高运行效率并减少上下文切换。
总结来说,Docker容器的CPU资源控制是通过权重分配实现的,不是硬性分配,而是根据容器间的竞争和进程需求动态调整。对于有疑问的读者,文中也提供了关于进程绑定、上下文切换等问题的解答。
最后,如果你喜欢本文内容,记得关注和分享哦!
Dockerçcgroup讲解
æè¿å¨çä¸ä¸ªå¾®æå¡æ¡æ¶ github.com/tal-tech/go-zero ï¼å¨ core/stat/internal ç®å½ä¸å¦ä¹ å°cgroupç¥è¯ï¼æ¬æåªæ¶åå°äºææå¦ä¹ å°çï¼æ£æå¼å§ãcgroup ï¼æ§å¶ç»ï¼å®æä¾äºä¸å¥æºå¶ç¨äºæ§å¶ä¸ç»ç¹å®è¿ç¨å¯¹èµæºç使ç¨ãcgroupç»å®ä¸ä¸ªè¿ç¨éåå°ä¸ä¸ªæå¤ä¸ªåç³»ç»ä¸ã å®æ¹è§£é
对äºcgroupï¼å ¶æ¬èº«çä½ç¨åªæ¯ä»»å¡è·è¸ªãä½å ¶å®ç³»ç»ï¼æ¯å¦cpusetsï¼cpuacctï¼ï¼å¯ä»¥å©ç¨cgroupçè¿ä¸ªåè½å®ç°ä¸äºæ°çå±æ§ï¼æ¯å¦ç»è®¡æè æ§å¶ä¸ä¸ªcgroupä¸è¿ç¨å¯ä»¥è®¿é®çèµæºã举个ä¾åï¼cpusetsåç³»ç»å¯ä»¥å°è¿ç¨ç»å®å°ç¹å®çcpuåå åèç¹ä¸ã
å¦ææªç解跳è¿å¾ä¸çï¼å头åç
第ä¸è¡ä»£è¡¨æ»çcpuæ¶é´ï¼åä½æ¯jiffiesï¼jiffiesæ¯å æ ¸ä¸çä¸ä¸ªå ¨å±åéï¼ç¨æ¥è®°å½èªç³»ç»å¯å¨ä¸æ¥äº§ççèææ°ï¼å¨linuxä¸ï¼ä¸ä¸ªèæ大è´å¯ç解为æä½ç³»ç»è¿ç¨è°åº¦çæå°æ¶é´çï¼ä¸ålinuxå æ ¸å¯è½å¼æä¸åï¼é常å¨1mså°msä¹é´ã
理解docker [一] - control group
Docker作为一种容器技术,其核心理念是通过类似货轮运输的集装箱方式,将应用及其依赖打包,便于在不同环境中部署。相较于传统的基于hypervisor的虚拟机,Docker的容器在隔离性和资源消耗上有所不同,它更轻量级,能更高效地在同一个物理主机上运行多个容器。
Docker的实现离不开Linux的三大关键技术:cgroup、Namespace以及Union FS。cgroup,即控制组,是进程的集合,它改变了之前只能单进程资源控制的局面,支持对一组进程进行资源配额和限制,例如CPU使用时间、内存等,每个容器对应一个自定义的cgroup。
Linux的/sys/fs/cgroup目录结构清晰展示了cgroup的资源类型,如cpu、cpuacct和cpuset。其中,cpu限制的是CPU使用时间,cpuacct则用于记录和统计使用时间;cpuset则用于在SMP系统中控制进程可以使用的CPU组,以适应NUMA架构下的资源调度。
创建cgroup的过程相对简单,只需在对应subsystem目录下创建文件夹,然后将进程的PID添加到相应的组。cgroup支持层级结构,允许资源限制的灵活配置,但也可能带来复杂性。cgroup v2的发布是对v1的优化,以group为主导,统一了资源限制的层级,简化了实现,并在某些特性上做出调整,以平衡灵活性和复杂度。
尽管cgroup v2的引入带来了一些改变和兼容性问题,但随着Docker .的发布,v2模式在Linux发行版中的支持逐渐增强,预示着更高效和灵活的容器化未来。在软件开发中,类似Docker的重构过程,尽管短期内可能带来挑战,但长期来看有助于提升代码质量和系统的稳定性。