Skip to content
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

Add a way to run a script outside of the ostree root after build #96

Closed
wants to merge 1 commit into from

Conversation

mscherer
Copy link
Contributor

While running a postprocess script inside is sufficient for
lots of use case, being able to tun outside permit to avoid
polluting the ostree root. One of such use case would
be to use ansible outside of the root, to configure things
inside the root.

While running a postprocess script inside is sufficient for
lots of use case, being able to tun outside permit to avoid
polluting the ostree root. One of such use case would
be to use ansible outside of the root, to configure things
inside the root.
@mscherer
Copy link
Contributor Author

My motivation for this is to be able to reuse ansible and my existing playbook to run and install ostree image that i can then deploy on server ( using 'ansible-playbook -c chroot -i "$OSTREE_ROOT," foo.yml, ).

While this approach will work ( just requires a wrapper script ), I wonder if being able to give directly a command line wouldn't be better ( but slightly more complex to code ). I pushed the PR for discussion for now, but I forgot the doc, so it is not ready to be merged. And would like some feedback on the way we call the option, if someone has a better name for it ?

@mscherer
Copy link
Contributor Author

After a while, i decided to see if I couldn't directly give a playbook as a argument, so produced a different branch:
mscherer@217c8c0

@cgwalters
Copy link
Member

The original vision for rpm-ostree was to basically be "yum on the server side", and that's the current state. What that means is that the composed tree is not configured - you have to use something like cloud-init/kickstart to set up authentication, and then a generic config system like Ansible/Puppet per host.

What this is doing is blurring all of those domains together with compose-side confmgmt, which is a new direction. Now, I can see some benefits and drawbacks to this. A benefit here is that your system state description becomes stronger - because the Ansible run happened on the server side, when you atomic upgrade and reboot you know it's applied. You don't have to go in post-facto as part of a playbook.

However, there are disadvantages too. First, OSTree was not designed for carrying secrets (such as the provisioned root password, etc.). You can of course just do all fetches over TLS which provides confidentiality, but it wasn't part of the design today.

Another concern I have is that it increases the amount of respinning that's required as the RPMs change. For example, if you end up with multiple trees with different configuration per host type (e.g. you have a "frontend webserver" tree, a "database server" tree) that means that when say the next security errata for bash happens, each of those trees will need updating. That should of course not be difficult to do, and we will be increasing efficiency of the compose process. But it's still a concern.

So I guess what I'm getting at is - is this patch an experiment, or are you fairly confident that you want to do pre-configured trees?

@mscherer
Copy link
Contributor Author

I was aiming something in the line of the nixos stateless deployment idea ( http://gfxmonk.net/2015/01/03/nixos-and-stateless-deployment.html ), or at least, have something open enough to make this doable. Respin was not so long ( 10 minutes for a minimal system on my laptop, mostly I/O bound ), even if I guess starting to generalize this would mean having a rather complicated system.

So far, that was a experiment.

I didn't played enough with pre-configured tree to see, but I am quite sure that this would permit to enable something less minimalistic than * atomic host ( besides servers, one use case I had in mind were internal corporate laptops, where some people seldomly run update by themself, and where we cannot run upgrade in the background as they are not atomic ). Now indeed, the problem of populating /etc properly is open.

Another thing is that configuration is sometime tied to runtime. Let's take the case of apache. If I have a apache 2.2 and want to test a upgrade on 2.4, I cannot keep the same configuration, since the format changed for some directive regarding authentication, and some modules changed their names. In practice, I can work around with specific trick on the apache side, but that the exception more than the norm. So if I want to test apache 2.4 and decide to revert, then I have to reconfigure it again. If the configuration is part of the atomic upgrade, then it is also part of the downgrade.

@cgwalters
Copy link
Member

FWIW my conclusion on Nix was:
➕ Derivations are certainly nicer than spec files
➖ But rebuilding everything for a potential glibc security errata that changes a header file is very impractical for most of the world

This is a fantastically complex discussion; we haven't even mentioned Docker yet 😄 Or things like NixOS's ability to do installs as non-root (which the RPM world doesn't really do).

What I'm thinking on this issue though is that if the goal is to better support merging OS + config on a compose server, it would work best if rpm-ostree was a shared library effectively. And if say you were using Ansible, then you would have a YAML entry like:

    - rpmostree: name={{ item }} branch=examplecom/{{ arch }}/frontend-server
      with_items:
        - git
        - httpd
        - vim

And a higher level tool would know how to consume the special rpmostree entry and also do ansible --chroot with the rest of the config, or so? That way you only have one declarative language, and admins wouldn't need to be exposed to the underlying rpm-ostree binding bits as much. The packages become just something pulled in declaratively as part of defining a system.

@cgwalters
Copy link
Member

I forgot to mention of course that rpm-ostree has always been declarative, which is fundamentally different from traditional yum/apt-get/etc., and more like NixOS. I mentioned that here http://lwn.net/Articles/628748/

@cgwalters
Copy link
Member

Concretely in this PR, I'm uncertain about rpm-ostree calling ansible.

  • There are other management tools out there, does rpm-ostree start knowing about all of them?
  • Honestly while I think the treefile format is OK for rpm-ostree's small scope, IMO the Ansible YAML is nicer, and given that sysadmins will presumably be writing much more extensive Ansible code than treefiles, it makes sense for Ansible to drive rpm-ostree than the other way around.

Making rpm-ostree a library could even just be breaking up compose tree like:

rpm-ostree compose tree-prepare /path/to/treefile.json /var/tmp/tmptree.XXXXXX
ansible-playbook playbook.yml --chroot /var/tmp/tmptree.XXXXXX
rpm-ostree compose tree-commit /path/to/treefile.json /var/tmp/tmptree.XXXXXX

?

@cgwalters
Copy link
Member

Before I forget, this is a cool thing to experiment with, and thanks for submitting the patch 😄

@mscherer
Copy link
Contributor Author

Well, I think I didn't explain the PR correctly. I have basically 2 differents code.

One is to tell "run this script after the build, but outside of the tree". That's what this PR is about. Providing a wrapper script permit to use more than ansible, without being forced to use any of them. I think that's the most generic solution out there.

However, since my goal was to run ansible, I directly merged and made a different branch to play, which is not proposed to be merged. I found it more elegant for my purpose, but obviously, not generic enough. If there was a plugin system, I would have likely tried to add that as a plugin.

The idea of having a ostree ansible module seems interesting. Since you can dynamically inject a host in the list of ansible managed host after creating it ( example, ask for a vm on openstack, then start to manage it ), the same could be done with a rpmostree module that create the compose tree, give back the directory, then we could inject it in the list, modify it, and then commit the tree.

So your proposal to split rpm-ostree compose in 2 operations would be ok for me. A library would be nice, but calling binary is ok for me. If the rpm-ostree compose tree-prepare command could take a --json flag, and return the tree as a result, it would be perfect for me, but I can do that also in the ansible module.

@jdieter
Copy link

jdieter commented Feb 23, 2015

Ok, sorry for joining this late. I'm looking to use rpm-ostree to create a standard image for our school's desktops. I used to use rpms for configuration, but for F21, we switched to kickstart+ansible, which has been much easier to work with.

I think splitting rpm-ostree compose into two operations would make life much easier for me. I can translate my kickstart into a treefile pretty easily, but the ansible stuff is a whole lot more complex and I'd far prefer to just run ansible on the image before committing it.

One thing I don't understand is why we need a new commit operation. If rpm-ostree just stopped after preparing the tree, couldn't we just run ostree commit after running ansible?

@cgwalters cgwalters added the WIP label Apr 16, 2015
@cgwalters
Copy link
Member

http://www.ansible.com/blog/immutable-systems is also related to this - the concerns with cloud images are pretty similar to ostree commits.

@mscherer
Copy link
Contributor Author

mscherer commented Aug 5, 2015

Since I did broke a few VM because i underspecified them in term of memory ( and yum + selinux tend to consume too much ), immutable images and or offline upgrade ( ie, ostree ) would also help a lot for that.

@copumpkin
Copy link
Contributor

I'm also interested in this, also coming from a NixOS world.

@cgwalters
Copy link
Member

Let's move this to #471

cgwalters added a commit to cgwalters/rpm-ostree that referenced this pull request Oct 5, 2017
Right now `rpm-ostree compose tree` is very prescriptive about how
things work.  Trying to add anything that isn't an RPM is absolutely
fighting the system.  Our postprocessing system *enforces* no
network access (good for reproducibilty, but still prescriptive).

There's really a logical split between three phases:

 - "build a rootfs that installs packages"
 - "run postprocessing"
 - "commit result"

Our primary job is the first two - and we can do *either*. If for example
someone wants to use `rpm-ostree compose install`, and then tar up the result as
a Docker/OCI image, that becomes a bit easier. Or on the flip side, if someone
wants to do a `Dockerfile` style build system, we can make it easier to extract
the result of that and commit it into ostree.

Related issues/PRs:

 - coreos#96
 - coreos#471
@cgwalters
Copy link
Member

Closing this in favor of #1039

Thanks a ton for starting one of the very first interesting PRs here. It wasn't forgotten!

@cgwalters cgwalters closed this Oct 6, 2017
cgwalters added a commit to cgwalters/rpm-ostree that referenced this pull request Oct 16, 2017
… commit`

Right now `rpm-ostree compose tree` is very prescriptive about how things work.
Trying to add anything that isn't an RPM is absolutely fighting the system. Our
postprocessing system *enforces* no network access (good for reproducibilty, but
still prescriptive).

There's really a logical split between three phases:

 - "build a rootfs that installs packages"
 - "run postprocessing"
 - "commit result"

Our primary job is the first and last - and we can do *either*. If for example
someone wants to use `rpm-ostree compose install`, and then tar up the result as
a Docker/OCI image, that becomes a bit easier. Or on the flip side, if someone
wants to do a `Dockerfile` style build system, we can make it easier to extract
the result of that and commit it into ostree.

Related issues/PRs:

 - coreos#96
 - coreos#471
cgwalters added a commit to cgwalters/rpm-ostree that referenced this pull request Oct 17, 2017
Right now `rpm-ostree compose tree` is very prescriptive about how things work.
Trying to add anything that isn't an RPM is absolutely fighting the system. Our
postprocessing system *enforces* no network access (good for reproducibilty, but
still prescriptive).

There's really a logical split between three phases:

 - install: "build a rootfs that installs packages"
 - postprocess: "run magical ostree postprocessing like kernel"
 - commit: "commit result to ostree"

So there are two high level flows I'd like to enable here. First is to allow
people to do *arbitrary* postprocessing between `install` and `commit`. For
example, run Ansible and change `/etc`. This path basically is like what we have
today with `postprocess-script.sh`, except the builder can do anything they want
with network access enabled.

Going much farther, this helps us support a "build with Dockerfile" style flow.
We can then provide tooling to extract the container image, and combine
`postprocess` and `commit`.

Or completely the other way - if for example someone wants to use `rpm-ostree
compose install`, they could tar up the result as a Docker/OCI image. That's now
easier; an advantage of this flow over e.g. `yum --installroot` is the "change
detection" code we have.

Related issues/PRs:

 - coreos#96
 - coreos#471

One disadvantage of this approach right now is that if one *does* go for
the split approach, we lose the "input hash" metadata for example.  And
down the line, I'd like to add even more metadata, like the input rpm repos,
which could also be rendered on the client side.

But, I think we can address that later by e.g. caching the metadata in a file in
the install root and picking it back up or something.
cgwalters added a commit to cgwalters/rpm-ostree that referenced this pull request Oct 24, 2017
Right now `rpm-ostree compose tree` is very prescriptive about how things work.
Trying to add anything that isn't an RPM is absolutely fighting the system. Our
postprocessing system *enforces* no network access (good for reproducibilty, but
still prescriptive).

There's really a logical split between three phases:

 - install: "build a rootfs that installs packages"
 - postprocess: "run magical ostree postprocessing like kernel"
 - commit: "commit result to ostree"

So there are two high level flows I'd like to enable here. First is to allow
people to do *arbitrary* postprocessing between `install` and `commit`. For
example, run Ansible and change `/etc`. This path basically is like what we have
today with `postprocess-script.sh`, except the builder can do anything they want
with network access enabled.

Going much farther, this helps us support a "build with Dockerfile" style flow.
We can then provide tooling to extract the container image, and combine
`postprocess` and `commit`.

Or completely the other way - if for example someone wants to use `rpm-ostree
compose install`, they could tar up the result as a Docker/OCI image. That's now
easier; an advantage of this flow over e.g. `yum --installroot` is the "change
detection" code we have.

Related issues/PRs:

 - coreos#96
 - coreos#471

One disadvantage of this approach right now is that if one *does* go for
the split approach, we lose the "input hash" metadata for example.  And
down the line, I'd like to add even more metadata, like the input rpm repos,
which could also be rendered on the client side.

But, I think we can address that later by e.g. caching the metadata in a file in
the install root and picking it back up or something.
cgwalters added a commit to cgwalters/rpm-ostree that referenced this pull request Oct 24, 2017
Right now `rpm-ostree compose tree` is very prescriptive about how things work.
Trying to add anything that isn't an RPM is absolutely fighting the system. Our
postprocessing system *enforces* no network access (good for reproducibilty, but
still prescriptive).

There's really a logical split between three phases:

 - install: "build a rootfs that installs packages"
 - postprocess: "run magical ostree postprocessing like kernel"
 - commit: "commit result to ostree"

So there are two high level flows I'd like to enable here. First is to allow
people to do *arbitrary* postprocessing between `install` and `commit`. For
example, run Ansible and change `/etc`. This path basically is like what we have
today with `postprocess-script.sh`, except the builder can do anything they want
with network access enabled.

Going much farther, this helps us support a "build with Dockerfile" style flow.
We can then provide tooling to extract the container image, and combine
`postprocess` and `commit`.

Or completely the other way - if for example someone wants to use `rpm-ostree
compose install`, they could tar up the result as a Docker/OCI image. That's now
easier; an advantage of this flow over e.g. `yum --installroot` is the "change
detection" code we have.

Related issues/PRs:

 - coreos#96
 - coreos#471

One disadvantage of this approach right now is that if one *does* go for
the split approach, we lose the "input hash" metadata for example.  And
down the line, I'd like to add even more metadata, like the input rpm repos,
which could also be rendered on the client side.

But, I think we can address that later by e.g. caching the metadata in a file in
the install root and picking it back up or something.
rh-atomic-bot pushed a commit that referenced this pull request Oct 25, 2017
Right now `rpm-ostree compose tree` is very prescriptive about how things work.
Trying to add anything that isn't an RPM is absolutely fighting the system. Our
postprocessing system *enforces* no network access (good for reproducibilty, but
still prescriptive).

There's really a logical split between three phases:

 - install: "build a rootfs that installs packages"
 - postprocess: "run magical ostree postprocessing like kernel"
 - commit: "commit result to ostree"

So there are two high level flows I'd like to enable here. First is to allow
people to do *arbitrary* postprocessing between `install` and `commit`. For
example, run Ansible and change `/etc`. This path basically is like what we have
today with `postprocess-script.sh`, except the builder can do anything they want
with network access enabled.

Going much farther, this helps us support a "build with Dockerfile" style flow.
We can then provide tooling to extract the container image, and combine
`postprocess` and `commit`.

Or completely the other way - if for example someone wants to use `rpm-ostree
compose install`, they could tar up the result as a Docker/OCI image. That's now
easier; an advantage of this flow over e.g. `yum --installroot` is the "change
detection" code we have.

Related issues/PRs:

 - #96
 - #471

One disadvantage of this approach right now is that if one *does* go for
the split approach, we lose the "input hash" metadata for example.  And
down the line, I'd like to add even more metadata, like the input rpm repos,
which could also be rendered on the client side.

But, I think we can address that later by e.g. caching the metadata in a file in
the install root and picking it back up or something.

Closes: #1039
Approved by: jlebon
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants