不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • Docker

  • K8S

  • 容器原理

    • 01.docker原理
      • 01.namespace
        • 1、namespace介绍
        • 2、namespace实现原理
        • 1)struct nsproxy结构体
        • 2) struct pid_namespace 结构
        • 3、namespace结构拆解
      • 02.CGroup
        • 1、CGroup 概述
        • 2、CGroup 提供的功能
        • 3、CGroup 相关核心概念
      • 03.Docker实现本质
        • 1、命名空间应用
        • 1)PID(进程隔离)
        • 2)Network(网络隔离)
        • 3)Mount(文件系统隔离)
        • 4)User(用户隔离)
        • 5)IPC(进程间通信隔离)
        • 6)UTS(域名隔离)
        • 2、CGroup 应用
        • 1)CPU 资源控制
        • 2)内存 资源控制
        • 3)I/O 资源控制
        • 4)网络带宽 控制
    • 02.k8s网络原理
  • Istio

  • 容器
  • 容器原理
xiaonaiqiang
2022-02-06
目录

01.docker原理

# 01.namespace

# 1、namespace介绍

  • Namespace 是 Linux 提供的一种内核级别的资源隔离机制
  • 它允许不同进程在同一主机中互相隔离并使用相同的资源名称
  • 命名空间通过创建独立的资源视图,使每个进程只感知它所属命名空间内的资源
  • Linux 内核支持六种命名空间,分别是网络、进程、挂载、UTS、IPC、用户
    • Network Namespace:将网络设备、路由表等隔离
    • PID Namespace:使进程ID(PID)在不同的命名空间里相互独立
    • Mount Namespace:为文件系统挂载点提供隔离
    • UTS Namespace:允许隔离主机名和域名
    • IPC Namespace:隔离进程间通信资源
    • User Namespace:隔离用户和组ID
  • Docker 借助这些命名空间来实现容器的资源隔离
  • 使得每个容器都有自己独立的进程、网络栈等,从而实现轻量级虚拟化

# 2、namespace实现原理

# 1)struct nsproxy结构体

  • 每个进程都与特定的命名空间相关联
  • Linux 内核通过在进程描述符中添加 nsproxy 结构体来管理命名空间
  • nsproxy 负责管理进程所属的多个命名空间
  • 使得一个进程可以同时隶属于不同类型的命名空间,如 PID、网络、挂载等
  • 每种命名空间类型对应一个结构体
    • 如 pid_namespace 用于管理进程ID隔离,mnt_namespace 用于管理挂载点隔离等
struct task_struct {
    ...
    /* namespaces */
    struct nsproxy *nsproxy;
    ...
}
 
struct nsproxy {
    atomic_t count;
  
    struct pid_namespace  *pid_ns;  
  
    struct uts_namespace  *uts_ns;
    struct ipc_namespace  *ipc_ns;
    struct mnt_namespace  *mnt_ns;
    struct user_namespace *user_ns;
    struct net            *net_ns;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2) struct pid_namespace 结构

  • pid_namespace 是 PID 命名空间的核心结构,用于管理进程 ID
  • 其设计支持多级嵌套命名空间,并确保每个命名空间中的 PID 相互独立
  • 关键字段(树中每个节点包含这些信息):
    • kref: 引用计数,表示有多少进程正在使用该命名空间
    • pidmap: 位图,用于快速查找空闲的 PID
    • last_pid: 记录最后分配的 PID
    • level: 命名空间的层级,用于标识嵌套关系
    • parent: 父级命名空间,支持多级嵌套
struct pid_namespace {
    struct kref kref;
    struct pidmap pidmap[PIDMAP_ENTRIES];
    int last_pid;
    struct task_struct *child_reaper;
    struct kmem_cache *pid_cachep;
    unsigned int level;
    struct pid_namespace *parent;
    #ifdef CONFIG_PROC_FS
    struct vfsmount *proc_mnt;
    #endif
};
1
2
3
4
5
6
7
8
9
10
11
12
  • 由于 pid命名空间 是分层的,也就是说新创建一个 pid命名空间 时会记录父级 pid命名空间 到 parent 字段中
  • 所以随着 pid命名空间 的创建,在内核中会形成一颗 pid命名空间 的树
    • 第0层的 pid命名空间 是 init 进程所在的命名空间
    • 如果一个进程所在的 pid命名空间 为 N,那么其在 0 ~ N 层pid命名空间 都有一个唯一的pid号
    • 也就是说 高层pid命名空间 的进程对 低层pid命名空间 的进程是可见的
    • 但是 低层pid命名空间 的进程对 高层pid命名空间 的进程是不可见的

