Kubernetes构建高效集群的19个最佳实践方法

2021年11月20日18:10:07 发表评论 702 次浏览

Kubernetes构建高效集群教程介绍

Kubernetes 为编排大型分布式容器集群提供了非凡的灵活性。

可用功能和选项的绝对数量可能会带来挑战。应用最佳实践可帮助你避免潜在障碍,并从一开始就创建安全高效的环境。

Kubernetes如何构建高效集群?使用概述的Kubernetes 最佳实践来构建优化的容器、简化部署、管理可靠的服务和管理成熟的集群,包括Kubernetes构建高效集群的方法。

保护和优化容器

容器提供的隔离比虚拟机少得多。你应该始终验证容器映像并严格控制用户权限。

使用小型容器镜像可以提高效率、节省资源并减少潜在攻击者的攻击面。

仅使用受信任的容器映像

现成的容器镜像非常容易访问并且非常有用。然而,公共镜像很快就会变得陈旧,包含漏洞利用、漏洞,甚至恶意软件,这些软件会在整个 Kubernetes 集群中迅速传播。

仅使用来自受信任存储库的图像,并始终扫描图像以查找潜在漏洞。许多在线工具,例如AnchoreClair,提供容器镜像的快速静态分析,并通知你潜在的威胁和问题。在部署之前花一些时间扫描容器镜像,避免潜在的灾难性后果。

非 root 用户和只读文件系统

更改内置安全上下文以强制所有容器仅与非 root 用户和只读文件系统一起运行。

避免以 root 用户身份运行容器。如果用户可以授予自己额外的权限,则安全漏洞会迅速升级。

Kubernetes构建高效集群的19个最佳实践方法

如果文件系统设置为只读,则几乎不可能篡改容器的内容。不需要编辑系统文件,而是需要删除整个容器并在其位置放置一个新容器。

注意:了解Docker 特权容器以及为什么不应该运行它们。

创建小而分层的图像

Kubernetes如何构建高效集群?小图像可加快构建速度并减少存储空间。有效地分层图像可以显着减小图像大小。尝试从头开始构建图像以获得最佳结果。

如果你需要许多不同的组件,请在单个 Dockerfile 中使用多个 FROM 语句。此功能创建部分,每个部分引用不同的基本图像。最终的镜像不再存储之前的层,只存储每一层所需的组件,从而使 Docker 容器更加纤薄。

每一层都是根据FROM位于部署容器中的命令拉取的。

Kubernetes构建高效集群的方法:使用 RBAC 限制用户访问

基于角色的访问控制 (RBAC) 可确保没有用户拥有超过完成任务所需的权限。你可以通过在启动 API 服务器时附加以下标志来启用 RBAC:

--authorization-mode=RBAC

RBAC 使用rbac.authorization.k8s.io API 组通过 Kubernetes API 驱动授权决策。

注意:将机密和密码与你的容器映像隔离开来。有权在命名空间内创建 pod 的用户可以使用该角色来创建 pod 并访问配置映射或机密。

Stdout 和 Stderr 日志

Kubernetes如何构建高效集群?通常的做法是将应用程序日志发送到stdout(标准输出)流,并将错误日志发送到stderr(标准错误)流。一旦应用程序写入 stdout 和 stderr,容器引擎(如 Docker)会将记录重定向并存储在 JSON 文件中。

Kubernetes 容器、Pod 和节点是动态实体。日志需要一致且永久可用。因此,建议将集群范围的日志保存在单独的后端存储系统中。

Kubernetes 可以与各种现有的日志记录解决方案集成,例如ELK Stack。

简化部署

Kubernetes 部署建立了一个模板,以确保 pod 启动并运行、定期更新或按用户定义回滚。

使用清晰的标签、标志、链接容器和 DaemonSet 可以让你对部署过程进行细粒度控制。

使用记录标志

附加--record标志时,执行的kubectl命令将存储为注释。通过检查部署推出历史记录,你可以轻松地在CHANGE-CAUSE列中跟踪更新。

Kubernetes构建高效集群的19个最佳实践方法

通过在 undo 命令中声明修订号来回滚到任何修订。

kubectl rollout undo deployment example-deployment --to-revision=1

如果没有--record标志,就很难确定具体的修订版。

Kubernetes构建高效集群教程:描述性标签

尝试使用尽可能多的描述性标签。标签是键:值对,允许用户在有意义的子集中对 pod 进行分组和组织。大多数功能、插件和第三方解决方案都需要标签才能识别 Pod 并控制自动化流程。

Kubernetes构建高效集群的19个最佳实践方法

