Kubernetes概述

文章目录

Kubernetes概述

docker和k8s是云原生时代两颗璀璨的明珠,分别对应了云计算中的两大核心功能:虚拟化和调度。资源的虚拟化为调度提供了前提,而调度则增加了系统了灵活性和资源的利用率。

kubernetes,简称k8s,至今已经已经成为容器编排的事实标准。本文则主要讲述k8s相关的一概念,并对其余的云上调度算法进行比较。

k8s提供的功能

  • 服务发现与负载均衡
    • 通过DNS名称或者IP地址访问容器
    • 分配节点间的网络流量
  • 存储编排
  • 自动部署和回滚
  • 自动完成装箱计算
  • 自我修复
  • 密钥与配置管理

k8s的组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pwXz3V7p-1622985228011)(https://gitee.com/weixiao619/pic/raw/master/components-of-kubernetes-20210605222057314.svg)]

控制面板组件

  • Kube-apiserver 对外暴露k8s的服务
  • etcd etcd是高可用的k-v数据库,在k8s中作为集群运行所需的持久化数据存储组件
  • Kube-scheduler 调度组件,选择将pod调度到哪个git当中
  • Kube-controller-manager 从逻辑上讲,每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。 这些控制器包括:
    • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应
    • 任务控制器(Job controller): 监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
    • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)
    • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌
  • Cloud-controller-manager 云控制器管理器是指嵌入特定云的控制逻辑的 控制平面组件。 云控制器管理器允许您链接聚合到云提供商的应用编程接口中, 并分离出相互作用的组件与您的集群交互的组件。

Node组件

  • kubelet
    • 运行在集群的每一个节点上,确保容器在pod上的运行
  • kube-proxy
    • 运行在每一个节点上的网络代理,负责节点和pod间通讯的网路规则
  • Container Runtime
    • Docker,containerd,CRI-O等任何实现k8s CRI (容器运行环境接口)
    • 最新k8s已不支持docker

插件

  • DNS
  • Web界面
  • 容器资源监控
  • 集群日志

k8s架构

如图为k8s的架构,其中一个Node一般为一个实际的宿主机,

Pods

pods是k8s管理的的最小计算单元

一个pod中包含一个或多个container,共享存储和网络资源

Pod也可以包含init container,同时也有ephemeral containers可以用于debug

Pod之间的上下文共享,依赖一系列linux的隔离技术实现,如 namespace、cgroups等

pod并不需要直接创建,而是通过deployment或statefulset等进行创建

pod的更新并不是更新已有的pod,而是创建一个新的pod去替换已有的pod

pod内共享资源和通信

存储

一个pod中共享一系列存储卷,pod中所有的containers都可以访问这些共享的卷,从而实现共享存储。pod内部的

网络
  • 每个pod被指定一个唯一的ip地址,pod中的每个容器都共享ip地址和端口。
  • pod内部的容器之间可以通过localhost进行通信,也可以通过linux标准的进程间通讯方式进行通讯

容器的特权模式:允许容器使用操作系统的管理员能力,例如操作网络栈,访问硬件资源等

静态pod

静态pod是直接通过kubelet进行管理的特殊节点,不能通过APIServer暴露,

pod的限制性拓扑策略

pod的拓扑策略配置样例,主要依赖四个参数:

#pod.spec.topologySpreadConstraints demo
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  topologySpreadConstraints:
    - maxSkew: <integer>   #标识节点的最大深度差
      topologyKey: <string>  # 标识一组调度节点
      whenUnsatisfiable: <string> # 不满足时的调度策略
      labelSelector: <object> # 用于寻找labels匹配的的pods

pod如何管理多个containers

Pod 被设计成支持形成内聚服务单元的多个协作过程(形式为容器)。 Pod 中的容器被自动安排到集群中的同一物理机或虚拟机上,并可以一起进行调度。 容器之间可以共享资源和依赖、彼此通信、协调何时以及何种方式终止自身。

