前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >容器运行时硬核技术内幕 (3) 不要辜负这个时代

容器运行时硬核技术内幕 (3) 不要辜负这个时代

作者头像
用户8289326
发布2022-08-04 15:08:40
2130
发布2022-08-04 15:08:40
举报
文章被收录于专栏:帅云霓的技术小屋

预警:本期开始涉及kubernetes的实现源代码,也就是干货,请各位深呼吸。

上回我们说到,kubernetes与docker之间的距离,其实就是一个cri接口

kubernetes在每个工作节点(node)上安装了代理端kubelet,而kubelet本质上就是一个发放启动/停止容器命令的组件。当然,执行启动/停止容器命令的组件,就是容器运行时引擎了。

docker就是最常见的容器运行时引擎,没有之一。在kubernetes 1.3以前的版本中,它和docker是紧耦合的。

什么叫紧耦合呢?

我们前面提到,kubernetes发放容器启停命令的组件叫做kubelet。让我们看看kubelet的实现:

幸运的是,咱们生在一个伟大的时代,越来越多的信息透明化。

在全球最大同性交友网站github上,可以找到大多数开源组件的实现。

我们追溯到kubernetes 0.8:

https://github.com/kubernetes/kubernetes/blob/release-0.8/pkg/kubelet/kubelet.go

这个文件长达近1200行,我们只需要关注从500行开始的这个地方:

代码语言:javascript
复制
func (kl *Kubelet) runContainer(pod *api.BoundPod, container *api.Container, podVolumes volumeMap, netMode string) (id dockertools.DockerID, err error) {
  //......
  dockerContainer, err := kl.dockerClient.CreateContainer(opts)
  if err != nil {
    if ref != nil {
      record.Eventf(ref, "failed", "failed",
        "Failed to create docker container with error: %v", err)
    }
    return "", err
  }

肉眼可见地,kubelet直接调用了docker的API创建容器。

在kubernetes 1.0版本中,这个地方实现终于发生了变化。

https://github.com/kubernetes/kubernetes/blob/release-1.0/pkg/kubelet/kubelet.go

在函数NewMainKubelet中的280行:

代码语言:javascript
复制
  // Initialize the runtime.
  switch containerRuntime {
  case "docker":
    // Only supported one for now, continue.
    klet.containerRuntime = dockertools.NewDockerManager(
      dockerClient,
      recorder,
      readinessManager,
      containerRefManager,
      podInfraContainerImage,
      pullQPS,
      pullBurst,
      containerLogsDir,
      osInterface,
      klet.networkPlugin,
      klet,
      klet.httpClient,
      newKubeletRuntimeHooks(recorder),
      dockerExecHandler)
  case "rkt":
    conf := &rkt.Config{InsecureSkipVerify: true}
    rktRuntime, err := rkt.New(
      conf,
      klet,
      recorder,
      containerRefManager,
      readinessManager,
      klet.volumeManager)
    if err != nil {
      return nil, err
    }
    klet.containerRuntime = rktRuntime

即使忘光了代码如何写的同学,也可以看出,这个地方kubelet做了一个判断,根据选择的运行时引擎是docker或rkt,来选择容器运行时调用的接口。

显然,如果咱们期望使用docker或rkt以外的第三种容器运行时引擎,在kubernetes 1.0版本中,是行不通的。

在kubernetes 1.5版本中,这个问题通过引入CRI得到了解决。

让我们再一次打开世界最大的同性交友网站:

https://github.com/kubernetes/kubernetes/blob/release-1.5/pkg/kubelet/kubelet.go

还是找到函数NewMainKubelet:

从525行开始的地方,开始出现了CRI相关的内容。

代码语言:javascript
复制


    case "docker":
      streamingConfig := getStreamingConfig(kubeCfg, kubeDeps)
      // Use the new CRI shim for docker.
      ds, err := dockershim.NewDockerService(klet.dockerClient, kubeCfg.SeccompProfileRoot, kubeCfg.PodInfraContainerImage, streamingConfig, &pluginSettings, kubeCfg.RuntimeCgroups)
      if err != nil {
        return nil, err
      }
      // TODO: Once we switch to grpc completely, we should move this
      // call to the grpc server start.
      if err := ds.Start(); err != nil {
        return nil, err
      }

注意到注释内容:"Once we switch to grpc completely..."

实际上,在1.6版本的kubernetes中,才真正开始使用grpc机制实现CRI接口,这一机制也沿用至今。

在下一期中,我们开始拆解kubernetes 1.6引入的grpc机制实现的CRI规范。

我们可以在github上如此方便地通过kubernetes的源码修改历程学习到它的演进历史,做到“知其然,并知其所以然”,是生在我们这个时代的幸运,我们应该珍惜和感激,通过实际行动把这个时代建设得更美好……

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 帅云霓的技术小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档