什么是kubernetes

Kubernetes是一个完整的分布式系统支撑平台,kubernetes具有完备的集群管理能力,包括多层次的安全防护和准入机制,多租户应用支撑能力,透明的服务注册和服务发现机制,内建了智能的负载均衡器,强大的故障发现和自我修复能力,服务滚动升级和在线扩容能力,可扩展的资源自动调度机制,以及多粒度的资源配额管理能力,Kubernetes使用共享网络将多个物理机或者虚拟机汇集到一个集群中,在每个服务器之间进行通信,该进群是配置kubernetes的所有组件、功能和工作负载的物理平台。集群中一台服务器(或高可用部署中的一组服务器)作为master,负责管理整个集群,剩余的其他机器作为 worker node,它们是充当工作节点的服务器,为什么叫kubernetes为K8S呢?因为从u到e之间有8个字母所以叫k8s,k8s中的大部分概念,如POD,replication,controller,service等都可以被看作为一种资源对象,几乎所有的资源对象都可以通过k8s提供的kubectl工具来调用,比如执行增,删,改,查等操作,并将其保存在etcd中进行持久化存储,它通过跟踪和对比etcd库里保存的“资源期望状态”与当前环境中的“实际资源状态”的差异来实现自动控制和自动纠错的高级功能

k8s术语

master:

  • master是整个集群的网关和中枢,主要负载用户和客户端暴漏API,跟踪其他服务器的健康状态,以最优方式调度工作负载,以及编排其他组件之间的通信任务,它是用户与客户端和集群之间的核心联络点,并负责k8s系统的大多数集中式管控逻辑,单个master节点即可完成其所有的功能,但出于冗余及负载均衡的目的,生产环境通常需要部署多个master做高可用

node:

  • node是k8s集群的工作节点,负责接收来自master的工作指令,并根据指令快速的创建或者销毁Pod对象,以及调整规则,理论上讲,Node可以是任何形式的计算设备,只要你能在该设备上面部署其需要的组件,不过master都会统一的将其抽象为Node对象进行管理,在生产环境中,他们通常数量众多
  • k8s将所有node的资源集结与一处形成一台更加强大的服务器,在用于需要将应用部署到上面时,master会使用调度算法将其自动指派到某个特定的node节点上运行,当node加入集群或者从集群中移除时候,master也会按照需要重新编排该移除的节点上的Pod,用户无需关系其应用运行与何处,从抽象的角度来讲,k8s还有着众多的组件来支撑其内部的业务逻辑,包括运行应用,应用编排,服务暴漏,应用恢复等

Pod:

  • k8s并不直接运行容器,而是使用一个抽象的资源对象来封装一个或者多个容器,这个抽象的资源对象为Pod,它也是k8s的最小调度单元。同一pod中的容器共享网络名称空间和存储资源,这些容器可通过本地回环接口直接通信,但是彼此之间又在mount,user,及PID等名称空间上保持了隔离,但是作为最为最小调度单元,它应该尽可能的保持“小”,通常只应该包含一个主容器,或者与业务由关联的其他容器,以及必要的辅助型容器,每一个被创建出来的Pod都有一个特殊的被称为“根容器”的pause容器,pause容器作为pod的根容器,以它的状态代表整个容器的状态,Pod里的多个业务容器共享Pause容器的IP,共享 Pause容器挂接的Volume,Kubernetes为每个Pod都分配了唯一的IP地址,称之为Pod IP,一 个Pod里的多个容器共享Pod IP地址。Kubernetes要求底层网络支持集 群内任意两个Pod之间的TCP/IP直接通信,这通常采用虚拟二层网络 技术来实现,例如Flannel、Open vSwitch等,因此我们需要牢记一 点:在Kubernetes里,一个Pod里的容器与另外主机上的Pod容器能够 直接通信。
  • Pod的特征
  • 包含多个共享IPC,Network和UTC namespace的容器,可以直接通过localhost通信
  • 所有Pod内容器都可以访问共享的Volume,可以访问共享数据
  • 无容错性,直接创建的Pod一旦被调度后就跟Node绑定,即使Node挂掉也不会被重新调度(而是被删除),因此推荐使用Deployment、DaemonSet等控制器来容错
  • 优雅终止,Pod删除的时候会选给其容器内的进程发送SIGTERM信号,等到一段时间后强制停止依然还在运行的进程
  • 特权容器(通过SecurityContext配置)具有改变系统权限的配置(在网络插件中大量应用)

