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

Postgres rework #3

Open
rainest opened this issue Sep 5, 2024 · 1 comment
Open

Postgres rework #3

rainest opened this issue Sep 5, 2024 · 1 comment

Comments

@rainest
Copy link
Owner

rainest commented Sep 5, 2024

Import or roll your own

Postgres is currently part of the OCHAMI chart itself. We may want to consider other options here.

The same considerations here should apply to most commodity applications we include, though Postgres is the one I'm most familiar with.

Keep the in-tree Postgres templates

Keeping the current in-tree Postgres templates doesn't require much work now because it's already there. Future feature development and upgrades to keep up with new Kubernetes features are, however, on us. Doing so probably outweighs the burden of keeping up with third-party configuration, with the expectation that we won't configure too much in the default values,yaml

Customization is difficult

Maintaining our own templates with limited configuration surface can provide a more consistent experience, but IME we'll eventually have some users that need to change something we don't expose. Unfortunately, Helm's options for modifying outputs without values.yaml support are limited:

  • Three-way merge should maintain changes to resources (running kubectl edit on something installed by the chart) for the life of the release. I haven't used this extensively, however, and expect it has edge cases.
  • Post-rendering allows arbitrary modification of template output, but it's very arbitrary, in that it's essentially a direct pipe of output to something that can parse and modify it. I'd like to see first-class support for Kustomize, but there don't appear to be any ongoing efforts to add this

Because neither option can be released with the chart and used with the standard Helm client (much less CD system Helm integrations), convincing users to use them is difficult.

Though there are no formal plans to add other first-party customization methods that I know of, extended Kustomize support did come up during KubeCon 2024 EU discussions around a Helm 4 roadmap.

Should probably use a StatefulSet

Postgres uses persistent storage and thus should probably use a StatefulSet. It currently uses a Deployment.

Offhand I'm not sure how this affects storage interactions--I've never tried. Brief review of others' discussion suggests Deployment use would not play nice with Postgres' replication protocols.

Assume Postgres will run elsewhere

My previous experience with "batteries included" chart design that deploys both the main application and database dependencies was that it was generally inadvisable. It added complications for lifecycle management (Helm has only defined ephemeral pre- and post- phases outside the "main" resources, which creates a chicken/egg problem if you want to, for instance, run schema initialization before install--Postgres won't actually be running yet), and we recommended against using the built-in database outside demo environments.

IME most users preferred to use managed database options from their IaaS provider, as running your own stateful applications in Kubernetes complicates the environment without much benefit.

We probably should support external databases (you provide credentials and a URL in values.yaml and the chart assumes it'll find a database there) regardless, but removing in-chart support entirely could simplify development.

Providing a separate opinionated batteries-included umbrella chart for quick test installs is an option, though I don't have experience doing this myself.

Use a third-party subchart

As Postgres is a fairly standard application, we should consider using a stock chart. AFAIK Postgres does not maintain their own first-party chart, but Bitnami does maintain a 3rd-party chart that's reasonably feature rich.

I used this chart (and its container image, which is also maintained by Bitnami) previously for deploying Postgres-backed Kong, so I have familiarity with the challenges involved.

Upgrade burden

While the Bitnami chart generally does not get in your way (it and most Bitnami charts follow a simple "align values.yaml with the underlying resources" approach to UX), it does (or did) move a bit fast.

While there's nothing stopping you from just using an older version for a while, making use of the latest features may require a fair amount of 3rd-party config janitoring, with upgrade procedures that aren't always clear.

I don't believe they have the notion of an LTS.

Subcharts aren't perfect

Bundling this chart (or any chart) with our chart requires using it as a subchart. This is essentially a package dependency, but without a thoroughly designed package workflow.

Helm's subchart system isn't particularly robust, and there's not really a defined mechanism to pass information between charts and subcharts. AFAIK subchart values have to be set directly from values.yaml subsections: you cannot, for example, use the output of a template in the parent chart to set a value in the subchart.

Helm has global variables that extend across both parents and subcharts, but subcharts have to intentionally use them. As such, global variables are somewhat limited to use by charts and subcharts all produced by the same party. Bitnami is at least aware of this limitation, so they provide hook points (for example, they will read .Values.global.postgresql.auth.username and similar if the parent sets it).

Kong charts previously used loose coupling instead of these globals--effectively we relied on expected Service/Deployment/etc. names from the subchart and had parent chart templates generate them where needed.

Helm also exposes (perhaps not entirely intentionally) templates globally, so you can utilize subcharts' templates within the parent. However, those templates will work exactly as they would normally, so templates that attempt to access values via global paths will get lost (if your subchart template wants .Values.foo.bar and that key is actually .Values.subchart.foo.bar for the parent chart, sadness happens). Designing templates to never expect global context (to instead always expect to be invoked via with and a local context) can help with this, but the language won't enforce it. You can maybe force it by invoking with a constructed dict combining their expected global context.

@xeruf
Copy link

xeruf commented Dec 14, 2024

I only got here through the backlink from bitnami and have no idea what this project is about, but this is a great overview! Thanks for taking the time to write this!

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

2 participants