Kubernetes 持续发展,提供可以显著增强集群性能、效率和安全性的新功能和优化。对于高级工程师,掌握这些优化可以带来更强大、更可扩展且更具成本效益的部署。以下是 18 个高级 Kubernetes 节点优化的精选列表,按其在 2024 年的预期实用性和受欢迎程度排序。
译自 13 Kubernetes Node Optimizations You Should Know in 2024,作者 DavidW (skyDragon)。
大容器镜像会导致更长的拉取时间、更慢的 Pod 启动以及增加的网络和存储资源消耗。优化镜像大小可以显著提高部署效率和应用程序可扩展性。
# Build stage
FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .
# Final stage
FROM alpine:latest
COPY --from=builder /app/myapp .
ENTRYPOINT ["./myapp"]
选择更精简的基础镜像:Alpine Linux 等基础镜像提供最小的占用空间。迁移到此类镜像可以大幅减小容器镜像的整体大小。
未使用的容器镜像会消耗节点上的宝贵磁盘空间,可能导致影响新部署和 Kubernetes 集群整体运行状况的资源限制。
docker image prune -a --filter "until=168h"
节点亲和性和反亲和性是 Kubernetes 中的强大功能,可以对 Pod 在集群中的放置位置进行精细控制。这些功能对于优化资源利用、确保高可用性以及在不同工作负载之间强制分离关注点至关重要。让我们深入了解它们的功能、用例以及如何在 Kubernetes 部署中有效实施这些策略。
节点亲和性允许你指定规则,将 Pod 的放置限制在具有特定标签的节点上。这对于特定工作负载需要具有特定特征的节点(例如特定硬件或软件配置)的情况特别有用。
以下示例演示如何使用节点亲和性将 Pod 调度到标记为disktype=ssd的节点上,确保这些 Pod 受益于 SSD 存储的性能特征。
apiVersion: v1
kind: Pod
metadata:
name: ssd-affinity-pod
spec:
containers:
- name: nginx
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
虽然节点亲和性将 Pod 吸引到具有特定标签的节点,但节点反亲和性将 Pod 从具有特定标签的节点中排斥出去,或确保 Pod 不与具有特定特征的其他 Pod 放置在同一节点上。这对于通过在不同的故障域中分布 Pod 来维护高可用性和灾难恢复协议至关重要。
以下代码段说明了如何使用节点反亲和性来避免在同一节点上调度 Pod,如果它们被标记为 app=frontend,通过将它的实例分散在不同的节点上,增强前端服务的弹性。
apiVersion: v1
kind: Pod
metadata:
name: frontend-pod
spec:
containers:
- name: frontend
image: frontend-image
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: "kubernetes.io/hostname"
污点和容忍提供了一种强大的机制来控制节点上的 Pod 放置,确保只有容忍特定污点的 Pod 才能在被污染的节点上调度。此功能对于隔离工作负载至关重要,尤其是在多租户环境中或特定节点专用于特定任务时。
对节点应用污点:
kubectl taint nodes node1 key=value:NoSchedule
此命令对 node1 应用污点,防止 Pod 在此节点上调度,除非它们具有匹配的容忍度。
在 Pod 中定义容忍度:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: myimage
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
此 Pod 规范包括与 node1 上的污点匹配的容忍度,允许它在那里调度。
Descheduler 是一个外部组件,它根据当前的调度策略和集群状态帮助优化集群中的 Pod 放置。它驱逐违反新更新策略或可以更好地放置在其他节点上的 Pod,从而提高整体集群效率和资源利用率。
Descheduler 需要一个策略配置来确定要驱逐哪些 Pod。以下是一个示例策略,用于驱逐 Pod 以实现更好的平衡:
apiVersion: "k8s.descheduler.io/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
"LowNodeUtilization":
enabled: true
params:
nodeResourceUtilizationThresholds:
thresholds:
cpu: 20
memory: 20
pods: 20
targetThresholds:
cpu: 50
memory: 50
pods: 50
此策略旨在平衡节点利用率,将 Pod 从利用率低节点驱逐到利用率目标较高的节点。
内核参数调优允许系统管理员优化其 Kubernetes 节点的网络性能。对 Linux 内核设置的调整可以显著提高吞吐量并降低延迟,这对网络密集型应用程序至关重要。
调整网络缓冲区:增加网络缓冲区的大小有助于容纳大量流量,从而减少丢包和延迟。
sysctl -w net.core.rmem_max=26214400
sysctl -w net.core.wmem_max=26214400
增加最大打开文件描述符数:高性能服务器可能需要比默认限制更多的打开文件描述符。
sysctl -w fs.file-max=100000
垂直 Pod 自动伸缩器 (VPA) 根据历史使用数据自动调整 Kubernetes 集群中 Pod 的 CPU 和内存预留,确保 Pod 拥有所需的资源,而不会浪费资源。
安装 VPA:VPA 安装在集群中,并要求为其应管理的每个应用程序定义一个 VPA 对象。
apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: myapp-vpa spec: targetRef: apiVersion: "apps/v1" kind: Deployment name: myapp updatePolicy: updateMode: "Auto"
此 VPA 对象自动调整 myapp 部署的资源请求。
Cilium 是 Kubernetes 的 CNI(容器网络接口)插件,提供高级网络功能,包括细粒度网络策略、负载均衡和加密。它利用 eBPF(扩展 Berkeley 数据包过滤器)技术来提供高度可扩展和安全的网络策略。
安装 Cilium:Cilium 可以通过 Helm 图表或基于操作员的部署安装在 Kubernetes 集群中。
helm install cilium cilium/cilium --version <version> --namespace kube-system
定义网络策略:Cilium 允许您定义网络策略,这些策略可以根据标签、命名空间甚至应用程序协议控制 Pod 级别的入站和出站流量。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "restrictive-policy"
spec:
endpointSelector:
matchLabels:
app: myapp
ingress:
- fromEndpoints:
- matchLabels:
app: database
Kubernetes 中的临时存储管理是指节点上的 Pod 分配和使用临时存储。此类存储用于存储瞬态的应用程序数据,例如日志、缓存或 Pod 需要与在同一节点上运行的其他 Pod 共享的文件。使用 Kubernetes,您可以管理本地临时存储,以优化节点资源利用率并确保应用程序拥有所需的必要临时存储,而不会影响节点的稳定性。
指定临时存储请求和限制:在定义 Pod 时,您可以为临时存储指定请求和限制,类似于您对 CPU 和内存资源所做的那样。这可确保 Pod 被调度到具有足够可用临时存储的节点上,并且单个 Pod 不会消耗过多的节点级资源。
apiVersion: v1
kind: Pod
metadata:
name: ephemeral-storage-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
ephemeral-storage: "1Gi"
limits:
ephemeral-storage: "2Gi"
在此示例中,Pod 请求 1Gi 的临时存储,并限制为 2Gi,超过此限制后,Kubernetes 将采取纠正措施,以确保 Pod 不超过分配的存储。
Pod 拓扑扩展约束是 Kubernetes 中的一项复杂功能,它增强了调度机制,允许开发人员和管理员控制 Pod 在集群拓扑中分布的方式。此功能旨在通过在不同拓扑域(例如节点、可用区或自定义定义的区域)中均匀分布 Pod 来提高应用程序的弹性和效率。它对于高可用性配置、容错和优化分布式计算环境中的资源利用率特别有用。
在 Pod 规格中定义拓扑扩展约束:要利用此功能,您需要在 Pod 规格中定义 topologySpreadConstraints。以下是一个示例,它确保 Pod 均匀分布在不同的可用区中:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: myapp
image: myapp:latest
topologySpreadConstraints:
- maxSkew: 1
topologyKey: "topology.kubernetes.io/zone"
whenUnsatisfiable: "ScheduleAnyway"
labelSelector:
matchLabels:
app: myapp
在此配置中,maxSkew 定义了允许的最大 Pod 不平衡。topologyKey 指定要考虑的拓扑域(在本例中为云提供商区域)。whenUnsatisfiable 表示在无法实现所需分布时应采取的措施;“ScheduleAnyway”表示即使调度程序无法完全满足约束条件,它仍会调度 Pod。labelSelector 用于确定应考虑进行扩展的 Pod。
垂直 Pod 自动伸缩器 (VPA) 是 Kubernetes 中用于动态管理资源分配的不可或缺的工具。它根据 Pod 的使用情况自动调整 Pod 的 CPU 和内存请求和限制,确保应用程序拥有在不过度配置的情况下以最佳方式执行所需的资源。这对于具有可变资源需求的应用程序特别有益,因为它有助于减少资源浪费,并有可能降低成本。
设置 VPA:VPA 可以通过自定义资源定义 (CRD) 部署到您的集群。安装后,您可以为要自动调整其资源的每个应用程序定义一个 VPA 资源。
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: myapp-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
updatePolicy:
updateMode: Auto
在此示例中,VPA 被配置为自动调整 myapp 部署的资源。
WireGuard 是一种现代、高性能的 VPN 协议,可用于保护 Kubernetes 集群中的节点间通信。其简单性和效率使其成为加密节点间流量的理想选择,确保集群中传输的数据对潜在窃听者来说是私密且安全的。
设置 WireGuard:可以通过安装 WireGuard 软件并在其上配置必要的密钥和网络设置,在 Kubernetes 节点上设置 WireGuard。
在节点上安装 WireGuard:集群中的每个节点都需要安装 WireGuard。这通常可以通过操作系统的包管理器来完成。
apt install wireguard # On Debian/Ubuntu
生成密钥:WireGuard 使用公钥密码术。在每个节点上生成密钥:
wg genkey | tee privatekey | wg pubkey > publickey
配置 WireGuard 接口:在每个节点上创建一个 WireGuard 配置文件 ( /etc/wireguard/wg0.conf) 并设置私钥和对等方(集群中的其他节点)。
[Interface]
Address = 10.0.0.1/24
PrivateKey = <node-private-key>
[Peer]
PublicKey = <peer-public-key>
Endpoint = <peer-ip-address>:51820
AllowedIPs = 10.0.0.2/32
启动 WireGuard:在每个节点上启用并启动 WireGuard 接口。
wg-quick up wg0
CSI(容器存储接口)卷克隆允许 Kubernetes 用户在同一存储类中克隆现有的持久卷声明 (PVC)。此功能简化了存储层的数据复制和备份流程,使其比传统的应用程序级数据复制方法更有效。
创建 PVC 克隆:要创建现有 PVC 的克隆,请定义一个新的 PVC 并指定要克隆的现有 PVC。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cloned-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 5Gi
dataSource:
kind: PersistentVolumeClaim
name: original-pvc
apiGroup: ""
使用开放策略代理 (OPA) 和 Gatekeeper 进行动态准入控制提供了一种强大的方法,可以在运行时对 Kubernetes 资源强制执行自定义策略。这允许集群管理员在所有 Kubernetes 对象上实施治理和合规规则,确保只有符合特定条件的资源才能在集群内运行。
设置 Gatekeeper:Gatekeeper 是 OPA 的准入控制器 webhook,可与 Kubernetes 无缝集成。
安装 Gatekeeper:在您的集群中部署 Gatekeeper,通常使用 Helm 图表或直接应用 YAML 文件。
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.1/deploy/gatekeeper.yaml
定义约束和约束模板:创建约束模板以定义自定义策略 (Regos) 和约束以对特定 Kubernetes 对象强制执行这些策略。
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg, "details": {"missing_labels": missing}}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("you must provide labels: %v", [missing])
Kubernetes 中的用户命名空间是一项功能,它通过允许容器拥有与主机系统不同的用户和组 ID 来增强容器隔离。此功能通过限制容器逃逸漏洞的潜在影响来提高安全性。
启用用户命名空间:对用户命名空间的支持因容器运行时而异。对于 Docker,您可以通过配置 Docker 守护进程来启用用户命名空间。
配置 Docker 守护进程:编辑 Docker 守护进程配置文件 ( /etc/docker/daemon.json) 启用用户命名空间。
{
"userns-remap": "default"
}
重启 Docker:通过重启 Docker 服务应用更改。
systemctl restart docker
用户命名空间是 Linux 中的一项功能,允许在主机和容器之间隔离用户 ID 和组 ID。这种隔离通过确保在容器内作为 root 运行的进程在主机机上没有 root 权限来增强安全性。将 pod 中的用户映射到节点内核中的不同用户会创建额外的安全层,使得恶意行为者更难利用容器漏洞来获取主机访问权限。
在 Kubernetes 中配置用户命名空间:
apiVersion: v1
kind: Pod
metadata:
name: userns-pod
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
containers:
- name: example
image: nginx
结构化日志记录将传统日志消息转换为结构化格式,例如 JSON,使其更易于分析和查询。这种日志记录方法在 Kubernetes 等分布式系统中特别有益,在这些系统中,了解微服务之间的交互对于调试和监控至关重要。
将结构化日志记录集成到应用程序中:
import log "github.com/sirupsen/logrus"
func main() {
log.SetFormatter(&log.JSONFormatter{})
log.WithFields(log.Fields{
"event": "create",
"topic": "topic_name",
"key": "key_value",
}).Info("Message about creating an item")
}
随着 Kubernetes 的不断发展,对于希望提高其集群性能、效率和安全性的工程师来说,紧跟最新的节点优化至关重要。本综合指南涵盖了一系列高级优化,从优化镜像大小和管理临时存储到使用 WireGuard 保护节点通信以及使用 Cilium 实施细粒度网络策略。通过采用这些策略以及利用垂直 Pod 自动伸缩器和结构化日志等工具,Kubernetes 管理员和开发人员可以确保其部署不仅健壮且可扩展,而且还为 2024 年及以后的挑战做好准备。采用这些优化将带来更具成本效益、更安全和性能更高的 Kubernetes 环境,使组织能够充分利用云原生技术的优势。随着 Kubernetes 生态系统的不断发展,持续探索和整合这些高级实践将成为维护最先进部署的关键。