Instance flag and pathing
Background:
One of the nice things about SPIRE is the ability to run multiple instances of both the spire-agent and spire-server.
SystemD is being used more and more on linux systems for deploying services. It suipports having multiple instances of a service. You create a unit file like [email protected], and then can start a particular instance by providing a name after the @.
Ex, start two instances of spire-agent named a and b:
systemctl start spire-agent@a spire-agent@b
The SystemD unit uses a template to path out variables such as /var/run/spire/agent/sockets/%i/public/spiffe.sock
This all works pretty well except for the cli tools.
Problem: Say you want to run an agent command against the agent.
Ex:
spire-agent api watch -socketPath /var/run/spire/agent/sockets/a/public/spiffe.sock
This makes for a pretty hard to use cli though, as you have to remember where the system stores its sockets.
Proposed solution:
We make some new variables (exact names TBD): SPIFFE_PUBLIC SOCKET_TEMPLATE SPIRE_AGENT_PRIVATE_SOCKET_TEMPLATE SPIRE_SERVER_PRIVATE_SOCKET_TEMPLATE
ex:
export SPIFFE_PUBLIC_SOCKET_TEMPLATE=/var/run/spire/agent/sockets/%i/public/spiffe.sock
and add a new -i flag to the cli's.
spire-agent -i b api watch
Thanks for raising this issue. Multi-instance deployments with systemd templates is an interesting use case.
I have some concerns about adding template expansion logic (like %i substitution) directly into SPIRE's CLI, as this would couple SPIRE to systemd-specific conventions. SPIRE aims to remain platform-agnostic where possible.
I think that there are some alternatives that may work without the need of making changes in SPIRE:
-
Wrapper scripts: A simple bash wrapper could handle the instance selection and path construction, keeping the complexity outside of SPIRE.
-
Environment variables without templates: The systemd unit file could set an environment variable directly for each instance using systemd's Environment directive, avoiding the need for SPIRE to understand template syntax. The environment variable would then be used in the CLI invocation to specify the value of the -socketPath argument.
-
Existing config mechanism: Using per-instance configuration files with the existing -config flag.
Could any of these alternatives work for you? If there are specific constraints that make these approaches unsuitable, I'd be interested to understand them better.
Its not systemd specific. It is just a feature that can be easily used from a systemd based system. Sysadmins can do the same kind of setup using just a raw init based system and shell scripts.
I've already explored them over the last 6 months or so and feel adding the templated env var is probably less painful in the long run then those options. Here's why:
- A wrapper script would add confusion if it was called something else:
spire-instance-agent -i a api watch
spire-instance-server -i a entry show
The project will get questions about:
- "why sometimes its spire-instance-agent in docs and other times spire-agent".
- "Where did spire-instance-agent go. I installed from the tarball".
- "which one is better for what purpose"
- etc
Or if is was named the same, execs out to the real binary, would use a flag that wasn't in the normal spire-agent/spire-server that would be confusing.:
-
spire-agent -i a api watchworks on some systems, but on others says the flag doesnt exist. The version is the same. whats up? - The project would have to be careful not to use the -i flag.
- --help would be difficult to implement.
- Env switching would be worse then using the -socketPath because you would then have to:
export SOMETHING=/var/lib/spire/agent/socket/a/socket/spire.sock
spire-agent api watch
export SOMETHING=/var/lib/spire/agent/socket/b/socket/spire.sock
spire-agent api watch
rather then just:
spire-agent api watch -socketPath=/var/lib/spire/agent/socket/a/socket/spire.sock
spire-agent api watch -socketPath=/var/lib/spire/agent/socket/b/socket/spire.sock
so, its even longer to type/remember.
-
-config /etc/spire/agent/a/configisnt much easier to use then -socketPath=/var/lib/spire/agent/socket/a/socket/spire.sock
I think 3 though has an interesting extra thought. Rather then multiple env vars for the different sockets, it could be single template variable for agent and a single one for server that points to the config file rather then socket since there are more sockets then config files. So -i could be an alternate way of specifying -config rather then an alternate way of specifying -socketPath
Thank you @kfox1111 for your thoughtful feedback. You raised valid points.
We discussed this request in today’s maintainer sync and agreed to welcome a contribution implementing your approach. We appreciate your patience while we considered it.