Skip to content

Helm chart #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ jobs:
- name: "Update Deployment Image Tag" # [3]
working-directory: "deploy"
run: |
# Get any tags that were pushed
# Get any tags that were pushed
# XXX: Get sha or tag one
# Hint: tags are actually full image names with tags here
image_tag=$(echo ${{ steps.meta.outputs.tags }} | cut -d',' -f1)

kustomize edit set image node-specific-sizing=$image_tag

kustomize build . > deploy.yaml

- name: "Upload Deployment YAML" # [4]
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/publish_charts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Publish Helm charts
Copy link
Author

@mlladb mlladb Mar 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow requires a gh-pages branch to publish the chart to. Sample https://mlladb.github.io/kubernetes-node-specific-sizing/

### Install
helm repo add node-specific-sizing https://mlladb.github.io/kubernetes-node-specific-sizing/
helm repo update
helm repo list
helm install node-specific-sizing node-specific-sizing/node-specific-sizing --namespace node-specific-sizing --create-namespace
helm list --namespace node-specific-sizing

### Uninstall
helm uninstall node-specific-sizing --namespace node-specific-sizing


permissions: {}

on:
push:
tags:
- 'v*'

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
packages: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Publish Helm charts
uses: stefanprodan/helm-gh-pages@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

Helps you resize pods created by a DaemonSet depending on the amount of allocatable resources present on the node.

## Helm

### Install

```bash
helm repo add node-specific-sizing https://manomanotech.github.io/kubernetes-node-specific-sizing/
helm repo update
helm repo list
helm install node-specific-sizing node-specific-sizing/node-specific-sizing --namespace node-specific-sizing --create-namespace
helm list --namespace node-specific-sizing
```

### Uninstall

```bash
helm uninstall node-specific-sizing --namespace node-specific-sizing
```

## How to use

1. Add the `node-specific-sizing.manomano.tech/enabled: "true"` label any pod you'd like to size depending on the node.
Expand All @@ -19,7 +37,7 @@ Helps you resize pods created by a DaemonSet depending on the amount of allocata
- `node-specific-sizing.manomano.tech/maximum-cpu: 4`
- `node-specific-sizing.manomano.tech/minimum-memory: 50M`
- `node-specific-sizing.manomano.tech/maximum-memory: 4G`
- NOTE: Minimums and maximums are applied to both resource and limits.
- NOTE: Minimums and maximums are applied to both resource and limits.
We don't see the need to add different minimums for requests in limits in practice. You may challenge that choice by opening an issue.
- NOTE: Minimums and maximums are to be understood per-pod and not per-container. See resource-sizing algorithm for details.

Expand All @@ -29,7 +47,7 @@ Helps you resize pods created by a DaemonSet depending on the amount of allocata

5. Take care of the following
- In some instances, if limit ends up being below request it will be adjusted to be equal to the request.
- WARNING: We have not tested all cases of partial configuration or weird mish-mashes.
- WARNING: We have not tested all cases of partial configuration or weird mish-mashes.
- You're safer defining both requests and limits, or just requests if the underlying DaemonSet does not have limits.
- Having some containers define a request or limit while others do not is unsupported.

