pull/402/head
Jimmy song 2020-06-08 20:32:34 +08:00
parent b3af7d2b04
commit b0c129cda2
14 changed files with 365 additions and 508 deletions

View File

@ -1,8 +1,8 @@
## Aggregated API Server # Aggregated API Server
Aggregated聚合的API server是为了将原来的API server这个巨石monolithic应用给拆分成为了方便用户开发自己的API server集成进来而不用直接修改kubernetes官方仓库的代码这样一来也能将API server解耦方便用户使用实验特性。这些API server可以跟core API server无缝衔接使用kubectl也可以管理它们。 Aggregated聚合的API server是为了将原来的API server这个巨石monolithic应用给拆分成为了方便用户开发自己的API server集成进来而不用直接修改kubernetes官方仓库的代码这样一来也能将API server解耦方便用户使用实验特性。这些API server可以跟core API server无缝衔接使用kubectl也可以管理它们。
### 架构 ## 架构
我们需要创建一个新的组件,名为`kube-aggregator`,它需要负责以下几件事: 我们需要创建一个新的组件,名为`kube-aggregator`,它需要负责以下几件事:
@ -14,7 +14,7 @@ Aggregated聚合的API server是为了将原来的API server这个巨石
关于聚合的API server的更多信息请参考[Aggregated API Server](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/aggregated-api-servers.md) 关于聚合的API server的更多信息请参考[Aggregated API Server](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/aggregated-api-servers.md)
### 安装配置聚合的API server ## 安装配置聚合的API server
有两种方式来启用`kube-aggregator` 有两种方式来启用`kube-aggregator`

View File

@ -1,33 +1,28 @@
# Annotation # Annotation
Annotation顾名思义就是注解。Annotation可以将Kubernetes资源对象关联到任意的非标识性元数据。使用客户端如工具和库可以检索到这些元数据。 Annotation顾名思义就是注解。Annotation 可以将 Kubernetes 资源对象关联到任意的非标识性元数据。使用客户端(如工具和库)可以检索到这些元数据。
## 关联元数据到对象 ## 关联元数据到对象
Label和Annotation都可以将元数据关联到Kubernetes资源对象。Label主要用于选择对象可以挑选出满足特定条件的对象。相比之下annotation 不能用于标识及选择对象。annotation中的元数据可多可少可以是结构化的或非结构化的也可以包含label中不允许出现的字符。 Label Annotation 都可以将元数据关联到 Kubernetes 资源对象。Label 主要用于选择对象可以挑选出满足特定条件的对象。相比之下annotation 不能用于标识及选择对象。annotation 中的元数据可多可少,可以是结构化的或非结构化的,也可以包含 label 中不允许出现的字符。
annotation和label一样都是key/value键值对映射结构: Annotation 和 label 一样都是 key/value 键值对映射结构:
```json ```json"annotations": {"key1":"value1","key2":"value2"}```
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
```
以下列出了一些可以记录在 annotation 中的对象信息: 以下列出了一些可以记录在 annotation 中的对象信息:
- 声明配置层管理的字段。使用annotation关联这类字段可以用于区分以下几种配置来源客户端或服务器设置的默认值自动生成的字段或自动生成的 auto-scaling 和 auto-sizing 系统配置的字段。 - 声明配置层管理的字段。使用 annotation 关联这类字段可以用于区分以下几种配置来源:客户端或服务器设置的默认值,自动生成的字段或自动生成的 auto-scaling 和 auto-sizing 系统配置的字段。
- 创建信息、版本信息或镜像信息。例如时间戳、版本号、git分支、PR序号、镜像哈希值以及仓库地址。 - 创建信息、版本信息或镜像信息。例如时间戳、版本号、git 分支、PR 序号、镜像哈希值以及仓库地址。
- 记录日志、监控、分析或审计存储仓库的指针 - 记录日志、监控、分析或审计存储仓库的指针
- 可以用于debug的客户端库或工具信息例如名称、版本和创建信息。 - 可以用于 debug 的客户端(库或工具)信息,例如名称、版本和创建信息。
- 用户信息以及工具或系统来源信息、例如来自非Kubernetes生态的相关对象的URL信息。 - 用户信息,以及工具或系统来源信息、例如来自非 Kubernetes 生态的相关对象的 URL 信息。
- 轻量级部署工具元数据,例如配置或检查点。 - 轻量级部署工具元数据,例如配置或检查点。
- 负责人的电话或联系方式,或能找到相关信息的目录条目信息,例如团队网站。 - 负责人的电话或联系方式,或能找到相关信息的目录条目信息,例如团队网站。
如果不使用annotation您也可以将以上类型的信息存放在外部数据库或目录中但这样做不利于创建用于部署、管理、内部检查的共享工具和客户端库。 如果不使用 annotation您也可以将以上类型的信息存放在外部数据库或目录中但这样做不利于创建用于部署、管理、内部检查的共享工具和客户端库。
## 示例 ## 示例
@ -75,4 +70,4 @@ spec:
fieldPath: metadata.namespace fieldPath: metadata.namespace
``` ```
`alpha.istio.io/sidecar` 注解就是用来控制是否自动向 pod 中注入 sidecar 的。 `alpha.istio.io/sidecar` 注解就是用来控制是否自动向 pod 中注入 sidecar 的。

View File

@ -1,8 +1,8 @@
# APIService # APIService
APIService是用来表示一个特定的`GroupVersion`的中的server它的结构定义位于代码`staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go`中。 APIService 是用来表示一个特定的 `GroupVersion` 的中的 server它的结构定义位于代码 `staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/types.go` 中。
下面是一个APIService的示例配置 下面是一个 APIService 的示例配置:
```yaml ```yaml
apiVersion: apiregistration.k8s.io/v1beta1 apiVersion: apiregistration.k8s.io/v1beta1
@ -20,24 +20,22 @@ spec:
version: v1alpha1 version: v1alpha1
``` ```
## APIService详解 ## APIService 详解
使用`apiregistration.k8s.io/v1beta1` 版本的APIService在metadata.name中定义该API的名字。 使用 `apiregistration.k8s.io/v1beta1` 版本的 APIService metadata.name 中定义该 API 的名字。
使用上面的yaml的创建`v1alpha1.custom-metrics.metrics.k8s.io` APIService。 使用上面的 yaml 的创建 `v1alpha1.custom-metrics.metrics.k8s.io` APIService。
- `insecureSkipTLSVerify `当与该服务通信时禁用TLS证书认证。强加建议不要设置这个参数默认为 false。应该使用CABundle代替。 - `insecureSkipTLSVerify`:当与该服务通信时,禁用 TLS 证书认证。强加建议不要设置这个参数,默认为 false。应该使用 CABundle 代替。
- `service`与该APIService通信时引用的service其中要注明service的名字和所属的namespace如果为空的话则所有的服务都会该API groupversion将在本地443端口处理所有通信。 - `service`:与该 APIService 通信时引用的 service其中要注明 service 的名字和所属的 namespace如果为空的话则所有的服务都会该 API groupversion 将在本地 443 端口处理所有通信。
- `groupPriorityMinimum`该组API的处理优先级主要排序是基于`groupPriorityMinimum`该数字越大表明优先级越高客户端就会与其通信处理请求。次要排序是基于字母表顺序例如v1.bar比v1.foo的优先级更高。 - `groupPriorityMinimum`:该组 API 的处理优先级,主要排序是基于 `groupPriorityMinimum`,该数字越大表明优先级越高,客户端就会与其通信处理请求。次要排序是基于字母表顺序,例如 v1.bar v1.foo 的优先级更高。
- `versionPriority`VersionPriority控制其组内的API版本的顺序。必须大于零。主要排序基于VersionPriority从最高到最低20大于10排序。次要排序是基于对象名称的字母比较。 v1.foo在v1.bar之前由于它们都是在一个组内因此数字可能很小一般都小于10。 - `versionPriority`VersionPriority 控制其组内的 API 版本的顺序。必须大于零。主要排序基于 VersionPriority从最高到最低20 大于 10排序。次要排序是基于对象名称的字母比较。 v1.foo v1.bar 之前)由于它们都是在一个组内,因此数字可能很小,一般都小于 10。
查看我们使用上面的yaml文件创建的APIService。 查看我们使用上面的 yaml 文件创建的 APIService。
```bash ```bash
kubectl get apiservice v1alpha1.custom-metrics.metrics.k8s.io -o yaml kubectl get apiservice v1alpha1.custom-metrics.metrics.k8s.io -o yaml
``` ``````yaml
```yaml
apiVersion: apiregistration.k8s.io/v1beta1 apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService kind: APIService
metadata: metadata:
@ -65,11 +63,11 @@ status:
type: Available type: Available
``` ```
## 查看集群支持的APISerivce ## 查看集群支持的 APISerivce
作为Kubernetes中的一种资源对象可以使用`kubectl get apiservice`来查看。 作为 Kubernetes 中的一种资源对象,可以使用 `kubectl get apiservice` 来查看。
例如查看集群中所有的APIService 例如查看集群中所有的 APIService
```bash ```bash
$ kubectl get apiservice $ kubectl get apiservice
@ -98,7 +96,7 @@ v1beta2.apps 2d
v2beta1.autoscaling 2d v2beta1.autoscaling 2d
``` ```
另外查看当前kubernetes集群支持的API版本还可以使用`kubectl api-versions` 另外查看当前 kubernetes 集群支持的 API 版本还可以使用`kubectl api-versions`
```bash ```bash
$ kubectl api-versions $ kubectl api-versions

View File

@ -1,3 +1,3 @@
# 身份与权限认证 # 身份与权限认证
Kubernetes中提供了良好的多租户认证管理机制如RBAC、ServiceAccount还有各种Policy等。 Kubernetes 中提供了良好的多租户认证管理机制,如 RBAC、ServiceAccount 还有各种 Policy 等。

View File

