Skip to content

Commit 5f58e67

Browse files
committed
feat: helm chart
Added a Helm chart so that users can install the Oxide cloud controller manager using Helm. Helm has its own quirks, listed below, that influenced my approach. * Helm "best practices" place arbitrary top-level attributes in `values.yaml` that, quite frankly, I didn't see as good design. I used a minimal approach for `_helpers.tpl` and `values.yaml` that we'll refine over time through usage and feedback. * `helm push` expects to use `name` and `version` from `Chart.yaml` as the last part of the image name and the image tag respectively. Originally, I wanted to push to `ghcr.io/oxidecomputer/oxide-cloud-controller-manager/charts` to keep the image name in line with the GitHub organization and repository name. However, that would mean I'd need to use `charts` as the value for `name`, which is extremely silly. I ended up setting `name` to `oxide-cloud-controller-manager` and pushing to `ghcr.io/oxidecomputer/charts/oxide-cloud-controller-manager`. I'll hold my thoughts on Helm overall, but let's just say I was reminded why I avoided Helm most of my career. Regardless, it's good to support Helm for our Kubernetes integrations so users have a "standard" path for installation. Closes #178.
1 parent de07651 commit 5f58e67

12 files changed

Lines changed: 1056 additions & 56 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.tgz

Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ IMAGE_NAME ?= oxide-cloud-controller-manager
1717
IMAGE_TAG ?= $(patsubst v%,%,$(VERSION))$(if $(RELEASE),,-$(GIT_COMMIT_SHORT))
1818
IMAGE_FULL ?= $(if $(IMAGE_REGISTRY),$(IMAGE_REGISTRY)/)$(IMAGE_NAME):$(IMAGE_TAG)
1919

