Kubernetes 云管理控制器

云管理控制器(Cloud Controller Manager)是 1.8 版本中的一个 alpha 特性。在以后的版本中,它将成为 Kubernetes 与任何云服务进行集成的首选方式。这将保证云服务提供商(cloud provider)能够在 Kubernetes 核心发布周期外独立开发他们的特性。

云管理控制器

Kubernetes v1.6 包含一个新的二进制文件,叫做 cloud-controller-manager。cloud-controller-manager 是一个嵌入了特定云服务(cloud-specific)控制循环逻辑的守护进程。这些特定云服务控制循环逻辑最初存在于 kube-controller-manager 中。由于云服务提供商开发和发布的速度与 Kubernetes 项目不同,将服务提供商专用代码从 cloud-controller-manager 二进制中抽象出来有助于云服务厂商在 Kubernetes 核心代码之外独立进行开发。

cloud-controller-manager 可以被链接到任何满足 cloudprovider.Interface 约束的云服务提供商。为了兼容旧版本,Kubernetes 核心项目中提供的 cloud-controller-manager 使用和 kube-controller-manager 相同的云服务类库。已经在 Kubernetes 核心项目中支持的云服务提供商预计将通过使用 in-tree 的 cloud-controller-manager 过渡到 Kubernetes 核心之外。在将来的 Kubernetes 发布中,所有的云管理控制器将在 Kubernetes 核心项目之外,由 sig 领导者或者云服务厂商进行开发。

管理

需求

每个云服务都有一套各自的需求用于系统平台的集成,这不应与运行 kube-controller-manager 的需求有太大差异。作为经验法则,你需要:

  • 云服务认证/授权:您的云服务可能需要使用令牌或者 IAM 规则以允许对其 API 的访问
  • kubernetes 认证/授权:cloud-controller-manager 可能需要 RBAC 规则以访问 kubernetes apiserver
  • 高可用:类似于 kube-controller-manager,您可能希望通过主节点选举(leader election,默认开启)配置一个高可用的云管理控制器

运行 cloud-controller-manager

您需要对集群配置做适当的修改以成功地运行 cloud-controller-manager:

  • 一定不要为 kube-apiserver 和 kube-controller-manager 指定 --cloud-provider 标志。这将保证它们不会运行任何云服务专用循环逻辑,这将会由云控制管理器运行。未来这个标记将被废弃并去除。
  • kubelet 必须使用 --cloud-provider=external 运行。这是为了保证让 kubelet 知道在执行任何任务前,它必须被云控制管理器初始化。
  • kube-apiserver 不应该运行 PersistentVolumeLabel 准入控制器,因为云管理控制器将接管对 persistent volume 的标记工作。为了避免运行 PersistentVolumeLabel 准入控制插件,请确认 kube-apiserver 的 --admission-control 标志的值不包含 PersistentVolumeLabel。
  • 为了使用 cloud-controller-manager 标记 persistent volume,需要启用 initializer 并添加 InitializerConifguration 到系统中。请参照 这些指导 来启用 initializer。使用下面的 YAML 文件创建 InitializerConfiguration:
persistent-volume-label-initializer-config.yaml 
kind: InitializerConfiguration
apiVersion: admissionregistration.k8s.io/v1alpha1
metadata:
  name: pvlabel.kubernetes.io
initializers:
  - name: pvlabel.kubernetes.io
    rules:
    - apiGroups:
      - ""
      apiVersions:
      - "*"
      resources:
      - persistentvolumes

请记住,配置集群使用云管理控制器将会从几个方面改变集群的行为:

  • 指定了 --cloud-provider=external 的 kubelet 将被添加一个 node.cloudprovider.kubernetes.io/uninitialized 的 taint,导致其在初始化过程中 不可调度(NoSchedule)。这将标记该节点在能够正常调度前,需要外部的控制器进行二次初始化。请注意,如果云管理控制器不可用,集群中的新节点会一直处于不可调度的状态。这个 taint 很重要,因为调度器可能需要关于节点的云服务特定的信息,比如他们的区域或类型(high cpu, gpu, high memory, spot instance 等)。
  • 集群中节点的云服务信息将不再能够从本地元数据中获取,取而代之的是所有获取节点信息的 API 调用都将通过云管理控制器。这意味着你可以通过限制到 kubelet 云服务 API 的访问来提升安全性。在更大的集群中您可能需要考虑云管理控制器是否会遇到速率限制,因为它现在负责集群中几乎所有到云服务的 API 调用。

