Kubernetes application deployment model analysis (principle)

[Editor's note] Kubernetes can be used to manage Linux container clusters, accelerate development and simplify operation and maintenance (ie DevOps). However, the articles about Kubernetes on the Internet are far more introductory than practical. This series of articles takes you up to speed quickly with Kubernetes by focusing on real-world deployments. This article is the first part, which mainly introduces the principles and concepts that need to be understood before deployment, including the component structure of Kubernetes, the functions of each component role, and the application model of Kubernetes.


Google has been running its business with containers in production for more than a decade, and the system responsible for managing its container clusters is Borg, the predecessor of Kubernetes. In fact, many Google developers working on the Kubernetes project have previously worked on the Borg project. Most of the Kubernetes application deployment models originated from Borg, and understanding these models is the key to mastering Kubernetes. The API version of Kubernetes is currently v1. This article introduces its application deployment model based on the code version 0.18.2. Finally, we use a simple use case to illustrate the deployment process. After the deployment, it explains how it uses Iptables rules to implement various types of services.

 

Kubernetes Architecture

 

A Kubernetes cluster includes two roles: Kubernetes agents (agents) and Kubernetes services (master node) . The components of the proxy role include Kube-proxy  and Kubelet , which are deployed on a node at the same time, which is also the proxy node. The components of the service role include kube-apiserver , kube-scheduler , kube-controller-manager , which can be distributed arbitrarily, and they can be deployed on the same node or on different nodes (the current version doesn't seem to work). The third-party components that Kubernetes clusters rely on currently include etcd and docker . The former provides state storage, and the two are used to manage containers. Clusters can also use distributed storage to provide storage space for containers. The following diagram shows the components of the current system:

 

Kubernetes agent node

Kubelet and Kube-proxy run on proxy nodes. They listen to service node information to start containers and implement Kubernetes networking and other business models, such as Service, Pod, etc. Of course each agent node runs Docker. Docker is responsible for downloading container images and running containers.

 

 

Kubelet

 

The Kubelet component manages information about Pods and their containers, images, and volumes.

 

Kube-Proxy

Kube-proxy is a simple web proxy and load balancer. It specifically implements the Service model, and each Service will be reflected on all Kube-proxy nodes. According to the Pods covered by the Service 's selector , Kube-proxy will load balance these Pods to serve the Service 's visitors.

 

 

Kubernetes service node

The Kubernetes service components form the Kubernetes control plane, currently they run on a single node, but will be deployed separately in the future to support high availability.

 

 

etcd

All persistent state is kept in etcd. Etcd also supports watch, so that components can easily get the changes of system state, so as to quickly respond and coordinate work.

 

 

Kubernetes API Server

This component provides support for the API, responds to REST operations, validates the API model and updates the corresponding objects in etcd.

 

 

Scheduler

By accessing the /binding API in Kubernetes, the Scheduler is responsible for the allocation of Pods on each node. Scheduler is plug-in, Kubernetes can support user-defined scheduler in the future.

 

 

Kubernetes Controller Manager Server

The Controller Manager Server is responsible for all other functions, such as the endpoints controller is responsible for the creation and update of the Endpoints object. The node controller is responsible for node discovery, management and monitoring. In the future these controllers may be split and pluggable implementations provided.

 

 

Kubernetes模型

Kubernetes的伟大之处就在于它的应用部署模型,主要包括Pod、Replication controller、Label和Service。

 

 

Pod

Kubernetes的最小部署单元是Pod而不是容器。作为First class API公民,Pods能被创建,调度和管理。简单地来说,像一个豌豆荚中的豌豆一样,一个Pod中的应用容器同享同一个上下文:

 

 

  1. PID 名字空间。但是在docker中不支持
  2. 网络名字空间,在同一Pod中的多个容器访问同一个IP和端口空间。
  3. IPC名字空间,同一个Pod中的应用能够使用SystemV IPC和POSIX消息队列进行通信。
  4. UTS名字空间,同一个Pod中的应用共享一个主机名。
  5. Pod中的各个容器应用还可以访问Pod级别定义的共享卷。

 

从生命周期来说,Pod应该是短暂的而不是长久的应用。 Pods被调度到节点,保持在这个节点上直到被销毁。当节点死亡时,分配到这个节点的Pods将会被删掉。将来可能会实现Pod的迁移特性。在实际使用时,我们一般不直接创建Pods, 我们通过replication controller来负责Pods的创建,复制,监控和销毁。一个Pod可以包括多个容器,他们直接往往相互协作完成一个应用功能。

 

Replication controller

复制控制器确保Pod的一定数量的份数(replica)在运行。如果超过这个数量,控制器会杀死一些,如果少了,控制器会启动一些。控制器也会在节点失效、维护的时候来保证这个数量。所以强烈建议即使我们的份数是1,也要使用复制控制器,而不是直接创建Pod。

 

在生命周期上讲,复制控制器自己不会终止,但是跨度不会比Service强。Service能够横跨多个复制控制器管理的Pods。而且在一个Service的生命周期内,复制控制器能被删除和创建。Service和客户端程序是不知道复制控制器的存在的。

复制控制器创建的Pods应该是可以互相替换的和语义上相同的,这个对无状态服务特别合适。

Pod是临时性的对象,被创建和销毁,而且不会恢复。复制器动态地创建和销毁Pod。虽然Pod会分配到IP地址,但是这个IP地址都不是持久的。这样就产生了一个疑问:外部如何消费Pod提供的服务呢?

 

Service

Service定义了一个Pod的逻辑集合和访问这个集合的策略。集合是通过定义Service时提供的Label选择器完成的。举个例子,我们假定有3个Pod的备份来完成一个图像处理的后端。这些后端备份逻辑上是相同的,前端不关心哪个后端在给它提供服务。虽然组成这个后端的实际Pod可能变化,前端客户端不会意识到这个变化,也不会跟踪后端。Service就是用来实现这种分离的抽象。

 

对于Service,我们还可以定义Endpoint,Endpoint把Service和Pod动态地连接起来。

 

Service Cluster IP和 kuber proxy

每个代理节点都运行了一个kube-proxy进程。这个进程从服务进程那边拿到Service和Endpoint对象的变化。 对每一个Service, 它在本地打开一个端口。 到这个端口的任意连接都会代理到后端Pod集合中的一个Pod IP和端口。在创建了服务后,服务Endpoint模型会体现后端Pod的 IP和端口列表,kube-proxy就是从这个endpoint维护的列表中选择服务后端的。另外Service对象的sessionAffinity属性也会帮助kube-proxy来选择哪个具体的后端。缺省情况下,后端Pod的选择是随机的。可以设置service.spec.sessionAffinity "ClientIP"来指定同一个ClientIP的流量代理到同一个后端。在实现上,kube-proxy会用IPtables规则把访问Service的Cluster IP和端口的流量重定向到这个本地端口。下面的部分会讲什么是service的Cluster IP。

 

注意:在0.18以前的版本中Cluster IP叫PortalNet IP。

 

内部使用者的服务发现

Kubernetes在一个集群内创建的对象或者在代理集群节点上发出访问的客户端我们称之为内部使用者。要把服务暴露给内部使用者,Kubernetes支持两种方式:环境变量和DNS。

 

 

环境变量

当kubelet在某个节点上启动一个Pod时,它会给这个Pod的容器为当前运行的Service设置一系列环境变量,这样Pod就可以访问这些Service了。一般地情况是{SVCNAME}_SERVICE_HOSTh{SVCNAME}_SERVICE_PORT变量, 其中{SVCNAME}Service名字变成大写,中划线变成下划线。比如Service "redis-master",它的端口是 TCP  6379,分配到的Cluster IP地址是 10.0.0.11,kubelet可能会产生下面的变量给新创建的Pod容器:

 

REDIS_MASTER_SERVICE_HOST= 10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR= 10.0.0.11

注意,只有在某个Service后创建的Pod才会有这个Service的环境变量。

 

DNS

一个可选的Kubernetes附件(强烈建议用户使用)是DNS服务。它跟踪集群中Service对象,为每个Service对象创建DNS记录。这样所有的Pod就可以通过DNS访问服务了。

 

比如说我们在Kubernetes 名字空间"my-ns"中有个叫my-service的服务,DNS服务会创建一条"my-service.my-ns"的DNS记录。同在这个命名空间的Pod就可以通过"my-service"来得到这个Service分配到的Cluster IP,在其它命名空间的Pod则可以用全限定名"my-service.my-ns"来获得这个Service的地址。

 

Pod IP and Service Cluster IP

Pod IP 地址是实际存在于某个网卡(可以是虚拟设备)上的,但Service Cluster IP就不一样了,没有网络设备为这个地址负责。它是由kube-proxy使用Iptables规则重新定向到其本地端口,再均衡到后端Pod的。我们前面说的Service环境变量和DNS都使用Service的Cluster IP和端口。

 

就拿上面我们提到的图像处理程序为例。当我们的Service被创建时,Kubernetes给它分配一个地址10.0.0.1。这个地址从我们启动API的service-cluster-ip-range参数(旧版本为portal_net参数)指定的地址池中分配,比如--service-cluster-ip-range=10.0.0.0/16。假设这个Service的端口是1234。集群内的所有kube-proxy都会注意到这个Service。当proxy发现一个新的service后,它会在本地节点打开一个任意端口,建相应的iptables规则,重定向服务的IP和port到这个新建的端口,开始接受到达这个服务的连接。

当一个客户端访问这个service时,这些iptable规则就开始起作用,客户端的流量被重定向到kube-proxy为这个service打开的端口上,kube-proxy随机选择一个后端pod来服务客户。这个流程如下图所示:

根据Kubernetes的网络模型,使用Service Cluster IP和Port访问Service的客户端可以坐落在任意代理节点上。外部要访问Service,我们就需要给Service外部访问IP。

 

外部访问Service

Service对象在Cluster IP range池中分配到的IP只能在内部访问,如果服务作为一个应用程序内部的层次,还是很合适的。如果这个Service作为前端服务,准备为集群外的客户提供业务,我们就需要给这个服务提供公共IP了。

 

外部访问者是访问集群代理节点的访问者。为这些访问者提供服务,我们可以在定义Service时指定其spec.publicIPs,一般情况下publicIP 是代理节点的物理IP地址。和先前的Cluster IP range上分配到的虚拟的IP一样,kube-proxy同样会为这些publicIP提供Iptables 重定向规则,把流量转发到后端的Pod上。有了publicIP,我们就可以使用load balancer等常用的互联网技术来组织外部对服务的访问了。

spec.publicIPs在新的版本中标记为过时了,代替它的是spec.type=NodePort,这个类型的service,系统会给它在集群的各个代理节点上分配一个节点级别的端口,能访问到代理节点的客户端都能访问这个端口,从而访问到服务。

 

Label和Label selector

Label标签在Kubernetes模型中占着非常重要的作用。Label表现为key/value对,附加到Kubernetes管理的对象上,典型的就是Pods。它们定义了这些对象的识别属性,用来组织和选择这些对象。Label可以在对象创建时附加在对象上,也可以对象存在时通过API管理对象的Label。

 

在定义了对象的Label后,其它模型可以用Label 选择器(selector)来定义其作用的对象。

Label选择器有两种,分别是Equality-basedSet-based

比如如下Equality-based选择器样例:

 

environment = production
tier != frontend
environment = production,tier != frontend

 

对于上面的选择器,第一条匹配Label具有environment key且等于production的对象,第二条匹配具有tier key,但是值不等于frontend的对象。由于kubernetes使用AND逻辑,第三条匹配production但不是frontend的对象。

Set-based选择器样例:

 

environment in (production, qa)
tier notin (frontend, backend)
partition

 

第一条选择具有environment key,而且值是production或者qalabel附加的对象。第二条选择具有tier key,但是其值不是frontendbackend。第三条选则具有partition key的对象,不对value进行校验。

replication controller复制控制器和Service都用labellabel selctor来动态地配备作用对象。复制控制器在定义的时候就指定了其要创建PodLabel和自己要匹配这个Podselector, API服务器应该校验这个定义。我们可以动态地修改replication controller创建的PodLabel用于调式,数据恢复等。一旦某个Pod由于Label改变replication controller移出来后,replication controller会马上启动一个新的Pod来确保复制池子中的份数。对于ServiceLabel selector可以用来选择一个Service的后端Pods

 

http://www.csdn.net/article/2015-06-11/2824933

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326619416&siteId=291194637