@@ -3,34 +3,20 @@ package io.airbyte.workload.launcher.pods
3
3
import com.google.common.annotations.VisibleForTesting
4
4
import datadog.trace.api.Trace
5
5
import io.airbyte.commons.constants.WorkerConstants.KubeConstants.FULL_POD_TIMEOUT
6
- import io.airbyte.config.ResourceRequirements
7
- import io.airbyte.featureflag.Connection
8
6
import io.airbyte.featureflag.ConnectorSidecarFetchesInputFromInit
9
7
import io.airbyte.featureflag.Context
10
8
import io.airbyte.featureflag.FeatureFlagClient
11
9
import io.airbyte.featureflag.Multi
12
- import io.airbyte.featureflag.ReplicationMonoPod
13
- import io.airbyte.featureflag.ReplicationMonoPodMemoryTolerance
14
10
import io.airbyte.featureflag.Workspace
15
11
import io.airbyte.metrics.lib.ApmTraceUtils
16
12
import io.airbyte.persistence.job.models.ReplicationInput
17
- import io.airbyte.workers.input.getDestinationResourceReqs
18
- import io.airbyte.workers.input.getOrchestratorResourceReqs
19
- import io.airbyte.workers.input.getSourceResourceReqs
20
- import io.airbyte.workers.input.setDestinationLabels
21
- import io.airbyte.workers.input.setSourceLabels
22
13
import io.airbyte.workers.models.CheckConnectionInput
23
14
import io.airbyte.workers.models.DiscoverCatalogInput
24
15
import io.airbyte.workers.models.SpecInput
25
16
import io.airbyte.workers.pod.PodLabeler
26
- import io.airbyte.workers.process.KubePodProcess
27
17
import io.airbyte.workload.launcher.metrics.MeterFilterFactory.Companion.LAUNCH_REPLICATION_OPERATION_NAME
28
- import io.airbyte.workload.launcher.metrics.MeterFilterFactory.Companion.WAIT_DESTINATION_OPERATION_NAME
29
- import io.airbyte.workload.launcher.metrics.MeterFilterFactory.Companion.WAIT_ORCHESTRATOR_OPERATION_NAME
30
- import io.airbyte.workload.launcher.metrics.MeterFilterFactory.Companion.WAIT_SOURCE_OPERATION_NAME
31
18
import io.airbyte.workload.launcher.pipeline.consumer.LauncherInput
32
19
import io.airbyte.workload.launcher.pods.factories.ConnectorPodFactory
33
- import io.airbyte.workload.launcher.pods.factories.OrchestratorPodFactory
34
20
import io.airbyte.workload.launcher.pods.factories.ReplicationPodFactory
35
21
import io.fabric8.kubernetes.api.model.Pod
36
22
import io.fabric8.kubernetes.client.KubernetesClientTimeoutException
@@ -52,7 +38,6 @@ class KubePodClient(
52
38
private val kubePodLauncher : KubePodLauncher ,
53
39
private val labeler : PodLabeler ,
54
40
private val mapper : PayloadKubeInputMapper ,
55
- private val orchestratorPodFactory : OrchestratorPodFactory ,
56
41
private val replicationPodFactory : ReplicationPodFactory ,
57
42
@Named(" checkPodFactory" ) private val checkPodFactory : ConnectorPodFactory ,
58
43
@Named(" discoverPodFactory" ) private val discoverPodFactory : ConnectorPodFactory ,
@@ -69,59 +54,7 @@ class KubePodClient(
69
54
replicationInput : ReplicationInput ,
70
55
launcherInput : LauncherInput ,
71
56
) {
72
- if (useMonoPod(replicationInput = replicationInput)) {
73
- launchReplicationMonoPod(replicationInput, launcherInput)
74
- } else {
75
- launchReplicationPodTriplet(replicationInput, launcherInput)
76
- }
77
- }
78
-
79
- fun launchReplicationPodTriplet (
80
- replicationInput : ReplicationInput ,
81
- launcherInput : LauncherInput ,
82
- ) {
83
- val sharedLabels = labeler.getSharedLabels(launcherInput.workloadId, launcherInput.mutexKey, launcherInput.labels, launcherInput.autoId)
84
-
85
- val inputWithLabels =
86
- replicationInput
87
- .setSourceLabels(sharedLabels)
88
- .setDestinationLabels(sharedLabels)
89
-
90
- val kubeInput = mapper.toKubeInput(launcherInput.workloadId, inputWithLabels, sharedLabels)
91
-
92
- var pod =
93
- orchestratorPodFactory.create(
94
- replicationInput.connectionId,
95
- kubeInput.orchestratorLabels,
96
- kubeInput.resourceReqs,
97
- kubeInput.nodeSelectors,
98
- kubeInput.kubePodInfo,
99
- kubeInput.annotations,
100
- kubeInput.extraEnv,
101
- )
102
- try {
103
- pod =
104
- kubePodLauncher.create(pod)
105
- } catch (e: RuntimeException ) {
106
- ApmTraceUtils .addExceptionToTrace(e)
107
- throw KubeClientException (
108
- " Failed to create pod ${kubeInput.kubePodInfo.name} ." ,
109
- e,
110
- KubeCommandType .CREATE ,
111
- PodType .ORCHESTRATOR ,
112
- )
113
- }
114
-
115
- waitForPodInitComplete(pod, PodType .ORCHESTRATOR .toString())
116
-
117
- waitForOrchestratorStart(pod)
118
-
119
- // We wait for the destination first because orchestrator starts destinations first.
120
- waitDestinationReadyOrTerminalInit(kubeInput)
121
-
122
- if (! replicationInput.isReset) {
123
- waitSourceReadyOrTerminalInit(kubeInput)
124
- }
57
+ launchReplicationMonoPod(replicationInput, launcherInput)
125
58
}
126
59
127
60
fun launchReplicationMonoPod (
@@ -174,52 +107,6 @@ class KubePodClient(
174
107
waitForPodInitComplete(pod, PodType .REPLICATION .toString())
175
108
}
176
109
177
- @Trace(operationName = WAIT_ORCHESTRATOR_OPERATION_NAME )
178
- fun waitForOrchestratorStart (pod : Pod ) {
179
- try {
180
- kubePodLauncher.waitForPodReadyOrTerminalByPod(pod, ORCHESTRATOR_STARTUP_TIMEOUT_VALUE )
181
- } catch (e: RuntimeException ) {
182
- ApmTraceUtils .addExceptionToTrace(e)
183
- throw KubeClientException (
184
- " Main container of orchestrator pod failed to start within allotted timeout of ${ORCHESTRATOR_STARTUP_TIMEOUT_VALUE .seconds} seconds. " +
185
- " (${e.message} )" ,
186
- e,
187
- KubeCommandType .WAIT_MAIN ,
188
- PodType .ORCHESTRATOR ,
189
- )
190
- }
191
- }
192
-
193
- @Trace(operationName = WAIT_SOURCE_OPERATION_NAME )
194
- fun waitSourceReadyOrTerminalInit (kubeInput : OrchestratorKubeInput ) {
195
- try {
196
- kubePodLauncher.waitForPodReadyOrTerminal(kubeInput.sourceLabels, REPL_CONNECTOR_STARTUP_TIMEOUT_VALUE )
197
- } catch (e: RuntimeException ) {
198
- ApmTraceUtils .addExceptionToTrace(e)
199
- throw KubeClientException (
200
- " Source pod failed to start within allotted timeout of ${REPL_CONNECTOR_STARTUP_TIMEOUT_VALUE .seconds} seconds. (${e.message} )" ,
201
- e,
202
- KubeCommandType .WAIT_MAIN ,
203
- PodType .SOURCE ,
204
- )
205
- }
206
- }
207
-
208
- @Trace(operationName = WAIT_DESTINATION_OPERATION_NAME )
209
- fun waitDestinationReadyOrTerminalInit (kubeInput : OrchestratorKubeInput ) {
210
- try {
211
- kubePodLauncher.waitForPodReadyOrTerminal(kubeInput.destinationLabels, REPL_CONNECTOR_STARTUP_TIMEOUT_VALUE )
212
- } catch (e: RuntimeException ) {
213
- ApmTraceUtils .addExceptionToTrace(e)
214
- throw KubeClientException (
215
- " Destination pod failed to start within allotted timeout of ${REPL_CONNECTOR_STARTUP_TIMEOUT_VALUE .seconds} seconds. (${e.message} )" ,
216
- e,
217
- KubeCommandType .WAIT_MAIN ,
218
- PodType .DESTINATION ,
219
- )
220
- }
221
- }
222
-
223
110
fun launchCheck (
224
111
checkInput : CheckConnectionInput ,
225
112
launcherInput : LauncherInput ,
@@ -388,39 +275,9 @@ class KubePodClient(
388
275
}
389
276
}
390
277
391
- private fun useMonoPod (replicationInput : ReplicationInput ): Boolean {
392
- val ffContext = Multi (listOf (Workspace (replicationInput.workspaceId), Connection (replicationInput.connectionId)))
393
- val memoryFootprint = getMemoryLimitTotal(replicationInput)
394
- return featureFlagClient.boolVariation(
395
- ReplicationMonoPod ,
396
- ffContext,
397
- ) && featureFlagClient.intVariation(ReplicationMonoPodMemoryTolerance , ffContext) >= toGigabytes(memoryFootprint)
398
- }
399
-
400
- private fun getMemoryLimitTotal (replicationInput : ReplicationInput ): Long {
401
- val sourceMemoryLimit = extractMemoryLimit(replicationInput.getSourceResourceReqs())
402
- val destinationMemoryLimit = extractMemoryLimit(replicationInput.getDestinationResourceReqs())
403
- val orchestratorMemoryLimit = extractMemoryLimit(replicationInput.getOrchestratorResourceReqs())
404
- return sourceMemoryLimit + destinationMemoryLimit + orchestratorMemoryLimit
405
- }
406
-
407
- private fun extractMemoryLimit (resourceRequirements : ResourceRequirements ? ): Long {
408
- return KubePodProcess .buildResourceRequirements(resourceRequirements)?.limits?.get(" memory" )?.numericalAmount?.toLong() ? : 0
409
- }
410
-
411
278
companion object {
412
279
private val TIMEOUT_SLACK : Duration = Duration .ofSeconds(5 )
413
- val ORCHESTRATOR_STARTUP_TIMEOUT_VALUE : Duration = Duration .ofMinutes(2 )
414
280
val POD_INIT_TIMEOUT_VALUE : Duration = Duration .ofMinutes(15 )
415
281
val REPL_CONNECTOR_STARTUP_TIMEOUT_VALUE : Duration = FULL_POD_TIMEOUT .plus(TIMEOUT_SLACK )
416
- private const val BYTES_PER_GB = 1024 * 1024 * 1024
417
-
418
- private fun toGigabytes (bytes : Long ): Int {
419
- return if (bytes > 0 ) {
420
- (bytes / BYTES_PER_GB ).toInt()
421
- } else {
422
- bytes.toInt()
423
- }
424
- }
425
282
}
426
283
}
0 commit comments