k8s学习笔记

谁借莪1个温暖的怀抱¢ 2023-07-10 08:45 88阅读 0赞

管理集群

安装网络插件

如果要让pod可以相互通信,必须安装网络插件

网络必须在所有应用程序之前部署。并且,在安装网络之前CoreDNS不会启动。kubeadm仅支持基于容器网络接口(CNI)的网络(不支持kubenet)。

一些项目使用CNI提供Kubernetes Pod网络,其中一些还支持网络策略(Network Policy)。

附件页面里有所有可用的网络插件,如果要快速安装可以看这里

例:使用Calico作为网络插件

Calico默认使用 192.168.0.0/16 作为CIDR(Classless Inter-Domain Routing,无类域间路由选择),需要在执行 kubeadm init 命令时配置Calico的CIDR:

  1. kubeadm init --apiserver-advertise-address masterIP --pod-network-cidr 192.168.0.0/16

然后应用网络插件(插件中的CIDR必须与上面配置的一致)

  1. kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml

安装完之后,可以看看下面命令的输出中的CoreDNS Pod是否正在运行来确认其是否正常工作

  1. kubectl get pods --all-namespaces

使用k8s API访问集群

要访问集群,需要知道集群位置并拥有凭证,使用下面的命令检查kubectl已知的位置和凭证

  1. kubectl config view

直接访问REST API

kubectl 处理对 API 服务器的定位和身份验证。如果想通过 http 客户端(如 curlwget,或浏览器)直接访问 REST API,可以通过多种方式对 API 服务器进行定位和身份验证:

  1. 以代理模式运行 kubectl(推荐)。 使用存储的 apiserver 位置并使用自签名证书验证 API 服务器的标识。可以防止中间人(MITM)攻击。
  2. 另外,也可以直接为 http 客户端提供位置和身份认证。这适用于被代理混淆的客户端代码。为防止中间人攻击,您需要将根证书导入浏览器。

使用kubectl代理

运行kubectl的反向代理来处理API请求

  1. kubectl proxy --port=8080 &

然后就可以通过 curl,wget,或浏览器访问 API:

  1. curl http://localhost:8080/api/

输出类似如下:

  1. {
  2. "versions": [
  3. "v1"
  4. ],
  5. "serverAddressByClientCIDRs": [
  6. {
  7. "clientCIDR": "0.0.0.0/0",
  8. "serverAddress": "10.0.1.149:443"
  9. }
  10. ]
  11. }

不使用 kubectl 代理

将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理:

使用 grep/cut 方式:

  1. # 检查所有可用的集群,因为 .KUBECONFIG 可能有多个上下文:
  2. kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'
  3. # 从上面的输出中选择你要进行交互的集群名:
  4. export CLUSTER_NAME="some_server_name"
  5. # 选择指定集群的API服务器
  6. APISERVER=$(kubectl config view -o jsonpath="{ .clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}") # 获取令牌的值 TOKEN=$(kubectl get secrets -o jsonpath="{ .items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 -d)
  7. # 持令牌访问API
  8. curl -X GET $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

输出类似如下:

  1. {
  2. "kind": "APIVersions",
  3. "versions": [
  4. "v1"
  5. ],
  6. "serverAddressByClientCIDRs": [
  7. {
  8. "clientCIDR": "0.0.0.0/0",
  9. "serverAddress": "10.0.1.149:443"
  10. }
  11. ]
  12. }

使用 jsonpath 方式:

  1. $ APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
  2. $ TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
  3. $ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
  4. {
  5. "kind": "APIVersions",
  6. "versions": [
  7. "v1"
  8. ],
  9. "serverAddressByClientCIDRs": [
  10. {
  11. "clientCIDR": "0.0.0.0/0",
  12. "serverAddress": "10.0.1.149:443"
  13. }
  14. ]
  15. }

使用 --insecure 标志位会导致易受到 MITM 攻击。当 kubectl 访问集群时,会使用存储的根证书和客户端证书访问服务器(已安装在 ~/.kube 目录下)。由于集群认证通常是自签名的,因此可能需要特殊设置才能使 http 客户端使用根证书。

在一些集群中,API 服务器不需要身份认证;它运行在本地,或由防火墙保护着。配置对 API 的访问 里会说集群管理员如何对此进行配置。这种方法可能与未来的高可用性支持发生冲突。

编程方式访问 API

Kubernetes 官方支持 Go 和 Python 的客户端库.

例:python客户端

