Debian package advice

175 views
Skip to first unread message

jdtangney

unread,
Feb 27, 2013, 2:39:38 AM2/27/13
to devops-t...@googlegroups.com
We use Debian packages to deploy our services to our CI, QA and prod environments. Each release consists of multiple packages. We need to provide the ability to roll back/forward in production across several releases in a very small time window, ideally something like switching a symlink between release.

But Debian packages don't really support multiple versions so we can't just install both version 1.1 and 1.2 in separate directories and switch between them.

Someone must surely have solved this problem before...

How have other people solved the problem of switching back and forth between multiple releases, each of which consists of multiple packages?

I'd be grateful for any advice.
--johnt

Justin Lynn

unread,
Feb 27, 2013, 2:44:17 AM2/27/13
to devops-t...@googlegroups.com
Hi johnt, You might consider taking a look at how the kernel or possibly python (as an example) is packaged (which shows how to build multiple simultaneously installable versions of the same system) and then looking at the using the debian alternatives system to select the default version which is used. - J



--
You received this message because you are subscribed to the Google Groups "devops-toolchain" group.
To unsubscribe from this group and stop receiving emails from it, send an email to devops-toolcha...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Abe Hassan

unread,
Feb 27, 2013, 2:46:22 AM2/27/13
to devops-t...@googlegroups.com
A couple thoughts on what we do at Say Media:

- we haven't yet tackled this under debian. with rpm-based distros, we
actually changed the name of the package so that we had typepad-29.01,
typepad-29.02, etc. not just version bumps, but whole new package
names. that way we can install multiple. the running application was
activated in a final step, wherein we stopped the app, switch a
symlink, and start it up again.

- we also haven't figured out the issue of upgraded dependencies and
roll forward, roll back, etc. right now we assume that dependencies
are not tightly coupled, and that we can survive with upgraded
dependencies in a rolled-back state.

- we bristled a bit at debian packaging (though i think we should
reconsider) because they're not relocatable, and so we can't shift
around the install destination at install time. i think that's a silly
reason to not use debian packages though. :)

- instead what we have is just tarballs that we schlep around,
install, and do the symlink trick. in this world, we've also bundled
in package dependencies into the package (via virtualenv, or nodeenv,
or cpanm, or whatever). not into the repo, just into the package.

- i've heard of a bunch of people who use things like AWS to install
new packages to new machines, change their load balancer, and then
retire the old one. that seems like an awful lot of machinery to me,
but it's also the cleanest solution, because it also guarantees you
that your provisioning/deployment stack works from "bare metal" all
the way through to production. and you literally get 100% isolation,
etc etc.

On Tue, Feb 26, 2013 at 11:39 PM, jdtangney <jo...@jdtangney.com> wrote:

Al Tobey

unread,
Feb 27, 2013, 3:00:07 AM2/27/13
to devops-t...@googlegroups.com
This is totally doable. Put the version into the package name and provide the same resources in each package. I do this to install multiple rubies on a box without integrating with all the Debian/FHS madness.

When I build, say, ruby 1.9.2-p320, the package name is "ruby-1.9.2-p320" and the version is "2013.02.12", resulting in:
ruby-1.9.2-p320_2013.02.12-precise_amd64.deb

The ruby installs in /opt/ruby/1.9.2-p320 and we symlink defaults with Chef (e.g. /opt/ruby/default /opt/ruby/1.9 /opt/ruby/1.9.2).  A "current" link as used by tools such as Capistrano and Fabric is pretty trivial to set up, so version changes can be a symlink away. When you want to clean up, just remove the old packages. With the right incantations you can get the alternatives system to put links into the OS paths, but I generally don't go for that.

You can do the same thing with just about any application. I've done similar things with rpm and deb for perl, python, ruby, apache (back in the day when it had to be carefully built to make mod_perl2 and DBD::Oracle all work together), and a bunch of other stuff.

I use the effing awesome FPM but this is likely doable with the normal tooling. Here's an example:

fpm \
    --name ruby-1.9.2-p320 \
    --provides ruby1.9.1 --provides rubygems1.9.1 --provides ruby --provides rubygems \
    --category ruby \
    --version 2013.02.12 \
    --iteration precise \
    --description "Ruby ruby-1.9.2-p320 as built by ruby-build" \
    -m root@localhost \
    -a native \
    -t deb \
    --license MIT \
    --vendor MyCompany \
    --depends zlib1g-dev \
    --depends libssl-dev \
    --depends libreadline-dev \
    -s dir \
    /opt/ruby/1.9.2-p320

I'm not really advocating app deploys via OS packages - I'm not a fan of it myself, but it could be the right thing for your environment, so yeah you can do that.

-Al

David Gillies

unread,
Feb 27, 2013, 3:02:13 AM2/27/13
to devops-t...@googlegroups.com
So we're using reprepro to manage our repos. For each distro we've got:

* $distro-unstable
* $distro
* $distro-rollback

