K8S 名词解释

2018/09/18 k8s
  • CLuster: 集群是指由Kubernetes使用一系列的物理机、虚拟机喝其他基础资源来运行你的应用程序。
  • Node: 一个node就是运营着Kubernetes的物理机或虚拟机,并且pod可以在其上面被调度。
  • Pod: 一个pod队友一个由相关容器和卷组成的容器组。
  • Label: 一个label是一个被附加到资源上的键/值对,譬如附件到一个Pod上,为它传递一个用户自定义的并且可识别的属性,Label还可以被应用来阻止和选择网中的资源。
  • selector: 是一个通过匹配label来定义资源之间关系的表达式,例如为一个负载均衡的service指定所目标Pod。
  • Replication Controller: 是为了保证一定数量被指定的Pod的复制品在任何时间都能正常工作,它不仅允许复制的系统易于扩展,还会处理当pod在机器在重启或发生故障的时候再创建一个。
  • Service: 一个service定义了访问pod的方式,就像单个固定IP地址与其相对应的DNS名之间的关系。
  • Volume: 一个volume是一个目录,可能会被容器作为未见系统的一部分来访问。
  • Kubernetes volume: 构建在Docker Volumes之上,并且支持添加喝配置volume目录或者其他存储设备。
  • Secret: secret存储了敏感数据,例如能允许容器接受请求的权限令牌。
  • Name: 用户为Kubernetes中资源定义的名字。
  • Namespace: namespace好比一个资源名字的前缀。它帮助不同的项目、团队或是客户可以共享cluster,例如防止相互独立的团队间出现命名冲突
  • Annotation:相对于label来说可以容纳更大的键值对,它对我们来说可能是不可读的数据,只是为了存储不可识别的辅助数据,尤其是一些被工具或者系统扩展用来操作的数据。

Pod

一个Pod相当于一个共享context的配置组,在同一个context下,应用可能还会有独立的cgroup隔离机制,一个Pod是一个容器环境下的“逻辑主机”,它可能包含一个或者多个紧密相连的应用,这些应用可能是在同一个物理主机或虚拟机上。

Pod 的context可以列举成多个linux命名空间的联合

  • PID 命名空间 (同一个Pod中应用可以看到其他进程)
  • 网络 命名空间 (同一个Pod中应用对相同的IP地址和端口有权限)
  • IPC 命名空间 (同一个Pod中的应用可以通过VPC或者POSIX进行通信)
  • UTS 命名空间 (同一个Pod中的应用共享一个主机名称)

Label

标签


标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够标示对象的特殊特点,并且对用户而言是有意义的(就是一眼就看出了这个Pod是尼玛数据库),但是标签对内核系统是没有直接意义的。标签可以用来划分特定组的对象(比如,所有女的),标签可以在创建一个对象的时候直接给与,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的

"labels": {
 "key1" : "value1",
 "key2" : "value2"
 } 我们最终会索引并且反向索引(reverse-index)labels,以获得更高效的查询和监视,把他们用到UI或者CLI中用来排序或者分组等等。我们不想用那些不具有指认效果的label来污染label,特别是那些体积较大和结构型的的数据。不具有指认效果的信息应该使用annotation来记录。

Motivation


Label可以让用户将他们自己的有组织目的的结构以一种松耦合的方式应用到系统的对象上,且不需要客户端存放这些对应关系(mappings)。

服务部署和批处理管道通常是多维的实体(例如多个分区或者部署,多个发布轨道,多层,每层多微服务)。管理通常需要跨越式的切割操作,这会打破有严格层级展示关系的封装,特别对那些是由基础设施而非用户决定的很死板的层级关系。

Label例子