label(资源标签)

  • 标签是将资源进行分类的标识符,资源标签就是一个键值型(key/valus)的数据,其中key和vlaue由用户自己制定,标签是为了让对象(如POD)有更好的辨识属性,这些属性仅对用户存在特定的意义,label可以在对象被创建时加入到对象的资源清单里面,label可以被附加到各种资源对象上,一个对象可以拥有多个label,一个label也可以被附加到多个对象

label selector(标签选择器)

  • 它是一种根据label来过滤符合条件的资源对象的机制,用户通常使用标签对资源对象进行分类,然后使用标签选择器挑选出他们

POD控制器

  • 尽管pod是集群的最小调度单元,但是用户通常并不会直接部署及管理Pod资源对象,而是借助于另一类对象—控制器对其进行管理,用于工作的控制器是一种管理Pod生命周期的资源抽象,它们是K8S上的一类对象,而非单个资源对象,包括replication controller,replicaset,deployment,statefulset,job等

Service(服务资源)

  • Service是建立在一组Pod对象之上的资源对象,它通过标签选择器选定一组Pod对象与之绑定,并为这组Pod对象定义一个统一的固定访问入口,若K8S集群存在DNS附件,它将会在Service创建时为其自动配置一个DNS名称以便客户端进行服务发现,到达Service IP的请求都将被负载均衡到后端的各个Pod对象之上,因此Service从本质上来讲是一个四层代理服务,另外,Service还可以将集群外部流量引入到集群内部中来
  • k8s在设计之初就充分考虑了针对容器的服务发现和负载均衡机制,提供了Service资源,并通过kube-proxy配合cloud provider来适应不同的应用场景,随着K8S用户的激增,用户场景的不断丰富,又产生了一些新的负载均衡机制。目前K8s中的负载均衡可以分为以下几种机制,每种机制都有其特定的应用场景
  • Service:直接用Service提供集群内部的负载均衡,并借助cloud provider提供的LB提供外部访问
  • Ingress Controller:还是用Service提供集群内部的负载均衡,但是通过自定义Ingress Controller提供外部访问
  • Service LoadBanlancer:把load banlancer直接跑在容器中,实现bare metal的服务负载均衡
  • Custom LoadBanlancer:自定义负载均衡,替代kube-proxy,一般在物理部署K8S时使用,方便接入公司已有的外部服务
  • Service是对一组提供相同功能的Pod的抽象,并为它们提供一个统一的访问入口,借助Service,应用可以很方便的实现负载均衡于服务发现,并实现应的零宕机升级,Service通过标签来选取后端服务,一般配合Deployment来保证后端容器的正常运行,这些匹配标签的Pod IP和端口列表组成endpoints,由kube-proxy负载将服务IP负载均衡到这些endpoints上

volume(存储卷)

  • 存储卷是独立于容器文件系统之外的存储空间,常用于扩展容器的存储空间并为容器提供持久化的存储能力,也是Pod中能够被多个容器访问的工程目录,Kubernetes中的Volume被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下,k8s集群上的存储卷大体可以分为临时存储卷,本地存储卷和网络存储卷,其中临时存储卷和本地存储卷都位于Node节点本地,一旦Pod被调度到其他的Node节点,这种类型的存储卷就会无法访问到,因此临时存储卷和本地存储通常用于数据缓存,持久化的数据则需要放置与持久卷之上
  • 与Docker不同,kubernetes Volume的生命周期与Pod绑定
  • 容器挂掉后,kubelet再次重启容器时,Volume的数据依然还在
  • 而Pod删除时,Volume才会清理,数据是否会丢失取决于Volume的类型,比如emptyrDir的数据会丢失,而PV的数据则不会丢失