20+
# Helm chart configuration.
21+
CHART_DIR ?= charts/oxide-cloud-controller-manager
22+
CHART_REGISTRY ?= oci://ghcr.io/oxidecomputer/charts
23+
HELM ?= go tool -modfile tools/go.mod helm
24+
2025
.PHONY: test
2126
test:
2227
@echo "Running tests in container..."
@@ -45,3 +50,24 @@ build:
4550
push:
4651
@echo "Pushing container image: $(IMAGE_FULL)"
4752
$(CONTAINER_RUNTIME) push $(IMAGE_FULL)
53+
54+
.PHONY: manifest
55+
manifest: helm-set-version
56+
@echo "Generating manifest: manifests/oxide-cloud-controller-manager.yaml"
57+
$(HELM) template oxide-cloud-controller-manager $(CHART_DIR) \
58+
--namespace kube-system \
59+
> manifests/oxide-cloud-controller-manager.yaml
60+
61+
.PHONY: helm-set-version
62+
helm-set-version:
63+
@sed -i 's/^version: .*/version: "$(patsubst v%,%,$(VERSION))"/' $(CHART_DIR)/Chart.yaml
64+
@sed -i 's/^appVersion: .*/appVersion: "$(patsubst v%,%,$(VERSION))"/' $(CHART_DIR)/Chart.yaml
65+
66+
.PHONY: helm-package
67+
helm-package: helm-set-version
68+
$(HELM) package $(CHART_DIR)
69+
70+
.PHONY: helm-push
71+
helm-push: helm-package
72+
$(HELM) push $(IMAGE_NAME)-$(patsubst v%,%,$(VERSION)).tgz \
73+
$(CHART_REGISTRY)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
apiVersion: v2
3+
name: oxide-cloud-controller-manager
4+
description: "Oxide Kubernetes Cloud Controller Manager."
5+
type: application
6+
version: "0.3.0"
7+
appVersion: "0.3.0"
8+
keywords:
9+
- oxide
10+
- cloud-controller-manager
11+
home: "https://github.com/oxidecomputer/oxide-cloud-controller-manager"
12+
sources:
13+
- "https://github.com/oxidecomputer/oxide-cloud-controller-manager"
14+
maintainers:
15+
- name: Oxide Computer Company
16+
email: support@oxide.computer
17+
url: "https://oxide.computer"
18+
icon: "https://oxide.computer/favicon.svg"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{{- define "oxide-ccm.name" -}}
2+
{{- default .Chart.Name .Values.name | trunc 63 | trimSuffix "-" }}
3+
{{- end }}
4+
5+
{{- define "oxide-ccm.fullName" -}}
6+
{{- $name := include "oxide-ccm.name" . }}
7+
{{- if contains $name .Release.Name }}
8+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
9+
{{- else }}
10+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
11+
{{- end }}
12+
{{- end }}
13+
14+
{{- define "oxide-ccm.chart" -}}
15+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
16+
{{- end }}
17+
18+
{{- define "oxide-ccm.selectorLabels" -}}
19+
app.kubernetes.io/name: {{ include "oxide-ccm.name" . }}
20+
app.kubernetes.io/instance: {{ .Release.Name }}
21+
{{- end }}
22+
23+
{{- define "oxide-ccm.labels" -}}
24+
helm.sh/chart: {{ include "oxide-ccm.chart" . }}
25+
{{ include "oxide-ccm.selectorLabels" . }}
26+
{{- if .Chart.AppVersion }}
27+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
28+
{{- end }}
29+
app.kubernetes.io/managed-by: {{ .Release.Service }}
30+
{{- end }}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRole
3+
metadata:
4+
name: system:{{ include "oxide-ccm.fullName" . }}
5+
labels:
6+
{{- include "oxide-ccm.labels" . | nindent 4 }}
7+
annotations:
8+
rbac.authorization.kubernetes.io/autoupdate: "true"
9+
rules:
10+
- apiGroups:
11+
- coordination.k8s.io
12+
resources:
13+
- leases
14+
verbs:
15+
- get
16+
- watch
17+
- list
18+
- create
19+
- update
20+
- delete
21+
- apiGroups:
22+
- ""
23+
resources:
24+
- events
25+
verbs:
26+
- create
27+
- patch
28+
- update
29+
- apiGroups:
30+
- ""
31+
resources:
32+
- nodes
33+
verbs:
34+
- '*'
35+
- apiGroups:
36+
- ""
37+
resources:
38+
- nodes/status
39+
verbs:
40+
- patch
41+
- apiGroups:
42+
- ""
43+
resources:
44+
- services
45+
verbs:
46+
- list
47+
- patch
48+
- update
49+
- watch
50+
- apiGroups:
51+
- ""
52+
resources:
53+
- services/status
54+
verbs:
55+
- list
56+
- patch
57+
- update
58+
- watch
59+
- apiGroups:
60+
- ""
61+
resources:
62+
- serviceaccounts
63+
verbs:
64+
- create
65+
- apiGroups:
66+
- ""
67+
resources:
68+
- persistentvolumes
69+
verbs:
70+
- get
71+
- list
72+
- update
73+
- watch
74+
- apiGroups:
75+
- ""
76+
resources:
77+
- endpoints
78+
verbs:
79+
- create
80+
- get
81+
- list
82+
- watch
83+
- update
84+
- apiGroups:
85+
- ""
86+
resources:
87+
- configmaps
88+
verbs:
89+
- get
90+
- list
91+
- watch
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRoleBinding
3+
metadata:
4+
name: system:{{ include "oxide-ccm.fullName" . }}
5+
labels:
6+
{{- include "oxide-ccm.labels" . | nindent 4 }}
7+
roleRef:
8+
apiGroup: rbac.authorization.k8s.io
9+
kind: ClusterRole
10+
name: system:{{ include "oxide-ccm.fullName" . }}
11+
subjects:
12+
- kind: ServiceAccount
13+
name: {{ include "oxide-ccm.fullName" . }}
14+
namespace: {{ .Release.Namespace }}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: {{ include "oxide-ccm.fullName" . }}
5+
namespace: {{ .Release.Namespace }}
6+
labels:
7+
{{- include "oxide-ccm.labels" . | nindent 4 }}
8+
spec:
9+
replicas: {{ .Values.deployment.replicas }}
10+
selector:
11+
matchLabels:
12+
{{- include "oxide-ccm.selectorLabels" . | nindent 6 }}
13+
template:
14+
metadata:
15+
labels:
16+
{{- include "oxide-ccm.selectorLabels" . | nindent 8 }}
17+
spec:
18+
dnsPolicy: Default
19+
hostNetwork: true
20+
serviceAccountName: {{ include "oxide-ccm.fullName" . }}
21+
priorityClassName: system-cluster-critical
22+
tolerations:
23+
- key: "node.cloudprovider.kubernetes.io/uninitialized"
24+
value: "true"
25+
effect: "NoSchedule"
26+
- key: "CriticalAddonsOnly"
27+
operator: "Exists"
28+
- key: "node-role.kubernetes.io/control-plane"
29+
effect: NoSchedule
30+
containers:
31+
- name: {{ include "oxide-ccm.name" . }}
32+
image: "{{ .Values.deployment.image.name }}:{{ .Values.deployment.image.tag | default .Chart.AppVersion }}"
33+
imagePullPolicy: {{ .Values.deployment.imagePullPolicy }}
34+
command:
35+
- "/usr/bin/oxide-cloud-controller-manager"
36+
- "--cloud-provider=oxide"
37+
resources:
38+
requests:
39+
cpu: 100m
40+
memory: 50Mi
41+
env:
42+
- name: OXIDE_HOST
43+
valueFrom:
44+
secretKeyRef:
45+
name: {{ include "oxide-ccm.fullName" . }}
46+
key: oxide-host
47+
- name: OXIDE_TOKEN
48+
valueFrom:
49+
secretKeyRef:
50+
name: {{ include "oxide-ccm.fullName" . }}
51+
key: oxide-token
52+
- name: OXIDE_PROJECT
53+
valueFrom:
54+
secretKeyRef:
55+
name: {{ include "oxide-ccm.fullName" . }}
56+
key: oxide-project
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: {{ include "oxide-ccm.fullName" . }}
5+
namespace: {{ .Release.Namespace }}
6+
labels:
7+
{{- include "oxide-ccm.labels" . | nindent 4 }}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
deployment:
2+
replicas: 1
3+
image:
4+
name: ghcr.io/oxidecomputer/oxide-cloud-controller-manager
5+
tag: ""
6+
imagePullPolicy: IfNotPresent

0 commit comments

Comments
 (0)