听说有12个因素定义了云原生应用程序。也有人说Kubernetes专为云原生计算而设计。那么如何使用Kubernetes建立12要素应用程序?让咱们来看看到底什么是十二因子应用程序,以及它们与Kubernetes的关系。git
十二因子应用程序是Heroku建立的软件即服务架构的宣言。这个想法是,为了真正适合SaaS并避免软件侵蚀的问题-随着时间的流逝,未更新的应用程序将与最新的操做系统,安全补丁等不一样步-应遵循一个应用程序这12条原则:github
让咱们看一下这一切对Kubernetes应用程序的意义。sql
12因子应用程序的原则1是“一份基础代码库,经过版本管理,实现多个部署”。数据库
对于Kubernetes应用程序,该原理实际上已嵌入到容器编排自己的本质中。一般,您使用git repo之类的源代码控制存储库建立代码,而后将特定版本的镜像存储在Docker Hub中。当您定义要做为Kubernetes Pod,Deployment,DaemonSet的一部分进行编排的容器时,还能够指定镜像的特定版本,以下所示:编程
... spec: containers: - name: AcctApp image: acctApp:v3 ...
这样,您可能会在不一样的部署中运行多个版本的应用程序。后端
应用程序的运行方式也可能有所不一样,具体取决于配置信息。安全
12因素应用程序的原则2是“显式声明和隔离依赖项”。服务器
实际上,要确保知足应用程序的依赖关系。对于12因子应用程序,这不只包括确保可使用特定于应用程序的库,还不包括期望操做系统,并假设系统库(例如curl)在那里。 12因子应用程序必须是独立的。网络
这包括确保应用程序足够隔离,不会受到主机上可能安装的冲突库的影响。架构
幸运的是,若是应用程序确实有任何特定或不寻常的系统要求,则容器能够轻松知足这两个要求。容器包括应用程序所依赖的全部依赖关系,而且还提供了容器在其中运行的合理隔离的环境。 (与流行的见解相反,容器环境不是彻底隔离的,可是在大多数状况下,它们足够好。)
对于模块化且依赖于其余组件(例如HTTP服务和日志提取器)的应用程序,Kubernetes提供了一种将全部这些组件组合到单个Pod中的方法,以实现适当封装这些组件的环境。
12因素应用程序的原则3是“在环境中存储配置”。
该原理背后的思想是,应用程序应彻底独立于其配置。换句话说,您应该可以将其移动到另外一个环境,而无需改变源代码。
一些开发人员经过建立某种类型的配置文件,指定详细信息(例如目录,主机名和数据库凭据)来实现此目标。这是一项改进,可是确实存在有人将配置文件签入源代码控制存储库的风险。
相反,有12个因子的应用程序将其配置存储为环境变量。正如宣言所述,它们“不太可能被偶然检查到存储库中”,而且它们独立于操做系统。
Kubernetes使您能够经过Downward API在清单中指定环境变量,可是因为这些清单自己确实受到检查的int源代码控制,因此这不是一个完整的解决方案。
相反,您能够指定环境变量应由Kubernetes ConfigMap或Secrets的内容填充,这些内容能够与应用程序分开保存。例如,您能够将Pod定义为:
如您所见,此Pod接收三个环境变量SECRET_USERNAME,SECRET_PASSWORD和CONFIG_VERSION,前两个来自引用的Kubernetes Secrets,第三个来自Kubernetes ConfigMap。这使您能够将它们保留在配置文件以外。
固然,仍然存在有人对用于建立这些对象的文件进行错误处理的风险,可是将它们放在一块儿并制定安全的处理策略比清除散布在部署中的数十个配置文件要大。
并且,社区中的一些人指出,即便环境变量因为其自身的缘由也不必定是安全的。例如,若是应用程序崩溃,则可能会将全部环境变量保存到日志中,甚至将其传输到另外一个服务。 DiogoMónica指出了一种可与Kubernetes一块儿使用的名为Keywhiz的工具,可建立安全的秘密存储。
12因素应用程序的原则4是“将后端服务做为附加资源”。
在12因子应用程序中,不属于核心应用程序的任何服务(例如数据库,外部存储或消息队列)都应做为服务(经过HTTP或相似请求)进行访问,并在配置中指定,以即可以更改服务源,而不会影响应用程序的核心代码。
例如,若是您的应用程序使用消息队列系统,则应该可以从RabbitMQ更改成ZeroMQ(或ActiveMQ甚至其余功能),而无需更改配置信息。
对于基于Kubernetes的应用程序,此要求有两个含义。
首先,这意味着您必须考虑应用程序如何接收(和分发)信息。例如,若是您有一个支持数据库,那么即便将其复制到其余实例,您也不想拥有一个本地Mysql实例。相反,您但愿有一个单独的容器来处理数据库操做,并使这些操做可经过API调用。这样,若是您须要更改成PostgreSQL或远程托管的MySQL服务器,则能够建立一个新的容器镜像,更新Pod定义,而后从新启动Pod(或更多是由Deployment或StatefulSet管理它)。
一样,若是您将凭据或地址信息存储在ConfigMap支持的环境变量中,则能够更改该信息并替换Pod。
请注意,这两个示例均假设尽管您未对源代码(甚至主应用程序的容器镜像)进行任何更改,但仍须要替换Pod;作到这一点的能力其实是12因素应用程序的另外一项原则。
12 Factor App的原则5是“严格分开的构建和运行阶段”。
现在,很难想象会有这样的状况,可是十二要素应用程序必须具备单独的构建阶段。换句话说,您应该可以构建或编译代码,而后将其与特定的配置信息结合起来以建立特定的发行版,而后有意地运行该发行版。
发布应该是可识别的。您应该能够说“此部署正在运行此应用程序的1.14版本”或相似的内容,就像咱们说咱们在运行“ OpenStack Ocata版本”或“ Kubernetes 1.6”同样。它们也应该是不变的。任何更改应致使新版本。若是这听起来使人生畏,请记住,当咱们说“应用程序”时,咱们再也不在谈论大型的总体发行版。取而代之的是,咱们谈论的是很是具体的微服务,每一个微服务都有其本身的发行版,而且能够在不引发使用服务错误的状况下提升发行版。
全部这些都是为了让应用程序运行时,该“运行”过程能够彻底自动化。十二因子应用程序须要可以以自动化方式运行,由于它们须要可以在出现问题时从新启动。
将其转换为Kubernetes领域,咱们已经说过,该应用程序须要存储在源代码管理中,而后使用其全部依赖项进行构建。这就是您的构建过程。咱们讨论了分离配置信息,所以须要将其与构建结合在一块儿以发布版本。自动运行应用程序或应用程序的多个副本的能力正是Kubernetes像Deployments,ReplicaSets和DaemonSets那样构造的。
12因素应用程序的原则6是“将应用程序做为一个或多个无状态进程执行”。
无状态进程是云本机应用程序背后的核心思想。每一个十二要素应用程序都须要在单独的,无共享的流程中运行。这意味着,每当您须要保留信息时,就须要将其存储在数据库等支持服务中。
若是您是云应用程序编程的新手,那么这看似简单。许多开发人员习惯于“粘性”会话,并在下一个请求将到达同一服务器的状况下将信息存储在会话中。可是,在云应用程序中,绝对不能作这个假设。
相反,若是您运行的是托管特定Pod的多个副本的基于Kubernetes的应用程序,则必须假定后续请求能够到达任何地方。要解决此问题,您将须要使用某种后备卷或数据库来实现持久性。
对此原则的一个警告是,Kubernetes StatefulSets可使您建立具备稳定网络身份的Pod,所以从理论上讲,您能够将请求定向到特定Pod。从技术上讲,若是该过程实际上没有存储状态,而且能够删除和从新建立Pod并仍能正常运行,那么它能够知足此要求。
12 Factor App的原则7是“经过端口绑定导出服务”。
在咱们假设不一样功能由不一样进程处理的环境中,很容易就能够经过诸如HTTP之类的协议来实现这些功能的链接,所以,一般在Web服务器(如Apache)以后运行应用程序或Tomcat。可是,十二要素应用程序不该该以这种方式依赖于其余应用程序。请记住,每一个功能都应处于本身的进程中,与其余全部事物隔离。相反,《 12因子应用宣言》建议添加一个Web服务器库或与应用自己相似的东西,以便该应用能够在已定义的端口上等待请求,不管是使用HTTP仍是其余协议。
在基于Kubernetes的应用程序中,这部分是经过应用程序自己的体系结构完成的,部分是经过确保应用程序具备全部依赖项做为建立应用程序所基于的基础容器的一部分来完成的。
12 Factor App的原则8是“经过进程模型进行横向扩展”。
在编写包含十二个要素的应用程序时,请确保将其设计为横向扩展而不是纵向扩展。这意味着,为了增长容量,您应该可以向运行该应用程序的计算机添加更多实例,而不是添加更多内存或CPU。请注意,这特别意味着可以在其余计算机上启动其余进程,幸运的是,这是Kubernetes的一项关键功能。
12 Factor App的原则9是“经过快速启动和平稳关闭来最大化鲁棒性”。
彷佛该原理是针对容器和基于Kubernetes的应用程序量身定制的。进程应为一次性的想法意味着,在任什么时候候,一个应用程序均可能死亡,而且不会由于任何其余事情要代替它,由于它会从新启动而对用户形成影响,或者二者兼而有之。
固然,容器是基于此原理构建的,即便面对问题(例如ReplicaSets),Kubernetes结构也能够管理多个实例并保持必定级别的可用性,从而构成了完整的部署。
12因素应用程序的原则10是“保持开发,测试和生产尽量类似”。
这彷佛是另外一条原则,但彷佛比大多数人认为的要深。从表面上看,这确实意味着您应具备尽量相同的开发,阶段和生产环境。实现此目的的一种方法是使用Kubernetes命名空间,使您可以(理论上)在相同的实际集群上针对相同的实际系统运行代码,同时仍保持环境分离。在某些状况下,您还可使用Minikube或kubeadm-dind-cluster之类的工具来建立生产系统的近克隆。
不过,从更深层次上讲,如《十二个因子》应用宣言所说,它涉及三种不一样类型的“鸿沟”:
这里的目标是建立一个持续集成/持续部署的状况,在这种状况下,更改几乎能够当即投入生产(固然,在测试以后!),由编写该更改的开发人员进行部署,以便他们能够实际使用相同的版本在生产中看到它。实际编写代码的工具,以最大程度地减小环境之间的兼容性错误的可能性。
固然,其中一些因素不在Kubernetes的范围内。例如,人员缺口是一个文化问题。可是,时间和工具上的差距能够经过两种方式来弥补。
对于时间间隔,基于Kubernetes的应用程序固然基于容器,而容器自己是基于存储在版本控制系统中的镜像的,所以它们适合CI / CD。还能够经过滚动更新来更新它们,若是出现问题能够回滚,所以它们很是适合这种环境。
就工具差距而言,基于Kubernetes的应用程序的体系结构使管理变得更加容易,既能够经过简化本地依赖关系将其包含在各类镜像中,也能够经过模块化应用程序以使外部支持服务成为可能。标准化。
12 Factor App的原则11是“将日志做为事件流处理”。
尽管大多数传统应用程序将日志信息存储在文件中,但十二要素应用程序却将其做为事件流定向到stdout。执行环境负责收集这些事件。这可能就像将stdout重定向到文件同样简单,可是在大多数状况下,它涉及使用日志路由器(例如Fluentd)并将日志保存到Hadoop或服务(例如Splunk)。
在Kubernetes中,您至少有两个选择能够进行自动日志记录捕获:若是您使用的是Google Cloud,则为Stackdriver Logging;若是您不使用的是,则为Elasticsearch。
12 Factor App的原则12是“将管理/管理任务做为一次性进程运行”。
该原则涉及将管理任务(如迁移数据库或检查记录)与应用程序的其他部分分开。尽管它们是分开的,可是它们仍必须在与应用程序相同的环境中运行,而且在与应用程序相同的基本代码和配置下运行,而且它们的代码必须与应用程序一块儿提供,以防止漂移。
您能够在基于Kubernetes的应用程序中以多种不一样方式实现此功能,具体取决于应用程序自己的大小和规模。例如,对于小型任务,您可使用kubectl exec在特定的容器上进行操做,也可使用Kubernetes做业来运行独立的应用程序。可是,对于涉及变动编排的更复杂的任务,您还可使用Kubernetes Helm。
除非您仍在构建桌面应用程序,不然您颇有可能会遇到至少一些十二要素应用程序的基本原则。可是,您可能还会发现至少一两个可能会更加努力地工做。