背景
应该是去年在摸索servicemesh时,看过些关于Kubernetes资料(主要是ppt载体的信息),也部署并体验了一番Openshift,同时留下过两篇关于servicemesh和Kubernetes的两篇文章。
但个人感觉以前的了解是有点片面和零散(其实网上大多分享都是如此哈)。这次组里需要评估分析下Dubbo在云原生的思路,所以这几天我就花了些时间温习了这块的知识,看了《Docker实践》《Kubernetes实战》两本书,希望能够全面而分层次地做一些记录。
为了说清楚云原生,先从三个问题开始,希望大家能自己思考下。
三个问题
- docker是为了解决什么问题出现的?提供了哪些核心能力?
- Kubernetes是为了解决什么问题出现的? 在容器化基础上增加了哪些核心能力?
- ServiceMesh是为了解决什么问题出现的? 在k8s基础上增加了哪些核心能力?
Docker记录
这里主要是阅读《Docker实践》的记录。
Docker是一种Linux容器工具集,它是为构建(Build)、交付(Ship)和运行(Run)分布式应用而设计的。容器化保证应用的独立可重复性;虚拟化来保证物理主机安全的功能模式。
Docker的本质
- Docker首先是一种契约,是串联了整个应用生命周期的契约,核心价值是加快软件交付的效率,提高生产力。
- Docker与虚拟机的定位是本质不一样的,Docker并不是一项虚拟机技术(这其实是容器技术与虚拟机技术的区别)。它不会模拟一台机器的硬件。Docker定位于应用侧,是对应用(包括其配置,环境依赖)的封装——通过标准化的dockerfile规范,而虚拟机定位于OS层,偏重于资源管理。
- Docker也可以与Chef,Jenkins做深度整合。
- Docker的Hub是其应用程序的管理中心,最能够体现其应用侧的特性,每个镜像都可以命名,tag,唯一ID。
与软件各环节的结合
Docker与开发: 开发环境的一致,进程即环境;传统配置工具(make,chef,puppet等)与Docker协作;构建更小的镜像;Docker对于开发的友好性,最好隐藏dockerfile,使得source到Image自动化。
Docker与Devops:从Git到Docker Hub到Jecksin的自动化工作流;从持续提交(source)-》持续集成(test) -》持续部署(蓝布发布,灰度发布等)-》持续交付(版本管理,基础环境的整体搭建,资源按需伸缩);
Docker与生产环境:其实就是swarm,Kubernetes等PaaS层的东东的用武之地。
- 多宿主机情况下容器的运行时状态和配置管理
- 多宿主机情况下容器间的“串联编排”,安全,日志,问题诊断排查等服务管理
Kubernetes记录
前面说了有了Docker化后的应用后,需要一平台级的东东来管理这些Docker容器。以下是阅读《Kubernetes实战》的一些点。
为什么K8S
Kubernetes的流行跟Docker是息息相关:Docker的流行激活了一直不温不火的PaaS。Kubernetes可以说是Google借助着容器领域的爆发,对于其巨大规模数据中心管理的丰富经验的一次实践,旨在建立新的技术业界标准。Google从2004年起就已经开始使用容器技术了,于2006年发布了Cgroup,而且内部开发了强大的集群资源管理平台Borg和Omega,这些都已经广泛使用在Google的各个基础设施中,而Kubernetes的灵感来源于Google的内部Borg系统,更是吸收了包括Omega在内的容器管理器的经验和教训。
抛个问题吧。为什么Kubernetes在最早的compose,swarm,甚至mesos中能够脱颖而出? 这个跟它的模型抽象(也对应了核心概念)是有很大关系。
核心概念
- Pod:是若干相关容器的组合,Pod包含的容器运行在同一台宿主机上,这些容器使用相同的网络命名空间、IP地址和端口,相互之间能通过localhost来发现和通信。另外,这些容器还可共享一块存储卷空间。在Kubernetes中创建、调度和管理的最小单位是Pod,而不是容器,Pod通过提供更高层次的抽象,提供了更加灵活的部署和管理模式。
- Controller: 控制器,是任务执行的逻辑载体,有Controller Manager负载调度执行。ReplicationController是其中之一的具体实现,是弹性伸缩、滚动升级的实现核心。基本上每种实体model都会有对应的controller,比如Node,Service,Endpoint,SA,PV,Deployment,Job等等,也可以扩展实现自己的controller。
- Service:是真实应用服务的抽象,定义了Pod的逻辑集合和访问这个Pod集合的策略。Service将代理Pod对外表现为一个单一访问接口,外部不需要了解后端Pod如何运行,这给扩展和维护带来很多好处,提供了一套简化的服务代理和发现机制。另外,Service不仅可以代理Pod,还可以代理任意其他后端,比如运行在Kubernetes外部的服务——这时候不需要selector,但需要手动定义对应的与Service同名的Endpoint。
- Label:键值对,可以对POD做标准,实现service,RC对于POD的松耦合。
- Node: 宿主机?
架构设计
list-watch事件的控制器模式
CI/CD主流选型对比
持续集成与持续部署(Continuous Integration & Deployment)应该是最能体现PaaS平的特色之处,各家云厂商都在基于Kubernetes提供PaaS服务,在CI/CD上的产品特性和用户使用体验是区分这一服务的重要之处。 下图是从别处Copy来的简单对比。个人理解,广义上的CI/CD应该包含从创建项目开始,囊括了需求管理,设计管理,到代码管理,到环境配置,到代码(镜像)构建,最后到日常/测试/预发/灰度/线上等环境的部署,这可能也算是核心切入点之一吧,也就是发挥集成优势,打通相关环节,提供一站式应用服务。
可以花点时间了解以下主流的CI/CD,取长补短:
- Jenkins:Hudson?️,采用Java实现,用的最广泛。
- Teamcity:10年前曾经用过一点点,留下了功能更多更强的印象。
- CircleCI
- Travis CI:Apache的项目都是基于TC来做集成测试,每次PR都有TC任务,做单元测试,同时做各种代码规范的检查。
- Drone:
API对象与元数据
无论是pod,Service,还是Node,Endpoint,PV等等都是Kubernetes的基本对象,有三种方式来访问和操作这些对象。
- 命令行工具kuberctl:一般演示中都是基于此。
- 直接访问Rest API:Kubernetes API Server作为Kubernetes系统的入口,以REST API接口方式提供给外部调用,同时集成了Swagger来做API的定义描述。
- SDK:比如Java中fabric8提供了Kubernetes-client。
API对象的元数据用来定义API对象的基本信息,体现在定义中的metadata字段,包含以下属性。
•namespace:指定API对象所在的Namespace。
•name:指定API对象的名称。
•labels:设置API对象的Label。
•annotations:设置API对象的Annotation。
Namespace
Namespace是Kubernetes提供的多租户,不同的项目、团队或者用户可以通过Namespace进行区分管理,并且设置安全控制和其他策略。绝大部分API对象(除了Node)归属于Namespace,API对象通过.metadata.namespace指定Namespace,如果没有指定Namespace,那么就是归属于默认Namespace default。
Name
名称是一个重要的属性,是人类可读的,元数据中的.metadata.name用于指定API对象的名称。Kubernetes系统中的API对象必须能够通过名称唯一标识,Kubernetes包含Namespace的逻辑层级,大部分API对象必须归属于Namespace,所以这些API对象的名称必须在Namespace内唯一。而另外对于Node和Namespace来说,需要在Kubernetes系统中唯一。
Label
Label用于区分API对象的Key/Value对,Label存放的应该是具有标识性的数据,Kubernetes通过Label可以对API对象进行选择。ReplicationController和Service都是通过Label关联Pod,而Pod也可以通过Label选择Node。
Annotation
Annotation用于存放用户的自定义数据,Annotation存放的是非标识的数据,所以不能像Label一样进行对象选择。但是Annotation的数据可以是长数据,可以有结构或者无结构,作为Label的一种补充,Annotation也是Key/Value对。
ServiceMesh相关
这部分不谈sidecar,也不谈Envoy和Dubbo的区别,具体可以看上面提到的两篇文章。个人认为,ServiceMesh最核心的点还是控制面的能力,也就是Istio相关的事情。Istio如果model定义得足够标准且可扩展,以至于成为像Kubernetes成为事实上的容器应用的PaaS标准,那么无论Dubbo,还是envoy,还是Nginx,还是Conduit都会作为一种可选的方式来接入,就像用户(一般是开发者)只看到的是Kubernetes,而无需关注Docker还是其他CRI的实现。
所以,下面着重把istio定义的一些model来做个记录。
Istio的设计第一要务
一句话理解就是先做service的基本模型抽象,继而允许适配到具体的容器调度平台上,无论pilot还是mixer。
Istio的模型
Istio Services Model Introduction |
|
Services Model: Services |
|
Services Model: Instances |
Each service has one or more instances, i.e., actual manifestations of the service.
|
Services Model: Service Versions |
|
Services Model: Labels |
|
Services Model: Routing |
• Services have no knowledge of different versions of the Service being accessed. • Services are simply accessed using the Network Endpoint of the Service. • The proxy is responsible for routing the connection/request to the appropriate Versionbased on the routing rules set up by the user and pushed to Istio-Manager. |
云原生的自问自答
- 何为云原生?当前各有理解,但基本是围绕CNCF的定义来展开。CNCF做了这样的定义:
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。
这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。
云原生计算基金会(CNCF)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。
- 云原生是核心价值和意义在哪里?我们能做什么才不会被Google,Redhat,Pivital等“意识形态”所带偏?狭义上的云原生是以Kubernetes为基石,那传统的微服务方案是要如何改造来融入?
前面一个问题估计就是个人云亦云,很可能被人带着走的,走入被人牵着鼻子的境地。云原生首先是一种思想,而Kubernetes是提出这套思想的CNCF所推崇的最佳实践和核心,无论是CNCF的Landscape还是Trail Map都能看出Kubernetes的无处不在,所以在我们无法准确表述云原生思想和没有自己的服务云原生的实现情况下,从狭义上理解Kubernetes≈≈云原生,通过应用和实践Kubernetes来慢慢理云原生思想无疑是最合适。
传统意义上的微服务方案Dubbo/HSF融合到CNCF Landscape,成为其一等公民,从而享受到这个生态的服务红利,同时也要展示出自己的特色,有其独特的吸引力来立足,说白了让大家知道Dubbo也是先进的“时髦”的微服务方案,这个问题才是核心,但回答这个问题,好难!期待有人能答疑解惑。
简单说来,云原生(Cloud Native)是伴随的容器技术发展出现的的一个词,需要应用符合一些特质如无状态、可持续交付、微服务化等。Kubernetes与云原生概念两者互相成就,一起推波助澜,基本上形成了当前新一代PaaS的基石。云原生的流行本质上是开放开源的流行:开放意外着可扩展且共建,开源意味着可控且快速迭代。
从一定角度看,以Kubernetes为基石来落ServiceMesh最终拥抱云原生这条路应该是比较切实际。