5 ms·
I'm not intimately familiar with those, but I did a lot of similar things with scripts. As far as I can tell: those are imperative. At least in some areas. Ku
by silviogutierrez 6y ago
I'm not intimately familiar with those, but I did a lot of similar things with scripts.
As far as I can tell: those are imperative. At least in some areas.
Kubernetes is declarative. You mention the end state and it just "figures it out". Mind you, with issues sometimes.
All abstractions leak. Note that k8s's adamance about declarative configuration can make you bend over backwards. Example: running a migration script post deploys. Or waiting for other services to start before starting your own. Etc.
I think in many ways, those compete with Terraform which is "declarative"-ish. There's very much a state file.
- bcrosby95 6y agoI've only ever used cfengine and Ansible, but they are both declarative. Hell, Ansible uses yaml files too. I would be somewhat surprised to find out Puppet and Chef weren't declarative either. Because setting up a system in an imperative fashion is ripe for trouble. You may as well use bash scripts at that point. I've used Ansible for close to 10 years for hobby projects. And setting up my development environment. Give me a freshly installed Ubuntu laptop, and I can have my development environment 100% setup with a single command.
- james-mcelwain 6y agoEven though Ansible is declarative in spirit, in practice I feel like a lot of playbooks just read like imperative code.
- fastball 6y agoI use Ansible for managing my infra, and the only time my playbooks look imperative is when I execute a shell script or similar, which is about 5% of total commands in my playbooks.
- takeda 6y agoOne way to test if your playbook is declarative is try to rearrange the states and have them in different order. If the playbook breaks with different order it is imperative.
- silviogutierrez 6y agoCheck out nix for actual development environments. Huge fan of that as well. I can buy a new laptop and be back to 100% in a few minutes. Though the amount of time I spent learning how to get there far exceeds any time savings. Ever.
- sam_lowry_ 6y agoHm... I just dd my hard disk to the new one and launch gparted to resize. A few years ago I even bothered to have two EFI loaders: one for amd an one intel, in case I want to change architecture as well.
- open-paren 6y agoI've been testing out nix and I haven't found out how to install packages in a declarative way yet. Using "nix-env -iA <whatever>` seems really imperative. How are you doing that? Do you use something like home-manager, or do you just define a default.nix and then nix-shell it whenever you need something?
- silviogutierrez 6y agoI've avoided home manager for now. I'll get into it soon. Instead, every project I work on has a shell.nix in the root (and if it's not a project I control, I have a shell.nix mapping elsewhere). Check it out, run nix-shell. Profit. Once you're really ready for the big leagues, run it with --pure.
- takeda 6y agoYes `nix-env -iA` is installing packages in an imperative way. I think it is there to be some kind of tool that people from other OS can relate to. Purist say you should avoid using it for installing packages and instead list global packages in `/etc/nixos/configuration.nix` for globally installed packages and home-manager for user specific ones, and if you need temporarily just to try something out use `nix-shell -p <whatever>`. Back to your second question, you can configure the system through `/etc/nixos/configuration.nix` it is enough to configure system as a service. Pretty much everything you could do through Chef/Puppet/Saltstack/Ansible/CFEngine etc. home-manager is taking it a step further and do this kind of configuration per user. It is actually written in a way that can be added to NixOS (or nix-darwin for OS X users) to integrate with the main configuration so then when you're declaring users you can also provide a configuration for each of them. So it all depends what you want to do, the main configuration.nix is good enough if your machine to run specific service, that's pretty much all you need, you don't care about each user configuration in that scenario, you just create users and start services using them. If you have a workstation, home-manager while not essential can be used to take care of setting up your individual user settings, stuff like dot-files (although it goes beyond that). The benefit of using home-manager is that most of what you configure in it should be reusable on OS X as well. If you care about local development, you can use Nix to declare what is needed, for example[1]. This is especially awesome if you have direnv + lorri installed you can add these to home-manager configuration: programs.direnv.enable = true; services.lorri.enable = true; When you do that you magically will get your CDE (that includes all needed tools, in this case proper python version, you also enter equivalent of virtualenv with all dependencies installed and extra tools) by just entering the directory, if you don't have them installed all you have to do is just call `nix-shell`. I also can't wait when Flakes[2] get merged. This will standardize setup like this and enable other possibilities. [1] https://github.com/takeda/example_python_project https://github.com/takeda/example_python_project [2] https://www.tweag.io/blog/2020-05-25-flakes/ https://www.tweag.io/blog/2020-05-25-flakes/
- geofft 6y agoAnsible is YAML, but it's definitely imperative YAML - each YAML file is a list of steps to execute. It uses YAML kind of like how Lisp uses S-expressions, as a nice data structure for people to write code in, but it's still code. Sure, the steps are things like "if X hasn't been done yet, do it." That means it's idempotent imperative code. It doesn't mean it's declarative. CFEngine is slightly less imperative, but when I was doing heavy CFEngine work I had a printout on my cubicle wall of the "normal ordering" because it was extremely relevant that CFEngine ran each step in a specific order and looped over that order until it converged, and I cared about things like whether a files promise or packages promise executed first so I could depend on one in the other. Kubernetes - largely because it insists you use containers - doesn't have any concept of "steps". You tell it what you want your deployment to look like and it makes it happen. You simply do not have the ability to say, install this package, then edit this config file, then start this service, then start these five clients. It does make it harder to lift an existing design onto Kubernetes, but it means the result is much more robust. (For some of these things, you can use Dockerfiles, which are in fact imperative steps - but once a build has happened you use the image as an artifact. For other things, you're expected to write your systems so that the order between steps doesn't matter, which is quite a big thing to ask, but it is the only manageable way to automate large-scale deployments. On the flip side, it's overkill for scale-of-one tasks like setting up your development environment on a new laptop.)
- fastball 6y agoHow does K8s know what order to do things in if there aren't steps? Because on a system, certain things obviously need to happen before other things.
- twblalock 6y agoYou can save your Kubernetes manifests in any order. Stuff that depends on other stuff just won't come up until the other stuff exists. For example, I can declare a Pod that mounts a Secret. If the Secret does not exist, the Pod won't start -- but once I create the Secret the pod will start without requiring further manual intervention. What Kubernetes really is, under the hood, is a bunch of controllers that are constantly comparing the desired state of the world with the actual state, and taking action if the actual state does not match. The configuration model exposed to users is declarative. The eventual consistency model means you don't need to tell it what order things need to be done.
- takeda 6y agoChef and from what I heard, since I didn't use it, Puppet are declarative, but since their DSL is really Ruby, it is really easy to introduce imperative code. Ansible uses YAML, but when I used it few times it felt that you still use it in imperative way. The saltstack (which also uses YAML) was the closest from that group (never used CFengine, but the author wrote research paper and shown that declarative is the way to go, so I would imagine he would also implement it that way). If you truly want a declarative approach designated from a ground up, then you should try Nix or NixOS.
- reddit_clone 6y agoChef can be declarative. If you stick to the resources and templatized config files. But it has full power of ruby at your disposal (both at load/compile time and run time). So it usually turns imperative quickly.