对于 v1.8 版本,云管理控制器可以实现:

  • node 控制器 - 负责使用云服务 API 更新 kubernetes 节点并删除在云服务上已经删除的 kubernetes 节点。
  • service 控制器 - 负责在云服务上为类型为 LoadBalancer 的 service 提供负载均衡器。
  • route 控制器 - 负责在云服务上配置网络路由。
  • PersistentVolumeLabel Admission 控制器 - 负责在云服务上标记 persistent volume - 请确保 persistent volume label 准入控制插件没有在您的 kube-apiserver 上启用。
  • 如果您使用的是 out-of-tree 提供商,请按需实现其余任意特性。

示例

如果当前 Kubernetes 内核支持您使用的云服务,并且想要采用云管理控制器,请参见 kubernetes 内核中的云管理控制器

对于不在 Kubernetes 内核中的云管理控制器,您可以在云服务厂商或 sig 领导者的源中找到对应的项目。

对于已经存在于 Kubernetes 内核中的提供商,您可以在集群中将 in-tree 云管理控制器作为守护进程运行。请使用如下指南:

cloud-controller-manager-daemonset-example.yaml 
# This is an example of how to setup cloud-controller-manger as a Daemonset in your cluster.
# It assumes that your masters can run pods and has the role node-role.kubernetes.io/master
# Note that this Daemonset will not work straight out of the box for your cloud, this is
# meant to be a guideline.

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cloud-controller-manager
  namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: system:cloud-controller-manager
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: cloud-controller-manager
  namespace: kube-system
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  labels:
    k8s-app: cloud-controller-manager
  name: cloud-controller-manager
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: cloud-controller-manager
  template:
    metadata:
      labels:
        k8s-app: cloud-controller-manager
    spec:
      serviceAccountName: cloud-controller-manager
      containers:
      - name: cloud-controller-manager
        # for in-tree providers we use gcr.io/google_containers/cloud-controller-manager
        # this can be replaced with any other image for out-of-tree providers
        image: gcr.io/google_containers/cloud-controller-manager:v1.8.0
        command:
        - /usr/local/bin/cloud-controller-manager
        - --cloud-provider=<YOUR_CLOUD_PROVIDER>   # Add your own cloud provider here!
        - --leader-elect=true
        - --use-service-account-credentials
        # these flags will vary for every cloud provider
        - --allocate-node-cidrs=true
        - --configure-cloud-routes=true
        - --cluster-cidr=172.17.0.0/16
      tolerations:
      # this is required so CCM can bootstrap itself
      - key: node.cloudprovider.kubernetes.io/uninitialized
        value: "true"
        effect: NoSchedule
      # this is to have the daemonset runnable on master nodes
      # the taint may vary depending on your cluster setup
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      # this is to restrict CCM to only run on master nodes
      # the node selector may vary depending on your cluster setup
      nodeSelector:
        node-role.kubernetes.io/master: ""

限制

运行云管理控制器会有一些可能的限制。虽然以后的版本将处理这些限制,但是知道这些生产负载的限制很重要。

对 Volume 的支持

云管理控制器未实现 kube-controller-manager 中的任何 volume 控制器,因为和 volume 的集成还需要与 kubelet 协作。由于我们引入了 CSI (容器存储接口,container storage interface) 并对弹性 volume 插件添加了更强大的支持,云管理控制器将添加必要的支持,以使云服务同 volume 更好的集成。请在 这里 了解更多关于 out-of-tree CSI volume 插件的信息。

可扩展性

在以前为云服务提供商提供的架构中,我们依赖 kubelet 的本地元数据服务来获取关于它本身的节点信息。通过这个新的架构,现在我们完全依赖云管理控制器来获取所有节点的信息。对于非常大的集群,您需要考虑可能的瓶颈,例如资源需求和 API 速率限制。

鸡和蛋的问题

云管理控制器的目标是将云服务特性的开发从 Kubernetes 核心项目中解耦。不幸的是,Kubernetes 项目的许多方面都假设云服务提供商的特性同项目紧密结合。因此,这种新架构的采用可能导致某些场景下,当一个请求需要从云服务提供商获取信息时,在该请求没有完成的情况下云管理控制器不能返回那些信息。

