Skip to content
Open
23 changes: 23 additions & 0 deletions dist/chart-crds/.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/
19 changes: 19 additions & 0 deletions dist/chart-crds/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v2
name: mcp-lifecycle-operator-crds
description: CRDs for the mcp-lifecycle-operator Helm chart
type: application
version: 0.1.0
appVersion: "v0.1.0"
kubeVersion: ">= 1.28.0"
home: https://github.com/kubernetes-sigs/mcp-lifecycle-operator
sources:
- https://github.com/kubernetes-sigs/mcp-lifecycle-operator
keywords:
- kubernetes
- operator
- mcp
- model-context-protocol
- crds
maintainers:
- name: mcp-lifecycle-operator maintainers
url: https://github.com/kubernetes-sigs/mcp-lifecycle-operator
1,742 changes: 1,742 additions & 0 deletions dist/chart-crds/templates/mcp.x-k8s.io_mcpservers.yaml
Comment thread
aliok marked this conversation as resolved.
Copy link
Copy Markdown
Member

@aliok aliok May 7, 2026

Choose a reason for hiding this comment

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

What would happen if we put the CRD under dist/chart/crds rather then dist/chart/templates?

I understand that keeping it upper level would mean no automatic CRD upgrades with helm install but when one does helm uninstall, CRD and thus all the instances are kept.

If we put it under templates, we would have automatic CRD upgrade but introduce this deletion risk.

I don't have that much Helm experience TBH.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

cc @ibm-adarsh @Cali0707 @matzew @koksay (Helm expert)?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@aliok looking here it seems like the two best ways to handle CRDs in a PR is:

  1. In crds
  2. In a separate CRD only chart

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Helm does not automatically update CRDs during a helm update when they live in the crds directory.

If you expect frequent CRD updates, I suggest moving them to a separate chart. Otherwise, for a couple of updates a year, you can include in the upgrade doc that users update them manually.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IMO we should move the CRDs to a separate chart then. Thoughts @aliok ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We're gonna have frequent updates, as the project is new. So, let's do a separate chart for that.

cc @Venkatesh1505

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Done in f13ce27 — moved the CRD to a separate dist/chart-crds/ chart (mcp-lifecycle-operator-crds).

The CRD is now a regular template in the new chart, so helm upgrade will update it automatically. The main chart's crds/ directory has been removed, and NOTES.txt updated to mention installing the CRD chart first.

Tested on a kind cluster:

  • helm install mcp-lifecycle-operator-crds dist/chart-crds/ — CRD created
  • helm upgrade mcp-lifecycle-operator-crds dist/chart-crds/ — CRD updated (revision 2)
  • helm install mcp-lifecycle-operator dist/chart/ — pod 1/1 Running, all RBAC resources created
  • helm uninstall — both charts cleaned up

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file seems to be out of sync with the CRD in config/crd/bases/mcp.x-k8s.io_mcpservers.yaml.
It seems to miss

  • extraAnnotations field
  • extraLabels field
  • mcp section under spec

Can we make sure those are updated as part of make manifests too?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I want to tackle that sync with #134

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW: in #207 we added a Makefile target which checks if the generated files & manifests are up-to-date. This also runs then in a workflow.

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/chart-crds/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# This chart has no configurable values.
# It installs the CRDs required by mcp-lifecycle-operator.
23 changes: 23 additions & 0 deletions dist/chart/.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/
18 changes: 18 additions & 0 deletions dist/chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v2
name: mcp-lifecycle-operator
description: A Kubernetes operator that provides a declarative API to deploy, manage, and safely roll out MCP Servers
type: application
version: 0.1.0
appVersion: "v0.1.0"
kubeVersion: ">= 1.28.0"
home: https://github.com/kubernetes-sigs/mcp-lifecycle-operator
sources:
- https://github.com/kubernetes-sigs/mcp-lifecycle-operator
keywords:
- kubernetes
- operator
- mcp
- model-context-protocol
maintainers:
- name: mcp-lifecycle-operator maintainers
url: https://github.com/kubernetes-sigs/mcp-lifecycle-operator
32 changes: 32 additions & 0 deletions dist/chart/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{ .Chart.Name }} {{ .Chart.AppVersion }} has been deployed successfully!