That allows us 3 versions. Typically test/dev/staging machines get subscribed to the $distro-unstable repo and everybody subscribes to the $distro (aka stable) and $distro-rollback.

Now when a package gets published to $distro-unstable, we don't bother keeping the old version. It just gets overwritten. But when we want to promote something from $distro-unstable to $distro, firstly the old version in $distro gets copied to $distro-rollback, then version in $distro-unstable gets copied to $distro.

This is all using reprepro's copy command.

So if you need to install a particular version, there's a copy of ways that can be done depending on what version of apt is installed on your servers and how you've setup your reprepro repos:
* apt-get install package-name=some_version_here
* apt-get install -t $repo_name package-name

We're using the first method since there's some idiocracies between lucid & precise I haven't quite worked out with the -t option.

So the above method allows you 3 versions of packages.


Matt

unread,
Feb 27, 2013, 4:09:23 AM2/27/13
to devops-t...@googlegroups.com
On 27 February 2013 08:02, David Gillies <dave.g...@gmail.com> wrote:
> So we're using reprepro to manage our repos. For each distro we've got:
>
> * $distro-unstable
> * $distro
> * $distro-rollback
>
> That allows us 3 versions. Typically test/dev/staging machines get
> subscribed to the $distro-unstable repo and everybody subscribes to the
> $distro (aka stable) and $distro-rollback.
>
> Now when a package gets published to $distro-unstable, we don't bother
> keeping the old version. It just gets overwritten. But when we want to
> promote something from $distro-unstable to $distro, firstly the old version
> in $distro gets copied to $distro-rollback, then version in $distro-unstable
> gets copied to $distro.
>
> This is all using reprepro's copy command.
>
> So if you need to install a particular version, there's a copy of ways that
> can be done depending on what version of apt is installed on your servers
> and how you've setup your reprepro repos:
> * apt-get install package-name=some_version_here
> * apt-get install -t $repo_name package-name
>
> We're using the first method since there's some idiocracies between lucid &
> precise I haven't quite worked out with the -t option.
>
> So the above method allows you 3 versions of packages.
>

I've used apt-ftparchive to have multiple versions of the same package
in a ubuntu repository.

Used the excellent https://github.com/tcurdt/jdeb to build deb
packages from Jenkins. Then install on the client with {
"package-name" : ensure => "version" } or the apt equivalent.

Matt

Scott McCarty

unread,
Feb 27, 2013, 8:43:50 AM2/27/13
to devops-t...@googlegroups.com
I know this doesn't solve your problem with Debian, but on RPM based distros, software collections will definitely solve this:

http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Software_Collections_Guide/sect-What_Are_Software_Collections.html

Best Regards
Scott M

Stefanos Harhalakis

unread,
Mar 10, 2013, 8:46:16 AM3/10/13
to devops-t...@googlegroups.com, jdtangney
Hi,

In case this is still an issue:
Answering in reverse:

On Wednesday 27 February 2013, jdtangney wrote:
> But Debian packages don't really support multiple versions so we can't just
> install both version 1.1 and 1.2 in separate directories and switch
> between them.

You just can't have multiple versions installed at the same time, but you can
install/reinstall. In theory it is similar to repointing a link and running
some scripts. Maybe you're misinterpreting what "package" and "version" means
as it is impossible to have multiple versions of the same package since they
will conflict by definition.

If your packages don't conflict with each other and you don't need only one
installed at any time (i.e. other packages don't depend on just one) then you
don't have a single package but multiple packages. The version-in-package-name
will work here as others suggested. Just like how Debian handle libraries.

You can also have a single package with all your "current" versions if that's
what you want and manage just that package. Then you can add/remove directory
trees from that as you see fit.

> We use Debian packages to deploy our services to our CI, QA and prod
> environments. Each release consists of multiple packages. We need to
> provide the ability to roll back/forward in production across several
> releases in a very small time window, ideally something like switching a
> symlink between release.

(Is this a repository problem or an installation problem?)

If you do have multiple versions in the repository then apt can be asked to
install a specific version with (e.g. apt-get -s install ssh=1:6.0p1-4) and
this can be also handled by puppet.

If your problem has to do with the dependencies then you'll have to use strict
dependencies between your package sets. Try using equality within the control
file. Then you should be able to rollback by installing the head package of a
specific version which should also bring all the dependencies to their
required version.

If your problem is the repository then I believe it gets a bit more trickier.
Here's a guess: If your current method for creating the repo does not support
multiple versions you can manage your own repo by copying to the pool from the
master repo (you current one) without deleting old versions and then using -m
with dpkg-scanpackages.

In short, if your problem is the repository then the solution depends on the
way you're managing it. Any pool based method may support multiple versions
and most probably non-pool based as well. I believe dak is able to do that and
much more but it's also a huge pain to fully setup and requires some crystal
ball skills.

Cheers,
Stefanos
Reply all
Reply to author
Forward
0 new messages