code: def kill(self):
      failures = 0
      max_failures = 3
      node = None
      terminated_succesfully = False
      while not terminated_succesfully and failures < max_failures:
          try:
              node = get_random_node()
              if not node:
                  logger.info("No alive worker nodes")
                  continue
              terminate_node(node["NodeID"])
              terminated_succesfully = True
              logger.info(
                  f"Killed node {node['NodeID']} with IP {node['NodeManagerAddress']}"
              )
          except Exception:
              failures += 1
              logger.exception(
                  "Killing random node failed in attempt "
                  f"{failures}. "
                  f"Retrying {max_failures - failures} more times"
              )
      self.history.append(
          {
              "timestamp": time.time(),
              "node": node,
              "terminated_succesfully": terminated_succesfully,
          }
      )
      safe_write_to_results_json(self.history)
  
file_path: ray/release/tune_tests/fault_tolerance_tests/workloads/terminate_node_aws.py
imports: import subprocess
  import random
  import requests
  import time
  import logging
  import ray
  from ray.util.scheduling_strategies import NodeAffinitySchedulingStrategy
  from ray._private.test_utils import safe_write_to_results_json
label_desc: Use image node_id 3 for calling the InstanceKillerActor obj's underlying member method code with example usage: obj.kill() without return types