Add extra custom labels to existing helm chart - kubernetes

I am using an existing helm chart repo
https://github.com/kubecost/cost-analyzer-helm-chart
For deployment I am using custom helm chart, have created tgz of the repo and put it under my own charts/ directory and then i put my own certain templates which deploys some resources related to cost-analyzer.
I want to assign some custom labels to the resources which are coming from that tgz.
Is there something/someway that i can add custom labels to all the resources which are deployed using my custom helm chart including the resource which are from tgz.

There is nothing built into Helm for doing that.
You can set the additionalLabels field in their Helm chart values.yaml file (there are multiple places this needs to be done).
A potential kludge could be to pull the manifests after deploying, get the name and type of every resource, and pump that into a kubectl command to label everything, for example:
HELM_RELEASE="???"
NAMESPACE="???"
LABEL="???"
helm get manifest $HELM_RELEASE -n $NAMESPACE \
| kubectl get -n $NAMESPACE -f - \
| grep -vE '^$|^NAME' \
| cut -d' ' -f1 \
| xargs -I {} kubectl label {} $LABEL

Related

How do I know which repository the installed Chart belongs to

I have many helm repositories in my kubernetes,
And I installed a lot of charts,
So How do I know which repository the installed Chart belongs to?
For example:
$> helm repo list
NAME URL
lucy-dev https://harbor.mydomain.net/chartrepo/lucy-dev
lucy-prod https://harbor.mydomain.net/chartrepo/lucy-prod
$> helm ls -n msgbox-lucy -o yaml
- app_version: "1.0"
chart: msgbox-lucy-8.27.3
name: msgbox-lucy
namespace: msgbox-lucy
revision: "48"
status: deployed
updated: 2022-04-19 08:11:16.761059067 +0000 UTC
I can't use helm show because:
$> helm show all msgbox-lucy -n msgbox-lucy --debug
show.go:195: [debug] Original chart version: ""
Error: non-absolute URLs should be in form of repo_name/path_to_chart, got: msgbox-lucy
...
I don't believe you're guaranteed to get the info you're looking for, however we can try.
Find the latest Helm secret for your Helm release.
kubectl get secret -n msgbox-lucy
Yours might look something like this:
sh.helm.release.v1.msgbox-lucy.v5
and run this command to view the chart's metadata:
SECRET_NAME="sh.helm.release.v1.msgbox-lucy.v5"
kubectl get secret $SECRET_NAME -o json | jq .data.release \
| tr -d '"' | base64 -d | base64 -d | gzip -d \
| jq '.chart.metadata'
The metadata should hopefully show you 2 things you're looking for. The chart name will be under the name field. The chart repository URL might be under sources.
I say "might" because the chart developer should have added it there, but they might not have.
Then you can match the URL to your repo alias.
If it's not included in the metadata, you're probably out of luck for now.
There is an open Github issue about exactly this feature you're wanting:
https://github.com/helm/helm/issues/4256
And an open PR that adds that feature:
https://github.com/helm/helm/pull/10369
And an open PR to add a HIP (Helm Improvement Proposal) for adding that feature:
https://github.com/helm/community/pull/224
You can run helm search repo <keyword>
This will search for the keyword msgbox-lucy in all your available repos and list results.
helm search repo msgbox-lucy
Official Doc : https://helm.sh/docs/helm/helm_search_repo/

Deploy separate k8s manifest files

I have a Spring boot application and I deploy the application to Kubernetes using a single k8s.yml manifest file via Github actions. This k8s.yml manifest contains Secrets, Service, Ingress, Deployment configurations. I was able to deploy the application successfully as well. Now I plan to separate the Secrets, Service, Ingress, Deployment configurations into a separate file as secrets.yml, service.yml, ingress.yml and deployment.yml.
Previously I use the below command for deployment
kubectl: 1.5.4
command: |
sed -e 's/$SEC/${{ secrets.SEC }}/g' -e 's/$APP/${{ env.APP_NAME }}/g' -e 's/$ES/${{ env.ES }}/g' deployment.yml | kubectl apply -f -
Now after the separation I use the below commands
kubectl: 1.5.4
command: |
kubectl apply -f secrets.yml
kubectl apply -f service.yml
sed -e 's/$ES/${{ env.ES }}/g' ingress.yml | kubectl apply -f -
sed -e 's/$SEC/${{ secrets.SEC }}/g' -e 's/$APP/${{ env.APP_NAME }}/g' deployment.yml | kubectl apply -f -
But some how the application is not deploying correctly, I would like to know if the command which I am using is correct or not
You can consider perform the sed first, then apply all files kubectl apply -f . instead of going one by one. Append --recursive if you have files in sub folder to apply, too.
Like the other answer says, you can ask kubectl to apply all files recursively in a directory.
Now the sed replaces are soon going to become overwhelming as the resources and configuration grow.
That is why kubctl comes with integrated kustomize support:
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
In short:
Break up all kubernetes resources into smaller files/components, put them in a directory.
Place a file called kustomization.yaml in same directory.
In the kustomization.yaml configure which file you want to apply, in which order, and also do some on-the-fly edits.
And apply with -k flag:
kubectl apply -k <kustomization_directory>

How to get a list of docker images given some kubernetes template?

