Kubernetes的本质

  • 一个“容器”,实际上是一个由Linux Namespace、Linux Cgroups和rootfs三种技术构建出来的隔离环境。
    • 容器的静态视图:一组联合挂载在/var/lib/docker/aufs/mnt上的rootfs,称为“容器镜像”(Container Image)
    • 容器的动态视图:一个由Namespace+Cgroups构成的隔离环境,称为“容器运行时”(Container Runtime)
  • 在整个“开发-测试-发布”的流程中,真正承载着容器信息进行传递的,是容器镜像,非容器运行时。
  • 作为一家云服务商或者基础设施提供商,只要能够将用户提交的Docker镜像以容器的方式运行起来,就能成为容器生态图上的一个承载点,从而将整个容器技术栈上的价值,沉淀在我的这个节点上。
  • 单一容器-->容器集群
  • 容器-->容器云
  • 容器就从一个开发者手里的小工具,一跃成为了云计算领域的绝对主角;而能够定义容器组织和管理规范的“容器编排”技术,则当仁不让地坐上了容器技术领域的“头把交椅”。
  • Borg技术架构图Kubernetes的本质_第1张图片
  • Kubernetes项目在Borg体系的指导下,体现出一种独有的“先进性”与“完备性”,而这些特质才是一个基础设施领域开源项目赖以生存的核心价值。
  • kubernetes项目可以带来什么?
    • 希望把一个应用的容器镜像,在一个给定的集群上把这个应用运行起来。
    • 还希望 Kubernetes 能给我提供路由网关、水平扩展、监控、备份、灾难恢复等一系列运维能力。
  • K8S框架:Kubernetes的本质_第2张图片
  • Master节点:
    • 负责API服务的kube-apiserver
    • 负责调度的kube-scheduler
    • 负责容器编排的kube-controller-manager
    • 整个集群的持久化数据,则由kube-apiserver处理后保存在Etcd中
  • Node节点:
    • 核心:kubelet,主要负责和容器运行时(比如Docker项目)打交道。
      • k8s--CRI-->容器--OCI-->操作系统内核
      • 这个交互所依赖的,是一个称作CRI(Container Runtime Interface)的远程调用接口,这个接口定义了容器运行时的各项核心操作,比如:启动一个容器所需的所有参数。
      • Kubernetes 项目并不关心你部署的是什么容器运行时、使用的什么技术实现,只要你的这个容器运行时能够运行标准的容器镜像,它就可以通过实现 CRI 接入到 Kubernetes 项目当中。
      • 具体的容器运行时,比如 Docker 项目,则一般通过 OCI 这个容器运行时规范同底层的 Linux 操作系统进行交互,即:把 CRI 请求翻译成对 Linux 操作系统的调用(操作 Linux Namespace 和 Cgroups 等)。
      • kubelet 还通过 gRPC 协议同一个叫作 Device Plugin 的插件进行交互。这个插件,是 Kubernetes 项目用来管理 GPU 等宿主机物理设备的主要组件,也是基于 Kubernetes 项目进行机器学习训练、高性能作业支持等工作必须关注的功能。
      • kubelet 的另一个重要功能,则是调用网络插件和存储插件为容器配置网络和持久化存储。这两个插件与 kubelet 进行交互的接口,分别是 CNI(Container Networking Interface)和 CSI(Container Storage Interface)。
      • kubelet 完全就是为了实现 Kubernetes 项目对容器的管理能力而重新实现的一个组件,与 Borg 之间并没有直接的传承关系。
  • Kubernetes项目要解决的问题:
    • 运行在大规模集群中的各种任务之间,实际上存在着各种各样的关系。这些关系的处理,才是作业编排和管理系统最困难的地方。
  • 从一开始,Kubernetes项目就没有像同期的各种“容器云”项目那样,把Docker作为整个架构的核心,而仅仅把它作为最底层的一个容器运行时实现。
  • 但容器技术出现以后,你就不难发现,在“功能单位”的划分上,容器有着独一无二的“细粒度”优势:毕竟容器的本质,只是一个进程而已。
  • 一个应用被部署在虚拟机里面之后,你还得手动维护很多跟它协作的守护进程(Daemon),用来处理它的日志搜集、灾难恢复、数据备份等辅助工作。
  • 只要你愿意,那些原先拥挤在同一个虚拟机里的各种应用、组件、守护进程,都可以被分别做成镜像,然后运行在一个个专属的容器中。它们之间互不干涉,拥有各自的资源配额,可以被调度在整个集群里的任何一台机器上。而这,正是一个PaaS系统最理想的工作状态,也是所谓“微服务”思想得以落地的先决条件。
  • 一旦要追求项目的普适性,那就一定要从顶层开始做好设计。Kubernetes项目最主要的设计思想是,从更宏观的角度,以统一的方式来定义任务之间的各种关系,并且为将来支持更多种类的关系留有余地。
  • 在 Compose 项目中,其具体做法是:Docker 会在 Web 容器中,将 DB 容器的 IP 地址、端口等信息以环境变量的方式注入进去,供应用进程使用,比如:
    • DB_NAME=/web/db
    • DB_PORT=tcp://172.17.0.5:5432
    • DB_PORT_5432_TCP=tcp://172.17.0.5:5432
    • DB_PORT_5432_TCP_PROTO=tcp
    • DB_PORT_5432_TCP_PORT=5432
    • DB_PORT_5432_TCP_ADDR=172.17.0.5
  • 在常规环境下,这些应用往往会被直接部署在同一台机器上,通过Localhost通信,通过本地磁盘目录交换文件。而在Kubernetes项目中,这些容器则会被划分为一个“Pod”,Pod里的容器共享同一个Network Namespace、同一组数据卷,从而达到高效率交换信息的目的。
  • Kubernetes项目的做法是给Pod绑定一个Service服务,而Service服务声明的IP地址等信息是“终生不变”的。这个Service服务的主要作用,就是作为Pod的代理入口(Portal),从而代替Pod对外暴露一个固定的网络地址。
  • Kubernetes项目核心功能的“全景图”。Kubernetes的本质_第3张图片
    • 我们从容器这个最基础的概念出发,首先遇到容器间“紧密协作”关系的难题,于是就扩展到了Pod;
    • 有了Pod之后,我们希望能一次启动多个应用的实例,这样就需要Deployment这个Pod的多实例管理器;
    • 有了这样一组相同的Pod后,我们需要通过一个固定IP地址和端口以负载均衡的方式访问它,于是就有了Service。
    • Web应用对数据库访问时需要Credential(数据库的用户名和密码)信息,在Kubernetes中这样的关系又如何处理?
      • Kubernetes项目提供了一种叫作Secret的对象,它其实是一个保存在Etcd里的键值对数据。把Credential信息以Secret的方式存在Etcf里,Kubernetes就会在你指定的Pod(eg,Web应用的Pod)启动时,自动把Secret里的数据以Volume的方式挂载到容器。这样,这个Web应用就可以访问数据库了。
    • Job,用来描述一次性运行的Pod(比如,大数据任务);
    • DaemonSet,用来描述每个宿主机上必须且只能运行一个副本的守护进程服务;
    • CronJob,用于描述定时任务;
    • Kubernetes项目,推崇的使用方法是:
      • 首先,通过一个“编排对象”,比如Pod、Job、CronJob等,来描述你试图管理的应用;
      • 然后,再为它定义一些“服务对象”,比如Service、Secret、Horizontal Pod Autoscaler(自动水平扩展器)等。这些对象,会负责具体的平台级功能。
      • 这种使用方法,就是所谓的“声明式API”。这种API对应的“编排对象”和“服务对象”,都是Kubernetes项目中的API对象(API Object)。
  • Kubernetes项目如何启动一个容器化任务呢?
    • eg:我现在已经制作好了一个 Nginx 容器镜像,希望让平台帮我启动这个镜像。并且,我要求平台帮我运行两个完全相同的 Nginx 副本,以负载均衡的方式共同对外提供服务。
      • 具体操作:编写一个YAML文件(比如名叫 nginx-deployment.yaml):
      • apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nginx-deployment
          labels:
            app: nginx
        spec:
          replicas: 2
          selector:
            matchLabels:
              app: nginx
          template:
            metadata:
              labels:
                app: nginx
            spec:
              containers:
              - name: nginx
                image: nginx:1.7.9
                ports:
                - containerPort: 80

         

      • kubectl create -f nginx-deployment.yaml
  • 容器其实可以分为两个部分:容器运行时和容器镜像。
  • 很多集群管理项目(比如Yarn、Mesos,以及Swarm)所擅长的,都是把一个容器,按照某种规则,放置在某个最佳节点上运行起来,这种功能,我们称为“调度”。
  • Kubernetes项目所擅长的,是按照用户的意愿和整个系统的规则,完全自动化地处理好容器之间地各种关系。这种功能,就是:编排。
  • Kubernetes项目地本质,是为用户提供一个具有普遍地容器编排工具。更重要地是,Kubernetes项目为用户提供地不仅限于一个工具。它真正地价值,乃在于提供了一套基于容器构建分布式系统地基础依赖。
  •  
  •  

你可能感兴趣的:(Kubernetes,kubernetes)