adopt existing helm resources
Every once in a while, you need to install a helm chart that corresponds with
already existing resources. Usually, when trying to use a helm chart to have
more control over a kube-system daemonset or operator: aws-node, coreDNS, or
kube-proxy for instance. But if you try to install their helm chart you can
get Error: INSTALLATION FAILED: rendered manifests contain a resource that
already exists.
You can get helm to adopt resources by using the correct
annotation/labels.
tldr
For each pre-existing resource run:
kubectl annotate $OBJ meta.helm.sh/release-namespace=${NAMESPACE}
kubectl annotate $OBJ meta.helm.sh/release-name=${RELEASE_NAME}
kubectl label $OBJ app.kubernetes.io/managed-by=Helm
then run helm install
or helm upgrade
Setting the stage
Let’s create an example deployment and service. Using kubernetes yaml. Then we will attempt to wrap these resources into a helm chart.
http-echo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-echo
labels:
app: http-echo
spec:
replicas: 3
selector:
matchLabels:
app: http-echo
template:
metadata:
labels:
app: http-echo
spec:
containers:
- name: echo
image: hashicorp/http-echo
args:
- "-text=success"
---
kind: Service
apiVersion: v1
metadata:
name: echo-service
labels:
app: http-echo
spec:
type: LoadBalancer
selector:
app: http-echo
ports:
# Default port used by the image
- port: 5678
Apply and verify that everything works
kubectl apply -f http-echo.yaml
kubectl get pods,deployment,service -l app=http-echo
NAME READY STATUS RESTARTS AGE
pod/http-echo-58c8855bc6-62zjv 1/1 Running 0 5m
pod/http-echo-58c8855bc6-rbgqm 1/1 Running 0 5m
pod/http-echo-58c8855bc6-vrd2d 1/1 Running 0 5m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/http-echo 3/3 3 3 5m
NAME TYPE CLUSTER-IP EXTERNAL-IP
service/echo-service LoadBalancer 10.96.182.49 172.18.0.150
Wrapping in a helm chart
We can use a minimal Chart.yaml file for this example.
Chart.yaml
name: http-echo
version: 0.1.0
And setup a basic helm chart directory
http-echo/
├── Chart.yaml
└── templates
└── http-echo.yaml
1 directory, 2 files
The problem is that all of the resources that are specified in
templetes/http-echo.yaml already exist. When we try to install this chart
via helm install http-echo http-echo/
we get met with:
Error: INSTALLATION FAILED: rendered manifests contain a resource
that already exists. Unable to continue with install: Service
"echo-service" in namespace "default" exists and cannot be
imported into the current release: invalid ownership metadata;
label validation error: missing key
"app.kubernetes.io/managed-by": must be set to "Helm"; annotation
validation error: missing key "meta.helm.sh/release-name": must
be set to "http-echo"; annotation validation error: missing key
"meta.helm.sh/release-namespace": must be set to "default"
Annotate and label existing resources
Each resource needs two annoations and a label to be adopted by Helm.
annotations
meta.helm.sh/release-namespace
meta.helm.sh/release-name
label
app.kubernetes.io/managed-by
for OBJ in deployment/http-echo service/echo-service
do
kubectl annotate $OBJ meta.helm.sh/release-namespace=default
kubectl annotate $OBJ meta.helm.sh/release-name=http-echo
kubectl label $OBJ app.kubernetes.io/managed-by=Helm
done
Run helm install --dry-run http-echo http-echo/
to show the error no longer
exist; without actually installing the chart.
More Information
This doesn’t work with CRD objects
It does! You need to annotate/label the CRDs as usual. But then set
--skip-crds
. Most charts have a crd.create = false setting.