例如,Kubernetes DaemonSets依赖标签和节点选择器来管理集群内的 pod 部署。

在一个 Pod 内创建多个进程

Kubernetes构建高效集群的方法:使用 Kubernetes 的容器链接能力,而不是试图解决容器内的所有问题。它可以在单个 Kubernetes pod 上有效地部署多个容器。一个很好的例子是将安全功能外包给代理边车容器。

Kubernetes构建高效集群的19个最佳实践方法

耦合容器可以支持或增强主容器的核心功能或帮助主容器适应其部署环境。

使用初始化容器

一个或多个 init 容器通常执行你不想包含在主应用程序容器中的实用程序任务或安全检查。在启动 pod 的主容器之前,你可以使用 init 容器来确保服务已准备就绪。

在后续的 init 容器启动之前,每个 init 容器都必须成功运行完成。Init 容器可以延迟 Pod 主容器的启动,直到满足前提条件。如果没有这个先决条件,Kubernetes 会重新启动 pod。一旦满足先决条件,init 容器会自行终止并允许主容器启动。

避免使用最新标签

:latest在生产环境中部署容器时,避免使用 no tag 或tag。最新标签使得很难确定正在运行的映像版本。

确保容器始终使用相同版本镜像的有效方法是使用唯一的镜像摘要作为标签。在此示例中,Redis 映像版本使用其唯一摘要进行部署:

redisd@sha256:675hgjfn48324cf93ffg43269ee113168c194352dde3eds876677c5cb

除非你更改摘要值,否则 Kubernetes 不会自动更新映像版本。

设置就绪和活跃度探测器

Liveness 和 Readiness探针可帮助Kubernetes 监控和解释应用程序的运行状况。如果你定义了活性检查并且进程确实满足要求,Kubernetes 将停止容器并启动一个新实例来代替它。

就绪探针在 Pod 级别进行审计,并评估 Pod 是否可以接受流量。如果 Pod 没有响应,就绪探针会触发进程以重新启动 Pod。

注意:建议在配置就绪探针时配置时间延迟。加载大型配置文件可能需要一些时间。就绪探针可能会在 Pod 设法加载之前停止它,从而触发重启循环。

Kubernetes 官方网站上提供了配置就绪和活跃度探测器的文档。

尝试不同的服务类型

通过学习如何利用不同的服务类型,你可以有效地管理内部和外部 Pod 流量。你的目标是通过管理 IP、端口和 DNS 等可靠端点来创建稳定的网络环境。

带有 NodePort 的静态端口

Kubernetes如何构建高效集群?通过将服务类型设置为 NodePort,将 pod 公开给外部用户。如果你在该nodePort字段中指定一个值,Kubernetes 会在所有节点上保留该端口号,并转发所有传入服务的 pod 的流量。可以使用内部集群 IP 和具有保留端口的节点 IP 访问该服务。

Kubernetes构建高效集群的19个最佳实践方法

用户可以通过以下请求从集群外部联系 NodePort 服务:

NodeIP:NodePort

始终使用为 NodePort 配置的范围内的端口号 (30000-32767)。如果 API 事务失败,你需要对可能的端口冲突进行故障排除。

Ingress 与负载均衡器

Kubernetes构建高效集群的方法:LoadBalancer 类型使用你的提供者的负载均衡器在外部公开服务。你使用 LoadBalancer 类型公开的每个服务都会接收其 IP。如果你有许多服务,根据公开服务的数量,你可能会遇到计划外的额外费用。

什么是入口?Ingress 允许你使用单个 IP 从集群外部向集群内的服务公开多个服务。Ingress 不是一种服务类型,而是定位为路由多个服务的流量并充当你的服务的唯一入口点。入口控制器提供一组功能,让你可以设置到后端服务的子域和基于路径的路由。

标准配置要求是为入口控制器提供现有的静态公共 IP 地址。如果入口控制器被删除,静态公共 IP 地址仍然存在。这种方法允许你在应用程序的整个生命周期中一致地使用当前的 DNS 记录和网络配置。

Kubernetes构建高效集群教程:将外部服务映射到 DNS

ExternalName 类型不会将服务映射到选择器,而是使用 DNS 名称。使用externalName参数通过 CNAME 记录映射服务。CNAME 记录是完全限定的域名,而不是数字 IP。

连接到服务的客户端将绕过服务代理并直接连接到外部资源。在此示例中,pnap-service映射到admin.phoenixnap.com外部资源。

Kubernetes构建高效集群的19个最佳实践方法

访问pnap-service 的工作方式与其他服务相同。关键的区别在于重定向现在发生在 DNS 级别。

