Logo

Documentation

Health Rules

Cartographer reports the health of each object stamped on the cluster.

Specifying No Health Rule

If no health rule is specified in the template, Cartographer’s health behavior will be rudimentary:

  • if the object is rejected by the API server (e.g. if you mistakenly try to template out a CinfogMap instead of a ConfigMap) then the workload will report the resource’s Healthy condition as “Unknown”. The workload will report the resource’s Ready condition as “False” for the reason “TemplateRejectedByAPIServer”.
  • if the object is created but the path that is meant to be read does not exist (e.g. you have a ClusterImageTemplate where the imagePath mistakenly points to a non-existent field) then the workload will report the resource’s Healthy condition as “Unknown” for the reason “OutputNotAvailable”. The workload will report the resource’s Ready condition as “Unknown” for the reason “MissingValueAtPath”.

Otherwise, the object’s Healthy condition will be “True”. By defining one of several types of health rules, a template author can better define the conditions that report healthy or unhealthy status. This will ensure that the proper status is returned to users.

Always Healthy

Some resources simply have no sense of “healthiness” and are meant to be considered always healthy. For instance, a ConfigMap would never be unhealthy as it always simply reflects the data values that were last submitted.

Template authors may choose not specify a healthrule at all (i.e., rely on the default behavior). But it is clearer to be explicit:

apiVersion: carto.run/v1alpha1
kind: Cluster[Config|Deployment|Image|Source]Template
spec:
  healthRule:
    alwaysHealthy: {}

This leads to the following status on the owner object:

status:
  conditions:
    - type: ResourcesHealthy  # <=== aggregates status.resources[*].conditions[type == Healthy].status
      status: "True"
      reason: HealthyConditionRule
    ...
  resources:
    - conditions:
        - type: Healthy
          status: "True"
          reason: AlwaysHealthy
        ...

Single Condition

This type of health rule is useful for the majority of resources out there as most custom resources implement the pattern of providing a condition set under status.conditions.

With singleConditionType all you need to provide is the type of the condition to look up when evaluating healthiness.

e.g., consider the kpack/Image object:

status:
  conditions:
    - status: "True"
      type: Ready
    - status: "True"
      type: BuilderReady

Given that it makes use of the status.conditions pattern (and Ready: True indicates healthiness), we can leverage singleConditionType:

  healthRule:
    singleConditionType: Ready

Cartographer will then consider the named condition (in this case Ready) and evaluate healthiness as the status on that condition:

  • healthy: status == true
  • unhealthy: status == false
  • unknown: anything else

The message field of the specified condition will be replicated on the owner object.

Multi Match

With multiMatch we’re able to specify more than one matching rule for determining healthiness. This is the most flexible of the health rules.

For some controllers, two conditions must be met for the object to be healthy. For example in Deployments, users want both the Available and Progressing conditions to be true. For other resources, one condition indicates the object is healthy and another condition indicates that the object is unhealthy. Kapp’s App resource behaves in this manner, if the ReconcileSucceeded condition is true the object is healthy, while if the ReconcileFailed condition is true the object is unhealthy. Multimatch can address both of these use cases.

When specifying multiMatch, users must define both what constitutes healthy and what indicates unhealthy. Users may specify multiple matchers. The matchers for healthy must all be met for an object to be healthy. If any of the matchers under unhealthy are met, the object is considered unhealthy.

  healthRule:
    multiMatch:
      healthy: #! matchers here are ANDed
        ...
      unhealthy: #! matchers here are ORed
        ...

There are two types of matchers available, matchConditions and matchFields.

Match Conditions

MultiMatch’s MatchConditions provide more nuance to SingleCondition. Users specify the type of the condition on the object that should be inspected as well as the status value which is considered a match. When a matcher set is satisfied, the message field of the first condition will be replicated on the owner object.

As an example, we can replicate the behavior of the single condition type that we observed above.

  healthRule:
    multiMatch:
      healthy:
        matchConditions:
          - type: Ready
            status: True
      unhealthy:
        matchConditions:
          - type: Ready
            status: False

Match Fields

Match fields allow users to inspect arbitrary fields on an object in order to determine health. This is useful for objects which do not use conditions. Match fields also allow users to specify arbitrary fields on the object for messagePath, which explains the reason for failure to an end user.

Using match fields we can again replicate the behavior of the single condition type that we observed above.

  healthRule:
    multiMatch:
      healthy:
        matchFields:
          - key: 'status.conditions[?(@.type=="Ready")].status'
            operator: 'In'
            values: [ 'True' ]
            messagePath: 'status.conditions[?(@.type=="Ready")].message'
      unhealthy:
        matchFields:
          - key: 'status.conditions[?(@.type=="Ready")].status'
            operator: 'In'
            values: [ 'False' ]
            messagePath: 'status.conditions[?(@.type=="Ready")].message'

Along with the In operator, there is a NotIn operator that also leverages the values field. There are also Exists and DoesNotExist operators.