Kubelet 中的 TLS 引导特性是一个很好的例子。目前,TLS 引导认为 Kubelet 有能力从 cloud provider 获取所有的地址类型(私有、公用等),但在被初始化之前,云管理控制器不能设置节点地址类型,而这需要 kubelet 拥有 TLS 证书以和 apiserver 通信。

随着这种措施的演进,将来的发行版中将作出改变来解决这些问题。

开发自己的云管理控制器

要构建和开发您自己的云管理控制器,请阅读 开发云管理控制器 文档。

译者:xiaosuiba / 原文链接

K8S中文社区微信公众号

Kubernetes 创建一个外部负载均衡器

本文描述如何创建一个外部负载均衡设备。

当创建一个服务时,你可以选择自动创建一个云端的网路负载均衡器。这能为外部提供一个可达的 IP 地址, 这个地址会将数据传递到集群节点上正确的服务端口,但前提是,集群运行在一个可支持负载均衡的环境中,并且对云端但负载均衡正确地进行了配置。

Before you begin

  • You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.

配置文件

创建外部负载均衡器时,请把下面几行添加到 服务配置文件中:

    "type": "LoadBalancer"

配置文件类似于:

    {
      "kind": "Service",
      "apiVersion": "v1",
      "metadata": {
        "name": "example-service"
      },
      "spec": {
        "ports": [{
          "port": 8765,
          "targetPort": 9376
        }],
        "selector": {
          "app": "example"
        },
        "type": "LoadBalancer"
      }
    }

使用 kubectl

或者也可以使用 kubectl expose 命令和 --type=LoadBalancer 参数创建服务:

kubectl expose rc example --port=8765 --target-port=9376 \
        --name=example-service --type=LoadBalancer

这个命令使用了相同的 selector 作为关联资源来创建服务(在上面这个例子中,replication controller 的名字为 example):

更多信息(包括可选的参数)参考 kubectl expose 手册

查看 IP 地址

通过 kubectl 可以查看到所创建服务的 IP 地址:

kubectl describe services example-service

输出应该是这样的:

    Name:  example-service
    Selector:   app=example
    Type:     LoadBalancer
    IP:     10.67.252.103
    LoadBalancer Ingress: 123.45.678.9
    Port:     <unnamed> 80/TCP
    NodePort:   <unnamed> 32445/TCP
    Endpoints:    10.64.0.4:80,10.64.1.5:80,10.64.2.4:80
    Session Affinity: None
    No events.

IP 地址会显示在 LoadBalancer Ingress 右侧。

保留客户端源 IP

因为对于这个特性的代码实现的关系,目标容器看到的源 IP 不是客户端的源 IP。如需要保留客户端源 IP, 可以配置一下这些服务的 spec 字段(GCE/GKE 环境中可支持):

  • service.spec.externalTrafficPolicy - 如果这个服务需要将外部流量路由到 本地节点或者集群级别的端点,那么需要指明该参数。存在两种选项:”Cluster”(默认)和 “Local”。 “Cluster” 隐藏源 IP 地址,可能会导致第二跳(second hop)到其他节点,但是全局负载效果较好。”Local” 保留客户端源 IP 地址,避免 LoadBalancer 和 NodePort 类型服务的第二跳,但是可能会导致负载不平衡。
  • service.spec.healthCheckNodePort - 定义服务的 healthCheckNodePort (数字端口号)。 如果没有声明,服务 API 后端会用分配的 nodePort 创建 healthCheckNodePort。如果客户端 指定了 nodePort,则会使用用户自定义值。这只有当类型被设置成 “LoadBalancer” 并且 externalTrafficPolicy 被设置成 “Local” 时,才会生效。

可用通过将服务的配置文件中的 externalTrafficPolicy 参数设置为 “Local” 来激活这个特性。

    {
      "kind": "Service",
      "apiVersion": "v1",
      "metadata": {
        "name": "example-service",
      },
      "spec": {
        "ports": [{
          "port": 8765,
          "targetPort": 9376
        }],
        "selector": {
          "app": "example"
        },
        "type": "LoadBalancer",
        "externalTrafficPolicy": "Local"
      }
    }

功能特性可用性

k8s 版本 特性功能
1.7+ 支持全 API 字段
1.5 - 1.6 支持 Beta Annotations
<1.5 不支持