“release” : “stable”, “release” : “canary”, …
 “environment” : “dev”, “environment” : “qa”, “environment” : “production”
 “tier” : “frontend”, “tier” : “backend”, “tier” : “middleware”
 “partition” : “customerA”, “partition” : “customerB”, …
 “track” : “daily”, “track” : “weekly” ### Label的语法和字符集 ---- Label其实是一对 key/value,有效的Label keys必须是部分:一个可选前缀+名称,通过/来区分,名称部分是必须的,并且最多63个字符,开始和结束的字符必须是字母或者数字,中间是字母数字和”_”,”-“,”.”,前缀是刻有可无的,如果指定了,那么前缀必须是一个DNS子域,一系列的DNSlabel通过”.”来划分,长度不超过253个字符,“/”来结尾。如果前缀被省略了,这个Label的key被假定为对用户私有的,自动系统组成部分(比如kube-scheduler, kube-controller-manager, kube-apiserver, kubectl),这些为最终用户添加标签的必须要指定一个前缀,Kuberentes.io 前缀是为Kubernetes 内核部分保留的。

合法的label值必须是63个或者更短的字符。要么是空,要么首位字符必须为字母数字字符,中间必须是横线,下划线,点或者数字字母。

Label选择器


与name和UID不同,label不提供唯一性。通常,我们会看到很多对象有着一样的label。

通过label选择器,客户端/用户能方便辨识出一组对象。label选择器是kubernetes中核心的组织原语。

API目前支持两种选择器:基于相等的和基于集合的。一个label选择器一可以由多个必须条件组成,由逗号分隔。在多个必须条件指定的情况下,所有的条件都必须满足,因而逗号起着AND逻辑运算符的作用。

一个空的label选择器(即有0个必须条件的选择器)会选择集合中的每一个对象。

一个null型label选择器(仅对于可选的选择器字段才可能)不会返回任何对象。

Equality-based requirement


基于相等性或者不相等性的条件允许用label的键或者值进行过滤。匹配的对象必须满足所有指定的label约束,尽管他们可能也有额外的label。有三种运算符是允许的,“=”,“==”和“!=”。前两种代表相等性(他们是同义运算符),后一种代表非相等性。例如:

environment = production
 tier != frontend 第一个选择所有键等于 environment 值为 production 的资源。后一种选择所有键为 tier 值不等于 frontend 的资源,和那些没有键为 tier 的label的资源。

要过滤所有处于 production 但不是 frontend 的资源,可以使用逗号操作符, environment=production,tier!=frontend 。

environment=production,tier!=frontend ### 基于set的条件 ---- 基于集合的label条件允许用一组值来过滤键。支持三种操作符: in , notin ,和 exists(仅针对于key符号) 。例如:

environment in (production, qa)
tier notin (frontend, backend)
partition
!partitio 第一个例子,选择所有键等于 environment ,且value等于 production 或者 qa 的资源。 第二个例子,选择所有键等于 tier 且值是除了 frontend 和 backend 之外的资源,和那些没有label的键是 tier 的资源。 第三个例子,选择所有所有有一个label的键为partition的资源;值是什么不会被检查。 第四个例子,选择所有的没有lable的键名为 partition 的资源;值是什么不会被检查。

类似的,逗号操作符相当于一个AND操作符。因而要使用一个 partition 键(不管值是什么),并且 environment 不是 qa 过滤资源可以用 partition,environment notin (qa) 。

基于集合的选择器是一个相等性的宽泛的形式,因为 environment=production 相当于environment in (production) ,与 != and notin 类似。

基于集合的条件可以与基于相等性 的条件混合。例如, partition in (customerA,customerB),environment!=qa 。

API

LIST 和WATCH过滤


LIST和WATCH操作,可以使用query参数来指定label选择器来过滤返回对象的集合。两种条件都可以使用: 基于相等性条件: ?labelSelector=environment%3Dproduction,tier%3Dfrontend基于集合条件的:

labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29 两种label选择器风格都可以用来通过REST客户端来列表或者监视资源。比如使用 kubectl 来针对 apiserver ,并且使用基于相等性的条件,可以用:

$ kubectl get pods -l environment=production,tier=frontend

or using set-based requirements: 或者使用基于集合的条件:

$ kubectl get pods -l 'environment in (production),tier in (frontend)'

如以上已经提到的,基于集合的条件表达性更强。例如,他们可以实现值上的OR操作:

$ kubectl get pods -l 'environment in (production, qa)' 或者通过exists操作符进行否定限制匹配:

$ kubectl get pods -l 'environment,environment notin (frontend)'

Set references in API objects


一些Kubernetes对象,比如service和replication controlle的,也使用label选择器来指定其他资源的集合,比如pods。

Service and ReplicationController


一个service针对的pods的集合是用label选择器来定义的。类似的,一个replicationcontroller管理的pods的群体也是用label选择器来定义的。

对于这两种对象的Label选择器是用map定义在json或者yaml文件中的,并且只支持基于相等性的条件:

“selector”: {
“component” : “redis”,
}

或者

selector:
component: redis

这个选择器(分别是位于json或者yaml格式的)相等于 component=redis 或者 component in(redis) 。

Job and other new resources


Job和其他新的资源 较新的资源,如job,也支持基于集合的条件。

selector:
matchLabels:相当于一个
component: redis
matchExpressions:
– {key: tier, operator: In, values: [cache]}
– {key: environment, operator: NotIn, values: [dev]}

matchLabels 是一个键值对的映射。一个单独的 {key,value} 相当于 matchExpressions 的一个元素,它的键字段是”key”,操作符是 In ,并且值数组值包含”value”。 matchExpressions 是一个pod的选择器条件的列表。合法的操作符包含In, NotIn, Exists, and DoesNotExist。在In和NotIn的情况下,值的组必须不能为空。所有的条件,包含 matchLabels andmatchExpressions 中的,会用AND符号连接,他们必须都被满足以完成匹配。

Namespace

Namespace


Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是属于某一个namespace的(默认是default),而node, persistentVolumes等则不属于任何namespace。

Namespace常用来隔离不同的用户,比如Kubernetes自带的服务一般运行在kube-system namespace中。

Namespace操作


kubectl可以通过–namespace或者-n选项指定namespace。如果不指定,默认为default。查看操作下,也可以通过设置–all-namespace=true来查看所有namespace下的资源。

查询

$ kubectl get namespaces
NAME          STATUS    AGE
default       Active    11d
kube-system   Active    11d

注意:namespace包含两种状态”Active”和”Terminating”。在namespace删除过程中,namespace状态被设置成”Terminating”。

创建

(1) 命令行直接创建
$ kubectl create namespace new-namespace

(2) 通过文件创建
$ cat my-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: new-namespace

$ kubectl create -f ./my-namespace.yaml

注意:命名空间名称满足正则表达式 [a-z0-9]([-a-z0-9]*[a-z0-9])?,最大长度为63位

删除

$ kubectl delete namespaces new-namespace

注意:

  • 删除一个namespace会自动删除所有属于该namespace的资源。
  • default和kube-system命名空间不可删除。

Replication Controller

什么是Replication Controller


Replication Controller 保证了在所有时间内,都有特定数量的Pod副本正在运行,如果太多了,Replication Controller就杀死几个,如果太少了,Replication Controller会新建几个,和直接创建的pod不同的是,Replication Controller会替换掉那些删除的或者被终止的pod,不管删除的原因是什么(维护阿,更新啊,Replication Controller都不关心)。基于这个理由,我们建议即使是只创建一个pod,我们也要使用Replication Controller。Replication Controller 就像一个进程管理器,监管着不同node上的多个pod,而不是单单监控一个node上的pod,Replication Controller 会委派本地容器来启动一些节点上服务(Kubelet ,Docker)。

正如我们在pod的生命周期中讨论的,Replication Controller只会对那些RestartPolicy = Always的Pod的生效,(RestartPolicy的默认值就是Always),Replication Controller 不会去管理那些有不同启动策略pod

如我们在issue #503讨论的,我们希望在将来别的控制器被加入到Kubernete中来管理一些例如负载阿,测试等相关功能

Replication Controller永远不会自己关闭,但是,我们并不希望Replication Controller成为一个长久存在的服务。服务可能会有多个Pod组成,这些Pod又被多个Replication Controller控制着,我们希望Replication Controller 会在服务的生命周期中被删除和新建(例如在这些pod中发布一个更新),对于服务和用户来说,Replication Controller是通过一种无形的方式来维持着服务的状态

Replication Controller是如何工作的


Pod template

一个Replication Controller通过模版来创建pod,这个是Replication Controller对象内置的功能,但是我们计划要将这个功能从Replication Controller剥离开来

与其说Pod的模版是一个多有Pod副本的期望状态,Pod的模版更像是一个饼干的模具,一旦从模具中出来之后,饼干就和饼干模具美啥关系了,没有任何关联。模版的改变甚至是模版的更改对已经存在的pod没有任何影响,Replication Controller创建的pod可以在之后直接的修改,这对Pod来说是非常重要的,这样就定制了Pod中的所有容器的期望状态。这从根本上简化系统复杂度增加了灵活性,正如下面的这个例子

Replication Controller 创建的的Pod 是可以相互替代和语义上相同的,尽管他们的配置文件可能会随着是时间的变化而不一样,这非常适合无状态服务器,但是Replication Controller也可以被用在保持主从的高可用,共享,work-pool类应用程序,这样的程序应该使用的是动态分配机制,例如etcd lock module和RabbitMQ 的队列,相对于静态/一次性的定制的Pod的配置文件,应该是一种反模式,任何定制化的pod,例如垂直的自动变化资源(cpu,内存),应该被其它的线上Controller管理,而不是Replication Controller.

Labels

由Replication Controller监控的Pod的数量是是由一个叫 label selector(标签选择器)决定的,label selector在Replication Controller和被控制的pod创建了一个松散耦合的关系,与pod相比,pod与他们的定义文件关系紧密。我们故意的不使用固定长度的数组来存储被管理的pod,因为根据我们的经验,如果那样作了,会增加管理的复杂度,不论是系统还是客户

replication controller 需要确认那些从特定模版创建出来的pod拥有label selector所要求的标签,尽管,它还没有这么作,我们需要通过确认replication controllers的label selectors 没有覆盖设置来确定仅有一个Replication Controller控制所指定的Pod(这段话有点怪)

记住这个:replication controller自己也可以由标签,would generally carry the labels their corresponding pods have in common,但是这些标签并不影响replication controller的行为

Pod会被replication controller删除,如果修改那些pod的标签,这个功能可能会被应用在从服务中删除pod来作测试,数据恢复等。Pod如果是以这种方式被删除的话,那么那个pod会被自动的替换(前提是宗的副本数量未修改)

类似的,删除一个replication controller不会影响它创建的pod,如果向删除那些它那些控制的pod,需要首先拔replcas的值设置为0(注意,用户端工具kubectl 提供了一个命令stop,来删除replication controller以及它控制的pod,但是,这个功能在现在的api中不存在)

Responsibilities of the replication controller(replication controller的责任)

replication controller的任务就是保证预计数量的pod并并保证其可用性,目前,只有那些被终止的Pod是从总数量中排除的,在将来,可读性以及其它系统信息可能会被纳入统计,我们肯能会增加更多的替代策略,并且我们计划可以执行其它外部程序可以使使用并实现复杂的替换或者策略

replication controller的任务永远都只会是单一的。它自身不会进行是否可读和是否可用的检测,相比与自动进行缩放和放大,replication controller更倾向与使用外部的自动平衡工具,这些外部工具要作的仅仅是修改replicas的值来实现Pod数量的变化,我们不会增加replication controller的调度策率,也不会让replication controller来验证受控的Pod是否符合特定的模版,因为这些都会阻碍自动调整和其它的自动的进程。类似的,完成时限,需求依赖,配置扩展,等等都属于其它的部分。

replication controller的目的是成为一个原始的积木,我们希望在replication controller上层的api或者工具来为用户提供方便,现在kubectl支持的宏观操作比如run,stop,scale,rolling-update就是这个概念的例子,举例来说,我们可以想象和“天庭”管理着replication controller,auto-scalers, services, scheduling policies, canaries, 等等

常见的使用模式


Rescheduling(重新规划)

正如我们之前提到的,无论你是有1个或者有1000个pod需要运行,Replication Controller 会确保该数量的pod在运行,甚至在节点(node)失败或者节点(node)终止的情况下

Scaling(缩放)

Replication Controller让我们更容易的控制pod的副本的数量,不管我们是手动控制还是通过其它的自动管理的工具,最简单的:修改replicas的值

Rolling updates(动态更新)

Replication Controller 可以支持动态更新,当我们更新一个服务的时候,它可以允许我们一个一个的替换pod

正如我们在#1353中解释的,推荐的方法是创建一个新的只有1个pod副本的Replication Controller,然后新的每次+1,旧的每次-1,直到旧的Replication Controller 的值变成0,然后我们就可以删除旧的了,这样就可以规避省级过程中出现的未知错误了

理论上,动态更新控制器应考虑应用的可用性,并确保足够的pod制成服务在任何时间都能正常提供服务

两个 Replication Controller创建的pod至少要由一个不同的标签,可以是镜像的标签,因为一般镜像的更新都会带来一个新的更新

kubectl是实现动态更新的客户端

Multiple release tracks多个发布版本追踪

除了在程序更新过程中同时运行多个版本的程序外,在更新完成之后的一段时间内或者持续的同时运行多个版本(新旧),通过多国版本的追踪(版本的追踪是通过label来实现的)

举个例子来说:一个服务可能绑定的Pod为tier in (frontend), environment in (prod),现在我们旧假设我们由10个副本来组成这个tier,现在我们要发布一个新的版本canary,这个时候,我们就应该设置一个Replication Controller,并且设置replcas的值为9,并且标签为tier=frontend, environment=prod, track=stable,然后再设置另外一个Replication Controller,并且把replacas的值设置为1标签为:tier=frontend, environment=prod, track=canary.现在这个服务就同时使用了新版和旧版两个版本了,这个时候我们旧可以通过不同的Replication Controller进行一些测试,监控…

Node

Node


Node是Pod真正运行的主机,可以物理机,也可以是虚拟机。为了管理Pod,每个Node节点上至少要运行container runtime(比如docker或者rkt)、kubelet和kube-proxy服务。

Node管理


不像其他的资源(如Pod和Namespace),Node本质上不是Kubernetes来创建的,Kubernetes只是管理Node上的资源。虽然可以通过Manifest创建一个Node对象(如下json所示),但Kubernetes也只是去检查是否真的是有这么一个Node,如果检查失败,也不会往上调度Pod。

{
  "kind": "Node",
  "apiVersion": "v1",
  "metadata": {
    "name": "10.240.79.157",
    "labels": {
      "name": "my-first-k8s-node"
    }
  }
}

这个检查是由Node Controller来完成的。Node Controller负责

  • 维护Node状态
  • 与Cloud Provider同步Node
  • 给Node分配容器CIDR
  • 删除带有NoExecute taint的Node上的Pods

默认情况下,kubelet在启动时会向master注册自己,并创建Node资源。

Node的状态


每个Node都包括以下状态信息

  • 地址:包括hostname、外网IP和内网IP
  • 条件(Condition):包括OutOfDisk、Ready、MemoryPressure和DiskPressure
  • 容量(Capacity):Node上的可用资源,包括CPU、内存和Pod总数
  • 基本信息(Info):包括内核版本、容器引擎版本、OS类型等

Taints和tolerations


Taints和tolerations用于保证Pod不被调度到不合适的Node上,Taint应用于Node上,而toleration则应用于Pod上(Toleration是可选的)。

比如,可以使用taint命令给node1添加taints:

kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value2:NoExecute

Taints和tolerations的具体使用方法请参考调度器章节。

Node维护模式


标志Node不可调度但不影响其上正在运行的Pod,这种维护Node时是非常有用的

kubectl cordon $NODENAME

ReplicaSets

什么是ReplicaSet?


ReplicaSet是下一代复本控制器。ReplicaSet和 Replication Controller之间的唯一区别是现在的选择器支持。Replication Controller只支持基于等式的selector(env=dev或environment!=qa),但ReplicaSet还支持新的,基于集合的selector(version in (v1.0, v2.0)或env notin (dev, qa))。在试用时官方推荐ReplicaSet。

大多数kubectl支持Replication Controller的命令也支持ReplicaSets。rolling-update命令有一个例外 。如果您想要滚动更新功能,请考虑使用Deployments。此外, rolling-update命令是必须的,而Deployments是声明式的,因此我们建议通过rollout命令使用Deployments。

虽然ReplicaSets可以独立使用,但是今天它主要被 Deployments 作为协调pod创建,删除和更新的机制。当您使用Deployments时,您不必担心管理他们创建的ReplicaSets。Deployments拥有并管理其ReplicaSets。

何时使用ReplicaSet?


ReplicaSet可确保指定数量的pod“replicas”在任何设定的时间运行。然而,Deployments是一个更高层次的概念,它管理ReplicaSets,并提供对pod的声明性更新以及许多其他的功能。因此,我们建议您使用Deployments而不是直接使用ReplicaSets,除非您需要自定义更新编排或根本不需要更新。

这实际上意味着您可能永远不需要操作ReplicaSet对象:直接使用Deployments并在规范部分定义应用程序。


frontend.yaml:

apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
  name: frontend
  # these labels can be applied automatically
  # from the labels in the pod template if not set
  # labels:
    # app: guestbook
    # tier: frontend
spec:
  # this replicas value is default
  # modify it according to your case
  replicas: 3
  # selector can be applied automatically
  # from the labels in the pod template if not set,
  # but we are specifying the selector here to
  # demonstrate its usage.
  selector:
    matchLabels:
      tier: frontend
    matchExpressions:
      - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access environment variables to find service host
          # info, comment out the 'value: dns' line above, and uncomment the
          # line below.
          # value: env
        ports:
        - containerPort: 80

将此配置保存frontend.yaml到Kubernetes集群并将其提交给Kubernetes集群时,应创建定义的ReplicaSet及其管理的pod。

$ kubectl create -f frontend.yaml
replicaset "frontend" created
$ kubectl describe rs/frontend
Name:          frontend
Namespace:     default
Image(s):      gcr.io/google_samples/gb-frontend:v3
Selector:      tier=frontend,tier in (frontend)
Labels:        app=guestbook,tier=frontend
Replicas:      3 current / 3 desired
Pods Status:   3 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.
Events:
  FirstSeen    LastSeen    Count    From                SubobjectPath    Type        Reason            Message
  ---------    --------    -----    ----                -------------    --------    ------            -------
  1m           1m          1        {replicaset-controller }             Normal      SuccessfulCreate  Created pod: frontend-qhloh
  1m           1m          1        {replicaset-controller }             Normal      SuccessfulCreate  Created pod: frontend-dnjpy
  1m           1m          1        {replicaset-controller }             Normal      SuccessfulCreate  Created pod: frontend-9si5l
$ kubectl get pods
NAME             READY     STATUS    RESTARTS   AGE
frontend-9si5l   1/1       Running   0          1m
frontend-dnjpy   1/1       Running   0          1m
frontend-qhloh   1/1       Running   0          1m

Search

    Table of Contents