原文转自InfoQ

一、K8s与云原生应用

过去两年,容器和容器镜像已经成为了开发云原生应用所必不可少的技术。K8s平台的设计开发者以及K8s社区的技术人员,在不断推进K8s作为容器管理平台的快速发展的同时,也在探索如何帮助应用的设计开发者更好地运用容器技术进行云原生应用的开发。云原生应用本身必然是分布式系统,因此分布式系统的经验必然适用于云原生应用;只是一般的云原生应用,更多的借助像K8s或Mesos这样的平台来解决主要的分布式系统的问题。

笔者认为K8s社区人员设计K8s系统是基于两种非常重要的经验:一是Google多年来运行大型分布式系统的经验,二是支撑快速更新、敏捷迭代的云原生应用的经验。前者保证了K8s系统本身的稳定性和扩展性,后者保证了K8s系统对其用户,也就是云原生应用的运维人员和开发人员的有效性。本文将主要介绍K8s系统对云原生应用的支持。

二、K8s云原生应用技术理念的支持

1.代码仓库与部署

云原生应用理念要求严格区分应用的代码和部署。在K8s集群中与其相对应的就是Deployment操作对象。在K8s集群中,每一个微服务Service操作对象就是对应一个应用代码仓库,每个Service对应多个Deployment,正好服务一个应用多次部署的理念。

2.环境配置

云原生应用理念要求将环境配置存在应用运行的环境中,在K8s集群中,所有的环境配置都存在分布式共享存储Etcd中。K8s还有一些操作对象是用来专门存储环境配置的。例如ConfigMap是存储通用的配置变量的。ConfigMap有点儿像一个统一的配置文件,使用户可以将分布式系统中用于不同模块的环境变量统一到一个对象中管理;而它与配置文件的区别在于它是存在集群的“环境”中的,并且支持K8s集群中所有通用的操作调用方式。再比如Secret是专门用来存储密钥对象的,它使得在K8s集群中用到密码等私密信息时不必用明文环境变量来表示,从而加强密钥传递和保存的安全性。

3. 后台支撑服务

云原生应用理念要求将后台支撑服务作为挂载资源来使用。在K8s集群中,所有的应用服务都可以被当作一种资源去访问和引用。K8s集群可以通过SkyDNS在支持DNS域名服务,所有在集群中部署的服务都可以通过以.模式的DNS域名来访问。当然,后台支撑服务也可以是来自于集群外。不论来自哪里,这些服务都可以用以DNS:Port或IP:Port来标识的一个资源来表示,而资源的使用者可以通过ConfigMap来存储这个资源的配置,这样需要访问这个资源的应用就可以同通过ConfigMap来引用这个资源。

4. 无状态微服务实例

云原生应用理念要求应用是无状态的,对应实际环境中,就是要求应用不应该将数据存储在运行应用的主机节点上,所有状态存储在由云环境统一管理的共享存储之上,而这正是K8s中的微服务实例Pod的模型。在K8s集群中,Pod可以绑定多种存储驱动,除了emptyDIR和hostPath以外,K8s支持的多种存储驱动都是对接共享存储的。由于emptyDIR上存储的东西是临时可丢弃的,而hostPath主要用于测试,除此以外所有用于生产环境的存储都是对接共享存储的,因此可以说,K8s的存储机制是为无状态化的云原生应用而设计的。

5. 端口映射

云原生应用理念要求应用可以根据设定的端口直接对外发布服务。在K8s集群中,集群内部访问服务的端口是通过ContainerPort属性来设置的。对于需要集群外客户端访问的服务,可以有nodePort、loadBalancer和Ingress等模式接入外网访问,其中nodePort是将服务发布到K8s集群中的每个主机节点。

6.并发和水平扩展

云原生应用理念要求应用可以水平扩展以根据业务需求随时扩展计算能力,而K8s的Replication Controller操作对象和Replica Set操作对象就是支持水平扩展能力的。

7.快速启动和优雅终结

