0%

【Kubernetes】开篇

Kubernetes是一个开源的工业级自动化容器编排平台,广泛用于应用的部署、弹性扩充和管理。本文是「Kubernetes解读」系列开篇,主要介绍 Kubernetes 的整体概念。在以后的日子里,我会对 Kubernetes 涉及到的方方面面进行学习与解读。

Overview

发展历史

Kubernetes来源于希腊词汇κυβερνήτης,意思是helmsman,也即是舵手的意思,也可引申为pilot或者governor的含义。与此同时,kubernetes也是cybernetics的控制系统的意味。随着容器技术的广泛应用,特别是docker的流行,对于容器编排系统的需求导致了kubernetes的出现。docker具有集装箱的意思,而kubernetes就是管理运送集装箱的舵手。

2014年中,kubernetes首次被宣布,前期的主要开发人员来自于Google的 Borg)系统,它的发展与设计也深受Borg影响。与Borg采用C++设计不同,kubernetes一开始就采用Go语言实现。

Kubernetes v1.0 was released on July 21, 2015.[13] Along with the Kubernetes v1.0 release, Google partnered with the Linux Foundation to form the Cloud Native Computing Foundation (CNCF)[14] and offered Kubernetes as a seed technology. On March 6, 2018, Kubernetes Project reached ninth place in commits at GitHub, and second place in authors and issues to the Linux kernel.[15]

Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。

这是一艘载着一堆集装箱的轮船,轮船在大海上运着集装箱奔波,把集装箱送到它们该去的地方。我们之前其实介绍过一个概念叫做 container,container 这个英文单词也有另外的一个意思就是“集装箱”。Kubernetes 也就借着这个寓意,希望成为运送集装箱的一个轮船,来帮助我们管理这些集装箱,也就是管理这些容器。

从零开始入门 K8s:详解 K8s 核心概念

应用部署演进

  • 传统部署时代:直接在物理服务器上部署应用程序。无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。
    • 如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况,结果可能导致其他应用程序的性能下降。
    • 一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展,并且组织维护许多物理服务器的成本很高。
  • 虚拟化部署时代:引入虚拟化功能,允许在单个物理服务器的 CPU 上运行多个虚拟机(VM)。
    • 虚拟化功能允许应用程序在 VM 之间隔离,并提供安全级别,因为一个应用程序的信息不能被另一应用程序自由地访问。
    • 因为虚拟化可以轻松地添加或更新应用程序、降低硬件成本等等,所以虚拟化可以更好地利用物理服务器中的资源,并可以实现更好的可伸缩性。
    • 每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。
  • 容器化部署时代:容器是轻量级的虚拟化,相对于虚拟机,其具有更多的优势
    • 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
    • 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性),提供可靠且频繁的容器镜像构建和部署。
    • 关注开发与运维的分离:在构建/发布时而不是在部署时创建应用程序容器镜像,从而将应用程序与基础架构分离。
    • 可观察性:不仅可以显示操作系统级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
    • 跨开发、测试和生产的环境一致性:在便携式计算机上与在云中相同地运行。
    • 云和操作系统分发的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、Google Kubernetes Engine 和其他任何地方运行。
    • 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
    • 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分,并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
    • 资源隔离:可预测的应用程序性能。
    • 资源利用:高效率和高密度。

Container Evolution

沿着虚拟化的路径,容器流行后需要有容器编排管理的服务,于是诞生了kubernetes。

核心功能

  • 服务发现与负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果到容器的流量很大,Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排

    Kubernetes 允许自动挂载选择的存储系统,例如本地存储、公共云提供商等。

  • 自动二进制打包
    Kubernetes 允许您指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。

  • 自我修复
    Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。

  • 密钥与配置管理
    Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。您可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

Kubernetes Components

Kubernetes集群是由众多的Node组成,遵循主从架构,整个Kubernetes集群可以被划分为控制面和控制面管理的众多Node。

Kubernetes Components

Control Plane Components

