<转>理解VMware资源池

本文详细解释了vSphere中资源池的概念、如何分配CPU和内存资源,以及资源池之间的相互影响。包括资源池的Limit、Shares、Reservation配置,如何在集群级别和子资源池中进行资源分配,并探讨了资源争用和准入控制的重要性。


因为本人用的系统是英文版,截图也都是英文的,所以文中表述常常会中英混杂,只是为自己方便,还请见谅。

为方便描述,本文中的资源池(Resource Pool)都简写为RP。VM=虚机,Shares=份额,vCPU=虚机的CPU,Limit=限额或上限,Reservation=保留。

资源池(Resource Pool, RP)有2种,CPU资源池和Memory资源池。其概念还是很容易理解的。

下图截取自官方的《vSphere Resource Management Guide》第36页

图1:资源池

其中1台主机有6GHz CPU资源和3GB可用内存资源。并且创建了2个资源池,RP-QA获得2/3的资源,也就是4GHz CPU资源和2GB内存资源。RP-Marketing获得剩下的1/3的资源。

一个集群(Cluster)的资源池包含集群中所有主机(Host)的资源总和
。比如一个2主机的集群,每个主机都有16GHz CPU和16GB内存,那么这个集群的资源总和就是32GHz的CPU和32GB的内存。在这个集群中创建的资源池就从这个总的可用资源中分配。

集群的可用资源总是小于集群的总资源,这是因为每台主机都会占用一部分CPU和内存资源,保留给自己的Hypervisor和COS用(如果是ESX的话)。

虽然集群资源池是所有主机资源的总和,但是并不意味着某一VM可以使用超过某一主机的资源。比如,2台16GB内存的主机组成集群,集群中创建了一个30GB内存的资源池,但是任何单台VM都不能使用超过16GB pRAM的,因为 VM不能跨主机使用资源,VM可用到的资源还受到单台主机物理资源上限的影响。


 
思考题1:请问这样的描述正确吗?因为VM不能跨主机使用资源,所以在上面例子中30GB内存的资源池中将不能创建1台20GB内存的VM,因为20GB大于单台主机的物理内存。(答案点这里)
 

同VM一样,资源池也有Shares, Reservation和Limit这3个配置项。(见下图)


图2:编辑资源池属性

【Limit】

RP的Limit和VM的Limit类似,不同的就是这个limit是RP中所有VM可用物理资源的上限值。

虽然Limit不会限制VM的创建,但是它限定了可用物理资源,影响了RP中运行中VM的性能。

【Shares】

资源池的资源通常通过份额来分配。 有3种预设的份额分配方式,High,Normal和Low,比重分别为4:2:1。反映在Shares数字上则如下表

份额(Shares)类型
HighNormalLow
比重
421
CPU
800040002000
Memory
32768016384081920
如果各一个RP的%
57.1%28.6%14.3%
 

比如说一个集群有5个资源池,1个High,2个Normal,2个Low,那么High的RP可以获得4/(4+2*2+1*2)=40%的资源,Normal的RP各可以获得20%,Low的RP各可以获得10%资源。

资源池下可以建子资源池。资源按份额的比例分配。

看图很容易理解。

图3:资源池与子资源池
 

下面通过几个例子来说明问题。在我的例子中有2个RP,一个叫IT-RP,另一个叫QA-RP。有3台VM,其中Test01分配了2个vCPU和2GB内存;虚机thick-dp和thin-dp都只有1个vCPU和1GB内存。

(1)  CPU资源的份额(shares)和vCPU个数有关,Normal类型下,每个vCPU 1000份额
例如:同一个RP下的VM,都设了normal,1个vCPU的thick-dp和thin-dp都只占share 1000,2个vCPU的Test01占share 2000
图4:例子1-CPU

Worst case allocation是最坏情况下该VM会占用的资源数量,这个最坏情况是指VM,而不是RP,换一句话说就是VM在运行一个耗CPU的程序,已经达到了100% CPU占有率。这个值是根据当前资源状况动态计算出来的。我的例子中因为没有争用,所以耗CPU的VM可以跑满2个vCPU,我的host用的是XEON E5405,是四核且每核2GHz,因此2个vCPU可以用足4000MHz,2个vCPU的thick-dp可以用足2000MHz。thin-dp这台VM因为设置了CPU Limt为1000MHz,因此它的Worst Case Allocation是1000MHz。