Expand All @@ -42,7 +60,7 @@ To achieve this, the updated container requests and limits (from here on out, "t
follows:

- For each container in the pod, and for each tunable, compute the tunable's relative value per container.
For any given container, `relative_tunable = container_tunable / (sum(container_tunables) - sum(excluded_container_tunables))`
For any given container, `relative_tunable = container_tunable / (sum(container_tunables) - sum(excluded_container_tunables))`
- Derive a `pod_tunable_budget = allocatable_tunable_on_node * configured_pod_proportion - sum(excluded_container_tunables)`. This represents the resources that will be given to the pod.
- Clamp `pod_tunable_budget` if minimums and/or maximums are set for that tunable.
- Finally, `new_absolute_tunable = pod_tunable_budget * relative_tunable` spreads the budget between containers.
Expand Down Expand Up @@ -82,7 +100,7 @@ PC3| .50 .55 .50 .55 // Output: relative_tunables
1. `make build` and `make docker-build`
2. `make deploy` to setup manifests in current context
3. `bin/playground.sh` to setup a K3D playground cluster with a toy daemonset with annotations set
4. `bin/dev_toggle.sh` to reconfigure the K3D playground cluster so that it can reach the webhook server on your workstation,
4. `bin/dev_toggle.sh` to reconfigure the K3D playground cluster so that it can reach the webhook server on your workstation,
as well as extracting certs from the cluster. This allows you to use the IDE of your choice and try things directly.

###
###
23 changes: 23 additions & 0 deletions charts/node-specific-sizing/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
13 changes: 13 additions & 0 deletions charts/node-specific-sizing/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v2
name: node-specific-sizing
description: A Kubernetes controller that helps resize pods created by a DaemonSet depending on the amount of allocatable resources present on the node.
type: application
version: 0.1.0
appVersion: "0.1.0"

dependencies:
- name: cert-manager
repository: https://charts.jetstack.io
condition: certmanager.enabled
alias: certmanager
version: "v1.15.3"
76 changes: 76 additions & 0 deletions charts/node-specific-sizing/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "chart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}


{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "chart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}


{{/*
Common labels
*/}}
{{- define "chart.labels" -}}
helm.sh/chart: {{ include "chart.chart" . }}
{{ include "chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: "node-specific-sizing"
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "chart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "chart.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Allow the release namespace to be overridden for multi-namespace deployments in combined charts
*/}}
{{- define "chart.namespace" -}}
{{- if .Values.namespaceOverride }}
{{- .Values.namespaceOverride }}
{{- else }}
{{- .Release.Namespace }}
{{- end }}
{{- end }}
16 changes: 16 additions & 0 deletions charts/node-specific-sizing/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "chart.fullname" . }}-role
labels:
app.kubernetes.io/component: rbac
{{- include "chart.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
15 changes: 15 additions & 0 deletions charts/node-specific-sizing/templates/clusterrolebinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "chart.fullname" . }}-rolebinding
labels:
app.kubernetes.io/component: rbac
{{- include "chart.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "chart.name" . }}-role
subjects:
- kind: ServiceAccount
name: {{ include "chart.name" . }}
namespace: {{ include "chart.namespace" . }}
43 changes: 43 additions & 0 deletions charts/node-specific-sizing/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "chart.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/component: controller
{{- include "chart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app.kubernetes.io/component: controller
{{- include "chart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
app.kubernetes.io/component: controller
{{- include "chart.selectorLabels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "chart.serviceAccountName" . }}
terminationGracePeriodSeconds: 10
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
resources: {{- toYaml .Values.resources | nindent 12 }}
imagePullPolicy: {{ default "IfNotPresent" .Values.image.pullPolicy }}
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: serving-certs
readOnly: true
securityContext:
runAsNonRoot: true
volumes:
- name: serving-certs
secret:
defaultMode: 420
secretName: {{ include "chart.fullname" . }}-server-cert
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: {{ include "chart.fullname" . }}-webhook
annotations:
cert-manager.io/inject-ca-from: '{{ .Release.Namespace }}/{{ include "chart.fullname" . }}-serving-cert'
labels:
{{- include "chart.labels" . | nindent 4 }}
webhooks:
- name: {{ include "chart.fullname" . }}.svc.cluster.local
objectSelector:
matchLabels:
node-specific-sizing.manomano.tech/enabled: "true"
admissionReviewVersions: [ "v1" ]
sideEffects: None
failurePolicy: Ignore
timeoutSeconds: 1
clientConfig:
service:
namespace: node-specific-sizing
name: {{ include "chart.fullname" . }}
path: /mutate
rules:
- apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
operations: ["CREATE"]
scope: Namespaced

16 changes: 16 additions & 0 deletions charts/node-specific-sizing/templates/selfsigned-issuer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: {{ include "chart.fullname" . }}-selfsigned-issuer
namespace: {{ .Release.Namespace }}
annotations:
{{- if .Values.certmanager.enabled }}
helm.sh/hook: post-install,post-upgrade
{{- else }}
helm.sh/hook: pre-install,pre-upgrade
{{- end }}
helm.sh/hook-weight: "1"
labels:
{{- include "chart.labels" . | nindent 4 }}
spec:
selfSigned: {}
17 changes: 17 additions & 0 deletions charts/node-specific-sizing/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "chart.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/component: webhook
{{- include "chart.labels" . | nindent 4 }}
spec:
type: ClusterIP
selector:
{{- include "chart.selectorLabels" . | nindent 4 }}
ports:
- name: "https"
port: 443
targetPort: 8443
protocol: TCP
10 changes: 10 additions & 0 deletions charts/node-specific-sizing/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "chart.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/component: rbac
{{- include "chart.labels" . | nindent 4 }}
annotations:
{{- toYaml .Values.serviceAccount.annotations | nindent 4 }}
22 changes: 22 additions & 0 deletions charts/node-specific-sizing/templates/serving-cert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "chart.fullname" . }}-serving-cert
namespace: {{ .Release.Namespace }}
annotations:
{{- if .Values.certmanager.enabled }}
helm.sh/hook: post-install,post-upgrade
{{- else }}
helm.sh/hook: pre-install,pre-upgrade
{{- end }}
helm.sh/hook-weight: "2"
labels:
{{- include "chart.labels" . | nindent 4 }}
spec:
dnsNames:
- '{{ include "chart.fullname" . }}.{{ .Release.Namespace }}.svc'
- '{{ include "chart.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.kubernetesClusterDomain }}'
issuerRef:
kind: Issuer
name: {{ include "chart.fullname" . }}-selfsigned-issuer
secretName: {{ include "chart.fullname" . }}-server-cert
Loading