Helm Best Practices to Scale Your Self-Hosted Enterprise Software Distribution: Templating Essential Properties

Diamon Wiggins, Chuck D'Antonio, Kaylee McHugh
 | 
Jan 23, 2025

Part of what makes Helm so valuable is that it is incredibly flexible. Consumers of your chart may need to modify different aspects of how your application is deployed based on the tools and supporting infrastructure they have running inside of their clusters, and Helm allows you to address this. However, unless you have years of experience working with Helm, this flexibility can also make it difficult to decipher the best way to set up your charts. To help with this, Diamon Wiggins, Staff Engineer at Replicated, outlines Helm Best Practices specifically for ISVs deploying into self-hosted customer environments. In this blog, he describes best practices for templating essential properties. 

You can watch his walkthrough, or read the Best Practices below. 

Best Practice #1 - Add Labels and Annotations

This is essential for well-organized Helm charts. Many tools in the Kubernetes ecosystem, like Velero and Prometheus, operate based on labels and annotations applied to workloads. Many organizations will also have requirements around labels and annotations and enforce these with runtime policies. If your users don't label and annotate your workloads, they may not be able to run your application.

Best Practice #2 - Allow the Image Properties to Be Configured 

Users may need to push your images to their own registry, in which case they need to change the registry and/or tag of the images inside the Helm chart. Modifying the image tag can be useful for debugging and development. Users who need to modify the registry will also probably need to modify the image pull secrets to authenticate against a different registry. 

A good example of when you’d need to override the image properties is when integrating with the Replicated platform. When you’re supporting Embedded Cluster installs and you’re using our proxy registry to access images in a private registry, you’ll need to override the registry and repository in your kind: HelmChart resource with the necessary template to dynamically determine the image name. 

Best Practice #3 - Make the Security Context Configurable 

Users may need to modify the security context to meet the cluster specific policies and constraints. This is commonly seen in environments like OpenShift where security policies are more strict by default compared to other Kubernetes distributions. For instance, OpenShift often enforces the use of non-root users for pods, which may require setting the runAsUser and fsGroup explicitly, as shown in the example.

Best Practice #4 - Make Scheduling and Node Affinity Configurable 

Node selectors, affinity/anti-affinity, and tolerations are also important for controlling how your application is scheduled in a Kubernetes cluster, and it’s important to make these configurable. For example, there may be specific nodes with hardware that your application requires, and users may need a way to tell parts of your application to run on those specific nodes.

Or, users may need to leverage affinity rules to determine how applications like Postgres are distributed across the cluster.  Users may want to ensure that replicas of stateful application  databases like Postgres are spread out across multiple failure domains, like availability zones, to guarantee some fault tolerance. 

Best Practice #5 - Make the Kubernetes Services Configurable 

We've already discussed the general usefulness of labels and annotations that again applies here, but it's also important to consider making the service type configurable. 

Some users may prefer a load balancer or service type, while others may opt for a nodePort if the automation to create a load balancer is unavailable.  We think it's helpful to expose that service type configuration, and it's also helpful to allow the nodePort value itself to be configurable in case someone doesn't want to use the default value that's assigned dynamically whenever you create a nodePort service. 

Best Practice #6 - Make the Ingress Configurable 

Consumers of the chart may need to set a specific ingress class to match the cluster’s configuration as with other Kubernetes resources, labels, and annotations. Annotations in particular are really the primary method for how you configure ingress.

Additionally, users may need to control the TLS configuration to manage secure access to the application. In this snippet here, you can see in the TLS section that you might also consider  adding a really quick way for someone to turn TLS on, and then just get a self signed cert that you generate inside of the chart. 

Best Practice #7 - Allow Users to Reference Existing Kubernetes Objects 

Lastly, a common pattern is allowing users to reference existing Kubernetes objects like secrets or service accounts. This approach is particularly useful for organizations with existing infrastructure or strict security policies. For example, users may want to provide an existing secret for credentials if they are externally managing a dependency of the application, like a database or a message broker. In such cases, it’s important to explicitly offer values for both options—using an existingSecret for credentials and specifying an existing service account with predefined roles—to ensure the solution works seamlessly in environments with stricter RBAC policies. 

If you’re interested in scaling the distribution of your enterprise application into self-hosted environments using Helm Charts, Replicated can help. Request a demo today.