Subscription Manager#

Примечание

По умолчанию предполагается, что сценарии данного раздела выполняются пользователем с административными полномочиями (например, root), поэтому повышение полномочий sudo в командах не прописано.

Subscription Manager - инструмент, автоматизирующий процесс управления подписками на репозитории программных пакетов, предоставляемые разработчиком ОС.

С помощью Subscription Manager можно:

  • регистрировать ОС и получать список доступных репозиториев (например, для простого и быстрого способа получения обновлений);

  • подключать и отключать репозитории без необходимости редактировать вручную конфигурационные файлы;

  • отключать регистрацию одного хоста и подключать на другом с помощью одного и того же активационного ключа.

Инструмент поставляется в пакете subscription-manager. Для проверки наличия пакета в системе выполните команду:

rpm -q subscription-manager

При наличии пакета в выводе команды отобразится его версия. При отсутствии пакета выполните установку, подробнее см. в разделе «Установка Subscription Manager».

Установка Subscription Manager#

Предварительные условия

- Подключены репозитории, указанные в разделе «Подключение репозитория»

Установите пакет subscription-manager с помощью менеджера пакетов:

dnf -y install subscription-manager

Обзор команд Subscription Manager#

В таблице ниже представлен список основных команд:

Основные команды subscription-manager#

Команда

Описание

attach

Прикрепление подписки к зарегистрированной системе

list

Просмотр информации о продуктах и подписках для системы

refresh

Получение последних данных подписки с сервера

register

Регистрация на портале пользователей или в службе управления подписками

release

Выбор версии операционной системы

remove

Удаление подписок

repos

Просмотр доступных репозиториев

status

Статус состояния подписок и продуктов

unregister

Удаление регистрации на портале пользователей или в службе управления подписками

Дополнительная информация#

Дополнительную информацию можно получить, выполнив команду:

man subscription-manager

Или:

subscription-manager --help

Регистрация системы с помощью Subscription Manager#

Предварительные условия

- Права пользователя с административными полномочиями

- Локальное время системы установлено не ранее 01.09.2024

Для регистрации системы в службе управления подписками с помощью Subscription Manager выполните следующую команду:

subscription-manager register --org <organization_name> --activationkey <activation_key>

Где:

  • <organization_name> - наименование организации;

  • <activation_key> - активационный ключ.

Примечание

<organization_name> и <activation_key> запросите у разработчика ОС.

Важно

В случае ошибки при выполнении команды убедитесь, что <organization_name> и <activation_key> введены корректно и соответствуют требуемому регистру. Если ошибка сохраняется, обратитесь к разработчику ОС.

Пример вывода:

The system has been registered with ID: <system_ID>
The registered system name is: <system_name>

Где:

  • <system_ID> - зарегистрированый ID системы;

  • <system_name> - зарегистрированное имя системы.

При неверном вводе пользователь получит сообщение об ошибке:

Couldn't find Organization <organization_name>. (HTTP error code 404: Not Found)

Отключение регистрации хоста с помощью Subscription Manager#

Для отключения хоста с помощью Subscription Manager выполните команду:

subscription-manager unregister

Чтобы полностью отменить регистрацию и очистить данные подписки:

subscription-manager unregister && sudo subscription-manager clean

Примечание

Активационный ключ, с помощью которого хост был зарегистрирован, может быть применен на другом хосте по инструкции в разделе «Регистрация системы с помощью Subscription Manager».

Просмотр, подключение и отключение доступных репозиториев с помощью Subscription Manager#

Для просмотра доступных репозиториев с помощью Subscription Manager, которые распространяются для организации, выполните:

subscription-manager repos --list

Пример вывода:

+----------------------------------------------------------+
    Available Repositories in /etc/yum.repos.d/sberlinux.repo
+----------------------------------------------------------+
Repo ID:   <Repo_ID>
Repo Name: <Repo_Name>
Repo URL:  <Repo_URL>
Enabled:   0

Repo ID:   <Repo_ID>
Repo Name: <Repo_Name>
Repo URL:  <Repo_URL>
Enabled:   0

Где:

  • <Repo_ID> - ID репозитория;

  • <Repo_Name> - наименование репозитория;

  • <Repo_URL> - URL репозитория;

  • Enabled - количество подключений.

или

subscription-manager repos | grep -e "^.*ID"

Пример вывода:

Repo ID: SBERTECH_JSC_SberLinux_sberlinux-96-for-x86_64-baseos-rpms
Repo ID: SBERTECH_JSC_SberLinux_sberlinux-96-for-x86_64-appstream-debug-rpms