内存资源的份额和VM的配置内存大小(configured memory size)有关。Normal类型下,每1MB的内存占10份额。也就是说每1GB(1024MB)就是10240份额

例如:同一个RP下的VM,都设了normal,1GB内存的VM的份额是10240,2GB内存的Test01虚机就有20480份额。

图5:例子1-Memory


内存的Worst Case Allocation和CPU的类似,是指运行一个耗内存的程序时VM最多能占用的pRAM的数量。大家会发现这个最坏情况占用比配置内存/内存上限还要大一点,多的那部分就是用于memory overhead的。memeory overhead的大小和VM被配置了多少个vCPU和多少vRAM有关,关于memory overhead的具体信息,详见拙文:《VMware内存配置再探》。
 
(2)  在cluster根一级的VM和其下的第一层Resource Pool共同分享所有资源

Normal RP默认份额是4000,单vCPU的VM的Normal份额是1000,2个vCPU的是2000


图6:例子2

所以,如果某服务器特别重要,需要特别多的份额,那就直接放在cluster底下,可以不用放进任何RP 

Normal类型的资源池,其内存份额是163840,CPU份额是4000,相当于一台配置了4vCPU和16GB内存的VM。(为便于记忆这么类比)
 
(3)  将VM从某一个RP移走,份额总数会减少,意味着每一单位份额的资源增加了;VM移入某个RP,总份额会增加,意味着每一单位份额的资源减少了。

图7:例子3-移除VM对资源分配的影响

这个例子中,总份额数从8000下降到了6000,原先有16GHz CPU资源,每一份是2MHz,现在增加到了2.67MHz。因此每个RP的总资源也增加了。

VM移动到另一个RP的时候,其Limit和Reservation值保留
。其份额如果是以Normal, High, Low表示的话,将在目的RP中占有相应的比例。并且影响到目的RP的总份额数。下图例子中,Test01的加入导致该RP中总份额由2000增加到了4000,因此单位份额的CPU资源下降了一半,原先每台VM的可用资源比例也从50%下降到了25%.

图8:例子3-加入VM对资源分配的影响

重要!强调一点,份额(Shares)必须是在有资源争用(Contention)的情况下才起作用

千万不要被图1所迷惑了,错以为6GHz的CPU就应该按照Normal比Low的2:1的比例分配给2个RP,其中1个4GHz,另外一个2GHz。错!大错特错!真实的情况是,在没有发生争用的时候,不管其中哪1台VM(例如VM-Marketing1)都可以用5GHz甚至更多的CPU资源。

【Reservation】

RP的reservation不是决定其中的VM能用多少CPU/内存资源,而是用来分配给VM的Reservation用的。如果RP的可用保留(Available Reservation)不够VM Reservation需要的量,VM将不能被启动,或者正在运行中的VM不能被移动到该RP中。这种检查叫做准入控制(Admission Control)。

比如资源池中可用内存保留是1500MB。位于该RP中的VM1和VM2的内存保留都是1024MB,当我们启动VM1的时候,可以正常启动。但是再启动VM时,剩下的可用内存保留只有476MB,不够1024MB,于是VM2无法启动,用户将收到Insufficient Memory Resource的报错。

资源池有2种类型,Fixed和Expandable。在上面的截图中可以看见,CPU和Memory资源都可以勾选Expandable Reservation,默认是勾选的。如果手工去掉这个勾,就可以更改为Fixed。

Fixed类型就是其中的VM的Reservation只能使用自己的Reservation,而Expandable的RP Reservation就是不仅可以使用自己的Reservation,而且当RP中的可用保留(Available Reservation)不够VM用的时候,可以使用父RP中的可用保留。

下图就是将Memory Reservation类型从Fixed改成Expandable后,Available Reservation的变化。

图9:资源保留的类型Fixed和Expandable

VM开机才会有Reservation,关机的时候就把这部分Reservation还回资源池了

RP Reservation中的内存/CPU资源并非被这个RP独占,而其他RP无法使用。如果某一个RP Reservation中的内存没有被用掉,而其他RP的VM还是可以使用这部分内存的。

