Kiali, a developer journey — Day 2: Please Kube, what can I do?
Previously in “a developer journey”: Day 1, Some Background
Last week, I submitted a pull request that ended up being reverted due to a serious drop in performances in some pages. Woops. The goal of this PR was to get Kiali permissions from the Kubernetes cluster, for some operations like editing or deleting Istio objects, such as a virtual service.
At the moment, Kiali is a read-only software:
It makes you see what’s going on in your service mesh, view configured Istio resources, but you cannot bring any modification from Kiali. This is going to change. The first step is to read our own permissions from the Kubernetes cluster in order to, later, present the relevant actions in the GUI.
After some research and help from the team we decided to use the Kube’s SelfSubjectAccessReview request, from the authorization API. The performance drop that was experienced previously was due to running many queries against the Kubernetes API, as it expects only a single combination of parameters per query. So we had one query per combination of:
- verb (we want to get permissions for create, update and delete)
- resource type (such as destinationrules, virtualservices, etc. We manage 7 different types at the moment)
And of course, these queries cannot be grouped via the Kube go-client (as far as I know).
Consequently, while fetching the list of Istio resources in Kiali, we were performing 21 requests multiplied by the number of namespaces displayed. After thinking a while about caching Kiali permissions per namespace, we finally decided to simplify the task and fetch permissions only while loading a single Istio resource, and not while loading the list of all resources. Which boils down to just 3 queries (one per verb). Of course it means that we won’t be able to show edit or delete buttons from the list, but sometimes it’s better to accept trade-offs.
By the way: such discussions can take place on IRC #kiali, on the mailing list or sometimes directly in pull request comments or in JIRA comments.
Now that the context is set, let’s code! (don’t flee, it’s a small task, going to be quick and easy!)
The following changes are required:
1: Add permission flags in our model that is returned by the IstioConfigDetails endpoint. It’s the one called from that page:
The model structures used for the REST API are in… /models, you get it. So here it’s /models/istio_config.go. View changes.
2: Update the business layer (in /business). It is responsible for calling the lower layer clients (here, kubernetes client) and then it builds the REST API model. Within the existing GetIstioConfigDetails function, I’m adding a call to in.k8s.GetSelfSubjectAccessReview within a goroutine. View changes.
4: Adding a small test on the business layer, and we’re almost done. In VSCode, it’s possible to run a single tests from within the IDE:
Now is time to test (for real).
I always have a running OpenShift, most of the time using oc cluster up. There are many alternatives. You can run Maistra / istiooc, Minikube, Minishift, have a cluster provided somewhere using Rancher, Google Cloud or a vanilla Kubernetes… up to you.
make clean build test will build the binary and make sure there’s no broken test.
make docker-build openshift-deploy will… you get it! Build the docker image and deploy it on OpenShift.
After Kiali is deployed in the cluster, I can see that the permissions appear in the response, when navigating to an Istio Config item:
Last thing before I commit, since I modified the REST API model, is to regenerate swagger doc (which of course I forgot to do):
This will feed later our website’s API documentation: https://www.kiali.io/api/.
Finally, a Pull Request is opened, reviewed by peers, further discussions and changes may of course still happen before it is merged.
It’s the end of the day… I hope it was helpful for anyone willing to contribute and to help us improve Kiali!
: You may ask, why Go? Well, the language itself has pros and cons, but a good reason is that Kiali relies on other softwares also written in Go: Istio, Kubernetes, Prometheus. Hence it can consume their native API and models directly as lib dependencies, easily keeping it up-to-date. For the same reason, it makes it easy to build bridges with the related softwares and share communities.