例如,你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 “sidecar”容器负责从远端更新这些文件,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TzaRnOkk-1622985228014)(https://gitee.com/weixiao619/pic/raw/master/pod.svg)]

你可以使用工作负载资源来创建和管理多个 Pod。 资源的控制器能够处理副本的管理、上线,并在 Pod 失效时提供自愈能力。 例如,如果一个节点失败,控制器注意到该节点上的 Pod 已经停止工作, 就可以创建替换性的 Pod。调度器会将替身 Pod 调度到一个健康的节点执行

示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

工作负载类型

deploymnet

statefulset

DeamonSet

Jobs

服务

Service 从逻辑上定义了运行在集群中的一组 Pod,这些 Pod 提供了相同的功能。 当每个 Service 创建时,会被分配一个唯一的 IP 地址(也称为 clusterIP)。 这个 IP 地址与一个 Service 的生命周期绑定在一起,当 Service 存在的时候它也不会改变。 可以配置 Pod 使它与 Service 进行通信,Pod 知道与 Service 通信将被自动地负载均衡到该 Service 中的某些 Pod 上。

暴露服务的方式

  • NodePort
  • LoadBalancer
  • Ingress

拓扑感知提示

EndpointSlice 控制器

此特性开启后,EndpointSlice 控制器负责在 EndpointSlice 上设置提示信息。 控制器按比例给每个区域分配一定比例数量的端点。 这个比例来源于此区域中运行节点的 可分配 CPU 核心数。 例如,如果一个区域拥有 2 CPU 核心,而另一个区域只有 1 CPU 核心, 那控制器将给那个有 2 CPU 的区域分配两倍数量的端点。

服务内部流量策略

在相同node中访问pod

虚拟IP与Service代理

userspace 代理模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l4PUQnZ6-1622985228015)(https://gitee.com/weixiao619/pic/raw/master/services-userspace-overview.svg)]

iptable代理模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIh9V3QL-1622985228016)(https://gitee.com/weixiao619/pic/raw/master/services-iptables-overview.svg)]

ipvs代理模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MsQtTLd6-1622985228017)(https://gitee.com/weixiao619/pic/raw/master/services-ipvs-overview.svg)]

调度

在 Kubernetes 中,调度 是指将 Pod 放置到合适的 Node 上,然后对应 Node 上的 Kubelet 才能够运行这些 pod。

Kube-scheduler给一个pod做调度分为两部分内容:

1.过滤

2.打分

过滤

过滤过程中,会过滤出可调度的Node节点,过滤策略有如下几种:

GeneralPredicates

负责最基础的调度策略,过滤宿主机的CPU和内存等资源信息

Volume过滤规则

负责与容器持久化Volume相关的调度策略。例如:

检查多个 Pod 声明挂载的持久化 Volume 是否有冲突;

检查一个节点上某种类型的持久化 Volume 是不是已经超过了一定数目;

检查Pod 对应的 PV 的 nodeAffinity 字段,是否跟某个节点的标签相匹配

检查调度Pod是否满足Node本身的条件

如PodToleratesNodeTaints负责检查的就是我们前面经常用到的 Node 的“污点”机制。NodeMemoryPressurePredicate,检查的是当前节点的内存是不是已经不够充足。

affinity and anti-affinity

根据pod的node之间的亲和性与反亲和性进行过滤

打分

//筛选函数
// scheduleOne does the entire scheduling workflow for a single pod.
scheduleOne()

// 1. 超时打日志




// 2. 预选策略选出满足调度条件的Node节点
findNodesThatFit()
// Run "prefilter" plugins.
	s := fwk.RunPreFilterPlugins(ctx, state, pod)

// "NominatedNodeName" can potentially be set in a previous scheduling cycle as a result of preemption.
	// This node is likely the only candidate that will fit the pod, and hence we try it first before iterating over all nodes.
feasibleNodes, err := g.evaluateNominatedNode(ctx, pod, fwk, state, diagnosis)


// 用不同的过滤插件{NodePort, Volume, Label等}进行过滤
runFilterPlugin()

// 3. 对节点进行打分
prioritizeNodes()

// 运行预打分插件
// InterPodAffinity, NodeAffinity, PodTopologySpread, 
RunPreScorePlugins()

// 运行打分插件
RunScorePlugins()

代码逻辑

  1. 通过sched.NextPod()函数从优先队列中获取一个优先级最高的待调度Pod资源对象,如果没有获取到,那么该方法会阻塞住;
  2. 通过sched.Algorithm.Schedule调度函数执行Predicates的调度算法与Priorities算法,挑选出一个合适的节点;
  3. 当没有找到合适的节点时,调度器会尝试调用prof.RunPostFilterPlugins抢占低优先级的Pod资源对象的节点;
  4. 当调度器为Pod资源对象选择了一个合适的节点时,通过sched.bind函数将合适的节点与Pod资源对象绑定在一起;

Volcano 调度器

根据上一节的内容可以看出k8s原生的调度器,在调度的最后阶段(打分)是串行的调度每个pod,但是在AI训练或者大数据处理的场景下,多个实例需要进行相互协作,此时,实际的需求为需要保证一组实例同时运行成功,而k8s原生调度器无法满足此需求,因此kube-batch分组调度器应运而生,Volcano调度器则基于kube-batch进行了进一步的优化。

如图为Volcano调度器的工作流,一个job会打包多个pod形成一个PodGroup。

调度工作流

Volcano scheduler的工作流程如下:

  1. 客户端提交的Job被scheduler观察到并缓存起来。
  2. 周期性的开启会话,一个调度周期开始。
  3. 将没有被调度的Job发送到会话的待调度队列中。
  4. 遍历所有的待调度Job,按照定义的次序依次执行enqueue、allocate、preempt、reclaim、backfill等动作,为每个Job找到一个最合适的节点。将该Job 绑定到这个节点。action中执行的具体算法逻辑取决于注册的plugin中各函数的实现。
  5. 关闭本次会话。

Action作用

enqueue

Enqueue action负责通过一系列的过滤算法筛选出符合要求的待调度任务并将它们送入待调度队列。经过这个action,任务的状态将由pending变为inqueue。

allocate

Allocate action负责通过一系列的预选和优选算法筛选出最适合的节点。

preempt

Preempt action负责根据优先级规则为同一队列中高优先级任务执行抢占调度。

reclaim

Reclaim action负责当一个新的任务进入待调度队列,但集群资源已不能满足该任务所在队列的要求时,根据队列权重回收队列应得资源。

backfill

backfill action负责将处于pending状态的任务尽可能的调度下去以保证节点资源的最大化利用。

一些调度插件

Gang Scheduling

以组为单位进行调度,

DRF (dominant resource fairss)

优先调度请求资源较少的实例,yarn和mesos均有对应调度Sunday

binpack

该调度算法尽量先填满已有节点,将负载聚拢到部分节点,有利于弹性伸缩,减少资源碎片

proportion(队列)

与yarn的capacity Scheduler调度器类似,根据组织分配资源比例,在组织内部使用FIFO的队列模式进行资源调度

最终优选

Volcano支持各种调度算法的插件,不同插件的调度逻辑可能出现相互冲突,因此Volcano可以给不同的调度插件设置不同的权重,根据加权值来最终决定po d的调度。

kubelet工作原理

集群的每个Node均有一个kubelet进程,pod被调度到特定的Node后,由kubelet进行管理。

pod管理

Kubelet 以 PodSpec 的方式工作。PodSpec 是描述一个 Pod 的 YAML 或 JSON 对象。 kubelet 采用一组通过各种机制提供的 PodSpecs(主要通过 apiserver),并确保这些 PodSpecs 中描述的 Pod 正常健康运行

容器监控和健康检查

  • LivenessProbe
  • ReadinessProbe

容器运行时

工作模式

kubelet通过容器运行时接口 (Container Runtime Interface,CRI)与容器进行交互。

CRI将kubelet与容器运行时解耦:

架构

kubelet通过CRI结构与实际的container runtime进行交互,解耦不同容器的实现细节。如下为容器运行时的具体架构:

容器运行时主要定义了CRI Server和Streaming Server两个服务,其中CRI Server实现了具体的CRI服务接口,由Runtime Service和 Image Manger Service两个服务组成,具体的实现可参考下文中的源码分析。

CNI: Container Network Interface 容器网络接口

通过CNI将容器运行时与底层的网络插件实现解耦,使得容器无需关心底层的网络细节。

交互

CRI接口定义源码

// ImageManagerService 需要实现的功能
type ImageManagerService interface {
	// ListImages lists the existing images.
	ListImages(filter *runtimeapi.ImageFilter) ([]*runtimeapi.Image, error)
	// ImageStatus returns the status of the image.
	ImageStatus(image *runtimeapi.ImageSpec) (*runtimeapi.Image, error)
	// PullImage pulls an image with the authentication config.
	PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error)
	// RemoveImage removes the image.
	RemoveImage(image *runtimeapi.ImageSpec) error
	// ImageFsInfo returns information of the filesystem that is used to store images.
	ImageFsInfo() ([]*runtimeapi.FilesystemUsage, error)
}

