这段时间一直在想,云计算除了虚拟化之外,还应该有其它的东西,那就是优化。因为我们虚拟出来资源之后怎么用,怎么划分,是并行也好,是租给用户使用也好,都要实现资源调度和使用的最优化。嗯,这是这段时间关于云计算的想法。
下面分享一下最近两天做的一些事。
首先是对cpu的理解,这个大家应该都清楚,我这里只是进行记录,方便后面查询。
在linux下的/proc/cpuinfo文件里,保存了cpu的详细的信息,有兴趣的可以打开看看,有一个误区就是大家看到有两个或四个cpu其实只是一个物理cpu,那四个只是逻辑的,也就是说我们一般的pc只有一个插槽(socket),这个可以看你的 physical id来确定,如果只有一个cpu的话,这几个逻辑cpu的physical id应该都是一样的。那么我们平时所说的几核几核怎么看呢?对,你应该看你的core id,我现在用的机器就有两个core id,一个0,一个1,也就是说是两核的。那么你可能会问,逻辑cpu和核是什么关系呢?应该是这样的,你注意看你的 /proc/cpuinfo 文件会发现,有两个或多个逻辑cpu的core id相同,是的,也就是说,两个或多个逻辑cpu运行在一个核上。
如果还不够理解,那么看下面的例子:
从表中可以看到有两个物理cpu,八个逻辑cpu。
此例说明有逻辑处理器0 和 4 驻留在物理封装 0 的内核 0 上。这就表示逻辑处理器 0 和 4 支持超线程(HT)技术。相同的工作可用于封装 0 内核1 上的逻辑处理器 2 和 6,封装 1 内核 2 上的逻辑处理器 1 和 5,以及封装 1 内核 3 上的逻辑处理器 3 和7。此系统支持超线程(HT)技术,因为两个逻辑处理器共享同一个内核。有两种方式可以确定是否支持多内核。由于内核 0 和 1 存在于封装0 上,而内核 2 和 3 存在于封装 1 上,所以这是一个多内核系统。此外,cpu cores 条目为2,也说明有两个内核驻留在物理封装中。这是一个多路系统,因为有两个封装。
下面我们考虑,kvm虚拟出来的虚拟机(vm)是运行在单独的一个逻辑cpu还是可以分别在各个cpu之间运行?虚拟机cpu(vcpu)是什么概念?物理机(host)怎么看待kvm和vcpu? 为了搞懂这个概念我们还是要回到命令行中看。举例说明:
我这里有一个虚拟机叫core8,它含有8个虚拟cpu它的进程编号是20736.不知道怎么看虚拟机的进程编号? 在host里使用top命令,嗯,这时你会发现所有的运行在host上面的进程及其使用cpu情况,那么找到这个core8虚拟机的进程编号呢?我们在core8上面执行任意一个死循环操作,这时你再看host上的top就会发现,基本上第一个进程就是这core8 了,因为它占得cpu最多,我这里是20736。就是说core8在host看来就是一个进程而已,这个集成的编号是20736.那么现在提出一个问题,这个core8的8个vcpu是怎么个情况呢?在哪里运行呢?这时还是得借助命令行。我们在host里使用ps指令,但是不能单纯了用ps,还要借助于参数: ps -eL //e的意思是打印所有进程,L的意思是连县城也不放过。我这里只显示一下和我们的20736进程相关的信息:
你会看到和20736相关的有九行,那么这九行是什么呢?
首先第一列都是20736,第二列里只有第一行是20736,后面的都不是。那么我们这时就应该明白了,对于host来说,kvm虚拟机是一个进程(20736),虚拟机的vcpu都是这个进程衍生出来的线程。这就是为什么除了20736还有另外八行的原因。
那么我们接着询问,这八个线程是跑在同一个逻辑cpu里吗?为了回答这个问题,我们接着做实验:
还是借助于ps指令 :ps -eLo ruser,pid,ppid,lwp,psr| awk ‘{if($5==1) print $0}’
解释为:ps命令显示当前系统的进程信息的状态,它的“-e”参数用于显示所有的进程,“-L”参 数用于将线程(LWP,light-weight process)也显示出来,“-o”参数表示以用户自定义的格式输出(其中“psr”这列表示当前分配给进程运行的处理器编号,“lwp”列表示线程的 ID,“ruser”表示运行进程的用户,“pid”表示进程的ID,“ppid”表示父进程的ID,)。结合ps和 awk工具的使用,是为了分别打印出来运行在不同的逻辑cpu上的进程线程情况。上面的指令就是打印出1号(从0开始编号)cpu的进行线程情况,我们这里只列出和我们相关的:
这时你会看到,哦,20736号进程衍生出来的线程只有一部分运行在逻辑cpu1上,其它的线程在其它的cpu上了。
这时就大概明白了,不同的vcpu只是不同的线程,而不同的线程是跑在不同的cpu上的。
这时就有需求了,某用户提出要一个八核的虚拟机,而且这八个核是单独占用cpu的,也就是说不要和其它的虚拟机共享,为了避免调度带来的时间或者考虑安全,反正他就是提出这么一个需求。这时我们就要用到进程线程的绑定功能了。
为了实现这个功能,你首先得会 taskset命令,直观上来说,taskset就是设置任务,也就是制定任务运行的情况,是一个很好用的工具。
taskset绑定进程到某个CPU是很方便的:
#taskset -pc 0,1 1249
这会绑定1249进程到1号跟1号cpu上。
#cat /proc/1249/status
Cpus_allowed: 3
Cpus_allowed_list: 0-1
重新绑定下:
#taskset -pc 1 1249
#cat /proc/1249/status
Cpus_allowed: 2
Cpus_allowed_list: 1
注意这里的Cpu_allowed用的是二进制掩码,3的二进制是11,2的二进制是10。前一个表示可在两个CPU上运行,第二个表示仅在第二个CPU上运行。
那么我们这里就可以使用taskset了,只需把这九个线程都绑定在同一个cpu上即可。假设我们把这个虚拟机绑定到1号cpu上:
taskset -p 2 20736
taskset -p 20740
taskset -p 20741
......
taskset -p 20747
ok,这时你再运行ps -eLo ruser,pid,ppid,lwp,psr| awk ‘{if($5==1) print $0}’,会看到形如下面的结果:
那么也就是完成了我们的虚拟机绑定任务,为了验证一下是否真正实现了绑定,我们在core8虚拟机里运行一个死循环,然后看host里的 top指令的结果:
我们可以清楚的看到1号cpu的利用率100%,而其它的cpu基本上没用到,这说明我们的绑定是成功的,完成了客户提出的需求。