《Kubernetes 与云原生应用》专栏是 InfoQ 向轻元科技首席架构师王昕约稿的系列文章。本专栏包含 8 篇内容,将会从介绍和分析 Kubernetes 系统以及云原生应用入手,逐步推出基于 Kubernetes 的容器设计模式实践案例,希望对计划应用 Kubernetes 的朋友有所帮助。本文是该专栏的第三篇,阅读本系列全部内容请在细说云计算微信公众号(CloudNote)回复 K8s。
1. Kubernetes 系统架构与设计理念 2. 云原生应用的设计理念与挑战 3. Kubernetes 与云原生应用的容器设计模式 4. Kubernetes 容器设计模式实践案例 - 单节点多容器模式 5. Kubernetes 容器设计模式实践案例 - 多节点选举模式 6. Kubernetes 容器设计模式实践案例 - 工作队列模式 7. Kubernetes 容器设计模式实践案例 - 分散收集模式 8. 云原生应用的容器设计模式综述与展望
K8s 与云原生应用
过去两年,容器和容器镜像已经成为了开发云原生应用所必不可少的技术。K8s 平台的设计开发者以及 K8s 社区的技术人员,在不断推进 K8s 作为容器管理平台的快速发展的同时,也在探索如何帮助应用的设计开发者更好地运用容器技术进行云原生应用的开发。云原生应用本身必然是分布式系统,因此分布式系统的经验必然适用于云原生应用;只是一般的云原生应用,更多的借助像 K8s 或 Mesos 这样的平台来解决主要的分布式系统的问题。
笔者认为 K8s 社区人员设计 K8s 系统是基于两种非常重要的经验:一是 Google 多年来运行大型分布式系统的经验,二是支撑快速更新、敏捷迭代的云原生应用的经验。前者保证了 K8s 系统本身的稳定性和扩展性,后者保证了 K8s 系统对其用户,也就是云原生应用的运维人员和开发人员的有效性。本文将主要介绍 K8s 系统对云原生应用的支持。
K8s 云原生应用技术理念的支持
代码仓库与部署
云原生应用理念要求严格区分应用的代码和部署。在 K8s 集群中与其相对应的就是 Deployment 操作对象。在 K8s 集群中,每一个微服务 Service 操作对象就是对应一个应用代码仓库,每个 Service 对应多个 Deployment,正好服务一个应用多次部署的理念。
环境配置
云原生应用理念要求将环境配置存在应用运行的环境中,在 K8s 集群中,所有的环境配置都存在分布式共享存储 Etcd 中。K8s 还有一些操作对象是用来专门存储环境配置的。例如 ConfigMap 是存储通用的配置变量的。ConfigMap 有点儿像一个统一的配置文件,使用户可以将分布式系统中用于不同模块的环境变量统一到一个对象中管理;而它与配置文件的区别在于它是存在集群的“环境”中的,并且支持 K8s 集群中所有通用的操作调用方式。再比如 Secret 是专门用来存储密钥对象的,它使得在 K8s 集群中用到密码等私密信息时不必用明文环境变量来表示,从而加强密钥传递和保存的安全性。
后台支撑服务
云原生应用理念要求将后台支撑服务作为挂载资源来使用。在 K8s 集群中,所有的应用服务都可以被当作一种资源去访问和引用。K8s 集群可以通过 SkyDNS 在支持 DNS 域名服务,所有在集群中部署的服务都可以通过以<name>.<namespace>
模式的 DNS 域名来访问。当然,后台支撑服务也可以是来自于集群外。不论来自哪里,这些服务都可以用以DNS:Port
或IP:Port
来标识的一个资源来表示,而资源的使用者可以通过 ConfigMap 来存储这个资源的配置,这样需要访问这个资源的应用就可以同通过 ConfigMap 来引用这个资源。
无状态微服务实例
云原生应用理念要求应用是无状态的,对应实际环境中,就是要求应用不应该将数据存储在运行应用的主机节点上,所有状态存储在由云环境统一管理的共享存储之上,而这正是 K8s 中的微服务实例 Pod 的模型。在 K8s 集群中,Pod 可以绑定多种存储驱动,除了 emptyDIR 和 hostPath 以外,K8s 支持的多种存储驱动都是对接共享存储的。由于 emptyDIR 上存储的东西是临时可丢弃的,而 hostPath 主要用于测试,除此以外所有用于生产环境的存储都是对接共享存储的,因此可以说,K8s 的存储机制是为无状态化的云原生应用而设计的。
端口映射
云原生应用理念要求应用可以根据设定的端口直接对外发布服务。在 K8s 集群中,集群内部访问服务的端口是通过 ContainerPort 属性来设置的。对于需要集群外客户端访问的服务,可以有 nodePort、loadBalancer 和 Ingress 等模式接入外网访问,其中 nodePort 是将服务发布到 K8s 集群中的每个主机节点。
并发和水平扩展
云原生应用理念要求应用可以水平扩展以根据业务需求随时扩展计算能力,而 K8s 的 Replication Controller 操作对象和 Replica Set 操作对象就是支持水平扩展能力的。
快速启动和优雅终结
云原生应用理念要求应用能够快速启动和优雅地终结,这同时也要求云平台能够处理容器启动和终结时的超时等故障情况。在 K8s 集群中,有两个操作对象跟微服务实例的故障处理相关,一个是微服务实例 Pod,另一个是探针 Probe。其中 Pod 的 terminationGracePeriodSeconds 属性设置微服务终结时等待的时间,这段时间留给微服务自身在退出前释放资源。其中 Pod 的 activeDeadlineSeconds 属性设置微服务启动时等待的时间,如果应用超过这个时间,就不符合“云原生应用”的要求,要被云平台标识成启动失败了。Probe 操作对象是 K8s 系统和应用用来检查应用健康状况的。K8s 系统提供两种探针 LivenessProbe 和 ReadynessProbe。前者探测容器是否还正常,后者探测容器是否能提供服务,前者是后者前提。
配置共享和环境隔离
云原生应用理念要求尽量保证开发、测试和生产环境的配置一致,但是同时这几个不同的环境又应该是彼此隔离。在 K8s 集群中,不同的环境可以通过 namespace 进行隔离,保证彼此不互相干扰,例如可以有 dev、test、staging 和 production 等 4 个不同环境。对于不同环境中应该保持相同的配置,可以通过持续集成工具例如 Jenkins Pipeline 的脚本保持一致。
集中日志处理
云原生应用理念要求对应用日志有集中的处理,这其实是对应用管理平台的要求。在 K8s 集群中一个得到广泛接受的日志解决方案是 fluentd+elasticsearch+Kibana 的日志收集处理方案,其中 Fluentd 用来收集日志,Elasticsearch 用来存储、索引和查询日志,Kibana 用来以图形界面展示日志的统计信息。
管理服务
云原生应用理念要求将管理任务作为一次性任务运行,相当于针对管理对象执行了一笔管理交易。K8s 集群中的 Deployment 操作对象就是对这一理念的最好反映。Deployment 对象是用来管理 Pod 和 ReplicaSet 的,Pod 是一个微服务实例,而 ReplicaSet 是一组相同的微服务实例,即最新版的 Replication Controller。Deployment 对 Pod 和 ReplicaSet 的管理操作,就相当于对 K8s 集群中的服务做了一次交易,对服务做创建或者更新的操作。
K8s 操作对象对云原生应用理念的支持
从前面对 K8s 操作对象和云原生应用理念的解读可以发现,如下图所示,作为一个容器编排管理系统,K8s 对云原生应用理念中所有非开发构建期的理念都有了很好的支持。
(点击放大图像)
K8s 与容器设计模式
在程序设计领域,面向对象设计和面向对象语言是大家最为熟悉和强大的工具,而面向对象除了其强大的核心特性之外,还有人们通过实践总结出来的一系列设计模式,可以用来解决实际应用设计中的一些复杂问题。云原生应用运行的环境都是复杂的分布式环境,在这种情况下,一些有用的设计模式可以起到四两拨千斤的作用,而 K8s 社区推出的容器设计模式,则是结合了 K8s 集群的微服务模型提出的一系列可重用的解决典型分布式系统问题的模式。容器设计模式与传统的面向对象设计模式的最明显地区别在于,容器设计模式是跨编程语言的,这个当然也来自于容器本身的编程语言无关性。
(点击放大图像)
跨斗模式(Sidecar pattern)
是一种单节点多容器组合服务模式,多容器通过共享文件系统形成本地通信,共同提供一个微服务。
外交官模式(Ambassador pattern)
是一种单节点多容器组合服务模式,应用容器和外交官容器共享一个网络IP 地址,应用容器利用这个可重用的外交官容器作为代理来访问远程服务或资源。
适配器模式(Adapter pattern)
是一种单节点多容器提供服务模式,应用容器提供应用功能,同时和一个适配器容器共享文件系统和一个网络IP 地址,分布式系统管理平台可以利用适配器容器的统一接口,从应用容器收集日志和监控数据等信息。
选举模式(Election pattern)
是一种多节点组合服务模式。一个可重用的选举器容器跟应用容器组合起来,提供为在分布式系统中的多个应用实例选举主控节点的问题。
工作队列模式(Work queue pattern)
是一种多节点组合服务模式。应用容器跟可重用的队列消息处理器,共同工作,可以并行地处理队列中海量的同类型并行计算业务。
分散收集模式(Scatter/gather pattern)
是一种多节点组合服务模式,通过先将大任务分割成诸多小任务处理,在收集汇总合并产生最终结果的模式,支持复杂任务的分布式计算。
在本系列文章的后面几篇中,作者将结合实践案例介绍一些常见的容器设计模式。在本文中,我们只是简单介绍模式以留悬念。
感谢魏星对本文的策划和审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论