Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: AP 17 Fleet shard status #82

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
106 changes: 106 additions & 0 deletions _ap/17/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
num: 17
category: "Fleet manager, fleet shard and instance operators"
title: "Fleet shard status"
shawkins marked this conversation as resolved.
Show resolved Hide resolved
status: "Draft"
shawkins marked this conversation as resolved.
Show resolved Hide resolved
authors:
- "Steven Hawkins"
- "Luca Burgazzoli"
tags:
- "kafka"
---

## Intent

Define a pattern for fleet shard status representation and interpretation.
shawkins marked this conversation as resolved.
Show resolved Hide resolved

## Motivation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a small drawing of fleet-manager fleet-shard operator operand could help set the context.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After starting on a drawing it made me wonder if that was making this seem too complicated. So I just updated with some language about custom resources in general - I really am trying to convey this is the kubernetes custom resource paradigm with an intermediary, so it has some additional considerations on top of the base recommendations.


A fleet shard must convey the status of the data plane resources it is responsible for back to the control plane. This is typically done using mechanisms built around the Kubernetes status sub-resource. There should be consistency around the design and usage of that status information that conforms to Kuberentes guidelines and so that control planes, SREs, and developers can quickly and appropriately reason over the status.
shawkins marked this conversation as resolved.
Show resolved Hide resolved

## Status Guidelines

### Conditions

Kubernetes provides a significant amount of guidance for https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties[status conditions].

Highlights:
Condition types should be single word or short camel-cased names. They should be unique - it’s more of a map of conditions by type, rather than just an array.
The reason field should be a short word or short camel-cased phase.
The message should be human readable.
The status field should be a three-valued boolean.

More specific to fleet shards:
Since the fleet shard will typically send a full status object back to the control plane periodically or with every change, it is best to include only a minimally necessary set of conditions. However that does not mean you can simply omit conditions. If a condition is not present, it should be interpreted as having status Unknown.
It is fine to have a control plane reason over status conditions - in particular the type, reason, and status fields. However the parsing of a condition message should be avoided, and rather additional status fields should be used to provide specialized information.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Show examples in the form of yaml with a context of the status if necessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there specific examples you had in mind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things like showing non omited considtions even though not use for that specific effective status report.
And that might not be here but you say that the shard in most case cannot know whether a case is transient or terminal. which makes me wonder how the control plan makes that decision from thge status it receives fromt he shard. HEre some examples of how you achieved it , or how a status is interpreted for feedback tot he end user would be interesting for context on how the global machinery is orchestrated

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things like showing non omited considtions even though not use for that specific effective status report.

The guidance about minimizing is fleetshard specific. The interpretation of missing as unknown comes straight from the kubernetes recommendations. From existing non-fleetshard operators, we have counter examples like:

strimzi uses both a Ready and NotReady conditions. The NotReady condition is only populated when there's a problem. By their contract you have to know that a missing NotReady means to look instead for the Ready condition, not that NotReady is currently unknown.

But I'm honestly not sure how instructive that is.

which makes me wonder how the control plan makes that decision from thge status it receives fromt he shard

That's the gist of the recommendations around the error handling - the control plane nor a user can assume an immediate action is needed given seeing something is currently in error - regardless of whether we're installing.

The fleetshard operator interprets the strimzi status as follows:
https://github.com/bf2fc6cc711aee1a0c2a/kas-fleetshard/blob/main/operator/src/main/java/org/bf2/operator/operands/AbstractKafkaCluster.java#L169 That is then aggregated with the other operands. The fleet manager is further able to aggregate reasoning over the cluster itself and from things like route53.

We don't expect the fleet manager to make specific decisions based upon errors that appear in our status - we are instead calling out very specific service level cases - the wrong profile or version of something is in the cr, the data plane lacks capacity for the given instance - that the control plane may use to do things like select a different strimzi version or use a different cluster. Otherwise about the best that they can infer is whether we think we're still Installing.


### Other Status Fields

Beyond conditions, other status fields provide the ability to convey information via a custom schema.

For example the ManagedKafka status once Ready will include route and other information, which are not part of a condition:

[source,yaml]
----
status:
conditions:
- lastTransitionTime: '2022-08-02T08:24:04.818994Z'
message: ''
status: 'True'
type: Ready
routes:
- name: admin-server
prefix: admin-server
router: ingresscontroller.kas.mk-0419-204008.t6kh.p1.openshiftapps.com
- name: bootstrap
prefix: ''
router: ingresscontroller.kas.mk-0419-204008.t6kh.p1.openshiftapps.com
----

### Interpretation

The meaning of any condition or status field is up to the controller / resource and should be a documented part of the API contract.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it's for the fleet manager to interpret in the end correct?


For example the ManagedKafka status Ready condition refers to the operator’s view of the resource. A ManagedKafka is only ready when all of the dependent resources are observed to be in their desired / ready state. This will not always be the same notion of readiness from an end user’s observation of managed kafka service. In particular, the restart of a broker pods, a temporary networking issue, etc. may not be reflected in ManagedKafka status. It follows that a ManagedKafka status Ready condition alone is insufficient to show the user the state of their service. For ManagedKafka canary and other kafka metrics provide a more exact representation of cluster functioning.
Error States
shawkins marked this conversation as resolved.
Show resolved Hide resolved

