Helm
Kubernetes
Configuration Management
DevOps
Variable Handling

How to make nested variables optional in Helm

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Understanding Nested Variables in Helm

Helm is a popular package manager for Kubernetes that simplifies the deployment and management of applications in a Kubernetes cluster. One of the core concepts in Helm is the use of templates, which allow you to create customizable and dynamic YAML files. A significant feature of Helm templates is their ability to handle complex configurations using nested variables. However, handling nested variables can sometimes be cumbersome, especially when you want to make some of them optional. This article explores various techniques to make nested variables optional in Helm, enhancing flexibility and ease of configuration.

YAML and Templates in Helm

To understand the need for optional nested variables, consider how configurations are structured in Helm charts. In Helm, your configuration typically resides in the values.yaml file:

yaml
1service:
2  type: ClusterIP
3  port: 80
4  annotations:
5    prometheus.io/scrape: "true"
6    prometheus.io/port: "80"

Here, annotations are nested under service. These nested variables add complexity but are also powerful in configuring your application.

Making Nested Variables Optional

While working with Helm, you might want some of these nested variables to be optional. For instance, what if you want the annotations to be user-configurable or completely removable?

Technique 1: Using default Function

Helm provides a default function that allows you to specify default values if the variable is not set:

yaml
annotations:
  prometheusScrape: {{ .Values.service.annotations.prometheusScrape | default "false" }}
  prometheusPort: {{ .Values.service.port | default "80" }}

Here, default is used to provide a fallback value for missing keys, ensuring that the template doesn't fail due to unset variables.

Technique 2: Conditional Logic with if Statements

Alternatively, you can use conditional statements to determine whether a nested variable should be added to the template:

yaml
1annotations: 
2    {{- if .Values.service.annotations }}
3      prometheusScrape: {{ .Values.service.annotations.prometheusScrape | default "false" }}
4    {{- end }}

In this case, the block within if only executes if annotations exist under service, making the entire construct optional.

Example: Making Annotations Fully Optional

Consider the full service template where annotations are optional:

yaml
1apiVersion: v1
2kind: Service
3metadata:
4  name: my-service
5  annotations:
6    {{- if .Values.service.annotations }}
7    {{- toYaml .Values.service.annotations | nindent 4 }}
8    {{- end }}
9spec:
10  type: {{ .Values.service.type | default "ClusterIP" }}
11  ports:
12    - port: {{ .Values.service.port | default 80 }}

In this example, the block under annotations is only added if annotations exist in values.yaml. The toYaml function, along with nindent, formats the annotations correctly, ensuring proper YAML indentation.

Best Practices

When dealing with nested variables in Helm, follow these guidelines:

  • Use Defaults: Use default values to avoid runtime errors.
  • Conditional Logic: Employ if conditions to make sections optional.
  • Tidy Templates: Keep templates clean and readable by avoiding deep nesting of logic.
  • Document Defaults: Clearly document default values and expected configurations for easier maintenance.

Quick Reference

  • Use default when an individual nested value should fall back to something safe.
  • Use if when an entire block should disappear if the parent value is missing.
  • Use toYaml with nindent when you want to render an optional nested map cleanly.

Conclusion

Handling nested variables in Helm templates becomes significantly easier when employing techniques to make these variables optional. By leveraging functions such as default and employing conditional logic carefully, you can craft flexible Helm charts that cater to a wide range of configurations. Adhering to best practices will ensure that your charts remain robust, maintainable, and easy to understand.

This article has detailed the methods to address optional nested variables, but thorough testing and good documentation are essential when implementing these concepts in real-world Helm charts, as they enhance predictability and usability.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.