安装:pip install kubernetes (详见 Python 客户端库主页 )。

Python 客户端可以使用与 kubectl 命令行工具相同的 kubeconfig 文件 进行验证:

  1. from kubernetes import client, config
  2. config.load_kube_config()
  3. v1=client.CoreV1Api()
  4. print("Listing pods with their IPs:")
  5. ret = v1.list_pod_for_all_namespaces(watch=False)
  6. for i in ret.items:
  7. print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))
其他语言

详见 客户端库 。

从 Pod 中访问 API

最简单的方法就是使用一个官方的 客户端库。这些库可以自动发现 API 服务器并进行身份验证。

客户端在运行在 Pod 中时,可以通过 default 命名空间中的名为 kubernetes 的服务访问 Kubernetes apiserver。也就是说,Pods 可以使用 kubernetes.default.svc 主机名来查询 API 服务器。官方客户端库自动完成这个工作。

从 Pod 中向 API 服务器进行身份认证的推荐做法是使用 服务账号 凭证。一个 Pod 默认与一个服务账号关联,该服务账号的凭证放置在此 Pod 中每个容器的文件系统树中的 /var/run/secrets/kubernetes.io/serviceaccount/token 处。

如果可用,凭证包被放入每个容器的文件系统树中的 /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 处,并且将被用于验证 API 服务器的服务证书。

最后,用于命名空间 API 操作的默认的命名空间放置在每个容器中的 /var/run/secrets/kubernetes.io/serviceaccount/namespace 文件中。

从一个 Pod 内,连接 Kubernetes API 的推荐方法是:

  • 使用官方的 客户端库 因为他们会自动地完成 API 主机发现和身份认证。以 Go 客户端来说,rest.InClusterConfig() 可以帮助解决这个问题。参见 这里的一个例子。
  • 如果您想要在没有官方客户端库的情况下查询 API,可以在 Pod 里以一个新容器的 命令的方式运行 kubectl proxy 。此方式下,kubectl proxy 将对 API 进行身份验证并将其公开在 Pod 的 localhost 接口上,以便 Pod 中的其他容器可以直接使用它。

所有情况下,Pod 的服务账号凭证都可以用于与 API 服务器的安全通信。

访问集群中运行的服务

从集群外连接nodes、pods、services

nodes、pods 和 services 都有它们自己的 IP。一般情况下,集群上的 node IP、pod IP 和某些 service IP 路由不可达,所以不能从集群外的节点访问它们(比如自己电脑)。开发者一般不需要通过节点 IP 直接访问 nodes。

从集群外连接nodes、pods、services有以下方式:

  • 通过公共 IP 访问 services。

    • 具有 NodePortLoadBalancer 类型的 service 可以从外部访问。参考 services 和 kubectl expose 文档。
    • 取决于你的集群环境,可以仅把 service 暴露在你的企业网络中,也可以将其暴露在公共网络上。需要考虑暴露的 service 是否安全,它是否有自己的用户认证?
    • 将 pods 放在 services 中。可以给一些 pod 指定特殊的标签并创建一个新 service 选择这个标签。
  • 通过 Proxy Verb 访问 services、nodes 或者 pods。

    • 应用场景:服务暴露在公有网络中不安全时,或需要获取 node IP 之上的端口,或者处于调试目的。
    • Proxies 可能给某些应用带来麻烦。
    • 仅适用于 HTTP/HTTPS。
    • 详见这里
  • 从集群中的 node 或者 pod 访问。

    • 运行一个 pod,然后使用 kubectl exec 连接到它的shell。从 shell 连接其他的 nodes、pods 和 services。
    • 某些集群可能允许你 ssh 到集群中的节点。你或许可以从那里访问集群服务。非标准方式,是否工作取决于环境。

访问内置服务

一般 kube-system 会启动集群中的几个服务。

取得 service 的代理 URL:

  1. kubectl cluster-info

会显示访问每个服务的 proxy-verb URL。提供凭据即可访问。

手动构建 apiserver 代理 URLs

要创建包含 service endpoints、suffixes 和 parameters 的代理 URLs,可以在 service 的代理 URL中 添加: http://kubernetes_master_address/api/v1/namespaces/namespace_name/services/service_name[:port_name]/proxy

如果没有为端口指定名称,可以不用在 URL 中指定 port_name