// RuntimeService的实现又分为4个子实现,分别实现不同类型的功能模块
// RuntimeService interface should be implemented by a container runtime.
// The methods should be thread-safe.
type RuntimeService interface {
	RuntimeVersioner
	ContainerManager
	PodSandboxManager
	ContainerStatsManager

	// UpdateRuntimeConfig updates runtime configuration if specified
	UpdateRuntimeConfig(runtimeConfig *runtimeapi.RuntimeConfig) error
	// Status returns the status of the runtime.
	Status() (*runtimeapi.RuntimeStatus, error)
}

// 1. RuntimeVersioner contains methods for runtime name, version and API version.
type RuntimeVersioner interface {
	// Version returns the runtime name, runtime version and runtime API version
	Version(apiVersion string) (*runtimeapi.VersionResponse, error)
}

// 2. ContainerManager contains methods to manipulate containers managed by a
// container runtime. The methods are thread-safe.
type ContainerManager interface {
	// CreateContainer creates a new container in specified PodSandbox.
	CreateContainer(podSandboxID string, config *runtimeapi.ContainerConfig, sandboxConfig *runtimeapi.PodSandboxConfig) (string, error)
	// StartContainer starts the container.
	StartContainer(containerID string) error
	// StopContainer stops a running container with a grace period (i.e., timeout).
	StopContainer(containerID string, timeout int64) error
	// RemoveContainer removes the container.
	RemoveContainer(containerID string) error
	// ListContainers lists all containers by filters.
	ListContainers(filter *runtimeapi.ContainerFilter) ([]*runtimeapi.Container, error)
	// ContainerStatus returns the status of the container.
	ContainerStatus(containerID string) (*runtimeapi.ContainerStatus, error)
	// UpdateContainerResources updates the cgroup resources for the container.
	UpdateContainerResources(containerID string, resources *runtimeapi.LinuxContainerResources) error
	// ExecSync executes a command in the container, and returns the stdout output.
	// If command exits with a non-zero exit code, an error is returned.
	ExecSync(containerID string, cmd []string, timeout time.Duration) (stdout []byte, stderr []byte, err error)
	// Exec prepares a streaming endpoint to execute a command in the container, and returns the address.
	Exec(*runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error)
	// Attach prepares a streaming endpoint to attach to a running container, and returns the address.
	Attach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error)
	// ReopenContainerLog asks runtime to reopen the stdout/stderr log file
	// for the container. If it returns error, new container log file MUST NOT
	// be created.
	ReopenContainerLog(ContainerID string) error
}