Kubernetes 的控制面负责对集群作出全局决策(比如调度),以及检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的Pod)。控制面的组建可以在集群中的任意节点中运行,但是通常会在同一个节点上启动所有控制面的组建,并且这个节点不再运行用户容器,此即称作Master节点。控制面的每一个组件都既可以运行在单master节点,也可以运行在多master节点以实现高可用。

Master节点包含四个主要的组件:API Server、Controller Manager、Scheduler 以及 Etcd,如下图所示。

Control Plane

API Server

kube-apiserver 是 Kubernetes 最重要的核心组件之一,暴露了Kubernetes API,是控制面的前端组件,它主要提供以下的功能:

  • 提供集群管理的 REST API 接口,实现了认证、授权、准入控制等安全校验功能,同时也负责集群状态的存储操作(通过 etcd)。
  • 提供其他模块之间的数据交互和通信的枢纽(其他模块通过 API Server 查询或修改数据,只有 API Server 才直接操作 etcd)

Kube Api Server

在实际使用中,通常通过 kubectl 来访问 apiserver,也可以通过 Kubernetes 各个语言的 client 库来访问 apiserver。在使用 kubectl 时,打开调试日志也可以看到每个 API 调用的格式,比如

1
$ kubectl --v=8 get pods

可通过 kubectl api-versionskubectl api-resources 查询 Kubernetes API 支持的 API 版本以及资源对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ kubectl api-versions
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
apps/v1beta1
apps/v1beta2
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
metrics.k8s.io/v1beta1
networking.k8s.io/v1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

$ kubectl api-resources --api-group=storage.k8s.io
NAME SHORTNAMES APIGROUP NAMESPACED KIND
storageclasses sc storage.k8s.io false StorageClass
volumeattachments storage.k8s.io false VolumeAttachment

Etcd

Etcd是一个分布式的键值数据库,兼具一致性和高可用性,API Server 中所需要的这些原信息都被放置在 etcd 中。Etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。

Controller Manager

Controller Manager作为集群内部的管理控制中心,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。

controller manager

每个Controller通过API Server提供的接口实时监控整个集群的每个资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试将系统状态修复到“期望状态”。从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。

这些控制器包括:

  • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
  • 副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
  • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)。
  • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌.

我们刚刚提到的 API Server,它本身在部署结构上是一个可以水平扩展的一个部署组件;Controller 是一个可以进行热备的一个部署组件,它只有一个 active,它的调度器也是相应的,虽然只有一个 active,但是可以进行热备。

Scheduler

Scheduler是Master节点上的调度器组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。

Scheduler在整个系统中起”承上启下”作用:

  • 承上:负责接收Controller Manager创建的新的Pod,为其选择一个合适的Node
  • 启下:Node上的kubelet接管Pod的生命周期。

Scheduler的主要工作:

  • 通过调度算法为待调度Pod列表的每个Pod从Node列表中选择一个最适合的Node,并将信息写入etcd中

  • kubelet通过API Server监听到kubernetes Scheduler产生的Pod绑定信息,然后获取对应的Pod清单,下载Image,并启动容器。

    Scheduler

Scheduler的调度流程:

  • 预选调度过程,即遍历所有目标Node,筛选出符合要求的候选节点,kubernetes内置了多种预选策略(xxx Predicates)供用户选择
  • 确定最优节点,在第一步的基础上采用优选策略(xxx Priority)计算出每个候选节点的积分,取最高积分。

调度流程通过插件式加载的“调度算法提供者”(AlgorithmProvider)具体实现,一个调度算法提供者就是包括一组预选策略与一组优选策略的结构体。

Node Components

Kubernetes 的 Node 是真正运行业务负载的,每个业务负载会以 Pod 的形式运行。一个 Pod 中运行的一个或者多个容器,真正去运行这些 Pod 的组件的是叫做 kubelet,也就是 Node 上最为关键的组件,它通过 API Server 接收到所需要 Pod 运行的状态,然后提交到 Container Runtime 组件中。

在 OS 上去创建容器所需要运行的环境,最终把容器或者 Pod 运行起来,也需要对存储跟网络进行管理。Kubernetes 并不会直接进行网络存储的操作,他们会靠 Storage Plugin 或者是网络的 Plugin 来进行操作。用户自己或者云厂商都会去写相应的 Storage Plugin 或者 Network Plugin,去完成存储操作或网络操作。

