1、 server/sandbox.go

// RunPodSandbox creates and runs a pod-level sandbox

func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest) (*pb.RunPodSandboxResponse, error)

  name := req.GetConfig().GetMetadata().GetName()

  namespace := req.GetConfig().GetMetadata().GetNamespace() //在test中,该字段为空

  attempt := req.GetConfig().GetMetadata().GetAttempt() //在test中,该字段为空

  id, name, err := s.generatePodIDandName(name,  namespace, attempt)

  podSandboxDir := filepath.Join(s.sandbox, id)

  os.MkdirAll(podSandboxDir, 0755)

  ... // defer函数,用于创建pod失败,移除podSandboxDir

  // creates a spec Generator with the default spec

  g := generate.New()  // 返回一个Generator结构,其中包含了默认的spec

  podInfraRootfs := filepath.Join(s.root, "graph/vfs/pause")

  g.SetRootPath(filepath.Join(podInfraRootfs, "rootfs"))  //对默认的spec进行修改,针对的字段为Root和Process.Args

  g.SetRootReadonly(true)

  g.SetProcessArgs([]string{"/pause"})

  ... // 设置g.spec的hostname,如果req.config中的hostname 不为空的话

  // set log directory

  logDir := req.GetConfig().GetLogDirectory() // test的config文件默认为"."

  if logDir == "" {

    logDir = fmt.Sprintf("/var/log/ocid/pods/%s", id)

  }  

  // set DNS options

  ... // 从req.Config中获取dnsServers和dnsSearches

  resolvPat := fmt.Sprintf("%s/resolv.conf", podSandboxDir)

  parseDNSOptions(dnsServers, dnsSearches, resolvPath)

  // add labels

  labels := req.GetConfig().GetLabels()

  labelsJSON, err := json.Marshal(labels)  

  // add annotations

  annotations := req.GetConfig().GetAnnotations()
  annotationsJSON, err := json.Marshal(annotations)

  // Don't use SELinux separation with Host Pid or IPC Namespace

  if !req.GetConfig.GetLinux().GetNamespaceOptions().GetHostPid() && !req.GetConfig().GetLinux().GetNamespaceOptions().GetHostIpc() {

    processLabel, mountLabel, err = getSELinuxLabels(nil)

    g.SetProcessSelinuxLabel(processLabel)

  }

  containerID, containerName, err :=  s.generateContainerIDandName(name, "infra", 0)

  g.AddAnnotation("ocid/labels", string(labelsJSON))

  ... // add annotation "ocid/annotations", "ocid/log_path", "ocid/name", "ocid/container_name", "ocid/container_id"

  s.addSandbox(&sandbox{

    id:    id,

    ....

    containers:  oci.NewMemoryStore(),

    ...

    metadata:  req.GetConfig().GetMetadata(),

  })

  for k, v := range annotations {

    g.AddAnnotation(k, v)
  }

  ...  // setup cgroup settings, setup namespaces

  err = g.SaveToFile(filepath.Join(podSandboxDir, "config.json"))

  if _, err = os.stat(podInfraRootfs); err != nil {

    if os.IsNotExist(err) {

      utils.CreateInfraRootfs(podInfraRootfs, s.pausePath) // podInfraRootfs is /var/lib/ocid/graph/vfs/pause

      // copying infra rootfs binary: /usr/libexec/ocid/pause -> /var/lib/ocid/graph/vfs/pause/rootfs/pause
    }

  }

  container, err := oci.NewContainer(containerID, containerName, podSandboxDir, podSanboxDir, labels, id, false) // bundlePath 也是podSandboxDir

  s.runtime.CreateContainer(container)

  s.runtime.UpdateStatus(container)

  // setup the network

  podNamespace := ""

  netnsPath, err := container.NetNsPath()

  s.netPlugin.SetUpPod(netnsPath, podNamespace, id, containerName)

  s.runtime.StartContainer(container)

  s.addContainer(container)

  s.podIDIndex.Add(id)

  s.runtime.UpdateStatus(container)

  return &pb.RunSandboxResponse{PodSandboxId: &id}, nil

2、 oci/oci.go

// 该函数主要用于创建容器,并且同步等待返回容器的pid

func (r *Runtime) CreateContainer(c *Container) error

  parentPipe, childPipe, err := newPipe()

  defer parentPipe.Close()

  args := []string{"-c", c.name}

  args = append(args, "-r", r.path)

  if c.terminal { args = append(args, "-t")}

  cmd := exec.Command(r.conmonPath, args...)

  cms.Dir = c.bundlePath

  cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, }

  cmd.Stdin = os.Stdin

  cmd.Stdout = os.Stdout

  cmd.Stderr = os.Stderr

  cmd.ExtraFiles = append(cmd.ExtraFiles, childPipe)

  cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3))

  err = cmd.Start()

  childPipe.Close()

  // Wait to get container pid from conmon

  var si *syncInfo

  json.NewDecoder(parentPipe).Decode(&si)

  logrus.Infof("Received container pid: %v", si.Pid)

  return nil

3、 oci/oci.go

