containerd 源码分析:创建 container(三)
文接 containerd 源码分析:创建 container(二)
1.2.2.2 启动 task
上节介绍了创建 task,task 创建之后将返回 response 给 ctr。接着,ctr 调用 task.Start 启动容器。
// containerd/client/task.go
func (t *task) Start(ctx context.Context) error {
r, err := t.client.TaskService().Start(ctx, &tasks.StartRequest{
ContainerID: t.id,
})
if err != nil {
...
}
t.pid = r.Pid
return nil
}
// containerd/api/services/tasks/v1/tasks_grpc.pb.go
func (c *tasksClient) Start(ctx context.Context, in *StartRequest, opts ...grpc.CallOption) (*StartResponse, error) {
out := new(StartResponse)
err := c.cc.Invoke(ctx, "/containerd.services.tasks.v1.Tasks/Start", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
ctr 调用 contaienrd 的 /containerd.services.tasks.v1.Tasks/Start 接口创建 task。进入 containerd 查看提供该服务的插件:
// containerd/plugins/services/tasks/service.go
func (s *service) Start(ctx context.Context, r *api.StartRequest) (*api.StartResponse, error) {
return s.local.Start(ctx, r)
}
// containerd/plugins/services/tasks/local.go
func (l *local) Start(ctx context.Context, r *api.StartRequest, _ ...grpc.CallOption) (*api.StartResponse, error) {
t, err := l.getTask(ctx, r.ContainerID)
if err != nil {
return nil, err
}
p := runtime.Process(t)
if r.ExecID != "" {
if p, err = t.Process(ctx, r.ExecID); err != nil {
return nil, errdefs.ToGRPC(err)
}
}
// 启动 task: shimTask.Start
if err := p.Start(ctx); err != nil {
return nil, errdefs.ToGRPC(err)
}
state, err := p.State(ctx)
if err != nil {
return nil, errdefs.ToGRPC(err)
}
return &api.StartResponse{
Pid: state.Pid,
}, nil
}
// containerd/core/runtime/v2/shim.go
func (s *shimTask) Start(ctx context.Context) error {
_, err := s.task.Start(ctx, &task.StartRequest{
ID: s.ID(),
})
if err != nil {
return errdefs.FromGRPC(err)
}
return nil
}
// containerd/api/runtime/task/v2/shim_ttrpc.pb.go
func (c *taskClient) Start(ctx context.Context, req *StartRequest) (*StartResponse, error) {
var resp StartResponse
if err := c.client.Call(ctx, "containerd.task.v2.Task", "Start", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
经过 containerd 各个插件的层层调用,最终走到 containerd.task.v2.Task.Start ttrpc 服务。提供 containerd.task.v2.Task.Start 服务的是 containerd-shim-runc-v2:
// containerd/cmd/containerd-shim-runc-v2/task/service.go
// Start a process
func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.StartResponse, error) {
// 根据 task 的 StartRequest 获得 container 的 metadata
container, err := s.getContainer(r.ID)
if err != nil {
return nil, err
}
...
p, err := container.Start(ctx, r)
if err != nil {
handleStarted(container, p)
return nil, errdefs.ToGRPC(err)
}
...
}
调用 Container.Start 启动容器进程:
// containerd/cmd/containerd-shim-runc-v2/runc/container.go
// Start a container process
func (c *Container) Start(ctx context.Context, r *task.StartRequest) (process.Process, error) {
p, err := c.Process(r.ExecID)
if err != nil {
return nil, err
}
if err := p.Start(ctx); err != nil {
return p, err
}
...
}
Container.Start 调用 Process.Start 启动容器进程。启动容器后 runc init 将退出,将容器的主进程交由 runc init 的父进程 shim:
# ps -ef | grep 138915
root 138915 1 0 15:52 ? 00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace default -id nginx1 -address /run/containerd/containerd.sock
root 138934 138915 0 15:52 ? 00:00:00 nginx: master process nginx -g daemon off;
通过这样的处理,容器进程就和 containerd 没关系了,容器不再受 containerd 的影响,仅和它的 shim 有关系,被 shim 管理,这也是为什么要引入 shim 的原因。
1.3 containerd
从上述 containerd 创建 container 的分析可以看出,containerd 中插件之间的调用是分层的。contianerd 架构如下:

containerd 创建 container 的示意图如下:

ctr 创建的 container 的交互流程图如下:

2. 小结
containerd 源码分析系列文章介绍了 contianerd 是如何创建 container 的,完整了从 kubernetes 到容器创建这一条线。
containerd 源码分析:创建 container(三)的更多相关文章
- 手机自动化测试:appium源码分析之bootstrap三
手机自动化测试:appium源码分析之bootstrap三 研究bootstrap源码,我们可以通过代码的结构,可以看出来appium的扩展思路和实现方式,从中可以添加我们自己要的功能,针对app ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- Spring IOC 容器源码分析 - 创建原始 bean 对象
1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- Netty源码分析之NioEventLoop(三)—NioEventLoop的执行
前面两篇文章Netty源码分析之NioEventLoop(一)—NioEventLoop的创建与Netty源码分析之NioEventLoop(二)—NioEventLoop的启动中我们对NioEven ...
- jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——词法解析
jQuery源码9600多行,而Sizzle引擎就独占近2000行,占了1/5.Sizzle引擎.jQuery事件机制.ajax是整个jQuery的核心,也是jQuery技术精华的体现.里面的有些策略 ...
- linux中断源码分析 - 中断发生(三)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 回顾 上篇文章linux中断源码分析 - 初始化(二)已经描述了中断描述符表和中断描述符数组的初始化,由于在初始 ...
- 【LiteOS】LiteOS任务篇-源码分析-创建任务函数
目录 前言 链接 参考 笔录草稿 部分源码分析 源码分析 LOS_TaskCreate函数 LOS_TaskCreateOnly函数 宏 OS_TCB_FROM_PENDLIST 和 宏 LOS_DL ...
- InnoDB源码分析--缓冲池(三)
转载请附原文链接:http://www.cnblogs.com/wingsless/p/5582063.html 昨天写到了InnoDB缓冲池的预读:<InnoDB源码分析--缓冲池(二)> ...
- springMVC源码分析--SimpleControllerHandlerAdapter(三)
上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...
随机推荐
- Pytorch Dataset入门
Dataset入门 Pytorch Dataset code:torch/utils/data/dataset.py#L17 Pytorch Dataset tutorial: tutorials ...
- Redis工具类,不用框架时备用
redis.hostName=127.0.0.1 redis.port=6379 redis.database=3 redis.timeout=15000 redis.usePool=true red ...
- Python 潮流周刊#47:当你的老师希望你去做开源
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...
- linux中nginx的https证书过期替换
linux中nginx的https证书过期替换 工作记录,不然老是忘 一般提示这个就说明过期了 首先把新的证书换上去,最好和之前的文件名字一样,这样就不用改配置文件了 路径就自己找了需要,不过一般挺好 ...
- 轻松搭建基于 Serverless 的 ThinkPHP 应用
ThinkPHP 是什么? ThinkPHP 是一个免费开源的,快速.简单的面向对象的轻量级 PHP 开发框架,是为了敏捷 WEB 应用开发和简化企业应用开发而诞生的.ThinkPHP 从诞生以来一直 ...
- 【阿里云采购季】3月采购完,IT运维躺赢一年
阿里云2020上云采购季正式上线啦!今年的采购季可以逛些啥? 采购季正式期时间: 3月2日-3月31日 在这段时间里,想买啥就买吧,别忘了把想买的产品加入购物车噢,特惠产品叠加购物车满减,更划算噢! ...
- 媒体智能-淘宝直播流媒体互动实践 | D2 分享视频+文章
背景:今天给大家带来的分享主题是<媒体智能-淘宝直播流媒体互动实践>,内容分为5个部分,首先看看在淘宝直播的直播间里主播可以怎样给用户拜年:然后具体讲如何制作一个手势拜年的特效:接着介绍我 ...
- 拥抱云原生,Fluid结合JindoFS :阿里云OSS加速利器
简介: Fluid 是一个开源的 Kubernetes 原生的分布式数据集编排和加速引擎,主要服务于云原生场景下的数据密集型应用.在 Fluid 上使用和部署 JindoRuntime 实现数据集的可 ...
- Redis 7.0 Multi Part AOF的设计和实现
简介:本文将详解Redis中现有AOF机制的一些不足以及Redis 7.0中引入的Multi Part AOF的设计和实现细节. Redis 作为一种非常流行的内存数据库,通过将数据保存在内存中,R ...
- Dubbo 跨语言调用神兽:dubbo-go-pixiu
简介: Pixiu 是基于 Dubbogo 的云原生.高性能.可扩展的微服务 API 网关.作为一款网关产品,Pixiu 帮助用户轻松创建.发布.维护.监控和保护任意规模的 API ,接受和处理成千上 ...