可伸缩性和性能
扩展 OpenShift Container Platform 4.2 集群并调整产品环境的性能
摘要
第 1 章 推荐的主机实践
本节为 OpenShift Container Platform 提供推荐的主机实践。
1.1. 推荐的节点主机实践
OpenShift Container Platform 节点配置文件包含重要的选项。例如,控制可以为节点调度的最大 pod 数量的两个参数: podsPerCore
和 maxPods
。
当两个参数都被设置时,其中较小的值限制了节点上的 pod 数量。超过这些值可导致:
- CPU 使用率增加。
- 减慢 pod 调度的速度。
- 根据节点中的内存数量,可能出现内存耗尽的问题。
- 耗尽 IP 地址池。
- 资源过量使用,导致用户应用程序性能变差。
在 Kubernetes 中,包含单个容器的 pod 实际使用两个容器。第二个容器用来在实际容器启动前设置联网。因此,运行 10 个 pod 的系统实际上会运行 20 个容器。
podsPerCore
根据节点中的处理器内核数来设置节点可运行的 pod 数量。例如:在一个有 4 个处理器内核的节点上将 podsPerCore
设为 10
,则该节点上允许的最大 pod 数量为 40
。
kubeletConfig: podsPerCore: 10
将 podsPerCore
设置为 0
可禁用这个限制。默认为 0
。podsPerCore
的值不能超过 maxPods
的值。
maxPods
把节点可以运行的 pod 数量设置为一个固定值,而不需要考虑节点的属性。
kubeletConfig: maxPods: 250
1.2. 创建一个 KubeletConfig CRD 来编辑 kubelet 参数
kubelet 配置目前被序列化为 ignition 配置,因此可以直接编辑。但是,在 Machine Config Controller (MCC) 中同时添加了新的 kubelet-config-controller 。这可让您创建 KubeletConfig 自定义资源 (CR) 来编辑 kubelet 参数。
流程
运行:
$ oc get machineconfig
这个命令显示了可选择的可用机器配置对象列表。默认情况下,与 kubelet 相关的配置为
01-master-kubelet
和01-worker-kubelet
。要检查每个节点中最大 Pod 数量的当前设置,请运行:
# oc describe node <node-ip> | grep Allocatable -A6
找到
value: pods: <value>
.例如:
# oc describe node ip-172-31-128-158.us-east-2.compute.internal | grep Allocatable -A6 Allocatable: attachable-volumes-aws-ebs: 25 cpu: 3500m hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 15341844Ki pods: 250
要设置 worker 节点上的每个节点的最大 Pod,请创建一个包含 kubelet 配置的自定义资源文件。例如:
change-maxPods-cr.yaml
:apiVersion: machineconfiguration.openshift.io/v1 kind: KubeletConfig metadata: name: set-max-pods spec: machineConfigPoolSelector: matchLabels: custom-kubelet: large-pods kubeletConfig: maxPods: 500
kubelet 与 API 服务器进行交互的频率取决于每秒的查询数量 (QPS) 和 burst 值。如果每个节点上运行的 pod 有限,使用默认值(
kubeAPIQPS
为5
,kubeAPIBurst
为10
)就可以。如果节点上有足够 CPU 和内存资源,则建议更新 kubelet QPS 和 burst 率:apiVersion: machineconfiguration.openshift.io/v1 kind: KubeletConfig metadata: name: set-max-pods spec: machineConfigPoolSelector: matchLabels: custom-kubelet: large-pods kubeletConfig: maxPods: <pod_count> kubeAPIBurst: <burst_rate> kubeAPIQPS: <QPS>
运行:
$ oc label machineconfigpool worker custom-kubelet=large-pods
运行:
$ oc create -f change-maxPods-cr.yaml
运行:
$ oc get kubeletconfig
这个命令会返回
set-max-pods
。根据集群中的 worker 节点数量,等待每个 worker 节点被逐个重启。对于有 3 个 worker 节点的集群,这个过程可能需要大约 10 到 15 分钟。
查看 worker 节点的
maxPods
的变化 :$ oc describe node
运行以下命令验证更改:
$ oc get kubeletconfigs set-max-pods -o yaml
这个命令会显示
True
状态和type:Success
流程
默认情况下,在对可用的 worker 节点应用 kubelet 相关的配置时,只允许一台机器不可用。对于大型集群来说,它可能需要很长时间才可以反映出配置的更改。在任何时候,您可以调整更新的机器数量来加快进程速度。
运行:
$ oc edit machineconfigpool worker
将
maxUnavailable
设为所需值。spec: maxUnavailable: <node_count>
重要当设置该值时,请考虑无法使用的 worker 节点数量,而不影响在集群中运行的应用程序。
1.3. 主节点大小
主(master)节点对资源的要求取决于集群中的节点数量。以下推荐的主节点大小是基于 control plane 密度测试的结果。
worker 节点数量 | CPU 内核 | 内存 (GB) |
---|---|---|
25 | 4 | 16 |
100 | 8 | 32 |
250 | 16 | 64 |
因为无法修改正在运行的 OpenShift Container Platform 4.2 集群中的主节点大小,所以您必须估计节点总数并在安装过程中使用推荐的主节点大小。
在 OpenShift Container Platform 4.2 中,与 OpenShift Container Platform 3.11 及之前的版本相比,系统现在默认保留 CPU 内核的一半(500 millicore)。确定大小时应该考虑这一点。
1.4. 推荐的 etcd 实践
对于大型高密度的集群,如果键空间增长过大,超过空间配额,则 etcd 的性能可能会受到极大影响。因此,需要定期维护 etcd ,包括整理碎片以便在数据存储中释放空间。强烈建议您密切监控 Prometheus 中的 etcd 指标数据,并提早进行碎片整理。否则,etcd 可能会引发一个集群范围的警告,使集群进入维护模式(只能对键进行读和删除)。需要密切关注的指标数据是 etcd_server_quota_backend_bytes
, 即当前的配额限制;etcd_mvcc_db_total_size_in_use_in_in_bytes
,它显示了对历史数据进行压缩后的实际数据库用量;etcd_debugging_mvcc_db_total_size_in_bytes
,它显示了数据库大小,包括等待进行碎片处理的空闲空间。
1.5. 其他资源
第 2 章 使用 Node Tuning Operator
了解 Node Tuning Operator,以及如何使用它通过编排 tuned 守护进程以管理节点级别的性能优化。
2.1. 关于 Node Tuning Operator
Node Tuning Operator 可以帮助您通过编排 tuned 守护进程来管理节点级别的性能优化。大多数高性能应用程序都需要一定程度的内核级性能优化。Node Tuning Operator 为用户提供了一个统一的、节点一级的 sysctl 管理接口,并可以根据具体用户的需要灵活地添加自定义性能优化设置。Node Tuning Operator 把为 OpenShift Container Platform 容器化的 tuned 守护进程作为一个 Kubernetes DaemonSet 进行管理。它保证了自定义性能优化设置以可被守护进程支持的格式传递到在集群中运行的所有容器化的 tuned 守护进程中。相应的守护进程会在集群的所有节点上运行,每个节点上运行一个。
在发生触发配置集更改的事件时,或通过接收和处理终止信号安全终止容器化 tuned 守护进程时,容器化 tuned 守护进程所应用的节点级设置将被回滚。
在版本 4.1 及更高版本中,OpenShift Container Platform 标准安装中包含了 Node Tuning Operator。
2.2. 访问 Node Tuning Operator 示例规格
使用此流程来访问 Node Tuning Operator 的示例规格。
流程
运行:
$ oc get Tuned/default -o yaml -n openshift-cluster-node-tuning-operator
请注意,默认 CR 应用来为 OpenShift Container Platform 平台提供标准的节点级性能优化,而任何对默认 CR 的自定义更改都会被 Operator 覆盖。若进行自定义性能优化,请创建自己的 tuned CR。新创建的 CR 将与默认的 CR 合并,并基于节点或 pod 标签和配置文件优先级对节点应用自定义调整。
2.3. 在集群中设置默认配置集
以下是在集群中设置的默认配置集。
apiVersion: tuned.openshift.io/v1alpha1 kind: Tuned metadata: name: default namespace: openshift-cluster-node-tuning-operator spec: profile: - name: "openshift" data: | [main] summary=Optimize systems running OpenShift (parent profile) include=${f:virt_check:virtual-guest:throughput-performance} [selinux] avc_cache_threshold=8192 [net] nf_conntrack_hashsize=131072 [sysctl] net.ipv4.ip_forward=1 kernel.pid_max=>131072 net.netfilter.nf_conntrack_max=1048576 net.ipv4.neigh.default.gc_thresh1=8192 net.ipv4.neigh.default.gc_thresh2=32768 net.ipv4.neigh.default.gc_thresh3=65536 net.ipv6.neigh.default.gc_thresh1=8192 net.ipv6.neigh.default.gc_thresh2=32768 net.ipv6.neigh.default.gc_thresh3=65536 [sysfs] /sys/module/nvme_core/parameters/io_timeout=4294967295 /sys/module/nvme_core/parameters/max_retries=10 - name: "openshift-control-plane" data: | [main] summary=Optimize systems running OpenShift control plane include=openshift [sysctl] # ktune sysctl settings, maximizing i/o throughput # # Minimal preemption granularity for CPU-bound tasks: # (default: 1 msec# (1 + ilog(ncpus)), units: nanoseconds) kernel.sched_min_granularity_ns=10000000 # The total time the scheduler will consider a migrated process # "cache hot" and thus less likely to be re-migrated # (system default is 500000, i.e. 0.5 ms) kernel.sched_migration_cost_ns=5000000 # SCHED_OTHER wake-up granularity. # # Preemption granularity when tasks wake up. Lower the value to # improve wake-up latency and throughput for latency critical tasks. kernel.sched_wakeup_granularity_ns=4000000 - name: "openshift-node" data: | [main] summary=Optimize systems running OpenShift nodes include=openshift [sysctl] net.ipv4.tcp_fastopen=3 fs.inotify.max_user_watches=65536 - name: "openshift-control-plane-es" data: | [main] summary=Optimize systems running ES on OpenShift control-plane include=openshift-control-plane [sysctl] vm.max_map_count=262144 - name: "openshift-node-es" data: | [main] summary=Optimize systems running ES on OpenShift nodes include=openshift-node [sysctl] vm.max_map_count=262144 recommend: - profile: "openshift-control-plane-es" priority: 10 match: - label: "tuned.openshift.io/elasticsearch" type: "pod" match: - label: "node-role.kubernetes.io/master" - label: "node-role.kubernetes.io/infra" - profile: "openshift-node-es" priority: 20 match: - label: "tuned.openshift.io/elasticsearch" type: "pod" - profile: "openshift-control-plane" priority: 30 match: - label: "node-role.kubernetes.io/master" - label: "node-role.kubernetes.io/infra" - profile: "openshift-node" priority: 40
自定义性能优化规格的自定义配置集只是一个技术预览功能。红帽产品服务等级协议 (SLA) 不支持技术预览功能,且可能无法完成。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的详情,请参阅 https://access.redhat.com/support/offerings/techpreview/。
2.4. 自定义调整规格
Operator 的自定义资源 (CR) 包含两个主要部分。第一部分是 profile:
,这是 tuned 配置集及其名称的列表。第二部分是 recommend:
,用来定义配置集选择逻辑。
多个自定义调优规格可以共存,作为 Operator 命名空间中的多个 CR。Operator 会检测到是否存在新 CR 或删除了旧 CR。所有现有的自定义性能优化设置都会合并,同时更新容器化 tuned 守护进程的适当对象。
配置集数据
profile:
部分列出了 tuned 配置集及其名称。
profile: - name: tuned_profile_1 data: | # Tuned profile specification [main] summary=Description of tuned_profile_1 profile [sysctl] net.ipv4.ip_forward=1 # ... other sysctl's or other tuned daemon plugins supported by the containerized tuned # ... - name: tuned_profile_n data: | # Tuned profile specification [main] summary=Description of tuned_profile_n profile # tuned_profile_n profile settings
建议的配置集
profile:
选择逻辑通过 CR 的 recommend:
部分来定义:
recommend: - match: # optional; if omitted, profile match is assumed unless a profile with a higher matches first <match> # an optional array priority: <priority> # profile ordering priority, lower numbers mean higher priority (0 is the highest priority) profile: <tuned_profile_name> # e.g. tuned_profile_1 # ... - match: <match> priority: <priority> profile: <tuned_profile_name> # e.g. tuned_profile_n
如果省略 <match>
,则假定配置集匹配(如 true
)。
<match>
是一个递归定义的可选数组,如下所示:
- label: <label_name> # node or pod label name value: <label_value> # optional node or pod label value; if omitted, the presence of <label_name> is enough to match type: <label_type> # optional node or pod type ("node" or "pod"); if omitted, "node" is assumed <match> # an optional <match> array
如果不省略 <match>
,则所有嵌套的 <match>
部分也必须评估为 true
。否则会假定 false
,并且不会应用或建议具有对应 <match>
部分的配置集。因此,嵌套(子级 <match>
部分)会以逻辑 AND 运算来运作。反之,如果匹配 <match>
数组中任何一项,整个 <match>
数组评估为 true
。因此,该数组以逻辑 OR 运算来运作。
示例
- match: - label: tuned.openshift.io/elasticsearch match: - label: node-role.kubernetes.io/master - label: node-role.kubernetes.io/infra type: pod priority: 10 profile: openshift-control-plane-es - match: - label: node-role.kubernetes.io/master - label: node-role.kubernetes.io/infra priority: 20 profile: openshift-control-plane - priority: 30 profile: openshift-node
根据配置集优先级,以上 CR 针对容器化 tuned 守护进程转换为 recommend.conf
文件。优先级最高 (10
) 的配置集是 openshift-control-plane-es
,因此会首先考虑它。在给定节点上运行的容器化 tuned 守护进程会查看同一节点上是否在运行设有 tuned.openshift.io/elasticsearch
标签的 pod。如果没有,则整个 <match>
部分评估为 false
。如果存在具有该标签的 pod,为了让 <match>
部分评估为 true
,节点标签也需要是 node-role.kubernetes.io/master
或 node-role.kubernetes.io/infra
。
如果这些标签对优先级为 10
的配置集而言匹配,则应用 openshift-control-plane-es
配置集,并且不考虑其他配置集。如果节点/pod 标签组合不匹配,则考虑优先级第二高的配置集 (openshift-control-plane
)。如果容器化 tuned pod 在具有标签 node-role.kubernetes.io/master
或 node-role.kubernetes.io/infra
的节点上运行,则应用此配置集。
最后,配置集 openshift-node
的优先级最低 (30
)。它没有 <match>
部分,因此始终匹配。如果给定节点上不匹配任何优先级更高的配置集,它会作为一个适用于所有节点的配置集来设置 openshift-node
配置集。
2.5. 自定义调整示例
以下 CR 对运行带有标签 tuned.openshift.io/ingress-pod-label=ingress-pod-label-value
的一个 ingress pod 的OpenShift Container Platform 节点应用自定义节点级别调整。作为管理员,使用以下命令创建一个自定义的 CR。
示例
oc create -f- <<_EOF_ apiVersion: tuned.openshift.io/v1 kind: Tuned metadata: name: ingress namespace: openshift-cluster-node-tuning-operator spec: profile: - data: | [main] summary=A custom OpenShift ingress profile include=openshift-control-plane [sysctl] net.ipv4.ip_local_port_range="1024 65535" net.ipv4.tcp_tw_reuse=1 name: openshift-ingress recommend: - match: - label: tuned.openshift.io/ingress-pod-label value: "ingress-pod-label-value" type: pod priority: 10 profile: openshift-ingress _EOF_
2.6. 支持的 Tuned 守护进程插件
在使用 Tuned CR 的 profile:
部分中定义的自定义配置集时,以下 Tuned 插件都受到支持,但 [main]
部分除外:
- audio
- cpu
- disk
- eeepc_she
- modules
- mounts
- net
- scheduler
- scsi_host
- selinux
- sysctl
- sysfs
- usb
- video
- vm
其中一些插件提供了不受支持的动态性能优化功能。以下 Tuned 插件目前还不支持:
- bootloader
- script
- systemd
如需更多信息,请参阅 Available Tuned Plug-ins 和 Getting Started with Tuned 。
第 3 章 使用 Cluster Loader
Cluster Loader 是一个将大量对象部署到集群的工具程序,它可创建用户定义的集群对象。构建、配置并运行 Cluster Loader 以测量处于各种集群状态的 OpenShift Container Platform 部署的性能指标。
3.1. 安装 Cluster Loader
Cluster Loader 包括在 origin-tests
容器镜像中。
流程
运行以下命令抓取
origin-tests
容器镜像:$ sudo podman pull quay.io/openshift/origin-tests:4.2
3.2. 运行 Cluster Loader
流程
使用内置的测试配置执行 Cluster Loader,它会部署五个模板构建并等待它们完成:
$ sudo podman run -v ${LOCAL_KUBECONFIG}:/root/.kube/config:z -i \ quay.io/openshift/origin-tests:4.2 /bin/bash -c 'export KUBECONFIG=/root/.kube/config && \ openshift-tests run-test "[Feature:Performance][Serial][Slow] Load cluster should load the \ cluster [Suite:openshift]"'
或者,通过设置
VIPERCONFIG
环境变量来执行带有用户定义的配置的 Cluster Loader:$ sudo podman run -v ${LOCAL_KUBECONFIG}:/root/.kube/config:z \ -v ${LOCAL_CONFIG_FILE_PATH}:/root/configs/:z \ -i quay.io/openshift/origin-tests:4.2 \ /bin/bash -c 'KUBECONFIG=/root/.kube/config VIPERCONFIG=/root/configs/test.yaml \ openshift-tests run-test "[Feature:Performance][Serial][Slow] Load cluster should \ load the cluster [Suite:openshift]"'
在这个示例中,
${LOCAL_KUBECONFIG}
代表kubeconfig
在本地文件系统中的路径。另外,还有一个名为${LOCAL_CONFIG_FILE_PATH}
的目录,它被挂载到包含名为test.yaml
的配置文件的容器中。另外,如果test.yaml
引用了任何外部模板文件或 podspec 文件,则也应该被挂载到容器中。
3.3. 配置 Cluster Loader
该工具创建多个命名空间(项目),其中包含多个模板或 Pod。
3.3.1. Cluster Loader 配置文件示例
Cluster Loader 的配置文件是一个基本的 YAML 文件:
provider: local 1 ClusterLoader: cleanup: true projects: - num: 1 basename: clusterloader-cakephp-mysql tuning: default ifexists: reuse templates: - num: 1 file: cakephp-mysql.json - num: 1 basename: clusterloader-dancer-mysql tuning: default ifexists: reuse templates: - num: 1 file: dancer-mysql.json - num: 1 basename: clusterloader-django-postgresql tuning: default ifexists: reuse templates: - num: 1 file: django-postgresql.json - num: 1 basename: clusterloader-nodejs-mongodb tuning: default ifexists: reuse templates: - num: 1 file: quickstarts/nodejs-mongodb.json - num: 1 basename: clusterloader-rails-postgresql tuning: default templates: - num: 1 file: rails-postgresql.json tuningsets: 2 - name: default pods: stepping: 3 stepsize: 5 pause: 0 s rate_limit: 4 delay: 0 ms
本例假定对任何外部模板文件或 podspec 文件的引用也会挂载到容器中。
如果您在 Microsoft Azure 上运行 Cluster Loader,则必须将 AZURE_AUTH_LOCATION
变量设置为包含 terraform.azure.auto.tfvars.json
输出结果的文件,该文件存在于安装程序目录中。
3.3.2. 配置字段
字段 | 描述 |
---|---|
|
可设置为 |
|
包含一个或多个定义的子对象。在 |
|
每个配置都有的一个定义的子对象. |
| 每个配置都有一个定义的可选子对象。在创建对象的过程中添加同步的可能性。 |
字段 | 描述 |
---|---|
| 整数。定义要创建项目的数量。 |
|
字符串项目基本名称的一个定义。在 |
| 字符串需要应用到在这个命名空间里部署的项目的 tuning 设置。 |
|
包含 |
| 键值对列表。键是 ConfigMap 名称,值是一个指向用来创建 ConfigMap 的文件的路径。 |
| 键值对列表。key 是 secret 名称,值是一个指向用来创建 secret 的文件的路径。 |
| 要部署的 Pod 的一个或者多个定义的子对象。 |
| 要部署模板的一个或者多个定义的子对象。 |
字段 | 描述 |
---|---|
| 整数。要部署的 Pod 或模板数量。 |
| 字符串到可以拉取镜像的软件仓库的 docker 镜像 URL。 |
| 字符串要创建的模板(或 pod)的基本名称的一个定义。 |
| 字符串到要创建的 Podspec 或模板的本地文件路径。 |
|
健值对。在 |
字段 | 描述 |
---|---|
| 字符串tuning 集的名称,该名称将与在一个项目中定义turning 时指定的名称匹配。 |
|
指定应用于 Pod 的 |
|
指定应用于模板的 |
字段 | 描述 |
---|---|
| 子对象。如果要在步骤创建模式中创建对象,需要使用的步骤配置。 |
| 子对象。用来限制对象创建率的频率限制 turning 集。 |
字段 | 描述 |
---|---|
| 整数。在暂停对象创建前要创建的对象数量。 |
|
整数。在创建了由 |
| 整数。如果对象创建失败,在失败前要等待的秒数。 |
| 整数。在创建请求间等待多少毫秒 (ms) |
字段 | 描述 |
---|---|
|
带有 |
|
布尔值等待带有匹配标签的 |
|
布尔值等待带有标签的 |
|
匹配处于 |
|
字符串等待处于 |
3.4. 已知问题
- 当在没有配置的情况下调用 Cluster Loader 会失败。(BZ#1761925)
如果用户模板中没有定义
IDENTIFIER
参数,则模板创建失败,错误信息为:error: unknown parameter name "IDENTIFIER"
。如果部署模板,在模板中添加这个参数以避免出现这个错误:{ "name": "IDENTIFIER", "description": "Number to append to the name of resources", "value": "1" }
如果部署 Pod,则不需要添加该参数。
第 4 章 使用 CPU Manager
CPU Manager 管理 CPU 组并限制特定 CPU 的负载。
CPU Manager 对于有以下属性的负载有用:
- 需要尽可能多的 CPU 时间。
- 对处理器缓存丢失非常敏感。
- 低延迟网络应用程序。
- 需要与其他进程协调,并从共享一个处理器缓存中受益。
4.1. 设置 CPU Manager
流程
可选:标记节点:
# oc label node perf-node.example.com cpumanager=true
编辑启用 CPU Manager 的节点的
MachineConfigPool
。在这个示例中,所有 worker 都启用了 CPU Manager:# oc edit machineconfigpool worker
在 worker
MachineConfigPool
中添加一个标签:metadata: creationTimestamp: 2019-xx-xxx generation: 3 labels: custom-kubelet: cpumanager-enabled
创建
KubeletConfig
,cpumanager-kubeletconfig.yaml
,自定义资源 (CR) 。使用上一步中创建的标签,以新的KubeletConfig
更新正确的节点。请参见MachineConfigPoolSelector
部分:apiVersion: machineconfiguration.openshift.io/v1 kind: KubeletConfig metadata: name: cpumanager-enabled spec: machineConfigPoolSelector: matchLabels: custom-kubelet: cpumanager-enabled kubeletConfig: cpuManagerPolicy: static cpuManagerReconcilePeriod: 5s
创建动态
KubeletConfig
:# oc create -f cpumanager-kubeletconfig.yaml
这会在
KubeletConfig
中添加 CPU Manager 功能。如果需要,Machine Config Operator (MCO) 将重启节点。要启用 CPU Manager,则不需要重启。检查合并的
KubeletConfig
:# oc get machineconfig 99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet -o json | grep ownerReference -A7 "ownerReferences": [ { "apiVersion": "machineconfiguration.openshift.io/v1", "kind": "KubeletConfig", "name": "cpumanager-enabled", "uid": "7ed5616d-6b72-11e9-aae1-021e1ce18878" } ],
检查 worker 是否有更新的
kubelet.conf
:# oc debug node/perf-node.example.com sh-4.4# cat /host/etc/kubernetes/kubelet.conf | grep cpuManager cpuManagerPolicy: static 1 cpuManagerReconcilePeriod: 5s 2
创建请求一个或多个内核的 Pod。限制和请求都必须将其 CPU 值设置为一个整数。这是专用于这个 Pod 的内核数:
# cat cpumanager-pod.yaml apiVersion: v1 kind: Pod metadata: generateName: cpumanager- spec: containers: - name: cpumanager image: gcr.io/google_containers/pause-amd64:3.0 resources: requests: cpu: 1 memory: "1G" limits: cpu: 1 memory: "1G" nodeSelector: cpumanager: "true"
创建 Pod:
# oc create -f cpumanager-pod.yaml
确定为您标记的节点调度了 Pod:
# oc describe pod cpumanager Name: cpumanager-6cqz7 Namespace: default Priority: 0 PriorityClassName: <none> Node: perf-node.example.com/xxx.xx.xx.xxx ... Limits: cpu: 1 memory: 1G Requests: cpu: 1 memory: 1G ... QoS Class: Guaranteed Node-Selectors: cpumanager=true
确认正确配置了
cgroups
。获取pause
进程的进程 ID(PID):# ├─init.scope │ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17 └─kubepods.slice ├─kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice │ ├─crio-b5437308f1a574c542bdf08563b865c0345c8f8c0b0a655612c.scope │ └─32706 /pause
服务质量(QoS)等级为
Guaranteed
的 pod 被放置到kubepods.slice
中。其它 QoS 等级的 pod 会位于kubepods
的子cgroups
中:# cd /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice/crio-b5437308f1ad1a7db0574c542bdf08563b865c0345c86e9585f8c0b0a655612c.scope # for i in `ls cpuset.cpus tasks` ; do echo -n "$i "; cat $i ; done cpuset.cpus 1 tasks 32706
检查任务允许的 CPU 列表:
# grep ^Cpus_allowed_list /proc/32706/status Cpus_allowed_list: 1
确认系统中的另一个 pod(在这个示例中,QoS 等级为
burstable
的 pod)不能在为等级为Guaranteed
的 pod 分配的内核中运行:# cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podc494a073_6b77_11e9_98c0_06bba5c387ea.slice/crio-c56982f57b75a2420947f0afc6cafe7534c5734efc34157525fa9abbf99e3849.scope/cpuset.cpus 0
# oc describe node perf-node.example.com ... Capacity: attachable-volumes-aws-ebs: 39 cpu: 2 ephemeral-storage: 124768236Ki hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 8162900Ki pods: 250 Allocatable: attachable-volumes-aws-ebs: 39 cpu: 1500m ephemeral-storage: 124768236Ki hugepages-1Gi: 0 hugepages-2Mi: 0 memory: 7548500Ki pods: 250 ------- ---- ------------ ---------- --------------- ------------- --- default cpumanager-6cqz7 1 (66%) 1 (66%) 1G (12%) 1G (12%) 29m Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 1440m (96%) 1 (66%)
这个 VM 有两个 CPU 内核。将
kube-reserved
设定为 500 毫秒,这意味着,一个内核的一半被从节点的总容量中减小,以达到Node Allocatable
的数量。您可以看到Allocatable CPU
是 1500 毫秒。这意味着您可以运行一个 CPU Manager pod,因为每个 pod 需要一个完整的内核。一个完整的内核等于 1000 毫秒。如果您尝试调度第二个 pod,系统将接受该 pod,但不会调度它:NAME READY STATUS RESTARTS AGE cpumanager-6cqz7 1/1 Running 0 33m cpumanager-7qc2t 0/1 Pending 0 11s
第 5 章 扩展 Cluster Monitoring Operator
OpenShift Container Platform 会提供 Cluster Monitoring Operator 在基于 Prometheus 的监控堆栈中收集并存储的数据。作为管理员,您可以在一个 dashboard 接口(Grafana)中查看系统资源、容器和组件指标。
5.1. Prometheus 数据库存储要求
红帽对不同的扩展大小进行了各种测试。
节点数量 | Pod 数 | 每天增加的 Prometheus 存储 | 每 15 天增加的 Prometheus 存储 | RAM 空间(每个缩放大小) | 网络(每个 tsdb 块) |
---|---|---|---|---|---|
50 | 1800 | 6.3 GB | 94 GB | 6 GB | 16 MB |
100 | 3600 | 13 GB | 195 GB | 10 GB | 26 MB |
150 | 5400 | 19 GB | 283 GB | 12 GB | 36 MB |
200 | 7200 | 25 GB | 375 GB | 14 GB | 46 MB |
大约 20%的预期大小被添加为开销,以保证存储要求不会超过计算的值。
上面的计算用于默认的 OpenShift Container Platform Cluster Monitoring Operator。
CPU 利用率会有轻微影响。这个比例为在每 50 个节点和 1800 个 pod 的 40 个内核中大约有 1 个。
实验室环境
在以前的版本中,所有实验都是在 OpenStack 环境中的 OpenShift Container Platform 中进行的:
- infra nodes (VM) - 40 个内核,157 GB RAM。
- CNS 节点 (VM) - 16 个内核、62GB RAM 、nvme 驱动。
目前,OpenStack 环境还不支持 OpenShift Container Platform 4.2 。
针对 OpenShift Container Platform 的建议
- 至少使用三个基础架构(infra)节点。
- 至少使用三个带有 NVMe(non-volatile memory express)驱动的 openshift-container-storage 节点。
5.2. 配置集群监控
流程
为 Prometheus 增加存储容量:
创建 YAML 配置文件
cluster-monitoring-config.yml
。例如:apiVersion: v1 kind: ConfigMap data: config.yaml: | prometheusOperator: baseImage: quay.io/coreos/prometheus-operator prometheusConfigReloaderBaseImage: quay.io/coreos/prometheus-config-reloader configReloaderBaseImage: quay.io/coreos/configmap-reload nodeSelector: node-role.kubernetes.io/infra: "" prometheusK8s: retention: {{PROMETHEUS_RETENTION_PERIOD}} 1 baseImage: openshift/prometheus nodeSelector: node-role.kubernetes.io/infra: "" volumeClaimTemplate: spec: storageClassName: gp2 resources: requests: storage: {{PROMETHEUS_STORAGE_SIZE}} 2 alertmanagerMain: baseImage: openshift/prometheus-alertmanager nodeSelector: node-role.kubernetes.io/infra: "" volumeClaimTemplate: spec: storageClassName: gp2 resources: requests: storage: {{ALERTMANAGER_STORAGE_SIZE}} 3 nodeExporter: baseImage: openshift/prometheus-node-exporter kubeRbacProxy: baseImage: quay.io/coreos/kube-rbac-proxy kubeStateMetrics: baseImage: quay.io/coreos/kube-state-metrics nodeSelector: node-role.kubernetes.io/infra: "" grafana: baseImage: grafana/grafana nodeSelector: node-role.kubernetes.io/infra: "" auth: baseImage: openshift/oauth-proxy k8sPrometheusAdapter: nodeSelector: node-role.kubernetes.io/infra: "" metadata: name: cluster-monitoring-config namespace: openshift-monitoring
- 1
- 一个典型的值是
PROMETHEUS_retention_PERIOD=15d
。时间单位使用以下后缀之一 : s 、m 、h 、d。 - 2
- 一个典型的值是
PROMETHEUS_STORAGE_SIZE=2000Gi
。存储值可以是一个纯整数,也可以是带有以下后缀之一的整数: E 、P 、T 、G 、M 、K。您也可以使用以下效果相同的后缀:Ei 、Pi 、Ti 、Gi 、Mi 、Ki。 - 3
- 一个典型的值
是 alertmanager_STORAGE_SIZE=20Gi
。存储值可以是一个纯整数,也可以是带有以下后缀之一的整数: E 、P 、T 、G 、M 、K。您也可以使用以下效果相同的后缀:Ei 、Pi 、Ti 、Gi 、Mi 、Ki。
- 设置值,如保留周期和存储大小。
运行以下命令应用这些更改:
$ oc create -f cluster-monitoring-config.yml
第 6 章 根据对象限制规划您的环境
在规划 OpenShift Container Platform 集群时,请考虑以下对象限制。
这些限制基于最大可能的集群。对于较小的集群,最大值限制会较低。很多因素会影响指定的阈值,包括 etcd 版本或者存储数据格式。
在大多数情况下,超过这些限制会降低整体性能。它不一定意味着集群会出现错误。
6.1. 经过 OpenShift Container Platform 主发行版本测试的集群最大值
为 OpenShift Container Platform 3.x 测试的云平台: Red Hat OpenStack、Amazon Web Services 和 Microsoft Azure。为 OpenShift Container Platform 4.x 测试的云平台: Amazon Web Services、Microsoft Azure 和 Google Cloud Platform。
最大类型 | 3.x 测试的最大值 | 4.x 测试的最大值 |
---|---|---|
节点数量 | 2,000 | 2,000 |
Pod 数量 footnote:numberofpodsmajorrelease[这里显示的数量是测试 Pod 的数量。实际的 Pod 数量取决于应用程序的内存、CPU 和存储要求。] | 150,000 | 150,000 |
每个节点的 pod 数量 | 250 |
500 footnote:podspernodemajorrelease[这是在一个有 100 个 worker 节点,每个 worker 节点有 500 个 Pod 的集群中测试的。默认 |
每个内核的 pod 数量 | 没有默认值。 | 没有默认值。 |
命名空间数量 footnote:numberofnamepacesmajorrelease[当有大量活跃的项目时,如果键空间增长过大并超过空间配额,etcd 的性能将会受到影响。强烈建议您定期维护 etcd 存储,包括通过碎片管理释放 etcd 存储。] | 10,000 | 10,000 |
构建(build)数 | 10,000(默认 pod RAM 512 Mi)- 管道 (Pipeline) 策略 | 10,000(默认 pod RAM 512 Mi)- Source-to-Image (S2I) 构建策略 |
每个命名空间中的 Pod 数量 footnote:objectpernamespacemajorrelease[系统中有多个控制循环,必须迭代给定命名空间中的所有对象作为对一些状态更改的响应。在单一命名空间中有大量给定类型的对象可使这些循环的运行成本变高,并降低对给定状态变化的处理速度。限制假设系统有足够的 CPU 、内存和磁盘来满足应用程序的要求。] | 25,000 | 25,000 |
服务的数量 footnote:servicesandendpointsmajorrelease[每个服务端口和服务后端在 iptables 中都有一个相应的条目。给定服务的后端数量会影响端点对象的大小,这会影响到整个系统发送的数据大小。] | 10,000 | 10,000 |
每个命名空间的服务数 | 5,000 | 5,000 |
每个服务中的后端数 | 5,000 | 5,000 |
每个命名空间的部署数量 footnote:objectpernamespacemajorrelease[] | 2,000 | 2,000 |
6.2. 经过 OpenShift Container Platform 测试的集群最大值
限制类型 | 3.10 测试的最大值 | 3.11 测试的最大值 | 4.1 测试的最大值 | 4.2 测试的最大值 |
---|---|---|---|---|
节点数量 | 2,000 | 2,000 | 2,000 | 2,000 |
Pod 的数量 footnote:numberofpods[这里显示的 Pod 数是测试的 Pod 的数量。实际的 Pod 数量取决于应用程序的内存、CPU 和存储要求。] | 150,000 | 150,000 | 150,000 | 150,000 |
每个节点的 pod 数量 | 250 | 250 | 250 | 250 |
每个内核的 pod 数量 | 没有默认值。 | 没有默认值。 | 没有默认值。 | 没有默认值。 |
命名空间数量 footnote:numberofnamepaces[当有大量活跃的项目时,如果键空间增长过大并超过空间配额,etcd 的性能将会受到影响。强烈建议您定期维护 etcd 存储,包括通过碎片管理释放 etcd 存储。] | 10,000 | 10,000 | 10,000 | 10,000 |
构建(build)数 | 10,000(默认 pod RAM 512 Mi) | 10,000(默认 pod RAM 512 Mi) | 10,000(默认 pod RAM 512 Mi) | 10,000(默认 pod RAM 512 Mi) |
每个命名空间中的 Pod 数量 footnote:objectpernamespace[系统中有多个控制循环,必须迭代给定命名空间中的所有对象作为对一些状态更改的响应。在单一命名空间中有大量给定类型的对象可使这些循环的运行成本变高,并降低对给定状态变化的处理速度。限制假设系统有足够的 CPU 、内存和磁盘来满足应用程序的要求。] | 3,000 | 25,000 | 25,000 | 25,000 |
服务的数量 footnote:servicesandendpoints[每个服务端口和服务后端在 iptables 中都有一个相应的条目。给定服务的后端数量会影响端点对象的大小,这会影响到整个系统发送的数据大小。 | 10,000 | 10,000 | 10,000 | 10,000 |
每个命名空间的服务数 | 5,000 | 5,000 | 5,000 | 5,000 |
每个服务中的后端数 | 5,000 | 5,000 | 5,000 | 5,000 |
每个命名空间中的部署数量 footnote:objectpernamespace[] | 2,000 | 2,000 | 2,000 | 2,000 |
在 OpenShift Container Platform 4.2 中,与 OpenShift Container Platform 3.11 和之前的版本相比,系统保留 CPU 内核的一半(500 millicore)。
6.3. 测试集群最大值的 OpenShift Container Platform 环境和配置
Google Cloud Platform:
节点 | Flavor | vCPU | RAM(GiB) | 磁盘类型 | 磁盘大小(GiB)/IOPS | 数量 | 区域 |
---|---|---|---|---|---|---|---|
Master/etcd | n1-highmem-16 | 16 | 104 | Regional/Zonal SSD | 220 | 3 | us-east4 |
Infra footnote:infranodesgcp[Infra 节点用于托管 Monitoring、Ingress 和 Registry 组件,以确保它们有足够资源可大规模运行。] | n1-standard-64 | 64 | 240 | Regional/Zonal SSD | 100 | 3 | us-east4 |
Workload footnote:workloadnodegcp[工作负载节点专用于运行性能和可扩展工作负载生成器。] | n1-standard-16 | 16 | 60 | Regional/Zonal SSD | 500 footnote:disksizegcp[使用更大的磁盘,以便有足够的空间存储在运行性能和可扩展性测试期间收集的大量数据。] | 1 | us-east4 |
Worker | n1-standard-8 | 8 | 30 | Regional/Zonal SSD | 100 | 3/25/250 footnote:nodescalegcp[在迭代中扩展了集群,且性能和可扩展性测试是在指定节点数中执行的。] | us-east4 |
AWS cloud platform:
节点 | Flavor | vCPU | RAM(GiB) | 磁盘类型 | 磁盘大小(GiB)/IOPS | 数量 | 区域 |
---|---|---|---|---|---|---|---|
Master/Etcd footnote:masteretcdnodeaws[带有 3000 个 IOPS 的 io1 磁盘用于 master/etcd 节点,因为 etcd 非常大,且敏感延迟。] | r5.4xlarge | 16 | 128 | io1 | 220 / 3000 | 3 | us-west-2 |
Infra footnote:infranodesaws[Infra 节点用于托管 Monitoring、Ingress 和 Registry 组件,以确保它们有足够资源可大规模运行。] | m5.12xlarge | 48 | 192 | gp2 | 100 | 3 | us-west-2 |
Workload footnote:workloadnodeaws[工作负载节点专用于运行性能和可扩展工作负载生成器。] | m5.4xlarge | 16 | 64 | gp2 | 500 footnote:disksizeaws[使用更大的磁盘,以便有足够的空间存储在运行性能和可扩展性测试期间收集的大量数据。] | 1 | us-west-2 |
Worker | m5.large | 2 | 8 | gp2 | 100 | 2000 | us-west-2 |
6.4. 如何根据经过测试的集群限制规划您的环境
在节点中过度订阅物理资源会影响在 pod 放置过程中对 Kubernetes 调度程序的资源保证。了解可以采取什么措施避免内存交换。
某些限制只在单一维度中扩展。当很多对象在集群中运行时,它们会有所不同。
本文档中给出的数字基于红帽的测试方法、设置、配置和调整。这些数字会根据您自己的设置和环境而有所不同。
在规划您的环境时,请确定每个节点会运行多少 个 pod :
Required Pods per Cluster / Pods per Node = Total Number of Nodes Needed
每个节点上的 Pod 数量做多为 250。而在某个节点中运行的 pod 的具体数量取决于应用程序本身。请参阅 如何根据应用程序要求规划您的环境 中的内容来计划应用程序的内存、CPU 和存储要求。
示例情境
如果想把集群的规模限制在 2200 个 pod,假设每个节点最多有 250 个 pod,则需要最少 9 个节点:
2200 / 250 = 8.8
如果将节点数量增加到 20,那么 pod 的分布情况将变为每个节点有 110 个 pod:
2200 / 20 = 110
其中:
Required Pods per Cluster / Total Number of Nodes = Expected Pods per Node
6.5. 如何根据应用程序要求规划您的环境
考虑应用程序环境示例:
pod 类型 | pod 数量 | 最大内存 | CPU 内核 | 持久性存储 |
---|---|---|---|---|
Apache | 100 | 500 MB | 0.5 | 1 GB |
node.js | 200 | 1 GB | 1 | 1 GB |
postgresql | 100 | 1 GB | 2 | 10 GB |
JBoss EAP | 100 | 1 GB | 1 | 1 GB |
推断的要求: 550 个 CPU 内核、450GB RAM 和 1.4TB 存储。
根据您的具体情况,节点的实例大小可以被增大或降低。在节点上通常会使用资源过度分配。在这个部署场景中,您可以选择运行多个额外的较小节点,或数量更少的较大节点来提供同样数量的资源。在做出决定前应考虑一些因素,如操作的灵活性以及每个实例的成本。
节点类型 | 数量 | CPU | RAM (GB) |
---|---|---|---|
节点(选择 1) | 100 | 4 | 16 |
节点(选择 2) | 50 | 8 | 32 |
节点(选择 3) | 25 | 16 | 64 |
有些应用程序很适合于过度分配的环境,有些则不适合。大多数 Java 应用程序以及使用巨页的应用程序都不允许使用过度分配功能。它们的内存不能用于其他应用程序。在上面的例子中,环境大约会出现 30% 过度分配的情况,这是一个常见的比例。
第 7 章 优化存储
优化存储有助于最小化所有资源中的存储使用。通过优化存储,管理员可帮助确保现有存储资源以高效的方式工作。
7.1. 可用的持久性存储选项
了解持久性存储选项,以便可以优化 OpenShift Container Platform 环境。
存储类型 | 描述 | 例子 |
---|---|---|
Block |
| AWS EBS 和 VMware vSphere 支持在 OpenShift Container Platform 中的原生动态持久性卷 (PV)置备 。 |
File |
| RHEL NFS、NetApp NFS footnoteref:netappnfs[当使用 Trident 插件时,NetApp NFS 支持动态的 PV 置备。] 和 Vendor NFS |
对象 |
| AWS S3 |
目前,OpenShift Container Platform 4.2 不支持 CNS。
7.2. 推荐的可配置存储技术
下表总结了为给定的 OpenShift Container Platform 集群应用程序推荐的可配置存储技术。
存储类型 | ROX footnote:rox[ReadOnlyMany] | RWX footnote:rwx[ReadWriteMany] | Registry | 扩展的 registry | Metrics footnote:metrics-prometheus[Prometheus 是用于 metrics 的底层技术。] | Logging | Apps |
---|---|---|---|---|---|---|---|
Block | 是 footnote:disk[这不适用于物理磁盘、VM 物理磁盘、VMDK、loopback over NFS, AWS EBS,和 Azure 磁盘。] | 否 | 可配置 | 无法配置 | 推荐的 | 推荐的 | 推荐的 |
File | Yes footnote:disk[] | 是 | 可配置 | 可配置 | 可配置 footnote:metrics-warning[对于 metrics,使用 ReadWriteMany (RWX) 访问模式的文件存储不可靠。如果使用文件存储,请不要在配置用于指标数据的 PersistentVolumeClaims 上配置 RWX 访问模式。] | 可配置 footnote:logging-warning[对于 logging,不要使用任何共享的存储。每个 elasticsearch 都需要一个卷。] | 推荐的 |
对象 | 是 | 是 | 推荐的 | 推荐的 | 无法配置 | 无法配置 | 不可配置 footnote:object[对象存储不会通过 OpenShift Container Platform 的 PV/PVC 被使用。应用程序必须与对象存储 REST API 集成。] |
扩展的 registry 是指一个 OpenShift Container Platform registry,它有三个或更多个 pod 运行副本。
7.2.1. 特定应用程序存储建议
测试显示,在 RHEL 中使用 NFS 服务器作为容器镜像 registry 的存储后端可能会出现问题。这包括 OpenShift Container Registry 和 Quay,Cassandra for metrics 存储,以及 Elasticsearch for logging 存储。因此,不推荐使用 NFS 作为 PV 后端用于核心服务。
市场上的其他 NFS 实现可能没有这些问题。如需了解更多与此问题相关的信息,请联络相关的 NFS 厂商。
7.2.1.1. Registry
在一个非扩展的/高可用性 (HA) OpenShift Container Platform registry 集群部署中:
- 首选存储技术是对象存储,然后是块存储。存储技术不需要支持 RWX 访问模式。
- 存储技术必须保证读写一致性。对于应用于生产环境工作负载的 OpenShift Container Platform Registry 集群部署,我们不推荐使用任何 NAS 存储。
-
虽然
hostPath
卷对于一个非扩展的/HA OpenShift Container Platform Registry 是可配置的,但不推荐用于集群部署。
7.2.1.2. 扩展的 registry
在扩展的/HA OpenShift Container Platform registry 集群部署中:
- 首选存储技术是对象存储。存储技术必须支持 RWX 访问模式,且必须保证读写一致性。
- 对于应用于生产环境负载的扩展的/HA OpenShift Container Platform registry 集群部署,不建议使用文件存储和块存储。
- 对于应用于生产环境工作负载的 OpenShift Container Platform Registry 集群部署,我们不推荐使用任何 NAS 存储。
7.2.1.3. 指标
在 OpenShift Container Platform 托管的 metrics 集群部署中:
- 首选存储技术是块存储。
测试显示,使用文件存储会造成大量无法恢复的数据破坏问题,因此不建议在 metrics 中使用文件存储。
市场中某些文件存储可能没有这些问题。如需了解更多与此问题相关的信息,请联络相关的 存储厂商。
7.2.1.4. Logging
在 OpenShift Container Platform 托管的日志集群部署中:
- 首选存储技术是块存储。
- 在带有生产环境负载的托管 metrics 集群部署中不推荐使用 NAS 存储。
测试显示,在 RHEL 中使用 NFS 服务器作为容器镜像 registry 的存储后端可能会出现问题。这包括用于日志存储的 Elasticsearch。因此,不推荐使用 NFS 作为 PV 后端用于核心服务。
市场上的其他 NFS 实现可能没有这些问题。如需了解更多与此问题相关的信息,请联络相关的 NFS 厂商。
7.2.1.5. 应用程序
应用程序的用例会根据不同应用程序而不同,如下例所示:
- 支持动态 PV 部署的存储技术的挂载时间延迟较低,且不与节点绑定来支持一个健康的集群。
- 应用程序开发人员需要了解应用程序对存储的要求,以及如何与所需的存储一起工作以确保应用程序扩展或者与存储层交互时不会出现问题。
7.2.2. 其他特定的应用程序存储建议
-
OpenShift Container Platform 内部
etcd
:为了获得最好的etcd
可靠性,首选使用具有最低一致性延迟的存储技术。 -
强烈建议您使用带有可快速处理串口写入(fsync)的存储的
etcd
,比如 NVMe 或者 SSD。不建议使用 Ceph、NFS 和 spinning 磁盘。 - OpenStack Cinder: OpenStack Cinder 倾向于在 ROX 访问模式中使用案例。
- 数据库:数据库(RDBMS 、nosql DBs 等等)倾向于使用专用块存储来获得最好的性能。
第 8 章 优化路由
OpenShift Container Platform HAProxy 路由器扩展以优化性能。
8.1. 基础路由器性能
OpenShift Container Platform 路由器是所有用于 OpenShift Container Platform 服务的外部流量的入站点。
当根据每秒处理的 HTTP 请求来评估单个 HAProxy 路由器性能时,其性能取决于多个因素。特别是:
- HTTP keep-alive/close 模式
- 路由类型
- 对 TLS 会话恢复客户端的支持
- 每个目标路由的并行连接数
- 目标路由数
- 后端服务器页面大小
- 底层基础结构(网络/SDN 解决方案、CPU 等)
具体环境中的性能会有所不同,红帽实验室在一个有 4 个 vCPU/16GB RAM,一个单独的 HAProxy 路由器处理 100 个路由来提供后端的 1kB 静态页面的公共云实例中进行测试,其每秒的交易数如下。
在 HTTP 的 keep-alive 模式下:
Encryption | LoadBalancerService | HostNetwork |
---|---|---|
none | 21515 | 29622 |
edge | 16743 | 22913 |
passthrough | 36786 | 53295 |
re-encrypt | 21583 | 25198 |
在 HTTP 关闭(无 keep-alive)情境中:
Encryption | LoadBalancerService | HostNetwork |
---|---|---|
none | 5719 | 8273 |
edge | 2729 | 4069 |
passthrough | 4121 | 5344 |
re-encrypt | 2320 | 2941 |
使用 ROUTER_THREADS=4
默认路由器配置,并测试了两个不同的端点发布策略 (LoadBalancerService/hostnetwork) 。TLS 会话恢复用于加密路由。使用 HTTP keep-alive 设置,单个 HAProxy 路由器可在页面大小小到 8 kB 时充满 1 Gbit NIC。
当在使用现代处理器的裸机中运行时,性能可以期望达到以上公共云实例测试性能的大约两倍。这个开销是由公有云的虚拟化层造成的,基于私有云虚拟化的环境也会有类似的开销。下表是有关在路由器后面的应用程序数量的指导信息:
应用程序数量 | 应用程序类型 |
---|---|
5-10 | 静态文件/web 服务器或者缓存代理 |
100-1000 | 生成动态内容的应用程序 |
取决于所使用的技术,HAProxy 通常可支持 5 到 1000 个程序的路由。路由器性能可能会受其后面的应用程序的能力和性能的限制,如使用的语言,静态内容或动态内容。
如果有多个服务于应用程序的路由,则应该使用路由器分片(router sharding)以帮助横向扩展路由层。
8.2. 路由器性能优化
OpenShift Container Platform 不再支持通过设置以下环境变量来修改路由器的部署: ROUTER_THREADS
、ROUTER_DEFAULT_TUNNEL_TIMEOUT
、ROUTER_DEFAULT_CLIENT_TIMEOUT
、ROUTER_DEFAULT_SERVER_TIMEOUT
和 RELOAD_INTERVAL
。
您可以修改路由器部署,但当 Ingress Operator 被启用时,其配置会被覆盖。
第 9 章 巨页的作用及应用程序如何使用它们
9.1. 巨页的作用
内存在块(称为页)中进行管理。在大多数系统中,页的大小为 4Ki。1Mi 内存相当于 256 个页,1Gi 内存相当于 256,000 个页。CPU 有内置的内存管理单元,可在硬件中管理这些页的列表。Translation Lookaside Buffer (TLB) 是虚拟页到物理页映射的小型硬件缓存。如果在硬件指令中包括的虚拟地址可以在 TLB 中找到,则其映射信息可以被快速获得。如果没有包括在 TLN 中,则称为 TLB miss。系统将会使用基于软件的,速度较慢的地址转换机制,从而出现性能降低的问题。因为 TLB 的大小是固定的,因此降低 TLB miss 的唯一方法是增加页的大小。
巨页指一个大于 4Ki 的内存页。在 x86_64 构架中,有两个常见的巨页大小: 2Mi 和 1Gi。在其它构架上的大小会有所不同。要使用巨页,必须写相应的代码以便应用程序了解它们。Transparent Huge Pages (THP) 试图在应用程序不需要了解的情况下自动管理巨页,但这个技术有一定的限制。特别是,它的页大小会被限为 2Mi。当有较高的内存使用率时,THP 可能会导致节点性能下降,或出现大量内存碎片(因为 THP 的碎片处理)导致内存页被锁定。因此,有些应用程序可能更适用于(或推荐)使用预先分配的巨页,而不是 THP。
在 OpenShift Container Platform 中,pod 中的应用程序可以分配并消耗预先分配的巨页。
9.2. 应用程序如何使用巨页
节点必须预先分配巨页以便节点报告其巨页容量。一个节点只能预先分配一个固定大小的巨页。
巨页可以使用名为 hugepages-<size>
的容器一级的资源需求被消耗。其中 size 是特定节点上支持的整数值的最精简的二进制标记。例如:如果某个节点支持 2048KiB 页大小,它将会有一个可调度的资源 hugepages-2Mi
。与 CPU 或者内存不同,巨页不支持过量分配。
apiVersion: v1
kind: Pod
metadata:
generateName: hugepages-volume-
spec:
containers:
- securityContext:
privileged: true
image: rhel7:latest
command:
- sleep
- inf
name: example
volumeMounts:
- mountPath: /dev/hugepages
name: hugepage
resources:
limits:
hugepages-2Mi: 100Mi 1
memory: "1Gi"
cpu: "1"
volumes:
- name: hugepage
emptyDir:
medium: HugePages
- 1
- 为
巨页
指定要分配的准确内存数量。不要将这个值指定为巨页
内存大小乘以页的大小。例如,巨页的大小为 2MB,如果应用程序需要使用由巨页组成的 100MB 的内存,则需要分配 50 个巨页。OpenShift Container Platform 会进行相应的计算。如上例所示,您可以直接指定100MB
。
分配特定大小的巨页
有些平台支持多个巨页大小。要分配指定大小的巨页,在巨页引导命令参数前使用巨页大小选择参数hugepagesz=<size>
。<size>
的值必须以字节为单位,并可以使用一个可选的后缀 [kKmMgG
]。默认的巨页大小可使用 default_hugepagesz=<size>
引导参数定义。
巨页要求
- 巨页面请求必须等于限制。如果指定了限制,则它是默认的,但请求不是。
- 巨页在 pod 范围内被隔离。容器隔离功能计划在以后的版本中推出。
-
后端为巨页的
EmptyDir
卷不能消耗大于 pod 请求的巨页内存。 -
通过带有
SHM_HUGETLB
的shmget()
来使用巨页的应用程序,需要运行一个匹配 proc/sys/vm/hugetlb_shm_group 的 supplemental 组。
其他资源
9.3. 配置巨页
节点必须预先分配在 OpenShift Container Platform 集群中使用的巨页。使用 Node Tuning Operator 在特定节点中分配巨页。
流程
为相关节点添加标签,以便 Node Tuning Operator 知道要应用 tuned 配置集的节点。tuned 配置集规定了要分配的巨页数量:
$ oc label node <node_using_hugepages> hugepages=true
创建一个包含以下内容的名为
hugepages_tuning.yaml
的文件:apiVersion: tuned.openshift.io/v1 kind: Tuned metadata: name: hugepages 1 namespace: openshift-cluster-node-tuning-operator spec: profile: 2 - data: | [main] summary=Configuration for hugepages include=openshift-node [vm] transparent_hugepages=never [sysctl] vm.nr_hugepages=1024 name: node-hugepages recommend: - match: 3 - label: hugepages priority: 30 profile: node-hugepages
使用
hugepages_tuning.yaml
文件创建定制的hugepages
tuned 配置集:$ oc create -f hugepages_tuning.yaml
在创建配置集后,Operator 会将新配置集应用到正确的节点中,并分配巨页。在使用巨页的节点中检查 tuned pod 的日志以确认:
$ oc logs <tuned_pod_on_node_using_hugepages> \ -n openshift-cluster-node-tuning-operator | grep 'applied$' | tail -n1 2019-08-08 07:20:41,286 INFO tuned.daemon.daemon: static tuning from profile 'node-hugepages' applied