name和namespace(名称空间)

  • name是集群中资源对象的标识符,它们的作用域通常是名称空间,因此名称空间是名称的额外的限定机制,在同一个名称空间中,同一类型资源对象的名称必须具有唯一性,名称空间通常用于实现租户或者项目的资源隔离,从而形成逻辑分组,创建Pod时如果未指定名称空间则默认为default

Annotation (注解)

  • 注解是另外一种附加在对象上面的键值类型的数据,但他有用更强大的数据容量,Annotation常用于各种非标识型元数据附加到对象上面,它不能用于标识和选择对象,Annotation是用户任意定义的附加信息

Ingress

  • K8S将Pod对象的网络与外部的网络进行了隔离,Pod和Service等对象之间的通信都使用的是其内部的专用地址进行通信,若需要开放某些POD对象给外部用户访问,则需要为其打开一个集群内部的通道,除了service之外,Ingress也是这类通道的实现方式之一

Job

  • 批处理任务,通常并行(或者串行)启动多个计算进程去处理一批 工作项(work item),在处理完成后,整个批处理任务结束,我们可以通过 Kubernetes Job这种新的资源对象定义并启动一个批处理任务Job。与
    RC、Deployment、ReplicaSet、DaemonSet类似,Job也控制一组Pod 容器。从这个角度来看,Job也是一种特殊的Pod副本自动控制器,同 时Job控制Pod副本与RC等控制器的工作机制有以下重要差别。
    (1)Job所控制的Pod副本是短暂运行的,可以将其视为一组 Docker容器,其中的每个Docker容器都仅仅运行一次。当Job控制的 所有Pod副本都运行结束时,对应的Job也就结束了。Job在实现方式 上与RC等副本控制器不同,Job生成的Pod副本是不能自动重启的, 对应Pod副本的RestartPoliy都被设置为Never。因此,当对应的Pod副 本都执行完成时,相应的Job也就完成了控制使命,即Job生成的Pod 在Kubernetes中是短暂存在的。Kubernetes在1.5版本之后又提供了类 似crontab的定时任务——CronJob,解决了某些批处理任务需要定时 反复执行的问题。 (2)Job所控制的Pod副本的工作模式能够多实例并行计算,以 TensorFlow框架为例,可以将一个机器学习的计算任务分布到10台机 器上,在每台机器上都运行一个worker执行计算任务,这很适合通过 Job生成10个Pod副本同时启动运算。
  • Job类型:
  • 非并行Job:通常创建一个Pod直到其成功结束
  • 固定结束次数的Job:设置spec.completions,创建多个Pod,直到spec.completions,个Pod成功结束
  • 带有工作队列的Pod:设置.spec.Parallelism但不设置.spec.completions,当所有Pod结束并且至少一个访问成功时,Job就人为是成功

Replication Controller

  • RC是Kubernetes系统中的核心概念之一,简单来说,它其实定义 了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值

Deployment

  • Deployment是Kubernetes在1.2版本中引入的新概念,用于更好地解决Pod的编排问题。为此,Deployment在内部使用了Replica Set来实现目的,无论从Deployment的作用与目的、YAML定义,还是从它 的具体命令行操作来看,我们都可以把它看作RC的一次升级,两者 的相似度超过90%,Deployment相对于RC的一个最大升级是我们可以随时知道当前 Pod“部署”的进度。实际上由于一个Pod的创建、调度、绑定节点及在 目标Node上启动对应的容器这一完整过程需要一定的时间,所以我 们期待系统启动N个Pod副本的目标状态,实际上是一个连续变化 的“部署过程”导致的最终状态。 Deployment的典型使用场景有以下几个。
    ◎ 创建一个Deployment对象来生成对应的Replica Set并完成 Pod副本的创建。
    ◎ 检查Deployment的状态来看部署动作是否完成(Pod副本数 量是否达到预期的值)。
    ◎ 更新Deployment以创建新的Pod(比如镜像升级)。
    ◎ 如果当前Deployment不稳定,则回滚到一个早先的 Deployment版本。
    ◎ 暂停Deployment以便于一次性修改多个PodTemplateSpec的 配置项,之后再恢复Deployment,进行新的发布。
    ◎ 扩展Deployment以应对高负载。
    ◎ 查看Deployment的状态,以此作为发布是否成功的指标。
    ◎ 清理不再需要的旧版本ReplicaSets。