示例
  • 通过 http://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy访问 Elasticsearch service endpoint _search?q=user:kimchy
  • 通过 https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true访问 Elasticsearch 集群健康信息 endpoint _cluster/health?pretty=true

    {

    1. "cluster_name" : "kubernetes_logging",
    2. "status" : "yellow",
    3. "timed_out" : false,
    4. "number_of_nodes" : 1,
    5. "number_of_data_nodes" : 1,
    6. "active_primary_shards" : 5,
    7. "active_shards" : 5,
    8. "relocating_shards" : 0,
    9. "initializing_shards" : 0,
    10. "unassigned_shards" : 5

    }

通过 web 浏览器访问集群中运行的服务

可以用浏览器访问 apiserver 代理的 url ,不过:

  • Web 服务器并非总是能够传递令牌,所以你可能需要使用密码认证。 Apiserver 可以配置为接受密码认证,但集群可能会没有这样配置。
  • 某些 web 应用可能不能工作,特别是那些使用客户端侧 javascript 的应用,它们构造 url 的方式可能不能解析代理路径前缀。

在集群中自动缩放DNS服务

需要开启DNS功能,且节点使用的是AMD64或Intel 64 CPU架构

查看是否启用DNS水平自动缩放:

  1. kubectl get deployment --namespace=kube-system

如果启用了,输出中会看到“dns-autoscaler”:

  1. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
  2. ...
  3. dns-autoscaler 1 1 1 1 ...
  4. ...

如果没有就进行开启。

先确定缩放目标,如果用DNS部署,那么缩放目标就是:

  1. Deployment/DNS部署的名称

比如DNS部署名是coredns,那么缩放目标就是Deployment/coredns。

如果用DNS 副本控制器,那么你的缩放目标是:

  1. ReplicationController/DNS副本控制器的名称

创建一个运行 cluster-proportional-autoscaler-amd64 镜像的部署:

dns-horizontal-autoscaler.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: dns-autoscaler
  5. namespace: kube-system
  6. labels:
  7. k8s-app: dns-autoscaler
  8. spec:
  9. selector:
  10. matchLabels:
  11. k8s-app: dns-autoscaler
  12. template:
  13. metadata:
  14. labels:
  15. k8s-app: dns-autoscaler
  16. spec:
  17. containers:
  18. - name: autoscaler
  19. image: k8s.gcr.io/cluster-proportional-autoscaler-amd64:1.6.0
  20. resources:
  21. requests:
  22. cpu: 20m
  23. memory: 10Mi
  24. command:
  25. - /cluster-proportional-autoscaler
  26. - --namespace=kube-system
  27. - --configmap=dns-autoscaler
  28. - --target=<SCALE_TARGET>
  29. # 当集群使用大节点(核数较多)时应该以"coresPerReplica"为主导
  30. # 使用小节点应该以 "nodesPerReplica" 为主导
  31. - --default-params={ "linear":{ "coresPerReplica":256,"nodesPerReplica":16,"min":1}}
  32. - --logtostderr=true
  33. - --v=2

<SCALE_TARGET> 替换为缩放目标。

然后创建部署:

  1. kubectl apply -f dns-horizontal-autoscaler.yaml

DNS水平缩放就启用了。

优化自动缩放参数

验证是否存在 dns-autoscaler ConfigMap :

  1. kubectl get configmap --namespace=kube-system
  2. NAME DATA AGE
  3. ...
  4. dns-autoscaler 1 ...
  5. ...

编辑ConfigMap:

  1. kubectl edit configmap dns-autoscaler --namespace=kube-system

这一行:

  1. linear: '{"coresPerReplica":256,"min":1,"nodesPerReplica":16}'

“min”字段表示DNS后端数量的最小值。后端数量的实际值计算公式如下:

  1. replicas = max( ceil( cores * 1/coresPerReplica ) , ceil( nodes * 1/nodesPerReplica ) )

注意 coresPerReplicanodesPerReplica 的值都是整数。

其思想是,当集群使用具有多个核的节点时,coresPerReplica 占主导地位。当一个集群使用的节点的核比较少时,nodesPerReplica 占主导地位。 (应该是说单个节点好几个核时就一个部署占节点的几个核,核少就一个部署多用几个节点)

其他缩放模式见集群比例自动伸缩器。

禁用DNS水平自动缩放

有几个选项可以优化DNS水平自动缩放。使用哪个选项取决于不同的条件。

选项1:将dns-autoscaler部署缩减到0个副本

这个选项适用于所有情况。输入这个命令:

  1. kubectl scale deployment --replicas=0 dns-autoscaler --namespace=kube-system