从零开始入门 K8s:详解 K8s 核心概念

Kubelet

Kubelet是Node上的pod管家。在kubernetes集群中,每个Node节点都会启动kubelet进程,用来处理Master节点下发到本节点的任务,管理Pod和其中的容器。kubelet会在API Server上注册节点信息,定期向Master汇报节点资源使用情况,并通过cAdvisor监控容器和节点资源。

Kube-Proxy

kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes Service 概念的一部分。

kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。

如果操作系统提供了数据包过滤层并可用的话,kube-proxy会通过它来实现网络规则。否则,kube-proxy 仅转发流量本身。

Container Runtime

Container Runtime(容器运行时)是负责容器运行的软件。

Kubernetes支持几种容器运行时环境:Docker、Containerd、CRI-O等。

Addons

DNS

尽管并非严格要求其他附加组件,但所有示例都依赖集群 DNS,因此所有 Kubernetes 集群都应具有 DNS。

除了您环境中的其他 DNS 服务器之外,集群 DNS 还是一个 DNS 服务器,它为 Kubernetes 服务提供 DNS 记录。

Cluster DNS 是一个 DNS 服务器,和您部署环境中的其他 DNS 服务器一起工作,为 Kubernetes 服务提供DNS记录。

Kubernetes 启动的容器自动将 DNS 服务器包含在 DNS 搜索中。

Dashboard

Dashboard 是 Kubernetes 集群的通用基于 Web 的 UI。它使用户可以管理集群中运行的应用程序以及集群本身并进行故障排除。

Container Resource Monitoring

容器资源监控将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面。

Cluster-level Logging

集群层面日志 机制负责将容器的日志数据保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口。

Example

下面我们以一个例子再去看一下 Kubernetes 架构中的这些组件,是如何互相进行 interaction 的。

从零开始入门 K8s:详解 K8s 核心概念

用户可以通过 UI 或者 CLI 提交一个 Pod 给 Kubernetes 进行部署,这个 Pod 请求首先会通过 CLI 或者 UI 提交给 Kubernetes API Server,下一步 API Server 会把这个信息写入到它的存储系统 etcd,之后 Scheduler 会通过 API Server 的 watch 或者叫做 notification 机制得到这个信息:有一个 Pod 需要被调度。

这个时候 Scheduler 会根据它的内存状态进行一次调度决策,在完成这次调度之后,它会向 API Server report 说:“OK!这个 Pod 需要被调度到某一个节点上。”

这个时候 API Server 接收到这次操作之后,会把这次的结果再次写到 etcd 中,然后 API Server 会通知相应的节点进行这次 Pod 真正的执行启动。相应节点的 kubelet 会得到这个通知,kubelet 就会去调 Container runtime 来真正去启动配置这个容器和这个容器的运行环境,去调度 Storage Plugin 来去配置存储,network Plugin 去配置网络。

这个例子我们可以看到:这些组件之间是如何相互沟通相互通信,协调来完成一次 Pod 的调度执行操作的。

The Kubernetes API

Kubernetes API 允许你查询和操作 Kubernetes 集群中对象的状态。Kubernetes集群控制面的核心是 Api Server 以及他暴露的 HTTP API。用户,集群中的其他部分,还有外部组件都是通过API Server进行通信。

API 版本

为了使删除字段或者重构资源表示更加容易,Kubernetes 支持 多个API版本。每一个版本都在不同API路径下,例如 /api/v1 或者 /apis/extensions/v1beta1

我们选择在API级别进行版本化,而不是在资源或字段级别进行版本化,以确保API提供清晰,一致的系统资源和行为视图,并控制对已废止的API和/或实验性API的访问。 JSON和Protobuf序列化模式遵循架构更改的相同准则 - 下面的所有描述都同时适用于这两种格式。

请注意,API版本控制和软件版本控制只有间接相关性。 API和发行版本建议 描述了API版本与软件版本之间的关系。

