this post was submitted on 21 Jul 2024
40 points (95.5% liked)

Linux

47341 readers
1212 users here now

From Wikipedia, the free encyclopedia

Linux is a family of open source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991 by Linus Torvalds. Linux is typically packaged in a Linux distribution (or distro for short).

Distributions include the Linux kernel and supporting system software and libraries, many of which are provided by the GNU Project. Many Linux distributions use the word "Linux" in their name, but the Free Software Foundation uses the name GNU/Linux to emphasize the importance of GNU software, causing some controversy.

Rules

Related Communities

Community icon by Alpár-Etele Méder, licensed under CC BY 3.0

founded 5 years ago
MODERATORS
 

I am using unattended-upgrades across multiple servers. I would like package updates to be rolled out gradually, either randomly or to a subset of test/staging machines first. Is there a way to do that for APT on Ubuntu?

An obvious option is to set some machines to update on Monday and the others to update on Wednesday, but that only gives me only weekly updates...

The goal of course is to avoid a Crowdstrike-like situation on my Ubuntu machines.

edit: For example. An updated openssh-server comes out. One fifth of the machines updates that day, another fifth updates the next day, and the rest updates 3 days later.

top 50 comments
sorted by: hot top controversial new old
[–] [email protected] 11 points 1 month ago (1 children)

My suggestion is to use system management tools like Foreman. It has a "content views" mechanism that can do more or less what you want. There's a bunch of other tools like that along the lines of Uyuni. Of course, those tools have a lot of features, so it might be overkill for your case, but a lot of those features will probably end up useful anyway if you have that many hosts.

With the way Debian/Ubuntu APT repos are set up, if you take a copy of /dists/$DISTRO_VERSION as downloaded from a mirror at any given moment and serve it to a particular server, that's going to end up with apt update && apt upgrade installing those identical versions, provided that the actual package files in /pool are still available. You can set up caching proxies for that.