输出:

  1. deployment.extensions/dns-autoscaler scaled

验证副本数是否为0:

  1. kubectl get deployment --namespace=kube-system

输出显示列DESIRED 和CURRENT 为0:

  1. NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
  2. ...
  3. dns-autoscaler 0 0 0 0 ...
  4. ...
选项2:删除dns-autoscaler部署

dns-autoscaler处于你的控制下时有效。这意味着没有人会重新创建它:

  1. kubectl delete deployment dns-autoscaler --namespace=kube-system

输出:

  1. deployment.extensions "dns-autoscaler" deleted
选项3:从master节点删除dns-autoscaler清单文件

dns-autoscaler处于(已废弃) 插件管理器(Addon Manager) 的控制下并且你有对master的写入权限时有效。

登录到主节点并删除对应的清单(manifest)文件。这个dns-autoscaler的常见路径是:

  1. /etc/kubernetes/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml

清单文件删除之后,插件管理器会删除dns-autoscaler 部署。

理解DNS水平自动扩展如何工作

  • 集群比例自动缩放(cluster-proportional-autoscaler)应用程序与DNS服务分开部署。
  • 自动缩放器Pod运行一个客户端,该客户端轮询Kubernetes API服务器,以确定集群中的节点和核心的数量。
  • 根据当前可调度节点和核心以及给定的缩放参数,计算所需的副本数并将其应用于DNS后端。
  • 缩放参数和数据点通过ConfigMap提供给autoscaler,它会在每个轮询间隔刷新它的参数表,以获得最新的缩放参数需求。
  • 不需要重新构建或重新启动自动缩放器Pod就可以更改缩放参数。
  • 自动调度器提供了一个控制接口来支持两种控制模式:线性梯形

未来开发

正在考虑未来开发除了线性和梯形之外的自定义度量的控制模式。

基于DNS指定的缩放度量的DNS后端缩放是未来的发展方向。当前使用集群中的节点和内核的数量来实现是有限制的。

正在考虑未来支持自定义度量,类似于水平Pod自动缩放(Horizontal Pod Autoscaling) 提供的指标)。

配置Pod和容器

配置pod

为pod指定内存请求与限制

LimitRange 为命名空间设定的约束只有在 Pod 创建和更新时才会对要创建/更新的Pod强制执行。所以更新 LimitRange时不会影响之前创建的 Pod。

LimitRange也可以对单个Pod进行约束。

定义一个范围约束

  1. apiVersion: v1
  2. kind: LimitRange
  3. metadata:
  4. name: mem-limit-range
  5. spec:
  6. limits:
  7. - default:
  8. memory: 512Mi
  9. defaultRequest:
  10. memory: 256Mi
  11. type: Container

将约束应用到命名空间default-mem-example

  1. kubectl create -f https://k8s.io/examples/admin/resource/memory-defaults.yaml --namespace=default-mem-example

如果在这个命名空间中创建容器且容器没有声明内存请求和限制,就会使用约束中定义的请求256Mi和限制512Mi,指定了则使用指定的。

  • 如果指定了内存限制没有指定内存请求,则内存请求被设置为内存限制相同的值
  • 如果指定了请求没有指定限制,默认使用命名空间的内存限制

定义pod:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: default-mem-demo
  5. spec:
  6. containers:
  7. - name: default-mem-demo-ctr
  8. image: nginx
  9. # resources:
  10. # requests:
  11. # memory: "128Mi"
  12. # limits:
  13. # memory: "512Mi"

创建 Pod

  1. kubectl create -f https://k8s.io/examples/admin/resource/memory-defaults-pod.yaml --namespace=default-mem-example

查看 Pod 的详情:

  1. kubectl get pod default-mem-demo --output=yaml --namespace=default-mem-example
  2. containers:
  3. - image: nginx
  4. imagePullPolicy: Always
  5. name: default-mem-demo-ctr
  6. resources:
  7. limits:
  8. memory: 512Mi
  9. requests:
  10. memory: 256Mi

删除 Pod:

  1. kubectl delete pod default-mem-demo --namespace=default-mem-example

为命名空间指定容器运行的内存范围

即容器最小要多少请求,最大不超过多少限制,才能在命名空间里运行

定义约束

  1. apiVersion: v1
  2. kind: LimitRange
  3. metadata:
  4. name: 约束名
  5. spec:
  6. limits:
  7. - max:
  8. memory: 1Gi
  9. min:
  10. memory: 500Mi
  11. type: Container