Secret

  • Secret解决了密码,token,密钥等敏感数据的配置问题,而不需要把这些敏感数据暴漏到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用
  • Secret有三种类型
    ◎ Opaque:base64编码格式的Secret,用来存储密码、密钥等,但数据也通过base64 —decode解码得到原始数据,所以加密行很弱
    ◎ kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息
    ◎ kubernetes.io/service-account-token:用于被serviceaccout引用,serviceaccout创建时kubernetes会默认创建对应的secret,Pod如果使用了serviceaccout,对应的secret会自动挂载到Pod的/run/secret/kubernetes.io/serviceaccount目录中
    备注:serviceaccount用来使得Pod能够访问kubernetes API

kubernetes的特性

自动装箱

  • 建构于容器之上,基于资源依赖及其他约束自动完成容器部署且不影响其可用性,并通过调度机制混合关键型应用和非关键型应用的工作负载于同一节点以提升资源利用率

故障自愈

  • 支持容器故障后自动重启、节点故障后重新调度容器,以及其他可用节点、健康状态检查失败后关闭容器并重新创建等自我修复机制

水平扩展

  • 支持通过简单命令或 UI 手动水平扩展,以及基于 CPU 等资源负载率的自动水平扩展机制

服务发现和负载均衡

  • Kubernetes 通过其附加组件之一的 KubeDNS (或 CoreDNS )为系统内置了服务发现功能,它会为每个 Service 配置 DNS 名称,并允许集群内的客户端直接使用此名称发出访问请求,而 Service 则通过 iptables 或者ipvs 内建了负载均衡机制

自动发布和回滚

  • Kubernetes 支持“灰度”更新应用程序或其配置信息,它会监控更新过程中应用程序的健康状态,以确保它不会在同一时刻杀掉所有实例,而此过程中一旦有故障发生,就会立即自动执行回滚操作

密钥和配置管理

  • Kubernetes ConfigMap 实现了配置数据与 Docker 镜像解耦,需要时,仅对配置做出变更而无须重新构建 Docker 镜像,这为应用开发部署带来了很大的灵活性 此外,对于应用所依赖的一些敏感数据,如用户名和密码、 密钥等信息 Kubernetes专门提供了Secret对象为其解耦,既便利了应用的快速开发和交付,又提供了一定程度上的安全保障

存储编排

  • Kubernetes 支持 Pod 对象按需自动挂载不同类型的存储系统 ,这包括节点本地存储公有云服务商的云存储(如 AWS GCP 等),以及网络存储系统(例如, NFS、 iSCSI Gluster Ceph Cinder和Flocker 等)

批量处理作业

  • 除了服务型应用, Kubernetes 还支持批处理作业及 CI (持续集成),如果需要, 一样以实现容器故障后恢复

常见的docker编排工具

  • docker compose:只支持单机的docker host编排
  • docker swarm:支持集群编排,能够将多个docker host平台之下的资源集中整理使用
  • docker machine:初始化docker主机,使该docker主机能够满足加入docker swarm集群的条件,从而使该主机能够成为docker swarm的一份子
  • mesos:AWS旗下产品,但是mesos是一个IDC的OS,能够将一个IDC当中提供的硬件资源进行统一调度分配
  • kubernetes:基于谷歌borg系统开发的容器编排工具,kubernetes是一种架构

kubernetes组件介绍