NOTE: This chart requires the mcp-lifecycle-operator-crds chart to be installed first.
If you haven't already, install it with:

helm install mcp-lifecycle-operator-crds dist/chart-crds/

1. Verify the operator is running:

kubectl get deployment -n {{ .Release.Namespace }} {{ include "mcp-lifecycle-operator.fullname" . }}-controller-manager

2. Create an MCPServer resource:

kubectl apply -f - <<EOF
apiVersion: mcp.x-k8s.io/v1alpha1
kind: MCPServer
metadata:
name: test-server
spec:
source:
type: ContainerImage
containerImage:
ref: quay.io/containers/kubernetes_mcp_server:latest
config:
port: 8080
EOF

3. Check the MCPServer status:

kubectl get mcpservers

For more information, visit: {{ .Chart.Home }}
72 changes: 72 additions & 0 deletions dist/chart/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "mcp-lifecycle-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "mcp-lifecycle-operator.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 "mcp-lifecycle-operator.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

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

{{/*
Selector labels
*/}}
{{- define "mcp-lifecycle-operator.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mcp-lifecycle-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
control-plane: controller-manager
{{- end }}

{{/*
Create the name of the service account to use.
*/}}
{{- define "mcp-lifecycle-operator.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (printf "%s-controller-manager" (include "mcp-lifecycle-operator.fullname" .)) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Controller manager image
*/}}
{{- define "mcp-lifecycle-operator.image" -}}
{{- if contains "@" .Values.image.repository }}
{{- .Values.image.repository }}
{{- else }}
{{- printf "%s:%s" .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) }}
Comment thread
aliok marked this conversation as resolved.
{{- end }}
{{- end }}
85 changes: 85 additions & 0 deletions dist/chart/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mcp-lifecycle-operator.fullname" . }}-controller-manager
namespace: {{ .Release.Namespace }}
labels:
{{- include "mcp-lifecycle-operator.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
{{- include "mcp-lifecycle-operator.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: manager
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "mcp-lifecycle-operator.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: manager
image: {{ include "mcp-lifecycle-operator.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- /manager
args:
{{- if .Values.leaderElection.enabled }}
- --leader-elect
{{- end }}
- --health-probe-bind-address={{ .Values.healthProbe.bindAddress }}
- --metrics-bind-address={{ .Values.metrics.bindAddress }}
ports:
- name: metrics
containerPort: {{ .Values.metrics.service.port }}
protocol: TCP
- name: health
containerPort: {{ .Values.healthProbe.port }}
protocol: TCP
livenessProbe:
httpGet:
path: /healthz
port: {{ .Values.healthProbe.port }}
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: {{ .Values.healthProbe.port }}
initialDelaySeconds: 5
periodSeconds: 10
resources:
{{- toYaml .Values.resources | nindent 12 }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
serviceAccountName: {{ include "mcp-lifecycle-operator.serviceAccountName" . }}
terminationGracePeriodSeconds: 10
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
41 changes: 41 additions & 0 deletions dist/chart/templates/leader-election-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "mcp-lifecycle-operator.fullname" . }}-leader-election-role
namespace: {{ .Release.Namespace }}
labels:
{{- include "mcp-lifecycle-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
{{- end }}
17 changes: 17 additions & 0 deletions dist/chart/templates/leader-election-rolebinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "mcp-lifecycle-operator.fullname" . }}-leader-election-rolebinding
namespace: {{ .Release.Namespace }}
labels:
{{- include "mcp-lifecycle-operator.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "mcp-lifecycle-operator.fullname" . }}-leader-election-role
subjects:
- kind: ServiceAccount
name: {{ include "mcp-lifecycle-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
Loading
Loading