The problem
kubectl has a decent mechanism for querying kubernetes objects by label but sometimes you will need to get pods, services, or anything else by querying their annotation.
Some dudes asked for annotation query support here but it is not planned at the moment:
You cannot query annotations in Kubernetes, and this will not change in the foreseeable future.
To achieve that, you will find on the internet a way to achieve that with jsonpath. Here is an example taken from Fabian Lee’s blog:
# service that has annotation, regardless of value
kubectl get service -A -o jsonpath='{.items[?(@.metadata.annotations.prometheus\.io/scrape)].metadata.name}'
# has annotation set to "true"
kubectl get service -A -o jsonpath='{.items[?(@.metadata.annotations.prometheus\.io/scrape=="true")].metadata.name}'
# pull multiple values for the object
kubectl get service -A -o jsonpath='{range .items[?(@.metadata.annotations.prometheus\.io/scrape=="true")]}{ .metadata.namespace },{ .metadata.name}{"\n"}{end}'
What the fuck! I will never remember this boring syntax! It is too long to type this shit on my keyboard! I just want to get my k8s resources quickly!
kubectl plugin to the rescue
Hopefully, it is quite easy to create a kubectl plugin to do that. A kubectl plugin is just an executable file written in the language of your choice, located in your $PATH, with a name starting with kubectl-something
For the demo, I created a pod and its service, with the annotation server=mail
, and 2 plugins.
3 kubectl plugins
~/.local/bin/kubectl-filterannotation
#!/usr/bin/env bash
function _filter_annotation () {
ANNOTATION=${1:-}
echo "{range .items[?(@.metadata.annotations.${ANNOTATION//./\.})]}{ .metadata.name }{'\n'}{end}"
}
if [ "$1" == "--help" ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$#" -eq 0 ]
then
cat << EOF
Search for resources with a given annotation.
Usage: kubectl filterannotation your-annotation-name your-usual-kubectl-command
Examples:
Get pods who have annotation server:
kubectl filterannotation server get pods
Get services who have annotation server:
kubectl filterannotation server get svc
EOF
exit 0
fi
kubectl -o jsonpath="$(_filter_annotation ${1})" "${@:2}"
With this plugin, you can search if you have objects with a given annotation.
The syntax is: kubectl filterannotation your-annotation-name your-usual-kubectl-command
.
As an example, you want to get pods who have the annotation “server”. Instead of kubectl get pods
, you will type:
kubectl filterannotation server get pods
If you want to search for services:
kubectl filterannotation server get services
~/.local/bin/kubectl-filterannotationvalue
#!/usr/bin/env bash
function _filter_annotation_value () {
ANNOTATION=${1:-}
VALUE=${2:-}
echo "{range .items[?(@.metadata.annotations.${ANNOTATION//./\.}=='${VALUE}')]}{ .metadata.name }{'\n'}{end}"
}
if [ "$1" == "--help" ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$#" -eq 0 ]
then
cat << EOF
Search for resources with specific value for a given annotation.
Usage: kubectl filterannotationvalue your-annotation-name your-annoation-value your-usual-kubectl-command
Examples:
Get pods who have annotation server and mail value:
kubectl filterannotationvalue server mail get pods
Get services who have annotation server and mail value:
kubectl filterannotationvalue server mail get svc
EOF
exit 0
fi
kubectl -o jsonpath="$(_filter_annotation_value ${1} ${2})" "${@:3}"
This second plugin is working in the same way, but instead of searching only for annotation name, you can filter on the value too.
Imagine you want to query pods and services with the “server” annotation and “mail” value:
kubectl filterannotationvalue server mail get pods,svc
Maybe these 2 plugins are not perfect but it is a good start. You can create your owns who fits your needs :-)
Protip: If you call these plugins without argument, a help message will be displayed ;-)
~/.local/bin/kubectl-getannotationvalue
#!/usr/bin/env bash
function _filter_annotation () {
ANNOTATION=${1:-}
echo "{range .items[?(@.metadata.annotations.${ANNOTATION//./\.})]}{ .metadata.name }{'\n'}{end}"
}
if [ "$1" == "--help" ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$#" -eq 0 ]
then
cat << EOF
Search for resources with a given annotation.
Usage: kubectl filterannotation your-annotation-name your-usual-kubectl-command
Examples:
Get pods who have annotation server:
kubectl filterannotation server get pods
Get services who have annotation server:
kubectl filterannotation server get svc
EOF
exit 0
fi
kubectl -o jsonpath="$(_filter_annotation ${1})" "${@:2}" -o go-template --template "{{index .metadata.annotations \"${1}\"}}"
This plugin will help you to get annotation values.
Kubectl plugin documentation
My pod and service example
To test the commands while writing this blog post, I quickly created a pod and its associated service. Here is the manifest:
---
apiVersion: v1
kind: Pod
metadata:
annotations:
server: mail
labels:
app: mail
run: mailpit
name: mailpit
spec:
containers:
- image: anatomicjc/mailpit
imagePullPolicy: Always
name: mailpit
---
apiVersion: v1
kind: Service
metadata:
annotations:
server: mail
labels:
app: mail
run: mailpit
name: mailpit
spec:
ports:
- port: 1025
protocol: TCP
targetPort: 1025
selector:
app: mail
run: mailpit
type: ClusterIP