一个典型的K8S集群应该由多个工作节点(worker node)和一个或者多个master节点,以及一个集群状态存储系统(etcd)组成,其中master节点负责整个集群的管理工作,为集群提供管理接口,并监控和编排集群中的各个工作节点,各节点负责以 Pod 的形式运行容器,因此,各节点需要事先配置好容器运行依赖到的所有服务和资源,如容器运行时环境等 master节点主要由apiserver,controller-manager和scheduler三个组件以及一个用于存储集群状态的etcd存储服务组成,而每个node节点则需要包含kubelet,kube-proxy及容器引擎(docker)等组件,此外,一个完整的K8S集群还需要依赖与一些附件组件,如coreDNS,flannel或者calico等

master节点:

kube-apiserver:

  • kube-apiserver负责输出RESTful风格的kubernetes API,它是发往集群的所有REST操作的命令接入点,并负责校验,接收和相应所有的rest请求,结果状态被永久的存储与etcd中,通俗点讲kube-apiserver的主要功能就是负责接收客户端和node节点发来的所有请求,并且将不同的请求发给不同的组件进行处理

kube-scheduler:

  • 负责检测每一个node上总共可用的硬件资源,将需要待调度的POD按照调度算法绑定到合适的工作节点

kube-controller-manager:

  • 负责控制和管理对应的资源,它们是处理集群中常规任务的后台线程。逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成独立的可执行文件,并在单个进程中运行。

etcd:

  • 用户保存集群的配置信息和各种资源的状态信息,当数据发生变化时,etcd会很快速的通知集群的各个组件

DNS:

  • 虽然其他插件并不是必需的,但所有 Kubernetes 集群都应该具有Cluster DNS,许多示例依赖于它。Cluster DNS 是一个 DNS 服务器,和您部署环境中的其他 DNS 服务器一起工作,为 Kubernetes 服务提供DNS记录。Kubernetes 启动的容器自动将 DNS 服务器包含在 DNS 搜索中。

node节点

容器引擎:

  • 主要用于运行容器,目前主流的还是docker,它负责下载镜像和运行容器,

kube-proxy:

  • 每一个工作节点都需要部署一个kube-proxy,它能够按照需要生成iptables规则或者ipvs规则,然后通过维护主机上的网络规则并执行连接转发

kubelet:

  • kubelet是运行在node节点上的守护进程,它从API server接收关于pod对象的配置信息,并确保它们能够处于期望的状态,kubelet会在API server上注册当前的工作节点,并定期向master汇报节点的资源使用情况,负责管理和维护Pod的运行

addons

通常情况下,我们为了让整个K8S集群有更加完整的功能,所以还需要给集群添加一些附件,它们通常是由第三方提供的特定应用程序,并且需要托管在K8S集群上面,插件本身是受名称空间限制的,默认被创建于kube-system名称空间,下面列出几个常用的附件 coreDNS:

  • 在早期的版本叫kubedns,主要负责集群中提供DNS服务的POD,同一个集群中的其它POD可以使用此DNS服务解决主机名问题

dashboard:

  • k8s集群的web UI工具,集群的全部功能基本集成进去了,可以用来管理集群中的应用甚至是集群自身

Ingress controller:

  • Service是一种工作与传统层的负载均衡器,而Ingress则是在应用层实现的HTTP(S)负载均衡机制,不过,Ingress资源自身并不能进行“流量穿透”,它仅仅是一组路由规则的集合,这些规则需要通过Ingress控制器发挥作用,使用Ingress进行负载分发时候,Ingress controller基于Ingress规则将客户端请求直接转发到Service对应的后端POD上,这样会跳过kube-proxy的转发功能,kube-proxy不再起作用,如果Ingress提供的是对外的服务,则实际上实现的是边界路由器的功能,目前可以实现Ingrees的项目有Nginx,Traefik,Envoy和Haproxy等,Envoy和Nginx可能用的会比较多

kubernetes的基本网络模型基础