不同的API版本名称意味着不同级别的软件稳定性和支持程度。 每个级别的标准在API变更文档中有更详细的描述。 内容主要概括如下:

  • Alpha 测试版本:
    • 版本名称包含了 alpha (例如:v1alpha1)。
    • 可能是有缺陷的。启用该功能可能会带来隐含的问题,默认情况是关闭的。
    • 支持的功能可能在没有通知的情况下随时删除。
    • API的更改可能会带来兼容性问题,但是在后续的软件发布中不会有任何通知。
    • 由于bugs风险的增加和缺乏长期的支持,推荐在短暂的集群测试中使用。
  • Beta 测试版本:
    • 版本名称包含了 beta (例如: v2beta3)。
    • 代码已经测试过。启用该功能被认为是安全的,功能默认已启用。
    • 所有已支持的功能不会被删除,细节可能会发生变化。
    • 对象的模式和/或语义可能会在后续的beta测试版或稳定版中以不兼容的方式进行更改。 发生这种情况时,我们将提供迁移到下一个版本的说明。 这可能需要删除、编辑和重新创建API对象。执行编辑操作时需要谨慎行事,这可能需要停用依赖该功能的应用程序。
    • 建议仅用于非业务关键型用途,因为后续版本中可能存在不兼容的更改。 如果您有多个可以独立升级的集群,则可以放宽此限制。
    • 请尝试我们的 beta 版本功能并且给出反馈!一旦他们退出 beta 测试版,我们可能不会做出更多的改变。
  • 稳定版本:
    • 版本名称是 vX,其中 X 是整数。

API 描述

下面我们介绍一下 Kubernetes 的 API 的基础知识。从 high-level 上看,Kubernetes API 是由 HTTP+JSON 组成的:用户访问的方式是 HTTP,访问的 API 中 content 的内容是 JSON 格式的。

Kubernetes 的 kubectl 也就是 command tool,Kubernetes UI,或者有时候用 curl,直接与 Kubernetes 进行沟通,都是使用 HTTP + JSON 这种形式。

下面有个例子:比如说,对于这个 Pod 类型的资源,它的 HTTP 访问的路径,就是 API,然后是 apiVesion: V1, 之后是相应的 Namespaces,以及 Pods 资源,最终是 Podname,也就是 Pod 的名字。

从零开始入门 K8s:详解 K8s 核心概念

如果我们去提交一个 Pod,或者 get 一个 Pod 的时候,它的 content 内容都是用 JSON 或者是 YAML 表达的。上图中有个 yaml 的例子,在这个 yaml file 中,对 Pod 资源的描述也分为几个部分。

第一个部分,一般来讲会是 API 的 version。比如在这个例子中是 V1,它也会描述我在操作哪个资源;比如说我的 kind 如果是 pod,在 Metadata 中,就写上这个 Pod 的名字;比如说 nginx,我们也会给它打一些 label,我们等下会讲到 label 的概念。在 Metadata 中,有时候也会去写 annotation,也就是对资源的额外的一些用户层次的描述。

Kubernetes Objects

Kubernetes对象是Kubernetes集群中持久化的实体,通过这些实体可以代表集群的状态。具体的,它们可以描述以下内容:

  • 哪些容器化应用在运行(以及在哪个 Node 上)
  • 可以被应用使用的资源
  • 关于应用运行时表现的策略,比如重启策略、升级策略,以及容错策略

Kubernetes 对象是 “目标性记录” —— 一旦创建对象,Kubernetes 系统将持续工作以确保对象存在。通过创建对象,本质上是在告知 Kubernetes 系统,所需要的集群工作负载看起来是什么样子的,这就是 Kubernetes 集群的 期望状态(Desired State)

操作 Kubernetes 对象 —— 无论是创建、修改,或者删除 —— 需要使用 Kubernetes API。比如,当使用 kubectl 命令行接口时,CLI 会执行必要的 Kubernetes API 调用,也可以在程序中使用 客户端库 直接调用 Kubernetes API。

Object Spec and Status

