yarn_defaults_provider.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. var App = require('app');
  18. require('utils/configs/defaults_providers/defaultsProvider');
  19. App.YARNDefaultsProvider = App.DefaultsProvider.create({
  20. /**
  21. * List of the configs that should be calculated
  22. */
  23. configsTemplate: {
  24. 'yarn.nodemanager.resource.memory-mb': null,
  25. 'yarn.scheduler.minimum-allocation-mb': null,
  26. 'yarn.scheduler.maximum-allocation-mb': null,
  27. 'mapreduce.map.memory.mb': null,
  28. 'mapreduce.reduce.memory.mb': null,
  29. 'mapreduce.map.java.opts': null,
  30. 'mapreduce.reduce.java.opts': null,
  31. 'mapreduce.task.io.sort.mb': null,
  32. 'yarn.app.mapreduce.am.resource.mb': null,
  33. 'yarn.app.mapreduce.am.command-opts': null
  34. },
  35. /**
  36. * Information about ram, disk count, cpu count and hbase availability
  37. * Example:
  38. * {
  39. * disk: 12,
  40. * ram: 48,
  41. * cpu: 12,
  42. * hBaseInstalled: false
  43. * }
  44. */
  45. clusterData: null,
  46. /**
  47. * Reserved for system memory
  48. */
  49. reservedRam: null,
  50. /**
  51. * Reserved for HBase memory
  52. */
  53. hBaseRam: null,
  54. GB: 1024,
  55. /**
  56. * Minimum container size (in RAM).
  57. * This value is dependent on the amount of RAM available, as in smaller memory nodes the minimum container size should also be smaller
  58. *
  59. * Value in MB!
  60. */
  61. recommendedMinimumContainerSize: function () {
  62. if (!this.clusterDataIsValid()) return null;
  63. var ram = this.get('clusterData.ram');
  64. switch(true) {
  65. case (ram < 4): return 256;
  66. case (ram >= 4 && ram < 8): return 512;
  67. case (ram >= 8 && ram < 24): return 1024;
  68. case (ram >= 24):
  69. default: return 2048;
  70. }
  71. }.property('clusterData.ram'),
  72. /**
  73. * Maximum number of containers allowed per node
  74. * min (2*cores,min (1.8*DISKS,(Total available RAM) / MIN_CONTAINER_SIZE)))
  75. */
  76. containers: function () {
  77. if (!this.clusterDataIsValid()) return null;
  78. var cpu = this.get('clusterData.cpu');
  79. var disk = this.get('clusterData.disk');
  80. var ram = this.get('clusterData.ram');
  81. var containerSize = this.get('recommendedMinimumContainerSize');
  82. cpu *= 2;
  83. disk = Math.ceil(disk * 1.8);
  84. ram -= this.get('reservedRam');
  85. if (this.get('clusterData.hBaseInstalled')) {
  86. ram -= this.get('hBaseRam');
  87. }
  88. if (ram < 1) {
  89. ram = 1;
  90. }
  91. ram *= this.get('GB');
  92. ram /= containerSize;
  93. return Math.round(Math.min(cpu, Math.min(disk, ram)));
  94. }.property('clusterData.cpu', 'clusterData.ram', 'clusterData.hBaseInstalled', 'clusterData.disk', 'reservedRam', 'hBaseRam', 'recommendedMinimumContainerSize'),
  95. /**
  96. * Amount of RAM per container.
  97. * Calculated to be max(1GB, RAM - reservedRam - hBaseRam) / containers
  98. *
  99. * @return Memory per container in MB. If greater than 1GB,
  100. * value will be in multiples of 512.
  101. */
  102. ramPerContainer: function () {
  103. var containers = this.get('containers');
  104. if (!containers) {
  105. return null;
  106. }
  107. var ram = this.get('clusterData.ram');
  108. ram = (ram - this.get('reservedRam'));
  109. if (this.get('clusterData.hBaseInstalled')) {
  110. ram -= this.get('hBaseRam');
  111. }
  112. // On low memory systems, memory left over after
  113. // removing reserved-RAM and HBase might be
  114. // less than 1GB (even negative). If so, we force
  115. // a 1GB value relying on virtual memory.
  116. if (ram < 1) {
  117. ram = 1;
  118. }
  119. ram *= this.get('GB');
  120. var container_ram = Math.abs(ram / containers);
  121. // If container memory is greater than 1GB,
  122. // we use multiples of 512 as value
  123. return container_ram > this.get('GB') ? (Math.floor(container_ram / 512) * 512) : container_ram;
  124. }.property('containers', 'clusterData.ram', 'clusterData.hBaseInstalled', 'hBaseRam', 'reservedRam'),
  125. mapMemory: function () {
  126. return this.get('ramPerContainer');
  127. }.property('ramPerContainer'),
  128. reduceMemory: function () {
  129. var ramPerContainer = this.get('ramPerContainer');
  130. return ramPerContainer <= 2048 ? 2 * ramPerContainer : ramPerContainer;
  131. }.property('ramPerContainer'),
  132. amMemory: function () {
  133. return Math.max(this.get('mapMemory'), this.get('reduceMemory'));
  134. }.property('mapMemory', 'reduceMemory'),
  135. /**
  136. * Reserved for HBase and system memory is based on total available memory
  137. */
  138. reservedMemoryRecommendations: function() {
  139. var table = [
  140. {os:1,hbase:1},
  141. {os:2,hbase:1},
  142. {os:2,hbase:2},
  143. {os:4,hbase:4},
  144. {os:6,hbase:8},
  145. {os:8,hbase:8},
  146. {os:8,hbase:8},
  147. {os:12,hbase:16},
  148. {os:24,hbase:24},
  149. {os:32,hbase:32},
  150. {os:64,hbase:64}
  151. ];
  152. var ram = this.get('clusterData.ram');
  153. var index = 0;
  154. switch (true) {
  155. case (ram <= 4): index = 0; break;
  156. case (ram > 4 && ram <= 8): index = 1; break;
  157. case (ram > 8 && ram <= 16): index = 2; break;
  158. case (ram > 16 && ram <= 24): index = 3; break;
  159. case (ram > 24 && ram <= 48): index = 4; break;
  160. case (ram > 48 && ram <= 64): index = 5; break;
  161. case (ram > 64 && ram <= 72): index = 6; break;
  162. case (ram > 72 && ram <= 96): index = 7; break;
  163. case (ram > 96 && ram <= 128): index = 8; break;
  164. case (ram > 128 && ram <= 256): index = 9; break;
  165. case (ram > 256 && ram <= 512): index = 10; break;
  166. default: index = 10; break;
  167. }
  168. this.set('reservedRam', table[index].os);
  169. this.set('hBaseRam', table[index].hbase);
  170. }.observes('clusterData.ram'),
  171. /**
  172. * Provide an object where keys are property-names and values are the recommended defaults
  173. * @param {object} localDB Object with information about hosts and master/slave components
  174. * Example:
  175. * <code>
  176. * {
  177. * "hosts": {
  178. * "host1": {
  179. * "name": "host1",
  180. * "cpu": 1,
  181. * "memory": "6123683.00",
  182. * "disk_info": [{
  183. * ....
  184. * },...]
  185. * },...
  186. * },
  187. * "masterComponentHosts": [{
  188. * "component": "NAMENODE",
  189. * "hostName": "host1",
  190. * "serviceId": "HDFS"
  191. * },...],
  192. * "slaveComponentHosts": [{
  193. * "componentName": "DATANODE",
  194. * "hosts": [{
  195. * "hostName": "host2"
  196. * }]
  197. * },...]
  198. * }
  199. * </code>
  200. * @return {object}
  201. */
  202. getDefaults: function (localDB) {
  203. this._super();
  204. this.getClusterData(localDB);
  205. var configs = {};
  206. jQuery.extend(configs, this.get('configsTemplate'));
  207. if (!this.clusterDataIsValid()) {
  208. return configs;
  209. }
  210. configs['yarn.nodemanager.resource.memory-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
  211. configs['yarn.scheduler.minimum-allocation-mb'] = Math.round(this.get('ramPerContainer'));
  212. configs['yarn.scheduler.maximum-allocation-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
  213. configs['yarn.app.mapreduce.am.resource.mb'] = Math.round(this.get('amMemory'));
  214. configs['yarn.app.mapreduce.am.command-opts'] = "-Xmx" + Math.round(0.8 * this.get('amMemory')) + "m";
  215. configs['mapreduce.map.memory.mb'] = Math.round(this.get('mapMemory'));
  216. configs['mapreduce.reduce.memory.mb'] = Math.round(this.get('reduceMemory'));
  217. configs['mapreduce.map.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('mapMemory')) + "m";
  218. configs['mapreduce.reduce.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('reduceMemory')) + "m";
  219. configs['mapreduce.task.io.sort.mb'] = Math.round(0.4 * this.get('mapMemory'));
  220. return configs;
  221. },
  222. /**
  223. * Calculate needed cluster data (like disk count, cpu count, ram (in MB!) and hbase availability)
  224. * @param {object} localDB Object with information about hosts and master/slave components
  225. */
  226. getClusterData: function (localDB) {
  227. this._super();
  228. var components = ['NODEMANAGER'];
  229. var hosts = [];
  230. if (!localDB.hosts || !(localDB.masterComponentHosts || localDB.slaveComponentHosts)) return;
  231. var hBaseInstalled = !!localDB.masterComponentHosts.filterProperty('component', 'HBASE_MASTER').length;
  232. components.forEach(function (component) {
  233. var mc = localDB.masterComponentHosts.findProperty('component', component);
  234. if (mc) {
  235. if (!hosts.contains(mc.hostName)) {
  236. hosts.push(mc.hostName);
  237. }
  238. }
  239. else {
  240. var sc = localDB.slaveComponentHosts.findProperty('componentName', component);
  241. if (sc) {
  242. sc.hosts.map(function (host) {
  243. if (!hosts.contains(host.hostName)) {
  244. hosts.push(host.hostName);
  245. }
  246. });
  247. }
  248. }
  249. });
  250. var clusterData = {
  251. cpu: 0,
  252. disk: 0,
  253. ram: 0,
  254. hBaseInstalled: hBaseInstalled
  255. };
  256. var host = hosts[0] && localDB.hosts[hosts[0]];
  257. if (host) {
  258. clusterData.cpu = parseInt(host.cpu);
  259. var length = 0;
  260. host.disk_info.forEach(function(disk) {
  261. //invalid mountpoints
  262. if (!(disk.mountpoint.startsWith('/home/') || disk.mountpoint.startsWith('/homes/') ||
  263. disk.mountpoint.startsWith('/dev/') || disk.mountpoint.startsWith('/tmp/'))) {
  264. length++;
  265. }
  266. },this);
  267. clusterData.disk = length;
  268. clusterData.ram = Math.round(parseFloat(host.memory) / (1024 * 1024));
  269. }
  270. this.set('clusterData', clusterData);
  271. },
  272. /**
  273. * Verify <code>clusterData</code> - check if all properties are defined
  274. */
  275. clusterDataIsValid: function () {
  276. if (!this.get('clusterData')) return false;
  277. if (this.get('clusterData.ram') == null || this.get('clusterData.cpu') == null || this.get('clusterData.disk') == null || this.get('clusterData.hBaseInstalled') == null) return false;
  278. return true;
  279. }
  280. });