// 3. PodSandboxManager contains methods for operating on PodSandboxes. The methods
// are thread-safe.
type PodSandboxManager interface {
	// RunPodSandbox creates and starts a pod-level sandbox. Runtimes should ensure
	// the sandbox is in ready state.
	RunPodSandbox(config *runtimeapi.PodSandboxConfig, runtimeHandler string) (string, error)
	// StopPodSandbox stops the sandbox. If there are any running containers in the
	// sandbox, they should be force terminated.
	StopPodSandbox(podSandboxID string) error
	// RemovePodSandbox removes the sandbox. If there are running containers in the
	// sandbox, they should be forcibly removed.
	RemovePodSandbox(podSandboxID string) error
	// PodSandboxStatus returns the Status of the PodSandbox.
	PodSandboxStatus(podSandboxID string) (*runtimeapi.PodSandboxStatus, error)
	// ListPodSandbox returns a list of Sandbox.
	ListPodSandbox(filter *runtimeapi.PodSandboxFilter) ([]*runtimeapi.PodSandbox, error)
	// PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address.
	PortForward(*runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error)
}

// 4. ContainerStatsManager contains methods for retrieving the container
// statistics.
type ContainerStatsManager interface {
	// ContainerStats returns stats of the container. If the container does not
	// exist, the call returns an error.
	ContainerStats(containerID string) (*runtimeapi.ContainerStats, error)
	// ListContainerStats returns stats of all running containers.
	ListContainerStats(filter *runtimeapi.ContainerStatsFilter) ([]*runtimeapi.ContainerStats, error)
}