An operator in general may not consider any problem with a valid resource as terminal - one from which the resource can never recover. The operator’s job is to implement the desired state whenever possible. If at a given time additional resources are needed, other necessary system parts aren’t installed, etc. - it doesn’t mean the conditions won’t be correct at a later time. From the perspective of a managed service though we do have more rigid expectations. For example a ManagedKafka should only be created with a Strimzi version that has an operator installed to manage. For a fleet shard operator if such conditions are violated it is acceptable for the operator and the status handling to assume the resource is in a terminal state.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand what this is trying to say, but I think that way this is worded is a little vague. Do you think the following is better?

An operator in a fleetshard usually lacks sufficient context to determine whether a valid resource is in a terminal state. The operator’s job is simply to implement the desired state whenever possible. For example, if at a given time additional resources are needed, other necessary system parts aren’t installed, etc. - it doesn’t mean the conditions won’t be correct at a later time as a result of some action outside the context of the operator.

In cases where the operator does have sufficient context to determine terminality, for example violation of preconditions in installed versions of APIs, then it is acceptable for the operator and the status handling to assume the resource is in a terminal state.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorporated the above, please see if that matches what you are thinking.


When status is conveying an error that is not known to be terminal, it follows that the error may resolve on its own with additional time. Control planes should assume such errors are ephemeral and not immediately react as if a hard failure has occurred. If there are further actions that the control plane may take, the condition reason or other status fields should make that easy to determine. This allows the data plane logic to remain straightforward and not have to fully understand every possible error condition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a state diagram with some context could help setup the context of the conversation here.

  • transient vs terminal
  • data plane reconsiliation vs fleet manager expected state display
    I'm not sure it will work but could help as I feel I have to think at the problem to figure out what is recommended and for what use case.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There really isn't a state diagram, only very special exceptions to what qualifies as a terminal error.

Maybe restating more succinctly might help:

  • many, if not most, errors will be ephemeral
  • it's impractical, or impossible, for the data plane to know a priori how to categorize whether an error it's seeing is terminal or not.
  • requiring a data plane fix every time a new ephemeral error is encountered is cumbersome, instead only errors that lead to SLO breach need high priority remediation.


For example with managed kafka and auto-scaling enabled it may take longer for a node to become available than Strimzi’s timeout allows. That error is propagated onto the ManagedKafka status. However there is no further action expected by the control plane - and with additional time the auto-scaled node will be available and the placement will succeed. For example from https://issues.redhat.com/browse/MGDSTRM-9288 the control plane observed:

[source,yaml]
----
status:
conditions:
- lastTransitionTime: '2022-08-02T08:24:04.818994Z'
message: 'Exceeded timeout of 420000ms while waiting for Pods resource ninth-zookeeper-0 in namespace kafka-cbfv5rnfnecdu9rb4gc0 to be ready'
status: 'False'
reason: 'Error'
type: Ready
----

Rather than interpreting this as a hard failure, it should be assumed that with additional time and reconciliations that it will resolve on its own.
shawkins marked this conversation as resolved.
Show resolved Hide resolved

How much time to give an error to resolve is up to the control plane and relevant SLOs. During installation this may include waiting until the SLO has been exceeded. For other operations it may mean waiting at least 1 additional resolution time window if the operator or dependent operators uses a time based mechanism.
shawkins marked this conversation as resolved.
Show resolved Hide resolved

### Current vs. Desired State

Especially in instances where spec changes are rolled into dependent resources the desired state will not be fully realized until some point in the future. It is appropriate for the status to provide additional information about this transition. As per the Kubernetes guidelines that could be represented via a condition, or similar to the standard Deployment resource additional status fields such as ready or available replicas, allow for the control plane or a user to infer the progress of the transition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we give a concrete example here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elaborated more based upon a kafka version upgrade.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Show concrete YAML example to anchor the reader

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the yaml that matches the description.


### generation and observedGeneration

In kubernetes, each object should have a generation field which is defined as a sequence number - set by the system and monotonically increased per resource on a spec change. Some resources include a field named observedGeneration as part of the status, which is the generation most recently observed by the component responsible for acting upon changes to the desired state of the resource. This can be used, for instance, to ensure that the reported status reflects the most recent desired state. The observedGeneration field is also part of metav1.Conditions and represents the spec generation that the condition was set based upon.
shawkins marked this conversation as resolved.
Show resolved Hide resolved

Similar concepts with fields that mirror their kubernetes couterparts can be introduced to MAS resources to offer a standard way for clients and control planes to figure out when a specific desired state has been taken into account.

### Frequency Of Status Changes

Rapid changes to a status should be avoided. Each status change is an update that the local Kuberentes instance must process and is generally also relayed to the control plane, which can lead to a substantial amount of overhead for a large number of resources. For controllers that implement fixed interval resolving this is generally not an issue. Event driven controllers though should be designed to minimize unnecessary updates - in particular updates which do not imply a status change should leave the existing status unmodified.
shawkins marked this conversation as resolved.
Show resolved Hide resolved

## Participants
* Control Plane -- development team for the KAS Fleet Manager API.
* Kafka Services -- team developing the kafka fleet shard operator.
* MAS Connectors -- team developing the connector fleet shard operator.