@ -1,106 +1,106 @@
# 具备API感知的网络和安全性管理的开源软件Cilium # 具备 API 感知的网络和安全性管理的开源软件 Cilium
Cilium是一个纯开源软件没有哪家公司提供商业化支持也不是由某一公司开源该软件用于透明地保护使用Linux容器管理平台如Docker和Kubernetes部署的应用程序服务之间的网络连接。 Cilium 是一个纯开源软件,没有哪家公司提供商业化支持,也不是由某一公司开源,该软件用于透明地保护使用 Linux 容器管理平台(如 Docker Kubernetes部署的应用程序服务之间的网络连接。
Cilium的基础是一种名为BPF的新Linux内核技术它可以在Linux本身动态插入强大的安全可见性和控制逻辑。由于BPF在Linux内核中运行因此可以应用和更新Cilium安全策略而无需对应用程序代码或容器配置进行任何更改。 Cilium 的基础是一种名为 BPF 的新 Linux 内核技术,它可以在 Linux 本身动态插入强大的安全可见性和控制逻辑。由于 BPF Linux 内核中运行,因此可以应用和更新 Cilium 安全策略,而无需对应用程序代码或容器配置进行任何更改。
![Cilium](../images/006tNbRwly1fwqi98i51ij30sc0j80zn.jpg) ![Cilium](../images/006tNbRwly1fwqi98i51ij30sc0j80zn.jpg)
基于微服务的应用程序分为小型独立服务,这些服务使用**HTTP**、**gRPC**、**Kafka**等轻量级协议通过API相互通信。但是现有的Linux网络安全机制例如iptables仅在网络和传输层即IP地址和端口上运行并且缺乏对微服务层的可见性。 基于微服务的应用程序分为小型独立服务,这些服务使用 **HTTP**、**gRPC**、**Kafka** 等轻量级协议通过 API 相互通信。但是,现有的 Linux 网络安全机制(例如 iptables仅在网络和传输层 IP 地址和端口)上运行,并且缺乏对微服务层的可见性。
Cilium为Linux容器框架如[**Docker**](https://www.docker.com/)和[**Kubernetes**](https://kubernetes.io/)带来了API感知网络安全过滤。使用名为**BPF**的新Linux内核技术Cilium提供了一种基于容器/容器标识定义和实施网络层和应用层安全策略的简单而有效的方法。 Cilium Linux 容器框架(如 [**Docker**](https://www.docker.com/) [**Kubernetes**](https://kubernetes.io/) 带来了 API 感知网络安全过滤。使用名为 **BPF** 的新 Linux 内核技术Cilium 提供了一种基于容器 / 容器标识定义和实施网络层和应用层安全策略的简单而有效的方法。
**注**Cilium中文意思是“纤毛“它十分细小而又无处不在。 **注**Cilium 中文意思是 “纤毛 “,它十分细小而又无处不在。
## BPF ## BPF
**柏克莱封包过滤器**Berkeley Packet Filter缩写 BPF是[类Unix](https://zh.wikipedia.org/wiki/%E7%B1%BBUnix)系统上[数据链路层](https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82)的一种原始接口,提供原始链路层[封包](https://zh.wikipedia.org/wiki/%E5%B0%81%E5%8C%85)的收发,除此之外,如果网卡驱动支持[洪泛](https://zh.wikipedia.org/wiki/%E6%B4%AA%E6%B3%9B)模式,那么它可以让网卡处于此种模式,这样可以收到[网络](https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C)上的所有包,不管他们的目的地是不是所在[主机](https://zh.wikipedia.org/wiki/%E4%B8%BB%E6%A9%9F)。参考[维基百科](https://zh.wikipedia.org/wiki/BPF)和[eBPF简史](https://www.ibm.com/developerworks/cn/linux/l-lo-eBPF-history/index.html)。 **柏克莱封包过滤器**Berkeley Packet Filter缩写 BPF [ Unix](https://zh.wikipedia.org/wiki/% E7% B1% BBUnix) 系统上 [数据链路层](https://zh.wikipedia.org/wiki/% E6%95% B0% E6%8D% AE% E9%93% BE% E8% B7% AF% E5% B1%82) 的一种原始接口,提供原始链路层 [封包](https://zh.wikipedia.org/wiki/% E5% B0%81% E5%8C%85) 的收发,除此之外,如果网卡驱动支持 [洪泛](https://zh.wikipedia.org/wiki/% E6% B4% AA% E6% B3%9B) 模式,那么它可以让网卡处于此种模式,这样可以收到 [网络](https://zh.wikipedia.org/wiki/% E7% BD%91% E7% BB%9C) 上的所有包,不管他们的目的地是不是所在 [主机](https://zh.wikipedia.org/wiki/% E4% B8% BB% E6% A9%9F)。参考 [维基百科](https://zh.wikipedia.org/wiki/BPF) [eBPF 简史](https://www.ibm.com/developerworks/cn/linux/l-lo-eBPF-history/index.html)。
## 特性 ## 特性
以下是Cilium的特性。 以下是 Cilium 的特性。
**基于身份的安全性** **基于身份的安全性**
Cilium可见性和安全策略基于容器编排系统的标识例如Kubernetes中的Label。在编写安全策略、审计和故障排查时再也不用担心网络子网或容器IP地址了。 Cilium 可见性和安全策略基于容器编排系统的标识例如Kubernetes 中的 Label。在编写安全策略、审计和故障排查时再也不用担心网络子网或容器 IP 地址了。
**卓越的性能** **卓越的性能**
BPF利用Linux底层的强大能力通过提供Linux内核的沙盒可编程性来实现数据路径从而提供卓越的性能。 BPF 利用 Linux 底层的强大能力,通过提供 Linux 内核的沙盒可编程性来实现数据路径,从而提供卓越的性能。
**API协议可见性+安全性** **API 协议可见性 + 安全性 **
传统防火墙仅根据IP地址和端口等网络标头查看和过滤数据包。Cilium也可以这样做但也可以理解并过滤单个HTTP、gRPC和Kafka请求这些请求将微服务拼接在一起。 传统防火墙仅根据 IP 地址和端口等网络标头查看和过滤数据包。Cilium 也可以这样做,但也可以理解并过滤单个 HTTP、gRPC Kafka 请求,这些请求将微服务拼接在一起。
**专为扩展而设计** **专为扩展而设计**
Cilium是为扩展而设计的在部署新pod时不需要节点间交互并且通过高度可扩展的键值存储进行所有协调。 Cilium 是为扩展而设计的,在部署新 pod 时不需要节点间交互,并且通过高度可扩展的键值存储进行所有协调。
## 为什么选择Cilium ## 为什么选择 Cilium
现代数据中心应用程序的开发已经转向面向服务的体系结构SOA通常称为*微服务*其中大型应用程序被分成小型独立服务这些服务使用HTTP等轻量级协议通过API相互通信。微服务应用程序往往是高度动态的作为持续交付的一部分部署的滚动更新期间单个容器启动或销毁应用程序扩展/缩小以适应负载变化。 现代数据中心应用程序的开发已经转向面向服务的体系结构SOA通常称为 * 微服务 *,其中大型应用程序被分成小型独立服务,这些服务使用 HTTP 等轻量级协议通过 API 相互通信。微服务应用程序往往是高度动态的,作为持续交付的一部分部署的滚动更新期间单个容器启动或销毁,应用程序扩展 / 缩小以适应负载变化。
这种向高度动态的微服务的转变过程给确保微服务之间的连接方面提出了挑战和机遇。传统的Linux网络安全方法例如iptables过滤IP地址和TCP/UDP端口但IP地址经常在动态微服务环境中流失。容器的高度不稳定的生命周期导致这些方法难以与应用程序并排扩展因为负载均衡表和访问控制列表要不断更新可能增长成包含数十万条规则。出于安全目的协议端口例如用于HTTP流量的TCP端口80不能再用于区分应用流量因为该端口用于跨服务的各种消息。 这种向高度动态的微服务的转变过程,给确保微服务之间的连接方面提出了挑战和机遇。传统的 Linux 网络安全方法(例如 iptables过滤 IP 地址和 TCP/UDP 端口,但 IP 地址经常在动态微服务环境中流失。容器的高度不稳定的生命周期导致这些方法难以与应用程序并排扩展,因为负载均衡表和访问控制列表要不断更新,可能增长成包含数十万条规则。出于安全目的,协议端口(例如,用于 HTTP 流量的 TCP 端口 80不能再用于区分应用流量因为该端口用于跨服务的各种消息。
另一个挑战是提供准确的可见性因为传统系统使用IP地址作为主要识别工具其在微服务架构中的寿命可能才仅仅几秒钟被大大缩短。 另一个挑战是提供准确的可见性,因为传统系统使用 IP 地址作为主要识别工具,其在微服务架构中的寿命可能才仅仅几秒钟,被大大缩短。
利用Linux BPFCilium保留了透明地插入安全可视性+强制执行的能力,但这种方式基于服务/pod/容器标识与传统系统中的IP地址识别相反并且可以根据应用层进行过滤 例如HTTP。因此通过将安全性与寻址分离Cilium不仅可以在高度动态的环境中应用安全策略而且除了提供传统的第3层和第4层分割之外还可以通过在HTTP层运行来提供更强的安全隔离。 。 利用 Linux BPFCilium 保留了透明地插入安全可视性 + 强制执行的能力,但这种方式基于服务 /pod/ 容器标识(与传统系统中的 IP 地址识别相反),并且可以根据应用层进行过滤 (例如 HTTP。因此通过将安全性与寻址分离Cilium 不仅可以在高度动态的环境中应用安全策略,而且除了提供传统的第 3 层和第 4 层分割之外,还可以通过在 HTTP 层运行来提供更强的安全隔离。 。
BPF的使用使得Cilium能够以高度可扩展的方式实现以上功能即使对于大规模环境也不例外。 BPF 的使用使得 Cilium 能够以高度可扩展的方式实现以上功能,即使对于大规模环境也不例外。
## 功能概述 ## 功能概述
### 透明的保护API ### 透明的保护 API
能够保护现代应用程序协议如REST/HTTP、gRPC和Kafka。传统防火墙在第3层和第4层运行在特定端口上运行的协议要么完全受信任要么完全被阻止。Cilium提供了过滤各个应用程序协议请求的功能例如 能够保护现代应用程序协议,如 REST/HTTP、gRPC Kafka。传统防火墙在第 3 层和第 4 层运行在特定端口上运行的协议要么完全受信任要么完全被阻止。Cilium 提供了过滤各个应用程序协议请求的功能,例如:
- 允许所有带有方法`GET`和路径`/public/.*`的HTTP请求。拒绝所有其他请求。 - 允许所有带有方法 `GET` 和路径 `/public/.*` HTTP 请求。拒绝所有其他请求。
- 允许`service1`在Kafka topic上生成`topic1``service2`消费`topic1`。拒绝所有其他Kafka消息。 - 允许 `service1` Kafka topic 上生成 `topic1``service2` 消费 `topic1`。拒绝所有其他 Kafka 消息。
- 要求HTTP标头`X-Token: [0-9]+`出现在所有REST调用中。 - 要求 HTTP 标头 `X-Token: [0-9]+` 出现在所有 REST 调用中。
详情请参考[7层协议](http://docs.cilium.io/en/stable/policy/#layer-7)。 详情请参考 [7 层协议](http://docs.cilium.io/en/stable/policy/#layer-7)。
### 基于身份来保护服务间通信 ### 基于身份来保护服务间通信
现代分布式应用程序依赖于诸如容器之类的技术来促进敏捷性并按需扩展。这将导致在短时间内启动大量应用容器。典型的容器防火墙通过过滤源IP地址和目标端口来保护工作负载。这就要求不论在集群中的哪个位置启动容器时都要操作所有服务器上的防火墙。 现代分布式应用程序依赖于诸如容器之类的技术来促进敏捷性并按需扩展。这将导致在短时间内启动大量应用容器。典型的容器防火墙通过过滤源 IP 地址和目标端口来保护工作负载。这就要求不论在集群中的哪个位置启动容器时都要操作所有服务器上的防火墙。
为了避免受到规模限制Cilium为共享相同安全策略的应用程序容器组分配安全标识。然后该标识与应用程序容器发出的所有网络数据包相关联从而允许验证接收节点处的身份。使用键值存储执行安全身份管理。 为了避免受到规模限制Cilium 为共享相同安全策略的应用程序容器组分配安全标识。然后,该标识与应用程序容器发出的所有网络数据包相关联,从而允许验证接收节点处的身份。使用键值存储执行安全身份管理。
### 安全访问外部服务 ### 安全访问外部服务
基于标签的安全性是集群内部访问控制的首选工具。为了保护对外部服务的访问支持入口ingress和出口egress的传统基于CIDR的安全策略。这允许限制对应用程序容器的访问以及对特定IP范围的访问。 基于标签的安全性是集群内部访问控制的首选工具。为了保护对外部服务的访问支持入口ingress和出口egress的传统基于 CIDR 的安全策略。这允许限制对应用程序容器的访问以及对特定 IP 范围的访问。
### 简单网络 ### 简单网络
一个简单的扁平第3层网络能够跨越多个集群连接所有应用程序容器。使用主机范围分配器可以简化IP分配。这意味着每个主机可以在主机之间没有任何协调的情况下分配IP。 一个简单的扁平第 3 层网络能够跨越多个集群连接所有应用程序容器。使用主机范围分配器可以简化 IP 分配。这意味着每个主机可以在主机之间没有任何协调的情况下分配 IP。
支持以下多节点网络模型: 支持以下多节点网络模型:
- **Overlay**基于封装的虚拟网络产生所有主机。目前VXLAN和Geneve已经完成但可以启用Linux支持的所有封装格式。 - **Overlay**:基于封装的虚拟网络产生所有主机。目前 VXLAN Geneve 已经完成,但可以启用 Linux 支持的所有封装格式。
何时使用此模式此模式具有最小的基础架构和集成要求。它几乎适用于任何网络基础架构唯一的要求是主机之间可以通过IP连接。 何时使用此模式:此模式具有最小的基础架构和集成要求。它几乎适用于任何网络基础架构,唯一的要求是主机之间可以通过 IP 连接。
- **本机路由**使用Linux主机的常规路由表。网络必须能够路由应用程序容器的IP地址。 - **本机路由**:使用 Linux 主机的常规路由表。网络必须能够路由应用程序容器的 IP 地址。
何时使用此模式:此模式适用于高级用户,需要了解底层网络基础结构。此模式适用于: 何时使用此模式:此模式适用于高级用户,需要了解底层网络基础结构。此模式适用于:
- 本地IPv6网络 - 本地 IPv6 网络
- 与云网络路由器配合使用 - 与云网络路由器配合使用
- 如果您已经在运行路由守护进程 - 如果您已经在运行路由守护进程
### 负载均衡 ### 负载均衡
应用程序容器和外部服务之间的流量的分布式负载均衡。负载均衡使用BPF实现允许几乎无限的规模并且如果未在源主机上执行负载均衡操作则支持直接服务器返回DSR 应用程序容器和外部服务之间的流量的分布式负载均衡。负载均衡使用 BPF 实现允许几乎无限的规模并且如果未在源主机上执行负载均衡操作则支持直接服务器返回DSR
**注意**:负载均衡需要启用连接跟踪。这是默认值。 **注意**:负载均衡需要启用连接跟踪。这是默认值。
### 监控和故障排除 ### 监控和故障排除
可见性和故障排查是任何分布式系统运行的基础。虽然我们喜欢用`tcpdump`和 `ping`,它们很好用,但我们努力为故障排除提供更好的工具。包括以下工具: 可见性和故障排查是任何分布式系统运行的基础。虽然我们喜欢用 `tcpdump` `ping`,它们很好用,但我们努力为故障排除提供更好的工具。包括以下工具:
- 使用元数据进行事件监控当数据包被丢弃时该工具不仅仅报告数据包的源IP和目标IP该工具还提供发送方和接收方的完整标签信息等。 - 使用元数据进行事件监控:当数据包被丢弃时,该工具不仅仅报告数据包的源 IP 和目标 IP该工具还提供发送方和接收方的完整标签信息等。
- 策略决策跟踪:为什么丢弃数据包或拒绝请求。策略跟踪框架允许跟踪运行工作负载和基于任意标签定义的策略决策过程。 - 策略决策跟踪:为什么丢弃数据包或拒绝请求。策略跟踪框架允许跟踪运行工作负载和基于任意标签定义的策略决策过程。
- 通过Prometheus导出指标通过Prometheus导出关键指标以便与现有仪表板集成。 - 通过 Prometheus 导出指标:通过 Prometheus 导出关键指标,以便与现有仪表板集成。
### 集成 ### 集成
@ -111,6 +111,6 @@ BPF的使用使得Cilium能够以高度可扩展的方式实现以上功能
## 参考 ## 参考
- [Cilium官方网站 - cilium.io](https://cilium.io) - [Cilium 官方网站 - cilium.io](https://cilium.io)
- [eBPF 简史 - ibm.com](https://www.ibm.com/developerworks/cn/linux/l-lo-eBPF-history/index.html) - [eBPF 简史 - ibm.com](https://www.ibm.com/developerworks/cn/linux/l-lo-eBPF-history/index.html)
- [网络层拦截可选项 - zhihu.com](https://zhuanlan.zhihu.com/p/25672552) - [网络层拦截可选项 - zhihu.com](https://zhuanlan.zhihu.com/p/25672552)

View File

@ -1,108 +0,0 @@
# 云原生应用
## 云原生应用的基本概念
云原生应用,是指原生为在云平台上部署运行而设计开发的应用。公平的说,大多数传统的应用,不做任何改动,都是可以在云平台运行起来的,只要云平台支持这个传统应用所运行的计算机架构和操作系统。只不过这种运行模式,仅仅是把虚拟机当物理机一样使用,不能够真正利用起来云平台的能力。
## 云原生应用与相关技术理念的关系
### 云原生应用与云平台的关系
云平台是用来部署、管理和运行SaaS云应用的。SaaS是云计算的三种服务模型之一即跟业务相关的应用即服务。云计算最根本的特性是提供按需分配资源和弹性计算的能力而云原生应用的设计理念就是让部署到云平台的应用能够利用到云平台的能力实现按需使用计算资源和弹性伸缩成为一个合格的SaaS应用。
### 云原生应用与12要素的关系
12要素是PaaS平台Haroku团队提出的应用设计理念是有关SaaS应用设计理念的红宝书可以说12要素应用就是云原生应用的同义词。
### 云原生应用与Stateless和Share Nothing架构的关系
为了实现水平伸缩的能力云原生应用应该是Stateless和Share Nothing的。
### 云原生应用与微服务架构的关系
微服务架构是实现企业分布式系统的一种架构模式,即将一个复杂的单体应用按照业务的限定上下文,分解成多个独立部署的组件。这些独立部署的组件,就称为微服务。而在谈论云原生应用与微服务架构关系的时候,根据上下文不同可能是有两种不同的含义。一种含义是宏观的云原生应用,即将整个分布式系统看作一个应用,这种语境下,微服务架构是实现云原生应用的一种架构模式;另一种含义是微观的云原生应用,即每个微服务是一个应用,这种语境下,每个微服务要按照云原生应用的设计理念去设计,才能真正实现微服务架构所要达到的目的,即让分布式系统具备按需使用计算资源和弹性伸缩的能力,这里“应用”和“服务”变成了同义词。
### 云原生应用与宠物和牲畜的关系
云原生应用的设计理念是希望把应用当作牲畜来养,而不是当作宠物来养。部署一个云原生应用的集群,就好像圈养了一大群奶牛,目的主要是为了产奶,对待每头牛就像对待机器一样没有什么感情,死了一头就再养一头,而不会像对待宠物那样细心呵护。而传统应用,因为往往因为对运行环境依赖严重,运维人员需要细心照顾、维护,万一出现宕机,一般要在原来的服务器上修复问题再恢复运行;如果恢复不了,整个应用系统就瘫痪了,因此会令运维人员像“宠物死了”一样伤心。
## 云原生应用的设计理念——12要素
### 一个应用对应一套代码多次部署
这一理念主要是强调应用应该清晰明确地区分什么是应用,什么是部署。一个应用对应的就是一个代码仓库,一个软件产品;一次部署对应的是一个运行起来的应用;因此应用与部署的关系是一对多。这种一对多的关系也体现了应用代码的可重用性,一套代码可以重用到多次的部署中去;不同部署之间的区分是配置,而代码是共享的。对应用架构来说,最基本的是要区分运行时行为和非运行时行为,一个应用的非运行时的代表就是一个代码仓库,它可能有多个运行时实例,每个实例就是一次部署。
### 明确地声明并隔离依赖的程序库
不管用什么语言开发应用,编程语言一定都有管理程序库的机制。这一理念强调所有依赖库一定要明确的声明出来,因为只有这样,在运行应用的时候,才能保证所有运行所需要的程序库都正确部署到了云环境中。
### 将配置存储到部署环境中
正像前面所说一个应用的不同部署之间是共享一套代码的不同之处是配置。代码是存储到代码仓库中的那自然配置不应该是存到代码仓库中。每次部署都有自己独立的部署环境每次部署所对应的配置要存到这次部署所对应的部署环境中去因此配置的另一个同义词就是环境变量。这里的部署不包括应用内部的配置例如Java的Properties文件或者是Servlet的映射配置文件web.xml等这些算作是代码而不是配置。这是一个容易令人混淆的地方那到底什么算代码什么算配置判断的标准很简单就是变化的频率。变动导致产品版本更新的就是代码每次部署都可能变更而每次变动不导致产品版本更新的就是配置就是环境变量。
### 将后端支撑服务作为挂载资源来使用
这一理念强调应用使用后台支撑服务的方式。不同的服务之间的区别就只是资源的URL不同也就是设定这个资源的相关环境变量不同。不管是本地资源还是远程资源应用程序都可以正常使用区别只是环境变量的值不同而应用本身并不会因为环境变量不同而有所区别。最常用的后台支撑服务就是数据库、缓存、消息队列等服务。这一理念可以保证应用在任何环境都可以正常运行不会因为后台支撑服务的变化而导致应用无法运行。
### 严格区分构建阶段和运行阶段
这一理念跟区分应用和部署类似,本质上也是要严格区分应用的非运行时行为和运行时行为。构建是将应用的代码仓库编译打包成可运行的软件的过程,是非运行时行为。因此说,这一理念另一方面也说明要防止在运行阶段改代码的行为,这样才能够保证运行中应用的稳定性。
### 将应用作为无状态的进程来运行
这一理念要求所有的用户数据都要通过后端支撑服务来存储,而应用本身是无状态的,因为只有这样,应用才能做到水平伸缩,从而利用云平台弹性伸缩的能力。
### 仅需要绑定一个端口就可以对外发布一个服务
这一理念强调应用本身对于发布服务的环境不应该有过多的要求,而应该是完全自包含的,也就是说不需要依赖云平台提供应用运行容器,而只需要云平台分配某个端口对外发布服务。这一理念保证应用可以使用云平台中任意分配的端口发布服务。
### 可以像UNIX进程一样水平扩展
在UNIX操作系统上不同的进程彼此独立地运行着共享这整个操作系统管理的计算机资源。云原生应用在云平台上的运行模式也是类似的云平台就是分布式操作系统不同的云原生应用彼此独立互补干扰的运行在一个云平台上可以充分利用云平台的整体计算能力。
### 可以快速启动和优雅地关闭
快速启动是为了能充分利用云平台根据需要调度资源的能力,能够在需要的时候,以最小的延时扩展计算能力提供服务。优雅地关闭,一方面是为了释放资源,将不再使用的计算资源归还云平台;另一方面也是为了保证应用逻辑的完整性,将该完成的任务正确完成,未能完成的任务重新交回到系统由其它应用的运行实例来继续完成。要假设云原生应用的目标工作环境中随时有大量同样的应用实例在运行、启动和关闭,因此快速启动和优雅关闭对高性能和稳定的系统非常重要。
### 保持开发环境、预发布环境和生产环境尽量一致
保持环境一致,是为了提高开发单元测试、功能测试和集成测试的有效性,避免出现开发测试中正常而在生产环境中出现问题的情况。
### 将日志作为事件流来处理
云原生应用运行在复杂的分布式基础设施之上,如果日志不通过简单统一的模式来管理,将给系统排错或通过日志挖掘信息带来很大困难。同时,如果应用将日志输出到系统的文件中,也会给系统的存储空间造成压力,增加系统运维的复杂性。因此这一理念推荐应用将日志输出到标准输出,然后由云平台统一收集处理。
### 将应用管理任务当作一次性进程来运行
将应用的管理任务与应用的业务请求以相似的方式运行,以同样的方式进行调度、日志和监控,将有利于系统的稳定性和分析系统的整体行为。
## 云原生应用的挑战
### 处理分布式系统的网络通信问题
云原生应用必须要针对分布式系统中网络通信的复杂性进行设计。对于分布式系统,如果还像单一进程应用那样考虑问题,就会进入所谓的“分布式系统的认识误区”,包括武断地认为:网络是可靠的;网络的延时为零;网络带宽是无限大的;网络是安全的;网络拓扑是不变的;系统中只有一个管理员和网络环境都是统一一致的。也许现在很少会有人幼稚到真的认为分布式环境中的交互处理和运行在单一进程中的函数调用是一样的;但开发的复杂度、功能上线的压力,经常会使开发人员把这些复杂问题暂时放在一边,不断积累起越来越多的“技术负债”。
### 处理分布式系统的状态一致性问题
分布式系统的CAP理论认为在分布式系统中系统的一致性、可用性和分区容忍性三者不可能同时兼顾。当然实际在分布式系统中由于网络通信固有的不稳定分区容忍性是必须要存在的因此在设计应用的时候就要在一致性和可用性之间权衡选择。
### 最终一致性
很多情况下在一致性和可用性之间云原生应用比传统应用更加偏向可用性而采用最终一致性代替传统用事务交易保证的ACID一致性。传统的ACID一致性编程模型与业务无关开发人员对它经验丰富而最终一致性的交互模式与业务相关必须通过业务的合理性来校验阶段不一致的合理性这使得最终一致性比ACID一致性复杂得多。
### 服务发现和负载均衡
云原生应用的运行实例随时可能关闭和启动,因此需要机制使得访问应用服务的客户端随时都能找到健康运行的实例,放弃对宕机实例的访问,这就是服务发现的问题。与服务发现同时存在的,是在多个健康实例中选择一个实例真正为某个客户请求提供服务的过程,这就是负载均衡。
### 任务分解和数据分片
大的任务要分解成很多小任务,分配到各个运行实例上去执行,然后再将执行结果汇总,这就是任务分解。数据分布到各个实例上做处理和存储,这个就是数据分片。这些都需要适应云计算环境的机制去支持。
### 主控角色选举
不管是任务分解还是数据分片,每个应用实例上负责的子任务和数据分片虽然是不同的,但如何分解、谁负责谁这种分配映射表一定是完全相同的;因此在这种情况下,需要负责计算分配映射表的主控角色;而因为云计算环境下没有实例是永远保证健康运行的,主控角色不可能是永远固定的;这就需要主控角色选举的机制,能够在主控角色空白或出现故障宕机的情况下,自选举出新的主控角色。
像设计模式解决面向对象设计中的复杂问题一样,面对云原生应用的复杂应用场景,我们也需要一些典型的设计模式能够可重用地解决一些特定场景的问题。这些我们将在本系列文章的后面结合应用案例予以介绍。
[1] http://www.infoq.com/cn/articles/kubernetes-and-cloud-native-applications-part02

View File

@ -1,3 +1,3 @@
# 集群信息 # 集群信息
为了管理异构和不同配置的主机为了便于Pod的运维管理Kubernetes中提供了很多集群管理的配置和管理功能通过namespace划分的空间通过为node节点创建label和taint用于pod的调度等。 为了管理异构和不同配置的主机,为了便于 Pod 的运维管理Kubernetes 中提供了很多集群管理的配置和管理功能,通过 namespace 划分的空间,通过为 node 节点创建label和 taint 用于 pod 的调度等。

View File

@ -1,20 +1,19 @@
# CNI - Container Network Interface容器网络接口 # CNI - Container Network Interface容器网络接口
CNIContainer Network Interface是CNCF旗下的一个项目由一组用于配置Linux容器的网络接口的规范和库组成同时还包含了一些插件。CNI仅关心容器创建时的网络分配和当容器被删除时释放网络资源。通过此链接浏览该项目<https://github.com/containernetworking/cni> CNIContainer Network Interface CNCF 旗下的一个项目,由一组用于配置 Linux 容器的网络接口的规范和库组成同时还包含了一些插件。CNI 仅关心容器创建时的网络分配,和当容器被删除时释放网络资源。通过此链接浏览该项目:<https://github.com/containernetworking/cni>
Kubernetes源码的`vendor/github.com/containernetworking/cni/libcni`目录中已经包含了CNI的代码也就是说kubernetes中已经内置了CNI。 Kubernetes 源码的 `vendor/github.com/containernetworking/cni/libcni` 目录中已经包含了 CNI 的代码,也就是说 kubernetes 中已经内置了 CNI。
## 接口定义 ## 接口定义
CNI的接口中包括以下几个方法 CNI 的接口中包括以下几个方法:
```go ```go
type CNI interface { type CNI interface {AddNetworkList (net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) DelNetworkList (net *NetworkConfigList, rt *RuntimeConf) error
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) AddNetwork (net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error DelNetwork (net *NetworkConfig, rt *RuntimeConf) error
} }
``` ```
@ -22,105 +21,104 @@ type CNI interface {
## 设计考量 ## 设计考量
CNI设计的时候考虑了以下问题 CNI 设计的时候考虑了以下问题:
- 容器运行时必须在调用任何插件之前为容器创建一个新的网络命名空间。 - 容器运行时必须在调用任何插件之前为容器创建一个新的网络命名空间。
- 然后,运行时必须确定这个容器应属于哪个网络,并为每个网络确定哪些插件必须被执行。 - 然后,运行时必须确定这个容器应属于哪个网络,并为每个网络确定哪些插件必须被执行。
- 网络配置采用JSON格式可以很容易地存储在文件中。网络配置包括必填字段如`name`和`type`以及插件(类型)。网络配置允许字段在调用之间改变值。为此,有一个可选的字段`args`,必须包含不同的信息。 - 网络配置采用 JSON 格式,可以很容易地存储在文件中。网络配置包括必填字段,如 `name` `type` 以及插件(类型)。网络配置允许字段在调用之间改变值。为此,有一个可选的字段 `args`,必须包含不同的信息。
- 容器运行时必须按顺序为每个网络执行相应的插件,将容器添加到每个网络中。 - 容器运行时必须按顺序为每个网络执行相应的插件,将容器添加到每个网络中。
- 在完成容器生命周期后,运行时必须以相反的顺序执行插件(相对于执行添加容器的顺序)以将容器与网络断开连接。 - 在完成容器生命周期后,运行时必须以相反的顺序执行插件(相对于执行添加容器的顺序)以将容器与网络断开连接。
- 容器运行时不能为同一容器调用并行操作,但可以为不同的容器调用并行操作。 - 容器运行时不能为同一容器调用并行操作,但可以为不同的容器调用并行操作。
- 容器运行时必须为容器订阅ADD和DEL操作这样ADD后面总是跟着相应的DEL。 DEL可能跟着额外的DEL但是插件应该允许处理多个DEL即插件DEL应该是幂等的 - 容器运行时必须为容器订阅 ADD DEL 操作,这样 ADD 后面总是跟着相应的 DEL。 DEL 可能跟着额外的 DEL但是插件应该允许处理多个 DEL即插件 DEL 应该是幂等的)。
- 容器必须由ContainerID唯一标识。存储状态的插件应该使用网络名称容器ID的主键来完成。 - 容器必须由 ContainerID 唯一标识。存储状态的插件应该使用(网络名称,容器 ID的主键来完成。
- 运行时不能调用同一个网络名称或容器ID执行两次ADD没有相应的DEL。换句话说给定的容器ID必须只能添加到特定的网络一次。 - 运行时不能调用同一个网络名称或容器 ID 执行两次 ADD没有相应的 DEL。换句话说给定的容器 ID 必须只能添加到特定的网络一次。
## CNI插件 ## CNI 插件
CNI插件必须实现一个可执行文件这个文件可以被容器管理系统例如rkt或Kubernetes调用。 CNI 插件必须实现一个可执行文件,这个文件可以被容器管理系统(例如 rkt Kubernetes调用。
CNI插件负责将网络接口插入容器网络命名空间例如veth对的一端并在主机上进行任何必要的改变例如将veth的另一端连接到网桥。然后将IP分配给接口并通过调用适当的IPAM插件来设置与“IP地址管理”部分一致的路由。 CNI 插件负责将网络接口插入容器网络命名空间例如veth 对的一端),并在主机上进行任何必要的改变(例如将 veth 的另一端连接到网桥)。然后将 IP 分配给接口,并通过调用适当的 IPAM 插件来设置与 “IP 地址管理” 部分一致的路由。
### 参数 ### 参数
CNI插件必须支持以下操作 CNI 插件必须支持以下操作:
#### 将容器添加到网络 #### 将容器添加到网络
参数: 参数:
- **版本**调用者正在使用的CNI规范容器管理系统或调用插件的版本。 - **版本**调用者正在使用的 CNI 规范(容器管理系统或调用插件)的版本。
- **容器ID **由运行时分配的容器的唯一明文标识符。一定不能是空的。 - **容器 ID**由运行时分配的容器的唯一明文标识符。一定不能是空的。
- **网络命名空间路径**要添加的网络名称空间的路径,即`/proc/[pid]/ns/net`或绑定挂载/链接。 - **网络命名空间路径**要添加的网络名称空间的路径,即 `/proc/[pid]/ns/net` 或绑定挂载 / 链接。
- **网络配置**描述容器可以加入的网络的JSON文档。架构如下所述。 - **网络配置**描述容器可以加入的网络的 JSON 文档。架构如下所述。
- **额外的参数**这提供了一个替代机制允许在每个容器上简单配置CNI插件。 - **额外的参数**这提供了一个替代机制,允许在每个容器上简单配置 CNI 插件。
- **容器内接口的名称**这是应该分配给容器网络命名空间内创建的接口的名称因此它必须符合Linux接口名称上的标准限制。 - **容器内接口的名称**这是应该分配给容器(网络命名空间)内创建的接口的名称;因此它必须符合 Linux 接口名称上的标准限制。
结果: 结果:
- **接口列表**根据插件的不同,这可以包括沙箱(例如容器或管理程序)接口名称和/或主机接口名称,每个接口的硬件地址以及接口所在的沙箱(如果有的话)的详细信息。 - **接口列表**根据插件的不同,这可以包括沙箱(例如容器或管理程序)接口名称和 / 或主机接口名称,每个接口的硬件地址以及接口所在的沙箱(如果有的话)的详细信息。
- **分配给每个接口的IP配置**分配给沙箱和/或主机接口的IPv4和/或IPv6地址网关和路由。 - **分配给每个接口的 IP 配置**分配给沙箱和 / 或主机接口的 IPv4 / IPv6 地址,网关和路由。
- **DNS信息**包含nameserver、domain、search domain和option的DNS信息的字典。 - **DNS 信息**包含 nameserver、domain、search domain option DNS 信息的字典。
#### 从网络中删除容器 #### 从网络中删除容器
参数: 参数:
- **版本**调用者正在使用的CNI规范容器管理系统或调用插件的版本。 - **版本**调用者正在使用的 CNI 规范(容器管理系统或调用插件)的版本。
- **容器ID **,如上所述。 - **容器 ID **,如上所述。
- **网络命名空间路径**,如上定义。 - **网络命名空间路径 **,如上定义。
- **网络配置**,如上所述。 - **网络配置 **,如上所述。
- **额外的参数**,如上所述。 - **额外的参数 **,如上所述。
- **上面定义的容器**内的接口的名称。 - **上面定义的容器 **内的接口的名称。
- 所有参数应与传递给相应的添加操作的参数相同。 - 所有参数应与传递给相应的添加操作的参数相同。
- 删除操作应释放配置的网络中提供的containerid拥有的所有资源。 - 删除操作应释放配置的网络中提供的 containerid 拥有的所有资源。
报告版本 报告版本
- 参数:无。 - 参数:无。
- 结果插件支持的CNI规范版本信息。 - 结果:插件支持的 CNI 规范版本信息。
```json ```json
{ {“cniVersion”“0.3.1”,// 此输出使用的 CNI 规范的版本
“cniVersion”“0.3.1”,//此输出使用的CNI规范的版本 “supportedVersions”[“0.1.0”“0.2.0”“0.3.0”“0.3.1”] // 此插件支持的 CNI 规范版本列表
“supportedVersions”[“0.1.0”“0.2.0”“0.3.0”“0.3.1”] //此插件支持的CNI规范版本列表
} }
``` ```
CNI插件的详细说明请参考[CNI SPEC](https://github.com/containernetworking/cni/blob/master/SPEC.md)。 CNI 插件的详细说明请参考:[CNI SPEC](https://github.com/containernetworking/cni/blob/master/SPEC.md)。
### IP分配 ### IP 分配
作为容器网络管理的一部分CNI插件需要为接口分配并维护IP地址并安装与该接口相关的所有必要路由。这给了CNI插件很大的灵活性但也给它带来了很大的负担。众多的CNI插件需要编写相同的代码来支持用户需要的多种IP管理方案例如dhcp、host-local 作为容器网络管理的一部分CNI 插件需要为接口分配并维护IP 地址,并安装与该接口相关的所有必要路由。这给了 CNI 插件很大的灵活性,但也给它带来了很大的负担。众多的 CNI 插件需要编写相同的代码来支持用户需要的多种 IP 管理方案(例如 dhcp、host-local
为了减轻负担使IP管理策略与CNI插件类型解耦我们定义了IP地址管理插件IPAM插件。CNI插件的职责是在执行时恰当地调用IPAM插件。 IPAM插件必须确定接口IP/subnet网关和路由并将此信息返回到“主”插件来应用配置。 IPAM插件可以通过协议例如dhcp、存储在本地文件系统上的数据、网络配置文件的“ipam”部分或上述的组合来获得信息。 为了减轻负担,使 IP 管理策略与 CNI 插件类型解耦,我们定义了 IP 地址管理插件IPAM 插件。CNI 插件的职责是在执行时恰当地调用 IPAM 插件。 IPAM 插件必须确定接口 IP/subnet网关和路由并将此信息返回到 “主” 插件来应用配置。 IPAM 插件可以通过协议(例如 dhcp、存储在本地文件系统上的数据、网络配置文件的 “ipam” 部分或上述的组合来获得信息。
#### IPAM插件 #### IPAM 插件
像CNI插件一样调用IPAM插件的可执行文件。可执行文件位于预定义的路径列表中通过`CNI_PATH`指示给CNI插件。 IPAM插件必须接收所有传入CNI插件的相同环境变量。就像CNI插件一样IPAM插件通过stdin接收网络配置。 CNI 插件一样,调用 IPAM 插件的可执行文件。可执行文件位于预定义的路径列表中,通过 `CNI_PATH` 指示给 CNI 插件。 IPAM 插件必须接收所有传入 CNI 插件的相同环境变量。就像 CNI 插件一样IPAM 插件通过 stdin 接收网络配置。
## 可用插件 ## 可用插件
### Main接口创建 ### Main接口创建
- **bridge**:创建网桥,并添加主机和容器到该网桥 - **bridge**:创建网桥,并添加主机和容器到该网桥
- **ipvlan**:在容器中添加一个[ipvlan](https://www.kernel.org/doc/Documentation/networking/ipvlan.txt)接口 - **ipvlan**:在容器中添加一个 [ipvlan](https://www.kernel.org/doc/Documentation/networking/ipvlan.txt) 接口
- **loopback**:创建一个回环接口 - **loopback**:创建一个回环接口
- **macvlan**创建一个新的MAC地址将所有的流量转发到容器 - **macvlan**:创建一个新的 MAC 地址,将所有的流量转发到容器
- **ptp**创建veth对 - **ptp**:创建 veth
- **vlan**分配一个vlan设备 - **vlan**:分配一个 vlan 设备
### IPAMIP地址分配 ### IPAMIP 地址分配
- **dhcp**在主机上运行守护程序代表容器发出DHCP请求 - **dhcp**:在主机上运行守护程序,代表容器发出 DHCP 请求
- **host-local**维护分配IP的本地数据库 - **host-local**:维护分配 IP 的本地数据库
### Meta其它插件 ### Meta其它插件
- **flannel**根据flannel的配置文件创建接口 - **flannel**:根据 flannel 的配置文件创建接口
- **tuning**调整现有接口的sysctl参数 - **tuning**:调整现有接口的 sysctl 参数
- **portmap**一个基于iptables的portmapping插件。将端口从主机的地址空间映射到容器。 - **portmap**:一个基于 iptables portmapping 插件。将端口从主机的地址空间映射到容器。
## 参考 ## 参考

View File

@ -1,36 +1,36 @@
# Kubernetes的设计理念 # Kubernetes 的设计理念
这一章将介绍 Kubernetes 的设计理念及基本概念。 这一章将介绍 Kubernetes 的设计理念及基本概念。
### Kubernetes设计理念与分布式系统 ### Kubernetes 设计理念与分布式系统
分析和理解Kubernetes的设计理念可以使我们更深入地了解Kubernetes系统更好地利用它管理分布式部署的云原生应用另一方面也可以让我们借鉴其在分布式系统设计方面的经验。 分析和理解 Kubernetes 的设计理念可以使我们更深入地了解 Kubernetes 系统,更好地利用它管理分布式部署的云原生应用,另一方面也可以让我们借鉴其在分布式系统设计方面的经验。
### 分层架构 ### 分层架构
Kubernetes设计理念和功能其实就是一个类似Linux的分层架构如下图所示 Kubernetes 设计理念和功能其实就是一个类似 Linux 的分层架构,如下图所示
![Kubernetes 分层架构示意图](../images/006tNc79ly1fzniqvmi51j31gq0s0q5u.jpg) ![Kubernetes 分层架构示意图](../images/006tNc79ly1fzniqvmi51j31gq0s0q5u.jpg)
* 核心层Kubernetes最核心的功能对外提供API构建高层的应用对内提供插件式应用执行环境 * 核心层Kubernetes 最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境
* 应用层部署无状态应用、有状态应用、批处理任务、集群应用等和路由服务发现、DNS解析等 * 应用层部署无状态应用、有状态应用、批处理任务、集群应用等和路由服务发现、DNS 解析等)
* 管理层系统度量如基础设施、容器和网络的度量自动化如自动扩展、动态Provision等以及策略管理RBAC、Quota、PSP、NetworkPolicy等 * 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态 Provision 以及策略管理RBAC、Quota、PSP、NetworkPolicy 等)
* 接口层kubectl命令行工具、客户端SDK以及集群联邦 * 接口层kubectl 命令行工具、客户端 SDK 以及集群联邦
* 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴 * 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴
* Kubernetes外部日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等 * Kubernetes 外部日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS 应用、ChatOps
* Kubernetes内部CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等 * Kubernetes 内部CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等
### API设计原则 ### API 设计原则
对于云计算系统系统API实际上处于系统设计的统领地位正如本文前面所说Kubernetes集群系统每支持一项新功能引入一项新技术一定会新引入对应的API对象支持对该功能的管理操作理解掌握的API就好比抓住了Kubernetes系统的牛鼻子。Kubernetes系统API的设计有以下几条原则 对于云计算系统,系统 API 实际上处于系统设计的统领地位正如本文前面所说Kubernetes 集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的 API 对象,支持对该功能的管理操作,理解掌握的 API就好比抓住了 Kubernetes 系统的牛鼻子。Kubernetes 系统 API 的设计有以下几条原则:
1. **所有API应该是声明式的**。正如前文所说声明式的操作相对于命令式操作对于重复操作的效果是稳定的这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外声明式操作更容易被用户使用可以使系统向用户隐藏实现的细节隐藏实现的细节的同时也就保留了系统未来持续优化的可能性。此外声明式的API同时隐含了所有的API对象都是名词性质的例如Service、Volume这些API都是名词这些名词描述了用户所期望得到的一个目标分布式对象。 1. ** 所有 API 应该是声明式的**。正如前文所说,声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性。此外,声明式的 API同时隐含了所有的 API 对象都是名词性质的,例如 Service、Volume 这些 API 都是名词,这些名词描述了用户所期望得到的一个目标分布式对象。
2. **API对象是彼此互补而且可组合的**。这里面实际是鼓励API对象尽量实现面向对象设计时的要求即“高内聚松耦合”对业务相关的概念有一个合适的分解提高分解出来的对象的可重用性。事实上Kubernetes这种分布式系统管理平台也是一种业务系统只不过它的业务就是调度和管理容器服务。 2. **API 对象是彼此互补而且可组合的**。这里面实际是鼓励 API 对象尽量实现面向对象设计时的要求,即 “高内聚松耦合”对业务相关的概念有一个合适的分解提高分解出来的对象的可重用性。事实上Kubernetes 这种分布式系统管理平台,也是一种业务系统,只不过它的业务就是调度和管理容器服务。
3. **高层API以操作意图为基础设计**。如何能够设计好API跟如何能用面向对象的方法设计好应用系统有相通的地方高层设计一定是从业务出发而不是过早的从技术实现出发。因此针对Kubernetes的高层API设计一定是以Kubernetes的业务为基础出发也就是以系统调度管理容器的操作意图为基础设计。 3. **高层 API 以操作意图为基础设计**。如何能够设计好 API跟如何能用面向对象的方法设计好应用系统有相通的地方高层设计一定是从业务出发而不是过早的从技术实现出发。因此针对 Kubernetes 的高层 API 设计,一定是以 Kubernetes 的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。
4. **低层API根据高层API的控制需要设计**。设计实现低层API的目的是为了被高层API使用考虑减少冗余、提高重用性的目的低层API的设计也要以需求为基础要尽量抵抗受技术实现影响的诱惑。 4. **低层 API 根据高层 API 的控制需要设计**。设计实现低层 API 的目的,是为了被高层 API 使用,考虑减少冗余、提高重用性的目的,低层 API 的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。
5. **尽量避免简单封装不要有在外部API无法显式知道的内部隐藏的机制**。简单的封装实际没有提供新的功能反而增加了对所封装API的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式例如StatefulSet和ReplicaSet本来就是两种Pod集合那么Kubernetes就用不同API对象来定义它们而不会说只用同一个ReplicaSet内部通过特殊的算法再来区分这个ReplicaSet是有状态的还是无状态。 5. **尽量避免简单封装,不要有在外部 API 无法显式知道的内部隐藏的机制**。简单的封装,实际没有提供新的功能,反而增加了对所封装 API 的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式,例如 StatefulSet ReplicaSet本来就是两种 Pod 集合,那么 Kubernetes 就用不同 API 对象来定义它们,而不会说只用同一个 ReplicaSet内部通过特殊的算法再来区分这个 ReplicaSet 是有状态的还是无状态。
6. **API操作复杂度与对象数量成正比**。这一条主要是从系统性能角度考虑要保证整个系统随着系统规模的扩大性能不会迅速变慢到无法使用那么最低的限定就是API的操作复杂度不能超过O\(N\)N是对象的数量否则系统就不具备水平伸缩性了。 6. **API 操作复杂度与对象数量成正比**。这一条主要是从系统性能角度考虑,要保证整个系统随着系统规模的扩大,性能不会迅速变慢到无法使用,那么最低的限定就是 API 的操作复杂度不能超过 O\(N\)N 是对象的数量,否则系统就不具备水平伸缩性了。
7. **API对象状态不能依赖于网络连接状态**。由于众所周知在分布式环境下网络连接断开是经常发生的事情因此要保证API对象状态能应对网络的不稳定API对象的状态就不能依赖于网络连接状态。 7. **API 对象状态不能依赖于网络连接状态**。由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证 API 对象状态能应对网络的不稳定API 对象的状态就不能依赖于网络连接状态。
8. **尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的**。 8. **尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的**。
### 控制机制设计原则 ### 控制机制设计原则
@ -42,95 +42,96 @@ Kubernetes设计理念和功能其实就是一个类似Linux的分层架构
* **每个模块都可以在出错后自动恢复**。由于分布式系统中无法保证系统各个模块是始终连接的,因此每个模块要有自我修复的能力,保证不会因为连接不到其他模块而自我崩溃。 * **每个模块都可以在出错后自动恢复**。由于分布式系统中无法保证系统各个模块是始终连接的,因此每个模块要有自我修复的能力,保证不会因为连接不到其他模块而自我崩溃。
* **每个模块都可以在必要时优雅地降级服务**。所谓优雅地降级服务,是对系统鲁棒性的要求,即要求在设计实现模块时划分清楚基本功能和高级功能,保证基本功能不会依赖高级功能,这样同时就保证了不会因为高级功能出现故障而导致整个模块崩溃。根据这种理念实现的系统,也更容易快速地增加新的高级功能,因为不必担心引入高级功能影响原有的基本功能。 * **每个模块都可以在必要时优雅地降级服务**。所谓优雅地降级服务,是对系统鲁棒性的要求,即要求在设计实现模块时划分清楚基本功能和高级功能,保证基本功能不会依赖高级功能,这样同时就保证了不会因为高级功能出现故障而导致整个模块崩溃。根据这种理念实现的系统,也更容易快速地增加新的高级功能,因为不必担心引入高级功能影响原有的基本功能。
## Kubernetes的核心技术概念和API对象 ## Kubernetes 的核心技术概念和 API 对象
API对象是Kubernetes集群中的管理操作单元。Kubernetes集群系统每支持一项新功能引入一项新技术一定会新引入对应的API对象支持对该功能的管理操作。例如副本集Replica Set对应的API对象是RS。 API 对象是 Kubernetes 集群中的管理操作单元。Kubernetes 集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的 API 对象,支持对该功能的管理操作。例如副本集 Replica Set 对应的 API 对象是 RS。
每个API对象都有3大类属性元数据metadata、规范spec和状态status。元数据是用来标识API对象的每个对象都至少有3个元数据namespacename和uid除此以外还有各种各样的标签labels用来标识和匹配不同的对象例如用户可以用标签env来标识区分不同的服务部署环境分别用env=dev、env=testing、env=production来标识开发、测试、生产的不同服务。规范描述了用户期望Kubernetes集群中的分布式系统达到的理想状态Desired State例如用户可以通过复制控制器Replication Controller设置期望的Pod副本数为3status描述了系统实际当前达到的状态Status例如系统当前实际的Pod副本数为2那么复制控制器当前的程序逻辑就是自动启动新的Pod争取达到副本数为3。 每个 API 对象都有 3 大类属性:元数据 metadata、规范 spec 和状态 status。元数据是用来标识 API 对象的,每个对象都至少有 3 个元数据namespacename uid除此以外还有各种各样的标签 labels 用来标识和匹配不同的对象,例如用户可以用标签 env 来标识区分不同的服务部署环境,分别用 env=dev、env=testing、env=production 来标识开发、测试、生产的不同服务。规范描述了用户期望 Kubernetes 集群中的分布式系统达到的理想状态Desired State例如用户可以通过复制控制器 Replication Controller 设置期望的 Pod 副本数为 3status 描述了系统实际当前达到的状态Status例如系统当前实际的 Pod 副本数为 2那么复制控制器当前的程序逻辑就是自动启动新的 Pod争取达到副本数为 3。
Kubernetes中所有的配置都是通过API对象的spec去设置的也就是用户通过配置系统的理想状态来改变系统这是Kubernetes重要设计理念之一即所有的操作都是声明式Declarative的而不是命令式Imperative的。声明式操作在分布式系统中的好处是稳定不怕丢操作或运行多次例如设置副本数为3的操作运行多次也还是一个结果而给副本数加1的操作就不是声明式的运行多次结果就错了。 Kubernetes 中所有的配置都是通过 API 对象的 spec 去设置的,也就是用户通过配置系统的理想状态来改变系统,这是 Kubernetes 重要设计理念之一即所有的操作都是声明式Declarative的而不是命令式Imperative的。声明式操作在分布式系统中的好处是稳定不怕丢操作或运行多次例如设置副本数为 3 的操作运行多次也还是一个结果,而给副本数加 1 的操作就不是声明式的,运行多次结果就错了。
### Pod ### Pod
Kubernetes有很多技术概念同时对应很多API对象最重要的也是最基础的是Pod。Pod是在Kubernetes集群中运行部署应用或服务的最小单元它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8最基础的设计理念。比如你运行一个操作系统发行版的软件仓库一个Nginx容器用来发布软件另一个容器专门用来从源仓库做同步这两个容器的镜像不太可能是一个团队开发的但是他们一块儿工作才能提供一个微服务这种情况下不同的团队各自开发构建自己的容器镜像在部署的时候组合成一个微服务对外提供服务。 Kubernetes 有很多技术概念,同时对应很多 API 对象,最重要的也是最基础的是 Pod。Pod 是在 Kubernetes 集群中运行部署应用或服务的最小单元它是可以支持多容器的。Pod 的设计理念是支持多个容器在一个 Pod 中共享网络地址和文件系统可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod 对多容器的支持是 K8 最基础的设计理念。比如你运行一个操作系统发行版的软件仓库,一个 Nginx 容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。
Pod是Kubernetes集群中所有业务类型的基础可以看作运行在Kubernetes集群中的小机器人不同类型的业务就需要不同类型的小机器人去执行。目前Kubernetes中的业务主要可以分为长期伺服型long-running、批处理型batch、节点后台支撑型node-daemon和有状态应用型stateful application分别对应的小机器人控制器为Deployment、Job、DaemonSet和StatefulSet本文后面会一一介绍。 Pod Kubernetes 集群中所有业务类型的基础,可以看作运行在 Kubernetes 集群中的小机器人,不同类型的业务就需要不同类型的小机器人去执行。目前 Kubernetes 中的业务主要可以分为长期伺服型long-running、批处理型batch、节点后台支撑型node-daemon和有状态应用型stateful application分别对应的小机器人控制器为 Deployment、Job、DaemonSet StatefulSet本文后面会一一介绍。
### 副本控制器Replication ControllerRC ### 副本控制器Replication ControllerRC
RC是Kubernetes集群中最早的保证Pod高可用的API对象。通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个少于指定数目RC就会启动运行新的Pod副本多于指定数目RC就会杀死多余的Pod副本。即使在指定数目为1的情况下通过RC运行Pod也比直接运行Pod更明智因为RC也可以发挥它高可用的能力保证永远有1个Pod在运行。RC是Kubernetes较早期的技术概念只适用于长期伺服型的业务类型比如控制小机器人提供高可用的Web服务。 RC Kubernetes 集群中最早的保证 Pod 高可用的 API 对象。通过监控运行中的 Pod 来保证集群中运行指定数目的 Pod 副本。指定的数目可以是多个也可以是 1 少于指定数目RC 就会启动运行新的 Pod 副本多于指定数目RC 就会杀死多余的 Pod 副本。即使在指定数目为 1 的情况下,通过 RC 运行 Pod 也比直接运行 Pod 更明智,因为 RC 也可以发挥它高可用的能力,保证永远有 1 Pod 在运行。RC Kubernetes 较早期的技术概念,只适用于长期伺服型的业务类型,比如控制小机器人提供高可用的 Web 服务。
### 副本集Replica SetRS ### 副本集Replica SetRS
RS是新一代RC提供同样的高可用能力区别主要在于RS后来居上能支持更多种类的匹配模式。副本集对象一般不单独使用而是作为Deployment的理想状态参数使用。 RS 是新一代 RC提供同样的高可用能力区别主要在于 RS 后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为 Deployment 的理想状态参数使用。
### 部署Deployment ### 部署Deployment
部署表示用户对Kubernetes集群的一次更新操作。部署是一个比RS应用模式更广的API对象可以是创建一个新的服务更新一个新的服务也可以是滚动升级一个服务。滚动升级一个服务实际是创建一个新的RS然后逐渐将新RS中副本数增加到理想状态将旧RS中的副本数减小到0的复合操作这样一个复合操作用一个RS是不太好描述的所以用一个更通用的Deployment来描述。以Kubernetes的发展方向未来对所有长期伺服型的的业务的管理都会通过Deployment来管理。 部署表示用户对 Kubernetes 集群的一次更新操作。部署是一个比 RS 应用模式更广的 API 对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的 RS然后逐渐将新 RS 中副本数增加到理想状态,将旧 RS 中的副本数减小到 0 的复合操作;这样一个复合操作用一个 RS 是不太好描述的,所以用一个更通用的 Deployment 来描述。以 Kubernetes 的发展方向,未来对所有长期伺服型的的业务的管理,都会通过 Deployment 来管理。
### 服务Service ### 服务Service
RC、RS和Deployment只是保证了支撑服务的微服务Pod的数量但是没有解决如何访问这些服务的问题。一个Pod只是一个运行服务的实例随时可能在一个节点上停止在另一个节点以一个新的IP启动一个新的Pod因此不能以确定的IP和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作是针对客户端访问的服务找到对应的的后端服务实例。在K8集群中客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP集群内部通过虚拟IP访问一个服务。在Kubernetes集群中微服务的负载均衡是由Kube-proxy实现的。Kube-proxy是Kubernetes集群内部的负载均衡器。它是一个分布式代理服务器在Kubernetes的每个节点上都有一个这一设计体现了它的伸缩性优势需要访问服务的节点越多提供负载均衡能力的Kube-proxy就越多高可用节点也随之增多。与之相比我们平时在服务器端做个反向代理做负载均衡还要进一步解决反向代理的负载均衡和高可用问题。 RC、RS Deployment 只是保证了支撑服务的微服务 Pod 的数量,但是没有解决如何访问这些服务的问题。一个 Pod 只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的 IP 启动一个新的 Pod因此不能以确定的 IP 和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的的后端服务实例。在 K8 集群中,客户端需要访问的服务就是 Service 对象。每个 Service 会对应一个集群内部有效的虚拟 IP集群内部通过虚拟 IP 访问一个服务。在 Kubernetes 集群中微服务的负载均衡是由 Kube-proxy 实现的。Kube-proxy Kubernetes 集群内部的负载均衡器。它是一个分布式代理服务器,在 Kubernetes 的每个节点上都有一个;这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的 Kube-proxy 就越多,高可用节点也随之增多。与之相比,我们平时在服务器端做个反向代理做负载均衡,还要进一步解决反向代理的负载均衡和高可用问题。
### 任务Job ### 任务Job
Job是Kubernetes用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾而长期伺服业务在用户不停止的情况下永远运行。Job管理的Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的spec.completions策略而不同单Pod型任务有一个Pod成功就标志完成定数成功型任务保证有N个任务全部成功工作队列型任务根据应用确认的全局成功而标志成功。 Job Kubernetes 用来控制批处理型任务的 API 对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾而长期伺服业务在用户不停止的情况下永远运行。Job 管理的 Pod 根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的 spec.completions 策略而不同:单 Pod 型任务有一个 Pod 成功就标志完成;定数成功型任务保证有 N 个任务全部成功;工作队列型任务根据应用确认的全局成功而标志成功。
### 后台支撑服务集DaemonSet ### 后台支撑服务集DaemonSet
长期伺服型和批处理型服务的核心在业务应用可能有些节点运行多个同类业务的Pod有些节点上又没有这类Pod运行而后台支撑型服务的核心关注点在Kubernetes集群中的节点物理机或虚拟机要保证每个节点上都有一个此类Pod运行。节点可能是所有集群节点也可能是通过nodeSelector选定的一些特定节点。典型的后台支撑型服务包括存储日志和监控等在每个节点上支持Kubernetes集群运行的服务。 长期伺服型和批处理型服务的核心在业务应用,可能有些节点运行多个同类业务的 Pod有些节点上又没有这类 Pod 运行;而后台支撑型服务的核心关注点在 Kubernetes 集群中的节点(物理机或虚拟机),要保证每个节点上都有一个此类 Pod 运行。节点可能是所有集群节点也可能是通过 nodeSelector 选定的一些特定节点。典型的后台支撑型服务包括,存储,日志和监控等在每个节点上支持 Kubernetes 集群运行的服务。
### 有状态服务集StatefulSet ### 有状态服务集StatefulSet
Kubernetes在1.3版本里发布了Alpha版的PetSet功能在1.5版本里将PetSet功能升级到了Beta版本并重新命名为StatefulSet最终在1.9版本里成为正式GA版本。在云原生应用的体系里有下面两组近义词第一组是无状态stateless、牲畜cattle、无名nameless、可丢弃disposable第二组是有状态stateful、宠物pet、有名having name、不可丢弃non-disposable。RC和RS主要是控制提供无状态服务的其所控制的Pod的名字是随机设置的一个Pod出故障了就被丢弃掉在另一个地方重启一个新的Pod名字变了。名字和启动在哪儿都不重要重要的只是Pod总数而StatefulSet是用来控制有状态服务StatefulSet中的每个Pod的名字都是事先确定的不能更改。StatefulSet中Pod的名字的作用并不是《千与千寻》的人性原因而是关联与该Pod对应的状态。 Kubernetes 1.3 版本里发布了 Alpha 版的 PetSet 功能,在 1.5 版本里将 PetSet 功能升级到了 Beta 版本,并重新命名为 StatefulSet最终在 1.9 版本里成为正式 GA 版本。在云原生应用的体系里有下面两组近义词第一组是无状态stateless、牲畜cattle、无名nameless、可丢弃disposable第二组是有状态stateful、宠物pet、有名having name、不可丢弃non-disposable。RC RS 主要是控制提供无状态服务的,其所控制的 Pod 的名字是随机设置的,一个 Pod 出故障了就被丢弃掉,在另一个地方重启一个新的 Pod名字变了。名字和启动在哪儿都不重要重要的只是 Pod 总数;而 StatefulSet 是用来控制有状态服务StatefulSet 中的每个 Pod 的名字都是事先确定的不能更改。StatefulSet Pod 的名字的作用,并不是《千与千寻》的人性原因,而是关联与该 Pod 对应的状态。
对于RC和RS中的Pod一般不挂载存储或者挂载共享存储保存的是所有Pod共享的状态Pod像牲畜一样没有分别这似乎也确实意味着失去了人性特征对于StatefulSet中的Pod每个Pod挂载自己独立的存储如果一个Pod出现故障从其他节点启动一个同样名字的Pod要挂载上原来Pod的存储继续以它的状态提供服务。 对于 RC RS 中的 Pod一般不挂载存储或者挂载共享存储保存的是所有 Pod 共享的状态Pod 像牲畜一样没有分别(这似乎也确实意味着失去了人性特征);对于 StatefulSet 中的 Pod每个 Pod 挂载自己独立的存储,如果一个 Pod 出现故障,从其他节点启动一个同样名字的 Pod要挂载上原来 Pod 的存储继续以它的状态提供服务。
适合于StatefulSet的业务包括数据库服务MySQL和PostgreSQL集群化管理服务ZooKeeper、etcd等有状态服务。StatefulSet的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物运维人员需要不断地维护它容器刚开始流行时我们用容器来模拟虚拟机使用所有状态都保存在容器里而这已被证明是非常不安全、不可靠的。使用StatefulSetPod仍然可以通过漂移到不同节点提供高可用而存储也可以通过外挂的存储来提供高可靠性StatefulSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。 适合于 StatefulSet 的业务包括数据库服务 MySQL PostgreSQL集群化管理服务 ZooKeeper、etcd 等有状态服务。StatefulSet 的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。使用 StatefulSetPod 仍然可以通过漂移到不同节点提供高可用而存储也可以通过外挂的存储来提供高可靠性StatefulSet 做的只是将确定的 Pod 与确定的存储关联起来保证状态的连续性。
### 集群联邦Federation ### 集群联邦Federation
Kubernetes在1.3版本里发布了beta版的Federation功能。在云计算环境中服务的作用距离范围从近到远一般可以有同主机HostNode、跨主机同可用区Available Zone、跨可用区同地区Region、跨地区同服务商Cloud Service Provider、跨云平台。Kubernetes的设计定位是单一集群在同一个地域内因为同一个地区的网络性能才能满足Kubernetes的调度和计算存储连接要求。而联合集群服务就是为提供跨Region跨服务商Kubernetes集群服务而设计的。 Kubernetes 1.3 版本里发布了 beta 版的 Federation 功能。在云计算环境中服务的作用距离范围从近到远一般可以有同主机HostNode、跨主机同可用区Available Zone、跨可用区同地区Region、跨地区同服务商Cloud Service Provider、跨云平台。Kubernetes 的设计定位是单一集群在同一个地域内,因为同一个地区的网络性能才能满足 Kubernetes 的调度和计算存储连接要求。而联合集群服务就是为提供跨 Region 跨服务商 Kubernetes 集群服务而设计的。
每个Kubernetes Federation有自己的分布式存储、API Server和Controller Manager。用户可以通过Federation的API Server注册该Federation的成员Kubernetes Cluster。当用户通过Federation的API Server创建、更改API对象时Federation API Server会在自己所有注册的子Kubernetes Cluster都创建一份对应的API对象。在提供业务请求服务时Kubernetes Federation会先在自己的各个子Cluster之间做负载均衡而对于发送到某个具体Kubernetes Cluster的业务请求会依照这个Kubernetes Cluster独立提供服务时一样的调度模式去做Kubernetes Cluster内部的负载均衡。而Cluster之间的负载均衡是通过域名服务的负载均衡来实现的。 每个 Kubernetes Federation 有自己的分布式存储、API Server Controller Manager。用户可以通过 Federation API Server 注册该 Federation 的成员 Kubernetes Cluster。当用户通过 Federation API Server 创建、更改 API 对象时Federation API Server 会在自己所有注册的子 Kubernetes Cluster 都创建一份对应的 API 对象。在提供业务请求服务时Kubernetes Federation 会先在自己的各个子 Cluster 之间做负载均衡,而对于发送到某个具体 Kubernetes Cluster 的业务请求,会依照这个 Kubernetes Cluster 独立提供服务时一样的调度模式去做 Kubernetes Cluster 内部的负载均衡。而 Cluster 之间的负载均衡是通过域名服务的负载均衡来实现的。
Federation V1的设计是尽量不影响Kubernetes Cluster现有的工作机制这样对于每个子Kubernetes集群来说并不需要更外层的有一个Kubernetes Federation也就是意味着所有现有的Kubernetes代码和机制不需要因为Federation功能有任何变化。 Federation V1 的设计是尽量不影响 Kubernetes Cluster 现有的工作机制,这样对于每个子 Kubernetes 集群来说,并不需要更外层的有一个 Kubernetes Federation也就是意味着所有现有的 Kubernetes 代码和机制不需要因为 Federation 功能有任何变化。
目前正在开发的Federation V2在保留现有Kubernetes API的同时会开发新的Federation专用的API接口详细内容可以在[这里](https://github.com/kubernetes/community/tree/master/sig-multicluster)找到。 目前正在开发的 Federation V2在保留现有 Kubernetes API 的同时,会开发新的 Federation 专用的 API 接口,详细内容可以在 [这里](https://github.com/kubernetes/community/tree/master/sig-multicluster) 找到。
### 存储卷Volume ### 存储卷Volume
Kubernetes集群中的存储卷跟Docker的存储卷有些类似只不过Docker的存储卷作用范围为一个容器而Kubernetes的存储卷的生命周期和作用范围是一个Pod。每个Pod中声明的存储卷由Pod中的所有容器共享。Kubernetes支持非常多的存储卷类型特别的支持多种公有云平台的存储包括AWSGoogle和Azure云支持多种分布式存储包括GlusterFS和Ceph也支持较容易使用的主机本地目录emptyDir, hostPath和NFS。Kubernetes还支持使用Persistent Volume Claim即PVC这种逻辑存储使用这种存储使得存储的使用者可以忽略后台的实际存储技术例如AWSGoogle或GlusterFS和Ceph而将有关存储实际技术的配置交给存储管理员通过Persistent Volume来配置。 Kubernetes 集群中的存储卷跟 Docker 的存储卷有些类似,只不过 Docker 的存储卷作用范围为一个容器,而 Kubernetes 的存储卷的生命周期和作用范围是一个 Pod。每个 Pod 中声明的存储卷由 Pod 中的所有容器共享。Kubernetes 支持非常多的存储卷类型,特别的,支持多种公有云平台的存储,包括 AWSGoogle Azure 云;支持多种分布式存储包括 GlusterFS Ceph也支持较容易使用的主机本地目录 emptyDir, hostPath NFS。Kubernetes 还支持使用 Persistent Volume Claim PVC 这种逻辑存储,使用这种存储,使得存储的使用者可以忽略后台的实际存储技术(例如 AWSGoogle GlusterFS Ceph而将有关存储实际技术的配置交给存储管理员通过 Persistent Volume 来配置。
### 持久存储卷Persistent VolumePV和持久存储卷声明Persistent Volume ClaimPVC ### 持久存储卷Persistent VolumePV和持久存储卷声明Persistent Volume ClaimPVC
PV和PVC使得Kubernetes集群具备了存储的逻辑抽象能力使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置而把这项配置的工作交给PV的配置者即集群的管理者。存储的PV和PVC的这种关系跟计算的Node和Pod的关系是非常类似的PV和Node是资源的提供者根据集群的基础设施变化而变化由Kubernetes集群管理员配置而PVC和Pod是资源的使用者根据业务服务的需求变化而变化有Kubernetes集群的使用者即服务的管理员来配置。 PV PVC 使得 Kubernetes 集群具备了存储的逻辑抽象能力,使得在配置 Pod 的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给 PV 的配置者,即集群的管理者。存储的 PV PVC 的这种关系,跟计算的 Node Pod 的关系是非常类似的PV Node 是资源的提供者,根据集群的基础设施变化而变化,由 Kubernetes 集群管理员配置;而 PVC Pod 是资源的使用者,根据业务服务的需求变化而变化,有 Kubernetes 集群的使用者即服务的管理员来配置。
### 节点Node ### 节点Node
Kubernetes集群中的计算能力由Node提供最初Node称为服务节点Minion后来改名为Node。Kubernetes集群中的Node也就等同于Mesos集群中的Slave节点是所有Pod运行所在的工作主机可以是物理机也可以是虚拟机。不论是物理机还是虚拟机工作主机的统一特征是上面要运行kubelet管理节点上运行的容器。 Kubernetes 集群中的计算能力由 Node 提供,最初 Node 称为服务节点 Minion后来改名为 Node。Kubernetes 集群中的 Node 也就等同于 Mesos 集群中的 Slave 节点,是所有 Pod 运行所在的工作主机,可以是物理机也可以是虚拟机。不论是物理机还是虚拟机,工作主机的统一特征是上面要运行 kubelet 管理节点上运行的容器。
### 密钥对象Secret ### 密钥对象Secret
Secret是用来保存和传递密码、密钥、认证凭证这些敏感信息的对象。使用Secret的好处是可以避免把敏感信息明文写在配置文件里。在Kubernetes集群中配置和使用服务不可避免的要用到各种敏感信息实现登录、认证等功能例如访问AWS存储的用户名密码。为了避免将类似的敏感信息明文写在所有需要使用的配置文件中可以将这些信息存入一个Secret对象而在配置文件中通过Secret对象引用这些敏感信息。这种方式的好处包括意图明确避免重复减少暴漏机会。 Secret 是用来保存和传递密码、密钥、认证凭证这些敏感信息的对象。使用 Secret 的好处是可以避免把敏感信息明文写在配置文件里。在 Kubernetes 集群中配置和使用服务不可避免的要用到各种敏感信息实现登录、认证等功能,例如访问 AWS 存储的用户名密码。为了避免将类似的敏感信息明文写在所有需要使用的配置文件中,可以将这些信息存入一个 Secret 对象,而在配置文件中通过 Secret 对象引用这些敏感信息。这种方式的好处包括:意图明确,避免重复,减少暴漏机会。
### 用户帐户User Account和服务帐户Service Account ### 用户帐户User Account和服务帐户Service Account
顾名思义用户帐户为人提供账户标识而服务账户为计算机进程和Kubernetes集群中运行的Pod提供账户标识。用户帐户和服务帐户的一个区别是作用范围用户帐户对应的是人的身份人的身份与服务的namespace无关所以用户账户是跨namespace的而服务帐户对应的是一个运行中程序的身份与特定namespace是相关的。 顾名思义,用户帐户为人提供账户标识,而服务账户为计算机进程和 Kubernetes 集群中运行的 Pod 提供账户标识。用户帐户和服务帐户的一个区别是作用范围;用户帐户对应的是人的身份,人的身份与服务的 namespace 无关,所以用户账户是跨 namespace 的;而服务帐户对应的是一个运行中程序的身份,与特定 namespace 是相关的。
### 命名空间Namespace ### 命名空间Namespace
命名空间为Kubernetes集群提供虚拟的隔离作用Kubernetes集群初始有两个命名空间分别是默认命名空间default和系统命名空间kube-system除此以外管理员可以可以创建新的命名空间满足需要。 命名空间为 Kubernetes 集群提供虚拟的隔离作用Kubernetes 集群初始有两个命名空间,分别是默认命名空间 default 和系统命名空间 kube-system除此以外管理员可以可以创建新的命名空间满足需要。
### RBAC访问授权 ### RBAC 访问授权
Kubernetes在1.3版本中发布了alpha版的基于角色的访问控制Role-based Access ControlRBAC的授权模式。相对于基于属性的访问控制Attribute-based Access ControlABACRBAC主要是引入了角色Role和角色绑定RoleBinding的抽象概念。在ABAC中Kubernetes集群中的访问策略只能跟用户直接关联而在RBAC中访问策略可以跟某个角色关联具体的用户在跟一个或多个角色相关联。显然RBAC像其他新功能一样每次引入新功能都会引入新的API对象从而引入新的概念抽象而这一新的概念抽象一定会使集群服务管理和使用更容易扩展和重用。 Kubernetes 1.3 版本中发布了 alpha 版的基于角色的访问控制Role-based Access ControlRBAC的授权模式。相对于基于属性的访问控制Attribute-based Access ControlABACRBAC 主要是引入了角色Role和角色绑定RoleBinding的抽象概念。在 ABAC Kubernetes 集群中的访问策略只能跟用户直接关联;而在 RBAC 访问策略可以跟某个角色关联具体的用户在跟一个或多个角色相关联。显然RBAC 像其他新功能一样,每次引入新功能,都会引入新的 API 对象,从而引入新的概念抽象,而这一新的概念抽象一定会使集群服务管理和使用更容易扩展和重用。
## 总结 ## 总结
从Kubernetes的系统架构、技术概念和设计理念我们可以看到Kubernetes系统最核心的两个设计理念一个是**容错性**,一个是**易扩展性**。容错性实际是保证Kubernetes系统稳定性和安全性的基础易扩展性是保证Kubernetes对变更友好可以快速迭代增加新功能的基础。 Kubernetes 的系统架构、技术概念和设计理念,我们可以看到 Kubernetes 系统最核心的两个设计理念:一个是 **容错性**,一个是 **易扩展性**。容错性实际是保证 Kubernetes 系统稳定性和安全性的基础,易扩展性是保证 Kubernetes 对变更友好,可以快速迭代增加新功能的基础。
按照分布式系统一致性算法Paxos发明人计算机科学家[Leslie Lamport](http://research.microsoft.com/users/lamport/pubs/pubs.html)的理念一个分布式系统有两类特性安全性Safety和活性Liveness。安全性保证系统的稳定保证系统不会崩溃不会出现业务错误不会做坏事是严格约束的活性使得系统可以提供功能提高性能增加易用性让系统可以在用户“看到的时间内”做些好事是尽力而为的。Kubernetes系统的设计理念正好与Lamport安全性与活性的理念不谋而合也正是因为Kubernetes在引入功能和技术的时候非常好地划分了安全性和活性才可以让Kubernetes能有这么快版本迭代快速引入像RBAC、Federation和PetSet这种新功能。 按照分布式系统一致性算法 Paxos 发明人计算机科学家 [Leslie Lamport](http://research.microsoft.com/users/lamport/pubs/pubs.html) 的理念,一个分布式系统有两类特性:安全性 Safety 和活性 Liveness。安全性保证系统的稳定保证系统不会崩溃不会出现业务错误不会做坏事是严格约束的活性使得系统可以提供功能提高性能增加易用性让系统可以在用户 “看到的时间内” 做些好事是尽力而为的。Kubernetes 系统的设计理念正好与 Lamport 安全性与活性的理念不谋而合,也正是因为 Kubernetes 在引入功能和技术的时候,非常好地划分了安全性和活性,才可以让 Kubernetes 能有这么快版本迭代,快速引入像 RBAC、Federation PetSet 这种新功能。
原文地址:[《Kubernetes与云原生应用》系列之Kubernetes的系统架构与设计理念](http://www.infoq.com/cn/articles/kubernetes-and-cloud-native-applications-part01) ## 参考
- [《Kubernetes 与云原生应用》系列之 Kubernetes 的系统架构与设计理念](https://www.infoq.cn/article/kubernetes-and-cloud-native-applications-part01/)

View File

@ -1,3 +1,3 @@
# 控制器 # 控制器
Kubernetes中内建了很多controller控制器这些相当于一个状态机用来控制Pod的具体状态和行为。 Kubernetes 中内建了很多 controller控制器这些相当于一个状态机用来控制 Pod 的具体状态和行为。

View File

@ -26,7 +26,7 @@ Kubernetes中不仅支持CPU、内存为指标的HPA还支持自定义指标
确认您的kubernetes版本在1.7或以上,修改以下配置: 确认您的kubernetes版本在1.7或以上,修改以下配置:
- 将kube-controller-manager的启动参数中`--horizontal-pod-autoscaler-use-rest-clients`设置为true并指定`--master`为API server地址如`--master=http://172.20.0.113:8080 - 将kube-controller-manager的启动参数中`--horizontal-pod-autoscaler-use-rest-clients`设置为true并指定`--master`为API server地址如`--master=http://172.20.0.113:8080`
- 修改kube-apiserver的配置文件apiserver增加一条配置`--requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem --requestheader-allowed-names=aggregator --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --proxy-client-cert-file=/etc/kubernetes/ssl/kubernetes.pem --proxy-client-key-file=/etc/kubernetes/ssl/kubernetes-key.pem`用来配置aggregator的CA证书。 - 修改kube-apiserver的配置文件apiserver增加一条配置`--requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem --requestheader-allowed-names=aggregator --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --proxy-client-cert-file=/etc/kubernetes/ssl/kubernetes.pem --proxy-client-key-file=/etc/kubernetes/ssl/kubernetes-key.pem`用来配置aggregator的CA证书。
已经内置了`apiregistration.k8s.io/v1beta1` API可以直接定义APIService 已经内置了`apiregistration.k8s.io/v1beta1` API可以直接定义APIService

View File

@ -1,37 +1,37 @@
# 使用自定义资源扩展API # 使用自定义资源扩展 API
> **注意:**TPR已经停止维护kubernetes 1.7及以上版本请使用CRD。 > **注意:**TPR 已经停止维护kubernetes 1.7 及以上版本请使用 CRD。
自定义资源是对Kubernetes API的扩展kubernetes中的每个资源都是一个API对象的集合例如我们在YAML文件里定义的那些spec都是对kubernetes中的资源对象的定义所有的自定义资源可以跟kubernetes中内建的资源一样使用kubectl操作。 自定义资源是对 Kubernetes API 的扩展kubernetes 中的每个资源都是一个 API 对象的集合,例如我们在 YAML 文件里定义的那些 spec 都是对 kubernetes 中的资源对象的定义,所有的自定义资源可以跟 kubernetes 中内建的资源一样使用 kubectl 操作。
## 自定义资源 ## 自定义资源
Kubernetes1.6版本中包含一个内建的资源叫做TPRThirdPartyResource可以用它来创建自定义资源但该资源在kubernetes1.7中版本已被CRDCustomResourceDefinition取代。 Kubernetes1.6 版本中包含一个内建的资源叫做 TPRThirdPartyResource可以用它来创建自定义资源但该资源在 kubernetes1.7 中版本已被 CRDCustomResourceDefinition取代。
## 扩展API ## 扩展 API
自定义资源实际上是为了扩展kubernetes的API向kubenetes API中增加新类型可以使用以下三种方式 自定义资源实际上是为了扩展 kubernetes API kubenetes API 中增加新类型,可以使用以下三种方式:
- 修改kubenetes的源码显然难度比较高也不太合适 - 修改 kubenetes 的源码,显然难度比较高,也不太合适
- 创建自定义API server并聚合到API中 - 创建自定义 API server 并聚合到 API
- 1.7以下版本编写TPRkubernetes1.7及以上版本用CRD - 1.7 以下版本编写 TPRkubernetes1.7 及以上版本用 CRD
编写自定义资源是扩展kubernetes API的最简单的方式是否编写自定义资源来扩展API请参考[Should I add a custom resource to my Kubernetes Cluster?](https://kubernetes.io/docs/concepts/api-extension/custom-resources/),行动前请先考虑以下几点: 编写自定义资源是扩展 kubernetes API 的最简单的方式,是否编写自定义资源来扩展 API 请参考 [Should I add a custom resource to my Kubernetes Cluster?](https://kubernetes.io/docs/concepts/api-extension/custom-resources/),行动前请先考虑以下几点:
- 你的API是否属于[声明式的](https://kubernetes.io/docs/concepts/api-extension/custom-resources/#declarative-apis) - 你的 API 是否属于 [声明式的](https://kubernetes.io/docs/concepts/api-extension/custom-resources/#declarative-apis)
- 是否想使用kubectl命令来管理 - 是否想使用 kubectl 命令来管理
- 是否要作为kubenretes中的对象类型来管理同时显示在kubernetes dashboard上 - 是否要作为 kubenretes 中的对象类型来管理,同时显示在 kubernetes dashboard
- 是否可以遵守kubernetes的API规则限制例如URL和API group、namespace限制 - 是否可以遵守 kubernetes API 规则限制,例如 URL API group、namespace 限制
- 是否可以接受该API只能作用于集群或者namespace范围 - 是否可以接受该 API 只能作用于集群或者 namespace 范围
- 想要复用kubernetes API的公共功能比如CRUD、watch、内置的认证和授权等 - 想要复用 kubernetes API 的公共功能,比如 CRUD、watch、内置的认证和授权等
如果这些都不是你想要的那么你可以开发一个独立的API。 如果这些都不是你想要的,那么你可以开发一个独立的 API。
## TPR ## TPR
> **注意:**TPR已经停止维护kubernetes 1.7及以上版本请使用CRD。 > **注意:**TPR 已经停止维护kubernetes 1.7 及以上版本请使用 CRD。
假如我们要创建一个名为`cron-tab.stable.example.com`的TPRyaml文件定义如下 假如我们要创建一个名为 `cron-tab.stable.example.com` TPRyaml 文件定义如下:
```yaml ```yaml
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
@ -41,12 +41,10 @@ metadata:
description: "A specification of a Pod to run on a cron style schedule" description: "A specification of a Pod to run on a cron style schedule"
versions: versions:
- name: v1 - name: v1
``` ```然后使用`kubectl create`命令创建该资源,这样就可以创建出一个 API 端点`/apis/stable.example.com/v1/namespaces/<namespace>/crontabs/...`。
然后使用`kubectl create`命令创建该资源这样就可以创建出一个API端点`/apis/stable.example.com/v1/namespaces/<namespace>/crontabs/...`。 下面是在 [Linkerd](https://linkerd.io) 中的一个实际应用Linkerd 中的一个名为 namerd 的组件使用了 TPR定义如下
```yaml
下面是在[Linkerd](https://linkerd.io)中的一个实际应用Linkerd中的一个名为namerd的组件使用了TPR定义如下
```yaml
--- ---
kind: ThirdPartyResource kind: ThirdPartyResource
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
@ -59,7 +57,7 @@ versions:
### CRD ### CRD
参考下面的CRDresourcedefinition.yaml 参考下面的 CRDresourcedefinition.yaml
```yaml ```yaml
apiVersion: apiextensions.k8s.io/v1beta1 apiVersion: apiextensions.k8s.io/v1beta1
@ -68,33 +66,25 @@ metadata:
# 名称必须符合下面的格式:<plural>.<group> # 名称必须符合下面的格式:<plural>.<group>
name: crontabs.stable.example.com name: crontabs.stable.example.com
spec: spec:
# REST API使用的组名称/apis/<group>/<version> # REST API 使用的组名称:/apis/<group>/<version>
group: stable.example.com group: stable.example.com
# REST API使用的版本号/apis/<group>/<version> # REST API 使用的版本号:/apis/<group>/<version>
version: v1 version: v1
# Namespaced或Cluster # Namespaced Cluster
scope: Namespaced scope: Namespaced
names: names:
# URL中使用的复数名称: /apis/<group>/<version>/<plural> # URL 中使用的复数名称: /apis/<group>/<version>/<plural>
plural: crontabs plural: crontabs
# CLI中使用的单数名称 # CLI 中使用的单数名称
singular: crontab singular: crontab
# CamelCased格式的单数类型。在清单文件中使用 # CamelCased 格式的单数类型。在清单文件中使用
kind: CronTab kind: CronTab
# CLI中使用的资源简称 # CLI 中使用的资源简称
shortNames: shortNames:
- ct - ct
``` ```创建该 CRD```bash
创建该CRD
```bash
kubectl create -f resourcedefinition.yaml kubectl create -f resourcedefinition.yaml
``` ```访问 RESTful API 端点如 <http://172.20.0.113:8080> 将看到如下 API 端点已创建:```bash
访问RESTful API端点如<http://172.20.0.113:8080>将看到如下API端点已创建
```bash
/apis/stable.example.com/v1/namespaces/*/crontabs/... /apis/stable.example.com/v1/namespaces/*/crontabs/...
``` ```
@ -112,7 +102,7 @@ spec:
image: my-awesome-cron-image image: my-awesome-cron-image
``` ```
引用该自定义资源的API创建对象。 引用该自定义资源的 API 创建对象。
**终止器** **终止器**
@ -126,24 +116,24 @@ metadata:
- finalizer.stable.example.com - finalizer.stable.example.com
``` ```
删除自定义对象前,异步执行的钩子。对于具有终止器的一个对象,删除请求仅仅是为`metadata.deletionTimestamp`字段设置一个值,而不是删除它,这将触发监控该对象的控制器执行他们所能处理的任意终止器。 删除自定义对象前,异步执行的钩子。对于具有终止器的一个对象,删除请求仅仅是为`metadata.deletionTimestamp` 字段设置一个值,而不是删除它,这将触发监控该对象的控制器执行他们所能处理的任意终止器。
详情参考:[Extend the Kubernetes API with CustomResourceDefinitions](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/) 详情参考:[Extend the Kubernetes API with CustomResourceDefinitions](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/)
## 自定义控制器 ## 自定义控制器
单纯设置了自定义资源并没有什么用只有跟自定义控制器结合起来才能将资源对象中的声明式API翻译成用户所期望的状态。自定义控制器可以用来管理任何资源类型但是一般是跟自定义资源结合使用。 单纯设置了自定义资源,并没有什么用,只有跟自定义控制器结合起来,才能将资源对象中的声明式 API 翻译成用户所期望的状态。自定义控制器可以用来管理任何资源类型,但是一般是跟自定义资源结合使用。
请参考使用[Operator](https://coreos.com/blog/introducing-operators.html)模式该模式可以让开发者将自己的领域知识转换成特定的kubenretes API扩展。 请参考使用 [Operator](https://coreos.com/blog/introducing-operators.html) 模式,该模式可以让开发者将自己的领域知识转换成特定的 kubenretes API 扩展。
## API server聚合 ## API server 聚合
Aggregated聚合的API server是为了将原来的API server这个巨石monolithic应用给拆分成为了方便用户开发自己的API server集成进来而不用直接修改kubernetes官方仓库的代码这样一来也能将API server解耦方便用户使用实验特性。这些API server可以跟core API server无缝衔接使用kubectl也可以管理它们。 Aggregated聚合的API server 是为了将原来的 API server 这个巨石monolithic应用给拆分成为了方便用户开发自己的 API server 集成进来,而不用直接修改 kubernetes 官方仓库的代码,这样一来也能将 API server 解耦,方便用户使用实验特性。这些 API server 可以跟 core API server 无缝衔接,使用 kubectl 也可以管理它们。
详情参考[Aggregated API Server](aggregated-api-server.md)。 详情参考 [Aggregated API Server](aggregated-api-server.md)。
## 参考 ## 参考
- [Custom Resources](https://kubernetes.io/docs/concepts/api-extension/custom-resources/) - [Custom Resources](https://kubernetes.io/docs/concepts/api-extension/custom-resources/)
- [Extend the Kubernetes API with CustomResourceDefinitions](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/) - [Extend the Kubernetes API with CustomResourceDefinitions](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/)
- [Introducing Operators: Putting Operational Knowledge into Software](https://coreos.com/blog/introducing-operators.html) - [Introducing Operators: Putting Operational Knowledge into Software](https://coreos.com/blog/introducing-operators.html)

View File

@ -2,14 +2,14 @@
## 简述 ## 简述
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括: Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义declarative方法用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括:
- 定义Deployment来创建Pod和ReplicaSet - 定义 Deployment 来创建 Pod ReplicaSet
- 滚动升级和回滚应用 - 滚动升级和回滚应用
- 扩容和缩容 - 扩容和缩容
- 暂停和继续Deployment - 暂停和继续 Deployment
比如一个简单的nginx应用可以定义为 比如一个简单的 nginx 应用可以定义为
```yaml ```yaml
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
@ -28,29 +28,13 @@ spec:
image: nginx:1.7.9 image: nginx:1.7.9
ports: ports:
- containerPort: 80 - containerPort: 80
``` ```扩容:```
扩容:
```
kubectl scale deployment nginx-deployment --replicas 10 kubectl scale deployment nginx-deployment --replicas 10
``` ```如果集群支持 horizontal pod autoscaling 的话,还可以为 Deployment 设置自动扩展:```
如果集群支持 horizontal pod autoscaling 的话还可以为Deployment设置自动扩展
```
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80 kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
``` ```更新镜像也比较简单:```
更新镜像也比较简单:
```
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
``` ```回滚:```
回滚:
```
kubectl rollout undo deployment/nginx-deployment kubectl rollout undo deployment/nginx-deployment
``` ```
@ -60,31 +44,31 @@ kubectl rollout undo deployment/nginx-deployment
## Deployment 概念详细解析 ## Deployment 概念详细解析
本文翻译自kubernetes官方文档https://kubernetes.io/docs/concepts/workloads/controllers/deployment 本文翻译自 kubernetes 官方文档https://kubernetes.io/docs/concepts/workloads/controllers/deployment
根据2017年5月10日的Commit 8481c02 翻译。 根据 2017 5 10 日的 Commit 8481c02 翻译。
## Deployment 是什么? ## Deployment 是什么?
Deployment为Pod和Replica Set下一代Replication Controller提供声明式更新。 Deployment Pod Replica Set下一代 Replication Controller提供声明式更新。
您只需要在 Deployment 中描述您想要的目标状态是什么Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。 您只需要在 Deployment 中描述您想要的目标状态是什么Deployment controller 就会帮您将 Pod 和 ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。
**注意**:您不该手动管理由 Deployment 创建的 ReplicaSet否则您就篡越了 Deployment controller 的职责!下文罗列了 Deployment 对象中已经覆盖了所有的用例。如果未有覆盖您所有需要的用例,请直接在 Kubernetes 的代码库中提 issue。 **注意**:您不该手动管理由 Deployment 创建的 ReplicaSet否则您就篡越了 Deployment controller 的职责!下文罗列了 Deployment 对象中已经覆盖了所有的用例。如果未有覆盖您所有需要的用例,请直接在 Kubernetes 的代码库中提 issue。
典型的用例如下: 典型的用例如下:
- 使用Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态看它是成功还是失败。 - 使用 Deployment 来创建 ReplicaSet。ReplicaSet 在后台创建 pod。检查启动状态看它是成功还是失败。
- 然后通过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会创建一个新的ReplicaSetDeployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。 - 然后,通过更新 Deployment PodTemplateSpec 字段来声明 Pod 的新状态。这会创建一个新的 ReplicaSetDeployment 会按照控制的速率将 pod 从旧的 ReplicaSet 移动到新的 ReplicaSet 中。
- 如果当前状态不稳定回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。 - 如果当前状态不稳定,回滚到之前的 Deployment revision。每次回滚都会更新 Deployment revision。
- 扩容Deployment以满足更高的负载。 - 扩容 Deployment 以满足更高的负载。
- 暂停Deployment来应用PodTemplateSpec的多个修复然后恢复上线。 - 暂停 Deployment 来应用 PodTemplateSpec 的多个修复,然后恢复上线。
- 根据Deployment 的状态判断上线是否hang住了。 - 根据 Deployment 的状态判断上线是否 hang 住了。
- 清除旧的不必要的 ReplicaSet。 - 清除旧的不必要的 ReplicaSet。
## 创建 Deployment ## 创建 Deployment
下面是一个 Deployment 示例,它创建了一个 ReplicaSet 来启动3个 nginx pod。 下面是一个 Deployment 示例,它创建了一个 ReplicaSet 来启动 3 个 nginx pod。
下载示例文件并执行命令: 下载示例文件并执行命令:
@ -93,7 +77,7 @@ $ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml
deployment "nginx-deployment" created deployment "nginx-deployment" created
``` ```
kubectl的 `--record` 的 flag 设置为 `true`可以在 annotation 中记录当前命令创建或者升级了该资源。这在未来会很有用,例如,查看在每个 Deployment revision 中执行了哪些命令。 kubectl 的`--record`的 flag 设置为`true` 可以在 annotation 中记录当前命令创建或者升级了该资源。这在未来会很有用,例如,查看在每个 Deployment revision 中执行了哪些命令。
然后立即执行 `get` 将获得如下结果: 然后立即执行 `get` 将获得如下结果:
@ -103,9 +87,9 @@ NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 0 0 0 1s nginx-deployment 3 0 0 0 1s
``` ```
输出结果表明我们希望的repalica数是3根据deployment中的`.spec.replicas`配置当前replica数 `.status.replicas`是0, 最新的replica数`.status.updatedReplicas`是0可用的replica数`.status.availableReplicas`是0。 输出结果表明我们希望的 repalica 数是 3根据 deployment 中的`.spec.replicas`配置)当前 replica 数(`.status.replicas`)是 0, 最新的 replica 数(`.status.updatedReplicas`)是 0可用的 replica 数(`.status.availableReplicas`)是 0。
过几秒后再执行`get`命令,将获得如下输出: 过几秒后再执行 `get` 命令,将获得如下输出:
```bash ```bash
$ kubectl get deployments $ kubectl get deployments
@ -113,7 +97,7 @@ NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 18s nginx-deployment 3 3 3 3 18s
``` ```
我们可以看到Deployment已经创建了3个 replica所有的 replica 都已经是最新的了包含最新的pod template可用的根据Deployment中的`.spec.minReadySeconds`声明处于已就绪状态的pod的最少个数。执行`kubectl get rs`和`kubectl get pods`会显示Replica SetRS和Pod已创建。 我们可以看到 Deployment 已经创建了 3 个 replica所有的 replica 都已经是最新的了(包含最新的 pod template可用的根据 Deployment 中的`.spec.minReadySeconds`声明,处于已就绪状态的 pod 的最少个数)。执行`kubectl get rs`和`kubectl get pods`会显示 Replica SetRS Pod 已创建。
```bash ```bash
$ kubectl get rs $ kubectl get rs
@ -121,7 +105,7 @@ NAME DESIRED CURRENT READY AGE
nginx-deployment-2035384211 3 3 0 18s nginx-deployment-2035384211 3 3 0 18s
``` ```
您可能会注意到 ReplicaSet 的名字总是`<Deployment>-<pod templatehash>`。 您可能会注意到 ReplicaSet 的名字总是`<Deployment >-<pod template hash >`。
```bash ```bash
$ kubectl get pods --show-labels $ kubectl get pods --show-labels
@ -131,28 +115,28 @@ nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211 nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
``` ```
刚创建的Replica Set将保证总是有3个 nginx 的 pod 存在。 刚创建的 Replica Set 将保证总是有 3 个 nginx 的 pod 存在。
**注意:** 您必须在 Deployment 中的 selector 指定正确的 pod template label在该示例中是 `app = nginx`),不要跟其他的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication Controller 等)。**Kubernetes 本身并不会阻止您任意指定 pod template label **,但是如果您真的这么做了,这些 controller 之间会相互打架,并可能导致不正确的行为。 **注意:** 您必须在 Deployment 中的 selector 指定正确的 pod template label在该示例中是 `app = nginx`),不要跟其他的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication Controller 等)。**Kubernetes 本身并不会阻止您任意指定 pod template label**,但是如果您真的这么做了,这些 controller 之间会相互打架,并可能导致不正确的行为。
### Pod-template-hash label ### Pod-template-hash label
**注意**:这个 label 不是用户指定的! **注意**:这个 label 不是用户指定的!
注意上面示例输出中的 pod label 里的 pod-template-hash label。当 Deployment 创建或者接管 ReplicaSet 时Deployment controller 会自动为 Pod 添加 pod-template-hash label。这样做的目的是防止 Deployment 的子ReplicaSet 的 pod 名字重复。通过将 ReplicaSet 的 PodTemplate 进行哈希散列,使用生成的哈希值作为 label 的值,并添加到 ReplicaSet selector 里、 pod template label 和 ReplicaSet 管理中的 Pod 上。 注意上面示例输出中的 pod label 里的 pod-template-hash label。当 Deployment 创建或者接管 ReplicaSet 时Deployment controller 会自动为 Pod 添加 pod-template-hash label。这样做的目的是防止 Deployment 的子 ReplicaSet 的 pod 名字重复。通过将 ReplicaSet 的 PodTemplate 进行哈希散列,使用生成的哈希值作为 label 的值,并添加到 ReplicaSet selector 里、 pod template label 和 ReplicaSet 管理中的 Pod 上。
## 更新Deployment ## 更新 Deployment
**注意:** Deployment 的 rollout 当且仅当 Deployment 的 pod template例如`.spec.template`中的label更新或者镜像更改时被触发。其他更新例如扩容Deployment不会触发 rollout。 **注意:**Deployment 的 rollout 当且仅当 Deployment 的 pod template例如 `.spec.template`)中的 label 更新或者镜像更改时被触发。其他更新,例如扩容 Deployment 不会触发 rollout。
假如我们现在想要让 nginx pod 使用`nginx:1.9.1`的镜像来代替原来的`nginx:1.7.9`的镜像。 假如我们现在想要让 nginx pod 使用 `nginx:1.9.1` 的镜像来代替原来的 `nginx:1.7.9` 的镜像。
```bash ```bash
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 $ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated deployment "nginx-deployment" image updated
``` ```
我们可以使用`edit`命令来编辑 Deployment修改 `.spec.template.spec.containers[0].image` ,将`nginx:1.7.9` 改写成 `nginx:1.9.1` 我们可以使用`edit`命令来编辑 Deployment修改`.spec.template.spec.containers [0].image`,将`nginx:1.7.9`改写成`nginx:1.9.1`。
```bash ```bash
$ kubectl edit deployment/nginx-deployment $ kubectl edit deployment/nginx-deployment
@ -167,7 +151,7 @@ Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out deployment "nginx-deployment" successfully rolled out
``` ```
Rollout 成功后,`get` Deployment Rollout 成功后,`get`Deployment
```bash ```bash
$ kubectl get deployments $ kubectl get deployments
@ -177,9 +161,9 @@ nginx-deployment 3 3 3 3 36s
UP-TO-DATE 的 replica 的数目已经达到了配置中要求的数目。 UP-TO-DATE 的 replica 的数目已经达到了配置中要求的数目。
CURRENT 的 replica 数表示 Deployment 管理的 replica 数量AVAILABLE 的 replica 数是当前可用的replica数量。 CURRENT 的 replica 数表示 Deployment 管理的 replica 数量AVAILABLE 的 replica 数是当前可用的 replica 数量。
我们通过执行`kubectl get rs`可以看到 Deployment 更新了Pod通过创建一个新的 ReplicaSet 并扩容了3个 replica同时将原来的 ReplicaSet 缩容到了0个 replica。 我们通过执行 `kubectl get rs` 可以看到 Deployment 更新了 Pod通过创建一个新的 ReplicaSet 并扩容了 3 个 replica同时将原来的 ReplicaSet 缩容到了 0 个 replica。
```bash ```bash
$ kubectl get rs $ kubectl get rs
@ -188,7 +172,7 @@ nginx-deployment-1564180365 3 3 0 6s
nginx-deployment-2035384211 0 0 0 36s nginx-deployment-2035384211 0 0 0 36s
``` ```
执行 `get pods`只会看到当前的新的 pod: 执行`get pods`只会看到当前的新的 pod
```bash ```bash
$ kubectl get pods $ kubectl get pods
@ -200,13 +184,13 @@ nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
下次更新这些 pod 的时候,只需要更新 Deployment 中的 pod 的 template 即可。 下次更新这些 pod 的时候,只需要更新 Deployment 中的 pod 的 template 即可。
Deployment 可以保证在升级时只有一定数量的 Pod 是 down 的。默认的它会确保至少有比期望的Pod数量少一个是up状态最多一个不可用 Deployment 可以保证在升级时只有一定数量的 Pod 是 down 的。默认的,它会确保至少有比期望的 Pod 数量少一个是 up 状态(最多一个不可用)。
Deployment 同时也可以确保只创建出超过期望数量的一定数量的 Pod。默认的它会确保最多比期望的Pod数量多一个的 Pod 是 up 的最多1个 surge )。 Deployment 同时也可以确保只创建出超过期望数量的一定数量的 Pod。默认的它会确保最多比期望的 Pod 数量多一个的 Pod 是 up 的(最多 1 个 surge )。
**在未来的 Kuberentes 版本中将从1-1变成25%-25%。** **在未来的 Kuberentes 版本中,将从 1-1 变成 25%-25%。**
例如,如果您自己看下上面的 Deployment您会发现开始创建一个新的 Pod然后删除一些旧的 Pod 再创建一个新的。当新的Pod创建出来之前不会杀掉旧的Pod。这样能够确保可用的 Pod 数量至少有2个Pod的总数最多4个。 例如,如果您自己看下上面的 Deployment您会发现开始创建一个新的 Pod然后删除一些旧的 Pod 再创建一个新的。当新的 Pod 创建出来之前不会杀掉旧的 Pod。这样能够确保可用的 Pod 数量至少有 2 Pod 的总数最多 4 个。
```bash ```bash
$ kubectl describe deployments $ kubectl describe deployments
@ -224,27 +208,27 @@ NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events: Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ ------- --------- -------- ----- ---- ------------- -------- ------ -------
36s 36s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3 36s 36s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
23s 23s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1 23s 23s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
23s 23s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2 23s 23s 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
23s 23s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2 23s 23s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0 21s 21s 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3 21s 21s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
``` ```
我们可以看到当我们刚开始创建这个 Deployment 的时候,创建了一个 ReplicaSetnginx-deployment-2035384211并直接扩容到了3个 replica。 我们可以看到当我们刚开始创建这个 Deployment 的时候,创建了一个 ReplicaSetnginx-deployment-2035384211并直接扩容到了 3 个 replica。
当我们更新这个 Deployment 的时候,它会创建一个新的 ReplicaSetnginx-deployment-1564180365将它扩容到1个replica然后缩容原先的 ReplicaSet 到2个 replica此时满足至少2个 Pod 是可用状态同一时刻最多有4个 Pod 处于创建的状态。 当我们更新这个 Deployment 的时候,它会创建一个新的 ReplicaSetnginx-deployment-1564180365将它扩容到 1 replica然后缩容原先的 ReplicaSet 到 2 个 replica此时满足至少 2 个 Pod 是可用状态,同一时刻最多有 4 个 Pod 处于创建的状态。
接着继续使用相同的 rolling update 策略扩容新的 ReplicaSet 和缩容旧的 ReplicaSet。最终将会在新的 ReplicaSet 中有3个可用的 replica旧的 ReplicaSet 的 replica 数目变成0。 接着继续使用相同的 rolling update 策略扩容新的 ReplicaSet 和缩容旧的 ReplicaSet。最终将会在新的 ReplicaSet 中有 3 个可用的 replica旧的 ReplicaSet 的 replica 数目变成 0。
### Rollover多个rollout并行 ### Rollover多个 rollout 并行)
每当 Deployment controller 观测到有新的 deployment 被创建时,如果没有已存在的 ReplicaSet 来创建期望个数的 Pod 的话,就会创建出一个新的 ReplicaSet 来做这件事。已存在的 ReplicaSet 控制 label 与`.spec.selector`匹配但是 template 跟`.spec.template`不匹配的 Pod 缩容。最终,新的 ReplicaSet 将会扩容出`.spec.replicas`指定数目的 Pod旧的 ReplicaSet 会缩容到0。 每当 Deployment controller 观测到有新的 deployment 被创建时,如果没有已存在的 ReplicaSet 来创建期望个数的 Pod 的话,就会创建出一个新的 ReplicaSet 来做这件事。已存在的 ReplicaSet 控制 label 与 `.spec.selector` 匹配但是 template 跟 `.spec.template` 不匹配的 Pod 缩容。最终,新的 ReplicaSet 将会扩容出 `.spec.replicas` 指定数目的 Pod旧的 ReplicaSet 会缩容到 0。
如果您更新了一个的已存在并正在进行中的 Deployment每次更新 Deployment都会创建一个新的 ReplicaSet并扩容它同时回滚之前扩容的 ReplicaSet ——将它添加到旧的 ReplicaSet 列表中,开始缩容。 如果您更新了一个的已存在并正在进行中的 Deployment每次更新 Deployment 都会创建一个新的 ReplicaSet 并扩容它,同时回滚之前扩容的 ReplicaSet —— 将它添加到旧的 ReplicaSet 列表中,开始缩容。
例如假如您创建了一个有5个`niginx:1.7.9` replica的 Deployment但是当还只有3个`nginx:1.7.9`的 replica 创建出来的时候您就开始更新含有5个`nginx:1.9.1` replica 的 Deployment。在这种情况下Deployment 会立即杀掉已创建的3个`nginx:1.7.9`的 Pod并开始创建`nginx:1.9.1`的 Pod。它不会等到所有的5个`nginx:1.7.9`的 Pod 都创建完成后才开始改变航道。 例如,假如您创建了一个有 5 `niginx:1.7.9` replica 的 Deployment但是当还只有 3 `nginx:1.7.9` 的 replica 创建出来的时候您就开始更新含有 5 `nginx:1.9.1` replica 的 Deployment。在这种情况下Deployment 会立即杀掉已创建的 3 `nginx:1.7.9` 的 Pod并开始创建 `nginx:1.9.1` 的 Pod。它不会等到所有的 5 `nginx:1.7.9` 的 Pod 都创建完成后才开始改变航道。
### Label selector 更新 ### Label selector 更新
@ -256,17 +240,17 @@ Events:
- 更新 selector即更改 selector key 的当前值,将导致跟增添 selector 同样的后果。 - 更新 selector即更改 selector key 的当前值,将导致跟增添 selector 同样的后果。
- 删除 selector即删除 Deployment selector 中的已有的 key不需要对 Pod template label 做任何更改,现有的 ReplicaSet 也不会成为孤儿,但是请注意,删除的 label 仍然存在于现有的 Pod 和 ReplicaSet 中。 - 删除 selector即删除 Deployment selector 中的已有的 key不需要对 Pod template label 做任何更改,现有的 ReplicaSet 也不会成为孤儿,但是请注意,删除的 label 仍然存在于现有的 Pod 和 ReplicaSet 中。
## 回退Deployment ## 回退 Deployment
有时候您可能想回退一个 Deployment例如当 Deployment 不稳定时,比如一直 crash looping。 有时候您可能想回退一个 Deployment例如当 Deployment 不稳定时,比如一直 crash looping。
默认情况下kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录,以便您可以随时回退(您可以修改`revision history limit`来更改保存的revision数 默认情况下kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录,以便您可以随时回退(您可以修改 `revision history limit` 来更改保存的 revision 数)。
**注意:** 只要 Deployment 的 rollout 被触发就会创建一个 revision。也就是说当且仅当 Deployment 的 Pod template如`.spec.template`被更改例如更新template 中的 label 和容器镜像时,就会创建出一个新的 revision。 **注意:**只要 Deployment 的 rollout 被触发就会创建一个 revision。也就是说当且仅当 Deployment 的 Pod template `.spec.template`)被更改,例如更新 template 中的 label 和容器镜像时,就会创建出一个新的 revision。
其他的更新,比如扩容 Deployment 不会创建 revision——因此我们可以很方便的手动或者自动扩容。这意味着当您回退到历史 revision 时,只有 Deployment 中的 Pod template 部分才会回退。 其他的更新,比如扩容 Deployment 不会创建 revision—— 因此我们可以很方便的手动或者自动扩容。这意味着当您回退到历史 revision 时,只有 Deployment 中的 Pod template 部分才会回退。
假设我们在更新 Deployment 的时候犯了一个拼写错误,将镜像的名字写成了`nginx:1.91`,而正确的名字应该是`nginx:1.9.1` 假设我们在更新 Deployment 的时候犯了一个拼写错误,将镜像的名字写成了 `nginx:1.91`,而正确的名字应该是 `nginx:1.9.1`
```bash ```bash
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91 $ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
@ -282,7 +266,7 @@ Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
按住 Ctrl-C 停止上面的 rollout 状态监控。 按住 Ctrl-C 停止上面的 rollout 状态监控。
您会看到旧的 replicanginx-deployment-1564180365 和 nginx-deployment-2035384211和新的 replica nginx-deployment-3066724191数目都是2个。 您会看到旧的 replicanginx-deployment-1564180365 和 nginx-deployment-2035384211和新的 replica nginx-deployment-3066724191数目都是 2 个。
```bash ```bash
$ kubectl get rs $ kubectl get rs
@ -303,7 +287,7 @@ nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
nginx-deployment-3066724191-eocby 0/1 ImagePullBackOff 0 6s nginx-deployment-3066724191-eocby 0/1 ImagePullBackOff 0 6s
``` ```
注意Deployment controller会自动停止坏的 rollout并停止扩容新的 ReplicaSet。 注意Deployment controller 会自动停止坏的 rollout并停止扩容新的 ReplicaSet。
```bash ```bash
$ kubectl describe deployment $ kubectl describe deployment
@ -321,15 +305,15 @@ NewReplicaSet: nginx-deployment-3066724191 (2/2 replicas created)
Events: Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ ------- --------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3 1m 1m 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1 22s 22s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2 22s 22s 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2 22s 22s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0 21s 21s 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3 21s 21s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1 13s 13s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2 13s 13s 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2 13s 13s 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2
``` ```
为了修复这个问题,我们需要回退到稳定的 Deployment revision。 为了修复这个问题,我们需要回退到稳定的 Deployment revision。
@ -347,9 +331,9 @@ REVISION CHANGE-CAUSE
3 kubectl set image deployment/nginx-deployment nginx=nginx:1.91 3 kubectl set image deployment/nginx-deployment nginx=nginx:1.91
``` ```
因为我们创建 Deployment 的时候使用了`--record`参数可以记录命令,我们可以很方便的查看每次 revision 的变化。 因为我们创建 Deployment 的时候使用了`--record` 参数可以记录命令,我们可以很方便的查看每次 revision 的变化。
查看单个revision 的详细信息: 查看单个 revision 的详细信息:
```bash ```bash
$ kubectl rollout history deployment/nginx-deployment --revision=2 $ kubectl rollout history deployment/nginx-deployment --revision=2
@ -377,14 +361,14 @@ $ kubectl rollout undo deployment/nginx-deployment
deployment "nginx-deployment" rolled back deployment "nginx-deployment" rolled back
``` ```
也可以使用 `--revision`参数指定某个历史版本: 也可以使用`--revision`参数指定某个历史版本:
```bash ```bash
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2 $ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back deployment "nginx-deployment" rolled back
``` ```
该 Deployment 现在已经回退到了先前的稳定版本。如您所见Deployment controller产生了一个回退到revison 2的`DeploymentRollback`的 event。 该 Deployment 现在已经回退到了先前的稳定版本。如您所见Deployment controller 产生了一个回退到 revison 2 的`DeploymentRollback`的 event。
```bash ```bash
$ kubectl get deployment $ kubectl get deployment
@ -406,22 +390,22 @@ NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events: Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ ------- --------- -------- ----- ---- ------------- -------- ------ -------
30m 30m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3 30m 30m 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
29m 29m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2 29m 29m 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2
2m 2m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-3066724191 to 0 2m 2m 1 {deployment-controller} Normal ScalingReplicaSet Scaled down replica set nginx-deployment-3066724191 to 0
2m 2m 1 {deployment-controller } Normal DeploymentRollback Rolled back deployment "nginx-deployment" to revision 2 2m 2m 1 {deployment-controller} Normal DeploymentRollback Rolled back deployment "nginx-deployment" to revision 2
29m 2m 2 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3 29m 2m 2 {deployment-controller} Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
``` ```
### 清理 Policy ### 清理 Policy
您可以通过设置`.spec.revisonHistoryLimit`项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision如果将该项设置为0Deployment就不允许回退了。 您可以通过设置 `.spec.revisonHistoryLimit` 项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision如果将该项设置为 0Deployment 就不允许回退了。
## Deployment 扩容 ## Deployment 扩容
@ -432,7 +416,7 @@ $ kubectl scale deployment nginx-deployment --replicas 10
deployment "nginx-deployment" scaled deployment "nginx-deployment" scaled
``` ```
假设您的集群中启用了[horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough),您可以给 Deployment 设置一个 autoscaler基于当前 Pod的 CPU 利用率选择最少和最多的 Pod 数。 假设您的集群中启用了 [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough),您可以给 Deployment 设置一个 autoscaler基于当前 Pod 的 CPU 利用率选择最少和最多的 Pod 数。
```bash ```bash
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80 $ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
@ -443,7 +427,7 @@ deployment "nginx-deployment" autoscaled
RollingUpdate Deployment 支持同时运行一个应用的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout进行中或者已经暂停的为了降低风险Deployment controller 将会平衡已存在的活动中的 ReplicaSet有 Pod 的 ReplicaSet和新加入的 replica。这被称为比例扩容。 RollingUpdate Deployment 支持同时运行一个应用的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout进行中或者已经暂停的为了降低风险Deployment controller 将会平衡已存在的活动中的 ReplicaSet有 Pod 的 ReplicaSet和新加入的 replica。这被称为比例扩容。
例如您正在运行中含有10个 replica 的 Deployment。maxSurge=3maxUnavailable=2。 例如,您正在运行中含有 10 个 replica 的 Deployment。maxSurge=3maxUnavailable=2。
```bash ```bash
$ kubectl get deploy $ kubectl get deploy
@ -458,7 +442,7 @@ $ kubectl set image deploy/nginx-deployment nginx=nginx:sometag
deployment "nginx-deployment" image updated deployment "nginx-deployment" image updated
``` ```
镜像更新启动了一个包含ReplicaSet nginx-deployment-1989198191的新的rollout但是它被阻塞了因为我们上面提到的maxUnavailable。 镜像更新启动了一个包含 ReplicaSet nginx-deployment-1989198191 的新的 rollout但是它被阻塞了因为我们上面提到的 maxUnavailable。
```bash ```bash
$ kubectl get rs $ kubectl get rs
@ -467,9 +451,9 @@ nginx-deployment-1989198191 5 5 0 9s
nginx-deployment-618515232 8 8 8 1m nginx-deployment-618515232 8 8 8 1m
``` ```
然后发起了一个新的Deployment扩容请求。autoscaler将Deployment的repllica数目增加到了15个。Deployment controller需要判断在哪里增加这5个新的replica。如果我们没有谁用比例扩容所有的5个replica都会加到一个新的ReplicaSet中。如果使用比例扩容新添加的replica将传播到所有的ReplicaSet中。大的部分加入replica数最多的ReplicaSet中小的部分加入到replica数少的ReplciaSet中。0个replica的ReplicaSet不会被扩容。 然后发起了一个新的 Deployment 扩容请求。autoscaler Deployment repllica 数目增加到了 15 个。Deployment controller 需要判断在哪里增加这 5 个新的 replica。如果我们没有谁用比例扩容所有的 5 replica 都会加到一个新的 ReplicaSet 中。如果使用比例扩容,新添加的 replica 将传播到所有的 ReplicaSet 中。大的部分加入 replica 数最多的 ReplicaSet 中,小的部分加入到 replica 数少的 ReplciaSet 中。0 replica ReplicaSet 不会被扩容。
在我们上面的例子中3个replica将添加到旧的ReplicaSet中2个replica将添加到新的ReplicaSet中。rollout进程最终会将所有的replica移动到新的ReplicaSet中假设新的replica成为健康状态。 在我们上面的例子中3 replica 将添加到旧的 ReplicaSet 2 replica 将添加到新的 ReplicaSet 中。rollout 进程最终会将所有的 replica 移动到新的 ReplicaSet 中,假设新的 replica 成为健康状态。
```bash ```bash
$ kubectl get deploy $ kubectl get deploy
@ -480,16 +464,17 @@ NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m nginx-deployment-618515232 11 11 11 7m
``` ```
## 删除autoscale
## 删除 autoscale
```bash ```bash
kubectl get hpa kubectl get hpa
kubectl delete hpa ${name of hpa} kubectl delete hpa ${name of hpa}
``` ```
## 暂停和恢复Deployment ## 暂停和恢复 Deployment
您可以在发出一次或多次更新前暂停一个 Deployment然后再恢复它。这样您就能在Deployment暂停期间进行多次修复工作而不会发出不必要的 rollout。 您可以在发出一次或多次更新前暂停一个 Deployment然后再恢复它。这样您就能在 Deployment 暂停期间进行多次修复工作,而不会发出不必要的 rollout。
例如使用刚刚创建 Deployment 例如使用刚刚创建 Deployment
@ -509,7 +494,7 @@ $ kubectl rollout pause deployment/nginx-deployment
deployment "nginx-deployment" paused deployment "nginx-deployment" paused
``` ```
然后更新 Deplyment中的镜像 然后更新 Deplyment 中的镜像:
```bash ```bash
$ kubectl set image deploy/nginx nginx=nginx:1.9.1 $ kubectl set image deploy/nginx nginx=nginx:1.9.1
@ -536,7 +521,7 @@ $ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
deployment "nginx" resource requirements updated deployment "nginx" resource requirements updated
``` ```
Deployment 暂停前的初始状态将继续它的功能,而不会对 Deployment 的更新产生任何影响,只要 Deployment是暂停的。 Deployment 暂停前的初始状态将继续它的功能,而不会对 Deployment 的更新产生任何影响,只要 Deployment 是暂停的。
最后,恢复这个 Deployment观察完成更新的 ReplicaSet 已经创建出来了: 最后,恢复这个 Deployment观察完成更新的 ReplicaSet 已经创建出来了:
@ -566,32 +551,32 @@ nginx-2142116321 0 0 0 2m
nginx-3926361531 3 3 3 28s nginx-3926361531 3 3 3 28s
``` ```
**注意:** 在恢复 Deployment 之前您无法回退一个已经暂停的 Deployment。 **注意:**在恢复 Deployment 之前您无法回退一个已经暂停的 Deployment。
## Deployment 状态 ## Deployment 状态
Deployment 在生命周期中有多种状态。在创建一个新的 ReplicaSet 的时候它可以是 [progressing](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#progressing-deployment) 状态, [complete](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#complete-deployment) 状态,或者 [fail to progress ](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#failed-deployment)状态。 Deployment 在生命周期中有多种状态。在创建一个新的 ReplicaSet 的时候它可以是 [progressing](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#progressing-deployment) 状态, [complete](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#complete-deployment) 状态,或者 [fail to progress](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#failed-deployment) 状态。
### 进行中的 Deployment ### 进行中的 Deployment
Kubernetes 将执行过下列任务之一的 Deployment 标记为 *progressing* 状态: Kubernetes 将执行过下列任务之一的 Deployment 标记为 *progressing* 状态:
- Deployment 正在创建新的ReplicaSet过程中。 - Deployment 正在创建新的 ReplicaSet 过程中。
- Deployment 正在扩容一个已有的 ReplicaSet。 - Deployment 正在扩容一个已有的 ReplicaSet。
- Deployment 正在缩容一个已有的 ReplicaSet。 - Deployment 正在缩容一个已有的 ReplicaSet。
- 有新的可用的 pod 出现。 - 有新的可用的 pod 出现。
您可以使用`kubectl rollout status`命令监控 Deployment 的进度。 您可以使用 `kubectl rollout status` 命令监控 Deployment 的进度。
### 完成的 Deployment ### 完成的 Deployment
Kubernetes 将包括以下特性的 Deployment 标记为 *complete* 状态: Kubernetes 将包括以下特性的 Deployment 标记为 *complete* 状态:
- Deployment 最小可用。最小可用意味着 Deployment 的可用 replica 个数等于或者超过 Deployment 策略中的期望个数。 - Deployment 最小可用。最小可用意味着 Deployment 的可用 replica 个数等于或者超过 Deployment 策略中的期望个数。
- 所有与该 Deployment 相关的replica都被更新到了您指定版本也就说更新完成。 - 所有与该 Deployment 相关的 replica 都被更新到了您指定版本,也就说更新完成。
- 该 Deployment 中没有旧的 Pod 存在。 - 该 Deployment 中没有旧的 Pod 存在。
您可以用`kubectl rollout status`命令查看 Deployment 是否完成。如果 rollout 成功完成,`kubectl rollout status`将返回一个0值的 Exit Code。 您可以用 `kubectl rollout status` 命令查看 Deployment 是否完成。如果 rollout 成功完成,`kubectl rollout status` 将返回一个 0 值的 Exit Code。
```bash ```bash
$ kubectl rollout status deploy/nginx $ kubectl rollout status deploy/nginx
@ -612,24 +597,24 @@ $ echo $?
- 范围限制 - 范围限制
- 程序运行时配置错误 - 程序运行时配置错误
探测这种情况的一种方式是,在您的 Deployment spec 中指定[`spec.progressDeadlineSeconds`](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#progress-deadline-seconds)。`spec.progressDeadlineSeconds` 表示 Deployment controller 等待多少秒才能确定(通过 Deployment statusDeployment进程是卡住的。 探测这种情况的一种方式是,在您的 Deployment spec 中指定 [`spec.progressDeadlineSeconds`](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#progress-deadline-seconds)。`spec.progressDeadlineSeconds` 表示 Deployment controller 等待多少秒才能确定(通过 Deployment statusDeployment 进程是卡住的。
下面的`kubectl`命令设置`progressDeadlineSeconds` 使 controller 在 Deployment 在进度卡住10分钟后报告 下面的 `kubectl` 命令设置 `progressDeadlineSeconds` 使 controller 在 Deployment 在进度卡住 10 分钟后报告:
```bash ```bash
$ kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}' $ kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
"nginx-deployment" patched "nginx-deployment" patched
``` ```
当超过截止时间后Deployment controller 会在 Deployment 的 `status.conditions`中增加一条DeploymentCondition它包括如下属性 当超过截止时间后Deployment controller 会在 Deployment 的`status.conditions` 中增加一条 DeploymentCondition它包括如下属性
- Type=Progressing - Type=Progressing
- Status=False - Status=False
- Reason=ProgressDeadlineExceeded - Reason=ProgressDeadlineExceeded
**注意:** kubernetes除了报告`Reason=ProgressDeadlineExceeded`状态信息外不会对卡住的 Deployment 做任何操作。更高层次的协调器可以利用它并采取相应行动,例如,回滚 Deployment 到之前的版本。 **注意:**kubernetes 除了报告 `Reason=ProgressDeadlineExceeded` 状态信息外不会对卡住的 Deployment 做任何操作。更高层次的协调器可以利用它并采取相应行动,例如,回滚 Deployment 到之前的版本。
**注意:** 如果您暂停了一个 Deployment在暂停的这段时间内kubernetnes不会检查您指定的 deadline。您可以在 Deployment 的 rollout 途中安全的暂停它然后再恢复它这不会触发超过deadline的状态。 **注意:**如果您暂停了一个 Deployment在暂停的这段时间内 kubernetnes 不会检查您指定的 deadline。您可以在 Deployment 的 rollout 途中安全的暂停它,然后再恢复它,这不会触发超过 deadline 的状态。
您可能在使用 Deployment 的时候遇到一些短暂的错误,这些可能是由于您设置了太短的 timeout也有可能是因为各种其他错误导致的短暂错误。例如假设您使用了无效的引用。当您 Describe Deployment 的时候可能会注意到如下信息: 您可能在使用 Deployment 的时候遇到一些短暂的错误,这些可能是由于您设置了太短的 timeout也有可能是因为各种其他错误导致的短暂错误。例如假设您使用了无效的引用。当您 Describe Deployment 的时候可能会注意到如下信息:
@ -638,14 +623,14 @@ $ kubectl describe deployment nginx-deployment
<...> <...>
Conditions: Conditions:
Type Status Reason Type Status Reason
---- ------ ------ ---- ------ ------
Available True MinimumReplicasAvailable Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated Progressing True ReplicaSetUpdated
ReplicaFailure True FailedCreate ReplicaFailure True FailedCreate
<...> <...>
``` ```
执行 `kubectl get deployment nginx-deployment -o yaml`Deployement 的状态可能看起来像这个样子: 执行`kubectl get deployment nginx-deployment -o yaml`Deployement 的状态可能看起来像这个样子:
```yaml ```yaml
status: status:
@ -670,37 +655,36 @@ status:
reason: FailedCreate reason: FailedCreate
status: "True" status: "True"
type: ReplicaFailure type: ReplicaFailure
observedGeneration: 3 observedGeneration: 3
replicas: 2 replicas: 2
unavailableReplicas: 2 unavailableReplicas: 2
``` ```
最终,一旦超过 Deployment 进程的 deadlinekubernetes 会更新状态和导致 Progressing 状态的原因: 最终,一旦超过 Deployment 进程的 deadlinekubernetes 会更新状态和导致 Progressing 状态的原因:
```bash ```bash
Conditions: Conditions:
Type Status Reason Type Status Reason
---- ------ ------ ---- ------ ------
Available True MinimumReplicasAvailable Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate ReplicaFailure True FailedCreate
``` ```
您可以通过缩容 Deployment的方式解决配额不足的问题或者增加您的 namespace 的配额。如果您满足了配额条件后Deployment controller 就会完成您的 Deployment rollout您将看到 Deployment 的状态更新为成功状态(`Status=True`并且`Reason=NewReplicaSetAvailable`)。 您可以通过缩容 Deployment 的方式解决配额不足的问题,或者增加您的 namespace 的配额。如果您满足了配额条件后Deployment controller 就会完成您的 Deployment rollout您将看到 Deployment 的状态更新为成功状态(`Status=True`并且`Reason=NewReplicaSetAvailable`)。
```bash ```bash
Conditions: Conditions:
Type Status Reason Type Status Reason
---- ------ ------ ---- ------ ------
Available True MinimumReplicasAvailable Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable Progressing True NewReplicaSetAvailable
``` ```
`Type=Available``Status=True` 意味着您的Deployment有最小可用性。 最小可用性是在Deployment策略中指定的参数。`Type=Progressing` 、 `Status=True`意味着您的Deployment 或者在部署过程中或者已经成功部署达到了期望的最少的可用replica数量查看特定状态的Reason——在我们的例子中`Reason=NewReplicaSetAvailable` 意味着Deployment已经完成 `Type=Available``Status=True` 意味着您的 Deployment 有最小可用性。 最小可用性是在 Deployment 策略中指定的参数。`Type=Progressing` 、 `Status=True` 意味着您的 Deployment 或者在部署过程中,或者已经成功部署,达到了期望的最少的可用 replica 数量(查看特定状态的 Reason—— 在我们的例子中 `Reason=NewReplicaSetAvailable` 意味着 Deployment 已经完成)。
您可以使用`kubectl rollout status`命令查看Deployment进程是否失败。当Deployment过程超过了deadline`kubectl rollout status`将返回非0的exit code。 您可以使用 `kubectl rollout status` 命令查看 Deployment 进程是否失败。当 Deployment 过程超过了 deadline`kubectl rollout status` 将返回非 0 exit code。
```bash ```bash
$ kubectl rollout status deploy/nginx $ kubectl rollout status deploy/nginx
@ -712,13 +696,13 @@ $ echo $?
### 操作失败的 Deployment ### 操作失败的 Deployment
所有对完成的 Deployment 的操作都适用于失败的 Deployment。您可以对它扩/缩容,回退到历史版本,您甚至可以多次暂停它来应用 Deployment pod template。 所有对完成的 Deployment 的操作都适用于失败的 Deployment。您可以对它扩 / 缩容,回退到历史版本,您甚至可以多次暂停它来应用 Deployment pod template。
## 清理Policy ## 清理 Policy
您可以设置 Deployment 中的 `.spec.revisionHistoryLimit` 项来指定保留多少旧的 ReplicaSet。 余下的将在后台被当作垃圾收集。默认的,所有的 revision 历史就都会被保留。在未来的版本中将会更改为2。 您可以设置 Deployment 中的 `.spec.revisionHistoryLimit` 项来指定保留多少旧的 ReplicaSet。 余下的将在后台被当作垃圾收集。默认的,所有的 revision 历史就都会被保留。在未来的版本中,将会更改为 2。
**注意:** 将该值设置为0将导致所有的 Deployment 历史记录都会被清除,该 Deployment 就无法再回退了。 **注意:**将该值设置为 0将导致所有的 Deployment 历史记录都会被清除,该 Deployment 就无法再回退了。
## 用例 ## 用例
@ -728,85 +712,84 @@ $ echo $?
## 编写 Deployment Spec ## 编写 Deployment Spec
在所有的 Kubernetes 配置中Deployment 也需要`apiVersion``kind`和`metadata`这些配置项。配置文件的通用使用说明查看 [部署应用](https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/),配置容器,和使用 kubectl 管理资源文档。 在所有的 Kubernetes 配置中Deployment 也需要 `apiVersion``kind` `metadata` 这些配置项。配置文件的通用使用说明查看 [部署应用](https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/),配置容器,和使用 kubectl 管理资源文档。
### Pod Template ### Pod Template
`.spec.template``.spec`中唯一要求的字段。 `.spec.template``.spec` 中唯一要求的字段。
`.spec.template` 是 [pod template](https://kubernetes.io/docs/user-guide/replication-controller/#pod-template). 它跟 [Pod](https://kubernetes.io/docs/user-guide/pods)有一模一样的schema除了它是嵌套的并且不需要`apiVersion` 和 `kind`字段。 `.spec.template` 是 [pod template](https://kubernetes.io/docs/user-guide/replication-controller/#pod-template). 它跟 [Pod](https://kubernetes.io/docs/user-guide/pods) 有一模一样的 schema除了它是嵌套的并且不需要 `apiVersion``kind` 字段。
另外为了划分Pod的范围Deployment中的pod template必须指定适当的label不要跟其他controller重复了参考[selector](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#selector))和适当的重启策略。 另外为了划分 Pod 的范围Deployment 中的 pod template 必须指定适当的 label不要跟其他 controller 重复了,参考 [selector](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#selector))和适当的重启策略。
[`.spec.template.spec.restartPolicy`](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle) 可以设置为 `Always` , 如果不指定的话这就是默认配置。 [`.spec.template.spec.restartPolicy`](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle) 可以设置为 `Always` , 如果不指定的话这就是默认配置。
### Replicas ### Replicas
`.spec.replicas` 是可以选字段指定期望的pod数量默认是1。 `.spec.replicas` 是可以选字段,指定期望的 pod 数量,默认是 1。
### Selector ### Selector
`.spec.selector`是可选字段,用来指定 [label selector](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels) 圈定Deployment管理的pod范围。 `.spec.selector` 是可选字段,用来指定 [label selector](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels) ,圈定 Deployment 管理的 pod 范围。
如果被指定, `.spec.selector` 必须匹配 `.spec.template.metadata.labels`否则它将被API拒绝。如果 `.spec.selector` 没有被指定, `.spec.selector.matchLabels` 默认是 `.spec.template.metadata.labels` 如果被指定, `.spec.selector` 必须匹配 `.spec.template.metadata.labels`,否则它将被 API 拒绝。如果 `.spec.selector` 没有被指定, `.spec.selector.matchLabels` 默认是 `.spec.template.metadata.labels`
在Pod的template跟`.spec.template`不同或者数量超过了`.spec.replicas`规定的数量的情况下Deployment会杀掉label跟selector不同的Pod。 Pod template `.spec.template` 不同或者数量超过了 `.spec.replicas` 规定的数量的情况下Deployment 会杀掉 label selector 不同的 Pod。
**注意:** 您不应该再创建其他label跟这个selector匹配的pod或者通过其他Deployment或者通过其他Controller例如ReplicaSet和ReplicationController。否则该Deployment会被把它们当成都是自己创建的。Kubernetes不会阻止您这么做。 **注意:**您不应该再创建其他 label 跟这个 selector 匹配的 pod或者通过其他 Deployment或者通过其他 Controller例如 ReplicaSet ReplicationController。否则该 Deployment 会被把它们当成都是自己创建的。Kubernetes 不会阻止您这么做。
如果您有多个controller使用了重复的selectorcontroller们就会互相打架并导致不正确的行为。 如果您有多个 controller 使用了重复的 selectorcontroller 们就会互相打架并导致不正确的行为。
### 策略 ### 策略
`.spec.strategy` 指定新的Pod替换旧的Pod的策略。 `.spec.strategy.type` 可以是"Recreate"或者是 "RollingUpdate"。"RollingUpdate"是默认值。 `.spec.strategy` 指定新的 Pod 替换旧的 Pod 的策略。 `.spec.strategy.type` 可以是 "Recreate" 或者是 "RollingUpdate"。"RollingUpdate" 是默认值。
#### Recreate Deployment #### Recreate Deployment
`.spec.strategy.type==Recreate`在创建出新的Pod之前会先杀掉所有已存在的Pod。 `.spec.strategy.type==Recreate` 时,在创建出新的 Pod 之前会先杀掉所有已存在的 Pod。
#### Rolling Update Deployment #### Rolling Update Deployment
`.spec.strategy.type==RollingUpdate`Deployment使用[rolling update](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller) 的方式更新Pod 。您可以指定`maxUnavailable` 和 `maxSurge` 来控制 rolling update 进程。 `.spec.strategy.type==RollingUpdate` Deployment 使用 [rolling update](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller) 的方式更新 Pod 。您可以指定 `maxUnavailable``maxSurge` 来控制 rolling update 进程。
##### Max Unavailable ##### Max Unavailable
`.spec.strategy.rollingUpdate.maxUnavailable` 是可选配置项用来指定在升级过程中不可用Pod的最大数量。该值可以是一个绝对值例如5也可以是期望Pod数量的百分比例如10%)。通过计算百分比的绝对值向下取整。如果`.spec.strategy.rollingUpdate.maxSurge` 为0时这个值不可以为0。默认值是1。 `.spec.strategy.rollingUpdate.maxUnavailable` 是可选配置项,用来指定在升级过程中不可用 Pod 的最大数量。该值可以是一个绝对值(例如 5也可以是期望 Pod 数量的百分比(例如 10%)。通过计算百分比的绝对值向下取整。如果 `.spec.strategy.rollingUpdate.maxSurge` 0 时,这个值不可以为 0。默认值是 1。
例如该值设置成30%启动rolling update后旧的ReplicatSet将会立即缩容到期望的Pod数量的70%。新的Pod ready后随着新的ReplicaSet的扩容旧的ReplicaSet会进一步缩容确保在升级的所有时刻可以用的Pod数量至少是期望Pod数量的70%。 例如,该值设置成 30%,启动 rolling update 后旧的 ReplicatSet 将会立即缩容到期望的 Pod 数量的 70%。新的 Pod ready 后,随着新的 ReplicaSet 的扩容,旧的 ReplicaSet 会进一步缩容,确保在升级的所有时刻可以用的 Pod 数量至少是期望 Pod 数量的 70%。
##### Max Surge ##### Max Surge
`.spec.strategy.rollingUpdate.maxSurge` 是可选配置项用来指定可以超过期望的Pod数量的最大个数。该值可以是一个绝对值例如5或者是期望的Pod数量的百分比例如10%)。当`MaxUnavailable`为0时该值不可以为0。通过百分比计算的绝对值向上取整。默认值是1。 `.spec.strategy.rollingUpdate.maxSurge` 是可选配置项,用来指定可以超过期望的 Pod 数量的最大个数。该值可以是一个绝对值(例如 5或者是期望的 Pod 数量的百分比(例如 10%)。当 `MaxUnavailable` 0 时该值不可以为 0。通过百分比计算的绝对值向上取整。默认值是 1。
例如该值设置成30%启动rolling update后新的ReplicatSet将会立即扩容新老Pod的总数不能超过期望的Pod数量的130%。旧的Pod被杀掉后新的ReplicaSet将继续扩容旧的ReplicaSet会进一步缩容确保在升级的所有时刻所有的Pod数量和不会超过期望Pod数量的130%。 例如,该值设置成 30%,启动 rolling update 后新的 ReplicatSet 将会立即扩容,新老 Pod 的总数不能超过期望的 Pod 数量的 130%。旧的 Pod 被杀掉后,新的 ReplicaSet 将继续扩容,旧的 ReplicaSet 会进一步缩容,确保在升级的所有时刻所有的 Pod 数量和不会超过期望 Pod 数量的 130%。
### Progress Deadline Seconds ### Progress Deadline Seconds
`.spec.progressDeadlineSeconds` 是可选配置项用来指定在系统报告Deployment的[failed progressing](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#failed-deployment) ——表现为resource的状态中`type=Progressing`、`Status=False`、 `Reason=ProgressDeadlineExceeded`前可以等待的Deployment进行的秒数。Deployment controller会继续重试该Deployment。未来在实现了自动回滚后 deployment controller在观察到这种状态时就会自动回滚。 `.spec.progressDeadlineSeconds` 是可选配置项,用来指定在系统报告 Deployment [failed progressing](https://kubernetes.io/docs/concepts/workloads/controllers/deployment#failed-deployment) —— 表现为 resource 的状态中 `type=Progressing`、`Status=False`、 `Reason=ProgressDeadlineExceeded` 前可以等待的 Deployment 进行的秒数。Deployment controller 会继续重试该 Deployment。未来在实现了自动回滚后 deployment controller 在观察到这种状态时就会自动回滚。
如果设置该参数,该值必须大于 `.spec.minReadySeconds` 如果设置该参数,该值必须大于 `.spec.minReadySeconds`
### Min Ready Seconds ### Min Ready Seconds
`.spec.minReadySeconds`是一个可选配置项用来指定没有任何容器crash的Pod并被认为是可用状态的最小秒数。默认是0Pod在ready后就会被认为是可用状态。进一步了解什么什么后Pod会被认为是ready状态参阅 [Container Probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes)。 `.spec.minReadySeconds` 是一个可选配置项,用来指定没有任何容器 crash Pod 并被认为是可用状态的最小秒数。默认是 0Pod ready 后就会被认为是可用状态)。进一步了解什么什么后 Pod 会被认为是 ready 状态,参阅 [Container Probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes)。
### Rollback To ### Rollback To
`.spec.rollbackTo` 是一个可以选配置项用来配置Deployment回退的配置。设置该参数将触发回退操作每次回退完成后该值就会被清除。 `.spec.rollbackTo` 是一个可以选配置项,用来配置 Deployment 回退的配置。设置该参数将触发回退操作,每次回退完成后,该值就会被清除。
#### Revision #### Revision
`.spec.rollbackTo.revision`是一个可选配置项用来指定回退到的revision。默认是0意味着回退到上一个revision。 `.spec.rollbackTo.revision` 是一个可选配置项,用来指定回退到的 revision。默认是 0意味着回退到上一个 revision。
### Revision History Limit ### Revision History Limit
Deployment revision history存储在它控制的ReplicaSets中。 Deployment revision history 存储在它控制的 ReplicaSets 中。
`.spec.revisionHistoryLimit` 是一个可选配置项用来指定可以保留的旧的ReplicaSet数量。该理想值取决于心Deployment的频率和稳定性。如果该值没有设置的话默认所有旧的Replicaset或会被保留将资源存储在etcd中是用`kubectl get rs`查看输出。每个Deployment的该配置都保存在ReplicaSet中然而一旦您删除的旧的RepelicaSet您的Deployment就无法再回退到那个revison了。 `.spec.revisionHistoryLimit` 是一个可选配置项,用来指定可以保留的旧的 ReplicaSet 数量。该理想值取决于心 Deployment 的频率和稳定性。如果该值没有设置的话,默认所有旧的 Replicaset 或会被保留,将资源存储在 etcd 中,是用 `kubectl get rs` 查看输出。每个 Deployment 的该配置都保存在 ReplicaSet 中,然而,一旦您删除的旧的 RepelicaSet您的 Deployment 就无法再回退到那个 revison 了。
如果您将该值设置为0所有具有0个replica的ReplicaSet都会被删除。在这种情况下新的Deployment rollout无法撤销因为revision history都被清理掉了。 如果您将该值设置为 0所有具有 0 replica ReplicaSet 都会被删除。在这种情况下,新的 Deployment rollout 无法撤销,因为 revision history 都被清理掉了。
### Paused ### Paused
`.spec.paused`是可以可选配置项boolean值。用来指定暂停和恢复Deployment。Paused和没有paused的Deployment之间的唯一区别就是所有对paused deployment中的PodTemplateSpec的修改都不会触发新的rollout。Deployment被创建之后默认是非paused。 `.spec.paused` 是可以可选配置项boolean 值。用来指定暂停和恢复 Deployment。Paused 和没有 paused 的 Deployment 之间的唯一区别就是,所有对 paused deployment 中的 PodTemplateSpec 的修改都不会触发新的 rollout。Deployment 被创建之后默认是非 paused。

View File

@ -1,11 +1,11 @@
# Pod hook # Pod hook
Pod hook钩子是由Kubernetes管理的kubelet发起的当容器中的进程启动前或者容器中的进程终止之前运行这是包含在容器的生命周期之中。可以同时为Pod中的所有容器都配置hook。 Pod hook钩子是由 Kubernetes 管理的 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为 Pod 中的所有容器都配置 hook。
Hook的类型包括两种 Hook 的类型包括两种:
- exec执行一段命令 - exec执行一段命令
- HTTP发送HTTP请求。 - HTTP发送 HTTP 请求。
参考下面的配置: 参考下面的配置:
@ -21,19 +21,19 @@ spec:
lifecycle: lifecycle:
postStart: postStart:
exec: exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] command: ["/bin/sh", "-c", "echo Hello from the postStart handler> /usr/share/message"]
preStop: preStop:
exec: exec:
command: ["/usr/sbin/nginx","-s","quit"] command: ["/usr/sbin/nginx","-s","quit"]
``` ```
在容器创建之后容器的Entrypoint执行之前这时候Pod已经被调度到某台node上被某个kubelet管理了这时候kubelet会调用postStart操作该操作跟容器的启动命令是在异步执行的也就是说在postStart操作执行完成之前kubelet会锁住容器不让应用程序的进程启动只有在 postStart操作完成之后容器的状态才会被设置成为RUNNING。 在容器创建之后,容器的 Entrypoint 执行之前,这时候 Pod 已经被调度到某台 node 上,被某个 kubelet 管理了,这时候 kubelet 会调用 postStart 操作,该操作跟容器的启动命令是在异步执行的,也就是说在 postStart 操作执行完成之前kubelet 会锁住容器,不让应用程序的进程启动,只有在 postStart 操作完成之后容器的状态才会被设置成为 RUNNING。
如果postStart或者preStop hook失败将会终止容器。 如果 postStart 或者 preStop hook 失败,将会终止容器。
## 调试hook ## 调试 hook
Hook调用的日志没有暴露给Pod的event所以只能通过`describe`命令来获取,如果有错误将可以看到`FailedPostStartHook`或`FailedPreStopHook`这样的event。 Hook 调用的日志没有暴露给 Pod event所以只能通过 `describe` 命令来获取,如果有错误将可以看到 `FailedPostStartHook` `FailedPreStopHook` 这样的 event。
## 参考 ## 参考