Skip to content

Commit 56521f7

Browse files
committed
Implement an actual Helm chart
Our existing Helm chart is just a copy and paste of the existing `deployment.yaml` for `kubectl`, with some unrelated broken files alongside it. Replace this with templates that actually interpolate the values in the chart. Rather than having the release process copy-paste the `deployment.yaml` from the root into the chart, do the opposite: use Helm's template as the source of truth to generate `deployment.yaml` from.
1 parent bf18eb4 commit 56521f7

9 files changed

Lines changed: 243 additions & 140 deletions

File tree

.github/workflows/publish_release.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ jobs:
4040
echo "$(git config --get user.email) namespaces=\"git\" $(cat $PUBLISH_GIT_SIGN_KEY_PATH.pub)" >> ~/.ssh/allowed_signers
4141
git config --global user.signingkey "$PUBLISH_GIT_SIGN_KEY_PATH"
4242
43+
- name: "Install Helm"
44+
uses: azure/setup-helm@v4
45+
with:
46+
version: 'v3.14.0'
47+
4348
- name: "Create version"
4449
id: version
4550
run: |

README.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
11
# AppSignal for Kubernetes
22

3-
Extracts Kubenetes Cluster Metrics.
3+
AppSignal for Kubernetes is an agent that collects and sends metrics about your Kubernetes cluster to your AppSignal account.
44

55
## Installation
66

