k8s杂记 - 有选择的翻译

k8s杂记 - 有选择的翻译

刚看到有中文版,wtf。。。

Resource capacity tracking

Node objects track information about the Node's resource capacity: for example, the amount of memory available and the number of CPUs. Nodes that self register report their capacity during registration. If you manually add a Node, then you need to set the node's capacity information when you add it.

The Kubernetes scheduler ensures that there are enough resources for all the Pods on a Node. The scheduler checks that the sum of the requests of containers on the node is no greater than the node's capacity. That sum of requests includes all containers managed by the kubelet, but excludes any containers started directly by the container runtime, and also excludes any processes running outside of the kubelet's control.
Note: If you want to explicitly reserve resources for non-Pod processes, see reserve resources for system daemons.

https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#system-reserved

MEM SWAP 之前不支持,必须禁用

在k8s 1.22之前,nodes不支持使用swap内存,否则kubelet会无法启动。

在1.22以后,可以在某个(些)node上选择是否开启swap支持。

The Kubernetes API

k8s control plane 的核心是 API server。API server提供了HTTP API,可以让终端用户、集群的不同部分,以及外部组件之间互相通讯。

k8s API 可以查询和操作k8s中API对象的状态(如: Pods, Namespaces, ConfigMaps, and Events)。

大多数操作都可以通过kubectl命令或者其他命令行命令(如kubeadm)来执行,实际上仍然是转成API。当然也可以直接使用 REST请求来调用API。

如果你是通过编写应用来使用k8s API,可以考虑使用某个client library

所有操作都是API-server来调用的 - 通过HTTP协议。

嗯嗯,可以在论文里引用下openapi标准

Understanding Kubernetes objects 理解k8s对象

Kubernetes objects are persistent entities in the Kubernetes system. Kubernetes uses these entities to represent the state of your cluster. Specifically, they can describe:

  • What containerized applications are running (and on which nodes)
  • The resources available to those applications
  • The policies around how those applications behave, such as restart policies, upgrades, and fault-tolerance

A Kubernetes object is a "record of intent"--once you create the object, the Kubernetes system will constantly work to ensure that object exists. By creating an object, you're effectively telling the Kubernetes system what you want your cluster's workload to look like; this is your cluster's desired state.

To work with Kubernetes objects--whether to create, modify, or delete them--you'll need to use the Kubernetes API. When you use the kubectl command-line interface, for example, the CLI makes the necessary Kubernetes API calls for you. You can also use the Kubernetes API directly in your own programs using one of the Client Libraries.

最重要是类比概念。k8s objects 就是持久化的实体 - 描述了集群的状态。
一旦创建了一个对象,k8s系统就回努力确保该对象存在。创建对象,就是在告诉k8s系统你想让它变成这个样子,这就是你的需求。

Object Spec and Status

Almost every Kubernetes object includes two nested object fields that govern the object's configuration: the object spec and the object status.
For objects that have a spec, you have to set this when you create the object, providing a description of the characteristics you want the resource to have: its desired state.

The status describes the current state of the object, supplied and updated by the Kubernetes system and its components. The Kubernetes control plane continually and actively manages every object's actual state to match the desired state you supplied.

For example: in Kubernetes, a Deployment is an object that can represent an application running on your cluster. When you create the Deployment, you might set the Deployment spec to specify that you want three replicas of the application to be running. The Kubernetes system reads the Deployment spec and starts three instances of your desired application--updating the status to match your spec. If any of those instances should fail (a status change), the Kubernetes system responds to the difference between spec and status by making a correction--in this case, starting a replacement instance.

For more information on the object spec, status, and metadata, see the Kubernetes API Conventions.

几乎所有k8s对象都有两个内嵌object fields: spec和status,以管理对象的配置。
对于拥有spec的对象来说,当你创建该类对象的时候,必须设置spec,告诉系统该对象的disire state
而status则描述该对象的当前状态 - 由k8s系统和其组件提供。 嗯嗯,k8s control plane 会一直努力让每个对象的实际状态变成disired state

例如,k8s的Deployment对象,代表了运行在集群中的一个应用。
当你创建它的时候,需要设置spec,如副本数。
k8s系统读取了该对象的spec,并开启对应数量的实例。
如果有实例失败(也就是状态发生了改变),k8s系统会针对spec和实际状态的不同立即做出应对,在这个例子中也就是开启一个新实例以取代失败的实例。

举例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment



spec:
  selector:
    matchLabels:
      app: nginx



  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

应用 kubectl apply -f $path_to_yaml
或者直接使用API。

Required Fields 必填字段

想要创建k8s object,在yaml文件中必须设置以下字段:

  • apiVersion - 哪个版本的k8s API来创建该对象
  • kind - 创建什么kind的对象
  • metadata - 唯一识别该对象的数据,包括:a name string, UID, and optional namespace
  • spec - 你期望的目标状态

不同的k8s对象有不同的spec的格式,会含有独属于其object的内嵌字段。
k8s API Reference 上面有所有k8s对象的spec格式。

例如,对于Pod API 来说,每个Pod的spec字段 描述了pod和其期望状态(如容器镜像名字)。
例如,StatefulSet API,对于StatefulSet来说,spec字段 描述了StatefulSet和其期望状态。
而在StatefulSet的spec中则是用于Pod对象的一个模板。该模板描述了StatefulSet controller将会按序创建的Pods,以符合StatefulSet的spec。
不同kind的对象也会有不同的status。
详见API reference。

k8s对象管理

kubectl 命令支持数种方式来创建和管理k8s对象。

Read the Kubectl book for details of managing objects by Kubectl.

不建议通过混合方式来操作,最佳方式是选取一种方式。否则可能会导致k8s未知行为。

Management technique Operates on Recommended environment Supported writers Learning curve
Imperative commands Live objects 开发环境 1+ Lowest
Imperative object configuration Individual files 生产环境 1 Moderate
Declarative object configuration Directories of files 生产环境 1+ Highest

Imperative commands 祈使命令(更像是要求)

在使用imperative commands时,用户是直接作用于集群中活的对象(就在runtime的对象)上。
这种方式适合刚开始学习,或者执行一次性任务的情况。这种方式直接作用于活的对象上,没有提供之前配置的历史。

例如:通过创建一个Deployment对象来运行一个nginx实例(使用的容器镜像是nginx):
kubectl create deployment nginx --image nginx

Trade-offs 利弊

相比对象配置的有点:

  • 命令仅是一个动作单词
  • 命令仅需一步

相比对象配置的缺点:

  • Commands do not integrate with change review processes. 更改审阅
  • Commands do not provide an audit trail associated with changes.
  • Commands do not provide a source of records except for what is live.
  • Commands do not provide a template for creating new objects.

Imperative object configuration

In imperative object configuration, the kubectl command specifies the operation (create, replace, etc.), optional flags and at least one file name. The file specified must contain a full definition of the object in YAML or JSON format.

See the API reference for more details on object definitions.

Warning: The imperative replace command replaces the existing spec with the newly provided one, dropping all changes to the object missing from the configuration file. This approach should not be used with resource types whose specs are updated independently of the configuration file. Services of type LoadBalancer, for example, have their externalIPs field updated independently from the configuration by the cluster.

例如:

  1. 创建配置文件中定义的对象
    kubectl create -f nginx.yaml
  2. 删除配置文件中定义的对象
    kubectl delete -f nginx.yaml -f redis.yaml
  3. 使用配置文件中的定义来覆盖现有存活对象的定义
    kubectl replace -f nginx.yaml
Trade-offs 利弊

相对于imperative commands的优点:

  • 可使用Git之类的来保存历史。
  • 可集成其他流程,如git push之前的review。
  • 可作为模板来创建新对象。

相对于imperative commands的缺点:

  • 要求理解object schema
  • 要求书写YAML文件

相对于declarative object configuration 的优点:

  • 更简单易懂
  • 从 k8s 1.5 起,更成熟。

相对于declarative object configuration 的缺点:

  • 基于文件最佳,而非目录
  • 对live objects的更改必须反映在配置文件中,否则会在下次replacement时丢弃。

Declarative object configuration

使用声明式对象配置时,用户是在本地存储的对象配置文件上操作,当然用户不会定义针对这些文件的操作。
创建、更新和删除操作,是由kubectl按object自动检测的。 故而,可以作用于文件夹 - 可以针对不同对象的不同操作。

注意:声明式对象配置会保留其他writers做的更改,哪怕这些更改没有合并到该配置文件。这是因为使用patch API会write区别,而非使用replace API来替换整个对象配置。

例子:
处理configs文件夹下的所有对象配置文件,创建或patch the live objects。 可以先diff一下看看即将生效的区别,然后再apply:

kubectl diff -f configs/
kubectl apply -f configs/

递归处理文件夹:

kubectl diff -R -f configs/
kubectl apply -R -f configs/

Object Names and IDs

集群中的每个对象都有一个Name,在对象类型范围内唯一(就是某类对象可以很多,但每个名字都必须唯一;不同类的可以重名,虽然没啥意义)。
每个k8s对象还有一个UID,集群范围内唯一。

例如,在同一个namespace内,仅能有一个Pod叫 myapp-1234,但可以有一个Pod和Deployment同时叫 myapp-1234。
对于用户提供的非唯一的attributes,k8s提供了labels和annotations。

Names

由客户指定的字符串,代表了资源URL中的一个对象,如 /api/v1/pods/some-name

注意:当对象代表了一种物理实体时,如Node代表了一个物理host,当创建同名字的host而没有删除已有的时,k8s会将新host当成旧host,会导致不一致。
嗯嗯,就是说必须先删除旧的,或者起个不同的名字。

下面是针对资源常用的四种命名规范:

DNS Subdomain Names 子域名名字

多数资源类型要求名字必须符合 DNS子域名规范,也就是:

  • 最多253个字符
  • 只有小写字母、数字、"-"和"."
  • 必须以数字或字母开头
  • 必须以数字或字母结尾
RFC 1123 Label Names

某些资源类型要求名字必须符合 RFC 1123 DNS标签标准,也就是:

  • 最多63个字符
  • 只有小写字母、数字和"-"
  • 必须以数字或字母开头
  • 必须以数字或字母结尾
RFC 1035 Label Names

某些资源类型要求名字必须符合 RFC 1035 DNS标签标准,也就是:

  • 最多63个字符
  • 只有小写字母、数字和"-"
  • 必须以数字或字母开头
  • 必须以数字或字母结尾
Path Segment Names

某些资源类型要求名字必须能作为路径编码,也就是名字不能是"."或者"..",也不能包含"/"或者"%"。

例如 名字为 nginx-demo 的 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

注意:某些类型还有其他要求。

UIDs

k8s系统生成的字符串,用于区分每个对象。
k8s集群的整个生命期间创建的每个对象都有一个唯一的UID。
It is intended to distinguish between historical occurrences of similar entities.

Labels and Selectors 标签和选择器

Labels是附着于对象(如pods)的键值对。
Labels对用户有意义,但不直接作用于核心系统。
Labels可以用来组织和选择对象的子集合。
Labels可以附着于对象 - 在创建时,然后可以在后续任何时刻添加和修改。每个对象都可以定义一组 k/v labels。对于某个对象来说,每个Key必须唯一。

"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

Labels可以用于查询和观察,对于UI和CLI用户来说非常有用。
非标记信息(Non-identifying information)应该使用annotations,而非Labels。

Motivation 动机

Labels可以让用户将其组织结构映射到系统对象上 - 以一种松耦合的方式,不需要客户存储这些映射。

Service deployments and batch processing pipelines are often multi-dimensional entities (e.g., multiple partitions or deployments, multiple release tracks, multiple tiers, multiple micro-services per tier). Management often requires cross-cutting operations, which breaks encapsulation of strictly hierarchical representations, especially rigid hierarchies determined by the infrastructure rather than by users.

样例:

  • "release" : "stable", "release" : "canary"
  • "environment" : "dev", "environment" : "qa", "environment" : "production"
  • "tier" : "frontend", "tier" : "backend", "tier" : "cache"
  • "partition" : "customerA", "partition" : "customerB"
  • "track" : "daily", "track" : "weekly"

上面是常用的labels;当然可以开发自己的标签。谨记一个object的标签Key必须唯一。

Syntax and character set 语义和字符集

有效的标签keys有两部分:an optional prefix and name, separated by a slash (/)
name部分最多63个字符,以字母或数字开头和结尾,中间可以"-""_""."
prefix是可选的。如果指定了,必须是一个DNS子域名:以"."间隔,最多253字符,结尾"/"

如果省略了prefix,则假定标签Key是用户私有的。自动化系统组件(如kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, 或者其他三方自动化)为终端用户添加标签时,必须指定prefix。

prefix kubernetes.io/k8s.io/是为k8s核心组件保留的。

有效的标签value:

  • 最多63个字符,可以为空empty。
  • 如非empty,需要以数字和字母开始和结尾,含大小写。
  • 中间可以包含-_.,以及数字、字母。

例如,这里有个Pod的配置文件,其中有两个标签environment: productionapp: nginx

apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels:
    environment: production
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

Label selectors 标签选择器

不同于名字和UID,标签没有唯一性。事实上,我们反而期望很多对象携带相同的标签。

通过一个标签选择器,客户/用户可以标识一组对象。标签选择器是k8s的核心分组原语(core grouping primitive)。

API目前支持两种类型的选择器: equality-basedset-based
标签选择器可以由多个条件(requirements)组成,以逗号间隔即可。多个条件时,每个条件都需要满足,也就是说此处的逗号等同于逻辑与操作符(&&)。

如果是empty或者没有指定选择器,那结果取决于上下文,使用选择器的API类型应该在文档说明此时的有效性和含义.

注意:对于某些API类型,例如ReplicaSets,同一个namespace中的两个实例的标签选择器不能重叠,否则controller会遇到冲突指令,然后无法决定副本数量。

警告:对于两种选择器来说,都没有逻辑或操作符。请确保你的过滤器语句是合理的(Ensure your filter statements are structured accordingly)。

Equality-based requirement 等式条件

支持通过标签的键和值来过滤。
支持三种操作符: =, ==, !=
前两种代表相等,后一种代表不相等。

两个例子:

  • environment = production
  • tier != frontend

前者会选择所有键为environment,值为production的资源;
后者则会选择所有键为tier,值不为frontend,或无该键的资源。
二者还可以结合起来使用: environment=production,tier!=frontend

一个使用场景是为Pods指定nodes -- 通过nodeSelector。例如:

apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "registry.k8s.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100
Set-based requirement 集合条件

支持通过一组值来过滤键。
支持三种操作符:in, notin and exists (only the key identifier). For example:

  • environment in (production, qa)
  • tier notin (frontend, backend)
  • partition
  • !partition
  1. 第一个例子,会选择所有键为environment,值为production或qa的资源
  2. 第二个例子,会选择所有键为tier,值不为frontend或backend,或者没有该键的资源
  3. 第三个例子,会选择所有键为partition的资源,不检查值
  4. 第四个例子,会选择所有键不为partition的资源,不检查值

同样的,逗号操作符扮演了逻辑与操作符。

两种条件可以混用。 Set-based requirements can be mixed with equality-based requirements.

例如: partition in (customerA, customerB),environment!=qa

API

LIST and WATCH filtering 罗列和观察过滤

LIST and WATCH operations may specify label selectors to filter the sets of objects returned using a query parameter. Both requirements are permitted (presented here as they would appear in a URL query string):

  • equality-based requirements: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
  • set-based requirements: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29

Both label selector styles can be used to list or watch resources via a REST client. For example, targeting apiserver with kubectl and using equality-based one may write:
kubectl get pods -l environment=production,tier=frontend

or using set-based requirements:
kubectl get pods -l 'environment in (production),tier in (frontend)'

As already mentioned set-based requirements are more expressive. For instance, they can implement the OR operator on values:
kubectl get pods -l 'environment in (production, qa)'

or restricting negative matching via exists operator:
kubectl get pods -l 'environment,environment notin (frontend)'

Set references in API objects - API对象中的集合引用

某些k8s对象,例如services和replicationcontrollers,也使用标签选择器来指定其他资源(如pods)的集合。

Service and ReplicationController

一个service指向的pods集合,是通过标签选择器定义的。同样的,一个replicaitoncontroller管理的pods数量也是由标签选择器定义的。

标签选择器(json或yaml格式)如果使用了map类型,那仅支持equality-based条件选择器:
Labels selectors for both objects are defined in json or yaml files using maps, and only equality-based requirement selectors are supported:

"selector": {
    "component" : "redis",
}

或者

selector:
    component: redis

改选择器等同于 component=redis 或者 component in (redis)

Resources that support set-based requirements - 支持基于集合条件的资源

较新的资源,如 Job、 Deployment、 ReplicaSet和 DaemonSet,同样支持 set-based条件。

selector:
  matchLabels:
    component: redis
  matchExpressions:
    - {key: tier, operator: In, values: [cache]}
    - {key: environment, operator: NotIn, values: [dev]}

matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value".
matchExpressions is a list of pod selector requirements. Valid operators include In, NotIn, Exists, and DoesNotExist.
The values set must be non-empty in the case of In and NotIn.

All of the requirements, from both matchLabels and matchExpressions are ANDed together -- they must all be satisfied in order to match.

Selecting sets of nodes

一个通过标签来选择的案例是,限定pod可以shedule的nodes的集合。
详见node selection

posted on 2022-10-28 17:38  LarryZeal  阅读(135)  评论(0编辑  收藏  举报

导航