可以在下面找到已经被废弃的 Beta 注释(annotation),它们用于在老版本中开启这个功能。 新版本的 Kubernetes 将会在 v1.7 后停止支持这些注释。请更新现有应用直接使用字段(field)。

  • service.beta.kubernetes.io/external-traffic 注释 <-> service.spec.externalTrafficPolicy 字段
  • service.beta.kubernetes.io/healthcheck-nodeport 注释 <-> service.spec.healthCheckNodePort 字段

service.beta.kubernetes.io/external-traffic 注释相比 service.spec.externalTrafficPolicy 字段而言有一套不同的值。值的对应关系如下:

  • “OnlyLocal” 用于注释 <-> “Local” 用于字段
  • “Global” 用于注释 <-> “Cluster” 用于字段

注意这个特性目前并未在所有云平台/环境中实现。

外部负载均衡提供者

非常需要注意的是,这个功能的数据路径(datapath)是由 Kubernetes 集群的外部负载均衡器提供的。

当服务类型被设置为 LoadBalancer 时,Kubernetes 提供的功能等同于 type=<ClusterIP> 在集群中对于 pod 的功能, 并且通过使用 Kubernetes 虚拟机入口对负载均衡器(Kubernetes 外部的)编程来对其进行扩展。 Kubernetes 服务控制器自动创建外部负载均衡器,健康检查(如果需要的话),防火墙规则(如果需要的话)并且获取云服务提供商分配的外部 IP 并将其存入服务对象中。

使用保留源 IP 的警告和限制

GCE/AWS 负载均衡器不为目标池提供权重。这对于旧的负载均衡 kube-proxy 规则而言不是问题,旧的负载均衡规则依然能正确地平衡所有端点的流量。

新功能中,外部的流量不会按照 pod 平均分配,而是在节点(node)层面平均分配(因为 GCE/AWS 和其他外部负载均衡实现没有能力做节点权重, 而是平均地分配给所有目标节点,忽略每个节点上所拥有的 pod 数量)。

然而,在 pod 数量(NumServicePods) « 节点数(NumNodes)或者 pod 数量(NumServicePods) » 节点数(NumNodes)的情况下,即使没有权重策略,我们也可以看到非常接近公平分发的场景。

一旦外部负载均衡提供了权重,这个功能可以添加到负载均衡的编程路径中。 未来的工作:1.4 版本对于权重没有支持,但是可能会在未来加入这个功能

内部 pod 对 pod 的流量应该与 ClusterIP 服务类似,流量对于所有 pod 是均分的。

译者:zhangqx2010 / 原文链接

K8S中文社区微信公众号

Kubernetes 给 Pod 配置服务质量等级

这篇教程指导如何给 Pod 配置特定的服务质量(QoS)等级。Kubernetes 使用 QoS 等级来确定何时调度和终结 Pod 。

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.

QoS 等级

当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级:

  • Guaranteed
  • Burstable
  • BestEffort

创建一个命名空间

创建一个命名空间,以便将我们实验需求的资源与集群其他资源隔离开。

kubectl create namespace qos-example

创建一个 Pod 并分配 QoS 等级为 Guaranteed

想要给 Pod 分配 QoS 等级为 Guaranteed:

  • Pod 里的每个容器都必须有内存限制和请求,而且必须是一样的。
  • Pod 里的每个容器都必须有 CPU 限制和请求,而且必须是一样的。

这是一个含有一个容器的 Pod 的配置文件。这个容器配置了内存限制和请求,都是200MB。它还有 CPU 限制和请求,都是700 millicpu:

qos-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo
spec:
  containers:
  - name: qos-demo-ctr
    image: nginx
    resources:
      limits:
        memory: "200Mi"
        cpu: "700m"
      requests:
        memory: "200Mi"
        cpu: "700m"

创建 Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod.yaml --namespace=qos-example

查看 Pod 的详细信息:

kubectl get pod qos-demo --namespace=qos-example --output=yaml

输出显示了 Kubernetes 给 Pod 配置的 QoS 等级为 Guaranteed 。也验证了容器的内存和 CPU 的限制都满足了它的请求。

spec:
  containers:
    ...
    resources:
      limits:
        cpu: 700m
        memory: 200Mi
      requests:
        cpu: 700m
        memory: 200Mi
...
  qosClass: Guaranteed