每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:对象 spec 和 对象 statusspec 是必需的,它描述了对象的 期望状态(Desired State) —— 希望对象所具有的特征。 status 描述了对象的 实际状态(Actual State) ,它是由 Kubernetes 系统提供和更新的。在任何时刻,Kubernetes 控制面一直努力地管理着对象的实际状态以与期望状态相匹配。

例如,Kubernetes Deployment 对象能够表示运行在集群中的应用。 当创建 Deployment 时,可能需要设置 Deployment 的规约,以指定该应用需要有 3 个副本在运行。 Kubernetes 系统读取 Deployment 规约,并启动我们所期望的该应用的 3 个实例 —— 更新状态以与规约相匹配。 如果那些实例中有失败的(一种状态变更),Kubernetes 系统通过修正来响应规约和状态之间的不一致 —— 这种情况,会启动一个新的实例来替换。

关于对象 spec、status 和 metadata 的更多信息,查看 Kubernetes API 约定

Describing a Kubernetes object

当创建 Kubernetes 对象时,必须提供对象的Spec,用来描述该对象的期望状态,以及关于对象的一些基本信息(例如名称)。 当使用 Kubernetes API 创建对象时(或者直接创建,或者基于kubectl),API 请求必须在请求体中包含 JSON 格式的信息。 大多数情况下,需要在 .yaml 文件中为 kubectl 提供这些信息kubectl 在发起 API 请求时,将这些信息转换成 JSON 格式。

这里有一个 .yaml 示例文件,展示了 Kubernetes Deployment 的必需字段和对象规约:

application/deployment.yaml 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

Required Fields

在想要创建的 Kubernetes 对象对应的 .yaml 文件中,需要配置如下的字段:

  • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
  • kind - 想要创建的对象的类型
  • metadata - 帮助识别对象唯一性的数据,包括一个 name 字符串、UID 和可选的 namespace
  • spec - 你对该对象期望的状态

对象 spec 的精确格式对每个 Kubernetes 对象来说是不同的,包含了特定于该对象的嵌套字段。Kubernetes API 参考能够帮助我们找到任何我们想创建的对象的 spec 格式。 例如,可以从 这里 查看 Podspec 格式, 并且可以从 这里 查看 Deploymentspec 格式。

关键概念

Pod

Pod 是 Kubernetes 应用程序的基本执行单元,是Kubernetes对象模型中创建的最小单元,Pod表示集群是运行的进程。

用户可以通过 Kubernetes 的 Pod API 生产一个 Pod,让 Kubernetes 对这个 Pod 进行调度,也就是把它放在某一个 Kubernetes 管理的节点上运行起来。一个 Pod 简单来说是对一组容器的抽象,它里面会包含一个或多个容器。

比如像下面的这幅图里面,它包含了两个容器,每个容器可以指定它所需要资源大小。比如说,一个核一个 G,或者说 0.5 个核,0.5 个 G。

当然在这个 Pod 中也可以包含一些其他所需要的资源:比如说我们所看到的 Volume 卷这个存储资源;比如说我们需要 100 个 GB 的存储或者 20GB 的另外一个存储。

从零开始入门 K8s:详解 K8s 核心概念

在 Pod 里面,我们也可以去定义容器所需要运行的方式。比如说运行容器的 Command,以及运行容器的环境变量等等。Pod 这个抽象也给这些容器提供了一个共享的运行环境,它们会共享同一个网络环境,这些容器可以用 localhost 来进行直接的连接。而 Pod 与 Pod 之间,是互相有 isolation 隔离的。

Volume

Volume 就是卷的概念,它是用来管理 Kubernetes 存储的,是用来声明在 Pod 中的容器可以访问文件目录的,一个卷可以被挂载在 Pod 中一个或者多个容器的指定路径下面。

而 Volume 本身是一个抽象的概念,一个 Volume 可以去支持多种的后端的存储。比如说 Kubernetes 的 Volume 就支持了很多存储插件,它可以支持本地的存储,可以支持分布式的存储,比如说像 ceph,GlusterFS ;它也可以支持云存储,比如说阿里云上的云盘、AWS 上的云盘、Google 上的云盘等等。

从零开始入门 K8s:详解 K8s 核心概念

Deployment

Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。一般大家用 Deployment 这个抽象来做应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。

