teraslice 0.78.0 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cluster/services/cluster/backends/kubernetes/k8s.js +2 -2
- package/lib/cluster/services/cluster/backends/kubernetes/k8sResource.js +55 -12
- package/lib/config/schemas/system.js +5 -0
- package/lib/storage/analytics.js +1 -1
- package/lib/storage/backends/elasticsearch_store.js +9 -16
- package/lib/storage/state.js +13 -11
- package/lib/workers/worker/index.js +3 -3
- package/package.json +17 -17
|
@@ -8,10 +8,10 @@ const Request = require('kubernetes-client/backends/request');
|
|
|
8
8
|
const { getRetryConfig } = require('./utils');
|
|
9
9
|
|
|
10
10
|
class K8s {
|
|
11
|
-
constructor(logger, clientConfig, defaultNamespace
|
|
11
|
+
constructor(logger, clientConfig, defaultNamespace,
|
|
12
12
|
apiPollDelay, shutdownTimeout) {
|
|
13
13
|
this.apiPollDelay = apiPollDelay;
|
|
14
|
-
this.defaultNamespace = defaultNamespace;
|
|
14
|
+
this.defaultNamespace = defaultNamespace || 'default';
|
|
15
15
|
this.logger = logger;
|
|
16
16
|
this.shutdownTimeout = shutdownTimeout; // this is in milliseconds
|
|
17
17
|
|
|
@@ -25,6 +25,7 @@ class K8sResource {
|
|
|
25
25
|
constructor(resourceType, resourceName, terasliceConfig, execution) {
|
|
26
26
|
this.execution = execution;
|
|
27
27
|
this.jobLabelPrefix = 'job.teraslice.terascope.io';
|
|
28
|
+
this.jobPropertyLabelPrefix = 'job-property.teraslice.terascope.io';
|
|
28
29
|
this.nodeType = resourceName;
|
|
29
30
|
this.terasliceConfig = terasliceConfig;
|
|
30
31
|
|
|
@@ -54,6 +55,7 @@ class K8sResource {
|
|
|
54
55
|
this._setImagePullSecret();
|
|
55
56
|
this._setEphemeralStorage();
|
|
56
57
|
this._setExternalPorts();
|
|
58
|
+
this._setPriorityClassName();
|
|
57
59
|
|
|
58
60
|
if (resourceName === 'worker') {
|
|
59
61
|
this._setWorkerAntiAffinity();
|
|
@@ -219,6 +221,25 @@ class K8sResource {
|
|
|
219
221
|
}
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
_setPriorityClassName() {
|
|
225
|
+
if (this.terasliceConfig.kubernetes_priority_class_name) {
|
|
226
|
+
if (this.nodeType === 'execution_controller') {
|
|
227
|
+
// eslint-disable-next-line max-len
|
|
228
|
+
this.resource.spec.template.spec.priorityClassName = this.terasliceConfig.kubernetes_priority_class_name;
|
|
229
|
+
if (this.execution.stateful) {
|
|
230
|
+
// eslint-disable-next-line max-len
|
|
231
|
+
this.resource.spec.template.metadata.labels[`${this.jobPropertyLabelPrefix}/stateful`] = 'true';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (this.nodeType === 'worker' && this.execution.stateful) {
|
|
235
|
+
// eslint-disable-next-line max-len
|
|
236
|
+
this.resource.spec.template.spec.priorityClassName = this.terasliceConfig.kubernetes_priority_class_name;
|
|
237
|
+
// eslint-disable-next-line max-len
|
|
238
|
+
this.resource.spec.template.metadata.labels[`${this.jobPropertyLabelPrefix}/stateful`] = 'true';
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
222
243
|
_setAssetsVolume() {
|
|
223
244
|
if (this.terasliceConfig.assets_directory && this.terasliceConfig.assets_volume) {
|
|
224
245
|
this.resource.spec.template.spec.volumes.push({
|
|
@@ -266,14 +287,40 @@ class K8sResource {
|
|
|
266
287
|
_setResources() {
|
|
267
288
|
let cpu;
|
|
268
289
|
let memory;
|
|
290
|
+
let maxMemory;
|
|
291
|
+
|
|
292
|
+
const container = this.resource.spec.template.spec.containers[0];
|
|
269
293
|
|
|
270
294
|
// use teraslice config as defaults and execution config will override it
|
|
271
295
|
const envVars = Object.assign({}, this.terasliceConfig.env_vars, this.execution.env_vars);
|
|
272
296
|
|
|
273
297
|
if (this.nodeType === 'worker') {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
298
|
+
if (this.execution.resources_requests_cpu
|
|
299
|
+
|| this.execution.resources_limits_cpu) {
|
|
300
|
+
if (this.execution.resources_requests_cpu) {
|
|
301
|
+
_.set(container, 'resources.requests.cpu', this.execution.resources_requests_cpu);
|
|
302
|
+
}
|
|
303
|
+
if (this.execution.resources_limits_cpu) {
|
|
304
|
+
_.set(container, 'resources.limits.cpu', this.execution.resources_limits_cpu);
|
|
305
|
+
}
|
|
306
|
+
} else if (this.execution.cpu || this.terasliceConfig.cpu) {
|
|
307
|
+
// The settings on the executions override the cluster configs
|
|
308
|
+
cpu = this.execution.cpu || this.terasliceConfig.cpu || -1;
|
|
309
|
+
_.set(container, 'resources.requests.cpu', cpu);
|
|
310
|
+
_.set(container, 'resources.limits.cpu', cpu);
|
|
311
|
+
}
|
|
312
|
+
if (this.execution.resources_requests_memory
|
|
313
|
+
|| this.execution.resources_limits_memory) {
|
|
314
|
+
_.set(container, 'resources.requests.memory', this.execution.resources_requests_memory);
|
|
315
|
+
_.set(container, 'resources.limits.memory', this.execution.resources_limits_memory);
|
|
316
|
+
maxMemory = this.execution.resources_limits_memory;
|
|
317
|
+
} else if (this.execution.memory || this.terasliceConfig.memory) {
|
|
318
|
+
// The settings on the executions override the cluster configs
|
|
319
|
+
memory = this.execution.memory || this.terasliceConfig.memory || -1;
|
|
320
|
+
_.set(container, 'resources.requests.memory', memory);
|
|
321
|
+
_.set(container, 'resources.limits.memory', memory);
|
|
322
|
+
maxMemory = memory;
|
|
323
|
+
}
|
|
277
324
|
}
|
|
278
325
|
|
|
279
326
|
if (this.nodeType === 'execution_controller') {
|
|
@@ -282,21 +329,17 @@ class K8sResource {
|
|
|
282
329
|
|| this.terasliceConfig.cpu_execution_controller || -1;
|
|
283
330
|
memory = this.execution.memory_execution_controller
|
|
284
331
|
|| this.terasliceConfig.memory_execution_controller || -1;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const container = this.resource.spec.template.spec.containers[0];
|
|
288
|
-
|
|
289
|
-
if (cpu !== -1) {
|
|
290
332
|
_.set(container, 'resources.requests.cpu', cpu);
|
|
291
333
|
_.set(container, 'resources.limits.cpu', cpu);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (memory !== -1) {
|
|
295
334
|
_.set(container, 'resources.requests.memory', memory);
|
|
296
335
|
_.set(container, 'resources.limits.memory', memory);
|
|
336
|
+
maxMemory = memory;
|
|
297
337
|
}
|
|
298
338
|
|
|
299
|
-
|
|
339
|
+
// NOTE: This sucks, this manages the memory env var but it ALSO is
|
|
340
|
+
// responsible for doing the config and execution env var merge, which
|
|
341
|
+
// should NOT be in this function
|
|
342
|
+
setMaxOldSpaceViaEnv(container.env, envVars, maxMemory);
|
|
300
343
|
}
|
|
301
344
|
|
|
302
345
|
_setTargets() {
|
|
@@ -295,6 +295,11 @@ const schema = {
|
|
|
295
295
|
default: 'default',
|
|
296
296
|
format: 'optional_String'
|
|
297
297
|
},
|
|
298
|
+
kubernetes_priority_class_name: {
|
|
299
|
+
doc: 'Priority class that the Teraslice master, execution controller, and stateful workers should run with',
|
|
300
|
+
default: undefined,
|
|
301
|
+
format: 'optional_String'
|
|
302
|
+
},
|
|
298
303
|
kubernetes_config_map_name: {
|
|
299
304
|
doc: 'Specify the name of the Kubernetes ConfigMap used to configure worker pods',
|
|
300
305
|
default: 'teraslice-worker',
|
package/lib/storage/analytics.js
CHANGED
|
@@ -29,7 +29,7 @@ module.exports = function elasticsearchStorage(backendConfig) {
|
|
|
29
29
|
recordType,
|
|
30
30
|
idField,
|
|
31
31
|
storageName,
|
|
32
|
-
bulkSize =
|
|
32
|
+
bulkSize = 1000,
|
|
33
33
|
fullResponse = false,
|
|
34
34
|
logRecord = true,
|
|
35
35
|
forceRefresh = true,
|
|
@@ -161,13 +161,13 @@ module.exports = function elasticsearchStorage(backendConfig) {
|
|
|
161
161
|
* index saves a record to elasticsearch with a specified ID.
|
|
162
162
|
* If the document is already there it will be replaced.
|
|
163
163
|
*/
|
|
164
|
-
async function indexWithId(recordId, record, indexArg
|
|
164
|
+
async function indexWithId(recordId, record, indexArg, timeout) {
|
|
165
165
|
validateIdAndRecord(recordId, record);
|
|
166
166
|
|
|
167
167
|
logger.trace(`indexWithId call with id: ${recordId}, record`, logRecord ? record : null);
|
|
168
168
|
|
|
169
169
|
const query = {
|
|
170
|
-
index: indexArg,
|
|
170
|
+
index: indexArg || indexName,
|
|
171
171
|
type: recordType,
|
|
172
172
|
id: recordId,
|
|
173
173
|
body: record,
|
|
@@ -322,14 +322,17 @@ module.exports = function elasticsearchStorage(backendConfig) {
|
|
|
322
322
|
|
|
323
323
|
const type = _type || 'index';
|
|
324
324
|
|
|
325
|
-
const
|
|
325
|
+
const action = {
|
|
326
326
|
[type]: {
|
|
327
327
|
_index: indexArg,
|
|
328
328
|
_type: recordType,
|
|
329
329
|
}
|
|
330
330
|
};
|
|
331
331
|
|
|
332
|
-
bulkQueue.push(
|
|
332
|
+
bulkQueue.push({
|
|
333
|
+
action,
|
|
334
|
+
data: type === 'delete' ? undefined : record
|
|
335
|
+
});
|
|
333
336
|
|
|
334
337
|
// We only flush once enough records have accumulated for it to make sense.
|
|
335
338
|
if (bulkQueue.length >= bulkSize) {
|
|
@@ -375,17 +378,7 @@ module.exports = function elasticsearchStorage(backendConfig) {
|
|
|
375
378
|
}
|
|
376
379
|
|
|
377
380
|
async function bulkSend(bulkRequest) {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
await pRetry(async () => elasticsearch.bulkSend(bulkRequest), {
|
|
381
|
-
reason: `Failure to bulk create "${recordType}"`,
|
|
382
|
-
logError: logger.warn,
|
|
383
|
-
delay: isTest ? 100 : 1000,
|
|
384
|
-
backoff: 5,
|
|
385
|
-
retries: 100,
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
return recordCount;
|
|
381
|
+
return elasticsearch.bulkSend(bulkRequest);
|
|
389
382
|
}
|
|
390
383
|
|
|
391
384
|
async function _flush(shuttingDown = false) {
|
package/lib/storage/state.js
CHANGED
|
@@ -60,17 +60,19 @@ async function stateStorage(context) {
|
|
|
60
60
|
async function createSlices(exId, slices) {
|
|
61
61
|
await waitForClient();
|
|
62
62
|
|
|
63
|
-
const bulkRequest =
|
|
64
|
-
for (const slice of slices) {
|
|
63
|
+
const bulkRequest = slices.map((slice) => {
|
|
65
64
|
const { record, index } = _createSliceRecord(exId, slice, SliceState.pending);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
return {
|
|
66
|
+
action: {
|
|
67
|
+
index: {
|
|
68
|
+
_index: index,
|
|
69
|
+
_type: recordType,
|
|
70
|
+
_id: record.slice_id,
|
|
71
|
+
},
|
|
71
72
|
},
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
data: record
|
|
74
|
+
};
|
|
75
|
+
});
|
|
74
76
|
return backend.bulkSend(bulkRequest);
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -242,8 +244,8 @@ async function stateStorage(context) {
|
|
|
242
244
|
}
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
async function search(query, from, size, sort
|
|
246
|
-
return backend.search(query, from, size, sort, fields);
|
|
247
|
+
async function search(query, from, size, sort, fields) {
|
|
248
|
+
return backend.search(query, from, size, sort || '_updated:desc', fields);
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
async function count(query, from = 0, sort = '_updated:desc') {
|
|
@@ -192,7 +192,7 @@ class Worker {
|
|
|
192
192
|
this.slicesProcessed += 1;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
async shutdown(block
|
|
195
|
+
async shutdown(block, event, shutdownError) {
|
|
196
196
|
if (this.isShutdown) return;
|
|
197
197
|
if (!this.isInitialized) return;
|
|
198
198
|
const { exId } = this.executionContext;
|
|
@@ -202,11 +202,11 @@ class Worker {
|
|
|
202
202
|
'worker',
|
|
203
203
|
`shutdown was called for ${exId}`,
|
|
204
204
|
'but it was already shutting down',
|
|
205
|
-
block ? ', will block until done' : ''
|
|
205
|
+
block !== false ? ', will block until done' : ''
|
|
206
206
|
];
|
|
207
207
|
this.logger.debug(msgs.join(' '));
|
|
208
208
|
|
|
209
|
-
if (block) {
|
|
209
|
+
if (block !== false) {
|
|
210
210
|
await waitForWorkerShutdown(this.context, 'worker:shutdown:complete');
|
|
211
211
|
}
|
|
212
212
|
return;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teraslice",
|
|
3
3
|
"displayName": "Teraslice",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.79.0",
|
|
5
5
|
"description": "Distributed computing platform for processing JSON data",
|
|
6
6
|
"homepage": "https://github.com/terascope/teraslice#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -33,50 +33,50 @@
|
|
|
33
33
|
"test:watch": "ts-scripts test --watch . --"
|
|
34
34
|
},
|
|
35
35
|
"resolutions": {
|
|
36
|
-
"debug": "^4.3.
|
|
36
|
+
"debug": "^4.3.3",
|
|
37
37
|
"ms": "^2.1.3"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@terascope/elasticsearch-api": "^
|
|
41
|
-
"@terascope/job-components": "^0.
|
|
42
|
-
"@terascope/teraslice-messaging": "^0.
|
|
43
|
-
"@terascope/utils": "^0.
|
|
40
|
+
"@terascope/elasticsearch-api": "^3.0.2",
|
|
41
|
+
"@terascope/job-components": "^0.56.3",
|
|
42
|
+
"@terascope/teraslice-messaging": "^0.27.1",
|
|
43
|
+
"@terascope/utils": "^0.44.1",
|
|
44
44
|
"async-mutex": "^0.3.2",
|
|
45
45
|
"barbe": "^3.0.16",
|
|
46
|
-
"body-parser": "^1.19.
|
|
46
|
+
"body-parser": "^1.19.1",
|
|
47
47
|
"convict": "^4.4.1",
|
|
48
48
|
"decompress": "^4.2.1",
|
|
49
|
-
"easy-table": "^1.
|
|
49
|
+
"easy-table": "^1.2.0",
|
|
50
50
|
"event-loop-stats": "^1.2.0",
|
|
51
|
-
"express": "^4.17.
|
|
52
|
-
"fs-extra": "^
|
|
51
|
+
"express": "^4.17.2",
|
|
52
|
+
"fs-extra": "^10.0.0",
|
|
53
53
|
"gc-stats": "^1.4.0",
|
|
54
|
-
"got": "^11.8.
|
|
54
|
+
"got": "^11.8.3",
|
|
55
55
|
"ip": "^1.1.5",
|
|
56
56
|
"kubernetes-client": "^9.0.0",
|
|
57
57
|
"lodash": "^4.17.21",
|
|
58
58
|
"ms": "^2.1.3",
|
|
59
|
-
"nanoid": "^3.
|
|
59
|
+
"nanoid": "^3.2.0",
|
|
60
60
|
"porty": "^3.1.1",
|
|
61
61
|
"semver": "^7.3.5",
|
|
62
62
|
"socket.io": "^1.7.4",
|
|
63
63
|
"socket.io-client": "^1.7.4",
|
|
64
|
-
"terafoundation": "^0.
|
|
64
|
+
"terafoundation": "^0.37.1",
|
|
65
65
|
"uuid": "^8.3.2"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@terascope/teraslice-op-test-harness": "^1.24.
|
|
68
|
+
"@terascope/teraslice-op-test-harness": "^1.24.1",
|
|
69
69
|
"archiver": "^5.3.0",
|
|
70
70
|
"bufferstreams": "^3.0.0",
|
|
71
71
|
"chance": "^1.1.8",
|
|
72
72
|
"elasticsearch": "^15.4.1",
|
|
73
|
-
"got": "^11.8.
|
|
73
|
+
"got": "^11.8.3",
|
|
74
74
|
"jest-fixtures": "^0.6.0",
|
|
75
75
|
"js-yaml": "^4.1.0",
|
|
76
|
-
"nock": "^13.1
|
|
76
|
+
"nock": "^13.2.1"
|
|
77
77
|
},
|
|
78
78
|
"engines": {
|
|
79
|
-
"node": "^12.
|
|
79
|
+
"node": "^12.22.0 || >=14.17.0",
|
|
80
80
|
"yarn": ">=1.16.0"
|
|
81
81
|
},
|
|
82
82
|
"publishConfig": {
|