CNI接口源码

type CNI interface {
   AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
   CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
   DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
   GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
   GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error)

   AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
   CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
   DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
   GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
   GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error)

   ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
   ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
}

k8s的可扩展性

k8s通过定义接口的方式,解耦了许多底层组件,极大的增强了k8s的可扩展性。

k8s的局限性

集群管理

水平伸缩性

Kubernetes 社区对外宣传的是单个集群最多支持 5,000 节点,Pod 总数不超过 150,000,容器总数不超过 300,000 以及单节点 Pod 数量不超过 100 个3,与几万节点的 Apache Mesos 集群、50,000 节点的微软 YARN 集群4相比,Kubernetes 的集群规模整整差了一个数量级。虽然阿里云的工程师也通过优化 Kubernetes 的各个组件实现了 5 位数的集群规模,但是与其他的资源管理方式相比却有比较大的差距5

多集群管理

k8s的多集群管理会带来 资源不平衡、跨集群访问困难等问题

现有的一些探索方案

kubefed

kubefed(Kubernetes Cluster Federation)是k8s社区给出的解决方案,提供了跨集群资源和网络管理的功能

应用场景

应用分发

Kubernetes 主项目提供了几种部署应用的最基本方式,分别是 DeploymentStatefulSetDaemonSet,这些资源分别适用于无状态服务、有状态服务和节点上的守护进程,这些资源能够提供最基本的策略,但是它们无法处理更加复杂的应用

很多常见的场景,例如只运行一次的 DaemonSet11 以及金丝雀和蓝绿部署等功能,现在的资源也存在很多问题,例如 StatefulSet 在初始化容器中卡住无法回滚和更新12

批处理调度

机器学习、批处理任务和流式任务等工作负载的运行从 Kubernetes 诞生第一天起到今天都不是它的强项,大多数的公司都会使用 Kubernetes 运行在线服务处理用户请求,用 Yarn 管理的集群运行批处理的负载。

硬多租户

今天的 Kubernetes 还很难做到硬多租户支持,也就是同一个集群的多个租户不会相互影响,也感知不到彼此的存在。尽管目前k8s用命名空间来划分虚拟集群,但也很难实现。这里是k8s社区相关的讨论小组地址

K8S的对比

调度算法的演进

  1. 单阶段 使用一个单一的中心化调度器,调度所有资源,同时没有并发,但是集群规模过大时无法很好的处理。同时新增调度的规则变得十分困难,因为所有的用户资源使用同样的调度逻辑。
  2. 两阶段调度 增强了集群的弹性,但是受到资源可见性和锁的双重限制,导致很难调度挑剔的节点
  3. 优化的两阶段调度 使用共享状态,进行乐观的无锁并发控制。Omega系统使用了该架构,增强了延展性和性能。

问题分类

对调度问题进行分类

资源选择

互相干扰

对资源进行调度时,如何解决并发冲突。

1.加锁

2.回撤

分配粒度

集群行为

集中调度

通过中央式调度器有且仅有一个实例,没有并行,而且在一个单一的代码库,必须实现所有的策略选择。这种方法常见于高性能计算(HPC),对于多种策略的支持有两种方式:

1.通过复杂的计算,针对多个权重因子计算出整体的优先级