Kubernetes 是通过 Controller,也就是我们刚才提到的控制器去维护 Deployment 中 Pod 的数目,它也会去帮助 Deployment 自动恢复失败的 Pod。

比如说我可以定义一个 Deployment,这个 Deployment 里面需要两个 Pod,当一个 Pod 失败的时候,控制器就会监测到,它重新把 Deployment 中的 Pod 数目从一个恢复到两个,通过再去新生成一个 Pod。通过控制器,我们也会帮助完成发布的策略。比如说进行滚动升级,进行重新生成的升级,或者进行版本的回滚。

从零开始入门 K8s:详解 K8s 核心概念

Service

Service 提供了一个或者多个 Pod 实例的稳定访问地址。

比如在上面的例子中,我们看到:一个 Deployment 可能有两个甚至更多个完全相同的 Pod。对于一个外部的用户来讲,访问哪个 Pod 其实都是一样的,所以它希望做一次负载均衡,在做负载均衡的同时,我只想访问某一个固定的 VIP,也就是 Virtual IP 地址,而不希望得知每一个具体的 Pod 的 IP 地址。

我们刚才提到,这个 pod 本身可能 terminal go(终止),如果一个 Pod 失败了,可能会换成另外一个新的。

对一个外部用户来讲,提供了多个具体的 Pod 地址,这个用户要不停地去更新 Pod 地址,当这个 Pod 再失败重启之后,我们希望有一个抽象,把所有 Pod 的访问能力抽象成一个第三方的一个 IP 地址,实现这个的 Kubernetes 的抽象就叫 Service。

实现 Service 有多种方式,Kubernetes 支持 Cluster IP,上面我们讲过的 kuber-proxy 的组网,它也支持 nodePort、 LoadBalancer 等其他的一些访问的能力。

从零开始入门 K8s:详解 K8s 核心概念

Namespace

Namespace 是用来做一个集群内部的逻辑隔离的,它包括鉴权、资源管理等。Kubernetes 的每个资源,比如刚才讲的 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源需要命名的唯一性,不同的 Namespace 中的资源可以重名。

Namespace 一个用例,比如像在阿里巴巴,我们内部会有很多个 business units,在每一个 business units 之间,希望有一个视图上的隔离,并且在鉴权上也不一样,在 cuda 上面也不一样,我们就会用 Namespace 来去给每一个 BU 提供一个他所看到的这么一个看到的隔离的机制。

从零开始入门 K8s:详解 K8s 核心概念

命令备忘

参考 https://juejin.im/post/5de3a7e06fb9a0719139ad93#heading-8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# kubectl
## 声明式资源管理
# kubectl apply

## 命令式资源管理
# kubectl create
# kubectl expose
# kubectl scale
# kubectl annotate
# kubectl label
# kubectl delete

## 资源查看

### kubectl get
# Usage:
kubectl get [(-o|--output=)](TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags] [options]
# Examples:
kubectl get services # 列出当前NS中所有service资源
kubectl get pods --all-namespaces # 列出集群所有NS中所有的Pod
kubectl get pods -o wide # -o wide也比较常用,可以显示更多资源信息,比如pod的IP等
kubectl get deployment my-dep # 可以直接指定资源名查看
kubectl get deployment my-dep --watch # --watch 参数可以监控资源的状态,在状态变换时输出。在跟踪服务部署情况时很有用
kubectl get pod my-pod -o yaml # 查看yaml格式的资源配置,这里包括资实际的status,可以用--export排除
kubectl get pod my-pod -l app=nginx # 查看所有带有标签app: nginx的pod
# kubectl describe

## 容器管理
# kubectl log

### kubectl exec
# Usage:
kubectl exec POD [-c CONTAINER] -- COMMAND [args...] [options]
# Examples:
kubectl exec my-pod ls # 对my-pod执行ls命令
kubectl exec -t -i nginx-78f5d695bd-czm8z bash # 进入pod的shell,并打开伪终端和标准输入

# kubectl cp

## 集群管理
# kubectl cluster-info
# kubectl version
# kubectl cordon/uncordon
# kubectl drain