Kubernetes已经成为市场上事实上领先的编配工具,不仅对技术公司如此,对所有公司都是如此,因为它允许您快速且可预测地部署应用程序、动态地伸缩应用程序、无缝地推出新特性,同时有效地利用硬件资源。
本期我们将回顾采用Kubernetes作为容器编排工具的公司所面临的复杂性和挑战。我们希望我们提供的经验教训、最佳实践和技巧将帮助您在前往K8s旅途中起步并继续前进。
本期将介绍关于在Kubernetes生产环境的最佳实践,包括::
JFrog与Kubernetes的旅程始于我们寻找一个合适的容器编排解决方案,以便为内部目的创建一个功能齐全的环境。我们的开发人员需要测试我们非常复杂的环境,包括JFrog Artifactory和其他产品。与此同时,我们需要为程序和产品经理提供一个完整的功能环境,以便向我们的客户演示平台。
为了满足我们的需求,每个产品都需要一个独立的CI/CD开发环境,以便在测试各个分支之间的交互时独立地测试各个分支。
随着我们对Kubernetes越来越有信心,我们认识到将JFrog产品分发到Kubernetes的价值,能够跨不同的阶段、开发和生产环境运行应用程序。Kubernetes还允许我们更好地利用我们的资源,因为我们不再需要为单独部署每个产品而启动单个VM。下面我们将回顾落地过程中的主要挑战(6大挑战),同时分享我们的最佳实践、技巧,和在将您的容器应用程序一路带到生产环境中所获得的经验教训。
图1 - 应用分发到K8 的6大挑战
Kubernetes允许您创建容器化的应用程序,并将它们并行的部署,而不必担心各种服务和组件之间的兼容性。将应用程序容器化运行在Kubernetes中的好处是,您可以在一个充满活力的社区中开发产品,从而更容易创建可伸缩的微服务应用程序。这样做的缺点是,当整个团队都在处理各种组件时,情况会很快变得非常复杂。此外,容器化的应用程序可以包含多种组件类型,这取决于您使用的操作系统、语言和框架。
让我们从使用Kubernetes运行应用程序所需的三个基本组件开始:
Kubernetes集群是您的容器化应用程序运行的编排基础设施。您需要决定是否要自己管理它,以及是否要使用云提供商托管它。此组件不在文档的此范围内讨论。
CI/CD流水线在Kubernetes中运行,并使流程自动化,从源代码和外部依赖包开始,一直到将应用程序部署到Kubernetes集群中。Kubernetes流水线是“应用程序感知的”(面向应用),这意味着它们天生能够动态地提供一个完整的容器化应用程序堆栈(通常由多个service、deployments, replica sets, secrets, configmap等组成)。对应用程序上下文的每次更改,无论是代码、、镜像还是配置更改,都将触发流水线。
您的生产集群应该使用一个单独的、受管理的和可信的真实源,该源存储和记录应用程序和其依赖组件。使用Kubernetes Registry,您可以在一个pod中并行运行多个应用程序堆栈,而不产生冲突,也不需要关心每个应用程序的内部依赖关系。这将维护正在运行的集群、向上和向下扩容应用程序、开发新版本和调试应用程序具体问题分隔开来。
应用程序是服务/解决方案的核心。在Kubernetes中运行应用程序之前,需要计划和准备应用程序。
下表显示了在准备Kubernetes应用程序之前必须询问的与应用程序相关的任务和问题。
有关将构建软件的基础知识,请参见软件12因素。 https://12factor.net/
多语言编程和多种不同的工具和技术提供了多种可能性。您可以选择最适合您的业务需求的技术,但是每种技术可能有不同的接口、REST API和自己的包格式。支持这些工具的唯一方法是做到在制品从创建到部署的生命周期的管理中实现通用。
通过使用Artifactory作为“Kubernetes Registry”,您可以获得灵活性和通用性,作为可信的单一来源,它允许您深入了解代码到应用集群的过程,同时关联每个应用程序的每一层(layer)。Artifactory在一个系统中支持超过25种不同的技术栈,具有一个元数据模型、一个升级流和强大的制品依赖关系。
Artifactory允许您将容器化的微服务部署到Kubernetes集群,因为它作为一个通用存储库管理平台来满足您的所有CI/CD需求,而不管它们在您的组织中何处运行。登记应用程序包后,可以继续传播和执行构建、测试、升级,最后部署到Kubernetes。为了方便地将Artifactory(和其他JFrog产品)部署到Kubernetes,请参考我们在helm hub中的官方JFrog Helm Charts(https://hub.helm.sh/charts/jfrog)。
在CI/CD流水线的每个阶段中不需要人工干预的情况下可靠地大规模部署应用程序是的协调的主要原因。但是如何以一种可重复、可靠的方式将代码发布到集群中呢?如何确保只有正确版本的应用程序才能投入生产?
为此,我们建议将Artifactory部署为存储库管理平台,通过抹平开发和操作之间的差距在CI/CD流水线中扮演重要角色。
Artifactory原生支持Helm存储库,使您能够完全控制Kubernetes的部署过程。它提供安全的、私有的、本地的Helm存储库,通过细粒度的访问控制在您的组织中共享Helm Charts。使用远程存储库代理和缓存公共Helm Charts资源,并将本地和远程资源聚合到单个虚拟Helm存储库下,从而从单个URL访问所有Helm Charts。
K8S 专家建议:
当使用Artifactory作为您的Helm 存储库时,我们建议:
•分离您的稳定存储库和开发阶段存储库(基于成熟度)。
•在Charts中使用SemVer version 2版本。
•定期重新计算索引。
在CI/CD流水线中部署应用程序的最佳实践
在CI/CD流水线中部署应用程序时,我们建议:
在Kubernetes集群中并行运行多个应用程序需要建立对工件(Docker镜像)的持续访问,同时支持零停机的高负载服务。
通过在Kubernetes集群中部署Artifactory HA(高可用),在集群中,您将体验到零宕机服务,如果一个pod被回收或崩溃,或者节点意外停机,容器集群将自动调度恢复对应服务的Pod。
在Kubernetes部署Artifactory HA的好处是:
在下例中,使用三个节点部署了一个Artifactory HA集群:一个主节点和两个成员节点。因为负载均衡只在成员节点上执行。这使得主节点可以自由地处理作业和任务,不会被入站流量中断。
Artifactory HA允许您在Kubernetes中突破应用程序的限制,因为它支持大量存储替代方案。有关更多信息,请参见配置文件存储库。
( https://www.jfrog.com/confluence/display/RTF/Configuring+the+Filestore )
像Docker和Kubernetes这样的云本地技术提供了更大的攻击面,为恶意数据挖掘、勒索软件和数据盗窃提供了更多潜在的入口点。在Kubernetes集群中运行的服务并不是完全独立的,它们可以访问集群中的其他区域。
正是出于这个原因,集群的可见性非常重要,尤其是从安全性的角度来看。您需要知道容器中运行的是什么,因为您的应用程序很少包含单个组件,而是包含外部依赖项,如OS包、OSS libs和第三方流程。这就引出了一个不可避免的问题——它们安全吗?它们是否包含安全漏洞?他们是否遵守自由/开源软件许可?
Artifactory通过提供可审核性来深入了解整个CI/CD流程,因为它捕获了整个CI/CD流程中产生的大量有价值的元数据。您可以跟踪负责生成Docker镜像层的应用层的CI作业。它还可以通过允许比较两个构建来显示构建差异,从而很容易地跟踪Docker镜像基于哪个层生成的,到哪个构建产生的,从而跟踪到提交。
推荐阅读:每个人都必须遵循9个Kubernetes安全最佳实践。
( https://www.cncf.io/blog/2019/01/14/9-kubernetes-security-best-practices-everyone-must-follow/ )
JFrog Xray与Artifactory协作,在应用程序生命周期的任何阶段执行二进制软件工件的通用分析。它对容器中的所有层执行递归扫描,并通过扫描和分析工件及其元数据(递归地遍历任何级别的依赖关系)来帮助识别所有层中的漏洞。可以在Xray中设置策略,根据Xray扫描发现的风险级别限制或阻止容器镜像部署到Kubernetes。通过这种方式,可以阻止脆弱或不兼容的应用程序运行,或者限制它们在启动时可以做什么。
大多数应用程序严重依赖于包管理器和开源存储库,因此很容易受到来自这些源的恶意或不安全代码的攻击。作为我们支持和贡献开源社区计划的一部分,JFrog开发了KubeXray,这是一个开源项目,它将Xray的安全性扩展到Kubernetes pod中运行(或即将运行)的应用程序。使用Xray通过扫描容器映像生成的元数据,KubeXray可以对已经部署的内容执行策略。
KubeXray监控您所有的活动Kubernetes Pod,以帮助您:
Helm 2包含一个名为“Tiller”的服务器端组件。Tiller是一个集群内的服务器,它与Helm客户端交互,并与Kubernetes API服务器交互。
Tiller 绝对是很酷的,但重要的是要知道有安全问题。这是因为Helm客户端负责管理Charts,而服务器负责管理发布。这带来了很大的风险,因为Tiller使用root权限运行,有人可能会未经授权访问您的服务器。
Rimas Mocevicius是JFrog公司的一名员工,也是Helm公司的联合创始人,他提出了一种创新的方法来解决这种情况,即在工作站上或CI/CD管道上运行Helm和Tiller,而不将Tiller安装到Kubernetes集群中。您可以下载并安装无Tiller 的Helm v2插件。
必须将RBAC(基于角色的访问控制)设置为Kubernetes的管理功能,因为它允许您定义哪个用户可以管理集群及其粒度。除了定义可以列出哪些用户和应用程序之外,还可以获取、创建或删除pods和其他Kubernetes对象。一个好的实践是通过在为应用程序创建的服务帐户中设置“automountServiceAccountToken: false”来禁用对API的访问。
如果没有指定服务帐户,它会自动将相同名称空间中的“默认”服务帐户分配给pod。我们建议不要使用名称空间附带的默认值。始终为应用程序创建服务帐户,因为它允许您设置应用程序的限制,包括名称空间或集群范围的操作,并完全禁用对Kubernetes API的访问。
微服务的数量随着复杂性的增加而增加,问题是如何跟踪和监视它们,以及应该监视什么。当涉及到微服务时,您需要收集以下数据微服务:
应用程序和系统日志对于排除Kubernetes集群活动的故障非常重要。
在Kubernetes中应用程序记录日志时,请遵循以下最佳实践::
持续监视系统和应用程序健康状况非常重要。
对于实时监视Kubernetes集群和其中运行的应用程序,有许多免费的和商业的解决方案。其中一个流行的解决方案是Prometheus ,Grafana的结合,提供实时监控,可以与报警工具相结合。
1. 对于初学者,我们建议从阅读Kubernetes的艰难方式开始!
(https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/README.md)
2. 从小事做起。从示例中学习,从一个小应用程序(nginx)开始,使用现有的演示,并尝试在Docker的Skin Kubernetes中部署应用程序。
3. 在进入K8S之前准备好你的应用程序。
( https://docs.google.com/document/d/1YS_jICIEPZLle7KcpEoLjuKCZ_TkgNzb9LajPU4AhsI/edit#heading=h.81oh8o1kpi75 )
4. 为使应用程序在k8s中运行,设置一个最小的目标。
5. 使用托管的k8S来解放您的工作,例如:AKS、ESK或GKE,它们为您抽象了许多复杂性。
6. 每个Pod有一个主容器。
7. 我们建尝试GKE 托管管理Kubernetes。
8. 确定在Kubernetes集群内或集群外存储数据库的位置。这一点非常重要,因为您需要在集群崩溃时计划集群恢复。考虑以下:
-当K8S在prem上运行时:在Kubernetes中将现有的数据库作为无状态应用程序使用。
-在云上运行K8S时:,选择一个如PostgreSQL或MySQL 的 operator ,其知道如何在Kubernetes节点宕机时恢复的持久化数据库。
9. 部署到容器云时,请将对应集群分开,运行CI/CD流水线,以及从外部CI/CD流水线部署应用到Kubernetes集群。
10. 与社区合作
正如本篇文章所描述的,我们展示了Kubernetes和JFrog Artifactory是如何让您可靠地、可预测地部署应用程序、动态地伸缩应用程序、无缝地推出新特性并有效地利用硬件资源的。
本篇文章旨在回顾希望采用Kubernetes作为容器编排工具的公司所面临的复杂性和挑战。我们希望我们分享的经验教训、最佳实践和技巧将帮助您在前往K8s的旅途中起步并继续前进。