# 3、namespace结构拆解

  • 这里以 pid_namespace (进程ID)的树形结构推演namespace

  • 每个容器中的进程在容器内部拥有自己的 PID 空间,与宿主机中的 PID 独立

  • 然而,宿主机可以查看容器内部的所有进程,因为宿主机的 PID 命名空间是容器的父级命名空间

  • 举例说明

    • 宿主机上有一个进程 docker daemon,PID 为 1001,它启动了两个容器 container1 和 container2

    • container1 内的第一个进程是容器内部的 init 进程,PID 为 1该进程在宿主机上的 PID 是 2001

    • container2 内的第一个进程也是 init 进程,PID 为 1,宿主机上对应的 PID 为 3001

  • 那么对应的 pid namespance结构如下

宿主机 pid_namespace (level 0, last_pid = 3001)  # 宿主机命名空间(level 0)
  │
  ├── docker daemon (PID 1001, 宿主机内)
  ├── container1 pid_namespace (level 1, parent = 宿主机, last_pid = 1)  # container1 的命名空间(level 1)
  │     └── init (PID 1 in container1, 宿主机 PID = 2001)
  │  
  └── container2 pid_namespace (level 1, parent = 宿主机, last_pid = 1) # container2 的命名空间(level 1)
        └── init (PID 1 in container2, 宿主机 PID = 3001)
1
2
3
4
5
6
7
8
  • 宿主机的命名空间(level 0)中包含了 docker daemon 进程以及容器中的所有进程在宿主机的 PID 映射
  • 每个容器都有自己的 pid_namespace,在这个命名空间中,init 进程的 PID 是 1,并且这个 PID 与宿主机中的进程无关
  • 宿主机能够看到容器内部的所有进程,但容器无法看到宿主机或其他容器的进程
  • 通过这种结构,docker daemon 的作用变得清晰
    • 它位于宿主机的命名空间中,负责管理容器,并与容器的 pid_namespace 进行关联

# 02.CGroup

# 1、CGroup 概述

  • CGroup(Control Group)是 Linux 内核用于对进程进行资源限制和管理的功能
  • 它允许将进程分组,并对每个组的 CPU、内存、网络等资源进行限制、监控和隔离
  • Docker 使用 CGroup 实现容器的资源限制
  • 主要功能:
    • 资源限制:控制进程组能够使用的 CPU、内存、磁盘等资源的上限
    • 优先级控制:为不同的进程组设置优先级,如为某组分配更多 CPU 份额
    • 资源使用统计:记录进程组使用的 CPU、内存等资源情况
    • 资源隔离:将不同进程组在资源上相互隔离,避免干扰
    • 进程组管理:支持冻结和恢复某个进程组的执行状态

# 2、CGroup 提供的功能

  • 资源限制(Resource Limiting):

    • 比如,memory 子系统可以为某个进程组设定内存使用上限,一旦超出就会触发 OOM(内存不足)
  • 优先级控制(Prioritization):

    • cpu 子系统可以为不同进程组分配不同的 CPU 份额
  • 资源计量(Accounting):

    • cpuacct 子系统记录进程组使用的 CPU 时间,便于统计和监控
  • 进程隔离(Isolation):

    • ns 子系统可以让不同进程组使用独立的命名空间,达到资源隔离的目的
  • 控制功能(Control):

    • freezer 子系统允许将某个进程组挂起或恢复

# 3、CGroup 相关核心概念

  • 任务(Task):

    • 在 CGroup 中,任务就是系统中的一个进程
  • 控制组(Control Group):

    • 是按照某种标准划分的一组进程,CGroup 通过控制组来管理资源,限制或监控某个控制组的资源使用
  • 层级(Hierarchy):

    • 控制组可以形成树状层级结构,子控制组继承父控制组的属性,子控制组可以有独立的资源限制
  • 子系统(Subsystem):

    • 每个子系统对应一个资源控制器,如 cpu 子系统用于控制 CPU 时间,memory 子系统用于控制内存使用

    • 子系统附加到层级树上时,会对树中的所有控制组生效

# 03.Docker实现本质

  • Docker 利用 命名空间(Namespace) 和 控制组(CGroup) 实现了容器的隔离与资源管理

# 1、命名空间应用

  • 命名空间(Namespace)在 Docker 中的应用
  • Docker 使用命名空间为每个容器提供了一个隔离的资源视图
  • 使得容器看起来像是一个独立的操作系统环境

# 1)PID(进程隔离)

  • 作用:

    • 隔离进程 ID,使得容器内的进程与其他容器或宿主机的进程分开
    • 每个容器都有自己的进程编号空间,容器中的进程从 PID 1 开始(通常是容器内的 init 进程)
  • 例子:

    • 宿主机上可能有多个容器,每个容器中的 PID 1 都是独立的

      • 容器 A 中有一个进程,它的 PID 是 1
      • 容器 B 中也有一个进程,它的 PID 也是 1
      • 宿主机上可能还有其他进程,它们有不同的 PID
    • 由于使用了 PID 命名空间,容器 A 和容器 B 都认为它们的 PID 1 是系统的第一个进程

    • 而看不到宿主机或其他容器中的进程