创建 LimitRange:

  1. kubectl create -f https://k8s.io/examples/admin/resource/memory-constraints.yaml --namespace=要应用的命名空间

查看 LimitRange 的详情:

  1. kubectl get limitrange 约束名 --namespace=命名空间 --output=yaml

如果没有 LimitRange 的配置文件中为pod指定默认内存大小,则会将最大内存限制设置为默认大小,pod没有指定内存时就会读取这个默认大小。

  1. limits:
  2. - default:
  3. memory: 1Gi
  4. defaultRequest:
  5. memory: 1Gi
  6. max:
  7. memory: 1Gi
  8. min:
  9. memory: 500Mi
  10. type: Container

现在,在命名空间中创建容器,Kubernetes 会执行下面的步骤:

  • 如果 Container 未指定自己的内存请求和限制,将为它指定默认的内存请求和限制。
  • 验证 Container 的内存请求是否大于或等于最小限制。
  • 验证 Container 的内存限制是否小于或等于最大限制。

创建一个满足 LimitRange 的约束的pod:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: pod
  5. spec:
  6. containers:
  7. - name: 容器名
  8. image: nginx
  9. resources:
  10. limits:
  11. memory: "800Mi"
  12. requests:
  13. memory: "600Mi"

创建 Pod:

  1. kubectl create -f https://k8s.io/examples/admin/resource/memory-constraints-pod.yaml --namespace=命名空间

确认下 Pod 中的容器在运行:

  1. kubectl get pod Pod --namespace=命名空间

查看 Pod 详情:

  1. kubectl get pod Pod --output=yaml --namespace=命名空间
  2. resources:
  3. limits:
  4. memory: 800Mi
  5. requests:
  6. memory: 600Mi

如果不满足约束:

  1. #太大了
  2. Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml":
  3. pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi.
  4. #太小了
  5. Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-3.yaml":
  6. pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi.

如果没有指定内存请求和限制,则会从LimitRange约束那里获取默认的内存请求和限制。

  1. limits:
  2. - default:
  3. memory: 1Gi
  4. defaultRequest:
  5. memory: 1Gi

CPU限制

定义约束

  1. apiVersion: v1
  2. kind: LimitRange
  3. metadata:
  4. name: cpu-limit-range
  5. spec:
  6. limits:
  7. - default:
  8. cpu: 1
  9. defaultRequest:
  10. cpu: 0.5
  11. type: Container

将约束应用到命名空间 default-cpu-example(需先创建命名空间):

  1. kubectl create -f https://k8s.io/examples/admin/resource/cpu-defaults.yaml --namespace=default-cpu-example

创建pod:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: default-cpu-demo-3
  5. spec:
  6. containers:
  7. - name: default-cpu-demo-3-ctr
  8. image: nginx
  9. # resources:
  10. # requests:
  11. # cpu: "0.75"
  12. # limits:
  13. # cpu: "1"

只指定请求和只指定限制时的规则与内存相同。

最大和最小可在命名空间运行的CPU值的定义、不指定默认cpu大小时自动生成、不满足约束时创建失败、LimitRange更新不影响之前Pod等特性与内存相同。

GPU和大页限制

也可以使用LimitRange对象对GPU和大页进行限制,当这些资源同时声明了 ‘default’ 和 ‘defaultRequest’ 参数时,两个参数的值必须相同。

命名空间配置

为命名空间设置内存总量、CPU总量、Pod配额

即命名空间中左右容器的内存请求/限制、CPU请求/限制等的总和不能超过多少。使用ResourceQuota对象进行配置。

创建ResourceQuota(资源配额)对象:

  1. apiVersion: v1
  2. kind: ResourceQuota
  3. metadata:
  4. name: mem-cpu-demo
  5. spec:
  6. hard:
  7. requests.cpu: "1"
  8. requests.memory: 1Gi
  9. limits.cpu: "2"
  10. limits.memory: 2Gi
  11. pods: "2"

该配置文件设置了以下要求:

  • 每个容器必须有内存请求和限制,以及 CPU 请求和限制。
  • 所有容器的内存请求总和不能超过1 GiB。
  • 所有容器的内存限制总和不能超过2 GiB。
  • 所有容器的 CPU 请求总和不能超过1 cpu。
  • 所有容器的 CPU 限制总和不能超过2 cpu。
  • pod数量不能超过2个。

创建 ResourceQuota

  1. kubectl create -f https://k8s.io/examples/admin/resource/quota-mem-cpu.yaml --namespace=quota-mem-cpu-example

