Kubernetes基础知识

前言

之前的一年里我已经接触过一些Kubernetes相关的知识,但是一直以来没有系统地学习过Kubernetes。因此,我准备写一系列博客来系统地学习其相关知识,同时记录下自己的学习经历和感受,同时也希望能够帮助到想要学习相关知识的同学。

我学习时主要的的参考资料都会列在博客结尾,博客内容不一定正确、全面,只是作为我学习的记录,我会尽量把问题讲清楚,但是毕竟时间和能力有限,如果出现错误欢迎大家指出~

主要内容

作为系列博客的第一篇,今天主要来了解一下Kubernetes是什么,熟悉一下Kubernetes相关的一些常见术语。下一篇我会按照教程来搭建一个Kubernetes集群,再之后会在集群上一一尝试Kubernetes的各个组件,一边踩坑一边记录,一边学习~

Kubernetes 是什么?

Kubernetes(K8s)是一个基于容器技术的分布式架构领先方案,同时它也是一种设计思想,它也是一个开放的开发平台,也是一个完备的分布式系统支撑平台[1]。

这是参考资料[1]中的定义,当然Kubernetes官网也给出了它的定义:

Kubernetes 是用于自动部署,扩展和管理容器化应用程序的开源系统[3]。

从这些解释中可以看出,K8s是针对分布式系统的,与容器化技术相关,主要用于解决容器化应用程序的部署、扩展和管理问题。

那么以我目前的知识量来看,K8s是一套运维工具,开发时可以无需考虑最后是否使用它,如何使用它。如上面所说,它只是一个“平台”,是帮助我们来管理服务的。其它的目前也理解不了,现在先了解一下它的大概定位就行,后面随着深入的学习我们应该会对K8s的定位有更进一步的认识。

Google在2014年基于Borg发布了Kubernetes,Borg是Google内部使用的一个大规模集群管理系统。Kubernetes汲取了Borg过去十年的经验和教训,一经开源就迅速受到开源社区的追捧,许多知名公司加入到开发和推广的阵营[2]。

具体的咱也不清楚,总之据说很厉害就对了。但是究竟哪里厉害?是否应该是使用它,为什么要使用它,那就只能通过进一步学习来寻找答案了。

为什么要使用K8s?

我觉得[1]中一句话说的很好:

IT行业从来都是由新技术驱动的[1]。

随着时代和需求的变化,新技术的出现往往都是因为旧的技术已经无法满足现有的需求,不断探索和关注新的技术才能适应新的挑战。

不过面对新技术时也不是说大家都在用那么我也用,大家都说好那么我也得说好。一样东西会带来好处多少也需要付出一些代价,在学习和使用之前不妨也先思考一下:我学习/使用K8s能得到什么,需要付出什么?我是否真的有学习/使用它的必要?

嘛,冠冕堂皇的话也不多说,先根据我了解到的只是和参考资料来总结一下使用K8s的好处[1]:

  1. 可以减少运维成本。K8s作为一个运维平台提供了众多的工具,与旧有部署和运维方式相比本身就帮助我们做了很多事情,只需要简单的配置就可以非常方便地运维,团队可以把主要精力放在架构和开发。
  2. 可以使用微服务架构。微服务应用与传统巨石应用相比有着可独立开发、升级和扩展,系统稳定和迭代能力强,可快速扩容,技术栈自由等优点。K8s对于微服务架构的支持非常好,我们可以使用K8s来非常方便地管理微服务。
  3. 快速迁移。只要使用K8s,我们可以不改动任何配置文件,快速地把应用从私有云迁移至公有云上。目前阿里云、华为云、腾讯云都提供了K8s的PaaS服务,以后提供此类服务的厂商会越来越多,迁移方式也会更加简单和完善。
  4. 弹性服务扩容。K8s有服务弹性扩容机制,在遇到流量峰值的时候可以增加副本数量来应对。
  5. 横向扩容。整个系统可以快速从几个Node的集群迁移至几百个Node的集群。

其实这些好处都是得益于K8s底层工具和完善的服务调度和扩容策略,后面我们都会一一学习,这些好处看看即可,除非在生产系统中,否则平时我们能感受到的也就只有第一点而已2333。

不管怎么样,学还是要学的。下面我们来简单了解一下K8s中常见的一些术语和基本含义。

K8s相关知识

Cluster

