|
24 | 24 | from dags import composer_env |
25 | 25 | from dags.tpu_observability.utils import jobset_util as jobset |
26 | 26 | from dags.tpu_observability.utils import node_pool_util as node_pool |
27 | | -from dags.tpu_observability.utils.jobset_util import Workload, ReplicatedJobStatus |
| 27 | +from dags.tpu_observability.utils.jobset_util import Workload, JobSetHealthiness |
28 | 28 | from dags.tpu_observability.configs.common import ( |
29 | 29 | MachineConfigMap, |
30 | 30 | GCS_CONFIG_PATH, |
|
38 | 38 | SCHEDULE = SchedulingHelper.arrange_schedule_time(DAG_ID) |
39 | 39 |
|
40 | 40 | FAIL_WORKLOAD = "python3 -c 'import logging; import sys; logging.error(\"Simulating Failure\"); sys.exit(1)'" |
| 41 | +SUCCESS_WORKLOAD = "python3 -c 'import logging; import sys; logging.info(\"Simulating Success\"); sys.exit(0)'" |
41 | 42 |
|
42 | 43 | # Keyword arguments are generated dynamically at runtime (pylint does not |
43 | 44 | # know this signature). |
|
63 | 64 | doc_md=""" |
64 | 65 | # JobSet Healthiness Test For the "Suspended" Status |
65 | 66 | ### Description |
66 | | - This DAG automates the process of creating node-pools, ensuring the |
67 | | - correct number of "Suspended" replicas appear, then launching a jobset on |
68 | | - multiple replicas to ensure the correct number begin running. |
| 67 | + This DAG automates node-pool creation and validates JobSet healthiness |
| 68 | + by examining replica-based metrics: Specified, Active, Ready, |
| 69 | + Suspended, Succeeded, and Failed. It ensures the JobSet controller |
| 70 | + accurately reports these states during startup, maintenance, |
| 71 | + and failure scenarios. |
69 | 72 | ### Prerequisites |
70 | 73 | This test requires an existing cluster to run. |
71 | 74 | ### Procedures |
72 | | - First a node-pool is created. The validation test is then run to |
73 | | - check if the number of "Suspended" replicas is 0. Once the jobset is |
74 | | - running the jobs should quickly enter the "Ready" state. Then using |
75 | | - command to suspend entire jobset. The number of found replicas is |
76 | | - tested against the number of replicas which should be "Suspended". |
77 | | - If they match the DAG is a success. |
| 75 | + First a node-pool is created. This test uses a State-Trigger-Observe pattern: |
| 76 | + it triggers lifecycle transitions (e.g., suspension, failure or succeeded) |
| 77 | + and verifies that GKE telemetry reflects these shifts. Using sensors, |
| 78 | + the DAG polls for eventual consistency to account for ingestion latency, |
| 79 | + dynamically matching runtime JobSet configurations against normalized monitoring |
| 80 | + data types to ensure accurate state validation. |
78 | 81 | """, |
79 | 82 | ) as dag: |
80 | 83 | for machine in MachineConfigMap: |
|
110 | 113 | node_pool=cluster_info, |
111 | 114 | ) |
112 | 115 |
|
113 | | - startup = jobset.create_jobset_startup_group( |
| 116 | + startup = jobset.create_jobset_startup_tasks( |
114 | 117 | node_pool=cluster_info, |
115 | 118 | jobset_config=jobset_config, |
116 | 119 | workload_type=Workload.JAX_TPU_BENCHMARK, |
117 | 120 | ) |
118 | 121 |
|
119 | 122 | with TaskGroup(group_id="validate_running_metrics") as validate_running: |
120 | 123 | running_metrics = [ |
121 | | - (ReplicatedJobStatus.SPECIFIED, "USE_CONFIG_REPLICAS"), |
122 | | - (ReplicatedJobStatus.ACTIVE, "USE_CONFIG_REPLICAS"), |
123 | | - (ReplicatedJobStatus.READY, "USE_CONFIG_REPLICAS"), |
124 | | - (ReplicatedJobStatus.FAILED, 0), |
125 | | - (ReplicatedJobStatus.SUCCEEDED, 0), |
126 | | - (ReplicatedJobStatus.SUSPENDED, 0), |
| 124 | + (JobSetHealthiness.SPECIFIED, "USE_CONFIG_REPLICAS"), |
| 125 | + (JobSetHealthiness.ACTIVE, "USE_CONFIG_REPLICAS"), |
| 126 | + (JobSetHealthiness.READY, "USE_CONFIG_REPLICAS"), |
| 127 | + (JobSetHealthiness.FAILED, 0), |
| 128 | + (JobSetHealthiness.SUCCEEDED, 0), |
| 129 | + (JobSetHealthiness.SUSPENDED, 0), |
127 | 130 | ] |
128 | 131 | for status, expected in running_metrics: |
129 | 132 | jobset.wait_for_jobset_metrics.override( |
|
146 | 149 | group_id="validate_suspended_metrics" |
147 | 150 | ) as validate_suspended: |
148 | 151 | suspended_metrics = [ |
149 | | - (ReplicatedJobStatus.ACTIVE, 0), |
150 | | - (ReplicatedJobStatus.SUSPENDED, "USE_CONFIG_REPLICAS"), |
| 152 | + (JobSetHealthiness.ACTIVE, 0), |
| 153 | + (JobSetHealthiness.SUSPENDED, "USE_CONFIG_REPLICAS"), |
151 | 154 | ] |
152 | 155 | for status, expected in suspended_metrics: |
153 | 156 | jobset.wait_for_jobset_metrics.override( |
|
164 | 167 | jobset_config=jobset_config, |
165 | 168 | ) |
166 | 169 |
|
| 170 | + with TaskGroup(group_id="inject_and_validate_success") as success_test: |
| 171 | + cleanup_for_success = jobset.end_workload.override( |
| 172 | + task_id="cleanup_before_success_injection" |
| 173 | + )( |
| 174 | + node_pool=cluster_info, |
| 175 | + jobset_config=jobset_config, |
| 176 | + ) |
| 177 | + |
| 178 | + start_success_job = jobset.run_workload.override( |
| 179 | + task_id="start_success_job" |
| 180 | + )( |
| 181 | + node_pool=cluster_info, |
| 182 | + jobset_config=jobset_config, |
| 183 | + workload_type=SUCCESS_WORKLOAD, |
| 184 | + ) |
| 185 | + |
| 186 | + validate_succeeded_metric = jobset.wait_for_jobset_metrics.override( |
| 187 | + task_id="wait_for_succeeded_count" |
| 188 | + )( |
| 189 | + metric_name=JobSetHealthiness.SUCCEEDED, |
| 190 | + expected_value="USE_CONFIG_REPLICAS", |
| 191 | + node_pool=cluster_info, |
| 192 | + jobset_config=jobset_config, |
| 193 | + ) |
| 194 | + |
| 195 | + chain(cleanup_for_success, start_success_job, validate_succeeded_metric) |
| 196 | + |
167 | 197 | with TaskGroup(group_id="inject_and_validate_failure") as failure_test: |
168 | 198 | cleanup_for_failure = jobset.end_workload.override( |
169 | 199 | task_id="cleanup_before_failure_injection" |
|
181 | 211 | validate_failed_metric = jobset.wait_for_jobset_metrics.override( |
182 | 212 | task_id="wait_for_failed_count" |
183 | 213 | )( |
184 | | - metric_name=ReplicatedJobStatus.FAILED, |
| 214 | + metric_name=JobSetHealthiness.FAILED, |
185 | 215 | expected_value="USE_CONFIG_REPLICAS", |
186 | 216 | node_pool=cluster_info, |
187 | 217 | jobset_config=jobset_config, |
|
209 | 239 | jobset_config, |
210 | 240 | cluster_info, |
211 | 241 | create_node_pool, |
212 | | - startup.task_group, |
| 242 | + *startup.tasks, |
213 | 243 | validate_running, |
214 | 244 | suspend_action, |
215 | 245 | validate_suspended, |
216 | 246 | resume_action, |
| 247 | + success_test, |
217 | 248 | failure_test, |
218 | 249 | cleanup_workload, |
219 | 250 | cleanup_node_pool, |
|
0 commit comments