查看 ResourceQuota 详情:

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

输出显示配额总量及使用量。

  1. status:
  2. hard:
  3. limits.cpu: "2"
  4. limits.memory: 2Gi
  5. requests.cpu: "1"
  6. requests.memory: 1Gi
  7. pods: "2"
  8. used:
  9. limits.cpu: 800m
  10. limits.memory: 800Mi
  11. requests.cpu: 400m
  12. requests.memory: 600Mi
  13. pods: "1"

如果创建pod会导致超出配额会创建失败:

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

如果一次创建多个pod导致超出配额,则会创建配额数量的pod,超出的会创建失败。

例:使用部署一次创建3个pod

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: pod-quota-demo
  5. spec:
  6. selector:
  7. matchLabels:
  8. purpose: quota-demo
  9. replicas: 3
  10. template:
  11. metadata:
  12. labels:
  13. purpose: quota-demo
  14. spec:
  15. containers:
  16. - name: pod-quota-demo
  17. image: nginx

配置文件中,replicas: 3 使 Kubernetes 尝试创建3个 Pod,都运行相同的应用。

创建 Deployment:

  1. kubectl create -f https://k8s.io/examples/admin/resource/quota-pod-deployment.yaml --namespace=quota-pod-example

查看 Deployment 详情:

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

输出结果显示尽管 Deployment 声明了三个副本,但由于配额的限制只创建了两个 Pod。

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

定义和分配扩展资源

定义扩展资源

扩展资源是什么?它跟CPU和内存等资源相似,比如扩展一些磁盘资源,创建容器时可以请求内存和CPU,也可以请求扩展的磁盘资源。

  1. kubectl get nodes

选择其中一个节点,在这个节点上附加扩展资源。扩展资源的附加数量只能是整数。

给API server发送 HTTP PATCH 请求来向节点附加4个叫做dongle的资源:

  1. curl --header "Content-Type: application/json-patch+json" \
  2. --request PATCH \
  3. --data '[{"op": "add", "path": "/status/capacity/example.com~1dongle", "value": "4"}]' \
  4. http://localhost:8001/api/v1/nodes/<your-node-name>/status

Note: patch路径中的 ~1 代表 /

k8s并不知道dongle是什么有什么用, PATCH请求只是告诉节点有4个叫dongle的东西。

查看节点信息可以看到资源:

  1. kubectl describe node <your-node-name>
  2. Capacity:
  3. cpu: 2
  4. memory: 2049008Ki
  5. example.com/dongle: 4
例:

假如一个节点有800G的特殊磁盘空间,就可以将这个特殊空间命名为 example.com/special-storage,然后就可以以一定大小的块来附加了,比如100G。这样,你的节点就会附加8个 example.com/special-storage 类型的资源。

  1. Capacity:
  2. ...
  3. example.com/special-storage: 8

如果不想总是请求100G而是允许请求任意大小,可以使用大小为1byte的块来附加特殊存储。这样就会附加800G的类型为 example.com/special-storage 的资源。

  1. Capacity:
  2. ...
  3. example.com/special-storage: 800Gi

然后容器就可以申请任意字节的特殊存储了,最高800G。

请求扩展资源

现在创建节点时就可以向节点请求一定数量的dongle了。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: extended-resource-demo
  5. spec:
  6. containers:
  7. - name: extended-resource-demo-ctr
  8. image: nginx
  9. resources:
  10. requests:
  11. example.com/dongle: 3
  12. limits:
  13. example.com/dongle: 3

扩展资源不够用时创建的pod不会被调度,处于挂起状态。

删除扩展资源

发送HTTP PATCH请求。把 <your-node-name> 换成你的节点名:

  1. curl --header "Content-Type: application/json-patch+json" \
  2. --request PATCH \
  3. --data '[{"op": "remove", "path": "/status/capacity/example.com~1dongle"}]' \
  4. http://localhost:8001/api/v1/nodes/<your-node-name>/status

验证dongle是否被移除:

  1. kubectl describe node <your-node-name> | grep dongle

发表评论

表情:
评论列表 (有 0 条评论,88人围观)

还没有评论,来说两句吧...

相关阅读

    相关 k8s学习笔记:缩扩容&更新

    1. 前言 自动缩扩容是现代化的容器调度平台带给我们的最激动人心的一项能力。在上规模的业务系统中我们无时无刻不面临着这样的难题:用户的流量往往随着时间波动,甚至偶尔出现不