|
| 1 | +.. _node_health: |
| 2 | + |
| 3 | +=================== |
| 4 | +Marking Nodes Down |
| 5 | +=================== |
| 6 | + |
| 7 | +Every node in the lock server (paddles) has an ``up`` flag. A node that is |
| 8 | +marked down is never handed out to a job, so a broken machine stops eating |
| 9 | +scheduled jobs until someone looks at it. Nodes are marked down by hand with |
| 10 | +``teuthology-lock --update --status down <node>``, and automatically by |
| 11 | +``teuthology-supervisor`` in the two cases described below. |
| 12 | + |
| 13 | +All of this happens in the supervisor process, not in the job process. Tasks |
| 14 | +never talk to paddles about node status: a job should not depend on the lock |
| 15 | +server being reachable, and the supervisor is what owns the nodes for the |
| 16 | +duration of a job anyway. |
| 17 | + |
| 18 | +Repeated reimaging failures |
| 19 | +=========================== |
| 20 | + |
| 21 | +If reimaging a node fails, the supervisor asks paddles for that node's last 10 |
| 22 | +jobs. If all 10 of them failed to reimage, the node is marked down with the |
| 23 | +description ``reimage failed 10 times``. See |
| 24 | +``check_for_reimage_failures_and_mark_down()`` in |
| 25 | +``teuthology/dispatcher/supervisor.py``. |
| 26 | + |
| 27 | +Hardware failures reported by ansible |
| 28 | +===================================== |
| 29 | + |
| 30 | +Some ansible failures tell us right away that the node itself is broken - a |
| 31 | +disk that is missing or dead, for example. Waiting for such a node to fail ten |
| 32 | +more jobs is pure waste, so the supervisor marks it down as soon as it sees |
| 33 | +one. |
| 34 | + |
| 35 | +How it works |
| 36 | +------------ |
| 37 | + |
| 38 | +#. The ``ansible`` task sets ``ANSIBLE_FAILURE_LOG`` when it runs |
| 39 | + ``ansible-playbook``. ceph-cm-ansible's ``failure_log`` callback plugin |
| 40 | + (``callback_plugins/failure_log.py``) writes every task failure to that |
| 41 | + file as YAML. |
| 42 | +#. When the playbook fails, the task archives the log to |
| 43 | + ``ansible_failures.yaml`` in the job's archive directory. |
| 44 | +#. After the job process exits, the supervisor reads that file back and passes |
| 45 | + it to ``FailureAnalyzer.find_hardware_failures()``, in |
| 46 | + ``teuthology/task/ansible.py``. |
| 47 | +#. Any node whose failure message matches a known hardware-failure pattern is |
| 48 | + marked down, as long as it is one of the job's own targets. This is |
| 49 | + ``check_for_hardware_failures_and_mark_down()`` in |
| 50 | + ``teuthology/dispatcher/supervisor.py``. |
| 51 | + |
| 52 | +Only the node's status is changed; its lock description is left alone. The job |
| 53 | +still holds the lock at that point, and ``unlock_targets()`` refuses to unlock |
| 54 | +a node whose description no longer matches the job's archive path. |
| 55 | + |
| 56 | +Expected format |
| 57 | +--------------- |
| 58 | + |
| 59 | +The failure log is a YAML document keyed by hostname, with each value being the |
| 60 | +ansible result dict for the failed task. Only the ``msg`` field is examined - |
| 61 | +either on the record itself, or on each entry of its ``results`` list:: |
| 62 | + |
| 63 | + trial007.front.sepia.ceph.com: |
| 64 | + _ansible_no_log: false |
| 65 | + changed: false |
| 66 | + msg: 'Wanted 2 disks of ~1700 GB (rotational=False), but only matched 1: [''nvme1n1'']' |
| 67 | + |
| 68 | +Note that the callback plugin records the result, not the name of the task that |
| 69 | +produced it, so matching is done on the message text. Whitespace in ``msg`` is |
| 70 | +collapsed before matching, because ansible wraps long messages across lines. |
| 71 | + |
| 72 | +The patterns themselves live in ``FailureAnalyzer.hardware_failure_patterns``. |
| 73 | +Each is a regular expression matched case-insensitively against the message. |
| 74 | +Currently there is one: |
| 75 | + |
| 76 | +.. list-table:: |
| 77 | + :header-rows: 1 |
| 78 | + |
| 79 | + * - Pattern |
| 80 | + - Produced by |
| 81 | + * - ``Wanted \d+ disks? of .+ but only matched \d+`` |
| 82 | + - ceph-cm-ansible's ``Ensure we found enough OSD disks`` task, in |
| 83 | + ``roles/testnode/tasks/configure_lvm.yml`` |
| 84 | + |
| 85 | +This is a coupling worth keeping in mind: adding a pattern here means relying |
| 86 | +on the exact wording of a task in ceph-cm-ansible, so changing one of those |
| 87 | +messages means changing the matching pattern too. Only add patterns for |
| 88 | +failures that really do mean the hardware is broken - a node marked down stays |
| 89 | +down until a human brings it back up. |
| 90 | + |
| 91 | +Disabling it |
| 92 | +------------ |
| 93 | + |
| 94 | +Set ``mark_down_on_hardware_failure: false`` in :ref:`site_config` to turn this |
| 95 | +behavior off. The failure log is still archived either way. |
0 commit comments