7-
In a Kubernetes cluster, set up your AppSignal API key (find your _App-specific_ API key in [App settings](https://appsignal.com/redirect-to/app?to=info)) by creating a secret:
7+
First, set up your AppSignal API key (find your _App-specific_ API key in [App settings](https://appsignal.com/redirect-to/app?to=info)) by creating a secret:
88

9-
kubectl create secret generic appsignal --from-literal=api-key=00000000-0000-0000-0000-000000000000
9+
kubectl create secret generic appsignal --from-literal=api-key=00000000-0000-0000-0000-000000000000 --namespace appsignal
1010

11-
Then, add the AppSignal deployment to your cluster:
11+
### Using kubectl
12+
13+
Install AppSignal for Kubernetes by applying the deployment manifest:
1214

1315
kubectl apply -f https://raw.githubusercontent.com/appsignal/appsignal-kubernetes/main/deployment.yaml
1416

15-
Alternatively, install AppSignal through its Helm chart:
17+
This will create the `appsignal` namespace and deploy the AppSignal for Kubernetes agent in that namespace.
1618

17-
helm repo add appsignal-kubernetes https://appsignal.github.io/appsignal-kubernetes
18-
helm install appsignal-kubernetes/appsignal-kubernetes --generate-name
19+
### Using Helm
1920

20-
AppSignal for Kubernetes will start sending Kubernetes automatically.
21+
Add the AppSignal Helm repository and install the chart:
22+
23+
helm repo add appsignal-kubernetes https://appsignal.github.io/appsignal-kubernetes
24+
helm install appsignal-kubernetes appsignal-kubernetes/appsignal-kubernetes --create-namespace --namespace appsignal
2125

2226
## Cluster Metrics
2327

24-
After installing AppSignal for Kubernetes into a cluster, AppSignal's Host Metrics are automatically replaced with Cluster Metrics to display cluster metrics.
28+
AppSignal for Kubernetes will start sending Kubernetes metrics automatically.
29+
30+
After installing AppSignal for Kubernetes, AppSignal's Host Metrics are automatically replaced with Cluster Metrics to display cluster metrics.
2531

2632
## Development
2733

Rakefile

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,28 @@ task :protocol do
133133
`protoc -I ../appsignal-protocol --rust_out=protocol ../appsignal-protocol/kubernetes.proto`
134134
end
135135

136-
desc "Update the Helm template files"
137-
task :update_helm_templates do
138-
`mkdir -p charts/appsignal-kubernetes/templates`
139-
`cp deployment.yaml charts/appsignal-kubernetes/templates`
136+
desc "Generate deployment.yaml from Helm chart"
137+
task :generate_deployment do
138+
require 'tempfile'
139+
140+
# Create a temporary values file with only the overrides needed for standalone deployment
141+
values_override = <<~VALUES
142+
image:
143+
tag: "#{current_version}"
144+
VALUES
145+
146+
# Write temporary override values file
147+
Tempfile.create(['values-override', '.yaml']) do |override_file|
148+
override_file.write(values_override)
149+
override_file.flush
150+
151+
# Generate deployment.yaml using helm template with existing values.yaml plus overrides
152+
output = `helm template appsignal-kubernetes charts/appsignal-kubernetes --values charts/appsignal-kubernetes/values.yaml --values #{override_file.path} --namespace appsignal`
153+
154+
# Write the output to deployment.yaml
155+
File.write('deployment.yaml', output)
156+
puts "Generated deployment.yaml from Helm chart"
157+
end
140158
end
141159

142160
def current_version

charts/appsignal-kubernetes/Chart.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
apiVersion: v2
22
name: appsignal-kubernetes
3-
description: A Helm chart for Kubernetes
3+
description: A Helm chart for AppSignal Kubernetes monitoring
44

55
# A chart can be either an 'application' or a 'library' chart.
66
#
@@ -16,3 +16,8 @@ type: application
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
1818
version: 1.1.2
19+
20+
# This is the version number of the application being deployed. This version number should be
21+
# incremented each time you make changes to the application. Versions are not expected to
22+
# follow Semantic Versioning. They should reflect the version the application is using.
23+
appVersion: "1.1.2"
Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,116 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "appsignal-kubernetes.name" -}}
5+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11+
If release name contains chart name it will be used as a full name.
12+
*/}}
13+
{{- define "appsignal-kubernetes.fullname" -}}
14+
{{- if .Values.fullnameOverride }}
15+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16+
{{- else }}
17+
{{- $name := default .Chart.Name .Values.nameOverride }}
18+
{{- if contains $name .Release.Name }}
19+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
20+
{{- else }}
21+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22+
{{- end }}
23+
{{- end }}
24+
{{- end }}
25+
26+
{{/*
27+
Create chart name and version as used by the chart label.
28+
*/}}
29+
{{- define "appsignal-kubernetes.chart" -}}
30+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31+
{{- end }}
32+
33+
{{/*
34+
Common labels
35+
*/}}
36+
{{- define "appsignal-kubernetes.labels" -}}
37+
helm.sh/chart: {{ include "appsignal-kubernetes.chart" . }}
38+
{{ include "appsignal-kubernetes.selectorLabels" . }}
39+
{{- if .Chart.AppVersion }}
40+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41+
{{- end }}
42+
app.kubernetes.io/managed-by: {{ .Release.Service }}
43+
{{- end }}
44+
45+
{{/*
46+
Selector labels
47+
*/}}
48+
{{- define "appsignal-kubernetes.selectorLabels" -}}
49+
app.kubernetes.io/name: {{ include "appsignal-kubernetes.name" . }}
50+
app.kubernetes.io/instance: {{ .Release.Name }}
51+
{{- end }}
52+
53+
{{/*
54+
Create the name of the service account to use
55+
*/}}
56+
{{- define "appsignal-kubernetes.serviceAccountName" -}}
57+
{{- if .Values.serviceAccount.create }}
58+
{{- default (include "appsignal-kubernetes.fullname" .) .Values.serviceAccount.name }}
59+
{{- else }}
60+
{{- default "default" .Values.serviceAccount.name }}
61+
{{- end }}
62+
{{- end }}
63+
164
apiVersion: apps/v1
265
kind: Deployment
366
metadata:
4-
name: appsignal-kubernetes
67+
name: {{ include "appsignal-kubernetes.fullname" . }}
68+
namespace: {{ .Release.Namespace }}
69+
labels:
70+
{{- include "appsignal-kubernetes.labels" . | nindent 4 }}
571
spec:
6-
replicas: 1
72+
replicas: {{ .Values.replicaCount }}
773
selector:
874
matchLabels:
9-
app: appsignal-kubernetes
75+
{{- include "appsignal-kubernetes.selectorLabels" . | nindent 6 }}
1076
template:
1177
metadata:
1278
labels:
13-
app: appsignal-kubernetes
79+
{{- include "appsignal-kubernetes.selectorLabels" . | nindent 8 }}
1480
spec:
15-
serviceAccountName: appsignal-kubernetes-service-account
81+
serviceAccountName: {{ include "appsignal-kubernetes.serviceAccountName" . }}
1682
containers:
17-
- name: appsignal-kubernetes
18-
image: appsignal/appsignal-kubernetes:1.1.2
19-
imagePullPolicy: IfNotPresent
83+
- name: {{ .Chart.Name }}
84+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
85+
imagePullPolicy: {{ .Values.image.pullPolicy }}
2086
env:
2187
- name: APPSIGNAL_API_KEY
2288
valueFrom:
2389
secretKeyRef:
24-
name: appsignal
25-
key: api-key
90+
name: {{ .Values.appsignal.secretName }}
91+
key: {{ .Values.appsignal.secretKey }}
2692
- name: RUST_LOG
27-
value: info
93+
value: {{ .Values.logLevel }}
94+
resources:
95+
{{- toYaml .Values.resources | nindent 12 }}
2896
---
97+
{{- if .Values.serviceAccount.create -}}
2998
apiVersion: v1
3099
kind: ServiceAccount
31100
metadata:
32-
name: appsignal-kubernetes-service-account
101+
name: {{ include "appsignal-kubernetes.serviceAccountName" . }}
102+
namespace: {{ .Release.Namespace }}
103+
labels:
104+
{{- include "appsignal-kubernetes.labels" . | nindent 4 }}
105+
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
106+
{{- end }}
33107
---
34108
apiVersion: rbac.authorization.k8s.io/v1
35109
kind: ClusterRole
36110
metadata:
37-
name: appsignal-kubernetes-role
111+
name: {{ include "appsignal-kubernetes.fullname" . }}
112+
labels:
113+
{{- include "appsignal-kubernetes.labels" . | nindent 4 }}
38114
rules:
39115
- apiGroups: ["*"]
40116
resources: ["*"]
@@ -45,12 +121,14 @@ rules:
45121
apiVersion: rbac.authorization.k8s.io/v1
46122
kind: ClusterRoleBinding
47123
metadata:
48-
name: appsignal-kubernetes-cluster-role-binding
124+
name: {{ include "appsignal-kubernetes.fullname" . }}
125+
labels:
126+
{{- include "appsignal-kubernetes.labels" . | nindent 4 }}
49127
roleRef:
50128
apiGroup: rbac.authorization.k8s.io
51129
kind: ClusterRole
52-
name: appsignal-kubernetes-role
130+
name: {{ include "appsignal-kubernetes.fullname" . }}
53131
subjects:
54132
- kind: ServiceAccount
55-
name: appsignal-kubernetes-service-account
56-
namespace: default
133+
name: {{ include "appsignal-kubernetes.serviceAccountName" . }}
134+
namespace: {{ .Release.Namespace }}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: {{ .Release.Namespace }}
5+
labels:
6+
{{- include "appsignal-kubernetes.labels" . | nindent 4 }}

