这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
集群管理
关于创建和管理 Kubernetes 集群的底层细节。
集群管理概述面向任何创建和管理 Kubernetes 集群的读者人群。
我们假设你大概了解一些核心的 Kubernetes 概念。
规划集群
查阅安装中的指导,获取如何规划、建立以及配置 Kubernetes
集群的示例。本文所列的文章称为发行版 。
说明: 并非所有发行版都是被积极维护的。
请选择使用最近 Kubernetes 版本测试过的发行版。
在选择一个指南前,有一些因素需要考虑:
- 你是打算在你的计算机上尝试 Kubernetes,还是要构建一个高可用的多节点集群?
请选择最适合你需求的发行版。
- 你正在使用类似 Google Kubernetes Engine
这样的被托管的 Kubernetes 集群, 还是管理你自己的集群?
- 你的集群是在本地还是云(IaaS) 上?Kubernetes 不能直接支持混合集群。
作为代替,你可以建立多个集群。
- 如果你在本地配置 Kubernetes,需要考虑哪种
网络模型最适合。
- 你的 Kubernetes 在裸金属硬件上还是虚拟机(VMs) 上运行?
- 你是想运行一个集群,还是打算参与开发 Kubernetes 项目代码?
如果是后者,请选择一个处于开发状态的发行版。
某些发行版只提供二进制发布版,但提供更多的选择。
- 让你自己熟悉运行一个集群所需的组件。
管理集群
保护集群
保护 kubelet
可选集群服务
- DNS 集成
描述了如何将一个 DNS 名解析到一个 Kubernetes service。
- 记录和监控集群活动
阐述了 Kubernetes 的日志如何工作以及怎样实现。
1 - 证书
要了解如何为集群生成证书,参阅证书。
2 - 管理资源
你已经部署了应用并通过服务暴露它。然后呢?
Kubernetes 提供了一些工具来帮助管理你的应用部署,包括扩缩容和更新。
我们将更深入讨论的特性包括
配置文件和
标签。
组织资源配置
许多应用需要创建多个资源,例如 Deployment 和 Service。
可以通过将多个资源组合在同一个文件中(在 YAML 中以 ---
分隔)
来简化对它们的管理。例如:
apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
可以用创建单个资源相同的方式来创建多个资源:
kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created
资源将按照它们在文件中的顺序创建。
因此,最好先指定服务,这样在控制器(例如 Deployment)创建 Pod 时能够
确保调度器可以将与服务关联的多个 Pod 分散到不同节点。
kubectl create
也接受多个 -f
参数:
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
还可以指定目录路径,而不用添加多个单独的文件:
kubectl apply -f https://k8s.io/examples/application/nginx/
kubectl
将读取任何后缀为 .yaml
、.yml
或者 .json
的文件。
建议的做法是,将同一个微服务或同一应用层相关的资源放到同一个文件中,
将同一个应用相关的所有文件按组存放到同一个目录中。
如果应用的各层使用 DNS 相互绑定,那么你可以将堆栈的所有组件一起部署。
还可以使用 URL 作为配置源,便于直接使用已经提交到 Github 上的配置文件进行部署:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/zh/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created
kubectl 中的批量操作
资源创建并不是 kubectl
可以批量执行的唯一操作。
kubectl
还可以从配置文件中提取资源名,以便执行其他操作,
特别是删除你之前创建的资源:
kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
在仅有两种资源的情况下,可以使用"资源类型/资源名"的语法在命令行中
同时指定这两个资源:
kubectl delete deployments/my-nginx services/my-nginx-svc
对于资源数目较大的情况,你会发现使用 -l
或 --selector
指定筛选器(标签查询)能很容易根据标签筛选资源:
kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
由于 kubectl
用来输出资源名称的语法与其所接受的资源名称语法相同,
你可以使用 $()
或 xargs
进行链式操作:
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {}
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
上面的命令中,我们首先使用 examples/application/nginx/
下的配置文件创建资源,
并使用 -o name
的输出格式(以"资源/名称"的形式打印每个资源)打印所创建的资源。
然后,我们通过 grep
来过滤 "service",最后再打印 kubectl get
的内容。
如果你碰巧在某个路径下的多个子路径中组织资源,那么也可以递归地在所有子路径上
执行操作,方法是在 --filename,-f
后面指定 --recursive
或者 -R
。
例如,假设有一个目录路径为 project/k8s/development
,它保存开发环境所需的
所有清单,并按资源类型组织:
project/k8s/development
├── configmap
│ └── my-configmap.yaml
├── deployment
│ └── my-deployment.yaml
└── pvc
└── my-pvc.yaml
默认情况下,对 project/k8s/development
执行的批量操作将停止在目录的第一级,
而不是处理所有子目录。
如果我们试图使用以下命令在此目录中创建资源,则会遇到一个错误:
kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
正确的做法是,在 --filename,-f
后面标明 --recursive
或者 -R
之后:
kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
--recursive
可以用于接受 --filename,-f
参数的任何操作,例如:
kubectl {create,get,delete,describe,rollout}
等。
有多个 -f
参数出现的时候,--recursive
参数也能正常工作:
kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
如果你有兴趣进一步学习关于 kubectl
的内容,请阅读
命令行工具(kubectl)。
有效地使用标签
到目前为止我们使用的示例中的资源最多使用了一个标签。
在许多情况下,应使用多个标签来区分集合。
例如,不同的应用可能会为 app
标签设置不同的值。
但是,类似 guestbook 示例
这样的多层应用,还需要区分每一层。前端可以带以下标签:
labels:
app: guestbook
tier: frontend
Redis 的主节点和从节点会有不同的 tier
标签,甚至还有一个额外的 role
标签:
labels:
app: guestbook
tier: backend
role: master
以及
labels:
app: guestbook
tier: backend
role: slave
标签允许我们按照标签指定的任何维度对我们的资源进行切片和切块:
kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-jpy62 1/1 Running 0 1m guestbook frontend <none>
guestbook-redis-master-5pg3b 1/1 Running 0 1m guestbook backend master
guestbook-redis-slave-2q2yf 1/1 Running 0 1m guestbook backend slave
guestbook-redis-slave-qgazl 1/1 Running 0 1m guestbook backend slave
my-nginx-divi2 1/1 Running 0 29m nginx <none> <none>
my-nginx-o0ef1 1/1 Running 0 29m nginx <none> <none>
kubectl get pods -lapp=guestbook,role=slave
NAME READY STATUS RESTARTS AGE
guestbook-redis-slave-2q2yf 1/1 Running 0 3m
guestbook-redis-slave-qgazl 1/1 Running 0 3m
金丝雀部署(Canary Deployments)
另一个需要多标签的场景是用来区分同一组件的不同版本或者不同配置的多个部署。
常见的做法是部署一个使用金丝雀发布来部署新应用版本
(在 Pod 模板中通过镜像标签指定),保持新旧版本应用同时运行。
这样,新版本在完全发布之前也可以接收实时的生产流量。
例如,你可以使用 track
标签来区分不同的版本。
主要稳定的发行版将有一个 track
标签,其值为 stable
:
name: frontend
replicas: 3
...
labels:
app: guestbook
tier: frontend
track: stable
...
image: gb-frontend:v3
然后,你可以创建 guestbook 前端的新版本,让这些版本的 track
标签带有不同的值
(即 canary
),以便两组 Pod 不会重叠:
name: frontend-canary
replicas: 1
...
labels:
app: guestbook
tier: frontend
track: canary
...
image: gb-frontend:v4
前端服务通过选择标签的公共子集(即忽略 track
标签)来覆盖两组副本,
以便流量可以转发到两个应用:
selector:
app: guestbook
tier: frontend
你可以调整 stable
和 canary
版本的副本数量,以确定每个版本将接收
实时生产流量的比例(在本例中为 3:1)。
一旦有信心,你就可以将新版本应用的 track
标签的值从
canary
替换为 stable
,并且将老版本应用删除。
想要了解更具体的示例,请查看
Ghost 部署教程。
更新标签
有时,现有的 pod 和其它资源需要在创建新资源之前重新标记。
这可以用 kubectl label
完成。
例如,如果想要将所有 nginx pod 标记为前端层,运行:
kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled
首先用标签 "app=nginx" 过滤所有的 Pod,然后用 "tier=fe" 标记它们。
想要查看你刚才标记的 Pod,请运行:
kubectl get pods -l app=nginx -L tier
NAME READY STATUS RESTARTS AGE TIER
my-nginx-2035384211-j5fhi 1/1 Running 0 23m fe
my-nginx-2035384211-u2c7e 1/1 Running 0 23m fe
my-nginx-2035384211-u3t6x 1/1 Running 0 23m fe
这将输出所有 "app=nginx" 的 Pod,并有一个额外的描述 Pod 的 tier 的标签列
(用参数 -L
或者 --label-columns
标明)。
想要了解更多信息,请参考
标签 和
kubectl label
命令文档。
更新注解
有时,你可能希望将注解附加到资源中。注解是 API 客户端(如工具、库等)
用于检索的任意非标识元数据。这可以通过 kubectl annotate
来完成。例如:
kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
annotations:
description: my frontend running nginx
...
想要了解更多信息,请参考
注解和
kubectl annotate
命令文档。
扩缩你的应用
当应用上的负载增长或收缩时,使用 kubectl
能够实现应用规模的扩缩。
例如,要将 nginx 副本的数量从 3 减少到 1,请执行以下操作:
kubectl scale deployment/my-nginx --replicas=1
deployment.extensions/my-nginx scaled
现在,你的 Deployment 管理的 Pod 只有一个了。
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-2035384211-j5fhi 1/1 Running 0 30m
想要让系统自动选择需要 nginx 副本的数量,范围从 1 到 3,请执行以下操作:
kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled
现在,你的 nginx 副本将根据需要自动地增加或者减少。
想要了解更多信息,请参考
kubectl scale命令文档、
kubectl autoscale 命令文档和
水平 Pod 自动伸缩 文档。
就地更新资源
有时,有必要对你所创建的资源进行小范围、无干扰地更新。
kubectl apply
建议在源代码管理中维护一组配置文件
(参见配置即代码),
这样,它们就可以和应用代码一样进行维护和版本管理。
然后,你可以用 kubectl apply
将配置变更应用到集群中。
这个命令将会把推送的版本与以前的版本进行比较,并应用你所做的更改,
但是不会自动覆盖任何你没有指定更改的属性。
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured
注意,kubectl apply
将为资源增加一个额外的注解,以确定自上次调用以来对配置的更改。
执行时,kubectl apply
会在以前的配置、提供的输入和资源的当前配置之间
找出三方差异,以确定如何修改资源。
目前,新创建的资源是没有这个注解的,所以,第一次调用 kubectl apply
时
将使用提供的输入和资源的当前配置双方之间差异进行比较。
在第一次调用期间,它无法检测资源创建时属性集的删除情况。
因此,kubectl 不会删除它们。
所有后续的 kubectl apply
操作以及其他修改配置的命令,如 kubectl replace
和 kubectl edit
,都将更新注解,并允许随后调用的 kubectl apply
使用三方差异进行检查和执行删除。
说明: 想要使用 apply,请始终使用 kubectl apply
或 kubectl create --save-config
创建资源。
kubectl edit
或者,你也可以使用 kubectl edit
更新资源:
kubectl edit deployment/my-nginx
这相当于首先 get
资源,在文本编辑器中编辑它,然后用更新的版本 apply
资源:
kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# do some edit, and then save the file
kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured
rm /tmp/nginx.yaml
这使你可以更加容易地进行更重大的更改。
请注意,可以使用 EDITOR
或 KUBE_EDITOR
环境变量来指定编辑器。
想要了解更多信息,请参考
kubectl edit 文档。
kubectl patch
你可以使用 kubectl patch
来更新 API 对象。此命令支持 JSON patch、
JSON merge patch、以及 strategic merge patch。 请参考
使用 kubectl patch 更新 API 对象
和
kubectl patch.
破坏性的更新
在某些情况下,你可能需要更新某些初始化后无法更新的资源字段,或者你可能只想立即进行递归更改,
例如修复 Deployment 创建的不正常的 Pod。若要更改这些字段,请使用 replace --force
,
它将删除并重新创建资源。在这种情况下,你可以修改原始配置文件:
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
在不中断服务的情况下更新应用
在某些时候,你最终需要更新已部署的应用,通常都是通过指定新的镜像或镜像标签,
如上面的金丝雀发布的场景中所示。kubectl
支持几种更新操作,
每种更新操作都适用于不同的场景。
我们将指导你通过 Deployment 如何创建和更新应用。
假设你正运行的是 1.14.2 版本的 nginx:
kubectl create deployment my-nginx --image=nginx:1.14.2
deployment.apps/my-nginx created
要更新到 1.16.1 版本,只需使用我们前面学到的 kubectl 命令将
.spec.template.spec.containers[0].image
从 nginx:1.14.2
修改为 nginx:1.16.1
。
kubectl edit deployment/my-nginx
没错,就是这样!Deployment 将在后台逐步更新已经部署的 nginx 应用。
它确保在更新过程中,只有一定数量的旧副本被开闭,并且只有一定基于所需 Pod 数量的新副本被创建。
想要了解更多细节,请参考 Deployment。
接下来
3 - 集群网络系统
集群网络系统是 Kubernetes 的核心部分,但是想要准确了解它的工作原理可是个不小的挑战。
下面列出的是网络系统的的四个主要问题:
- 高度耦合的容器间通信:这个已经被 Pods
和
localhost
通信解决了。
- Pod 间通信:这个是本文档的重点要讲述的。
- Pod 和服务间通信:这个已经在服务里讲述过了。
- 外部和服务间通信:这也已经在服务讲述过了。
Kubernetes 的宗旨就是在应用之间共享机器。
通常来说,共享机器需要两个应用之间不能使用相同的端口,但是在多个应用开发者之间
去大规模地协调端口是件很困难的事情,尤其是还要让用户暴露在他们控制范围之外的集群级别的问题上。
动态分配端口也会给系统带来很多复杂度 - 每个应用都需要设置一个端口的参数,
而 API 服务器还需要知道如何将动态端口数值插入到配置模块中,服务也需要知道如何找到对方等等。
与其去解决这些问题,Kubernetes 选择了其他不同的方法。
要了解 Kubernetes 网络模型,请参阅此处。
如何实现 Kubernetes 的网络模型
有很多种方式可以实现这种网络模型,本文档并不是对各种实现技术的详细研究,
但是希望可以作为对各种技术的详细介绍,并且成为你研究的起点。
接下来的网络技术是按照首字母排序,顺序本身并无其他意义。
说明:
本部分链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不负责这些项目。此页面遵循
CNCF 网站指南,按字母顺序列出项目。要将项目添加到此列表中,请在提交更改之前阅读
内容指南。
ACI
Cisco Application Centric Infrastructure
提供了一个集成覆盖网络和底层 SDN 的解决方案来支持容器、虚拟机和其他裸机服务器。
ACI 为 ACI 提供了容器网络集成。
点击这里查看概述。
Antrea
Antrea 项目是一个开源的联网解决方案,旨在成为
Kubernetes 原生的网络解决方案。它利用 Open vSwitch 作为网络数据平面。
Open vSwitch 是一个高性能可编程的虚拟交换机,支持 Linux 和 Windows 平台。
Open vSwitch 使 Antrea 能够以高性能和高效的方式实现 Kubernetes 的网络策略。
借助 Open vSwitch 可编程的特性,Antrea 能够在 Open vSwitch 之上实现广泛的联网、安全功能和服务。
Kubernetes 的 AWS VPC CNI
AWS VPC CNI 为 Kubernetes 集群提供了集成的
AWS 虚拟私有云(VPC)网络。该 CNI 插件提供了高吞吐量和可用性,低延迟以及最小的网络抖动。
此外,用户可以使用现有的 AWS VPC 网络和安全最佳实践来构建 Kubernetes 集群。
这包括使用 VPC 流日志、VPC 路由策略和安全组进行网络流量隔离的功能。
使用该 CNI 插件,可使 Kubernetes Pod 拥有与在 VPC 网络上相同的 IP 地址。
CNI 将 AWS 弹性网络接口(ENI)分配给每个 Kubernetes 节点,并将每个 ENI 的辅助 IP 范围用于该节点上的 Pod 。
CNI 包含用于 ENI 和 IP 地址的预分配的控件,以便加快 Pod 的启动时间,并且能够支持多达 2000 个节点的大型集群。
此外,CNI 可以与
用于执行网络策略的 Calico 一起运行。
AWS VPC CNI 项目是开源的,请查看 GitHub 上的文档。
Kubernetes 的 Azure CNI
Azure CNI
是一个开源插件,
将 Kubernetes Pods 和 Azure 虚拟网络(也称为 VNet)集成在一起,可提供与 VM 相当的网络性能。
Pod 可以通过 Express Route 或者 站点到站点的 VPN 来连接到对等的 VNet ,
也可以从这些网络来直接访问 Pod。Pod 可以访问受服务端点或者受保护链接的 Azure 服务,比如存储和 SQL。
你可以使用 VNet 安全策略和路由来筛选 Pod 流量。
该插件通过利用在 Kubernetes 节点的网络接口上预分配的辅助 IP 池将 VNet 分配给 Pod 。
Azure CNI 可以在
Azure Kubernetes Service (AKS) 中获得。
Calico
Calico 是一个开源的联网及网络安全方案,
用于基于容器、虚拟机和本地主机的工作负载。
Calico 支持多个数据面,包括:纯 Linux eBPF 的数据面、标准的 Linux 联网数据面
以及 Windows HNS 数据面。Calico 在提供完整的联网堆栈的同时,还可与
云驱动 CNIs 联合使用,以保证网络策略实施。
Cilium
Cilium 是一个开源软件,用于提供并透明保护应用容器间的网络连接。
Cilium 支持 L7/HTTP,可以在 L3-L7 上通过使用与网络分离的基于身份的安全模型寻址来实施网络策略,
并且可以与其他 CNI 插件结合使用。
华为的 CNI-Genie
CNI-Genie 是一个 CNI 插件,
可以让 Kubernetes 在运行时使用不同的网络模型的
实现同时被访问。
这包括以
CNI 插件运行的任何实现,比如
Flannel、
Calico、
Weave-net。
CNI-Genie 还支持将多个 IP 地址分配给 Pod,
每个都来自不同的 CNI 插件。
cni-ipvlan-vpc-k8s
cni-ipvlan-vpc-k8s
包含了一组 CNI 和 IPAM 插件来提供一个简单的、本地主机、低延迟、高吞吐量
以及通过使用 Amazon 弹性网络接口(ENI)并使用 Linux 内核的 IPv2 驱动程序
以 L2 模式将 AWS 管理的 IP 绑定到 Pod 中,
在 Amazon Virtual Private Cloud(VPC)环境中为 Kubernetes 兼容的网络堆栈。
这些插件旨在直接在 VPC 中进行配置和部署,Kubelets 先启动,
然后根据需要进行自我配置和扩展它们的 IP 使用率,而无需经常建议复杂的管理
覆盖网络、BGP、禁用源/目标检查或调整 VPC 路由表以向每个主机提供每个实例子网的
复杂性(每个 VPC 限制为50-100个条目)。
简而言之,cni-ipvlan-vpc-k8s 大大降低了在 AWS 中大规模部署 Kubernetes 所需的网络复杂性。
Coil
Coil 是一个为易于集成、提供灵活的出站流量网络而设计的 CNI 插件。
与裸机相比,Coil 的额外操作开销低,并允许针对外部网络的出站流量任意定义 NAT 网关。
Contiv-VPP
Contiv-VPP 是用于 Kubernetes 的用户空间、面向性能的网络插件,使用 fd.io 数据平面。
Contrail/Tungsten Fabric
Contrail
是基于 Tungsten Fabric 的,真正开放的多云网络虚拟化和策略管理平台。
Contrail 和 Tungsten Fabric 与各种编排系统集成在一起,例如 Kubernetes、OpenShift、OpenStack 和 Mesos,
并为虚拟机、容器或 Pods 以及裸机工作负载提供了不同的隔离模式。
DANM
DANM 是一个针对在 Kubernetes 集群中运行的电信工作负载的网络解决方案。
它由以下几个组件构成:
- 能够配置具有高级功能的 IPVLAN 接口的 CNI 插件
- 一个内置的 IPAM 模块,能够管理多个、群集内的、不连续的 L3 网络,并按请求提供动态、静态或无 IP 分配方案
- CNI 元插件能够通过自己的 CNI 或通过将任务授权给其他任何流行的 CNI 解决方案(例如 SRI-OV 或 Flannel)来实现将多个网络接口连接到容器
- Kubernetes 控制器能够集中管理所有 Kubernetes 主机的 VxLAN 和 VLAN 接口
- 另一个 Kubernetes 控制器扩展了 Kubernetes 的基于服务的服务发现概念,以在 Pod 的所有网络接口上工作
通过这个工具集,DANM 可以提供多个分离的网络接口,可以为 Pod 使用不同的网络后端和高级 IPAM 功能。
Flannel
Flannel 是一个非常简单的能够满足
Kubernetes 所需要的覆盖网络。已经有许多人报告了使用 Flannel 和 Kubernetes 的成功案例。
Hybridnet
Hybridnet 是一个为混合云设计的开源 CNI 插件,
它为一个或多个集群中的容器提供覆盖和底层网络。 Overlay 和 underlay 容器可以在同一个节点上运行,
并具有集群范围的双向网络连接。
Jaguar
Jaguar 是一个基于 OpenDaylight 的 Kubernetes 网络开源解决方案。
Jaguar 使用 vxlan 提供覆盖网络,而 Jaguar CNIPlugin 为每个 Pod 提供一个 IP 地址。
k-vswitch
k-vswitch 是一个基于
Open vSwitch 的简易 Kubernetes 网络插件。
它利用 Open vSwitch 中现有的功能来提供强大的网络插件,该插件易于操作,高效且安全。
Knitter
Knitter 是一个支持 Kubernetes 中实现多个网络系统的解决方案。
它提供了租户管理和网络管理的功能。除了多个网络平面外,Knitter 还包括一组端到端的 NFV 容器网络解决方案,
例如为应用程序保留 IP 地址、IP 地址迁移等。
Kube-OVN
Kube-OVN 是一个基于 OVN 的用于企业的 Kubernetes 网络架构。
借助于 OVN/OVS ,它提供了一些高级覆盖网络功能,例如子网、QoS、静态 IP 分配、流量镜像、网关、
基于 openflow 的网络策略和服务代理。
Kube-router
Kube-router 是 Kubernetes 的专用网络解决方案,
旨在提供高性能和易操作性。
Kube-router 提供了一个基于 Linux LVS/IPVS
的服务代理、一个基于 Linux 内核转发的无覆盖 Pod-to-Pod 网络解决方案和基于 iptables/ipset 的网络策略执行器。
L2 networks and linux bridging
如果你具有一个“哑”的L2网络,例如“裸机”环境中的简单交换机,则应该能够执行与上述 GCE 设置类似的操作。
请注意,这些说明仅是非常简单的尝试过-似乎可行,但尚未经过全面测试。
如果您使用此技术并完善了流程,请告诉我们。
根据 Lars Kellogg-Stedman 的这份非常不错的“Linux 网桥设备”
使用说明来进行操作。
Multus (a Multi Network plugin)
Multus 是一个多 CNI 插件,
使用 Kubernetes 中基于 CRD 的网络对象来支持实现 Kubernetes 多网络系统。
Multus 支持所有参考插件(比如:
Flannel、
DHCP、
Macvlan )
来实现 CNI 规范和第三方插件(比如:
Calico、
Weave、
Cilium、
Contiv)。
除此之外, Multus 还支持
SRIOV、
DPDK、
OVS-DPDK & VPP 的工作负载,
以及 Kubernetes 中基于云的本机应用程序和基于 NFV 的应用程序。
NSX-T
VMware NSX-T 是一个网络虚拟化和安全平台。
NSX-T 可以为多云及多系统管理程序环境提供网络虚拟化,并专注于具有异构端点和技术堆栈的新兴应用程序框架和体系结构。
除了 vSphere 管理程序之外,这些环境还包括其他虚拟机管理程序,例如 KVM、容器和裸机。
NSX-T Container Plug-in (NCP)
提供了 NSX-T 与容器协调器(例如 Kubernetes)之间的结合,
以及 NSX-T 与基于容器的 CaaS/PaaS 平台(例如 Pivotal Container Service(PKS)和 OpenShift)之间的集成。
OVN (开放式虚拟网络)
OVN 是一个由 Open vSwitch 社区开发的开源的网络虚拟化解决方案。
它允许创建逻辑交换器、逻辑路由、状态 ACL、负载均衡等等来建立不同的虚拟网络拓扑。
该项目有一个特定的Kubernetes插件和文档 ovn-kubernetes。
Weaveworks 的 Weave Net
Weave Net 是 Kubernetes 及其
托管应用程序的弹性且易于使用的网络系统。
Weave Net 可以作为 CNI 插件 运行或者独立运行。
在这两种运行方式里,都不需要任何配置或额外的代码即可运行,并且在两种情况下,
网络都为每个 Pod 提供一个 IP 地址 -- 这是 Kubernetes 的标准配置。
接下来
网络模型的早期设计、运行原理以及未来的一些计划,都在
联网设计文档
里有更详细的描述。
4 - Kubernetes 系统组件指标
通过系统组件指标可以更好地了解系统组个内部发生的情况。系统组件指标对于构建仪表板和告警特别有用。
Kubernetes 组件以 Prometheus 格式
生成度量值。
这种格式是结构化的纯文本,旨在使人和机器都可以阅读。
Kubernetes 中组件的指标
在大多数情况下,可以通过 HTTP 访问组件的 /metrics
端点来获取组件的度量值。
对于那些默认情况下不暴露端点的组件,可以使用 --bind-address
标志启用。
这些组件的示例:
在生产环境中,你可能需要配置 Prometheus 服务器 或
某些其他指标搜集器以定期收集这些指标,并使它们在某种时间序列数据库中可用。
请注意,kubelet 还会在 /metrics/cadvisor
,
/metrics/resource
和 /metrics/probes
端点中公开度量值。这些度量值的生命周期各不相同。
如果你的集群使用了 RBAC,
则读取指标需要通过基于用户、组或 ServiceAccount 的鉴权,要求具有允许访问
/metrics
的 ClusterRole。
例如:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- nonResourceURLs:
- "/metrics"
verbs:
- get
指标生命周期
Alpha 指标 → 稳定的指标 → 弃用的指标 → 隐藏的指标 → 删除的指标
Alpha 指标没有稳定性保证。这些指标可以随时被修改或者删除。
稳定的指标可以保证不会改变。这意味着:
- 稳定的、不包含已弃用(deprecated)签名的指标不会被删除(或重命名)
- 稳定的指标的类型不会被更改
已弃用的指标最终将被删除,不过仍然可用。
这类指标包含注解,标明其被废弃的版本。
例如:
隐藏的指标不会再被发布以供抓取,但仍然可用。
要使用隐藏指标,请参阅显式隐藏指标节。
删除的指标不再被发布,亦无法使用。
显示隐藏指标
如上所述,管理员可以通过设置可执行文件的命令行参数来启用隐藏指标,
如果管理员错过了上一版本中已经弃用的指标的迁移,则可以把这个用作管理员的逃生门。
show-hidden-metrics-for-version
标志接受版本号作为取值,版本号给出
你希望显示该发行版本中已弃用的指标。
版本表示为 x.y,其中 x 是主要版本,y 是次要版本。补丁程序版本不是必须的,
即使指标可能会在补丁程序发行版中弃用,原因是指标弃用策略规定仅针对次要版本。
该参数只能使用前一个次要版本。如果管理员将先前版本设置为 show-hidden-metrics-for-version
,
则先前版本中隐藏的度量值会再度生成。不允许使用过旧的版本,因为那样会违反指标弃用策略。
以指标 A
为例,此处假设 A
在 1.n 中已弃用。根据指标弃用策略,我们可以得出以下结论:
- 在版本
1.n
中,这个指标已经弃用,且默认情况下可以生成。
- 在版本
1.n+1
中,这个指标默认隐藏,可以通过命令行参数 show-hidden-metrics-for-version=1.n
来再度生成。
- 在版本
1.n+2
中,这个指标就将被从代码中移除,不会再有任何逃生窗口。
如果你要从版本 1.12
升级到 1.13
,但仍依赖于 1.12
中弃用的指标 A
,则应通过命令行设置隐藏指标:
--show-hidden-metrics=1.12
,并记住在升级到 1.14
版本之前删除此指标依赖项。
禁用加速器指标
kubelet 通过 cAdvisor 收集加速器指标。为了收集这些指标,对于 NVIDIA GPU 之类的加速器,
kubelet 在驱动程序上保持打开状态。这意味着为了执行基础结构更改(例如更新驱动程序),
集群管理员需要停止 kubelet 代理。
现在,收集加速器指标的责任属于供应商,而不是 kubelet。供应商必须提供一个收集指标的容器,
并将其公开给指标服务(例如 Prometheus)。
DisableAcceleratorUsageMetrics
特性门控
禁止由 kubelet 收集的指标。
关于何时会在默认情况下启用此功能也有一定规划。
组件指标
kube-controller-manager 指标
控制器管理器指标可提供有关控制器管理器性能和运行状况的重要洞察。
这些指标包括通用的 Go 语言运行时指标(例如 go_routine 数量)和控制器特定的度量指标,
例如可用于评估集群运行状况的 etcd 请求延迟或云提供商(AWS、GCE、OpenStack)的 API 延迟等。
从 Kubernetes 1.7 版本开始,详细的云提供商指标可用于 GCE、AWS、Vsphere 和 OpenStack 的存储操作。
这些指标可用于监控持久卷操作的运行状况。
比如,对于 GCE,这些指标称为:
cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}
kube-scheduler 指标
FEATURE STATE: Kubernetes v1.21 [beta]
调度器会暴露一些可选的指标,报告所有运行中 Pods 所请求的资源和期望的约束值。
这些指标可用来构造容量规划监控面板、访问调度约束的当前或历史数据、
快速发现因为缺少资源而无法被调度的负载,或者将 Pod 的实际资源用量
与其请求值进行比较。
kube-scheduler 组件能够辩识各个 Pod 所配置的资源
请求和约束。
在 Pod 的资源请求值或者约束值非零时,kube-scheduler 会以度量值时间序列的形式
生成报告。该时间序列值包含以下标签:
- 名字空间
- Pod 名称
- Pod 调度所处节点,或者当 Pod 未被调度时用空字符串表示
- 优先级
- 为 Pod 所指派的调度器
- 资源的名称(例如,
cpu
)
- 资源的单位,如果知道的话(例如,
cores
)
一旦 Pod 进入完成状态(其 restartPolicy
为 Never
或 OnFailure
,且
其处于 Succeeded
或 Failed
Pod 阶段,或者已经被删除且所有容器都具有
终止状态),该时间序列停止报告,因为调度器现在可以调度其它 Pod 来执行。
这两个指标称作 kube_pod_resource_request
和 kube_pod_resource_limit
。
指标暴露在 HTTP 端点 /metrics/resources
,与调度器上的 /metrics
端点
一样要求相同的访问授权。你必须使用
--show-hidden-metrics-for-version=1.20
标志才能暴露那些稳定性为 Alpha
的指标。
禁用指标
你可以通过命令行标志 --disabled-metrics
来关闭某指标。
在例如某指标会带来性能问题的情况下,这一操作可能是有用的。
标志的参数值是一组被禁止的指标(例如:--disabled-metrics=metric1,metric2
)。
指标顺序性保证
在 Alpha 阶段,标志只能接受一组映射值作为可以使用的指标标签。
每个映射值的格式为<指标名称>,<标签名称>=<可用标签列表>
,其中
<可用标签列表>
是一个用逗号分隔的、可接受的标签名的列表。
最终的格式看起来会是这样:
--allow-label-value <指标名称>,<标签名称>='<可用值1>,<可用值2>...', <指标名称2>,<标签名称>='<可用值1>, <可用值2>...', ...
.
下面是一个例子:
--allow-label-value number_count_metric,odd_number='1,3,5', number_count_metric,even_number='2,4,6', date_gauge_metric,weekend='Saturday,Sunday'
接下来
5 - 日志架构
应用日志可以让你了解应用内部的运行状况。日志对调试问题和监控集群活动非常有用。
大部分现代化应用都有某种日志记录机制。同样地,容器引擎也被设计成支持日志记录。
针对容器化应用,最简单且最广泛采用的日志记录方式就是写入标准输出和标准错误流。
但是,由容器引擎或运行时提供的原生功能通常不足以构成完整的日志记录方案。
例如,如果发生容器崩溃、Pod 被逐出或节点宕机等情况,你可能想访问应用日志。
在集群中,日志应该具有独立的存储和生命周期,与节点、Pod 或容器的生命周期相独立。
这个概念叫 集群级的日志 。
集群级日志架构需要一个独立的后端用来存储、分析和查询日志。
Kubernetes 并不为日志数据提供原生的存储解决方案。
相反,有很多现成的日志方案可以集成到 Kubernetes 中。
下面各节描述如何在节点上处理和存储日志。
Kubernetes 中的基本日志记录
这里的示例使用包含一个容器的 Pod 规约,每秒钟向标准输出写入数据。
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
args: [/bin/sh, -c,
'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
用下面的命令运行 Pod:
kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml
输出结果为:
pod/counter created
像下面这样,使用 kubectl logs
命令获取日志:
输出结果为:
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
你可以使用命令 kubectl logs --previous
检索之前容器实例的日志。
如果 Pod 中有多个容器,你应该为该命令附加容器名以访问对应容器的日志。
详见 kubectl logs
文档。
如果 Pod 有多个容器,你应该为该命令附加容器名以访问对应容器的日志,
使用 -c
标志来指定要访问的容器的日志,如下所示:
kubectl logs counter -c count
详见 kubectl logs 文档。
节点级日志记录
容器化应用写入 stdout
和 stderr
的任何数据,都会被容器引擎捕获并被重定向到某个位置。
例如,Docker 容器引擎将这两个输出流重定向到某个
日志驱动(Logging Driver) ,
该日志驱动在 Kubernetes 中配置为以 JSON 格式写入文件。
说明: Docker JSON 日志驱动将日志的每一行当作一条独立的消息。
该日志驱动不直接支持多行消息。你需要在日志代理级别或更高级别处理多行消息。
默认情况下,如果容器重启,kubelet 会保留被终止的容器日志。
如果 Pod 在工作节点被驱逐,该 Pod 中所有的容器也会被驱逐,包括容器日志。
节点级日志记录中,需要重点考虑实现日志的轮转,以此来保证日志不会消耗节点上全部可用空间。
Kubernetes 并不负责轮转日志,而是通过部署工具建立一个解决问题的方案。
例如,在用 kube-up.sh
部署的 Kubernetes 集群中,存在一个
logrotate
,每小时运行一次。
你也可以设置容器运行时来自动地轮转应用日志。
例如,你可以找到关于 kube-up.sh
为 GCP 环境的 COS 镜像设置日志的详细信息,
脚本为
configure-helper
脚本。
当使用某 CRI 容器运行时 时,kubelet 要负责对日志进行轮换,并
管理日志目录的结构。kubelet 将此信息发送给 CRI 容器运行时,后者
将容器日志写入到指定的位置。在 kubelet 配置文件
中的两个 kubelet 参数
containerLogMaxSize
和 containerLogMaxFiles
可以用来配置每个日志文件的最大长度和每个容器可以生成的日志文件个数上限。
当运行 kubectl logs
时,
节点上的 kubelet 处理该请求并直接读取日志文件,同时在响应中返回日志文件内容。
说明: 如果有外部系统执行日志轮转或者使用了 CRI 容器运行时,那么 kubectl logs
仅可查询到最新的日志内容。
比如,对于一个 10MB 大小的文件,通过 logrotate
执行轮转后生成两个文件,
一个 10MB 大小,一个为空,kubectl logs
返回最新的日志文件,而该日志文件
在这个例子中为空。
系统组件日志
系统组件有两种类型:在容器中运行的和不在容器中运行的。例如:
- 在容器中运行的 kube-scheduler 和 kube-proxy。
- 不在容器中运行的 kubelet 和容器运行时。
在使用 systemd 机制的服务器上,kubelet 和容器容器运行时将日志写入到 journald 中。
如果没有 systemd,它们将日志写入到 /var/log
目录下的 .log
文件中。
容器中的系统组件通常将日志写到 /var/log
目录,绕过了默认的日志机制。
他们使用 klog 日志库。
你可以在日志开发文档
找到这些组件的日志告警级别约定。
和容器日志类似,/var/log
目录中的系统组件日志也应该被轮转。
通过脚本 kube-up.sh
启动的 Kubernetes 集群中,日志被工具 logrotate
执行每日轮转,或者日志大小超过 100MB 时触发轮转。
集群级日志架构
虽然Kubernetes没有为集群级日志记录提供原生的解决方案,但你可以考虑几种常见的方法。
以下是一些选项:
- 使用在每个节点上运行的节点级日志记录代理。
- 在应用程序的 Pod 中,包含专门记录日志的边车(Sidecar)容器。
- 将日志直接从应用程序中推送到日志记录后端。
使用节点级日志代理
你可以通过在每个节点上使用 节点级的日志记录代理 来实现群集级日志记录。
日志记录代理是一种用于暴露日志或将日志推送到后端的专用工具。
通常,日志记录代理程序是一个容器,它可以访问包含该节点上所有应用程序容器的日志文件的目录。
由于日志记录代理必须在每个节点上运行,通常可以用 DaemonSet
的形式运行该代理。
节点级日志在每个节点上仅创建一个代理,不需要对节点上的应用做修改。
容器向标准输出和标准错误输出写出数据,但在格式上并不统一。
节点级代理
收集这些日志并将其进行转发以完成汇总。
使用 sidecar 容器运行日志代理
你可以通过以下方式之一使用边车(Sidecar)容器:
- 边车容器将应用程序日志传送到自己的标准输出。
- 边车容器运行一个日志代理,配置该日志代理以便从应用容器收集日志。
传输数据流的 sidecar 容器
利用边车容器向自己的 stdout
和 stderr
传输流的方式,
你就可以利用每个节点上的 kubelet 和日志代理来处理日志。
边车容器从文件、套接字或 journald 读取日志。
每个边车容器向自己的 stdout
和 stderr
流中输出日志。
这种方法允许你将日志流从应用程序的不同部分分离开,其中一些可能缺乏对写入
stdout
或 stderr
的支持。重定向日志背后的逻辑是最小的,因此它的开销几乎可以忽略不计。
另外,因为 stdout
、stderr
由 kubelet 处理,你可以使用内置的工具 kubectl logs
。
例如,某 Pod 中运行一个容器,该容器向两个文件写不同格式的日志。
下面是这个 pod 的配置文件:
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
不建议在同一个日志流中写入不同格式的日志条目,即使你成功地将其重定向到容器的
stdout
流。相反,你可以创建两个边车容器。每个边车容器可以从共享卷
跟踪特定的日志文件,并将文件内容重定向到各自的 stdout
流。
下面是运行两个边车容器的 Pod 的配置文件:
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-1
image: busybox:1.28
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-2
image: busybox:1.28
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
现在当你运行这个 Pod 时,你可以运行如下命令分别访问每个日志流:
kubectl logs counter count-log-1
输出为:
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
kubectl logs counter count-log-2
输出为:
Mon Jan 1 00:00:00 UTC 2001 INFO 0
Mon Jan 1 00:00:01 UTC 2001 INFO 1
Mon Jan 1 00:00:02 UTC 2001 INFO 2
...
集群中安装的节点级代理会自动获取这些日志流,而无需进一步配置。
如果你愿意,你也可以配置代理程序来解析源容器的日志行。
注意,尽管 CPU 和内存使用率都很低(以多个 CPU 毫核指标排序或者按内存的兆字节排序),
向文件写日志然后输出到 stdout
流仍然会成倍地增加磁盘使用率。
如果你的应用向单一文件写日志,通常最好设置 /dev/stdout
作为目标路径,
而不是使用流式的边车容器方式。
应用本身如果不具备轮转日志文件的功能,可以通过边车容器实现。
该方式的一个例子是运行一个小的、定期轮转日志的容器。
然而,还是推荐直接使用 stdout
和 stderr
,将日志的轮转和保留策略
交给 kubelet。
具有日志代理功能的边车容器
如果节点级日志记录代理程序对于你的场景来说不够灵活,你可以创建一个
带有单独日志记录代理的边车容器,将代理程序专门配置为与你的应用程序一起运行。
说明:
在边车容器中使用日志代理会带来严重的资源损耗。
此外,你不能使用 kubectl logs
命令访问日志,因为日志并没有被 kubelet 管理。
下面是两个配置文件,可以用来实现一个带日志代理的边车容器。
第一个文件包含用来配置 fluentd 的
ConfigMap。
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
data:
fluentd.conf: |
<source>
type tail
format none
path /var/log/1.log
pos_file /var/log/1.log.pos
tag count.format1
</source>
<source>
type tail
format none
path /var/log/2.log
pos_file /var/log/2.log.pos
tag count.format2
</source>
<match **>
type google_cloud
</match>
第二个文件描述了运行 fluentd 边车容器的 Pod 。
flutend 通过 Pod 的挂载卷获取它的配置数据。
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox:1.28
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-agent
image: k8s.gcr.io/fluentd-gcp:1.30
env:
- name: FLUENTD_ARGS
value: -c /etc/fluentd-config/fluentd.conf
volumeMounts:
- name: varlog
mountPath: /var/log
- name: config-volume
mountPath: /etc/fluentd-config
volumes:
- name: varlog
emptyDir: {}
- name: config-volume
configMap:
name: fluentd-config
在示例配置中,你可以将 fluentd 替换为任何日志代理,从应用容器内
的任何来源读取数据。
从应用中直接暴露日志目录
从各个应用中直接暴露和推送日志数据的集群日志机制
已超出 Kubernetes 的范围。
6 - 系统日志
系统组件的日志记录集群中发生的事件,这对于调试非常有用。
你可以配置日志的精细度,以展示更多或更少的细节。
日志可以是粗粒度的,如只显示组件内的错误,
也可以是细粒度的,如显示事件的每一个跟踪步骤(比如 HTTP 访问日志、pod 状态更新、控制器动作或调度器决策)。
Klog
klog 是 Kubernetes 的日志库。
klog
为 Kubernetes 系统组件生成日志消息。
有关 klog 配置的更多信息,请参见命令行工具参考。
klog 原始格式的示例:
I1025 00:15:15.525108 1 httplog.go:79] GET /api/v1/namespaces/kube-system/pods/metrics-server-v0.3.1-57c75779f-9p8wg: (1.512ms) 200 [pod_nanny/v0.0.0 (linux/amd64) kubernetes/$Format 10.56.1.19:51756]
结构化日志
FEATURE STATE: Kubernetes v1.19 [alpha]
警告: 到结构化日志消息的迁移是一个持续的过程。
在此版本中,并非所有日志消息都是结构化的。
解析日志文件时,你也必须要处理非结构化日志消息。
日志格式和值的序列化可能会发生变化。
结构化日志记录旨在日志消息中引入统一结构,以便以编程方式提取信息。
你可以方便地用更小的开销来处理结构化日志。
新的消息格式向后兼容,并默认启用。
结构化日志的格式:
<klog header> "<message>" <key1>="<value1>" <key2>="<value2>" ...
示例:
I1025 00:15:15.525108 1 controller_utils.go:116] "Pod status updated" pod="kube-system/kubedns" status="ready"
JSON 日志格式
FEATURE STATE: Kubernetes v1.19 [alpha]
警告: JSON 输出并不支持太多标准 klog 参数。
对于不受支持的 klog 参数的列表,请参见
命令行工具参考。
并不是所有日志都保证写成 JSON 格式(例如,在进程启动期间)。
如果你打算解析日志,请确保可以处理非 JSON 格式的日志行。
字段名和 JSON 序列化可能会发生变化。
--logging-format=json
参数将日志格式从 klog 原生格式改为 JSON 格式。
JSON 日志格式示例(美化输出):
{
"ts": 1580306777.04728,
"v": 4,
"msg": "Pod status updated",
"pod":{
"name": "nginx-1",
"namespace": "default"
},
"status": "ready"
}
具有特殊意义的 key:
ts
- Unix 时间风格的时间戳(必选项,浮点值)
v
- 精细度(必选项,整数,默认值 0)
err
- 错误字符串(可选项,字符串)
msg
- 消息(必选项,字符串)
当前支持JSON格式的组件列表:
日志清理
FEATURE STATE: Kubernetes v1.20 [alpha]
警告: 日志清理可能会导致大量的计算开销,因此不应启用在生产环境中。
--experimental-logging-sanitization
参数可用来启用 klog 清理过滤器。
如果启用后,将检查所有日志参数中是否有标记为敏感数据的字段(比如:密码,密钥,令牌),并且将阻止这些字段的记录。
当前支持日志清理的组件列表:
- kube-controller-manager
- kube-apiserver
- kube-scheduler
- kubelet
说明: 日志清理过滤器不会阻止用户工作负载日志泄漏敏感数据。
日志精细度级别
参数 -v
控制日志的精细度。增大该值会增大日志事件的数量。
减小该值可以减小日志事件的数量。
增大精细度会记录更多的不太严重的事件。
精细度设置为 0 时只记录关键(critical)事件。
日志位置
有两种类型的系统组件:运行在容器中的组件和不运行在容器中的组件。例如:
- Kubernetes 调度器和 kube-proxy 在容器中运行。
- kubelet 和容器运行时,例如 Docker,不在容器中运行。
在使用 systemd 的系统中,kubelet 和容器运行时写入 journald。
在别的系统中,日志写入 /var/log
目录下的 .log
文件中。
容器中的系统组件总是绕过默认的日志记录机制,写入 /var/log
目录下的 .log
文件。
与容器日志类似,你应该轮转 /var/log
目录下系统组件日志。
在 kube-up.sh
脚本创建的 Kubernetes 集群中,日志轮转由 logrotate
工具配置。
logrotate
工具,每天或者当日志大于 100MB 时,轮转日志。
接下来
7 - 追踪 Kubernetes 系统组件
FEATURE STATE: Kubernetes v1.22 [alpha]
系统组件追踪功能记录各个集群操作的时延信息和这些操作之间的关系。
Kubernetes 组件基于 gRPC 导出器的
OpenTelemetry 协议
发送追踪信息,并用
OpenTelemetry Collector
收集追踪信息,再将其转交给追踪系统的后台。
追踪信息的收集
关于收集追踪信息、以及使用收集器的完整指南,可参见
Getting Started with the OpenTelemetry Collector。
不过,还有一些特定于 Kubernetes 组件的事项值得注意。
默认情况下,Kubernetes 组件使用 gRPC 的 OTLP 导出器来导出追踪信息,将信息写到
IANA OpenTelemetry 端口。
举例来说,如果收集器以 Kubernetes 组件的边车模式运行,以下接收器配置会收集 spans 信息,并将它们写入到标准输出。
receivers:
otlp:
protocols:
grpc:
exporters:
# 用适合你后端环境的导出器替换此处的导出器
logging:
logLevel: debug
service:
pipelines:
traces:
receivers: [otlp]
exporters: [logging]
组件追踪
kube-apiserver 追踪
kube-apiserver 为传入的 HTTP 请求、传出到 webhook 和 etcd 的请求以及重入的请求生成 spans。
由于 kube-apiserver 通常是一个公开的端点,所以它通过出站的请求传播
W3C 追踪上下文,
但不使用入站请求的追踪上下文。
在 kube-apiserver 中启用追踪
要启用追踪特性,需要启用 kube-apiserver 上的 APIServerTracing
特性门控。
然后,使用 --tracing-config-file=<<配置文件路径>
为 kube-apiserver 提供追踪配置文件。
下面是一个示例配置,它为万分之一的请求记录 spans,并使用了默认的 OpenTelemetry 端口。
apiVersion: apiserver.config.k8s.io/v1alpha1
kind: TracingConfiguration
# default value
#endpoint: localhost:4317
samplingRatePerMillion: 100
有关 TracingConfiguration 结构体的更多信息,请参阅
API 服务器配置 API (v1alpha1)。
稳定性
追踪工具仍在积极开发中,未来它会以多种方式发生变化。
这些变化包括:span 名称、附加属性、检测端点等等。
此类特性在达到稳定版本之前,不能保证追踪工具的向后兼容性。
接下来
8 - Kubernetes 中的代理
本文讲述了 Kubernetes 中所使用的代理。
代理
用户在使用 Kubernetes 的过程中可能遇到几种不同的代理(proxy):
-
kubectl proxy:
- 运行在用户的桌面或 pod 中
- 从本机地址到 Kubernetes apiserver 的代理
- 客户端到代理使用 HTTP 协议
- 代理到 apiserver 使用 HTTPS 协议
- 指向 apiserver
- 添加认证头信息
-
apiserver proxy:
- 是一个建立在 apiserver 内部的“堡垒”
- 将集群外部的用户与群集 IP 相连接,这些IP是无法通过其他方式访问的
- 运行在 apiserver 进程内
- 客户端到代理使用 HTTPS 协议 (如果配置 apiserver 使用 HTTP 协议,则使用 HTTP 协议)
- 通过可用信息进行选择,代理到目的地可能使用 HTTP 或 HTTPS 协议
- 可以用来访问 Node、 Pod 或 Service
- 当用来访问 Service 时,会进行负载均衡
-
kube proxy:
- 在每个节点上运行
- 代理 UDP、TCP 和 SCTP
- 不支持 HTTP
- 提供负载均衡能力
- 只用来访问 Service
-
apiserver 之前的代理/负载均衡器:
- 在不同集群中的存在形式和实现不同 (如 nginx)
- 位于所有客户端和一个或多个 API 服务器之间
- 存在多个 API 服务器时,扮演负载均衡器的角色
-
外部服务的云负载均衡器:
- 由一些云供应商提供 (如 AWS ELB、Google Cloud Load Balancer)
- Kubernetes 服务类型为
LoadBalancer
时自动创建
- 通常仅支持 UDP/TCP 协议
- SCTP 支持取决于云供应商的负载均衡器实现
- 不同云供应商的云负载均衡器实现不同
Kubernetes 用户通常只需要关心前两种类型的代理,集群管理员通常需要确保后面几种类型的代理设置正确。
请求重定向
代理已经取代重定向功能,重定向功能已被弃用。
9 - API 优先级和公平性
FEATURE STATE: Kubernetes v1.20 [beta]
对于集群管理员来说,控制 Kubernetes API 服务器在过载情况下的行为是一项关键任务。
kube-apiserver
有一些控件(例如:命令行标志 --max-requests-inflight
和 --max-mutating-requests-inflight
),
可以限制将要接受的未处理的请求,从而防止过量请求入站,潜在导致 API 服务器崩溃。
但是这些标志不足以保证在高流量期间,最重要的请求仍能被服务器接受。
API 优先级和公平性(APF)是一种替代方案,可提升上述最大并发限制。
APF 以更细粒度的方式对请求进行分类和隔离。
它还引入了空间有限的排队机制,因此在非常短暂的突发情况下,API 服务器不会拒绝任何请求。
通过使用公平排队技术从队列中分发请求,这样,
一个行为不佳的 控制器
就不会饿死其他控制器(即使优先级相同)。
注意: 属于“长时间运行”类型的请求(主要是 watch)不受 API 优先级和公平性过滤器的约束。
如果未启用 APF 特性,即便设置 --max-requests-inflight
标志,该类请求也不受约束。
启用/禁用 API 优先级和公平性
API 优先级与公平性(APF)特性由特性门控控制,默认情况下启用。
有关特性门控的一般性描述以及如何启用和禁用特性门控,
请参见特性门控。
APF 的特性门控称为 APIPriorityAndFairness
。
此特性也与某个 API 组
相关:
(a) 一个 v1alpha1
版本,默认被禁用;
(b) 一个 v1beta1
版本,默认被启用。
你可以在启动 kube-apiserver
时,添加以下命令行标志来禁用此功能门控
及 v1beta1 API 组:
kube-apiserver \
--feature-gates=APIPriorityAndFairness=false \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta1=false \
# ...其他配置不变
或者,你也可以通过
--runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true
启用 API 组的 v1alpha1 版本。
命令行标志 --enable-priority-fairness=false
将彻底禁用 APF 特性,即使其他标志启用它也是无效。
概念
APF 特性包含几个不同的功能。
传入的请求通过 FlowSchema 按照其属性分类,并分配优先级。
每个优先级维护自定义的并发限制,加强了隔离度,这样不同优先级的请求,就不会相互饿死。
在同一个优先级内,公平排队算法可以防止来自不同 flow 的请求相互饿死。
该算法将请求排队,通过排队机制,防止在平均负载较低时,通信量突增而导致请求失败。
优先级
如果未启用 APF,API 服务器中的整体并发量将受到 kube-apiserver
的参数
--max-requests-inflight
和 --max-mutating-requests-inflight
的限制。
启用 APF 后,将对这些参数定义的并发限制进行求和,然后将总和分配到一组可配置的 优先级 中。
每个传入的请求都会分配一个优先级;每个优先级都有各自的配置,设定允许分发的并发请求数。
例如,默认配置包括针对领导者选举请求、内置控制器请求和 Pod 请求都单独设置优先级。
这表示即使异常的 Pod 向 API 服务器发送大量请求,也无法阻止领导者选举或内置控制器的操作执行成功。
排队
即使在同一优先级内,也可能存在大量不同的流量源。
在过载情况下,防止一个请求流饿死其他流是非常有价值的
(尤其是在一个较为常见的场景中,一个有故障的客户端会疯狂地向 kube-apiserver 发送请求,
理想情况下,这个有故障的客户端不应对其他客户端产生太大的影响)。
公平排队算法在处理具有相同优先级的请求时,实现了上述场景。
每个请求都被分配到某个 流 中,该 流 由对应的 FlowSchema 的名字加上一个
流区分项(Flow Distinguisher) 来标识。
这里的流区分项可以是发出请求的用户、目标资源的名称空间或什么都不是。
系统尝试为不同流中具有相同优先级的请求赋予近似相等的权重。
将请求划分到流中之后,APF 功能将请求分配到队列中。
分配时使用一种称为 混洗分片(Shuffle-Sharding)
的技术。
该技术可以相对有效地利用队列隔离低强度流与高强度流。
排队算法的细节可针对每个优先等级进行调整,并允许管理员在内存占用、
公平性(当总流量超标时,各个独立的流将都会取得进展)、
突发流量的容忍度以及排队引发的额外延迟之间进行权衡。
豁免请求
某些特别重要的请求不受制于此特性施加的任何限制。这些豁免可防止不当的流控配置完全禁用 API 服务器。
默认值
APF 特性附带推荐配置,该配置对实验场景应该足够;
如果你的集群有可能承受较大的负载,那么你应该考虑哪种配置最有效。
推荐配置将请求分为五个优先级:
system
优先级用于 system:nodes
组(即 Kubelets)的请求;
kubelets 必须能连上 API 服务器,以便工作负载能够调度到其上。
leader-election
优先级用于内置控制器的领导选举的请求
(特别是来自 kube-system
名称空间中 system:kube-controller-manager
和
system:kube-scheduler
用户和服务账号,针对 endpoints
、configmaps
或 leases
的请求)。
将这些请求与其他流量相隔离非常重要,因为领导者选举失败会导致控制器发生故障并重新启动,
这反过来会导致新启动的控制器在同步信息时,流量开销更大。
workload-high
优先级用于内置控制器的请求。
workload-low
优先级适用于来自任何服务帐户的请求,通常包括来自 Pods
中运行的控制器的所有请求。
global-default
优先级可处理所有其他流量,例如:非特权用户运行的交互式 kubectl
命令。
系统内置了两个 PriorityLevelConfiguration 和两个 FlowSchema,它们是不可重载的:
- 特殊的
exempt
优先级的请求完全不受流控限制:它们总是立刻被分发。
特殊的 exempt
FlowSchema 把 system:masters
组的所有请求都归入该优先级组。
如果合适,你可以定义新的 FlowSchema,将其他请求定向到该优先级。
- 特殊的
catch-all
优先级与特殊的 catch-all
FlowSchema 结合使用,以确保每个请求都分类。
一般地,你不应该依赖于 catch-all
的配置,而应适当地创建自己的 catch-all
FlowSchema 和 PriorityLevelConfigurations(或使用默认安装的 global-default
配置)。
为了帮助捕获部分请求未分类的配置错误,强制要求 catch-all
优先级仅允许一个并发份额,
并且不对请求进行排队,使得仅与 catch-all
FlowSchema 匹配的流量被拒绝的可能性更高,
并显示 HTTP 429 错误。
健康检查并发豁免
推荐配置没有为本地 kubelet 对 kube-apiserver 执行健康检查的请求进行任何特殊处理
——它们倾向于使用安全端口,但不提供凭据。
在推荐配置中,这些请求将分配 global-default
FlowSchema 和 global-default
优先级,
这样其他流量可以排除健康检查。
如果添加以下 FlowSchema,健康检查请求不受速率限制。
注意: 进行此更改后,任何敌对方都可以发送与此 FlowSchema 匹配的任意数量的健康检查请求。
如果你有 Web 流量过滤器或类似的外部安全机制保护集群的 API 服务器免受常规网络流量的侵扰,
则可以配置规则,阻止所有来自集群外部的健康检查请求。
apiVersion: flowcontrol.apiserver.k8s.io/v1alpha1
kind: FlowSchema
metadata:
name: health-for-strangers
spec:
matchingPrecedence: 1000
priorityLevelConfiguration:
name: exempt
rules:
- nonResourceRules:
- nonResourceURLs:
- "/healthz"
- "/livez"
- "/readyz"
verbs:
- "*"
subjects:
- kind: Group
group:
name: system:unauthenticated
资源
流控 API 涉及两种资源。
PriorityLevelConfigurations
定义隔离类型和可处理的并发预算量,还可以微调排队行为。
FlowSchemas
用于对每个入站请求进行分类,并与一个 PriorityLevelConfigurations 相匹配。
此外同一 API 组还有一个 v1alpha1
版本,其中包含语法和语义都相同的资源类别。
PriorityLevelConfiguration
一个 PriorityLevelConfiguration 表示单个隔离类型。每个 PriorityLevelConfigurations
对未完成的请求数有各自的限制,对排队中的请求数也有限制。
PriorityLevelConfigurations 的并发限制不是指定请求绝对数量,而是在“并发份额”中指定。
API 服务器的总并发量限制通过这些份额按例分配到现有 PriorityLevelConfigurations 中。
集群管理员可以更改 --max-requests-inflight
(或 --max-mutating-requests-inflight
)的值,
再重新启动 kube-apiserver
来增加或减小服务器的总流量,
然后所有的 PriorityLevelConfigurations 将看到其最大并发增加(或减少)了相同的比例。
注意: 启用 APF 功能后,服务器的总并发量限制将设置为
--max-requests-inflight
和 --max-mutating-requests-inflight
之和。
可变请求和不可变请求之间不再有任何区别;
如果对于某种资源,你需要区别对待不同请求,请创建不同的 FlowSchema 分别匹配可变请求和不可变请求。
当入站请求的数量大于分配的 PriorityLevelConfigurations 中允许的并发级别时, type
字段将确定对额外请求的处理方式。
Reject
类型,表示多余的流量将立即被 HTTP 429(请求过多)错误所拒绝。
Queue
类型,表示对超过阈值的请求进行排队,将使用阈值分片和公平排队技术来平衡请求流之间的进度。
公平排队算法支持通过排队配置对优先级微调。 可以在增强建议中阅读算法的详细信息,但总之:
queues
递增能减少不同流之间的冲突概率,但代价是增加了内存使用量。
值为 1 时,会禁用公平排队逻辑,但仍允许请求排队。
queueLengthLimit
递增可以在不丢弃任何请求的情况下支撑更大的突发流量,
但代价是增加了等待时间和内存使用量。
-
修改 handSize
允许你调整过载情况下不同流之间的冲突概率以及单个流可用的整体并发性。
说明: 较大的 handSize
使两个单独的流程发生碰撞的可能性较小(因此,一个流可以饿死另一个流),
但是更有可能的是少数流可以控制 apiserver。
较大的 handSize
还可能增加单个高并发流的延迟量。
单个流中可能排队的请求的最大数量为 handSize * queueLengthLimit
。
下表显示了有趣的随机分片配置集合,
每行显示给定的老鼠(低强度流)被不同数量的大象挤压(高强度流)的概率。
表来源请参阅: https://play.golang.org/p/Gi0PLgVHiUg
Example Shuffle Sharding Configurations
随机分片 |
队列数 |
1 个大象 |
4 个大象 |
16 个大象 |
12 |
32 |
4.428838398950118e-09 |
0.11431348830099144 |
0.9935089607656024 |
10 |
32 |
1.550093439632541e-08 |
0.0626479840223545 |
0.9753101519027554 |
10 |
64 |
6.601827268370426e-12 |
0.00045571320990370776 |
0.49999929150089345 |
9 |
64 |
3.6310049976037345e-11 |
0.00045501212304112273 |
0.4282314876454858 |
8 |
64 |
2.25929199850899e-10 |
0.0004886697053040446 |
0.35935114681123076 |
8 |
128 |
6.994461389026097e-13 |
3.4055790161620863e-06 |
0.02746173137155063 |
7 |
128 |
1.0579122850901972e-11 |
6.960839379258192e-06 |
0.02406157386340147 |
7 |
256 |
7.597695465552631e-14 |
6.728547142019406e-08 |
0.0006709661542533682 |
6 |
256 |
2.7134626662687968e-12 |
2.9516464018476436e-07 |
0.0008895654642000348 |
6 |
512 |
4.116062922897309e-14 |
4.982983350480894e-09 |
2.26025764343413e-05 |
6 |
1024 |
6.337324016514285e-16 |
8.09060164312957e-11 |
4.517408062903668e-07 |
FlowSchema
FlowSchema 匹配一些入站请求,并将它们分配给优先级。
每个入站请求都会对所有 FlowSchema 测试是否匹配,
首先从 matchingPrecedence
数值最低的匹配开始(我们认为这是逻辑上匹配度最高),
然后依次进行,直到首个匹配出现。
注意: 对一个请求来说,只有首个匹配的 FlowSchema 才有意义。
如果一个入站请求与多个 FlowSchema 匹配,则将基于 matchingPrecedence
值最高的请求进行筛选。
如果一个请求匹配多个 FlowSchema 且 matchingPrecedence
的值相同,则按 name
的字典序选择最小,
但是最好不要依赖它,而是确保不存在两个 FlowSchema 具有相同的 matchingPrecedence
值。
当给定的请求与某个 FlowSchema 的 rules
的其中一条匹配,那么就认为该请求与该 FlowSchema 匹配。
判断规则与该请求是否匹配,不仅要求该条规则的 subjects
字段至少存在一个与该请求相匹配,
而且要求该条规则的 resourceRules
或 nonResourceRules
(取决于传入请求是针对资源URL还是非资源URL)字段至少存在一个与该请求相匹配。
对于 subjects
中的 name
字段和资源和非资源规则的
verbs
,apiGroups
,resources
,namespaces
和 nonResourceURLs
字段,
可以指定通配符 *
来匹配任意值,从而有效地忽略该字段。
FlowSchema 的 distinguisherMethod.type
字段决定了如何把与该模式匹配的请求分散到各个流中。
可能是 ByUser
,在这种情况下,一个请求用户将无法饿死其他容量的用户;
或者是 ByNamespace
,在这种情况下,一个名称空间中的资源请求将无法饿死其它名称空间的资源请求;
或者它可以为空(或者可以完全省略 distinguisherMethod
),
在这种情况下,与此 FlowSchema 匹配的请求将被视为单个流的一部分。
资源和你的特定环境决定了如何选择正确一个 FlowSchema。
问题诊断
启用了 APF 的 API 服务器,它每个 HTTP 响应都有两个额外的 HTTP 头:
X-Kubernetes-PF-FlowSchema-UID
和 X-Kubernetes-PF-PriorityLevel-UID
,
注意与请求匹配的 FlowSchema 和已分配的优先级。
如果请求用户没有查看这些对象的权限,则这些 HTTP 头中将不包含 API 对象的名称,
因此在调试时,你可以使用类似如下的命令:
kubectl get flowschemas -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
kubectl get prioritylevelconfigurations -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
来获取 UID 到 FlowSchema 的名称和 UID 到 PriorityLevelConfigurations 的名称的映射。
可观察性
指标
说明: 在 Kubernetes v1.20 之前的版本中,标签 flow_schema
和 priority_level
的命名有时被写作 flowSchema
和 priorityLevel
,即存在不一致的情况。
如果你在运行 Kubernetes v1.19 或者更早版本,你需要参考你所使用的集群
版本对应的文档。
当你开启了 APF 后,kube-apiserver 会暴露额外指标。
监视这些指标有助于判断你的配置是否不当地限制了重要流量,
或者发现可能会损害系统健康的,行为不良的工作负载。
apiserver_flowcontrol_dispatched_requests_total
是一个计数器向量,
记录开始执行的请求数量(自服务器启动以来的累积值),
由标签 flow_schema
(表示与请求匹配的 FlowSchema)和
priority_level
(表示分配给该请求的优先级)来区分。
apiserver_current_inqueue_requests
是一个表向量,
记录最近排队请求数量的高水位线,
由标签 request_kind
分组,标签的值为 mutating
或 readOnly
。
这些高水位线表示在最近一秒钟内看到的最大数字。
它们补充说明了老的表向量 apiserver_current_inflight_requests
(该量保存了最后一个窗口中,正在处理的请求数量的高水位线)。
apiserver_flowcontrol_read_vs_write_request_count_samples
是一个直方图向量,
记录当前请求数量的观察值,
由标签 phase
(取值为 waiting
和 executing
)和 request_kind
(取值 mutating
和 readOnly
)拆分。定期以高速率观察该值。
apiserver_flowcontrol_read_vs_write_request_count_watermarks
是一个直方图向量,
记录请求数量的高/低水位线,
由标签 phase
(取值为 waiting
和 executing
)和 request_kind
(取值为 mutating
和 readOnly
)拆分;标签 mark
取值为 high
和 low
。
apiserver_flowcontrol_read_vs_write_request_count_samples
向量观察到有值新增,
则该向量累积。这些水位线显示了样本值的范围。
apiserver_flowcontrol_current_inqueue_requests
是一个表向量,
记录包含排队中的(未执行)请求的瞬时数量,
由标签 priorityLevel
和 flowSchema
拆分。
apiserver_flowcontrol_current_executing_requests
是一个表向量,
记录包含执行中(不在队列中等待)请求的瞬时数量,
由标签 priority_level
和 flow_schema
进一步区分。
apiserver_flowcontrol_request_concurrency_in_use
是一个规范向量,
包含占用座位的瞬时数量,由标签 priority_level
和 flow_schema
进一步区分。
apiserver_flowcontrol_priority_level_request_count_samples
是一个直方图向量,
记录当前请求的观测值,由标签 phase
(取值为waiting
和 executing
)和
priority_level
进一步区分。
每个直方图都会定期进行观察,直到相关类别的最后活动为止。观察频率高。
apiserver_flowcontrol_priority_level_request_count_watermarks
是一个直方图向量,
记录请求数的高/低水位线,由标签 phase
(取值为 waiting
和 executing
)和
priority_level
拆分;
标签 mark
取值为 high
和 low
。
apiserver_flowcontrol_priority_level_request_count_samples
向量观察到有值新增,
则该向量累积。这些水位线显示了样本值的范围。
apiserver_flowcontrol_request_concurrency_limit
是一个表向量,
记录并发限制的计算值(基于 API 服务器的总并发限制和 PriorityLevelConfigurations
的并发份额),并按标签 priority_level
进一步区分。
apiserver_flowcontrol_request_execution_seconds
是一个直方图向量,
记录请求实际执行需要花费的时间,
由标签 flow_schema
(表示与请求匹配的 FlowSchema )和
priority_level
(表示分配给该请求的优先级)进一步区分。
调试端点
启用 APF 特性后, kube-apiserver 会在其 HTTP/HTTPS 端口提供以下路径:
-
/debug/api_priority_and_fairness/dump_priority_levels
——
所有优先级及其当前状态的列表。你可以这样获取:
kubectl get --raw /debug/api_priority_and_fairness/dump_priority_levels
输出类似于:
PriorityLevelName, ActiveQueues, IsIdle, IsQuiescing, WaitingRequests, ExecutingRequests,
workload-low, 0, true, false, 0, 0,
global-default, 0, true, false, 0, 0,
exempt, <none>, <none>, <none>, <none>, <none>,
catch-all, 0, true, false, 0, 0,
system, 0, true, false, 0, 0,
leader-election, 0, true, false, 0, 0,
workload-high, 0, true, false, 0, 0,
-
/debug/api_priority_and_fairness/dump_queues
—— 所有队列及其当前状态的列表。
你可以这样获取:
kubectl get --raw /debug/api_priority_and_fairness/dump_queues
输出类似于:
PriorityLevelName, Index, PendingRequests, ExecutingRequests, VirtualStart,
workload-high, 0, 0, 0, 0.0000,
workload-high, 1, 0, 0, 0.0000,
workload-high, 2, 0, 0, 0.0000,
...
leader-election, 14, 0, 0, 0.0000,
leader-election, 15, 0, 0, 0.0000,
-
/debug/api_priority_and_fairness/dump_requests
——当前正在队列中等待的所有请求的列表。
你可以这样获取:
kubectl get --raw /debug/api_priority_and_fairness/dump_requests
输出类似于:
PriorityLevelName, FlowSchemaName, QueueIndex, RequestIndexInQueue, FlowDistingsher, ArriveTime,
exempt, <none>, <none>, <none>, <none>, <none>,
system, system-nodes, 12, 0, system:node:127.0.0.1, 2020-07-23T15:26:57.179170694Z,
针对每个优先级别,输出中还包含一条虚拟记录,对应豁免限制。
你可以使用以下命令获得更详细的清单:
kubectl get --raw '/debug/api_priority_and_fairness/dump_requests?includeRequestDetails=1'
输出类似于:
PriorityLevelName, FlowSchemaName, QueueIndex, RequestIndexInQueue, FlowDistingsher, ArriveTime, UserName, Verb, APIPath, Namespace, Name, APIVersion, Resource, SubResource,
system, system-nodes, 12, 0, system:node:127.0.0.1, 2020-07-23T15:31:03.583823404Z, system:node:127.0.0.1, create, /api/v1/namespaces/scaletest/configmaps,
system, system-nodes, 12, 1, system:node:127.0.0.1, 2020-07-23T15:31:03.594555947Z, system:node:127.0.0.1, create, /api/v1/namespaces/scaletest/configmaps,
接下来
有关API优先级和公平性的设计细节的背景信息,
请参阅增强建议。
你可以通过 SIG APIMachinery
或特性的 Slack 频道
提出建议和特性请求。
10 - 安装扩展(Addons)
说明:
本部分链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不负责这些项目。此页面遵循
CNCF 网站指南,按字母顺序列出项目。要将项目添加到此列表中,请在提交更改之前阅读
内容指南。
Add-ons 扩展了 Kubernetes 的功能。
本文列举了一些可用的 add-ons 以及到它们各自安装说明的链接。
每个 Add-ons 按字母顺序排序 - 顺序不代表任何优先地位。
网络和网络策略
- ACI 通过 Cisco ACI 提供集成的容器网络和安全网络。
- Antrea 在第 3/4 层执行操作,为 Kubernetes
提供网络连接和安全服务。Antrea 利用 Open vSwitch 作为网络的数据面。
- Calico
是一个安全的 L3 网络和网络策略驱动。
- Canal 结合 Flannel 和 Calico,提供网络和网络策略。
- Cilium 是一个 L3 网络和网络策略插件,能够透明的实施 HTTP/API/L7 策略。
同时支持路由(routing)和覆盖/封装(overlay/encapsulation)模式。
- CNI-Genie 使 Kubernetes 无缝连接到一种 CNI 插件,
例如:Flannel、Calico、Canal、Romana 或者 Weave。
- 基于 Tungsten Fabric 的
Contrail
是一个开源的多云网络虚拟化和策略管理平台,Contrail 和 Tungsten Fabric 与业务流程系统
(例如 Kubernetes、OpenShift、OpenStack和Mesos)集成在一起,
为虚拟机、容器或 Pod 以及裸机工作负载提供了隔离模式。
- Flannel
是一个可以用于 Kubernetes 的 overlay 网络提供者。
- Knitter 是为 kubernetes 提供复合网络解决方案的网络组件。
- Multus 是一个多插件,可在 Kubernetes 中提供多种网络支持,
以支持所有 CNI 插件(例如 Calico,Cilium,Contiv,Flannel),
而且包含了在 Kubernetes 中基于 SRIOV、DPDK、OVS-DPDK 和 VPP 的工作负载。
- OVN-Kubernetes 是一个 Kubernetes 网络驱动,
基于 OVN(Open Virtual Network)实现,是从 Open vSwitch (OVS)
项目衍生出来的虚拟网络实现。
OVN-Kubernetes 为 Kubernetes 提供基于覆盖网络的网络实现,包括一个基于 OVS 实现的负载均衡器
和网络策略。
- OVN4NFV-K8S-Plugin 是一个基于 OVN 的 CNI
控制器插件,提供基于云原生的服务功能链条(Service Function Chaining,SFC)、多种 OVN 覆盖
网络、动态子网创建、动态虚拟网络创建、VLAN 驱动网络、直接驱动网络,并且可以
驳接其他的多网络插件,适用于基于边缘的、多集群联网的云原生工作负载。
- NSX-T 容器插件(NCP)
提供了 VMware NSX-T 与容器协调器(例如 Kubernetes)之间的集成,以及 NSX-T 与基于容器的
CaaS / PaaS 平台(例如关键容器服务(PKS)和 OpenShift)之间的集成。
- Nuage
是一个 SDN 平台,可在 Kubernetes Pods 和非 Kubernetes 环境之间提供基于策略的联网,并具有可视化和安全监控。
- Romana 是一个 pod 网络的第三层解决方案,并支持
NetworkPolicy API。
Kubeadm add-on 安装细节可以在这里找到。
- Weave Net
提供在网络分组两端参与工作的网络和网络策略,并且不需要额外的数据库。
服务发现
- CoreDNS 是一种灵活的,可扩展的 DNS 服务器,可以
安装为集群内的 Pod 提供 DNS 服务。
可视化管理
基础设施
遗留 Add-ons
还有一些其它 add-ons 归档在已废弃的 cluster/addons 路径中。
维护完善的 add-ons 应该被链接到这里。欢迎提出 PRs!