每个运行的容器都是可重复的; 包含依赖环境在内的标准,意味着无论你在哪里运行它都会得到相同的行为。
容器将应用程序从底层的主机设施中解耦。 这使得在不同的云或 OS 环境中部署更加容易。
Kubernetes 集群中的每个节点都会运行容器, 这些容器构成分配给该节点的 Pod。 单个 Pod 中的容器会在共同调度下,于同一位置运行在相同的节点上。
Pod 能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的 Init 容器。
Init 容器与普通的容器非常像,除了如下两点:
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy
为 Never,它不会重新启动。
指定容器为 Init 容器,在 PodSpec 中添加 initContainers
字段,以 v1.Container 类型对象的 JSON 数组的形式,还有 app 的 containers
数组。 Init 容器的状态在 status.initContainerStatuses
字段中以容器状态数组的格式返回(类似 status.containerStatuses
字段)
与普通容器的不同之处
Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同,在下面 资源 处有说明。 而且 Init 容器不支持 Readiness Probe,因为它们必须在 Pod 就绪之前运行完成。
如果为一个 Pod 指定了多个 Init 容器,那些容器会按顺序一次运行一个。只有当前面的 Init 容器必须运行成功后,才可以运行下一个 Init 容器。当所有的 Init 容器运行完成后,Kubernetes 才初始化 Pod 和运行应用容器
Lint容器能做什么
因为 Init 容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:
FROM
另一个镜像,只需要在安装过程中使用类似 sed
、 awk
、 python
或 dig
这样的工具。默认情况下, Kubernetes 集群上的容器运行使用的计算资源没有限制。 使用 Kubernetes 资源配额, 管理员(也称为 集群操作者)可以在一个指定的命名空间内限制集群资源的使用与创建。 在命名空间中,一个 Pod 最多能够使用命名空间的资源配额所定义的 CPU 和内存用量。 作为集群操作者或命名空间级的管理员,你可能也会担心如何确保一个 Pod 不会垄断命名空间内所有可用的资源。
LimitRange 是限制命名空间内可为每个适用的对象类别 (例如 Pod 或 PersistentVolumeClaim) 指定的资源分配量(限制和请求)的策略对象。
一个 LimitRange(限制范围) 对象提供的限制能够做到:
当某命名空间中有一个 LimitRange 对象时,将在该命名空间中实施 LimitRange 限制。
LimitRange 的名称必须是合法的 DNS 子域名。
资源限制和请求的约束
LimitRange
对象。LimitRanger
准入控制器对所有没有设置计算资源需求的所有 Pod(及其容器)设置默认请求值与限制值。LimitRange
跟踪其使用量以保证没有超出命名空间中存在的任意 LimitRange
所定义的最小、最大资源使用量以及使用量比值。LimitRange
的约束, 向 API 服务器的请求会失败,并返回 HTTP 状态码 403 Forbidden
以及描述哪一项约束被违反的消息。LimitRange
启用了对 cpu
和 memory
等计算相关资源的限制, 你必须指定这些值的请求使用量与限制使用量。否则,系统将会拒绝创建 Pod。LimitRange
的验证仅在 Pod 准入阶段进行,不对正在运行的 Pod 进行验证。 如果你添加或修改 LimitRange,命名空间中已存在的 Pod 将继续不变。LimitRange
对象,应用哪个默认值是不确定的。当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量。
资源配额是帮助管理员解决这一问题的工具。
资源配额,通过 ResourceQuota
对象来定义,对每个命名空间的资源消耗总量提供限制。 它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命名空间中的 Pod 可以使用的计算资源的总上限。
资源配额的工作方式如下:
cpu
和 memory
)的配额被启用, 则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。 提示: 可使用 LimitRanger
准入控制器来为没有设置计算资源需求的 Pod 设置默认值。Kubernetes Manifest 是一种 YAML 文件,用于定义 Kubernetes 资源对象的配置。这些资源对象可以包括 Pod、Service、Deployment、ReplicaSet 等。Manifest 文件描述了资源对象的属性,如名称、标签、容器镜像、端口等信息。通过 Manifest 文件,用户可以轻松地部署和管理 Kubernetes 集群中的应用程序。
当你在一个有严格网络边界的环境里运行 Kubernetes,例如拥有物理网络防火墙或者拥有公有云中虚拟网络的自有数据中心, 了解 Kubernetes 组件使用了哪些端口和协议是非常有用的。
控制面
协议 | 方向 | 端口范围 | 目的 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 6443 | Kubernetes API server | 所有 |
TCP | 入站 | 2379-2380 | etcd server client API | kube-apiserver, etcd |
TCP | 入站 | 10250 | Kubelet API | 自身, 控制面 |
TCP | 入站 | 10259 | kube-scheduler | 自身 |
TCP | 入站 | 10257 | kube-controller-manager | 自身 |
尽管 etcd 的端口也列举在控制面的部分,但你也可以在外部自己托管 etcd 集群或者自定义端口
工作节点
协议 | 方向 | 端口范围 | 目的 | 使用者 |
---|---|---|---|---|
TCP | 入站 | 10250 | Kubelet API | 自身, 控制面 |
TCP | 入站 | 30000-32767 | NodePort Services† | 所有 |
Kubernetes 管理的是集群,Kubernetes 中的网络要解决的核心问题就是每台主机的 IP 地址网段划分,以及单个容器的 IP 地址分配。概括为:
为了解决该问题,出现了一系列开源的 Kubernetes 中的网络插件与方案,如:
CNI给pod分配ip,给namespace添加网卡
CNI对行为有要求,对具体实现不关心
原生K8s CNI 与第三方
https://github.com/containernetworking/cni
Flannel 是作为一个二进制文件的方式部署在每个 node 上,主要实现两个功能:
扁平网络
https://github.com/flannel-io/flannel
Calico 创建和管理一个扁平的三层网络(不需要 overlay),每个容器会分配一个可路由的 IP。由于通信时不需要解包和封包,网络性能损耗小,易于排查,且易于水平扩展。
小规模部署时可以通过 BGP client 直接互联,大规模下可通过指定的 BGP Route Reflector 来完成,这样保证所有的数据流量都是通过 IP 路由的方式完成互联的。
Calico 基于 iptables 还提供了丰富而灵活的网络 Policy,保证通过各个节点上的 ACL 来提供 Workload 的多租户隔离、安全组以及其他可达性限制等功能。
可以使用 kubectl 直接管理 Calico
Felix
Felix 以 agent 代理的形式在每台机器端点上运行。对路由和 ACL 以及主机编程,为该主机上的端点提供所需的连接。
根据具体的编排器环境,Felix 负责:
接口管理
将有关接口的信息编入内核,以便内核能够正确处理来自该端点的流量。特别是,确保主机响应来自每个工作负载的 ARP 请求,提供主机的 MAC,并为它所管理的接口启用 IP 转发。它还监控接口,以确保编程在适当的时候应用。
路由编程
将其主机上的端点的路由编程到 Linux 内核的 FIB(转发信息库)。这可以确保到达主机上的以这些端点为目的地的数据包被相应地转发。
ACL 编程
在 Linux 内核中编程 ACL,以确保只有有效的流量可以在端点之间发送,并且端点不能规避 Calico 的安全措施。
状态报告
提供网络健康数据。特别是在配置其主机时报告错误和问题。这些数据被写入数据存储,以便对网络的其他组件和运营商可见。
BIRD
BGP Internet Routing Daemon,简称 BIRD。从 Felix 获取路由,并分发到网络上的 BGP peer,用于主机间的路由。在每个 Felix 代理的节点上运行。
BGP 客户端负责:
路由分配
当 Felix 将路由插入 Linux 内核的 FIB 时,BGP 客户端将它们分配给部署中的其他节点。这确保了部署中的有效流量路由。
BGP 路由反射器的配置
BGP 路由反射器通常是为大型部署而配置的,而不是一个标准的 BGP 客户端。BGP 路由反射器作为连接 BGP 客户端的一个中心点。(标准 BGP 要求每个 BGP 客户端在网状拓扑结构中与其他每个 BGP 客户端连接,这很难维护)。
为了实现冗余,你可以无缝部署多个 BGP 路由反射器。BGP 路由反射器只参与网络的控制:没有终端数据通过它们。当 Calico BGP 客户端将其 FIB 中的路由通告给路由反射器时,路由反射器将这些路由通告给部署中的其他节点。
IPIP onlink
Cilium 是一款开源软件,也是 CNCF 的孵化项目,目前已有公司提供商业化支持,还有基于 Cilium 实现的服务网格解决方案。最初它仅是作为一个 Kubernetes 网络组件。Cilium 在 1.7 版本后推出并开源了 Hubble,它是专门为网络可视化设计,能够利用 Cilium 提供的 eBPF 数据路径,获得对 Kubernetes 应用和服务的网络流量的深度可见性。这些网络流量信息可以对接 Hubble CLI、UI 工具,可以通过交互式的方式快速进行问题诊断。除了 Hubble 自身的监控工具,还可以对接主流的云原生监控体系 ——Prometheus 和 Grafana,实现可扩展的监控策略
Cilium 为基于 Kubernetes 的 Linux 容器管理平台上部署的服务,透明地提供服务间的网络和 API 连接及安全。
Cilium 底层是基于 Linux 内核的新技术 eBPF,可以在 Linux 系统中动态注入强大的安全性、可见性和网络控制逻辑。 Cilium 基于 eBPF 提供了多集群路由、替代 kube-proxy 实现负载均衡、透明加密以及网络和服务安全等诸多功能。除了提供传统的网络安全之外,eBPF 的灵活性还支持应用协议和 DNS 请求 / 响应安全。同时,Cilium 与 Envoy 紧密集成,提供了基于 Go 的扩展框架。因为 eBPF 运行在 Linux 内核中,所以应用所有 Cilium 功能,无需对应用程序代码或容器配置进行任何更改。
基于微服务的应用程序分为小型独立服务,这些服务使用 HTTP、gRPC、Kafka 等轻量级协议通过 API 相互通信。但是,现有的 Linux 网络安全机制(例如 iptables)仅在网络和传输层(即 IP 地址和端口)上运行,并且缺乏对微服务层的可见性。
Hubble 是一个完全分布式的网络和安全可观察性平台。它建立在 Cilium 和 eBPF 之上,以完全透明的方式实现对服务的通信和行为以及网络基础设施的深度可见性(visibility)。
通过建立在 Cilium 之上,Hubble 可以利用 eBPF 实现可见性。依靠 eBPF,所有的可见性都是可编程的,并允许采用一种动态方法,最大限度地减少开销,同时按照用户的要求提供深入和详细的可见性。Hubble 的创建和专门设计是为了最好地利用 eBPF 的能力
特性
基于身份的安全性
Cilium 可见性和安全策略基于容器编排系统的标识(例如,Kubernetes 中的 Label)。在编写安全策略、审计和故障排查时,再也不用担心网络子网或容器 IP 地址了。
卓越的性能
eBPF 利用 Linux 底层的强大能力,通过提供 Linux 内核的沙盒可编程性来实现数据路径,从而提供卓越的性能。
API 协议可见性 + 安全性
传统防火墙仅根据 IP 地址和端口等网络标头查看和过滤数据包。Cilium 也可以这样做,但也可以理解并过滤单个 HTTP、gRPC 和 Kafka 请求,这些请求将微服务拼接在一起。
专为扩展而设计
Cilium 是为扩展而设计的,在部署新 pod 时不需要节点间交互,并且通过高度可扩展的键值存储进行所有协调。
Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。 问题之一是当容器崩溃时文件丢失。 kubelet 会重新启动容器,但容器会以干净的状态重启。 第二个问题会在同一 Pod
中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题
Docker 也有卷(Volume) 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录。 Docker 提供卷驱动程序,但是其功能非常有限。
Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁持久卷。 对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。
卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。
使用卷时, 在 .spec.volumes
字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts
字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的容器镜像 的初始内容以及挂载在容器中的卷(如果定义了的话)所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作,如果被允许的话,都会影响接下来容器中进程访问文件系统时所看到的内容。
卷挂载在镜像中的指定路径下。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。
卷不能挂载到其他卷之上(不过存在一种使用 subPath 的相关机制),也不能与其他卷有硬链接。
卷类型
cephfs
cephfs
卷允许你将现存的 CephFS 卷挂载到 Pod 中。 不像 emptyDir
那样会在 Pod 被删除的同时也会被删除,cephfs
卷的内容在 Pod 被删除时会被保留,只是卷被卸载了。 这意味着 cephfs
卷可以被预先填充数据,且这些数据可以在 Pod 之间共享。同一 cephfs
卷可同时被多个写者挂载。
configMap
configMap
卷提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap
类型的卷引用,然后被 Pod 中运行的容器化应用使用。
引用 configMap 对象时,你可以在卷中通过它的名称来引用。 你可以自定义 ConfigMap 中特定条目所要使用的路径。 下面的配置显示了如何将名为 log-config
的 ConfigMap 挂载到名为 configmap-pod
的 Pod 中
log-config
ConfigMap 以卷的形式挂载,并且存储在 log_level
条目中的所有内容都被挂载到 Pod 的 /etc/config/log_level
路径下。 请注意,这个路径来源于卷的 mountPath
和 log_level
键对应的 path
。
downwardAPI
downwardAPI
卷用于为应用提供 downward API 数据。 在这类卷中,所公开的数据以纯文本格式的只读文件形式存在。
emptyDir
当 Pod 分派到某个节点上时,emptyDir
卷会被创建,并且在 Pod 在该节点上运行期间,卷一直存在。 就像其名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir
卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir
卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir
卷中的数据也会被永久删除。
emptyDir
的一些用途:
emptyDir.medium
字段用来控制 emptyDir
卷的存储位置。 默认情况下,emptyDir
卷存储在该节点所使用的介质上; 此处的介质可以是磁盘、SSD 或网络存储,这取决于你的环境。 你可以将 emptyDir.medium
字段设置为 "Memory"
, 以告诉 Kubernetes 为你挂载 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同:tmpfs 在节点重启时会被清除, 并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
你可以通过为默认介质指定大小限制,来限制 emptyDir
卷的存储容量。 此存储是从节点临时存储中分配的。 如果来自其他来源(如日志文件或镜像分层数据)的数据占满了存储,emptyDir
可能会在达到此限制之前发生存储容量不足的问题。
fc(光纤通道)
fc
卷类型允许将现有的光纤通道块存储卷挂载到 Pod 中。 可以使用卷配置中的参数 targetWWNs
来指定单个或多个目标 WWN(World Wide Names)。 如果指定了多个 WWN,targetWWNs 期望这些 WWN 来自多路径连接。
存储的管理是一个与计算实例的管理完全不同的问题。 PersistentVolume 子系统为用户和管理员提供了一组 API, 将存储如何制备的细节从其如何被使用中抽象出来。 为了实现这点,我们引入了两个新的 API 资源:PersistentVolume 和 PersistentVolumeClaim。
持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。
持久卷申领(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载,参见访问模式)。
尽管 PersistentVolumeClaim 允许用户消耗抽象的存储资源, 常见的情况是针对不同的问题用户需要的是具有不同属性(如,性能)的 PersistentVolume 卷。 集群管理员需要能够提供不同性质的 PersistentVolume, 并且这些 PV 卷之间的差别不仅限于卷大小和访问模式,同时又不能将卷是如何实现的这些细节暴露给用户。 为了满足这类需求,就有了存储类(StorageClass) 资源。
StorageClass
为管理员提供了一种描述他们提供的存储的 “类” 的方法。 不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes
本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为 “配置文件”
pv 和 pvc 遵循以下生命周期:
1、 供应准备。通过集群外的存储系统或者云平台来提供存储持久化支持。
2、绑定。用户创建 pvc 并指定需要的资源和访问模式。在找到可用 pv 之前,pvc 会保持未绑定状态。
3、使用。用户可在 pod 中像 volume 一样使用 pvc。
4、释放。用户删除 pvc 来回收存储资源,pv 将变成 “released” 状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他 pvc 使用。
5、回收 (Reclaiming)。pv 可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。
目前只有 NFS 和 HostPath 类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk
和 Cinder
支持删除 (Delete)
策略
有些应用程序需要额外的存储,但并不关心数据在重启后是否仍然可用。 例如,缓存服务经常受限于内存大小,而且可以将不常用的数据转移到比内存慢的存储中,对总体性能的影响并不大。
另有些应用程序需要以文件形式注入的只读数据,比如配置数据或密钥。
临时卷 就是为此类用例设计的。因为卷会遵从 Pod 的生命周期,与 Pod 一起创建和删除, 所以停止和重新启动 Pod 时,不会受持久卷在何处可用的限制。
临时卷在 Pod 规约中以 内联 方式定义,这简化了应用程序的部署和管理。
Kubernetes 为了不同的用途,支持几种不同类型的临时卷:
emptyDir
、configMap
、downwardAPI
、secret
是作为 本地临时存储 提供的。它们由各个节点上的 kubelet 管理。
CSI 临时卷 必须 由第三方 CSI 存储驱动程序提供。
通用临时卷 可以 由第三方 CSI 存储驱动程序提供,也可以由支持动态制备的任何其他存储驱动程序提供。 一些专门为 CSI 临时卷编写的 CSI 驱动程序,不支持动态制备:因此这些驱动程序不能用于通用临时卷。
使用第三方驱动程序的优势在于,它们可以提供 Kubernetes 本身不支持的功能, 例如,与 kubelet 管理的磁盘具有不同性能特征的存储,或者用来注入不同的数据。
与 PersistentVolume
和 PersistentVolumeClaim
这两个 API 资源用于给用户和管理员制备卷类似, VolumeSnapshotContent
和 VolumeSnapshot
这两个 API 资源用于给用户和管理员创建卷快照。
VolumeSnapshotContent
是从一个卷获取的一种快照,该卷由管理员在集群中进行制备。 就像持久卷(PersistentVolume)是集群的资源一样,它也是集群中的资源。
VolumeSnapshot
是用户对于卷的快照的请求。它类似于持久卷声明(PersistentVolumeClaim)。
VolumeSnapshotClass
允许指定属于 VolumeSnapshot
的不同属性。在从存储系统的相同卷上获取的快照之间, 这些属性可能有所不同,因此不能通过使用与 PersistentVolumeClaim
相同的 StorageClass
来表示。
卷快照能力为 Kubernetes 用户提供了一种标准的方式来在指定时间点复制卷的内容,并且不需要创建全新的卷。 例如,这一功能使得数据库管理员能够在执行编辑或删除之类的修改之前对数据库执行备份。
当使用该功能时,用户需要注意以下几点:
VolumeSnapshot
,VolumeSnapshotContent
和 VolumeSnapshotClass
是 CRD, 不属于核心 API。VolumeSnapshot
支持仅可用于 CSI 驱动。VolumeSnapshot
部署过程的一部分,Kubernetes 团队提供了一个部署于控制平面的快照控制器, 并且提供了一个叫做 csi-snapshotter
的边车(Sidecar)辅助容器,和 CSI 驱动程序一起部署。 快照控制器监视 VolumeSnapshot
和 VolumeSnapshotContent
对象, 并且负责创建和删除 VolumeSnapshotContent
对象。 边车 csi-snapshotter 监视 VolumeSnapshotContent
对象, 并且触发针对 CSI 端点的 CreateSnapshot
和 DeleteSnapshot
的操作。k8s定义给存储的标准,container storage interface