dockerd、contaierd、containerd-shim、runC通信机制分析

本文深入分析了Docker组件之间的通信机制,包括dockerd如何通过gRPC与containerd交互,containerd启动及与containerd-shim、runC的通信流程。详细探讨了dockerd启动容器的过程,以及containerd如何监控容器状态,如进程退出和OOM事件。此外,还介绍了containerd-shim在容器生命周期中的角色,以及runC作为符合OCI标准的容器引擎如何实现资源隔离和限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整体框架分析

dockerd 底层运行容器需要依赖多个二级制组件:docker daemon, containerd, container-shim, runC,
代码实现上,containerd包含了container-shim代码。同一份代码,通过Makefile编译控制,编译成两个二级制文件。

组件间通信

概括图
"底层通信概括图"

通信流程:
1. docker daemon 模块通过 grpc 和 containerd模块通信:dockerd 由libcontainerd负责和containerd模块进行交换, dockerd 和 containerd 通信socket文件:docker-containerd.sock
2. containerd 在dockerd 启动时被启动,启动时,启动grpc请求监听。containerd处理grpc请求,根据请求做相应动作;
3. 若是start或是exec 容器,containerd 拉起一个container-shim , 并通过exit 、control 文件(每个容器独有)通信;
4. container-shim别拉起后,start/exec/create拉起runC进程,通过exit、control文件和containerd通信,通过父子进程关系和SIGCHLD监控容器中进程状态;
5. 若是top等命令,containerd通过runC二级制组件直接和容器交换;
6. 在整个容器生命周期中,containerd通过 epoll 监控容器文件,监控容器的OOM等事件

NOTE:
containerd,container-shim 组件本质上runC 和dockerd 间的adapter中间件,容器本身有runC单独完成 — 使用runC可以单独完成一个容器部署。

组件通信详细分析

DOCKER DEAMON —> LIBCONTAINERD 组件分析

LIBCONTAINERD 部分主要作用:1,赋值和CONTAINERD进程通信 2,监控CONTAINERD进程状态

LIBCONTAINERD 随DOCKERD启动,启动过程中启动协程监控:1. 和CONTAINERD间的grpc链接情况 2. 监听由CONTAINERD发送过来的消息
启动监控消息协程

//libcontainerd/remote_linux.go
//starEventMonitor() ---> handleEventStream()

func (r *remote) handleEventStream(events containerd.API_EventsClient) {
    for {
        e, err := events.Recv()   // ---> 此为阻塞方法:等待CONTAINERD发送 gRPC消息
...
        if err := container.handleEvent(e); err != nil {
            logrus.Errorf("libcontainerd: error processing state change for %s: %v", e.Id, err)
        }
        ...
}

上面主要代码主要功能就是接收gRPC返回的事件,并调用各自容器来的handleEvent对事件进行处理

//libcontainerd/container_linux.go
func (ctr *container) handleEvent(e *containerd.Event) error {
    ctr.client.lock(ctr.containerID)
    defer ctr.client.unlock(ctr.containerID)
    switch e.Type {
    case StateExit, StatePause, StateResume, StateOOM:
        st := StateInfo{
            CommonStateInfo: CommonStateInfo{
                State:    e.Type,
                ExitCode: e.Status,
            },
            OOMKilled: e.Type == StateExit && ctr.oom,
        }
        if e.Type == StateOOM {
            ctr.oom = true
        }
        if e.Type == StateExit && e.Pid != InitFriendlyName {
            st.ProcessID = e.Pid
            st.State = StateExitProcess
        }

        // Remove process from list if we have exited
        switch st.State {
        case StateExit:
            ctr.clean()
            ctr.client.deleteContainer(e.Id)
        case StateExitProcess:
            ctr.cleanProcess(st.ProcessID)
        }
        ctr.client.q.append(e.Id, func() {
            if err := ctr.client.backend
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值