8000 Feature: Ordered Install/Upgrade · Issue #375 · helm/community · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Feature: Ordered Install/Upgrade #375

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

Open
mattfarina opened this issue Dec 14, 2024 · 10 comments
Open

Feature: Ordered Install/Upgrade #375

mattfarina opened this issue Dec 14, 2024 · 10 comments

Comments

@mattfarina
Copy link
Contributor

There have been discussions about adding the ability for Helm to do an ordered installation where different parts of the order are applied to Kubernetes at different times.

Currently, Helm sends all the resources (except CRDs) at one time. When there are subcharts, which are embedded in the chart, those are pulled into a shared sandbox, rendered together, and sent at once. Helm does order the resources by type as we have experience that this has mattered in some cases. The reason Helm sends everything at once is that controllers should eventually reconcile and make everything consistent.

This does not always work for applications, in practice.

Configuration management tools can be used to install different parts of an application separately to deal with this problem. But, this does not work for general distribution of applications as charts where end users can helm install an application.

The proposal is to do this with multiple times Helm sends resource to Kubernetes.

There are currently two ideas being discussed:

  1. The H4HIP: Helm Sequencing Proposal (H4HIP: Helm Sequencing Proposal #373) - where there are "layers" in a chart that are sent at different times. There are trade-offs with this effort. For example:
    • A single chart can have different parts that are sent at different times. This means you could have a database, caching server, and application server in a single chart (i.e. no subcharts) and they could be installed in an ordered manner.
    • What happens when subcharts introduce layers of their own and there is one large shared sandbox? How will the calculated layers work together and be easily debugged? There be dragons in this area.
    • Individual components cannot be upgraded separately. This is good if you want to disallow that but bad if you want to allow individual component upgrades.
  2. Hypper was a project that built on Helm and had the concept of a shared dependency. sub-charts inserted this way were not bundled with the chart in the traditional way and each of these subcharts was installed installed before its parent in an ordered manner.
    • Each chart is self contained and can be reasoned about.
    • Applications that have an ordering of parts (rather than well formed individual components) need to be broken up into multiple charts in an un-natural manner
    • Individual subcharts can be upgraded individually (a trade off listed on the previous bullet set).
    • Parts can be easily reused (e.g., a database chart that's used by multiple applications). It's DRY in this sense.

There may be alternative solutions to this problem and we are happy to discuss them. Neither of these 2 proposals is a solution for all the things.

We are interested in feedback and questions on these two ideas.

@banjoh
Copy link
Contributor
banjoh commented Dec 17, 2024

Applications that have an ordering of parts (rather than well formed individual components) need to be broken up into multiple charts in an un-natural manner

This statement sums the problem statement quite well

@banjoh
Copy link
Contributor
banjoh commented Dec 17, 2024

Today, Application Distributors are more often than not composing applications from ready made charts from bitnami et. al or vendors using charts to distribute their applications. I do not have data to back this up, I'm mostly speaking from experience.

With that, we'll see Application Distributors need to package charts that require to be distributed as a single installable entities. Some of these applications need to be composed from external dependencies (databases, caches, object stores etc) that might be separate distinct charts or templates in a chart. Today, having these applications start up in a particular order isn't always a simple thing to achieve.

Here is a concrete, but simplified example. I have an application that will conditionally generate a self-singed certificate if one does not exist in a defined secret at start up. I would like to have cert-manager issue a cert before my application starts, so my application can use that instead. Once I distribute this application, I want to have my users run helm install foo-release foo-chart.

There are two strategies I can use to allow my application to wait for cert-manager to generate a certificate before starting

  • Use init containers which at times need extra functionality present in external dependencies to support polling for readiness i.e I'd need to poll cert-manager custom resource status to ensure its completed generating my cert.
  • Split their application into separate charts. Install them separately and --wait/--wait-for-jobs. At times, some scripting will be needed to really wait for all components to be ready. A DB migration for example needs some custom logic that's not exposed as a kubernetes status. In the cert-manager case, we'd need to check if my certificate has been issued. This approach also introduces a distribution challenge where the application distributor needs to send install instructions which they cannot ensure will be used correctly. Installations might end up being done in the wrong order, wrong versions etc. At this point we'd be venturing into the land of installer scripts.

With chart resource ordering, the problem I see isn't that getting resources ordered is an impossible task, its the difficulty of achieving it that is the issue. It becomes harder the further away an Application Distributor is to the applications being packaged, especially if they are composing different applications from different charts/projects.

@gjenkins8
Copy link
Member

been thinking about this for the last few days (or weeks now).

First thought, is I think we should certainly support something with much better UX than using annotations as #373 proposes. For example, representing resource sets (or "layers") in separate directories (though I'm sure there is a better way out there than this example). Where the user can easily identify / support different resource sets, and their order without hunting through annotations in templates. I think #373 proposes annotations as that is perhap the only option for Charts V2 API as we have today.

Second thought, is that options 1. and two 2. ie. layers within a chart, or ordering sub-charts are not necessarily exclusive. But obviously they do occupy a large portion of the same solution space. The differences is perhaps whether Helm want to allow users to compose different charts into an "application". But that also might mean artificially breaking a chart into several pieces to support ordering (as describe above). There also might also be a middle group,

Third thought, extending on the above. Helm must consider upgrades as much as installs. Maintaining and upgrading software Day 2 is almost always harder than installing on Day 1. IMHO, a single package should always be subject to a single operation (install and upgrade) ie. all layers would be upgraded to a new chart version in a single Helm operation. Whereas, and IMHO especially if orchestrated by higher level software, a chart with ordered sub-chart dependencies could be updated progressively/independently e.g. db the blue/green the app layer.

@gjenkins8
Copy link
Member

https://kro.run/docs/overview#resourcegraphdefinition for inspiration

@banjoh
Copy link
Contributor
banjoh commented Feb 27, 2025
  • What happens when subcharts introduce layers of their own and there is one large shared sandbox? How will the calculated layers work together and be easily debugged? There be dragons in this area.

Layers are used to order resources in one chart. These annotations should not affect ordering resources outside of the same chart/subchart. I call this out 11d56ea

  • Individual components cannot be upgraded separately. This is good if you want to disallow that but bad if you want to allow individual component upgrades.

This should not be a problem anymore. See comment above.

@mattfarina

@scottrigby
Copy link
Member

I agree it makes sense to scope sequencing options for resources within a chart to only depend on other resources within the same chart.

Along those lines, the ability to sequence dependencies for a chart should be only for each entire dependency, not dig into a specific resource within any of those (that can happen with the above annotations).

In short, I agree with @mattfarina that orchestration for multiple charts—apart from functionality we already have, like dependencies of a chart—should be considered outside the scope of Helm 4. Other projects in the Helm ecosystem (like Matt said, Hypper, Helmfile, Flux Helm controller) can handle orchestrating multiple, independent charts.

@jessesimpson36
Copy link
jessesimpson36 commented Mar 20, 2025

I really like the idea of this Feature request. I'll give this topic some more thought and see if I can have more useful feedback. But I'll give what I can now. One frustration I often have with "just throwing all the manifests at the server all at once" is clumsy scheduling.

I'll use the camunda helm chart as an example, because my team and I maintain that. We have a set of pods that handle storage that could be layer 1, that would be postgresql and elasticsearch. then pods that depend on that would be our other apps zeebe, operate, tasklist, optimize ...

When all the pods get thrown onto the server at once, I get

Node 1: with storage
- operate
- zeebe
- tasklist
- optimize

Node 2: (doesn't have much storage)
- elasticsearch (cannot run, even with affinity rules preferring node1)
- postgresql (cannot run, even with affinity rules preferring node1)

Node 3: (doesn't have much storage)

It usually takes 5-ish rounds of helm-install , helm-uninstall, delete pvcs, helm-install to get all my affinity+antiAffinity rules perfect such that the scheduling puts the pods in this order:

Node 1: with storage
- elasticsearch (affinity node1)
- postgresql  (affinity node1)

Node 2:
- operate (antiAffinity away from node1)
- zeebe (antiAffinity away from node1)

Node 3: 
- tasklist (antiAffinity away from node1)
- optimize (antiAffinity away from node1)
- connectors (antiAffinity away from node1)

With a layered approach, then the database storage could be installed first, and the affinity rules put it on the right nodes, and the other pods wouldn't need antiaffinity rules to be scheduled.

Another point is that often customers come to us with logs about why one component fails and they can't see the dependency tree that is apparent in my head. If I had this, Layer 1 would be postgresql, and keycloak . Layer 2 would be zeebe, Layer 3 would be anything that depends on zeebe, like operate. It would always be clear what would need to be debugged first.

I definitely see the challenges in implementing this, though.

@jessesimpson36
Copy link
jessesimpson36 commented Mar 20, 2025

Third thought, extending on the above. Helm must consider upgrades as much as installs. Maintaining and upgrading software Day 2 is almost always harder than installing on Day 1. IMHO, a single package should always be subject to a single operation (install and upgrade) ie. all layers would be upgraded to a new chart version in a single Helm operation. Whereas, and IMHO especially if orchestrated by higher level software, a chart with ordered sub-chart dependencies could be updated progressively/independently e.g. db the blue/green the app layer.

My view is that installations could be layered, and upgrades could throw all the manifests at the server all at once (if it makes the problem any simpler to implement). The layered approach doesn't matter as much for upgrades because if I have a dependency (layer 2) that is out-of-date with the database version (layer 1), then pods in layer 2 are already going to be crashlooping.

@scottrigby
Copy link
Member

@gjenkins8 I wanted to reply to your three thoughts here #375 (comment)

  1. Better UX

    First thought, is I think we should certainly support something with much better UX than using annotations as H4HIP: Helm Sequencing Proposal #373 proposes. For example, representing resource sets (or "layers") in separate directories (though I'm sure there is a better way out there than this example). Where the user can easily identify / support different resource sets, and their order without hunting through annotations in templates. I think H4HIP: Helm Sequencing Proposal #373 proposes annotations as that is perhap the only option for Charts V2 API as we have today.

    I agree that grouping a chart's resource templates in directories under /templates can be useful for end users—especially a complex chart for an app that includes many resources. You can do that today with Helm 3, and some charts do this.

    I don't think it would help very simple charts with fewer resources—in those cases, I think seeing them flat is easier for an end user—IMO this is probably why most charts do this. So I'm not sure that this would be a good replacement for the annotations idea for sequencing resources within the same chart.

    I also don't think this would be a misuse of annotations. In our "Labels and Annotations" docs page, under "Is it a Label or an Annotation?" we say:

    If an item of metadata is not used for querying, it should be set as an annotation instead [of a label].

    Kubernetes docs give some examples of information that could be recorded in annotations, including these example, which I think describe our use case:

    • "Lightweight rollout tool metadata: for example, config or checkpoints"
    • "Directives from the end-user to the implementations to modify behavior or engage non-standard features"

    But I do think grouping resource sets (or "layers") in separate directories could be nice to optionally pair with the annotations in the sequencing HIP. Perhaps that HIP can suggest encouraging this by making a "advanced-sequencing" --starter scaffold example for helm create. What do you think?

  2. Overlap between ordered installation of resources within a chart, and ordered installation of subcharts within a parent chart

    Second thought, is that options 1. and two 2. ie. layers within a chart, or ordering sub-charts are not necessarily exclusive. But obviously they do occupy a large portion of the same solution space. The differences is perhaps whether Helm want to allow users to compose different charts into an "application". But that also might mean artificially breaking a chart into several pieces to support ordering (as describe above). There also might also be a middle group,

    I agree these fill similar use cases. However I also agree with the above statements that if resources groupings for sequencing are required to be in separate charts or subcharts, charts would need to be broken up into multiple charts in an un-natural manner, which I think is not ideal if we can offer a better solution. Therefore, I think we do need both of these use cases:

    • Allow chart authors to specify ordering RESOURCES WITHIN A SINGLE CHART
    • Allow chart authors to specify ordering SUBCHARTS WITHIN A PARENT CHART

    Helm 3 already allows the first use case for hook resources, when they're paired with hook-weight, and loops through those in order, waiting for each to be ready before the next one is installed. This is essentially what the sequencing HIP is proposing we allow for normal resources as well. It's just suggesting a more manageable way of specifying the order than numeric weights on each resource—proposing instead a dynamic DAG that includes resource grouping to accommodate charts for an app with many resources.

    Helm 3 does not yet allow the second use case. I think this one is the easiest to reason about. This second use case however also allows the first use case to remain well scoped—if you can also specify subchart installation order, then it very clearly makes sense to ONLY allow ordering of individual/grouped resources within a single chart. I agree with @mattfarina, that:

    What happens when subcharts introduce layers of their own and there is one large shared sandbox? How will the calculated layers work together and be easily debugged? There be dragons in this area.

    Let's avoid the dragons by defining the scope to NOT consider allowing sequencing individual/grouped resources outside of a single chart—ie, not between parent resources and subcharts, or between subcharts, etc. Those needs can be handled by the second use case. OR as Matt said, by other tools in the ecosystem that allow sequencing the installation order of separate charts. And I also agree with Matt that end users can decide at that point whether those other charts make the most sense as subcharts or as separately installed charts—and that the main deciding factor is likely to be whether or not they want to be able to upgrade those charts separately. I think each of these use cases are clear and can work in concert as needed.

  3. Day 2 considerations: upgrades as well as initial installs

    Third thought, extending on the above. Helm must consider upgrades as much as installs. Maintaining and upgrading software Day 2 is almost always harder than installing on Day 1. IMHO, a single package should always be subject to a single operation (install and upgrade) ie. all layers would be upgraded to a new chart version in a single Helm operation. Whereas, and IMHO especially if orchestrated by higher level software, a chart with ordered sub-chart dependencies could be updated progressively/independently e.g. db the blue/green the app layer.

    I agree this should apply equally to upgrades as installs. And under your second thought above I noted the user can decide whether or not to use separate charts or subcharts (main different being separate charts allow independent upgrades). I think the use cases above can be optional with each of these desired scenarios.

    Also, in reply to @jessesimpson36 about this:

    My view is that installations could be layered, and upgrades could throw all the manifests at the server all at once (if it makes the problem any simpler to implement). The layered approach doesn't matter as much for upgrades because if I have a dependency (layer 2) that is out-of-date with the database version (layer 1), then pods in layer 2 are already going to be crashlooping.

    The sequencing HIP makes this ordering opt-in by the end user. Currently it proposed that the --wait flag will trigger the wait behavior if the chart specifies sequencing. When --wait is passed, each sequenced layer—and/or subchart—will wait for the last to be ready before moving onto the next one (like hook-wait does today for individual hook resources). If --wait is not passed, this waiting behavior will not be triggered. This means that—in Jesse's example—an end user could choose to install with --wait, but upgrade without it if they don't want this behavior.

@jessesimpson36
Copy link

The sequencing HIP makes this ordering opt-in by the end user. Currently it proposed that the --wait flag will trigger the wait behavior if the chart specifies sequencing. When --wait is passed, each sequenced layer—and/or subchart—will wait for the last to be ready before moving onto the next one (like hook-wait does today for individual hook resources). If --wait is not passed, this waiting behavior will not be triggered. This means that—in Jesse's example—an end user could choose to install with --wait, but upgrade without it if they don't want this behavior.

This approach of only using --wait and specifying the dependencies in this directed acyclic graph through annotations makes a lot of sense to me. I also read the current state of the HIP and it all looks good for the use case that I would want it for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
0