鄂破机看 发表于 2018-1-6 16:53:59

cri-o pod 创建源码分析

  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,>  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",>  }  
  // 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,>  s.runtime.CreateContainer(container)
  s.runtime.UpdateStatus(container)
  // setup the network
  podNamespace := ""
  netnsPath, err := container.NetNsPath()

  s.netPlugin.SetUpPod(netnsPath, podNamespace,>  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))
  }
页: [1]
查看完整版本: cri-o pod 创建源码分析