1
votes

I've deploed an app to k8s using kubectl apply ... few weeks ago, the application is running in prod. Now we switch to helm installation and build chart that we want to update the application with it. The problem is that there is already deployed artifacts like secret/config maps of the application which I cannot delete.

And while running helm upgrade --install app chart/myapp -n ns

I got error like

Error: rendered manifests contain a resource that already exists. Unable to continue with install: existing resource conflict: namespace: ns, name: bts, existing_kind: /v1, Kind=Secret, new_kind: /v1, Kind=Secret

Is there any trick which I can use to overcome this without deleting the secret/configmap ?

2
are you doing this on your own customer cluster using Azure VMs or are you doing this on the managed k8s service on Azure like AKS? So in AKS - Helm already comes pre-installed. you can check more details about it from here: docs.microsoft.com/en-us/azure/aks/kubernetes-helm - Hassan Raza
@HassanRaza - we are managing our k8s, and have alredy helm installed, which working ok, this is not the question :) - bred straruts
No, helm does not have the ability to import existing resources. You need to rename them in helm so the names don't conflict, or delete them from the running cluster. github.com/helm/helm/issues/6561 - jordanm
When you deploy resources using Helm, some annotations is created in resources. you can try to deploy the secret with a different name and then try to copy the annotations to your running secret and deploy it again. In theory, it should work, since the control annotation will be present in the old resource. I will try in my lab env and back asap. - Mr.KoopaKiller
This might not be possible as helm can only upgrade resources that which was installed by helm..you can try if u can add those specific labels and annotation to trick helm if those resources were installed by helm but it might not be possible - Avinash Kumar

2 Answers

1
votes

After testing some options in my lab, I've realized that the way I told you in comments worked.

Helm uses information on metadata and labels are injected in the resources to know what are the resources managed by itself. The workaround below shows how you can import a previous created secret, not managed by Helm, using matadata information from a new secret deployed with Helm.

Let's suppose the my-secret is already deployed and you want to "import" that resource to helm, you need to get the metadata information of the new resource. Let's dig into it:

Scenario:

  1. A secret name my-secret deployed in default name space. (Not managed by Helm)
  2. A helm chart with a secret template named my-new-var with a different value.

Steps:

  1. Create a normal secret for testing purposes using this spec:
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret
    type: Opaque
    data:
      secret: S29vcGFLaWxsZXIK
  1. Apply the Helm chart to create the my-new-secret. The real purpose of that is get the metadata and labels information.

After that you can see the secret file using the command:

kubectl get secrets my-secret -o yaml:

apiVersion: v1
data:
  secret: VXB2b3RlSXQ=
kind: Secret
metadata:
  annotations:
    meta.helm.sh/release-name: myapp-1599472603
    meta.helm.sh/release-namespace: default
  creationTimestamp: "2020-09-07T10:03:05Z"
  labels:
    app.kubernetes.io/managed-by: Helm
  name: my-secret
  namespace: default
  resourceVersion: "2064792"
  selfLink: /api/v1/namespaces/default/secrets/my-secret
  uid: 7cf66475-b26b-415b-8c11-8fb6974da495
type: Opaque

From this file we need to get the annotations and labels to apply in our old my-secret.

  1. Edit the secret file created on step 1 to add thoses information. It will result in a file like that:
apiVersion: v1
data:
  secret: S29vcGFLaWxsZXIK
kind: Secret
metadata:
  annotations:
    meta.helm.sh/release-name: myapp-1599472603
    meta.helm.sh/release-namespace: default
  name: my-secret
  labels:
    app.kubernetes.io/managed-by: Helm
  namespace: default
  1. Delete the my-new-secret create by Helm, since we not longer use it: kubectl delete secrets my-new-secret

  2. In the Helm chart, edit the secret name to match with the old secret, in our case change the name from my-new-secret to my-secret.

  3. Upgrade the Helm chart, in my case I have used a value from Values.yaml:

$ helm upgrade -f myapp/values.yaml myapp-1599472603 ./myapp/
Release "myapp-1599472603" has been upgraded. Happy Helming!
NAME: myapp-1599472603
LAST DEPLOYED: Mon Sep  7 10:28:38 2020
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
0
votes

You can have helm hooks which can help you to remove it.

annotations:
  "helm.sh/hook": pre-install, pre-upgrade

Above annotation would help fixing this. Similar annotations can be added to resources which are not deleted by default such as ClusterRoles and such.

More hooks can be found here which can be used as per the need.