Как организован процесс обновления серверов?

«Как организован процесс обновления серверов?» — вопрос из категории Linux, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В современной инфраструктуре я не обновляю серверы по отдельности, а работаю с ними как со временным, заменяемым скотчем (cattle, not pets). Основной инструмент — инфраструктура как код (IaC) и оркестрация.

1. Подход «Immutable Infrastructure»: Вместо обновления пакетов на работающем сервере я создаю новый образ системы с помощью Packer. В скрипте provisioning указываю все необходимые пакеты и их версии.

source "amazon-ebs" "ubuntu" {
  ami_name = "my-app-base-{{timestamp}}"
  instance_type = "t3.micro"
  source_ami = "ami-0c55b159cbfafe1f0" # Ubuntu 20.04 LTS
}

build {
  sources = ["source.amazon-ebs.ubuntu"]
  provisioner "shell" {
    script = "scripts/install_dependencies.sh"
  }
}

Затем с помощью Terraform разворачиваю автоскейлинг-группу (ASG) в AWS или аналоги в другом облаке, используя этот новый AMI. Старые инстансы постепенно заменяются новыми.

2. Для Kubernetes: Если сервис работает в Kubernetes, обновление происходит через изменение манифеста Deployment.

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25% # Не более 25% подов могут быть недоступны
      maxSurge: 1 # Можно создать 1 дополнительный под во время обновления
  template:
    spec:
      containers:
      - name: app
        image: my-registry/app:v2.0.0 # Меняю версию образа

Kubernetes сам выполнит rolling update: создаст поды с новой версией, дождется их готовности (readiness probe) и затем удалит старые.

3. Для традиционных серверов (если immutable подход невозможен): Использую Ansible для идемпотентного управления конфигурацией. Плейбук описывает желаемое состояние системы.

- name: Update system packages
  hosts: webservers
  become: yes
  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes
        cache_valid_time: 3600
    - name: Upgrade all packages
      apt:
        upgrade: dist
        autoremove: yes
    - name: Reboot if required
      reboot:
        msg: "Reboot triggered by Ansible for kernel update"
        reboot_timeout: 300

Запускаю его в режиме rolling update, обрабатывая серверы по группам, чтобы обеспечить доступность сервиса. Все изменения предварительно тестирую на staging-окружении.