应用设计

使用 Kubernetes 进行自动化容器部署可确保大多数操作现在无需直接人工输入即可运行。设计你的应用程序和容器映像,以便它们可以互换并且不需要持续的微观管理。

专注于个人服务

尝试将你的应用程序拆分为多个服务,并避免在单个容器中捆绑太多功能。如果它们专注于执行一项功能,则水平扩展应用程序和重用容器会容易得多。

创建应用程序时,假设你的容器是将定期停止和重新启动的短期实体。

注意: Kubernetes 是一个自动化工具,一旦部署,你的镜像不应依赖于手动管理或输入。容器是不可变的,不应修改,而应从基础映像重新启动。

使用Helm chart

Helm 是 Kubernetes 应用程序包管理器,可以非常快速地简化安装过程并在整个集群中部署资源。Helm 应用程序包称为 Charts。

MySQL、PostgreSQL、MongoDB、Redis、WordPress 等应用程序是需求解决方案。你可以部署现成的 Helm Charts,而不是创建和编辑几个复杂的配置文件。

使用以下命令创建在集群上运行 Kafka 管理器所需的部署、服务、PersistentVolumeClaims和 Secrets。

helm install --name my-messenger stable/kafka-manager

你不再需要分析特定组件并学习如何配置它们以正确运行 Kafka。

如果你刚开始使用 Helm,请访问我们的指南如何在 Ubuntu、Mac 和 Windows 上安装 Helm以及如何添加或更新 Helm Repo。如果你想了解更多信息,或将 Helm 与其他工具进行比较,请查看我们的Helm 与 Kustomize 文章。

利用节点和 Pod 亲和性

亲和性功能用于定义节点亲和性和 Pod 间亲和性。节点亲和性允许你使用现有节点标签指定 Pod 有资格在其上调度的节点。

  • requiredDuringSchedulingIgnoredDuringExecution – 建立必须满足的强制性约束才能将 Pod 调度到节点。
  • preferredDuringSchedulingIgnoredDuringExecution – 定义调度程序优先但不保证的首选项。

如果节点标签在运行时发生变化,并且不再满足 Pod 的亲和性规则,则不会从节点中删除 Pod。该 nodeSelector 参数通过使用标签将 pod 限制到特定节点。在此示例中,Grafana pod 将仅在具有ssd标签的节点上进行调度。

Kubernetes构建高效集群的19个最佳实践方法

pod 关联/反关联功能扩展了你可以表达的约束类型。你可以使用现有的 pod 标签来描述可以在其上调度 pod 的节点,而不是使用节点标签。此功能允许你设置规则,以便根据其他 Pod 的标签来安排单个 Pod。

节点污点和容忍度

Kubernetes如何构建高效集群?Kubernetes 会自动尝试将 pod 部署到工作负载最小的位置。节点和 Pod 亲和性允许你控制将 Pod 部署到哪个节点。污点可以在不改变现有 Pod 的情况下阻止将 Pod 部署到特定节点。要在受污染节点上部署的 Pod 需要选择使用该节点。

  • 污点- 防止在节点上调度新 pod,定义节点首选项,并从节点中删除现有 pod。
  • 容忍度– 仅在具有现有和匹配污点的节点上启用 Pod。

污点和容忍度一起使用时会产生最佳结果,以确保将 pod 安排到适当的节点上。

注意:在我们的文章如何容器化遗留应用程序中了解将遗留应用程序迁移到容器时需要注意的事项

使用命名空间对资源进行分组

Kubernetes构建高效集群的方法:使用 Kubernetes 命名空间将大型集群划分为更小的、易于识别的组。命名空间允许你创建单独的测试、QA、生产或开发环境,并在唯一的命名空间内分配足够的资源。Kubernetes 资源的名称只需在单个命名空间内唯一。不同的命名空间可以具有相同名称的资源。

如果多个用户有权访问同一个集群,你可以限制用户并允许他们在特定命名空间的范围内进行操作。分隔用户是分隔资源和避免潜在命名或版本冲突的好方法。

命名空间是 Kubernetes 资源,非常容易创建。创建一个定义命名空间名称的 YAML 文件,并使用 kubectl 将其发布到 Kubernetes API 服务器。你随后可以使用命名空间来管理其他资源的部署。

Kubernetes构建高效集群教程结论

Kubernetes 集群代表了一个具有大量解决方案和功能的复杂结构。并非所有建议的做法都适用于所有用例。

尝试应用本文中概述的一些实践,看看它会对 Kubernetes 集群的内聚力和功能产生什么影响。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: