CircleCI’s Helm Orb lets you deploy to Kubernetes without writing a single line of Helm CLI code yourself.
Let’s see it in action. Imagine you have a simple Nginx deployment and service configuration in a k8s directory within your project:
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
Now, you want to deploy this to your Kubernetes cluster whenever you push a change to your main branch. Here’s how your CircleCI configuration (.circleci/config.yml) would look using the Helm Orb:
version: 2.1
orbs:
helm: circleci/helm@1.5.0 # Use a specific version
jobs:
deploy-to-k8s:
docker:
- image: cimg/base:stable # A basic image with necessary tools
steps:
- checkout
- helm/install-helm # Installs Helm CLI
- helm/apply: # This is the core command
kubeconfig: << pipeline.parameters.kubeconfig-value >> # Your Kubeconfig
context: << pipeline.parameters.kube-context-value >> # Your Kube context
namespace: default # The Kubernetes namespace to deploy to
chart-path: k8s # The directory containing your Kubernetes manifests
workflows:
version: 2
deploy:
jobs:
- deploy-to-k8s:
filters:
branches:
only: main # Only run on pushes to the main branch
parameters: # Define pipeline parameters for sensitive information
kubeconfig-value:
type: env_var_name
default: KUBECONFIG_VALUE
kube-context-value:
type: env_var_name
default: KUBECONTEXT_VALUE
In this setup:
- We declare the
circleci/helmorb. - The
deploy-to-k8sjob uses a base Docker image that has Helm pre-installed or can easily install it. helm/install-helmensures the Helm binary is available in the job’s environment.- The
helm/applycommand is the magic. It takes yourkubeconfig(which you’d store as an environment variable in CircleCI project settings, e.g.,KUBECONFIG_VALUE), the desiredcontextwithin that config, thenamespaceto deploy to, and thechart-path. - Crucially,
chart-path: k8stells the orb to treat thek8sdirectory as a Helm chart, even if it doesn’t have aChart.yamlfile. It will apply all YAML manifests found within that directory. - The workflow is configured to only run this job when changes are pushed to the
mainbranch. - Pipeline parameters are used to inject sensitive
kubeconfigandcontextvalues securely.
When this job runs, CircleCI will:
- Check out your code.
- Install Helm if it’s not already present.
- Execute
helm apply -f k8s --kubeconfig $KUBECONFIG_VALUE --context $KUBECONTEXT_VALUE --namespace default. Thehelm applycommand, when used with a directory containing Kubernetes manifests, functions similarly tokubectl apply -R -f k8s, ensuring that all resources defined in your YAML files are created or updated in the cluster.
The real power here is that the orb abstracts away the direct calls to kubectl or helm template | kubectl apply. It handles the orchestration, making your CI/CD pipeline cleaner and more focused on the deployment itself.
The helm/apply command, when pointed at a directory of raw Kubernetes manifests, essentially performs a kubectl apply -R -f <chart-path> operation. It iterates through all YAML files in the specified directory and applies them to your cluster, creating or updating resources as needed. This is a simple yet effective way to manage configurations that don’t require the full templating capabilities of Helm charts.
What most people miss is that helm/apply doesn’t require a Chart.yaml file to operate. You can point it directly at a directory containing standard Kubernetes YAML manifests, and it will treat them as a "chart" to be applied. This makes it incredibly versatile for deploying applications that are defined directly in YAML, without the overhead of creating a full Helm chart structure.
After successfully deploying your Nginx service, the next logical step would be to integrate automated testing of your deployed application.