Для подключения репозитория выполните команду:

subscription-manager repos --enable <Repo_ID>

Например:

subscription-manager repos --enable=SBERTECH_JSC_SberLinux_sberlinux-9-for-x86_64-appstream-rpms

Пример вывода:

Repository `<Repo_ID>` is enabled for this system.

Для проверки работоспособности подключения Subscription Manager введите команду обновления репозитория:

dnf update

Для отключения репозитория выполните команду:

subscription-manager repos --disable <Repo_ID>

Пример вывода:

Repository '<Repo_ID>' is disabled for this system.

Поиск пакетов при подключенных репозиториях#

Для поиска пакетов при подключенных репозиториях выполните команду:

dnf search <package_name>

или

dnf list <package_name> --showduplicates

Где <package_name> - имя пакета.

Например:

dnf list kernel-core --showduplicates

Настройка контейнера UBI SberLinux с активированной подпиской#

Данная инструкция описывает процесс создания SberLinux контейнера UBI (Universal Base Image) с активированной подпиской для доступа к репозиториям.

Предварительные условия#

  1. Машина подготовлена:

    • Убедитесь, что на машине активирована подписка:

      subscription-manager list
      

      Если подписка не активирована, выполните команду (подробнее в разделе «Регистрация системы с помощью Subscription Manager»):

      subscription-manager register --org <organization_name> --activationkey <activation_key>
      
    • Установлен Podman:

      which podman
      

      Если Podman не установлен, выполните команду:

      dnf install podman
      
  2. Загружен контейнер UBI.

    Если образ контейнера UBI отсутствует, выполните команду:

    • Для 8-го поколения:

      podman pull sberlinux.sbertech.ru/ubi8/ubi
      
    • Для 9-го поколения:

      podman pull sberlinux.sbertech.ru/ubi9/ubi
      

Сценарий настройки#

Примечание

Проверьте доступность зеркала и актуальность версии образа UBI.