举例,Host有3GB内存,完全竞争下RP1获得1GB,RP2获得2GB。RP1设了1GB的Reservation,但是其中没有VM。RP2中有且仅有一台VM配置了2.5GB内存,运行一个耗内存的程序,那么这个VM可以获得2.5GB的pRAM,其中0.5GB来自RP1,而无视其Reservation。

但是, 增加某个RP的Reservation就减少了其他RP可以获得的Reservation

还是上例中,Host有3GB内存,RP1 Normal,reservation 1GB,RP2 Low,reservation 0.5GB。那么Host还剩下1.5GB的 Available Reservation。如果RP1和RP2都是expandable的,那么RP1的Available Reservation有2.5GB,RP2的Available Reservation会显示有2GB。此时,增加RP1的Reservation到2GB,你会发现RP1的Available Reservation还是2.5GB,但是RP1的却只有1GB了。

开启一台VM所需要的物理内存,不仅和Memory Reservation有关,也和Memory Overhead有关
。当Available Reservation小于开启一台VM所需的需求(等于Memory Reservation和Overhead的和)时,VM就无法启动。

举例,如上图9中,Fixed的时候,可用保留只剩下132MB了,此时启动1台2vCPU,2GB内存,0内存保留的VM,是否能启动呢?答案是不能,因为虽然此VM内存保留设为了0,但是Memory Overhead还需要198MB可用内存保留。因此无法启动。
 
现在揭晓 思考题1的答案:不对。这台VM可以被创建,也可以被运行。虽然这台VM不能跨主机使用资源,也就是它最多可以用到16GB的pRAM,但是别忘记它还有swap,因此,20GB的swap保证了Guest OS的运行。

本文出自 “delxu的Live记事本” 博客,请务必保留此出处http://delxu.blog.51cto.com/975660/283522