k8s网络模型设计的一个基础原则是:每个Pod都有一个独立的IP地址,并且假定所有Pod都在一个可以直接联通的,扁平的网络空间中,所以不管他们是不是运行在同一个node中,都要求他们可以直接通过对方的IP进行通信,设计这个原则的原因是,用户不需要额外考虑如何建立Pod之间的连接,也不需要考虑如何将容器端口映射到主机端口等问题,实际上,在K8S的世界里,IP是以Pod为单位进行分配的,一个Pod内部的所有容器共享一个网络堆栈(相当于一个网络命名空间,他们的IP地址,网络设备,配置等都是共享的) K8S的网络中主要存在四种类型的通信:同一Pod内的容器间通信,各Pod彼此之间的通信,Pod与Service之间的通信,集群外部的流量与Service之间的通信。k8s为Pod和Service资源对象分别使用了不同的专用网络,Pod网络由k8s的网络插件来实现,而Service的网络则由k8s集群指定,为了提供更灵活的解决方式,k8s的网络模型需要借助于外部插件实现,它要求任何实现方式都必须满足以下需求 1.所有容器都可以在不利用NAT的方式与别的容器进行通信 2.所有节点都可以在不利用NAT的方式与所有的容器进行通信 3.容器自己使用的IP也需要能被其他容器或者节点直接看到 k8s使用的网络插件必须能够为Pod满足以上的要求,它需要为每个Pod配置至少一个特定的地址,即Pod IP,Pod IP地址实际存在于某个网卡(可能是虚拟设备)上,而Service的地址却是一个虚拟的IP地址,没有任何网络接口配置此地址,它由kube-proxy借助iptables规则或者ipvs规则重新定向到本地端口,再将其调度到后端Pod对象,Service的IP地址是集群提供服务的接口,也称为cluster IP Pod网络及其IP由k8s的网络插件负责配置和管理,具体使用的网络地址可以再管理配置网络插件时指定,而cluster网络和IP则是由K8S集群负责配置和管理 总结起来,K8S集群至少包含三个网络,

  • 节点网络,其地址配置在各主机的网卡上,用于各个node主机之间的通信,此地址并不能由k8s来管理,
  • Pod网络,专门用于pod资源对象的网络,它是一个虚拟网络,用于为各Pod对象设定IP地址等网络参数,其地址配置于Pod中容器的网络接口上面,Pod网络需要借助于插件或CNI插件实现,该插件可独立部署于K8S集群之外,也可以托管在K8S集群上面,它需要在构建K8S集群时由管理员进行指定,然后在创建Pod对象的时候由其自动完成各网络参数的配置
  • Clusetr网络,专用于Service资源对象的网络,它也是一个虚拟网络,用于为K8S集群中的Service配置IP地址,但是这个地址并不配置在主机或者容器的任何网络接口上面,儿是通过Node上的kube-proxy配置为iptables规则或者ipvs规则,从而将发往此地址的所有流量调度到其后端的各Pod对象上,Service网络在K8S集群创建时指定,而各Service的地址则在用户创建Service时予以动态配置

集群上的网络通信

K8S集群的客户端大体可以分为两类,API Server客户端和应用程序(运行在Pod中的容器客户端),第一类客户端通常包含人类用户和Pod对象两种,它们经常通过API Server访问K8S集群完成管理任务,例如管理集群上的各种资源对象,第二类客户端一般也包含人类用户和Pod对象两种,它们的访问目标是Pod上运行于容器中的应用程序提供的各种具体的服务,不过这些访问请求通常要经由Service或Ingress资源对象进行,另外第二类客户端的访问目标对象的操作要经由第一类客户端创建和配置完成后才能进行 访问API Sercer时,人类用户一般借助于命令行工具kubectl或者图形工具进行,也可以通过编程接口进行访问,访问Pod中的应用时,其主要访问方式要取决于Pod中的应用程序

小结:

  • kubernetes集群主要由master和node两类节点组成
  • master节点组件包含有:kube-apiserver,controller-manager,scheduler和etcd几个组件,其中API Server是整个集群的网关
  • node节点组件包含有:kubelet,kube-proxy和容器引擎构成
  • 完整的k8s集群还需要部署有coredns,promethues,dashboard和Ingress等附件
  • kubernetes的网络中主要有四种类型的通信,POD内的容器间通信,各Pod间的通信,Pod与Service间的通信,及集群外部的流量同Service间的通信