-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Library dependency system #301
Comments
Butane is currently designed around the assumption that all Butane configs are under the administrator's control. In other words, while a user might copy some config fragments from the Internet, they'll all ultimately be maintained in something like a single Git repo controlled by the user. That model may or may not be the right one, but I think there are some arguments in favor. Butane is intended as one tool in the toolbox, not as a grand unified configuration management engine. In some cases it'll be integrated into other components in the stack, e.g. Matchbox. And I don't think we want to build Yet Another Tool-Specific Registry Format. As a practical matter, I'm not sure that Butane configs will be complex enough to merit a lot of generic reuse. Unlike, say, many Ansible systems, user application code should all be running in containers. So, I'd expect the Butane config to be used mostly for disk configuration, some systemd services, and maybe a few host config files - and not much more. Do you have an example where this sort of mechanism would be especially useful?
We don't document this very well right now, but Afterburn metadata is the intended mechanism for node-specific network configuration.
For files that also need to be processed by external tools, you can use
I'm in favor! Any particular gaps you'd like to call out? |
Hi @bgilbert! Thanks for your answer.
My main concern is code duplication. To solve it, being able to reuse snippets of code (on the internet, maybe, but mainly my own snippets of code). For now, we can use the
I get that. Maybe butane will not be the answer for my need.
That is a good argument. However, consider how many services needs to be setup in a state-of-the-art machine today:
I believe this is quite a lot! Some important predicates:
Let’s say I have 30+ different-purpose web workers, here is what I would need to configure on each of them:
That’s not all. As you know:
Because of this "spaghetti bowl" compartmentalization, handling that many machines in the same git repository is simply not working in the long run (illustrated by the move towards micro services). That’s why I've been working for years with a highly granular code, each single machine having its own repository. Automation solving the problem of maintenance of that many repositories. With any other tool, libraries offers what I need: reusable, generic (or business-generic: generic but for my company) pieces of code, that I glue together with context variables in a repository representing a machine. The benefits are huge: every single component can be linted and tested independently and versioned making the overall system very robust:
With Butane… It is hard to deal with without a dependency system. I believe it’s gonna be an adoption problem for CoreOS, especially in companies. While a lot of people do static configurations and duplicate their code, it’s a huge brake for companies growth as the same things are repeated again and again.
It’s not only network configuration that needs to be passed. Secrets are one other important thing but also some flat values that are defined elsewhere. For example, I might define application ports, domain names, configuration values that I want to toggle, firewall rules, etc in infrastructure code (CloudFormation, Terraform…). These values are sometimes known at runtime, so I have no choice but pass them to Butane at runtime. Right now, I use Terraform templating system to inject these values but, it forces me to have a single butane file, otherwise needing to know what variables is in what file, which is a nightmare to maintain as it breaks separation of concerns. If Butane itself would accept variables as inputs and would be able to replace them before compile, it would change everything: no need to use any external template system and I would be able to split the butane code to simplify linting and unit testing.
First and foremost good practice is code duplication avoidance because consequences are dire! I was mentioning that if a dependency system is implemented in Butane one day. Technicalities about such system would surely be documented, but good practices are often overlooked. Ansible is a very bad example in the matter: it’s really hard to know how to do things correctly just be reading the documentation. That was a very long answer, I hope it will spark more discussions. I'll be happy to clarify some points if required. Also, if you see the purpose of all that but believe it should not belong to Butane itself, what can I leverage to make this happen in this community? |
Thanks for the detailed response; that's very helpful. Your usage model is largely aligned with how we think about FCOS (immutable cloud nodes with automated provisioning and declarative configuration), but interestingly, you're using individually configured "pet nodes". We think of large-scale FCOS deployment in terms of undifferentiated "cattle nodes", each of which can have arbitrary workloads scheduled onto them via some orchestrator (which is often but not necessarily Kubernetes). On the Butane side, it means the config matrix is typically environment x node-type, independent of workload. In your case, you're using Butane as a central component of your orchestration, so your configs also need to know about workloads. That puts more pressure on the Butane design. You can still use Butane in your model, but you'll have to add some infrastructure around it. If I were building the system you're describing with today's Butane, my first cut would use Butane + Git submodules + some templating system (maybe just We should still have a useful set of features, though. I think you're asking for three things: building a config from smaller ones (#118) that are maintained in separate repositories (this bug) and templated with context variables (#111). I think both #111 and #118 are worth pursuing in some form, for improved ergonomics. I'd like more information on the separate repo part, because I don't think Butane should handle this; In any event, we should certainly document a suggested workflow. |
Hello @bgilbert (sorry for the late answer)
That’s correct. If I do go full modern infrastructure, it’s hard to see if I will not hit a wall, not because I do not trust these tools to work, but I'm afraid the software I migrate might not be mature enough. In essence, I think that immutable-like OS like CoreOS and others are too good not to use, even in a kind of "pet" mode as you put it.
As far as I know git submodules will not handle pinning properly. The main (huge) advantage of separate repos is to be able to pins, hence, facilitate lifecycle of the code: try an update by pinning new version? Introduced some bugs? Rollback the pin. I'm not just talking about one repo depending on another one: but potentially 20 repos depending on 20, depending on 20… Any change in a transitive dependency can break several parts, let’s say, when someone uses a "feature" that was not intended originally (the linux kernel have this problem a LOT). Again: by pinning, it’s possible to let repositories that are ready to update while giving the time for everyone to fix their things before updating: the agility to test, update and rollback easily. I'm pretty sure this is debatable as it’s mainly from my personal experience, but so far I verified that in many context. For me, multi repositories have two advantages: be able to handle tags and pinning (as I demonstrate here) and to fine-tune users permissions in multi-team complex scenarios. After some months, here is how we solve the issues I mentioned: We create "snippets" of Butane code, one per repository, that we tag. A pipepline deploy each Butane repository as a pinned artifact. While it achieves what Iwe want to do, the big drawback that it’s very dependent on Terraform, the Terraform provider and a rather complex pipeline (manual artifact fetching). |
Thanks for the additional info. What specifically about the git submodule system won't work for you? Submodules are pinned to a specific commit of the submodule repo, and the pin is moved by making a new commit that updates the pin object. |
We find it hard to maintain inter-dependencies, updates, having to use many command lines to make sure the submodule is properly updated. I’ve been working on medium-size projects with 50 plus dependencies. Just imagine having to set them up manually instead of just maintaining a I see git submodule as a neat solution when you have to split code into multiple repositories of a single application, not to simulate a dependency system. As a consequence it lacks all the interesting features of the such systems:
Just to be clear: I'm not imagining all the the above for Butane. I believe that just the ability to call "snippets" of code with some kind of inheritance+ transitive dependency discovery would already be amazing. A dummy code example: variant: fcos
version: 1.6.0
snippets:
-
name: healthcheck-system
engine: git
url: https;//gitrepo/my/git.butane-dep.git
ref: 3.2.3
-
name: monitoring
engine: git
url: https;//gitrepo/my/git.monitoring-dep.git
ref: 2 (engine is an implementation of a code repository. I know it’s a lot more that it appears to be on this code example but:
|
Yes, it will. The parent repository stores the intended commit hash of each submodule.
One possibility is to write some wrapper code that provides a friendlier interface. You're right, though, that certain features like floating pins can't be handled by submodules.
#118 covers inheritance between Butane configs, and I do think we should pursue that. I believe the separate repository handling can be handled effiectively by another tool, with a separate config file, that clones the correct repositories and checks out the appropriate commits. (The tool could reduce disk space requirements by keeping a central archive of repos and creating shared clones as needed.) For example:
variant: fcos
version: 1.6.0
ignition:
config:
merge:
- local_butane: healthcheck-system/main.bu
- local_butane: monitoring/main.bu
modules:
-
name: healthcheck-system
engine: git
url: https;//gitrepo/my/git.butane-dep.git
ref: 3.2.3
-
name: monitoring
engine: git
url: https;//gitrepo/my/git.monitoring-dep.git
ref: 2 Conveniently, the tool that reads (Though, I've been assuming that child Butane configs would inherit the In general, the workflow you're describing is substantially different from the primary way we expect Butane to be used (xref #301 (comment)), and the functionality you're looking for would take a substantial amount of work to implement. This might be worth doing, but is not going to be on the Butane roadmap for a long time, if ever. To avoid getting anyone's hopes up who may run across this ticket, I'll go ahead and close it. I really do appreciate the discussion. I'd strongly encourage you to either use an existing general-purpose dependency management system, if there's a suitable one, or to consider writing and releasing a tool that meets your requirements. That tool could even offer native integration with Butane if that would be useful. |
Understood. 👍 Many thanks for listening! |
Allow me to give a bigger picture for this.
Butane is (becoming) another provisioning/configuration management tools, à la Ansible, Chef or puppet.
Contrary to these tools, it lacks essential features, including the "merge" of different configuration files, because code de-duplication:
roles
(backend: ansible-galaxy) to use in playbooks.recipes
(backend: chef-server/automate) to use in cookbooks.modules
(backend: Terraform registry) to use in other modules.pip
(backend: pypi) to use in python scripts.For now, Butane lacks this kind of “library dependency system”:
I think what is happening with butane/ignition and coreOS is very exciting! Although, I believe Butane is now the heart of coreOS adoption for DevOps and Sysadmins, but compared to other provisioning tools, it’s still a bit dry.
Can you consider not only this feature, but plan for the need to have a proper library management system for Butane?
Originally posted by @gui-don in #118 (comment)
The text was updated successfully, but these errors were encountered: