1 Node

Node 是 Kubernetes 集群的工作节点,可以是物理机也可以是虚拟机。

1.1 Node 状态

Node 包括如下状态信息

  • Address
    • HostName:可以被 kubelet 中的  --hostname-override  参数替代。
    • ExternalIP:可以被集群外部路由到的 IP 地址。
    • InternalIP:集群内部使用的 IP,集群外部无法访问。
  • Condition
    • OutOfDisk:磁盘空间不足时为  True
    • Ready:Node controller 40 秒内没有收到 node 的状态报告为  Unknown,健康为  True,否则为  False
    • MemoryPressure:当 node 有内存压力时为  True,否则为  False
    • DiskPressure:当 node 有磁盘压力时为  True,否则为  False
  • Capacity
    • CPU
    • 内存
    • 可运行的最大 Pod 个数
  • Info:节点的一些版本信息,如 OS、kubernetes、docker 等

1.2 Node 上 Pod 管理

禁止 Pod 调度到该节点上。

kubectl cordon <node>

驱逐该节点上的所有 Pod。

kubectl drain <node>

该命令会删除该节点上的所有 Pod(DaemonSet 除外),在其他 node 上重新启动它们,通常该节点需要维护时使用该命令。直接使用该命令会自动调用 kubectl cordon <node> 命令。当该节点维护完成,启动了 kubelet 后,再使用 kubectl uncordon <node>  即可将该节点添加到 kubernetes 集群中。

1.3 Node 命令

kubectl get nodes

2 Namespace

Namespace,命名空间,用于多套环境的资源隔离或者多租户的资源隔离

  1. 多环境的资源隔离
    • 默认情况下,pod 之间可相互访问。使用 namespace 可以将访问隔离,形成逻辑上的“组”。
  2. 多租户的资源隔离
    • 将不同的 namespace 交给不同的租户管理,从而实现租户的资源隔离。还可以结合 K8S 的资源配额机制,限定不同租户能占用的资源,如 CPU、内存使用量,来实现租户可用资源的管理。

kubernetes 在集群启动之后,会默认创建几个 namespace.

[root@master ~]# kubectl  get namespace
NAME              STATUS   AGE
default           Active   45h     #  所有未指定Namespace的对象都会被分配在default命名空间
kube-node-lease   Active   45h     #  集群节点之间的心跳维护,v1.13开始引入
kube-public       Active   45h     #  此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system       Active   45h     #  所有由Kubernetes系统创建的资源都处于这个命名空间

ns 的名字需要符合 [a-z0-9]([-a-z0-9]*[a-z0-9])? 不能有下划线.

Kubernetes @3 资源管理.png

2.1 Namespace 命令

# 查看所有的命名空间
kubectl get namespaces
kubectl get ns
# 查看指定命名空间
kubectl get ns default
# 查看指定命名空间 - yaml 格式 (特定格式 wide、json、yaml)
kubectl get ns default -o yaml
# 查看指定命名空间 - wide 格式(一行的形式展示相信信息)
kubectl get ns default -o yaml
# 查看命名空间详情
kubectl describe ns default
 
# 创建命名空间
kubectl create ns dev
# 删除命名空间
kubectl delete ns dev
# 基于 yaml 创建命名空间
kubectl apply -f dev.yaml
# 基于 yaml 删除命名空间
kubectl delete -f dev.yaml
 
# yaml 配置文件
apiVersion: v1
kind: Namespace
metadata:
  name: dev

3 Label

3.1 Label

Label 的目标 —— 便于微服务的管理

  • “release” : “stable, “release” : “canary”
  • “environment” : “dev”, “environment” : “qa”
  • “tier” : “frontend”, “tier” : “backend”, “tier” : “cache”
  • “partition” : “customerA”, “partition” : “customerB”
  • “track” : “daily”, “track” : “weekly”
  • “team” : “teamA”,“team:” : “teamB”`

Label 编写要求

  • Label key 的组成:
    • 不得超过 63 个字符
    • 可以使用前缀,使用 / 分隔,前缀必须是 DNS 子域,不得超过 253 个字符,系统中的自动化组件创建的 label 必须指定前缀,kubernetes.io/  由 kubernetes 保留
    • 起始必须是字母(大小写都可以)或数字,中间可以有连字符、下划线和点
  • Label value 的组成:
    • 不得超过 63 个字符
    • 起始必须是字母(大小写都可以)或数字,中间可以有连字符、下划线和点
# 为 pod 资源打标签
kubectl label pod nginx-pod version=1.0 -n dev
 
# 为 pod 资源更新标签
kubectl label pod nginx-pod version=2.0 -n dev --overwrite
 
# 查看标签
kubectl get pod nginx-pod  -n dev --show-labels
 
# 查看 version 标签
kubectl get pod -L version
 
# 筛选标签
kubectl get pod -n dev -l version=2.0  --show-labels
kubectl get pod -n dev -l version!=2.0 --show-labels
 
#删除标签
kubectl label pod nginx-pod version- -n dev
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: dev
  labels:
    version: "3.0"
    env: "test"
spec:
  containers:
    - image: nginx:latest
      name: pod
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP

3.2 Label Selector

Label selector

通过 label selector,客户端/用户可以指定一个 object 集合,通过 label selector 对 object 的集合进行操作。标签的选择条件可以使用多个,此时将多个 Label Selector 进行组合,使用逗号”,“进行分隔即可。

Label selector 有两种类型

  • equality-based :可以使用 =、==、!= 操作符,可以使用逗号分隔多个表达式
  • set-based :可以使用 in、notin、! 操作符,另外还可以没有操作符,直接写出某个 label 的 key,表示过滤有某个 key 的 object 而不管该 key 的 value 是何值,! 表示没有该 label 的 object
kubectl get pods -l environment=production,tier=frontend
kubectl get pods -l 'environment in (production),tier in (frontend)'
kubectl get pods -l 'environment in (production, qa)'
kubectl get pods -l 'environment,environment notin (frontend)'

API object 中设置 Label Selector

在  servicereplicationcontroller  等 object 中有对 pod 的 label selector,使用方法只能使用等于操作,例如:

selector:
  component: redis

在  JobDeploymentReplicaSet  和  DaemonSet  这些 object 中,支持  set-based  的过滤,例如:

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

另外在 node affinity 和 pod affinity 中的 label selector 的语法又有些许不同,示例如下:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/e2e-az-name
              operator: In
              values:
                - e2e-az1
                - e2e-az2
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
            - key: another-node-label-key
              operator: In
              values:
                - another-node-label-value

4 Annotation

Annotation 和 Label 类似,但是面向的受众不同。Label 主要面向 K8S 系统,K8S 系统根据 Label 进行多个 pod 管理等。Annotation 面向使用者,类似于代码中的注释,提供说明。例如,Owner 信息、构建、发布或镜像信息(如时间戳、发布 ID、Git 分支、PR 数量、镜像哈希、仓库地址)等。

注解和标签一样,是键/值对。注解中的元数据,可以很小,也可以很大,可以是结构化的,也可以是非结构化的,能够包含标签不允许的字符。

注解(Annotations)  存储的形式是键/值对。有效的注解键分为两部分: 可选的前缀和名称,以斜杠(/)分隔。 名称段是必需项,并且必须在 63 个字符以内,以字母数字字符([a-z0-9A-Z])开头和结尾, 并允许使用破折号(-),下划线(_),点(.)和字母数字。 前缀是可选的。如果指定,则前缀必须是 DNS 子域:一系列由点(.)分隔的 DNS 标签, 总计不超过 253 个字符,后跟斜杠(/)。 如果省略前缀,则假定注解键对用户是私有的。 由系统组件添加的注解 (例如,kube-schedulerkube-controller-managerkube-apiserverkubectl  或其他第三方组件),必须为终端用户添加注解前缀。

kubectl annotate svc nginx -n devops kubemaster.top/owner=@marionxue

Kubernetes @3 资源管理-1.png

Annotation | 云原生资料库

5 垃圾收集 - N

6 资源调度 - N

Kubernetes 中有一个叫做  kube-scheduler  的组件,该组件就是通过 K8S 的监测 Watch 专门监听  kube-apiserver  中是否有还未调度到 node 上的 pod,再通过特定的算法为 pod 指定分派 node 运行。

kube-scheduler 在设计上允许你自己编写一个调度组件并替换原有的 kube-scheduler。在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、 亲和以及反亲和要求、数据局部性、负载间的干扰等等。

Kubernetes 中的众多资源类型,例如 Deployment、DaemonSet、StatefulSet 等都已经定义了 Pod 运行的一些默认调度策略,但是如果我们细心的根据 node 或者 pod 的不同属性,分别为它们打上标签之后,我们将发现 Kubernetes 中的高级调度策略是多么强大。当然如果要实现动态的资源调度,即 pod 已经调度到某些节点上后,因为一些其它原因,想要让 pod 重新调度到其它节点。

考虑以下两种情况:

  • 集群中有新增节点,想要让集群中的节点的资源利用率比较均衡一些,想要将一些高负载的节点上的 pod 驱逐到新增节点上,这是 kuberentes 的 scheduler 所不支持的,需要使用如  descheduler  这样的插件来实现。
  • 想要运行一些大数据应用,设计到资源分片,pod 需要与数据分布达到一致均衡,避免个别节点处理大量数据,而其它节点闲置导致整个作业延迟,这时候可以考虑使用  kube-batch

kube-sheduler 中的节点选择

kube-scheduler 给一个 Pod 做调度选择时包含两个步骤 —— 过滤和打分。过滤:选出所有满足 pod 调度需求的节点。打分:从所有可调度节点中,选择最合适的节点,若存在多个,则随机选择。

支持以下两种方式配置调度器的过滤和打分行为:

  1. 调度策略  允许你配置过滤所用的  断言(Predicates)  和打分所用的  优先级(Priorities)
  2. 调度配置  允许你配置实现不同调度阶段的插件,包括:QueueSortFilterScoreBindReservePermit  等等。你也可以配置 kube-scheduler 运行不同的配置文件。

接下来阅读

7 服务质量等级 QoS

QoS(Quality of Service),大部分译为“服务质量等级”,又译作“服务质量保证”,是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:

  • Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。
  • Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。
  • BestEffort:容器必须没有任何内存或者 CPU 的限制或请求。

该配置不是通过一个配置项来配置的,而是通过配置 CPU/内存的  limits  与  requests  值的大小来确认服务质量等级的。使用  kubectl get pod -o yaml  可以看到 pod 的配置输出中有  qosClass  一项。该配置的作用是为了给资源调度提供策略支持,调度算法根据不同的服务质量等级可以确定将 pod 调度到哪些节点上。

例如,下面这个 YAML 配置中的 Pod 资源配置部分设置的服务质量等级就是  Guarantee

spec:
  containers:
    ...
    resources:
      limits:
        cpu: 100m
        memory: 128Mi
      requests:
        cpu: 100m
        memory: 128Mi

下面的 YAML 配置的 Pod 的服务质量等级是  Burstable

spec:
  containers:
    ...
    resources:
      limits:
        memory: "180Mi"
      requests:
        memory: "100Mi"