charts/appsignal-kubernetes/values.yaml

Lines changed: 10 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,59 +5,31 @@
55
replicaCount: 1
66

77
image:
8-
repository: nginx
8+
repository: appsignal/appsignal-kubernetes
99
pullPolicy: IfNotPresent
1010
# Overrides the image tag whose default is the chart appVersion.
11-
tag: ""
11+
tag: "1.1.2"
1212

13-
imagePullSecrets: []
14-
nameOverride: ""
15-
fullnameOverride: ""
1613

1714
serviceAccount:
1815
# Specifies whether a service account should be created
1916
create: true
2017
# Automatically mount a ServiceAccount's API credentials?
2118
automount: true
22-
# Annotations to add to the service account
23-
annotations: {}
2419
# The name of the service account to use.
2520
# If not set and create is true, a name is generated using the fullname template
2621
name: ""
2722

28-
podAnnotations: {}
29-
podLabels: {}
3023

31-
podSecurityContext: {}
32-
# fsGroup: 2000
24+
# AppSignal configuration
25+
appsignal:
26+
# Secret name containing the API key
27+
secretName: "appsignal"
28+
# Secret key containing the API key
29+
secretKey: "api-key"
3330

34-
securityContext: {}
35-
# capabilities:
36-
# drop:
37-
# - ALL
38-
# readOnlyRootFilesystem: true
39-
# runAsNonRoot: true
40-
# runAsUser: 1000
41-
42-
service:
43-
type: ClusterIP
44-
port: 80
45-
46-
ingress:
47-
enabled: false
48-
className: ""
49-
annotations: {}
50-
# kubernetes.io/ingress.class: nginx
51-
# kubernetes.io/tls-acme: "true"
52-
hosts:
53-
- host: chart-example.local
54-
paths:
55-
- path: /
56-
pathType: ImplementationSpecific
57-
tls: []
58-
# - secretName: chart-example-tls
59-
# hosts:
60-
# - chart-example.local
31+
# Log level for the application
32+
logLevel: "info"
6133

6234
resources: {}
6335
# We usually recommend not to specify default resources and to leave this as a conscious
@@ -71,37 +43,3 @@ resources: {}
7143
# cpu: 100m
7244
# memory: 128Mi
7345

74-
livenessProbe:
75-
httpGet:
76-
path: /
77-
port: http
78-
readinessProbe:
79-
httpGet:
80-
path: /
81-
port: http
82-
83-
autoscaling:
84-
enabled: false
85-
minReplicas: 1
86-
maxReplicas: 100
87-
targetCPUUtilizationPercentage: 80
88-
# targetMemoryUtilizationPercentage: 80
89-
90-
# Additional volumes on the output Deployment definition.
91-
volumes: []
92-
# - name: foo
93-
# secret:
94-
# secretName: mysecret
95-
# optional: false
96-
97-
# Additional volumeMounts on the output Deployment definition.
98-
volumeMounts: []
99-
# - name: foo
100-
# mountPath: "/etc/foo"
101-
# readOnly: true
102-
103-
nodeSelector: {}
104-
105-
tolerations: []
106-
107-
affinity: {}

0 commit comments

Comments
 (0)