注意: 如果一个容器配置了内存限制,但是没有配置内存申请,那 Kubernetes 会自动给容器分配一个符合内存限制的请求。 类似的,如果容器有 CPU 限制,但是没有 CPU 申请,Kubernetes 也会自动分配一个符合限制的请求。

删除你的 Pod:

kubectl delete pod qos-demo --namespace=qos-example

创建一个 Pod 并分配 QoS 等级为 Burstable

当出现下面的情况时,则是一个 Pod 被分配了 QoS 等级为 Burstable :

  • 该 Pod 不满足 QoS 等级 Guaranteed 的要求。
  • Pod 里至少有一个容器有内存或者 CPU 请求。

这是 Pod 的配置文件,里面有一个容器。这个容器配置了200MB的内存限制和100MB的内存申请。

qos-pod-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-2
spec:
  containers:
  - name: qos-demo-2-ctr
    image: nginx
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"

创建 Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-2.yaml --namespace=qos-example

查看 Pod 的详细信息:

kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml

输出显示了 Kubernetes 给这个 Pod 配置了 QoS 等级为 Burstable.

spec:
  containers:
  - image: nginx
    imagePullPolicy: Always
    name: qos-demo-2-ctr
    resources:
      limits:
        memory: 200Mi
      requests:
        memory: 100Mi
...
  qosClass: Burstable

删除你的 Pod:

kubectl delete pod qos-demo-2 --namespace=qos-example

创建一个 Pod 并分配 QoS 等级为 BestEffort

要给一个 Pod 配置 BestEffort 的 QoS 等级, Pod 里的容器必须没有任何内存或者 CPU 的限制或请求。

下面是一个 Pod 的配置文件,包含一个容器。这个容器没有内存或者 CPU 的限制或者请求:

qos-pod-3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-3
spec:
  containers:
  - name: qos-demo-3-ctr
    image: nginx

创建 Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-3.yaml --namespace=qos-example

查看 Pod 的详细信息:

kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml

输出显示了 Kubernetes 给 Pod 配置的 QoS 等级是 BestEffort.

spec:
  containers:
    ...
    resources: {}
  ...
  qosClass: BestEffort

删除你的 Pod:

kubectl delete pod qos-demo-3 --namespace=qos-example

创建一个拥有两个容器的 Pod

这是一个含有两个容器的 Pod 的配置文件,其中一个容器指定了内存申请为 200MB ,另外一个没有任何申请或限制。

qos-pod-4.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: qos-demo-4
spec:
  containers:

  - name: qos-demo-4-ctr-1
    image: nginx
    resources:
      requests:
        memory: "200Mi"

  - name: qos-demo-4-ctr-2
    image: redis

注意到这个 Pod 满足了 QoS 等级 Burstable 的要求. 就是说,它不满足 Guaranteed 的要求,而且其中一个容器有内存请求。

创建 Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-4.yaml --namespace=qos-example

查看 Pod 的详细信息:

kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml

输出显示了 Kubernetes 给 Pod 配置的 QoS 等级是 Burstable:

spec:
  containers:
    ...
    name: qos-demo-4-ctr-1
    resources:
      requests:
        memory: 200Mi
    ...
    name: qos-demo-4-ctr-2
    resources: {}
    ...
  qosClass: Burstable

删除你的 Pod:

kubectl delete pod qos-demo-4 --namespace=qos-example

清理

删除你的 namespace:

kubectl delete namespace qos-example

What’s next

对于集群管理员

对于应用开发者

译者:NickSu86 / 原文链接

K8S中文社区微信公众号

Kubernetes 为API对象配置配额

本任务将展示如何配置API对象的配额,包括对Kubernetes PersistentVolumeClaim对象 和Service对象的配额配置。配额限制了可以在某一名字空间(namespace)中所创建的特定类型的对象 的数量。可以通过ResourceQuota 对象设定配额。

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.

创建名字空间

创建一个单独的名字空间,以便于隔离您在本练习中创建的资源与集群的其他资源。

kubectl create namespace quota-object-example

创建ResourceQuota对象

以下展示了ResourceQuota对象的配置文件内容:

quota-objects.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-quota-demo
spec:
  hard:
    persistentvolumeclaims: "1"
    services.loadbalancers: "2"
    services.nodeports: "0"

下面,首先创建ResourceQuota对象:

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-objects.yaml --namespace=quota-object-example

