How to use One Helm Chart for EKS and GKE

Today’s Agenda :
  • How to use One Helm Chart for EKS and GKE

  • Kubernetes RBAC Best Practices and Tooling Collection

  • Useful Git Shortcuts and Autocomplete for Windows Bash Terminal

  • Red Hat OpenShift GitOps 1.12: Key Updates and Enhancements

  • Google Cloud Functions and Docker Engine Critical Flaws Exposed

Read Time: 4 minutes

How to use One Helm Chart for EKS and GKE

Namasthe 🙏 TechOps Soldiers !

I get this question a lot: "Can we use a single Helm chart for both EKS and GKE?"

The answer is a resounding yes!

Today, I'm going to walk you through how to do just that with a real-world example of an e-commerce application called ecom-app.

First, let's break down the sample structure of a Helm chart and understand the role of each file.

Helm Chart Structure

Now, let's dive into the actual code that makes all this happen.

chart.yaml:

This file is like the blueprint of our Helm chart. It gives Kubernetes all the information it needs about our chart.

apiVersion: v2
name: ecom-app
description: A Helm chart for a production-grade e-commerce application
type: application
version: 1.0.0
appVersion: "1.0"

values.yaml:

Here, we define the default configuration values. These are the settings that work for both EKS and GKE unless overridden.

replicaCount: 3

backend:
  image:
    repository: ecom-app/backend
    tag: "1.0.0"
    pullPolicy: Always

frontend:
  image:
    repository: nginx
    tag: "1.19.0"
    pullPolicy: IfNotPresent

service:
  type: LoadBalancer
  port: 80

ingress:
  enabled: true
  annotations: {}
  hosts:
    - host: ecom.example.com
      paths: 
        - /

resources:
  requests:
    memory: "256Mi"
    cpu: "100m"
  limits:
    memory: "512Mi"
    cpu: "200m"

nodeSelector: {}
tolerations: []
affinity: {}

persistence:
  enabled: true
  accessMode: ReadWriteOnce
  size: 10Gi

deployment-backend.yaml:

This template is for deploying our backend service. It ensures our backend containers run smoothly, with all the necessary configurations.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "ecom-app.fullname" . }}-backend
  labels:
    app: {{ include "ecom-app.name" . }}
    tier: backend
    release: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ include "ecom-app.name" . }}
      tier: backend
      release: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ include "ecom-app.name" . }}
        tier: backend
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: backend
          image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}"
          imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 20
          resources:
            requests:
              memory: {{ .Values.resources.requests.memory }}
              cpu: {{ .Values.resources.requests.cpu }}
            limits:
              memory: {{ .Values.resources.limits.memory }}
              cpu: {{ .Values.resources.limits.cpu }}

deployment-frontend.yaml:

Our frontend service uses Nginx. This deployment template handles all the settings needed to run our frontend containers.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "ecom-app.fullname" . }}-frontend
  labels:
    app: {{ include "ecom-app.name" . }}
    tier: frontend
    release: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ include "ecom-app.name" . }}
      tier: frontend
      release: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ include "ecom-app.name" . }}
        tier: frontend
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: frontend
          image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
          imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
          ports:
            - containerPort: 80

service.yaml:

This template sets up the Kubernetes Service. It defines how our application will be accessible over the network.

apiVersion: v1
kind: Service
metadata:
  name: {{ include "ecom-app.fullname" . }}
  labels:
    app: {{ include "ecom-app.name" . }}
    release: {{ .Release.Name }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: 80
  selector:
    app: {{ include "ecom-app.name" . }}
    release: {{ .Release.Name }}

ingress.yaml:

Ingress resources control external access to our services. This template handles the settings needed to expose our application outside the Kubernetes cluster.

{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "ecom-app.fullname" . }}
  annotations:
    {{- range $key, $value := .Values.ingress.annotations }}
      {{ $key }}: {{ $value | quote }}
    {{- end }}
spec:
  rules:
    {{- range .Values.ingress.hosts }}
    - host: {{ .host }}
      http:
        paths:
          {{- range .paths }}
          - path: {{ . }}
            pathType: Prefix
            backend:
              service:
                name: {{ include "ecom-app.fullname" $ }}
                port:
                  number: 80
          {{- end }}
    {{- end }}
{{- end }}

pvc.yaml:

This template defines the PersistentVolumeClaim, which is used to request storage resources in Kubernetes.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: {{ include "ecom-app.fullname" . }}-pvc
  labels:
    app: {{ include "ecom-app.name" . }}
    release: {{ .Release.Name }}
spec:
  accessModes:
    - {{ .Values.persistence.accessMode }}
  resources:
    requests:
      storage: {{ .Values.persistence.size }}

_helpers.tpl:

This file contains reusable code snippets. It helps keep our templates DRY (Don't Repeat Yourself) by providing common functions.

{{- define "ecom-app.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "ecom-app.fullname" -}}
{{- printf "%s-%s" .Release.Name (include "ecom-app.name" .) | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "ecom-app.chart" -}}
{{- .Chart.Name | replace "-" " " | title | replace " " "-" -}}
{{- end -}}

values-eks.yaml:

These are the settings specific to EKS. They override the defaults in values.yaml to suit AWS's Kubernetes service.

replicaCount: 3

service:
  type: LoadBalancer

persistence:
  storageClass: gp2

resources:
  requests:
    memory: "512Mi"
    cpu: "200m"
  limits:
    memory: "1Gi"
    cpu: "500m"

values-gke.yaml:

Similarly, these are the settings specific to GKE. They make sure our application runs smoothly on Google's Kubernetes service.

replicaCount: 3

service:
  type: LoadBalancer

persistence:
  storageClass: standard

resources:
  requests:
    memory: "512Mi"
    cpu: "200m"
  limits:
    memory: "1Gi"
    cpu: "500m"

Ready to deploy? Here’s how you can get your e-commerce app up and running on both EKS and GKE.

To deploy on EKS:

helm install ecom-app ./ecom-app -f values-eks.yaml

To deploy on GKE:

helm install ecom-app ./ecom-app -f values-gke.yaml

By using this structure and configuration, you can efficiently manage your Kubernetes deployments across both EKS and GKE with a single Helm chart.

Happy deploying!

📖 Resources & Tutorials

📈 Trends & Updates

The ConfusedFunction vulnerability in Google Cloud Functions allows attackers to escalate privileges and access sensitive data. Google's recent updates mitigate the issue for new deployments, but existing instances remain vulnerable.

The 1.12 release of Red Hat OpenShift GitOps introduces ArgoCD CLI support, enhanced NotificationsConfiguration, and critical fixes for TLS policies and secure authentication. These updates improve automation, security, and user experience for cloud-native deployments.

Docker has identified a critical vulnerability, CVE-2024-41110, allowing attackers to bypass authorization plugins and escalate privileges in certain versions of Docker Engine. With a maximum CVSS score of 10.0, this flaw has been patched in recent updates, and users are urged to upgrade to prevent potential exploits.

Want To Advertise in TechOps Examples ?

Our newsletter puts your products and services in front of the right people - engineering leaders and senior engineers - who make important tech decisions and big purchases.

Did someone forward this email to you? Sign up here