# 2)Network(网络隔离)

  • 作用:
    • 隔离网络资源,每个容器都有自己的网络设备(如虚拟网卡)、IP 地址、路由表等
    • 这使得容器之间的网络环境相互独立,除非显式连接
  • 例子:
    • 每个容器都有自己的虚拟网卡和独立的 IP 地址
      • 容器 A 的 IP 地址可能是 172.17.0.2
      • 容器 B 的 IP 地址可能是 172.17.0.3
    • 宿主机上的网络和容器 A、容器 B 之间是隔离的
    • 除非通过 Docker 提供的网络接口或桥接网络显式地连接

# 3)Mount(文件系统隔离)

  • 作用:
    • 每个容器有自己独立的文件系统视图,可以挂载独立的文件系统或只访问特定的目录
    • 宿主机和其他容器的文件系统是相互隔离的,除非使用卷(volumes)进行数据共享
  • 例子:
    • 容器 A 中看到的文件系统是特定镜像中的内容,而不会看到宿主机或其他容器的文件
    • 比如,宿主机的 /var/www/html 目录不会自动出现在容器中
    • 除非通过 Docker 的 -v 参数将该目录挂载到容器的某个路径

# 4)User(用户隔离)

  • 作用:
    • 实现用户和组的隔离,容器可以有独立的用户 ID 和组 ID
    • 宿主机上的 root 用户和容器中的 root 用户不等同
  • 例子:
    • 容器中的 root 用户拥有对容器内部所有文件的权限
    • 但在宿主机上,该用户并不拥有实际的 root 权限,增强了安全性

# 5)IPC(进程间通信隔离)

  • 作用:隔离容器间的进程间通信资源(如信号量、消息队列、共享内存等)
  • 例子:
    • 容器 A 和容器 B 都有各自的 IPC 资源
    • 容器 A 的进程无法访问容器 B 的共享内存或消息队列,除非明确设置共享通信

# 6)UTS(域名隔离)

  • 作用:
    • 为每个容器隔离主机名和域名
    • 容器可以有自己独立的主机名,而不会影响其他容器或宿主机
  • 例子:
    • 容器 A 的主机名可以是 containerA,容器 B 的主机名可以是 containerB
    • 而宿主机的主机名可能是 host123,三者互不影响

# 2、CGroup 应用

  • Docker 通过 CGroup 控制容器的资源使用情况
  • 确保每个容器只消耗指定的 CPU、内存等资源
  • 避免单个容器过度占用系统资源,影响其他容器或宿主机

# 1)CPU 资源控制

  • 作用:Docker 可以使用 CGroup 的 cpu 子系统来限制容器使用的 CPU 时间,防止某个容器占用过多的 CPU 资源

  • 例子:

    • 当创建容器时,可以指定容器使用的 CPU 份额:

      docker run --cpu-shares=512 ubuntu
      
      1
    • 上述命令启动了一个 Ubuntu 容器,并限制其 CPU 使用份额为 512

    • 默认值为 1024,因此该容器的 CPU 份额为默认容器的 50%

# 2)内存 资源控制

  • 作用:

    • 通过 CGroup 的 memory 子系统,Docker 可以限制容器使用的内存
    • 如果容器的内存使用超过设定的限制,CGroup 会触发 OOM(Out of Memory)错误并终止容器
  • 例子:

    • 限制容器的内存使用为 256MB

      docker run -m 256m ubuntu
      
      1
    • 这意味着容器内的所有进程共享 256MB 的内存,如果超过这个限制,容器将会被停止

# 3)I/O 资源控制

  • 作用:

    • CGroup 还可以控制容器的块设备 I/O 使用
    • 防止某些容器对磁盘或存储设备的过度使用,从而影响其他容器的性能
  • 例子:

    • 限制容器的 I/O 带宽:

      docker run --device-write-bps /dev/sda:1mb ubuntu
      
      1
    • 该命令限制了容器对 /dev/sda 设备的写入速度为 1MB/秒

# 4)网络带宽 控制

  • 作用:Docker 也可以通过 CGroup 的 net_cls 和 net_prio 子系统来限制和优先化容器使用的网络带宽

  • 例子:

    • 限制容器的网络上传速率:

      docker run --netem rate 1mbit ubuntu
      
      1
    • 这个命令限制容器的网络上传速率为 1 Mbit/s,防止某个容器占用太多网络带宽

上次更新: 2024/9/27 11:33:57
01.Java项目部署
02.k8s网络原理

← 01.Java项目部署 02.k8s网络原理→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式