然后可以通过以下命令查看ResourceQuota对象的详细信息:

kubectl get resourcequota object-quota-demo --namespace=quota-object-example --output=yaml

上述命令的输出显示在quota-object-example名字空间中,最多可以创建一个PersistentVolumeClaim以及两个 LoadBalancer类型的Service,不能创建NodePort类型的Service。

status:
  hard:
    persistentvolumeclaims: "1"
    services.loadbalancers: "2"
    services.nodeports: "0"
  used:
    persistentvolumeclaims: "0"
    services.loadbalancers: "0"
    services.nodeports: "0"

创建一个PersistentVolumeClaim:

下面展示了一个PersistentVolumeClaim对象的配置文件内容:

quota-objects-pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-quota-demo
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

创建这个PersistentVolumeClaim:

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-objects-pvc.yaml --namespace=quota-object-example

接下来验证这个PersistentVolumeClaim已经被成功创建:

kubectl get persistentvolumeclaims --namespace=quota-object-example

上述命令的输出显示这个PersistentVolumeClaim已经存在在系统中并处于Pending状态:

NAME             STATUS
pvc-quota-demo   Pending

尝试创建第二个PersistentVolumeClaim:

第二个PersistentVolumeClaim的配置文件如下所示:

quota-objects-pvc-2.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-quota-demo-2
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

尝试创建第二个PersistentVolumeClaim:

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-objects-pvc-2.yaml --namespace=quota-object-example

以上命令的输出中可以看到第二个PersistentVolumeClaim没有被创建,因为如果创建 第二个PersistentVolumeClaim对象将违反名字空间中的配额限制。

persistentvolumeclaims "pvc-quota-demo-2" is forbidden:
exceeded quota: object-quota-demo, requested: persistentvolumeclaims=1,
used: persistentvolumeclaims=1, limited: persistentvolumeclaims=1

注意

以下字符串用于标记可以由配额限制的API资源:

字符串 API对象
"pods" Pod
"services Service
"replicationcontrollers" ReplicationController
"resourcequotas" ResourceQuota
"secrets" Secret
"configmaps" ConfigMap
"persistentvolumeclaims" PersistentVolumeClaim
"services.nodeports" NodePort类型的Service
"services.loadbalancers" LoadBalancer类型的Service

环境清理

删除在本练习中创建的名字空间即可完成环境清理:

kubectl delete namespace quota-object-example

What’s next

对于集群管理员

对于应用开发者

译者:xingzhou / 原文链接

K8S中文社区微信公众号

Kubernetes 为 Namespace 配置Pod配额

This page shows how to set a quota for the total number of Pods that can run in a namespace. You specify quotas in a ResourceQuota object. 本任务展示了如何为某一名字空间(namespace)设置Pod配额以限制可以在名字空间中运行的Pod数量。 配额通过ResourceQuota对象设置。

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.

创建名字空间

创建一个单独的名字空间,以便于隔离您在本练习中创建的资源与集群的其他资源。

kubectl create namespace quota-pod-example

创建ResourceQuota对象

以下展示了ResourceQuota对象的配置文件内容:

quota-pod.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pod-demo
spec:
  hard:
    pods: "2"

下面,首先创建ResourceQuota对象

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-pod.yaml --namespace=quota-pod-example

然后可以通过以下命令查看ResourceQuota对象的详细信息:

kubectl get resourcequota pod-demo --namespace=quota-pod-example --output=yaml

命令输出显示了这个名字空间的Pod配额是2,由于目前没有Pod运行,所有配额并没有被使用。

spec:
  hard:
    pods: "2"
status:
  hard:
    pods: "2"
  used:
    pods: "0"

下面展示的是一个Deployment的配置文件:

quota-pod-deployment.yaml 
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: pod-quota-demo
spec:
  replicas: 3
  template:
    metadata:
      labels:
        purpose: quota-demo
    spec:
      containers:
      - name: pod-quota-demo
        image: nginx

从配置文件可以看到,replicas: 3将令Kubernetes尝试创建3个Pod,所有的Pod实例都将运行同样的应用程序。

接下来尝试创建这个Deployment:

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-pod-deployment.yaml --namespace=quota-pod-example

并通过以下命令查看Deployment的详细信息:

kubectl get deployment pod-quota-demo --namespace=quota-pod-example --output=yaml

