Logo AppDev24 Login / Sign Up
Sign Up
Have Login?
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Login
New Account?
Recovery
Go to Login
By continuing you indicate that you agree to Terms of Service and Privacy Policy of the site.
Kubernetes

Github Pages as Helm Chart Repository

Updated on Nov 11, 2024

Helm, a powerful package manager for Kubernetes, simplifies application deployment and management. GitHub Pages provides an easy and free hosting solution for Helm charts. This guide will walk you through setting up a Helm chart repository using GitHub Pages and uploading your charts.

GitHub offers a comprehensive solution for managing Kubernetes applications. By leveraging GitHub Pages for Helm charts and GitHub Container Registry for Docker images, you can centralize your application assets and automate your deployment workflows. This GitHub-centric approach creates a robust GitOps pipeline, streamlining development, deployment, and dependency management.

Create a simple Flask Application

To demonstrate this setup, let’s start with a minimal web application built with Flask. The application will be packaged and deployed via Helm charts.

app.py

import json
from flask import Flask, jsonify

app = Flask(__name__)

products = [
    { 'id': 1, 'name': 'Cakes' },
    { 'id': 2, 'name': 'Cookies' },
    { 'id': 3, 'name': 'Chocolates' },
    { 'id': 4, 'name': 'Milk' },
    { 'id': 5, 'name': 'Coffee' },
    { 'id': 6, 'name': 'Soft Drinks' },
    { 'id': 7, 'name': 'Ice cream' }
]

@app.route('/api/products', methods=['GET'])
def get_products():
    return jsonify(products)


if __name__ == '__main__':
   app.run(debug=True)

This application provides a simple API endpoint (/api/products) that returns a list of products, making it ideal for testing Helm and Docker integration.

requirements.txt

This file specifies the Python dependencies needed for the Flask application.

flask

Containerize the Flask Application

Now, we’ll create a Docker image for the Flask app to ensure consistent behavior across environments.

Dockerfile

The Dockerfile specifies the instructions for creating the Docker image.

# syntax=docker/dockerfile:1

FROM python:3.12.4-slim
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip3 install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD [ "python", "-m" , "flask", "run", "--host=0.0.0.0"]

This Dockerfile uses a lightweight Python base image, sets up a working directory, installs Flask, exposes port 5000, and runs the app.

Create Helm Chart for the Application

To package the application for Kubernetes deployment, we'll create a Helm chart. Use the Helm command to generate a new chart.

helm create charts/python-api

This command generates a Helm chart structure. We’ll keep only the relevant files for this setup:

python-api/
├── Chart.yaml
├── values.yaml
└── templates/
    ├── deployment.yaml
    └── service.yaml
    └── ingress.yaml

Chart.yaml

Chart.yaml includes the chart’s name, description, version, and application version. These fields provide essential metadata for Helm.

apiVersion: v2
name: python-api
description: A Helm chart for python-api demo
type: application
version: 0.1.1
appVersion: "0.1.1"
maintainers:
  - name: sarubhai
    email: saurav.karate@gmail.com
keywords:
  - helm-ghcr-gh-pages-demo
  - python-api-demo

values.yaml

This YAML file configures the Helm chart, with default values including details like replica count, service type, and ingress.

replicaCount: 1
imagePullSecrets: []
image:
  repository: ""
  tag: ""
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  className: ""
  annotations: {}
  
  hosts:
    - host: python-api.local
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: python-api-tls
      hosts:
        - python-api.local

deployment.yaml

This YAML file defines the deployment of the Flask application on Kubernetes, specifying the number of replicas and container image

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-api-deployment
  labels:
    app: python-api-deployment
    app.kubernetes.io/name: python-api-deployment
    app.kubernetes.io/version: v1.0
spec:
  replicas: \{\{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: python-api
      app.kubernetes.io/name: python-api
  template:
    metadata:
      labels:
        app: python-api
        app.kubernetes.io/name: python-api
    spec:
      \{\{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        \{\{- toYaml . | nindent 8 }}
      \{\{- end }}
      containers:
      - name: python-api
        image: "\{\{ .Values.image.repository }}:\{\{ .Values.image.tag }}"
        imagePullPolicy: \{\{ .Values.image.pullPolicy }}
        ports:
        - containerPort: 5000
          name: flask
          protocol: TCP

service.yaml

This YAML file defines a Kubernetes service that exposes the Flask application through a port.

apiVersion: v1
kind: Service
metadata:
  name: python-api-service
  labels:
    app: python-api-service
    app.kubernetes.io/name: python-api-service
    app.kubernetes.io/version: v1.0
spec:
  type: \{\{ .Values.service.type }}
  selector:
    app: python-api
  ports:
  - name: http
    protocol: TCP
    port: \{\{ .Values.service.port }}
    targetPort: 5000

ingress.yaml

This YAML file defines an Ingress resource that provides an external entrypoint for the application through a hostname and path.

\{\{- if .Values.ingress.enabled -}}
\{\{- $svcPort := .Values.service.port -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: python-api-ingress
  namespace: backend-api
  labels:
    app: python-api-ingress
    app.kubernetes.io/name: python-api-ingress
    app.kubernetes.io/version: v1.0
  \{\{- with .Values.ingress.annotations }}
  annotations:
    \{\{- toYaml . | nindent 4 }}
  \{\{- end }}
spec:
  ingressClassName: \{\{ .Values.ingress.className }}
  rules:
  \{\{- range .Values.ingress.hosts }}
  - host: \{\{ .host }}
    http:
      paths:
      \{\{- range .paths }}
      - backend:
          service:
            name: python-api-service
            port:
              number: \{\{ $svcPort }}
        path: \{\{ .path }}
        pathType: \{\{ .pathType }}
      \{\{- end }}
  \{\{- end }}
  \{\{- if .Values.ingress.tls }}
  tls:
  \{\{- range .Values.ingress.tls }}
  - hosts:
    \{\{- range .hosts }}
    - \{\{ . }}
    \{\{- end }}
    secretName: \{\{ .secretName }}
  \{\{- end }}
  \{\{- end }}
\{\{- end }}

Setup GitHub Repository for Helm Charts

  • Create a new GitHub repository (e.g., helm-repo-with-gh-pages-gcr). This will serve as both our Helm repository and the project’s source code. This can be private or public.
  • Next create a branch named "gh-pages" for publishing the helm charts.
  • Finally we will configure the Github Pages:
    In your repository, go to Settings > Pages, select your branch gh-pages, and set /root as the source directory.

Now that we have our main branch where it receives the helms charts and gh-pages branch where the index will be published.

GitHub Container Registry provides a straightforward way to host Docker images within GitHub. This integration enables you to manage your Docker containers and Helm Charts in a unified workflow.

Automate Publishing with GitHub Actions

GitHub Actions can automate the building and publishing Docker images and Helm charts, whenever you push changes to the repository.

.github/workflows/release.yaml

name: Release Helm Chart
on:
  push:
    branches:
      - main
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: $\{\{ github.repository }}

jobs:
  build:
    name: Github Pages as Helm Chart Repository 
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
    
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: $\{\{ env.REGISTRY }}
          username: $\{\{ github.actor }}
          password: $\{\{ secrets.GITHUB_TOKEN }}

      - name: Build and Push Docker image to GitHub Container Registry
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: |
            $\{\{ env.REGISTRY }}/$\{\{ env.IMAGE_NAME }}:latest
            $\{\{ env.REGISTRY }}/$\{\{ env.IMAGE_NAME }}:$\{\{ github.sha }}
      
      - name: Install YQ
        uses: dcarbone/install-yq-action@v1.2.0
            
      - name: Update values.yaml with Latest Image Tag
        run: |
          yq eval --inplace ".image.repository = \"$\{\{ env.REGISTRY }}/$\{\{ env.IMAGE_NAME }}\"" charts/python-api/values.yaml
          yq eval --inplace ".image.tag = \"$\{\{ github.sha }}\"" charts/python-api/values.yaml
    
      - name: Configure Git
        run: |
          git config user.name "GitHub Action"
          git config user.email "action@github.com"
      
      - name: Install Helm
        uses: azure/setup-helm@v3
        with:
          version: v3.7.0

      - name: Run chart-releaser to Package and Release Helm Charts
        uses: helm/chart-releaser-action@v1.6.0
        env:
          CR_TOKEN: $\{\{ secrets.GITHUB_TOKEN }}

The workflow uses various actions to:

  • Login to GitHub Container Registry
  • Build and push Docker image to the registry
  • Update the values.yaml file with the latest image tag
  • Install Helm and use chart-releaser to package and release Helm charts to gh-pages branch
Docker Container packages in Github Container Registry
Docker Container packages in Github Container Registry
Helm Chart Index
Helm Chart Index
Helm Chart Releases
Helm Chart Releases

Deploy the Helm Chart to Kubernetes

Once the Helm chart is published to GitHub Pages, you can install it in your Kubernetes cluster:

helm repo add gh-pages-as-helm-repo https://sarubhai.github.io/gh-pages-as-helm-repo

helm search repo gh-pages-as-helm-repo

With the repository added, install the chart in your Kubernetes cluster. Customize deployment options using Helm values (e.g., replica count, ingress)

helm upgrade --install python-api python-api \
    --repo https://sarubhai.github.io/gh-pages-as-helm-repo --version 0.1.2 \
    --namespace backend-api --create-namespace \
    --set replicaCount=2 \
    --set ingress.enabled=true \
    --set ingress.className=nginx \
    --set ingress.annotations."nginx\.ingress\.kubernetes\.io/backend-protocol"=HTTP \
    --set-string ingress.annotations."nginx\.ingress\.kubernetes\.io/force-ssl-redirect"=true \
    --set "ingress.hosts[0].host=python-api.local" \
    --set "ingress.hosts[0].paths[0].path=/,ingress.hosts[0].paths[0].pathType=Prefix" \
    --set "ingress.tls[0].hosts[0]=python-api.local" \
    --set "ingress.tls[0].secretName=python-api-tls"

Deploy the Helm Chart using ArgoCD

Alternatively you can configure ArgoCD to automatically deploy the Kubernetes resources from the GitHub-hosted Helm repository. Below is an example application.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: python-api
spec:
  destination:
    name: ''
    namespace: backend-api
    server: https://kubernetes.default.svc
  source:
    path: ''
    repoURL: https://sarubhai.github.io/gh-pages-as-helm-repo
    targetRevision: 0.1.2
    chart: python-api
    helm:
      parameters:
        - name: replicaCount
          value: '2'
        - name: ingress.enabled
          value: 'true'
        - name: ingress.className
          value: nginx
        - name: ingress.annotations.nginx\.ingress\.kubernetes\.io/backend-protocol
          value: HTTP
        - name: ingress.annotations.nginx\.ingress\.kubernetes\.io/force-ssl-redirect
          value: '"true"'
        - name: ingress.hosts[0].host
          value: python-api.local
        - name: ingress.hosts[0].paths[0].path
          value: /
        - name: ingress.hosts[0].paths[0].pathType
          value: Prefix
        - name: ingress.tls[0].hosts[0]
          value: python-api.local
        - name: ingress.tls[0].secretName
          value: python-api-tls
  sources: []
  project: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

This integrated approach simplifies version control, access management, and automates deployments, making it ideal for small teams and open-source projects. By leveraging Helm charts on GitHub Pages and Docker images in the Github Container Registry, you can efficiently manage your Kubernetes applications and accelerate your CI/CD pipeline.

You can use this https://github.com/sarubhai/gh-pages-as-helm-repo GitHub repository for your reference.

PrimeChess

PrimeChess.org

PrimeChess.org makes elite chess training accessible and affordable for everyone. For the past 6 years, we have offered free chess camps for kids in Singapore and India, and during that time, we also observed many average-rated coaches charging far too much for their services.

To change that, we assembled a team of top-rated coaches including International Masters (IM) or coaches with multiple IM or GM norms, to provide online classes starting from $50 per month (8 classes each month + 4 tournaments)

This affordability is only possible if we get more students. This is why it will be very helpful if you could please pass-on this message to others.

Exclucively For Indian Residents: 
Basic - ₹1500
Intermediate- ₹2000
Advanced - ₹2500

Top 10 Articles