Cluster其实指的就是你用来搭建K8s的集群,可以是多台物理机或者虚拟机。

其实,K8s的很多术语都可以看做是资源,它负责的就是把资源进行分配和管理,就跟大管家似的。Cluster其实指得就是K8s所拥有的资源的集合:所有的物理机或者虚拟机,包括计算、网络和存储等。

Master

K8s会把整个Cluster的资源整合之后抽象化之后来进行调度,同时它也需要给用户来提供统一控制和管理的入口。

在搭建集群的时候,我们会指定一台物理机或者虚拟机作为Master,它上面运行了K8s的核心服务,负责对整个Cluster进行管理和控制。上面主要运行着以下几个核心进程[1]:

  • Kubernetes API Server(kube-api-server): 集群控制的入口进程,提供了集群内所有资源的增删改查操作的入口。
  • Kubernetes Controller Manager(kube-controller-manager): 所有资源的自动化控制中心。
  • Kubernetes Scheduler(kube-scheduler): 负责资源调度的进程。
  • Etcd:负责存储所有资源对象的数据。

上面这几个核心进程在后面我们还会仔细研究,目前我们只需要知道这几个进程在Master上运行,并且负责整个集群的管理和调度,用户通过Master来完成资源对象的增删改查。

所以说,Master一旦宕机,整个集群将会处于失去管理的状态,虽然在后面我们一般只用一台物理机或者虚拟机作为Master,但是实际生产系统中一般会有三台物理机或者虚拟机作为Master来保证集群的高可用。

Node

Node就是集群中的普通机器,它们负责运行容器。Master会管理集群中的所有Node,Node负责监控汇报它上面运行的容器的状态,并且根据Master调度来管理容器的生命周期。Node一旦宕机,Master会将运行在其上的容器转移到其它Node上。在Node上主要运行着以下几个核心进程[1]:

  • kubelet: 负责Pod对应容器的创建、启停等任务,和Master密切合作完成集群管理的功能。
  • kube-proxy:实现K8s Service的通信和负载均衡的重要组件。
  • docker:负责本机容器的创建和管理。

Node可以随意增加和减少,只需要预先在Node上运行上述核心进程,然后向Master注册自己即可加入到集群之中。

Pod

上面所提到的Pod是K8s专有的一个重要概念,它是K8s的最小工作单元。每个Pod会有一个特殊的被称为“根容器”的Pause容器。除了Pause容器之外,每个Pod还包含一个或者多个业务容器。

K8s引入Pod的目的是[2]:

  1. 可管理性:有些容器联系比较紧密,需要一起工作,Pod是比容器更高层次的抽象资源,可以有多个容器。K8s以Pod为最小单位来进行调度、扩展、共享资源和管理生命周期。
  2. 通信和资源共享:Pod中的所有容器共享同一个IP和Port,容器之间可以通过localhost来通信。所有容器键也可以共享存储,volume挂载到Pod实质上是挂载到了Pod中的每一个容器。

Controller

K8s是通过Controller来创建Pod的,这也是我们最需要了解的一个重要部分,因为我们平常就是通过Controller来配置Pod的。Controller提供了多种Controller来满足不同场景的需求[1]:

  • Deployment:这是最常用的一种Controller,它可以管理Pod的运行。
  • ReplicaSet:实现了Pod的多副本管理,使用Deployment时会自动创建ReplicaSet,我们平常不需要直接使用ReplicaSet。
  • DaemonSet:用于每个Node最多运行一个Pod副本的场景。
  • StatefulSet:可以保证每个副本在Pod的生命周期中名称不变,其它Controller的Pod发生故障删除重启后Pod名称会发生变化。并且Stateful可以保证副本按照固定的顺序启动、更新或删除。
  • Job用于运行完就删除的应用,其它Controller的Pod长期持续运行。

关于这些Controller的具体使用在集群搭建之后,我们也会专门有一篇文章来进行详细介绍和讲解,这里只需要知道各种Controller的存在和大概作用就行。

Service

Service同样是我们需要着重了解的一个K8s的核心资源对象,我们上面说到Pod是K8s资源调度的单位,而Controller是负责创建、启停和删除Pod的,但是通过Controller启动的Pod有一个问题,Pod是允许有多个副本存在的,每个副本的IP是不同的,那么在访问时究竟访问哪个端口呢?就算知道了每个IP写好了访问方式,但是Pod有可能会销毁和重启,重启之后IP地址就会改变,所以直接用IP访问就不太现实[2]。