2.调度逻辑通过调用不同的代码逻辑进行分离。谷歌之前采用的就是这种,虽然经过各种优化使得它有较好的性能和拓展性表现,但是最后决定将调度算法改进为支持并发、独立调度组件的首要原因是出于软件工程角度的考虑。

静态分区调度

将资源分为不同的区,每个不同的区域采用不同的调度方式,区域之间互相隔离

两层调度器

解决静态分区调度器的一个显而易见的方案是实现分区的动态化,这就是两层调度器的工作原理,通过一个中心来对各个分区的资源进行协调分配,这种两层调度被Mesos和Hadoop-on-Demand广泛采用

mesos基于DRF策略和offer-based(主动提供)的方式由master向各个计算框架分配资源,并且提供了过滤器机制,计算框架可以事先描述自己需要的资源特征。该架构适用于短任务,并且存在一定的缺点:(1)offer-based的方式是悲观锁实现的,每次只能给一个计算框架分配资源,导致并发度低;(2)每次的分配都是基于当前状况进行的,计算框架并不能感知到系统的资源情况,所以分配不是全局最优的;(3)逐个计算框架进行分配导致系统不能够支持资源抢占;(4)当系统中被短任务填充时,会导致长任务饿死;(5)资源保持可能会导致死锁现象的发生;

Yarn采用的是可能是一种两层调度,但更多的是集中调度:

yarn是基于资源申请的方式进行资源分配的。AM向RM请求资源,RM基于NM的心跳触发分配,按照一定的策略将资源分配给AM,AM与NM通信运行任务。目前的yarn还存在一些缺点:目前的AM只负责进行任务管理并没有提供调度的能力,这也是一部分人将YARN划分为集中式调度器的原因;目前仅支持对内存的分配;虽然现在yarn支持AM在进行资源申请的时候选择放置偏好点,但是并没有说明这些偏好是根据什么标准得到的。

共享状态调度

针对两层调度系统存在的并行性和不能进行全局最优的调度问题,共享状态系统进行了优化。主要有两点措施,第一存在多个调度器,每个调度器都拥有系统全量的资源信息,可以根据该信息进行调度。第二调度器将其调度的结果以原子的方式提交给cell state维护模块,由其决定本次提交是否成功,这里体现了乐观并发的思想。

每个调度器会定期以私有的方式更新自己副本中的cell state; 每个调度器可以设置其私有得调度策略,有很大的自由度; Omega只是将优先级这一限制放到了共享数据的验证代码中,即当同时由多个应用程序申请同一份资源时,优先级最高的那个应用程序将获得该资源,其他资源限制全部下放到各个子调度器。 对整个集群中的所有资源分组,限制每类应用程序的资源使用量,限制每个用户的资源使用量等,这些全部由各个应用程序调度器自我管理和控制。 引入多版本并发控制后,限制该机制性能的一个因素是资源访问冲突的次数,冲突次数越多,系统性能下降的越快,而google通过实际负载测试证明,这种方式的冲突次数是完全可以接受的。

Borg