func (r *Runtime) UpdateStatus(c *Container) error

  ...

  out, err := exec.Command(r.path, "state", c.name).Output()

  stateReader := bytes.NewReader(out)

  json.NewDecoder(stateReader).Decode(&c.state)

  if c.state.Status == ContainerStateStopped {

    exitFilePath := filepath.Join(c.bundlePath, "exit")

    fi, err := os.Stat(exitFilePath)

    st := fi.Sys().(*syscall.Stat_t)

    c.state.Finished = time.Unix(st.Ctim.Sec, st.Ctim.Nsec)

    statusCodeStr, err := ioutil.ReadFile(exitFilePath)

    statusCode, err := strconv.Atoi(string(statusCodeStr))

    c.state.ExitCode = int32(utils.StatusToExitCode(statusCode))

  }

cri-o pod 创建源码分析的更多相关文章

  1. Netty中NioEventLoopGroup的创建源码分析

    NioEventLoopGroup的无参构造: public NioEventLoopGroup() { this(0); } 调用了单参的构造: public NioEventLoopGroup(i ...

  2. 【Java】NIO中Selector的创建源码分析

    在使用Selector时首先需要通过静态方法open创建Selector对象 public static Selector open() throws IOException { return Sel ...

  3. kubelet源码分析——关闭Pod

    上一篇说到kublet如何启动一个pod,本篇讲述如何关闭一个Pod,引用一段来自官方文档介绍pod的生命周期的话 你使用 kubectl 工具手动删除某个特定的 Pod,而该 Pod 的体面终止限期 ...

  4. kubelet源码分析——监控Pod变更

    前言 前文介绍Pod无论是启动时还是关闭时,处理是由kubelet的主循环syncLoop开始执行逻辑,而syncLoop的入参是一条传递变更Pod的通道,显然syncLoop往后的逻辑属于消费者一方 ...

  5. scheduler源码分析——调度流程

    前言 当api-server处理完一个pod的创建请求后,此时可以通过kubectl把pod get出来,但是pod的状态是Pending.在这个Pod能运行在节点上之前,它还需要经过schedule ...

  6. apiserver源码分析——启动流程

    前言 apiserver是k8s控制面的一个组件,在众多组件中唯一一个对接etcd,对外暴露http服务的形式为k8s中各种资源提供增删改查等服务.它是RESTful风格,每个资源的URI都会形如 / ...

  7. apiserver源码分析——处理请求

    前言 上一篇说道k8s-apiserver如何启动,本篇则介绍apiserver启动后,接收到客户端请求的处理流程.如下图所示 认证与授权一般系统都会使用到,认证是鉴别访问apiserver的请求方是 ...

  8. scheduler源码分析——preempt抢占

    前言 之前探讨scheduler的调度流程时,提及过preempt抢占机制,它发生在预选调度失败的时候,当时由于篇幅限制就没有展开细说. 回顾一下抢占流程的主要逻辑在DefaultPreemption ...

  9. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

随机推荐

  1. 泛函编程(17)-泛函状态-State In Action

    对OOP编程人员来说,泛函状态State是一种全新的数据类型.我们在上节做了些介绍,在这节我们讨论一下State类型的应用:用一个具体的例子来示范如何使用State类型.以下是这个例子的具体描述: 模 ...

  2. 【背景建模】VIBE

    ViBe是一种像素级的背景建模.前景检测算法,该算法主要不同之处是背景模型的更新策略,随机选择需要替换的像素的样本,随机选择邻域像素进行更新.在无法确定像素变化的模型时,随机的更新策略,在一定程度上可 ...

  3. xscript脚本

    最近看<游戏脚本高级编程>,然后顺便把里面实现的虚拟机,汇编器以及编译器手动用C++重写了一遍,原版书中提供的代码,风格不是很好,而且有几处BUG.我现在开源的代码中已经修复了BUG,而且 ...

  4. 为什么要用rem

    为什么要用rem 参考文章web app变革之rem 公司使用的375*667(也就是iPhone6)作为缩放比例标准,设计师是按照750px的标准出图 为了保证在不同的屏幕下显示效果基本等同,为此规 ...

  5. JavaScript正则表达式小记

    RegExp.html div.oembedall-githubrepos{border:1px solid #DDD;border-radius:4px;list-style-type:none;m ...

  6. SharePoint 2013 自定义模板页后在列表里修改不了视图

    前言 最近系统从2010升级至2013,有自定义模板页.突然发现在列表中切换不了视图,让我很费解. 我尝试过以下解决方案: 去掉自定义css 去掉自定义js 禁用所有自定义功能 结果都没有效还是一样的 ...

  7. R语言学习笔记:因子

    R语言中的因子就是factor,用来表示分类变量(categorical variables),这类变量不能用来计算而只能用来分类或者计数. 可以排序的因子称为有序因子(ordered factor) ...

  8. [android] SQLite 数据库的升级 和 降级

    public class SqliteHelp extends SQLiteOpenHelper { /* * context:创建数据库所需的 上下文对象 * name: 数据库名字 * facto ...

  9. JSP Model模式

    用JSP开发的Web应用模型可以分为Model1和Model2 对于小型的Web应用,通常可以使用模型1来完成. 模型1可以分为两种方式: 一种是完全使用JSP页面来开发Web应用: 另一种是使用JS ...

  10. 多种cell混合使用

    有时候我们会碰到一个tableView上有多种cell,这个时候就需要定义多种cell,根据条件判断,当满足某个条件的时候选择某个cell 先看plist文件: Person.h #import &l ...