- PVSM.RU - https://www.pvsm.ru -
Зеркалом называется копия данных одного информационного ресурса на другом. Зеркала используются для предоставления доступа к копиям информации через несколько источников. С помощью зеркал, например, осуществляется распространение дистрибутивов *nix-систем: копии репозиториев хранятся на многочисленных зеркалах, расположенных в различных точках мира. Использование зеркал позволяет рационально распределять нагрузку и обеспечить высокую скорость скачивания пакетов.
Свое зеркало пакетов, в котором хранятся копии репозиториев популярных linux-систем, есть и у нашей компании. В этой статье мы хотели бы подробно рассказать о его устройстве.
Запуская в 2010 году проект облачных серверов, мы выбрали для них модель установки net-install, при которой дистрибутивы устанавливаются «родным» исталлятором с одного из официальных зеркал. Благодаря такой модели можно всегда получать актуальные версии ПО со всеми последними изменениями, внесенными мейнтейнерами дистрибутива. Еще одно преимущество модели net-install заключается в том, что она позволяет избавиться от целого ряда проблем, связанных с клонированными инстансами (необходимость генерации SSH-ключей, UUID’ов файловых систем и т.п.).
В качестве основного зеркала мы выбрали mirror.yandex.ru, потому что оно близко расположено и содержит все нужные нашим клиентам репозитории. Сначала оно нас вполне устраивало. Но потом случилось непредвиденное. Число установок росло, инженеры налегали на тестирование шаблонов; в конце концов Яндекс, возмутившись огромным количеством одинаковых запросов, просто закрыл доступ к своему зеркалу для наших подсетей.
Мы стали искать решение, с помощью которого можно было бы обеспечить стабильность и свести вероятность возникновения внештатных ситуаций к минимуму. У нас возникла следующая идея: поднять nginx в качестве проксирующего сервера для нескольких зеркал. Такое решение казалось нам вполне разумным и надежным: даже если один из аплинков упадет, мы без проблем сможем скачать файлы с другого. Однако мы сразу же столкнулись с проблемой разнородной структуры зеркал: например, репозиторий CentOS на одном аплинке мог лежать в /centos, на другом — в /CentOS, а на третьем — вообще в /www/mirror/srv/pub/centos.
Так как универсальные зеркала, содержащие репозитории всех нужных нам дистрибутивов (CentOS, Debian, Ubuntu, OpenSUSE) можно пересчитать по пальцам, для каждого из дистрибутивов приходилось составлять отдельный список зеркал.
Претворив описанную идею в жизнь, мы столкнулись с куда более серьезными трудностями:
Из-за всех этих трудностей у нас не раз случался сбой автоматической установки. Чтобы раз и навсегда избавиться от сбоев, мы создали собственное зеркало — mirror.selectel.ru. Оно доступно только с IP-адресов Селектела (исходящий трафик для нас платный и предоставить его общественности мы не рискуем, ибо получить 10-20 гигабит можно запросто).
Создав собственное зеркало, мы решили все упомянутые выше проблемы. В числе преимуществ, полученных благодаря собственному зеркалу, нужно также назвать следующие:
С этого зеркала осуществляется установка операционных систем на выделенные серверы.
Как правило, репозитории состоят из двух основных частей: каталог (индекс) и пул (хранилище пакетов).
В каталоге хранится информация обо всех пакетах, находящихся в репозитории: имя, описание, архитектура, версия, контрольные суммы, а в некоторых случаях также информацию о зависимостях и содержимом пакетов. В каталоге также указано, где именно в пуле лежит файл той или иной версии каждого пакета.
В пуле хранятся сами файлы пакетов. Они могут быть разложены в соответствии с какой-либо иерархией или просто сложены в одну директорию.
В корне каждого RPM-репозитория находится директория с файлами каталога — repodata. Описание всех секций каталога хранится в файле repomd.xml. Каждая секция представлена отдельным файлом в директории каталога. В описании указан путь к файлу, содержащему секцию, а также его контрольная сумма.
Содержимое файла repomd.xml может выглядеть, например, так:
<?xml version="1.0" encoding="UTF-8"?> <repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm"> <revision>1362531727</revision> <data type="primary"> <!-- Описание секции primary - XML база данных содержащая информацию о пакетах репозитория --> <checksum type="sha256">87aa4c4e19f9a3ec93e3d820f1ea6b6ece8810cb45f117a16354465e57a1b50d</checksum> <open-checksum type="sha256">77b5cfcf2c06156858a14a52595e1f69cd8cbb58c09699a3ea4391379260e943</open-checksum> <location href="repodata/87aa4c4e19f9a3ec93e3d820f1ea6b6ece8810cb45f117a16354465e57a1b50d-primary.xml.gz"/> <timestamp>1362531876</timestamp> <size>2043735</size> <open-size>12931923</open-size> </data> <data type="primary_db"> <!-- Описание секции primary_db - то же что и primary только в sqlite БД --> <checksum type="sha256">243fdef956d09cb6d022e894e40d145f497bcf3d6d2bed79814e1c88452b9d29</checksum> <open-checksum type="sha256">533872a158160ac3a83746a676c125b5cfb2411725079502b0d5be4f4d05196e</open-checksum> <location href="repodata/243fdef956d09cb6d022e894e40d145f497bcf3d6d2bed79814e1c88452b9d29-primary.sqlite.bz2"/> <timestamp>1362531897.21</timestamp> <database_version>10</database_version> <size>3605913</size> <open-size>14942208</open-size> </data> ... </repomd>
RPM-каталог состоит из следующих секций:
Структурирование и группировка пакетов для разных ОС организованы по-разному. Например, CentOS хранит все файлы пакетов в директории Packages, расположенной в корне репозитория. Кроме того, для каждой из имеющихся архитектур создан отдельный репозиторий.
OpenSUSE хранит пакеты для всех архитектур в одном репозитории с раздельными пулами в директориях i686/x86_64/etc.
В DEB-репозиториях все пакеты хранятся в общем пуле. Это позволяет избежать дублирования пакетов, входящих в разные релизы. Для каждого релиза в репозитории создан отдельный каталог.
Разбор каталога начинается с файла /dists/[distribution]/Release (distribution здесь означает кодовое имя релиза — squeeze/wheezy/jessie). В нем содержится перечень компонентов релиза, а также информация о размере и контрольных суммах всех индексных файлов. Release-файл подпиcывается мейнтенерами архива; подпись хранится в файле Release.gpg(иногда содержимое Release вместе с подписью может находится в файле InRelease).
Описание содержимого пула находится в индексных файлов двух типов: Packages(в них перечислены бинарные пакеты) и Sources (в них перечислены исходники).
Путь к файлу Packages — /dists/[distribution]/[component]/binary-[architecture]/Packages, а к файлу Sources — /dists/[distribution]/[component]/source/Sources.
Примечание: иногда индексные файлы сжимаются с помощью gzip или bzip2 — в этом случае к имени файла соответственно добавляется расширение .gz или .bz2. Некоторые клиенты поддерживают LZMA(.lzma), XZ(.xz) и LZIP(.lz).
Приведем пример записи из файла Packages:
Package: openssh-server Source: openssh Version: 1:6.2p2-6 Installed-Size: 747 Maintainer: Debian OpenSSH Maintainers Architecture: amd64 Replaces: openssh-client (<= 2.16), libcomerr2 (>= 1.01), libgssapi-krb5-2 (>= 1.10+dfsg~), libkrb5-3 (>= 1.6.dfsg.2), libpam0g (>= 0.99.7.1), libselinux1 (>= 1.32), libssl1.0.0 (>= 1.0.1), libwrap0 (>= 7.6-4~), zlib1g (>= 1:1.1.4), openssh-client (= 1:6.2p2-6), sysv-rc (>= 2.88dsf-24) | file-rc (>= 0.8.16), libpam-runtime (>= 0.76-14), libpam-modules (>= 0.72-9), adduser (>= 3.9), dpkg (>= 1.9.0), lsb-base (>= 4.1+Debian3), procps Recommends: xauth, ncurses-term Suggests: ssh-askpass, rssh, molly-guard, ufw, monkeysphere, openssh-blacklist, openssh-blacklist-extra Conflicts: rsh-client (<< 0.16.1-1), sftp, ssh (<< 1:3.8.1p1-9), ssh-krb5 (<< 1:4.3p2-7), ssh-nonfree (<< 2), ssh-socks, ssh2 Description: secure shell (SSH) server, for secure access from remote machines Multi-Arch: foreign Homepage: http://www.openssh.org/ Description-md5: 842cc998cae371b9d8106c1696373919 Tag: admin::login, implemented-in::c, interface::daemon, network::server, protocol::ssh, role::program, security::authentication, security::cryptography, use::login, use::transmission Section: net Priority: optional Filename: pool/main/o/openssh/openssh-server_6.2p2-6_amd64.deb Size: 257438 MD5sum: 1f18e568c17d81cc2c493ee48c93a03f SHA1: 207f131bbd4d709a47bcb69c997520c998ed7593 SHA256: 242b7f041292dea0702b24e19dc6355f47147796b227f1024665920a493641f2
Репозиторий каждого дистрибутива на зеркале хранится в двух экземплярах: теневом (background) и рабочем (foreground). Обе части лежат на отдельном LVM-томе, что позволяет на ходу добавлять им дисковое пространство. В рабочей части хранится проверенная копия зеркала, она раздавается с помощью nginx. Теневая часть синхронизируется с upstream-зеркалом, а затем проходит тщательную проверку на валидность.
Процедура валидации включает проверку каталога, его цифровой подписи (если таковая имеется), а также проверку контрольных сумм всех индексных файлов. Проверить контрольные суммы всех пакетов довольно затруднительно: в пулах некоторых репозиториев могут храниться пакеты на десятки, а то и на сотни гигабайт. Поэтому контрольные суммы проверяются только у новых пакетов, до которых «дотронулся» rsync. После проверки теневая и рабочая часть меняются местами. Эта операция производится при помощи простого mv. Таким образом можно практически обеспечить атомарность подмены (достаточно трех быстрых вызовов mv, чтобы поменять директории местами) и минимизировать возможный простой. Отдача открытых файлов во время замены не прекращается.
После того, как две части поменялись местами, теневая часть локально «догоняется» до актуального состояния из рабочей копии.
Описанный выше алгоритм реализован в нашем наборе скриптов под названием mirror-sync, недавно опубликованном на GitHub [1] под лицензией GNU GPL. Надеемся, что наши наработки окажутся полезными широкой аудитории, и кто-то из наших читателей воспользуется нашим опытом при создании собственного зеркала. Все комментарии, содержащие замечания и предложения по улучшению зеркала, мы обязательно учтем в дальнейшей работе.
Автор: AndreiYemelianov
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/47522
Ссылки в тексте:
[1] опубликованном на GitHub: https://github.com/selectel/mirror-sync
[2] Источник: http://habrahabr.ru/post/200826/
Нажмите здесь для печати.