原文地址:https://cloud.tencent.com/developer/article/2028511

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读942次。kube-controller-manager 和 kubelet 是异步工作的,这意味着延迟可能包括任何的网络延迟、apiserver 的延迟、etcd 延迟,一个节点上的负载引起的延迟等等。当 Kubernetes 中 Node 节点出现状态异常的情况下,节点上的 Pod 会被重新调度到其他节点上去,但是有的时候我们会发现节点 Down 掉以后,Pod 并不会立即触发重新调度,这实际上就是和 Kubelet 的状态更新机制密切相关的,Kubernetes 提供了一些参数配置来触发重新调度的时间。_node-monitor-period
文章浏览阅读3.8k次。上篇文章详细介绍了弹性云混部的落地历程,弹性云是滴滴内部提供给网约车等核心服务的容器平台,其基于 k8s 实现了对海量 node 的管理和 pod 的调度。本文重点介绍弹性云的调度能力,分为以下部分:调度链路图:介绍当前弹性云调度体系链路,对架构体系有一个初步的认知k8s 调度能力的运用:整体介绍弹性云现在用到的 k8s 调度能力和对其的增强k8s 版本的升级:介绍到从 k8s 1.12 到 1...._滴滴机房 腾讯
文章浏览阅读897次。对于cpu来说,这种分配方式并不会有太大问题,因为cpu可以灵活调度,numa调度时我们只计算绑定了numa cpu的pod是可以接受的,但是对于内存来说,numa node上申请了的内存无法做到随时迁移,这就会导致调度器视角numa node的mem资源足够,但是等到pod真正使用时,由于没有绑定numa node的pod申请的内存,导致numa node的mem资源不足,造成swap中断或者远端内存申请,这会对绑定mem的pod来带来性能损耗。忽略了没有绑定numa node的pod资源。_kubectl numa
文章浏览阅读796次,点赞17次,收藏15次。只要在Service定义中设置了ClusterIp:None,就定义了一个HeadLess Service, 它与普通的Service关键区别在于它没有ClusterIp地址,如果解析HeadLess Service的DNS域名,则会返回该Service对应的全部Pod的EndPoint列表,这就意味着客户端是直接与后端的pod建立了TCP/IP链接进行通信的。一个Label是一个键值对。注解:属于资源对象的元数据,可以被理解为一种特殊的标签,不过更多的是与程序挂钩,通常用于实现资源对象属性的自定义扩展。
文章浏览阅读763次。但是此时如果配置成 NONE, 租户创建成功了,但是无法创建资源文件,也就是无法上传文件,可能 dolphinscheduler 团队就想着将文件上传到 hdfs,暂不支持本地。需要将 resource.storage.type 置为 NONE, 因为我之前用的 1.3.6 版本的时候,即使资源文件存在本地文件也需要配置成 hdfs。_[error] 2023-10-24 18:10:43.762 +0800 org.apache.dolphinscheduler.api.servic
文章浏览阅读2.7k次,点赞2次,收藏13次。公司使用的是交老的k8s版本(1.16),由于老版本的K8s对于现在很多新特性不支持,所以需要升级到新版本。目前2023年7月11日最新版本的k8s是v1.27.3。通过参考官方文档进行k8s部署工作。其中涉及到操作系统配置、防火墙配置、私有镜像仓库等。_k8s最新版本
文章浏览阅读1.8w次,点赞14次,收藏27次。能节省你在kubeadm init 时遇到问题的排错时间⌚️。整合了网上大佬
文章浏览阅读1.1k次,点赞2次,收藏7次。具体操作步骤可以参考之前的教程,建议是先安装一台,然后克隆虚拟机,这样速度快。注意:在克隆时记得修改Mac地址、IP地址、UUID和主机名。(最后别忘了保存下快照~)_部署k8s集群
文章浏览阅读863次,点赞23次,收藏16次。当部署完 Kubernetes,便拥有了一个完整的集群。一组工作机器,称为节点, 会运行容器化应用程序。每个集群至少有一个工作节点。工作节点会 托管Pod ,而 Pod 就是作为应用负载的组件。控制平面管理集群中的工作节点和Pod。说人话版本:集群:cluster,多个几点被组织到一起共同为系统提供服务过程称之为集群。本质上是将承载同一个软件服务节点组织到一起,称之为该软件(服务)的集群,当然集群中的节点身份地位是不一样的。k8s集群也是如此,他也是多个节点组成。
文章浏览阅读943次。Rancher是一个开源的企业级多集群Kubernetes管理平台,实现了Kubernetes集群在混合云+本地数据中心的集中部署与管理,以确保集群的安全性,加速企业数字化转型。Rancher 1.0版本在2016年就已发布,时至今日,Rancher已经成长为企业在生产环境中运行容器和Kubernetes的首要选择。_rancher管理k8s
文章浏览阅读742次,点赞2次,收藏3次。本篇来讲解如何在centos下安装部署高可用k8s集群。_kubeadm ha keepalived + nginx
文章浏览阅读1.9k次,点赞21次,收藏25次。那么这个空间设置成内存的2倍大小。点击IPv4设置--手动--添加--设置ip--设置DNS服务器,最后点击--“保存”;首先选中--“本地标准磁盘”,存储配置--自定义分区,点击--“完成”;在--主机名--设置主机名:(例如k8s-master01),点击--点击+,设置--挂载点/boot--期望容量,点击--添加挂载点;点击--+--挂载点swap--期望容量,点击--“添加挂载点”;默认选择--亚洲--上海,并调整日期和时间,点击--“完成”;设备类型--确认--LVM,卷组--选择“修改”;_euler 服务器搭建
文章浏览阅读1k次。在1.25版本的k8s集群中部署gpu-manage时,虽然显示gpu节点上gpu-manage的pod实例都是running状态,但是给pod申领。既可以用源码的Makefile自动编译打包成新的镜像,但是源码的。说明gpu-manager和容器运行时接口通信失败了。编译后的镜像在1.25版本的k8s中可以正常使用。,但是在k8s1.23版本之后,接口路径已经改为。资源时,却始终找不到有资源的节点。,另外有一些依赖需要国际上的支持。可以看到这里用的运行时接口是。查看节点的详情时,返回的。_launch gpu manager 报错 can't create container runtime manager: context dead
文章浏览阅读1k次,点赞18次,收藏16次。SelfLink:API的资源对象之一,表示资源对象在集群当中自身的一个连结,self-Link是一个唯一的标识号,可以用于标识k8s集群当中的每个资源的对象。容器里使用的配置,在provisioner当中定义好环境变量,传给容器,storageclass的名称,NFS服务器的地址,NFS的目录。NFS的provisionner的客户端以pod的方式运行在集群当中,监听k8s集群当中PV的请求,然后动态的创建于NFS相关的PV。命名为 nfs-client-provisioner-clusterrole。
文章浏览阅读6.3k次,点赞2次,收藏20次。k8s证书过期解决方案之替换证书_k8s证书过期如何更换
文章浏览阅读1k次。KMS,Key Management Service,即密钥管理服务,在K8S集群中,以驱动和插件的形式启用对Secret,Configmap进行加密。以保护敏感数据
文章浏览阅读888次。exporter对于云服务的监控还是很不完美,毕竟每家都有自己的护城河。自动发现多实例这样的借助consul 阿波罗这样的会简单一些。aws可以借助cloudwatch这样的导入模板到grafana中。还是希望能将类似腾讯云云监控中的这些指标采集到prometheus中,但是这过程应该还很遥远grafana出图 prometheus查询语法这些东西有时间的好好研究一下。报警有必要进行分级别,收敛配置一下!_command: - "-redis.password-file=/redis_passwd.json
文章浏览阅读1k次。可以在此处(https://cloud.google.com/kubernetes-engine/docs/how-to/kube-dns)和此处(https://www.digitalocean.com/community/tutorials/an-introduction-to-the-kubernetes-dns-service)找到更多的详细信息。-or-ipvs/)和此处(https://arthurchiao.art/blog/cracking-k8s-node-proxy/)。_k8s默认命名空间
文章浏览阅读4.9k次,点赞11次,收藏32次。如果运行runc命令时提示:runc: error while loading shared libraries: libseccomp.so.2: cannot open shared object file: No such file or directory,则表明runc没有找到libseccomp,需要检查libseccomp是否安装,本次安装默认就可以查询到。所有主机均需要操作。所有主机均需要操作。所有主机均需要操作。所有主机均需要操作。所有主机均需要操作。所有主机均需要操作。_kubernetes 1.28
文章浏览阅读3.6w次,点赞118次,收藏144次。Canal 提供了网络功能,使得 Kubernetes 集群中的 Pod 可以相互通信,并与集群外部的服务进行通信。它通过网络插件的方式,为每个 Pod 分配唯一的 IP 地址,并管理网络流量的路由和转发。此外,Canal 还支持网络策略,用于定义 Pod 之间的通信规则和安全策略。Canal 基于 Calico 和 Flannel 项目,结合了二者的优点。它使用 Calico 的数据平面,提供高性能的网络转发和安全特性,同时使用 Flannel 的控制平面,实现 IP 地址管理和网络策略的配置。_k8s canal