# Customizing Helm Charts

## Customizing Helm Charts

Helm charts offer a powerful way to deploy applications in Kubernetes, but the real strength of Helm lies in its ability to customize these deployments to meet specific needs. Whether you’re deploying a chart to different environments (e.g., development, staging, production) or tailoring an application to your unique requirements, customizing Helm charts is a crucial skill. In this lesson, we will explore how to modify Helm charts using various techniques, such as overriding values, utilizing the `values.yaml` file, and creating custom templates. By the end of this lesson, you'll have the knowledge and tools to tailor Helm charts to your exact specifications.

## **The Role of `values.yaml` in Customization**

The `values.yaml` file is the cornerstone of Helm chart customization. It contains default configuration values that define how the chart will be deployed. By modifying this file or overriding its values during installation, you can easily customize the behavior of the chart.

### **Default Values in `values.yaml`**

Every Helm chart comes with a `values.yaml` file that specifies default values for various configuration options. These options typically include settings for the application’s image, number of replicas, service type, resource limits, and more.

**Example `values.yaml`:**

```yaml
replicaCount: 2
image:
  repository: nginx
  tag: 1.16.0
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80
```

* **`replicaCount`**: Specifies the number of replicas for the deployment.
* **`image`**: Defines the Docker image repository, tag, and pull policy.
* **`service.type`**: Determines the type of Kubernetes service (e.g., `ClusterIP`, `NodePort`).

**Overriding Values from the Command Line**

One of the simplest ways to customize a Helm chart is to override values in the `values.yaml` file using the `--set` flag during installation or upgrade.

**Example of Overriding Values:**

```bash
helm install my-app bitnami/nginx --set replicaCount=3 --set service.type=NodePort
```

* **`replicaCount=3`**: Overrides the default replica count to 3.
* **`service.type=NodePort`**: Changes the service type to `NodePort`.

This approach is particularly useful for making quick adjustments without modifying the chart’s files directly.

**Using a Custom Values File**

For more complex customizations, you can create your own `values.yaml` file and pass it to Helm during installation or upgrade.

**Creating a Custom `values.yaml`:**

```yaml
replicaCount: 4
image:
  repository: custom-nginx
  tag: 1.17.0
service:
  type: LoadBalancer
  port: 8080
```

**Applying the Custom Values File:**

```bash
helm install my-app bitnami/nginx -f my-values.yaml
```

Using a custom values file allows for greater flexibility and makes it easier to manage configurations across different environments.

### **Customizing Templates with Go Templating**

Helm uses Go templating to render Kubernetes manifests, which means you can customize the templates themselves to achieve more dynamic behavior.

### **Understanding Go Templating in Helm**

Go templating allows you to introduce logic into your Kubernetes manifests. You can use variables, conditionals, loops, and more to create highly customizable templates.

**Example of a Simple Go Template:**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
      - name: {{ .Release.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        ports:
        - containerPort: 80
```

* **`{{ .Release.Name }}`**: Refers to the name of the Helm release.
* **`{{ .Values.replicaCount }}`**: Inserts the value for `replicaCount` from `values.yaml`.

**Adding Conditionals**

You can add conditionals to templates to include or exclude certain resources or configuration options based on specific conditions.

**Example of Using a Conditional:**

```yaml
spec:
  containers:
    - name: {{ .Release.Name }}
      image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
{{- if .Values.resources }}
      resources:
        limits:
          cpu: {{ .Values.resources.limits.cpu }}
          memory: {{ .Values.resources.limits.memory }}
{{- end }}
```

* **`{{- if .Values.resources }}`**: The resources section is only included if resource limits are defined in `values.yaml`.

**Using Loops**

Loops can be used to dynamically generate multiple resources or configuration entries based on a list of values.

**Example of a Loop in a Template:**

```yaml
env:
{{- range .Values.env }}
  - name: {{ .name }}
    value: {{ .value }}
{{- end }}
```

* **`{{- range .Values.env }}`**: Loops over each item in the `env` list and generates an environment variable entry.

### **Managing Dependencies**

Helm charts can depend on other charts, known as sub-charts. Managing dependencies allows you to build more complex applications from smaller, reusable components.

**Defining Dependencies in `Chart.yaml`**

You can specify chart dependencies in the `Chart.yaml` file. Dependencies are other Helm charts that your chart relies on, and they are stored in the `charts/` directory.

**Example of Dependencies in `Chart.yaml`:**

```yaml
dependencies:
  - name: redis
    version: 6.0.1
    repository: https://charts.bitnami.com/bitnami
```

* **`name: redis`**: Specifies the name of the dependent chart.
* **`version: 6.0.1`**: The version of the redis chart to use.
* **`repository`**: The repository from which to download the chart.

**Using the `requirements.yaml` File (Deprecated)**

In older versions of Helm (v2), dependencies were managed in a `requirements.yaml` file. While Helm v3 no longer uses this file, it’s important to be aware of it if you’re working with legacy charts.

**Example `requirements.yaml`:**

```yaml
dependencies:
  - name: redis
    version: 6.0.1
    repository: https://charts.bitnami.com/bitnami
```

Dependencies defined in `Chart.yaml` are automatically downloaded and placed in the `charts/` directory when you run `helm dependency update`.

**Managing Dependencies with `helm dependency`**

Helm provides commands to manage dependencies, such as updating, listing, and adding them.

**Updating Dependencies:**

```bash
helm dependency update
```

**Listing Dependencies:**

```bash
helm dependency list
```

These commands ensure that your chart has all the necessary components to function correctly.

### **Hands-on Example: Customizing an Nginx Chart**

To apply what you’ve learned, let’s customize an Nginx Helm chart:

**Steps:**

1. **Download the Chart**:

   ```bash
   helm pull bitnami/nginx --untar
   ```
2. **Edit the `values.yaml` File**: Modify the `values.yaml` to change the number of replicas and the service type.

   ```yaml
   replicaCount: 4
   service:
     type: NodePort
   ```
3. **Edit the `deployment.yaml` Template**: Add a conditional to include resource limits only if specified.

   ```yaml
   resources:
     {{- if .Values.resources }}
     limits:
       cpu: {{ .Values.resources.limits.cpu }}
       memory: {{ .Values.resources.limits.memory }}
     {{- end }}
   ```
4. **Install the Chart with Custom Values**:

   ```bash
   helm install my-custom-nginx ./nginx -f custom-values.yaml
   ```
5. **Verify the Deployment**: Check that the customizations were applied correctly.

   ```bash
   helm status my-custom-nginx
   ```

This example walks you through customizing a Helm chart by modifying `values.yaml` and templates, allowing you to tailor the deployment to specific requirements.

## **Summary**

Customizing Helm charts is a powerful way to adapt Kubernetes deployments to meet your specific needs. By understanding how to modify the `values.yaml` file, use Go templating, and manage dependencies, you can create highly tailored and dynamic Kubernetes applications. Mastering these techniques will allow you to deploy complex applications with precision and flexibility.