实际上,我们可以通过Service来访问Pod,我们在创建Service时通过label(后面解释)将Service和Pod进行绑定,Service会自动去寻找Pod的所有副本,而Service自身则拥有一个唯一的Cluster IP,也就是说,我们只需要通过Cluster IP : Port 访问Service,Service会自动寻找对应的一个或者多个Pod副本,而kube-proxy负责将Service的请求自动分配给多个Pod副本,自动完成了负载均衡。

所以,在K8s中,Pod负责创建容器,Service负责访问容器,在这个过程中自动完成了多副本Pod的负载均衡。

NameSpace

namespace其实就是类似于一个账号管理系统,就和你登录windows用的账号一样,每个用户的创建的资源都是互相隔离的,在k8s中,namespace就是负责不同用户或项目资源隔离的。

namespace可以将一个Cluster逻辑上划分为多个虚拟的Cluster,每个namespace可以认为是一个独立的Cluster,不同namespace资源完全隔离[2]。

如果不指定namespace,则所有的资源都会在default之下,kubernetes的系统进程运行在名为kube-system的namespace之下。

K8s相关的资源对象暂时介绍到这里,其实还有许多其它的东西没有说,比如Label、Volume、PersistentVolume、PersistentVolumeClaim、Annotation和ConfigMap等等。但是这些东西都是属于可以以后慢慢学习的高级内容,刚刚学习时我们还是先了解上述的核心资源对象,在脑海中想象出来K8s的基本结构和管理方式即可,其它东西说太多也记不住,等到后面以一个真实系统和实际应用场景为例再详细讲解那些东西。

整体认识

在了解了K8s的核心资源对象之后,我们其实可以在脑海中想象出来K8s集群的基本结构了:

首先K8s运行在几台物理机或者虚拟机上,我们就假设是四台好了,其中一台是Master,剩下三个是Node,就分别称之为Node1,Node2和Node3好了。

那么,首先,根据上面的描述Master和Node分别跑了几个核心进程,那么就如下图所示:

01

再结合每个进程的功能:Master中的kube-api-server给我们提供了资源管理的接口,所以我们可以在Master上面通过Deployment之类的Controller定义Pod。而kube-controller-manager则根据配置创建对应的Pod,kube-scheduler将需要创建的资源对象平均调度到所有正常工作的Node中,并且将绑定信息写入etcd。

而Node中kubelet通过kube-api-server监听到了Pod绑定事件,从etcd中拉取到资源对象配置后,去下载对应镜像。最终,容器在docker中启动了起来。当外部应用通过Service访问这个容器时,Node的kube-proxy负责将流量转发给真正的Pod副本。

上面是Master和Node运行的进程的结构,也就是真正运行的物理结构,但是实际上K8s引入了Pod、Service等虚拟资源,实际上我们进行调度和分配的过程还比较复杂,我们这里先看一种简化后能够说明目前问题的结构:

假设我们部署了一个Pod,这个Pod包含了两个Container:group和group-message,Pod的副本数量为2,同时我们创建了一个叫做group-service的Service关联到了这个副本,那么实际运行的情况应该是(此处为了简单起见,我们假设只有Node1和Node2两个Node,三个Node图太大了不好截图233):

02

两个Pod副本被分别调度到了两个Node中,但是两个Pod会和一个Service绑定,service会有一个Cluster IP,我们不需要知道实际上这个Pod在哪里运行,只需要通过Cluster IP:Port即可访问这个Pod中的容器。

假设我们这是又部署了一个Pod,这个Pod只含有一个容器user,同时我们创建了一个user-service与这个Pod绑定了,那么这时候的图应该为:

03

通过上面的解释和图片相信你能够对K8s的整体有了一定的认识。今天只是简单介绍一下K8s的大概情况和相关知识,帮助大家对所学习的内容建立起一个大概的印象,知道我们在学习的是一个什么东西,所以一直在空谈不动手。下节课我们将开始从零搭建一个K8s集群,后续我们将会在这个集群上进行更多的实验和学习。

参考资料

  1. 《Kubernetes 权威指南 第四版 从Docker到Kubernetes实践全接触》 龚正 等 中国工信出版社
  2. 《每天五分钟 玩转Kubernetes》 CloudMan 著 清华大学出版社
  3. Kubernetes官网: https://kubernetes.io/zh/