To simplify, I want to list all the docker images defined in a helm chart.
For eg, let's say I have the following set of templates:
$ helm template jenkins/jenkins
https://charts.jenkins.io/
Then, I want to somehow use kubectl to parse this result so I can apply a filter such as:
kubectl get pods -l k8s-app=kube-dns -o jsonpath={.items[*].spec.containers[*].name}
To return me the list. However, that command is to get pods. Any clue?
EDIT: I found a way:
❯ helm template jenkins/jenkins | kubectl apply -f - --dry-run=client -o jsonpath="{..image}" | tr -s '[[:space:]]' '\n' | sort | uniq
bats/bats:1.2.1
jenkins/jenkins:2.263.1
kiwigrid/k8s-sidecar:0.1.275
With one drawback: kubectl needs to be connected to a cluster. I would like to prevent that.
You can use a different jsonpath to get all images:
kubectl get pods -A -o jsonpath="{..image}"
If you just want unique images: kubectl get pods -A -o jsonpath="{..image}" | tr -s '[[:space:]]' '\n' | sort -u.
Substituting -A for the namespace of your chart or manifests.
If you have the manifests on your machine and not deployed, of course, you can just grep: grep 'image: ' *.yml
You can also use Go template syntax:
kubectl get pods -A -o go-template --template="{{range .items}}{{range .spec.containers}}{{.image}} {{end}}{{end}}"
If you have more than one chart in a given namespace, I think grepping would be the best way: helm template some-chart | grep 'image:'
EDIT:
Since this will be running in CI, it would be better to use a little bit of code to avoid potential false positives. This Python script does the trick:
#!/usr/bin/env python3
import sys
import yaml # pip install PyYAML
from nested_lookup import nested_lookup # pip install nested-lookup
template = ""
for line in sys.stdin:
template += line
parts = template.split('---')
for p in parts:
y = yaml.safe_load(p)
matches = nested_lookup("image", y)
if (len(matches)):
print("\n".join(matches))
Usage: helm template jenkins/jenkins | ./this-script.py. It prints out each occurrence of images, so if you only want unique images you'd need to throw all the matches in a list, then unique that before printing (or pipe it to sort -u).

How to replace JSON value in kubectl output using go-template?

I have a configMap and I want to create a backup configMap by using the last applied configuration from that.
I use the following command to get the last applied configuration:
kubectl get cm app-map -n app-space \
-o go-template \
--template='{{index .metadata "annotations" "kubectl.kubernetes.io/last-applied-configuration"}}' > backup.json
It returns something like this [the content of backup.json]:
{"kind":"ConfigMap","apiVersion":"v1","metadata":{"name":"app-map","creationTimestamp":null},"data":{"app.yml":"xxxxxxxxx","config.yml":"yyyyyyyyy"}}
Now, I want my backup configMap to have a different name. So, I want to change the .metadata.name from app-map to app-map-backup.
Is there a way I can achieve that with kubectl and -o go-template? I want to have the name changed before I write it to the backup.json file.
I know I can do that using jq but I do not have permission to install jq on the server where I am using kubectl.
you could use kubectl bulk plugin. The below command will replicate your config map
# get resource(s) and create with field(name) change
kubectl bulk configmap app-map -n app-space create name app-mapp-backup
Kubectl bulk is very powerful to use, I suggest to check samples.
You cannot do this just using kubectl. But there are other ways.
You can download statically linked jq binary from official jq website:
wget https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
chmod +x jq-linux64
and then you can use this binary like following:
kubectl -o go-template [...] | ./jq-linux64 ...
or you can use sed:
kubectl -o go-template [...] | sed 's/"name":"app-map"/"name":"app-map-backup"/'

diff between whats active on cluster versus kustomize

kustomize's docs provides a nice one-liner that compares two different overlays...
diff \
<(kustomize build $OVERLAYS/staging) \
<(kustomize build $OVERLAYS/production)
is there a way to do the same but against what is running within a specific kubernetes namespace and that of a defined overlay on disk?
more specifically, knowing what an kubectl apply -k . would do without actually doing it? using --dry-run just says spits out a list of the objects rather than a real diff.
kustomize build ./ | kubectl diff -f -
In Kustomize version 4.x.x
If you're looking for a way to do this visually, I highly recommend trying the Compare & Sync feature from Monokle:
In the picture above you can see an example where I'm comparing the output of the cluster-install kustomization to the objects in my minikube cluster.
You can easily determine which resources are missing in your cluster and which ones are different.
On top of that, you're not limited to only comparing kustomizations to clusters. You can also compare two clusters, two kustomizations, helm charts, etc.
I'm not sure if this is what you are looking for, but in Kubernetes you have kubectl diff.
It's nicely explained on APIServer dry-run and kubectl diff.
You can use option -k, --kustomize which does:
Process the kustomization directory. This flag can't be used together with -f or -R.
Or maybe something similar to one-liner to set context for specific namespace:
$ kubectl config set-context staging --user=cluster-admin --namespace=staging
$ kubectl config set-context prod --user=cluster-admin --namespace=prod
Once you have context setup you could use them maybe in a following way:
kubectl config use-context staging; cat patched_k8s.yaml | kubectl config use-context prod; kubectl diff -f -
This is just an example which I did not tested.
Try this kustomize command, currently in alpha:
KUSTOMIZE_ENABLE_ALPHA_COMMANDS=true kustomize resources diff -k your/kustomize/overlay
via https://kubernetes.slack.com/archives/C9A5ALABG/p1582738327027200?thread_ts=1582695987.023600&cid=C9A5ALABG
I have a small function on my shell config to do this:
kdiff() {
overlay="${1}"
kustomize build ${overlay} \
| kubectl diff -f - ${#:2} \
| sed '/kubectl.kubernetes.io\/last-applied-configuration/,+1 d' \
| sed -r "s/(^\+[^\+].*|^\+$)/$(printf '\e[0;32m')\1$(printf '\e[0m')/g" \
| sed -r "s/(^\-[^\-].*|^\-$)/$(printf '\e[0;31m')\1$(printf '\e[0m')/g"
}
It drops the last-applied-configuration annotation and adds some color.