pod 水平自动伸缩 (Horizontal Pod Autoscaling, HPA)
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让 service 中的 Pod 个数自动调整呢?这就有赖于 Horizontal Pod Autoscaling 了,顾名思义,使 Pod 水平自动缩放。这个 Object(跟 Pod、Deployment 一样都是 API resource)也是最能体现 kubernetes 之于传统运维价值的地方,不再需要手动扩容了,终于实现自动化了,还可以自定义指标,没准未来还可以通过人工智能自动进化呢!
HPA 属于 Kubernetes 中的autoscaling SIG(Special Interest Group),其下有两个 feature:
- Arbitrary/Custom Metrics in the Horizontal Pod Autoscaler#117
- Monitoring Pipeline Metrics HPA API #118
Kubernetes 自 1.2 版本引入 HPA 机制,到 1.6 版本之前一直是通过 kubelet 来获取监控指标来判断是否需要扩缩容,1.6 版本之后必须通过 API server、Heapseter 或者 kube-aggregator 来获取监控指标。
准入控制器 (Admission Controller)
准入控制器(Admission Controller)位于 API Server 中,在对象被持久化之前,准入控制器拦截对 API Server 的请求,一般用来做身份验证和授权。其中包含两个特殊的控制器:MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。分别作为配置的变异和验证准入控制 webhook。
变更(Mutating)准入控制:修改请求的对象
验证(Validating)准入控制:验证请求的对象
准入控制器是在 API Server 的启动参数重配置的。一个准入控制器可能属于以上两者中的一种,也可能两者都属于。当请求到达 API Server 的时候首先执行变更准入控制,然后再执行验证准入控制。
我们在部署 Kubernetes 集群的时候都会默认开启一系列准入控制器,如果没有设置这些准入控制器的话可以说你的 Kubernetes 集群就是在裸奔,应该只有集群管理员可以修改集群的准入控制器。
网络策略 (Network Policy)
网络策略说明一组 Pod
之间是如何被允许互相通信,以及如何与其它网络 Endpoint 进行通信。 NetworkPolicy
资源使用标签来选择 Pod
,并定义了一些规则,这些规则指明允许什么流量进入到选中的 Pod
上。
网络策略通过网络插件来实现,所以必须使用一种支持 NetworkPolicy 的网络方案(如 calico)—— 非 Controller 创建的资源,是不起作用的。
隔离的与未隔离的 Pod
默认 Pod 是未隔离的,它们可以从任何的源接收请求。 具有一个可以选择 Pod 的网络策略后,Pod 就会变成隔离的。 一旦 Namespace 中配置的网络策略能够选择一个特定的 Pod,这个 Pod 将拒绝任何该网络策略不允许的连接。(Namespace 中其它未被网络策略选中的 Pod 将继续接收所有流量)
NetworkPolicy
资源
下面是一个 NetworkPolicy
的例子:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
将上面配置 POST 到 API Server 将不起任何作用,除非选择的网络方案支持网络策略。
必选字段:像所有其它 Kubernetes 配置一样, NetworkPolicy
需要 apiVersion
、kind
和 metadata
这三个字段,关于如何使用配置文件的基本信息,可以查看 这里 和 这里。
spec:NetworkPolicy
spec 具有在给定 Namespace 中定义特定网络的全部信息。
podSelector:每个 NetworkPolicy
包含一个 podSelector
,它可以选择一组应用了网络策略的 Pod。由于 NetworkPolicy
当前只支持定义 ingress
规则,这个 podSelector
实际上为该策略定义了一组 “目标 Pod”。示例中的策略选择了标签为 “role=db” 的 Pod。一个空的 podSelector
选择了该 Namespace 中的所有 Pod。
ingress:每个NetworkPolicy
包含了一个白名单 ingress
规则列表。每个规则只允许能够匹配上 from
和 ports
配置段的流量。示例策略包含了单个规则,它从这两个源中匹配在单个端口上的流量,第一个是通过namespaceSelector
指定的,第二个是通过 podSelector
指定的。
egress:每个NetworkPolicy
包含了一个白名单 ingress
规则列表。每个规则只允许能够匹配上 to
和 ports
配置段的流量。示例策略包含了单个规则,它匹配目的地 10.0.0.0/24
单个端口的流量。
因此,上面示例的 NetworkPolicy:
- 在 “default” Namespace 中 隔离了标签 “role=db” 的 Pod(如果他们还没有被隔离)
- 在 “default” Namespace 中,允许任何具有 “role=frontend” 的 Pod,IP 范围在 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255(整个 172.17.0.0/16 段, 172.17.1.0/24 除外)连接到标签为 “role=db” 的 Pod 的 TCP 端口 6379
- 允许在 Namespace 中任何具有标签 “project=myproject” ,IP 范围在 10.0.0.0/24 段的 Pod,连接到 “default” Namespace 中标签为 “role=db” 的 Pod 的 TCP 端口 5978
默认策略
通过创建一个可以选择所有 Pod 但不允许任何流量的 NetworkPolicy,你可以为一个 Namespace 创建一个 “默认的” 隔离策略,如下所示:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec: podSelector:
这确保了即使是没有被任何 NetworkPolicy 选中的 Pod,将仍然是被隔离的。
可选地,在 Namespace 中,如果你想允许所有的流量进入到所有的 Pod(即使已经添加了某些策略,使一些 Pod 被处理为 “隔离的”),你可以通过创建一个策略来显式地指定允许所有流量:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector:
ingress:
- {}