While working on managing our Rancher clusters is the management of Rancher projects. I want to talk about the approach I have taken, which may be useful to you as well.
A project is a group of namespaces, and it is a concept introduced by Rancher. Projects allow you to manage multiple namespaces as a group and perform Kubernetes operations in them. You can use projects to support multi-tenancy, so that a team can access a project within a cluster without having access to other projects in the same cluster.
The obvious resource to do that is rancher2_project, which allows you to manage a project and it’s resources. However, if you also want to manage the permissions, you also need
rancher2_role_template - Provides a Rancher v2 Role Template resource. This can be used to create Role Template for Rancher v2 and retrieve their information
rancher2_project_role_template_binding - Provides a Rancher v2 Project Role Template Binding resource. This can be used to create Project Role Template Bindings for Rancher v2 environments and retrieve their information
I consider projects, relatively static, so we can easily have multiple blocks like this
Then we also need the rancher2_role_template and rancher2_project_role_template_binding, which will lead to a lot of resources and relatively tedious if you have a lot of projects and role-bindings. So my aim is to manage projects and the related role bindings together, also so that developers which are eventually not so deep into terraform can easily adjust limits and so.
How I manage projects
So I decided to have a local map, which contains all projects and it’s configuration in a file called projects.tf
Projects can be dynamically created using a fore_each
How I manage roles
First we have to understand that roles are defined in the local cluster, and in order to create the bindings, we need the role_template_id of these roles. As each cluster has it’s own state file, we need first make the current cluster aware of the remote state of the local cluster, in file data.tf. Assuming we use azurerm as backend it would look like this:
We also need to expose the role_template_ids in a way, we can use them, hence we have this output.tf
Now we can access them using the rolename, so for example custom-read-only-role will be accessed like this:
As a next step, as I already have the list local.projects, I extend it with a map memebers
At last I create the role binding dynamically, but first I need to create an iterable list with all data from the members element of each project. Hence I iterate over all projects and grab the required inf
Which will get me this list
From this least I use for_each to create a resource for each binding
Conclusion
When working with a lot of objects of the same type, it fastly becomes tedious to manually create multiple similar resource blocks, and adjusting the values of each of the blocks without errors. I find it easier to have a easy manageable list/map and create resources dynamically. Luckily [Terraform] supports that, although in the beginning I struggled quite a bit to get the loops and inner loops correctly. Once you manage that, you have a lot of possibilities to make your config files much more manageable and readable.