云原生应用理念要求应用能够快速启动和优雅地终结,这同时也要求云平台能够处理容器启动和终结时的超时等故障情况。在K8s集群中,有两个操作对象跟微服务实例的故障处理相关,一个是微服务实例Pod,另一个是探针Probe。其中Pod的terminationGracePeriodSeconds属性设置微服务终结时等待的时间,这段时间留给微服务自身在退出前释放资源。其中Pod的activeDeadlineSeconds属性设置微服务启动时等待的时间,如果应用超过这个时间,就不符合“云原生应用”的要求,要被云平台标识成启动失败了。Probe操作对象是K8s系统和应用用来检查应用健康状况的。K8s系统提供两种探针LivenessProbe和ReadynessProbe。前者探测容器是否还正常,后者探测容器是否能提供服务,前者是后者前提。

8.配置共享和环境隔离

云原生应用理念要求尽量保证开发、测试和生产环境的配置一致,但是同时这几个不同的环境又应该是彼此隔离。在K8s集群中,不同的环境可以通过namespace进行隔离,保证彼此不互相干扰,例如可以有dev、test、staging和production等4个不同环境。对于不同环境中应该保持相同的配置,可以通过持续集成工具例如Jenkins Pipeline的脚本保持一致。

9.集中日志处理

云原生应用理念要求对应用日志有集中的处理,这其实是对应用管理平台的要求。在K8s集群中一个得到广泛接受的日志解决方案是fluentd+elasticsearch+Kibana的日志收集处理方案,其中Fluentd用来收集日志,Elasticsearch用来存储、索引和查询日志,Kibana用来以图形界面展示日志的统计信息。

10.管理服务

云原生应用理念要求将管理任务作为一次性任务运行,相当于针对管理对象执行了一笔管理交易。K8s集群中的Deployment操作对象就是对这一理念的最好反映。Deployment对象是用来管理Pod和ReplicaSet的,Pod是一个微服务实例,而ReplicaSet是一组相同的微服务实例,即最新版的Replication Controller。Deployment对Pod和ReplicaSet的管理操作,就相当于对K8s集群中的服务做了一次交易,对服务做创建或者更新的操作。

三、K8s操作对象对云原生应用理念的支持

从前面对K8s操作对象和云原生应用理念的解读可以发现,如下图所示,作为一个容器编排管理系统,K8s对云原生应用理念中所有非开发构建期的理念都有了很好的支持。
这里写图片描述

四、分布式系统设计模式

在程序设计领域,面向对象设计和面向对象语言是大家最为熟悉和强大的工具,而面向对象除了其强大的核心特性之外,还有人们通过实践总结出来的一系列设计模式,可以用来解决实际应用设计中的一些复杂问题。云原生应用运行的环境都是复杂的分布式环境,在这种情况下,一些有用的设计模式可以起到四两拨千斤的作用,而K8s社区推出的容器设计模式,则是结合了K8s集群的微服务模型提出的一系列可重用的解决典型分布式系统问题的模式。容器设计模式与传统的面向对象设计模式的最明显地区别在于,容器设计模式是跨编程语言的,这个当然也来自于容器本身的编程语言无关性。
这里写图片描述

  • 跨斗模式(Sidecar pattern)
    是一种单个Pod含多个容器的服务模式,多容器通过共享文件系统形成本地通信,共同提供一个微服务。

  • 外交官模式(Ambassador pattern)

一种单个Pod含多个容器的服务模式,应用容器和外交官容器共享一个网络IP地址,应用容器利用这个可重用的外交官容器作为代理来访问远程服务或资源。

  • 适配器模式(Adapter pattern)

一种单个Pod含多个容器的服务模式,应用容器提供应用功能,同时和一个适配器容器共享文件系统和一个网络IP地址,分布式系统管理平台可以利用适配器容器的统一接口,从应用容器收集日志和监控数据等信息。

  • 选举模式(Election pattern)
    是一种多节点组合服务模式。一个可重用的选举器容器跟应用容器组合起来,提供为在分布式系统中的多个应用实例选举主控节点的问题。

  • 工作队列模式(Work queue pattern)
    是一种多节点组合服务模式。应用容器跟可重用的队列消息处理器,共同工作,可以并行地处理队列中海量的同类型并行计算业务。

  • 分散收集模式(Scatter/gather pattern)
    是一种多节点组合服务模式,通过先将大任务分割成诸多小任务处理,在收集汇总合并产生最终结果的模式,支持复杂任务的分布式计算。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