课程名称: 数据技术原理与应用 专业班级: 数科2304 姓 名: 仇一焯 学 号: 2023002253 指导教师: 陈泽华老师 2025年10月20日 实验 Spark Word Count 一 、实验内容: 基本要求: 完成Spark Word Count 二 、实验工具 虚拟机软件 VMware Workstation Pro17 操作系统 CentOS 7(64 位) ftp工具 XShell 8 Java 版本 jdk1.8.0_212 Hadoop 版本 hadoop-3.1.3 Spark版本 Spark 3.3.0 Maven 版本 Maven 3.6.3 三 、实验过程与截图 1.前置检查(必须执行) 1.1检查Spark集群状态 在 Master 节点(hadoop102)执行以下命令,确认 Master 和 Worker 进程正常运行: - 执行节点:在 HDFS 的主节点(通常是 `hadoop102`)上执行。 - 命令(绝对路径): /opt/module/hadoop-3.1.3/sbin/start-dfs.sh 验证:在所有节点上执行 `jps` 命令。 - `hadoop102` 应看到 `NameNode` 和 `DataNode`。 - `hadoop103` 应看到 `DataNode`。 - `hadoop104` 应看到 `DataNode` 和 `SecondaryNameNode` 一键启动集群(自动启动 Master 和所有 Worker): $SPARK_HOME/sbin/start-all.sh # 查看Master节点进程 Jps # 查看Worker节点进程(分别在hadoop103、hadoop104执行) Jps 解释:jps命令用于查看 Java 进程,需确保 hadoop102 有Master进程,hadoop103/104 有Worker进程,否则需重启集群:$SPARK_HOME/sbin/start-all.sh。 1.2验证HDFS服务可用性 词频统计需通过 HDFS 存储输入输出数据,执行以下命令检查 HDFS 状态: # 查看HDFS根目录 hdfs dfs -ls / # 测试HDFS写入权限 hdfs dfs -touchz /test.txt && hdfs dfs -rm /test.txt 解释:通过创建临时文件验证 HDFS 读写权限,若提示`Permission denied`需检查 Hadoop 目录权限配置。 2. 数据准备(HDFS 数据上传) 2.1 创建 HDFS 数据目录 # 创建输入目录(存放待分析文本) hdfs dfs -mkdir -p /spark-wordcount/input # 创建输出目录(后续运行前需删除,此处仅为演示) hdfs dfs -mkdir -p /spark-wordcount/output 2.2 准备本地测试文本 vi /home/atguigu/wordcount-data.txt 粘贴测试内容: Hello Spark Hello Hadoop Spark is fast Hadoop is stable Hello Spark HBase Spark Spark Spark 2.3上传文本到 HDFS hdfs dfs -put /home/atguigu/wordcount-data.txt /spark-wordcount/input/ # 验证上传结果 hdfs dfs -ls /spark-wordcount/input/ 3. 词频统计实现(Scala 语言方案) 3.1编写 Scala 代码 1. 创建代码目录(含 Maven 要求的源码结构) # 创建项目根目录 mkdir -p /home/atguigu/spark-code/scala # 进入项目根目录 cd /home/atguigu/spark-code/scala # 创建 Maven 规定的 Scala 源码目录(必须!否则 Maven 找不到代码) mkdir -p src/main/scala 2. 在正确目录下编写代码 # 注意:代码必须放在 src/main/scala 目录下 vi src/main/scala/WordCount.scala 3. 粘贴代码 // 导入Spark核心依赖(必须完整,避免编译错误) import org.apache.spark.{SparkConf, SparkContext} // 词频统计主类(单例对象,Scala中可作为入口类,类名必须与pom.xml的mainClass一致) object WordCount { def main(args: Array[String]): Unit = { // 1. 配置Spark应用(集群模式下,setMaster可通过spark-submit参数覆盖,更灵活) val conf = new SparkConf() .setAppName("Scala-WordCount") // 应用名称,Web UI可见 // 注:集群提交时建议删除setMaster,通过--master参数指定,避免硬编码 // .setMaster("spark://192.168.10.102:7077") .set("spark.executor.memory", "2g") .set("spark.cores.max", "4") // 2. 创建Spark上下文(核心入口,需确保配置正确) val sc = new SparkContext(conf) sc.setLogLevel("WARN") // 减少日志输出,聚焦结果 // 3. 处理输入输出路径(优先使用命令行参数,适配不同场景) val inputPath = if (args.length > 0) args(0) else "/spark-wordcount/input" val outputPath = if (args.length > 1) args(1) else "/spark-wordcount/output" // 4. 核心逻辑(分步注释,清晰易懂) val wordCounts = sc.textFile(inputPath) // 读取文件:每行作为一个元素 .flatMap(line => line.split("\\s+")) // 分词:按任意空白分割,扁平化为单词 .map(word => (word, 1)) // 标记计数:每个单词映射为(单词, 1) .reduceByKey(_ + _) // 聚合:按单词累加计数(简化写法,等价于(a,b)=>a+b) .sortBy(_._2, ascending = false) // 排序:按词频降序 // 5. 输出结果(控制台+HDFS,双重验证) println("=== 词频统计结果 ===") wordCounts.collect().foreach(println) // 控制台打印(仅适合小数据) wordCounts.saveAsTextFile(outputPath) // 保存到HDFS(分布式场景推荐) // 6. 释放资源(必须执行,避免内存泄漏) sc.stop() } } \- `textFile`:读取 HDFS 或本地文件,返回行级 RDD(弹性分布式数据集),是 Spark 数据处理的基础结构; `flatMap`:扁平化换,将每行文本拆分为单个单词,解决`map`操作可能产生的嵌套数组问题; `reduceByKey`:Spark 核心聚合算子,自动按 key 分组并执行累加,比`groupByKey`更高效(减少网络传输); `collect`:动作算子,将分布式 RDD 数据拉取到 Driver 节点,仅适合小结果集查看。 4. 验证代码位置(关键检查): # 确保代码在 src/main/scala 目录下 ls -l src/main/scala/WordCount.scala # 预期输出:-rw-r--r-- 1 atguigu atguigu ... src/main/scala/WordCount.scala 3.2 打包 Scala 代码(Maven 方式) 1.创建 `pom.xml`: vi /home/atguigu/spark-code/scala/pom.xml 复制粘贴以下配置(适配 Spark 3.3.0 和 Scala 2.12) <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 项目基本信息(自定义,确保唯一即可) --> <groupId>com.atguigu.spark</groupId> <artifactId>spark-wordcount</artifactId> <version>1.0-SNAPSHOT</version> <!-- 版本管理(关键:Scala与Spark版本必须匹配) --> <properties> <scala.version>2.12.15</scala.version> <!-- Spark 3.3.0适配Scala 2.12.x --> <spark.version>3.3.0</spark.version> <!-- 与集群Spark版本一致 --> <maven.compiler.source>1.8</maven.compiler.source> <!-- 适配JDK 1.8 --> <maven.compiler.target>1.8</maven.compiler.target> </properties> <!-- 依赖配置(仅包含必要依赖,避免冲突) --> <dependencies> <!-- Spark核心依赖(scope=provided:集群已存在,打包不包含) --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <!-- 后缀_2.12对应Scala版本 --> <version>${spark.version}</version> <scope>provided</scope> </dependency> </dependencies> <!-- 构建配置(核心:确保Scala代码编译并打包进JAR) --> <build> <sourceDirectory>src/main/scala</sourceDirectory> <!-- 指定Scala源码目录 --> <testSourceDirectory>src/main/test</testSourceDirectory> <plugins> <!-- 1. Scala编译插件(必须配置,否则Maven无法编译.scala文件) --> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>4.5.4</version> <executions> <execution> <id>scala-compile</id> <goals> <goal>compile</goal> <!-- 编译Scala源码 --> <goal>testCompile</goal> </goals> <configuration> <args> <arg>-dependencyfile</arg> <arg>${project.build.directory}/.scala_dependencies</arg> </args> </configuration> </execution> </executions> </plugin> <!-- 2. 打包插件(生成可执行JAR,包含主类信息) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <phase>package</phase> <goals><goal>shade</goal></goals> <configuration> <!-- 解决依赖冲突:保留最后一个依赖版本 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <!-- 指定主类(必须与Scala代码中的object名称一致) --> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>WordCount</mainClass> <!-- 无包名时直接写类名 --> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> 编译并打包: # 进入项目根目录 cd /home/atguigu/spark-code/scala # 清理旧文件并编译(首次编译时间较长) mvn clean scala:compile # 【关键验证1】检查是否生成 .class 文件 ls -l target/classes/WordCount.class # 若输出 ".class" 文件,说明编译成功;否则检查代码语法或目录 # 打包 mvn package 3.3 提交任务到 Spark 集群 1. 上传 JAR 到 HDFS: hdfs dfs -put -f target/spark-wordcount-1.0-SNAPSHOT.jar /spark-jars/ 2. 删除旧输出目录(避免冲突): hdfs dfs -rm -r /spark-wordcount/output 3. 提交任务: $SPARK_HOME/bin/spark-submit \ --master spark://192.168.10.102:7077 \ --class WordCount \ hdfs://192.168.10.102:8020/spark-jars/spark-wordcount-1.0-SNAPSHOT.jar \ /spark-wordcount/input \ /spark-wordcount/output 4. 问题:版本过低需要升级 解决步骤:升级 Maven 到 3.3.9 及以上版本 步骤 1:查看当前 Maven 版本(确认问题) 执行以下命令,查看当前 Maven 版本: mvn -v 如果输出的`Maven home`对应的版本低于`3.3.9`(例如`3.0.5`),则需要升级。 步骤 2:下载并安装兼容的 Maven 版本 推荐安装Maven 3.6.3(兼容 3.3.9 + 要求,且稳定): 1. 进入临时目录下载安装包: cd /tmp wget http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.tar.gz 2. 解压到`/opt/module`目录(与你的其他软件目录统一): sudo tar -zxvf apache-maven-3.6.3-bin.tar.gz -C /opt/module/ 3. 重命名目录(方便后续配置): sudo mv /opt/module/apache-maven-3.6.3 /opt/module/maven-3.6.3 4. 配置环境变量(替换旧版本 Maven):编辑`/etc/profile`文件: sudo vi /etc/profile 添加以下内容(分别在hadoop102.103.104上进行配置)(确保覆盖系统默认的 Maven 路径): export MAVEN_HOME=/opt/module/maven-3.6.3 export PATH=$MAVEN_HOME/bin:$PATH 生效配置: source /etc/profile 步骤 3:验证 Maven 版本是否升级成功 再次执行: mvn -v 若输出类似以下内容,说明升级成功: ```plaintext Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /opt/module/maven-3.6.3 Java version: 1.8.0_212, vendor: Oracle Corporation, runtime: /opt/module/jdk1.8.0_212/jre 根据以上内容,生成流程图,一共四部分分别是总体介绍,详细操作,问题解决和总结与讨论
最新发布
10-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值