Skip to content

Commit 554454f

Browse files
authored
Fix: Refine the wasted time during retries for jetstream_benchmark_serving (GoogleCloudPlatform#1051)
With 57 TaskGroups across four parallel branches, the retry wait alone wastes ~570 minutes (~9.5 hours) This change improves the error handling within the ssh_tpu Airflow task to distinguish between critical SSH authentication failures and other command execution errors. Solution: - If any host fails with an `AuthenticationException`, the task is failed with a non-retryable `AirflowFailException`. - If hosts fail due to other exceptions (e.g., `invoke.UnexpectedExit`), the original `fabric.group.GroupException` is re-raised. This allows Airflow's retry mechanism to handle these potentially transient issues as configured for the task.
1 parent 1986f30 commit 554454f

2 files changed

Lines changed: 31 additions & 4 deletions

File tree

xlml/apis/task.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,18 @@ def run_queued_resource_test(
109109
task_test_config,
110110
)
111111

112-
queued_resource_op >> tpu.ssh_tpu.override(task_id="setup")(
112+
setup_task = tpu.ssh_tpu.override(
113+
task_id="setup",
114+
# Setup/install retries don’t need a long cooldown.
115+
# 30s is enough for network connection problem; longer delays do not make sense.
116+
retry_delay=datetime.timedelta(seconds=30),
117+
)(
113118
queued_resource_name,
114119
task_test_config.setup_script,
115120
ssh_keys,
116121
True if task_test_config.test_name.startswith("tf_") else all_workers,
117122
)
123+
queued_resource_op >> setup_task
118124

119125
run_model = tpu.ssh_tpu.override(
120126
task_id="run_model",

xlml/utils/tpu.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from airflow.utils.task_group import TaskGroup
2828
from airflow.operators.python import get_current_context
2929
from airflow.models import Variable
30+
from airflow.exceptions import AirflowFailException
3031
from xlml.apis import gcp_config, test_config
3132
from xlml.utils import ssh, startup_script, composer
3233
import fabric
@@ -404,6 +405,27 @@ def ssh_tpu(
404405
gateway='corp-ssh-helper %h %p' if use_external_ips else None,
405406
)
406407

408+
def ssh_group_run(cmds: Iterable[str]):
409+
try:
410+
ssh_group.run(cmds, env=env)
411+
except fabric.group.GroupException as e:
412+
for connection, result in e.result.items():
413+
if isinstance(result, paramiko.ssh_exception.AuthenticationException):
414+
logging.error(
415+
f'SSH Authentication Failed on {connection.host}: {result}'
416+
)
417+
raise AirflowFailException(
418+
'SSH Authentication failed on one or more hosts. Check logs for details.'
419+
) from e
420+
raise
421+
except paramiko.ssh_exception.AuthenticationException as e:
422+
error_msg = f'SSH Authentication Failed: {e}'
423+
logging.error(error_msg)
424+
raise AirflowFailException(error_msg) from e
425+
426+
finally:
427+
ssh_group.close()
428+
407429
context = get_current_context()
408430
if context['task_instance'].try_number > 1:
409431
# kill TPU process by pid (if any) to avoid `TPU in use` error in retry
@@ -414,10 +436,9 @@ def ssh_tpu(
414436
f'set -xue; sudo echo "{script}" > {tmp_file}',
415437
f'bash {tmp_file} {accelerator_type}',
416438
)
417-
ssh_group.run(';'.join(kill_process_cmds))
418-
439+
ssh_group_run(';'.join(kill_process_cmds))
419440
# run provided commands
420-
ssh_group.run(cmds, env=env)
441+
ssh_group_run(cmds)
421442

422443

423444
@task

0 commit comments

Comments
 (0)