Для настройки контейнера UBI с подпиской выполните следующие шаги:

  1. Создайте рабочий каталог и скопируйте необходимые файлы для подготовки сертификатов и репозиториев:

    mkdir -p ubi-subscription/{certs,ca}
    cp /etc/pki/entitlement/*.pem ubi-subscription/certs/
    cp /etc/slsm/ca/sberlinux-uep.pem ubi-subscription/ca/
    cp /etc/yum.repos.d/sberlinux.repo /home/linux-tester/ubi-subscription/
    

    Примечание

    Убедитесь, что все пути к файлам корректны для системы.

  2. Загрузите локальный образ в Podman:

    podman load -i <path_to_container>
    

    Где <path_to_container> — путь к контейнеру SberLinux-UBI, например sberlinux-9-x86_64-ubi.tar.gz.

  3. Создайте Dockerfile в каталоге ubi-subscription:

    vi /home/linux-tester/ubi-subscription/Dockerfile
    

    Содержимое Dockerfile:

    FROM localhost/sberlinux-9-x86_64-ubi:latest
    
    # Копирует .repo файл
    COPY sberlinux.repo /etc/yum.repos.d/sberlinux.repo
    
    # Копирует сертификаты подписки
    COPY certs /etc/pki/entitlement/
    
    # Копирует CA-сертификат
    COPY ca/sberlinux-uep.pem /etc/pki/tls/certs/sberlinux-uep.pem
    
    # Создает символическую ссылку slsm-host → slsm
    RUN rm -rf /etc/slsm-host && \
        ln -s /etc/slsm /etc/slsm-host
    
    # Проверяет, что нужные каталоги существуют
    RUN mkdir -p /etc/slsm/ca && \
        ln -s /etc/pki/tls/certs/sberlinux-uep.pem /etc/slsm/ca/sberlinux-uep.pem
    
    # Устанавливает пакеты
    RUN yum install -y nss_wrapper uid_wrapper && \
        yum clean all
    
  4. Перейдите в рабочий каталог и соберите образ контейнера:

    cd ubi-subscription
    podman build -t sberlinux-with-subman .
    
  5. Запустите контейнер в интерактивном режиме:

    podman run -it sberlinux-with-subman bash
    

После успешного запуска контейнера можно установить любое программное обеспечение из подключенных репозиториев ОС SberLinux OS Server, используя стандартные команды yum или dnf.

Создание локального зеркала#

В изолированных сетях доступ к программному обеспечению рекомендуется организовать через локальное зеркало. Достаточно предоставить интернет-доступ одному серверу, синхронизирующему репозитории с внешними источниками. Клиенты получают пакеты по внутренней сети, что обеспечивает безопасность, контроль обновлений и экономию трафика.

Для создания локального зеркала:

  1. Установите полное имя хоста:

    hostnamectl set-hostname <host_name>
    

    Где <host_name> - имя хоста.

  2. Чтобы вывести список сетевых интерфейсов и их IP-адресов, выполните команду:

    ip a
    
  3. Зарегистрируйте систему с помощью Subscription Manager.

  4. Получите список доступных репозиториев и подключите базовые репозитории.

  5. Для проверки работоспособности подключения Subscription Manager введите команду обновления репозитория.

  6. Создайте каталог /mnt/mirror для локального зеркала:

    mkdir -p /mnt/mirror
    
  7. Для синхронизации требуемых репозиториев выполните следующую команду:

    dnf reposync -p /mnt/mirror --repoid=<Repo_ID>
    

    Где <Repo_ID> - ID репозитория.

    Примечание

    Выполните синхронизацию для каждого репозитория. Рекомендуется запускать команды синхронизации в сессии tmux.

    Чтобы установить tmux, используйте команду: dnf install tmux -y && tmux.

    Это позволяет обеспечить устойчивость процесса при длительном выполнении и предотвращает прерывание в случае разрыва SSH-сессии. Синхронизация может занимать значительное время в зависимости от объема данных и пропускной способности сети.

    После синхронизации репозиториев выполняется этап их публикации.

  8. В качестве веб-сервера для предоставления доступа к зеркалу установите Nginx:

    dnf install nginx
    
  9. Сделайте содержимое каталога /mnt/mirror доступным через веб-сервер *Nginx с помощью ngx_http_autoindex_module в виде автоматического списка файлов, чтобы клиенты могли получать пакеты по HTTP. Пример конфигурации:

    location /mnt/mirror {
        autoindex on;
    }
    
  10. Включите и запустите веб-сервер *Nginx:

    systemctrl enable --now nginx
    
  11. Выведите список всех TCP-портов в числовом формате (без DNS-имен), на которых в данный момент запущены службы и которые ожидают входящих соединений.

    ss -ntl
    

    Где:

    • — ss — утилита для отображения информации о сокетах (сетевых соединениях);

    • -n — опция, отключающая преобразование портов и адресов в человекочитаемый формат имен. При выводе отображаются числовые значения (например, <IP_address>:80, а не example.com:http);

    • -t — опция, включающая отображение TCP-сокетов;

    • -l — опция, включающая отображение только слушающих (listening) портов (т.е. сокетов, ожидающих входящих подключений; по умолчанию они не отображаются).

  12. Проверьте, что порт 80 прослушивается.

  13. Выполните HTTP-запрос к веб-серверу по IP-адресу:

    curl -L http://<IP_address>
    

    Где <IP_address> - IP-адрес хоста с зеркалом.

Создание локального зеркала с помощью Ansible playbook#

Ansible playbook для создания локального зеркала:

crowling.yaml
---
- name: Registration SBEL, install nginx and start crawling
  hosts: crawler
  become: true
  vars:
    key: "{{ activation_key }}"
    org_name: "{{ organization_name }}"
    crawling_time: "{{ time | default('00:00') }}"
    start_crawling_now: false
    mirror_dir: "{{ dir | default('/mnt/mirror') }}"
    major_version: "{{ ansible_distribution_major_version }}"
    basearch: "{{ ansible_architecture }}"
    custom_satellite: "{{ satellite }}"
    repos:
    # === The appstream-rpms and baseos-rpms repositories are required for Nginx installation ===
      - "SBERTECH_JSC_SberLinux_sberlinux-{{ major_version }}-for-{{ basearch }}-appstream-rpms"
      - "SBERTECH_JSC_SberLinux_sberlinux-{{ major_version }}-for-{{ basearch }}-baseos-rpms"
      # - "sbertech_sberlinux-{{ major_version }}_sberlinux-{{ major_version }}-for-{{ basearch }}-appstream-rpms"
      # - "sbertech_sberlinux-{{ major_version }}_sberlinux-{{ major_version }}-for-{{ basearch }}-baseos-rpms"
    mirror_repos:
      - "SBERTECH_JSC_SberLinux_sberlinux-8-for-x86_64-highavailability-rpms"
      - "SBERTECH_JSC_SberLinux_sberlinux-8-for-x86_64-resilientstorage-rpms"
      # - "SBERTECH_JSC_SberLinux_sberlinux-9-for-x86_64-highavailability-rpms"
      # - "SBERTECH_JSC_SberLinux_sberlinux-9-for-x86_64-resilientstorage-rpms"
      # - "sbertech_sberlinux-8_sberlinux-8-for-x86_64-highavailability-rpms"
      # - "sbertech_sberlinux-8_sberlinux-8-for-x86_64-resilientstorage-rpms"
  tasks:
    - name: Registration
      when:
        - key is defined
      block:
        - name: Configure custom satellite
          when: custom_satellite is defined
          block:
            - name: Custom slsm config
              ansible.builtin.replace:
                path: /etc/slsm/slsm.conf
                regexp: "slsm.sbertech.ru"
                replace: "{{ custom_satellite }}"

            - name: Custom ca path
              ansible.builtin.replace:
                path: /etc/slsm/slsm.conf
                regexp: "sberlinux-uep"
                replace: "{{ custom_satellite }}"

            - name: Add CA certificate
              ansible.builtin.shell: |
                openssl s_client -connect "{{ custom_satellite }}":443 -servername "{{ custom_satellite }}" -showcerts 2>/dev/null < /dev/null | \
                sed -ne "/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p" | \
                tee /etc/pki/ca-trust/source/anchors/"{{ custom_satellite }}".pem /etc/slsm/ca/"{{ custom_satellite }}".pem

        - name: Register with subscription manager
          ansible.builtin.command: subscription-manager register --org "{{ org_name }}" --activationkey "{{ key }}"
          register: registration_result
          failed_when: "'system is already registered' not in registration_result.stderr and registration_result.rc != 0 and 'system has been registered' not in registration_result.stdout"
          changed_when: "'system is already registered' not in registration_result.stderr or 'system has been registered' in registration_result.stdout"

    - name: Enable repositories
      when: repos is defined
      block:
        - name: Checking registration before connecting repositories
          ansible.builtin.command: subscription-manager identity
          register: subscription_status
          changed_when: false
          failed_when: subscription_status.rc != 0

        - name: Enable specified repositories
          when: subscription_status.rc == 0
          community.general.rhsm_repository:
            name: "{{ item }}"
            state: enabled
          loop: "{{ repos }}"
          register: enable_repos
          ignore_errors: true

        - name: The result of enabling repositories
          ansible.builtin.debug:
            msg: >
              "Результат включения репозиториев:
              {% for result in enable_repos.results %}
                {{ result.results }}
              {% endfor %}"
            
    - name: Install and configure Nginx
      when: major_version is defined
      block:
        - name: Install Nginx
          ansible.builtin.dnf:
            name: nginx
            state: present

        - name: Start Nginx service
          ansible.builtin.service:
            name: nginx
            state: started
            enabled: true

        - name: Ensure nginx root directory exists
          ansible.builtin.file:
            path: "{{ mirror_dir }}"
            state: directory
            owner: nginx
            group: nginx
            mode: "0755"

        - name: Configure SElinux
          block:
            - name: Add SELinux file context for the directory
              ansible.builtin.sefcontext:
                target: "{{ mirror_dir }}(/.*)?"
                setype: httpd_sys_content_t
                state: present

            - name: Apply the new SELinux context to the directory
              ansible.builtin.command: restorecon -Rv "{{ mirror_dir }}"
              register: result_command
              changed_when: "'Relabeled' in result_command.stdout"

        - name: Configure nginx with custom conf
          ansible.builtin.copy:
            dest: /etc/nginx/nginx.conf
            content: |
                # Managed by Ansible. Do not edit manually!

                user nginx;
                worker_processes auto;
                worker_rlimit_nofile 8192;

                error_log /var/log/nginx/error.log;
                pid /run/nginx.pid;

                # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
                include /usr/share/nginx/modules/*.conf;

                events {
                  worker_connections 8192;
                  use epoll;
                }

                http {
                    log_format extented  "$remote_addr - $remote_user [$time_local]  "
                                         "'$request' $status $body_bytes_sent "
                                         "'$http_referer' '$http_user_agent' [request_time:$request_time, upstream:$upstream_addr, upstream_response_time:$upstream_response_time]";

                    log_format post      "$remote_addr - $remote_user [$time_local]  "
                                         "'$request' $status $body_bytes_sent "
                                         "request_body:'$request_body'"
                                         "'$http_referer' '$http_user_agent' [request_time:$request_time, upstream:$upstream_addr]";

                    log_format cache     "$remote_addr - [cache_status:$upstream_cache_status] [$time_local] "
                                         "'$request' $status $body_bytes_sent "
                                         "'$http_referer' '$http_user_agent' [request_time:$request_time, upstream:$upstream_addr]";

                    log_format isotime  "$remote_addr - $remote_user [$time_iso8601]  "
                                        "'$request' $status $body_bytes_sent "
                                        "'$http_referer' '$http_user_agent' [request_time:$request_time, upstream:$upstream_addr]";

                    access_log  /var/log/nginx/access.log;

                    server_tokens         off;
                    sendfile              on;
                    tcp_nopush            on;
                    keepalive_timeout     65;
                    types_hash_max_size   4096;

                    client_body_timeout   20s;

                    send_timeout          20s;

                    server_names_hash_max_size 4096;
                    server_names_hash_bucket_size 512;

                    include             /etc/nginx/mime.types;
                    default_type        application/octet-stream;

                    charset UTF-8;

                    include /etc/nginx/conf.d/*.conf;
                }

        - name: Configure nginx mirror conf
          ansible.builtin.copy:
            dest: /etc/nginx/conf.d/mirror.conf
            content: |
                server {
                    listen    *:80;
                    root            "{{ mirror_dir }}";
                    autoindex       on;
                    access_log  /var/log/nginx/mirror-access.log;
                    error_log   /var/log/nginx/mirror-error.log;

                    location / {
                      try_files $uri $uri/ "{{ mirror_dir }}" =404;
                    }
                }
          notify:
            - Restart nginx

    - name: Configure crawling script
      when: mirror_repos is defined
      block:
        - name: Create a script file
          ansible.builtin.copy:
            dest: /usr/local/bin/crawl_repos.sh
            content: |
              #!/bin/bash
              REPOS=("{{ mirror_repos | join(' ') }}")
              for i in "${REPOS[@]}"; do
                dnf reposync -y \
                  --repoid="$i" \
                  --delete \
                  --download-metadata \
                  --downloadcomps \
                  --download-path="{{ mirror_dir }}"
              done
            mode: "0755"

        - name: Add cron job for crawling repos
          ansible.builtin.cron:
            name: "Crawl repositories"
            minute: "{{ crawling_time.split(':')[1] }}"
            hour: "{{ crawling_time.split(':')[0] }}"
            job: "/usr/local/bin/crawl_repos.sh"
            state: present

        - name: Start crawling now if required
          when:
            - start_crawling_now | bool
            - subscription_status.rc == 0
          ansible.builtin.command: "/usr/local/bin/crawl_repos.sh"

  handlers:
    - name: Restart nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

Для создания локального зеркала с помощью Ansible playbook:

  1. Установите полное имя хоста:

    hostnamectl set-hostname <host_name>
    

    Где <host_name> - имя хоста.

  2. Запросите у разрабочика ОС наименование организации <organization_name> и активационный ключ <activation_key> для регистрации системы при помощи Subscription Manager.

  3. Настройте переменные в crawling.yml:

    • crawling_time – время, когда скрипт будет синхронизировать локальное зеркало, например, 00:00.

    • start_crawling_now – параметр, который определяет, следует ли немедленно запускать процесс создания зеркала, либо отложить запуск до ручного или запланированного срабатывания.

    • mirror_dir – путь к каталогу, в котором будет находиться локальное зеркало, например, /mnt/mirror.

    • repos – репозитории, которые будут включены на хосте. В примере указаны репозитории необходимые для установки веб-сервера Nginx.

    • mirror_repos – репозитории, из которых будет состоять локальное зеркало. См. раздел, в котором описано как получить список доступных репозиториев.

  4. Запустите Ansible playbook:

    ansible-playbook -i inventory.yml crawling.yml -e "org_name=<organization_name> key=<activation_key> start_crawling_now=true"
    

    Где <»start_crawling_now=true»> - параметр, который указывает на необходимость немедленного создания зеркала.

  5. После завершения работы Ansible playbook, проверьте доступность зеркала:

    curl -L http://<IP_address>
    

    Где <IP_address> - IP-адрес хоста с зеркалом.

Примечание

Выполните синхронизацию для каждого репозитория. Рекомендуется запускать команды синхронизации в сессии tmux.

Чтобы установить tmux, используйте команду: dnf install tmux -y && tmux.

Это позволяет обеспечить устойчивость процесса при длительном выполнении и предотвращает прерывание в случае разрыва SSH-сессии. Синхронизация может занимать значительное время в зависимости от объема данных и пропускной способности сети.