从命令输出可以看到尽管在Deployment中我们设置了需要启动3个Pod实例,但由于配额的存在,只有两个Pod被成功创建。

spec:
  ...
  replicas: 3
...
status:
  availableReplicas: 2
...
lastUpdateTime: 2017-07-07T20:57:05Z
    message: 'unable to create pods: pods "pod-quota-demo-1650323038-" is forbidden:
      exceeded quota: pod-demo, requested: pods=1, used: pods=2, limited: pods=2'

练习环境的清理

通过删除名字空间即可完成环境的清理:

kubectl delete namespace quota-pod-example

What’s next

对于集群管理员

对于应用开发者

译者:xingzhou / 原文链接

K8S中文社区微信公众号

Kubernetes 为 Namespace 配置CPU和内存配额

本任务展示了如何为某一名字空间内运行的所有容器配置CPU和内存配额。配额可以通过 ResourceQuota对象设置。

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.

请确保您集群中的每个节点(node)拥有至少1GiB内存。

创建名字空间

创建一个单独的名字空间,以便于隔离您在本练习中创建的资源与集群的其他资源。

kubectl create namespace quota-mem-cpu-example

创建ResourceQuota对象

以下展示了ResourceQuota对象的配置文件内容:

quota-mem-cpu.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-demo
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

下面,首先创建ResourceQuota对象

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-mem-cpu.yaml --namespace=quota-mem-cpu-example

然后可以通过以下命令查看ResourceQuota对象的详细信息:

kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml

以上刚创建的ResourceQuota对象将在quota-mem-cpu-example名字空间中添加以下限制:

  • 每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
  • 所有容器的内存请求总额不得超过1 GiB。
  • 所有容器的内存限额总额不得超过2 GiB。
  • 所有容器的CPU请求总额不得超过1 CPU。
  • 所有容器的CPU限额总额不得超过2 CPU。

创建一个Pod

以下展示了一个Pod的配置文件内容:

quota-mem-cpu-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-demo
spec:
  containers:
  - name: quota-mem-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        memory: "800Mi"
        cpu: "800m" 
      requests:
        memory: "600Mi"
        cpu: "400m"

通过以下命令创建这个Pod:

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-mem-cpu-pod.yaml --namespace=quota-mem-cpu-example

运行以下命令验证这个Pod的容器已经运行:

kubectl get pod quota-mem-cpu-demo --namespace=quota-mem-cpu-example

然后再次查看ResourceQuota对象的详细信息:

kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml

除了配额本身信息外,上述命令还显示了目前配额中有多少已经被使用。可以看到,刚才创建的Pod的内存以及 CPU的请求和限额并没有超出配额。

status:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
  used:
    limits.cpu: 800m
    limits.memory: 800Mi
    requests.cpu: 400m
    requests.memory: 600Mi

尝试创建第二个Pod

第二个Pod的配置文件如下所示:

quota-mem-cpu-pod-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-demo-2
spec:
  containers:
  - name: quota-mem-cpu-demo-2-ctr
    image: redis
    resources:
      limits:
        memory: "1Gi"
        cpu: "800m"      
      requests:
        memory: "700Mi"
        cpu: "400m"

在配置文件中,您可以看到第二个Pod的内存请求是700 MiB。可以注意到,如果创建第二个Pod, 目前的内存使用量加上新的内存请求已经超出了当前名字空间的内存请求配额。即600 MiB + 700 MiB > 1 GiB。

下面尝试创建第二个Pod:

kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example

以下命令输出显示第二个Pod并没有创建成功。错误信息说明了如果创建第二个Pod,内存请求总额将超出名字空间的内存请求配额。

Error from server (Forbidden): error when creating "docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml":
pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo,
requested: requests.memory=700Mi,used: requests.memory=600Mi, limited: requests.memory=1Gi

讨论

在本练习中您已经看到,使用ResourceQuota可以限制一个名字空间中所运行的所有容器的内存请求总额。 当然,也可以通过ResourceQuota限制所有容器的内存限额、CPU请求以及CPU限额。

如果您仅仅想限制单个容器的上述各项指标,而非名字空间中所有容器的,请使用LimitRange

练习环境的清理

通过删除名字空间即可完成环境清理:

kubectl delete namespace quota-mem-cpu-example

What’s next

对于集群管理员

对于应用开发者

译者:xingzhou / 原文链接

K8S中文社区微信公众号