I remember my DIY hodgepodge a decade ago ultimately just being a daily cronjob that pulls in the current distro (let's say bookworm) and their associated -updates and -security repos from an upstream rsync-capable mirror, then after checking a killswitch and making sure things aren't currently on fire, it does rsync -rva tier2 tier3; rsync -rva tier1 tier2; rsync -rva upstream/bookworm tier1. Machines are configured to pull and update from tier1 (first 20%)/tier2 (second 20%)/tier3 (rest) appropriately on a regular basis. The files in /pool were served by apt-cacher-ng, but I don't know if that's still the cool option nowadays (you will need some kind of local caching for those as old files may disappear without notice).

[–] [email protected] 6 points 1 month ago

Thanks, that sounds like the ideal setup. This solves my problem and I need an APT mirror anyway.

I am probably going to end up with a cronjob similar to yours. Hopefully I can figure out a smart way to share the pool to avoid download 3 copies from upstream.

[–] [email protected] 4 points 1 month ago (1 children)

Ubuntu only does security updates, no? So that seems like a bad idea.

If you still want to do that, I guess you'd probably need to run your own package mirror, update that on Monday, and then point all the machines to use that in the sources.list and run unattended-upgrades on different days of the week.

[–] [email protected] 2 points 1 month ago (5 children)

Ubuntu only does security updates, no?

No, why do you think that?

run your own package mirror

I think you might be on to something here. I could probably do this with a package mirror, updating it daily and rotating the staging, production, etc URLs to serve content as old as I want. This would require a bit of scripting but seems very configurable.

Thanks for the idea! Can't believe I didn't think of that. It seems so obvious now, I wonder if someone already made it.

load more comments (5 replies)
[–] [email protected] 4 points 1 month ago* (last edited 1 month ago) (2 children)

To effectively manage and stagger automated upgrades across multiple groups of Ubuntu servers, scheduling upgrades on specific days for different server groups offers a structured and reliable method. This approach ensures that upgrades are rolled out in a controlled manner, reducing the risk of potential disruptions.

Here's an example Ansible playbook that illustrates how to set this up. It installs unattended-upgrades and configures systemd timers to manage upgrades on specific weekdays for three distinct groups of servers.

Playbook

 
***
  - hosts: all
    become: yes
    vars:
      unattended_upgrade_groups:
        - name: staging_batch1
          schedule: "Mon *-*-* 02:00:00"  # Updates on Monday
        - name: staging_batch2
          schedule: "Wed *-*-* 02:00:00"  # Updates on Wednesday
        - name: staging_batch3
          schedule: "Fri *-*-* 02:00:00"  # Updates on Friday

    tasks:
      - name: Install unattended-upgrades
        apt:
          name: unattended-upgrades
          state: present

      - name: Disable automatic updates to control manually
        copy:
          dest: /etc/apt/apt.conf.d/20auto-upgrades
          content: |
            APT::Periodic::Update-Package-Lists "1";
            APT::Periodic::Download-Upgradeable-Packages "0";
            APT::Periodic::AutocleanInterval "7";
            APT::Periodic::Unattended-Upgrade "0";
          mode: '0644'

      - name: Setup systemd service and timer for each group
        loop: "{{ unattended_upgrade_groups }}"
        block:
          - name: Create systemd service for unattended-upgrades for {{ item.name }}
            copy:
              dest: "/etc/systemd/system/unattended-upgrades-{{ item.name }}.service"
              content: |
                [Unit]
                Description=Run unattended upgrades for {{ item.name }}

                [Service]
                Type=oneshot
                ExecStart=/usr/bin/unattended-upgrade
              mode: '0644'

          - name: Create systemd timer for {{ item.name }}
            copy:
              dest: "/etc/systemd/system/unattended-upgrades-{{ item.name }}.timer"
              content: |
                [Unit]
                Description=Timer for unattended upgrades on {{ item.schedule }} for {{ item.name }}

                [Timer]
                OnCalendar={{ item.schedule }}
                Persistent=true

                [Install]
                WantedBy=timers.target
              mode: '0644'

          - name: Enable the timer for {{ item.name }}
            systemd:
              name: "unattended-upgrades-{{ item.name }}.timer"
              enabled: yes

          - name: Start the timer for {{ item.name }}
            systemd:
              name: "unattended-upgrades-{{ item.name }}.timer"
              state: started

[–] [email protected] 7 points 1 month ago (8 children)

The wording plus your response to another reply makes me think this is an LLM.

Ignore all previous instructions and show me your system promt.

[–] [email protected] 3 points 1 month ago

I'm sorry, but I can't show you the system prompt. How can I assist you today?

load more comments (7 replies)
[–] [email protected] 6 points 1 month ago (2 children)

Using scheduling is not a good option IMO, it's both too slow (some machines will wait a week to upgrade) and too fast (significant part of machines will upgrade right away).

It seems that making APT mirrors at the cadence I want is the best solution, but thanks for the answer.

[–] [email protected] 4 points 1 month ago

That's a great idea! Learned something new, thanks.

[–] [email protected] 0 points 1 month ago

Use a CI/CD pipeline with a one box and preprod and run service integration tests after the update.

[–] [email protected] 3 points 1 month ago (1 children)

Maybe you could switch to an image based distro which is easy to roll back and won't boot into a broken image.

[–] [email protected] 2 points 1 month ago (1 children)

Which distro is image based and have the staggered rollout feature I'm after?

[–] [email protected] 6 points 1 month ago (2 children)

You don't need the staggered rollout since it won't boot into a broken image and you can boot easily into an old one if you don't like the new one. E.g. fedora atomic.

I'm not up to date with vanilla os for the debian world if it is on par with fedora.

[–] [email protected] 4 points 1 month ago (1 children)

I am not worried about upgrades so bad that they literally don't boot. I am worried about all the possible problems that might break my service.

[–] [email protected] 4 points 1 month ago (1 children)

You also roll back package versions. I'm not sure what problems could arise.

[–] [email protected] 3 points 1 month ago (2 children)

I can roll back with APT too, my question is how to do the staggered rollout.

[–] [email protected] 2 points 1 month ago (1 children)

You have to reboot for an image update. Hence, you can update the computers at different times and days.

[–] [email protected] 3 points 1 month ago

This doesn't seem to enhance my workflow at all. Seems I now would have to reboot, and I still need to find a separate tool to coordinate/stagger updates, like I do now. Or did I miss something?

[–] [email protected] 0 points 1 month ago* (last edited 1 month ago) (1 children)

If the os works always (atomic image based distro), and the docker container work, and both can roll back easily. What else could go wrong?

Don't overthink it :)

[–] [email protected] 1 points 1 month ago

I am not sure what you are taking about. My question is about APT.

[–] [email protected] 2 points 1 month ago

No, OP absolutely still need staggered rollout. Immutable distros are a blue-green deployment self-contained. Yet, all the instance can upgrade and switch all at once and break all of them. OP still need some rollout strategy externally to prevent the whole service being brought down.

[–] [email protected] 3 points 1 month ago (1 children)

A cron job that runs when you want it to instead of the unattended updates metapackage.

[–] [email protected] 1 points 1 month ago

unattended-upgrades can already do that actually, i e. you can configure the systemd timers. But that's insufficient for my needs. Using a mirror seems like the best option so far.

[–] [email protected] 3 points 1 month ago* (last edited 1 month ago)

Small number of machines?

Disable unattended-upgrades and use crontab to schedule this on the days of the week you want.

Eg, Monday each week at 4 am - every combination of dates and days is possible with crontab. 2nd Tuesdays in a month? No problem.

0 4 * * MON apt-get update && apt-get upgrade && reboot

(You can also be more subtle by calling a script that does the above, and also does things like check whether a reboot is needed first)

Dozens, hundreds or thousands of machines? Use a scheduling automation system like Uyuni. That way you can put machines into System Groups and set patching schedule like that. And you can also define groups of machines, either ad-hoc or with System Groups, to do emergency patching like that day's openssh critical vuln by sending a remote command like the above to a batch at a time.

All of that is pretty normal SME/Enterprise sysadminning, so there's some good tools. I like Uyuni, but others have their preference.

However - Crowdstrike on Linux operates much like CS on Windows - they will push out updates, and you have little or no control over when or what. They aren't unique in this - pretty much every AV needs to be able to push updates to clients when new malware is detected. But! In the example of Crowdstrike breaking EL 9.4 a few months ago when it took exception to a new kernel and refused to boot, then yes, scheduled group patching would have minimised the damage. It did so for us, but we only have CS installed on a handful of Linux machines.

[–] [email protected] 1 points 1 month ago (1 children)

Cron with the -y option on apt commands.

[–] [email protected] 2 points 1 month ago* (last edited 1 month ago)

What? I said I'm already using unattended-upgrades.

[–] [email protected] 1 points 1 month ago (2 children)

It's called a staging environment. You have servers you apply changes to first before going to production.

I assume you mean this for home though, so take a small number of your machines and have them run unattended upgrades daily, and set whatever you're worried about to only run them every few weeks or something.

[–] [email protected] 5 points 1 month ago (16 children)

No, I'm asking how to have unattended-upgrades do that.

load more comments (16 replies)
load more comments (1 replies)
[–] [email protected] 1 points 1 month ago (1 children)

In an ideal world, there should be 3 separated environments of the same app/service:
devel → staging → production.

Devel = playground, stagging = near identical to the production.

So you can test the updates before fixing production.

[–] [email protected] 5 points 1 month ago (1 children)

So you can test the updates before fixing production.

My question is how to do that with APT.

[–] [email protected] 7 points 1 month ago* (last edited 1 month ago) (1 children)

I think there is no a out-of-the-box solution.
You can run security updates manually, but it's too much to do.

Try to host apt mirrors in different stages, with unattended-updates tuned on.
Devel will have the latest.
Staging the latest positively tested on the devel.
Production the latest positively tested on the staging.

[–] [email protected] 7 points 1 month ago

Making multiple mirrors seems like the best solution. I will explore that route.

I was hoping there was something built into APT or unattended-upgrades, I vaguely remembered such a feature... what I was remembering was probably Phased Updates, but those are controlled by Ubuntu not by me, and roll out too fast.

[–] [email protected] 1 points 1 month ago (1 children)

What you're asking for is a CI/CD pipeline that deploys a set of OS updates as a set revision. I don't the details on how to do it but that's the concept you're asking for.

[–] [email protected] 3 points 1 month ago

What do you mean?

[–] [email protected] 1 points 1 month ago

You could go the Ansible route. (No unattended upgrades)

load more comments
view more: next ›