Администрирование контейнеров#

Запуск контейнеров#

SberLinux OS Core поставляется c CRI-O. В этом разделе показано, как использовать системные устройства для запуска и остановки контейнеров CRI-O.

Следующий фрагмент конфигурации Butane настраивает systemd hello.service для запуска busybox (программного пакета, который предоставляет несколько утилит Unix в одном исполняемом файле):

variant: sbcos
version: 3.2.0
systemd:
  units:
    - name: hello.service
      enabled: true
      contents: |
        [Unit]
        Description=MyApp
        After=network-online.target
        Wants=network-online.target

        [Service]
        TimeoutStartSec=0
        ExecStartPre=-/bin/crio kill busybox1
        ExecStartPre=-/bin/crio rm busybox1
        ExecStartPre=/bin/crio pull busybox
        ExecStart=/bin/crio run --name busybox1 busybox /bin/sh -c "trap 'exit 0' INT TERM; while true; do echo Hello World; sleep 1; done"

        [Install]
        WantedBy=multi-user.target

Администрирование контейнеров на примере Platform V DropApp (K8S)#

В данном разделе представлена базовая информация по компонентам и настройке продукта Platform V DropApp (K8S) (далее — DropApp). Для получения полной информации обратитесь к документации продукта DropApp (https://client.sbertech.ru/docs/public/K8S/).

При установке DropApp в операционной системе SberLinux OS Core пропускается шаг установки RPM-пакетов, дальнейшая работа с кластерами не отличается от других ОС.

Роль администратора — это роль сервисного пользовательского аккаунта по умолчанию (привилегированного пользователя), который автоматически создается при создании кластера («cluster») DropApp.

Установка и настройка программного обеспечения осуществляется с помощью утилит управления кластером DropApp, например, kubeadm, kubelet и kubectl.

При развертывании DropApp осуществляется работа с кластерами. Кластер DropApp состоит из набора nodes («узлов»), которые запускают контейнерные приложения. Кластер DropApp имеет как минимум один рабочий node. В тестовых или небольших не отказоустойчивых инсталляциях возможна ситуация, когда главные nodes являются рабочими - на них запущена и управляющая, и рабочая нагрузка.

В рабочих nodes размещены pods, являющиеся компонентами приложения. Управляющий слой (control plane), представляет собой совокупность главных nodes и управляет рабочими nodes и pods в кластере DropApp.

Файл kubeconfig#

По умолчанию инструмент командной строки для управления кластерами kubectl задействуется через командную строку (например, через bash) и использует контексты (context) для взаимодействия с кластером DropApp.

Контекст DropApp — это набор параметров доступа, содержащий кластер DropApp, пользователя и namespace.

Контексты используются для доступа к определенному кластеру и namespace с помощью учетной записи пользователя. Установка, с каким кластером взаимодействует DropApp, и изменение конфигурационной информации осуществляются посредством kubectl.

В каждом контексте есть три ключевых параметра: cluster, namespace и user.

Для выбора контекста используйте команды:

kubectl config get-contexts ## показать список контекстов
kubectl config current-context ## показать текущий контекст (current-context)
kubectl config use-context my_cluster_name ## установить my_cluster_name как контекст по умолчанию

Для выбора, с каким кластером DropApp необходимо взаимодействовать при помощи kubectl, используйте одну из следующих команд:

kubectl config view # показать объединенные настройки kubeconfig

# использовать несколько файлов kubeconfig одновременно и посмотреть объединенную конфигурацию из этих файлов
KUBECONFIG=~/.kube/config:~/.kube/kubconfig2

kubectl config view

# получить пароль для пользователя user_1
kubectl config view -o jsonpath='{.users[?(@.name == "user_1")].user.password}'

# показать первого пользователя
kubectl config view -o jsonpath='{.users[].name}'

# получить список пользователей
kubectl config view -o jsonpath='{.users[*].name}'

# показать список контекстов
kubectl config get-contexts

# показать текущий контекст (current-context)
kubectl config current-context

# установить my_cluster_name как контекст по умолчанию
kubectl config use-context my_cluster_name

# добавить новую конфигурацию для кластера в kubeconf с базовой аутентификацией, задав вместо <password> пароль
kubectl config set-credentials kubeuser/foo.dropapp.com --username=dapp_user --password=<password>

# сохранить namespace для всех последующих команд kubectl в этом контексте.
kubectl config set-context --current --namespace=ggckad-s2

# установить контекст, используя имя пользователя (user) и namespace.
kubectl config set-context gce --user=cluster-admin --namespace=foo \
&& kubectl config use-context gce

# удалить пользователя foo
kubectl config unset users.foo

Переменная среды KUBECONFIG#

Переменная среды KUBECONFIG содержит список файлов kubeconfig. kubeconfig — это файл YAML со всеми деталями кластера DropApp, сертификатом и секретным токеном для аутентификации кластера. Специальной установки для KUBECONFIG не требуется.

Если KUBECONFIG отсутствует, kubectl использует файл kubeconfig по умолчанию, Например, через обращение к конфигурационному файлу $HOME/.kube/config.

Если KUBECONFIG присутствует, kubectl использует конфигурацию, которая является результатом объединения файлов, перечисленных в KUBECONFIG.

Конфигурация объединения файлов kubeconfig#

  1. Чтобы отобразить информацию о конфигурации, введите команду:

    kubectl config view
    

    Примечание

    Выходные данные могут как формироваться из одного файла kubeconfig, так и быть результатом объединения нескольких файлов kubeconfig.

  2. Если установлена опция --kubeconfig, используйте только указанный файл.

  3. Определите первый контекст для взаимодействия с кластером DropApp:

    • используйте опцию --context командной строки, если контекст присутствует;

    • используйте current-context из объединенных файлов kubeconfig.

    На этом этапе допускается незаполненный контекст.

  4. Определите кластер DropApp и пользователя (user). На этом этапе допускается неопределенность контекста.

    Определение пользователя к кластеру DropApp выполняется дважды: один раз для пользователя и один раз для кластера:

    • используйте опцию командной строки, если контекст существует: --user или --cluster;

    • если контекст уже заполнен, удалите пользователя или кластер DropApp из контекста.

      Примечание

      Пользователь и кластер DropApp могут быть не заполнены на этом этапе.

  5. Определите актуальную информацию о кластере DropApp для использования. На этом этапе актуальная информация не определена. Создайте атрибуты информации о кластере DropApp при помощи следующих опций командной строки: --server, --certificate-authority, --insecure-skip-tls-verify.

    Если в объединенных файлах kubeconfig существуют какие-либо атрибуты информации о кластере DropApp, используйте их. Если местоположение сервера не определено, то произойдет сбой.

  6. Определите фактическую информацию о пользователе для использования. Создайте информацию о пользователе, используя те же правила создания информации о кластере DropApp:

    • используйте опции командной строки: --client-certificate, --client-key, --username, --password --token;

    • используйте поля user из объединенных файлов kubeconfig.

    Примечание

    Также можно использовать значения по умолчанию.

Ссылки на файлы#

Ссылки на файлы и пути в файле kubeconfig относятся к расположению файла kubeconfig. Ссылки на файлы в командной строке относятся к текущему рабочему каталогу. Относительные пути $HOME/.kube/config хранятся относительно, а абсолютные пути хранятся абсолютно.

Управляющий слой#

Компоненты управляющего слоя, которые отвечают за основные операции кластера DropApp (например, планирование), также обрабатывают события кластера (например, запускают новый pod, когда поле развертывания replicas не соответствует требуемому количеству реплик).

Минимальный набор таких компонентов: etcd, API Server, kube-scheduler, controller manager.

Помимо управляющих компонентов, в DropApp входят агенты kubelet и kubeproxy, которые запущены на всех nodes кластера DropApp. Компоненты управляющего слоя могут быть запущены на любой машине в кластере. Однако сценарии настройки обычно запускают все компоненты управляющего слоя на одной машине и в то же время не позволяют запускать пользовательские контейнеры на ней.

Kubelet#

Kubelet — это сервис, который управляет pods, основываясь на их спецификации, является главным сервисом для рабочих nodes и взаимодействует с API server.

Для запуска полезной нагрузки на nodes используется агент kubelet. В отличие от компонентов управляющего слоя, он запущен на каждом node: управляющем и рабочем. kubelet считывает с помощью API Server, что экземпляр сервиса распределен посредством kube-scheduler на node, на котором он работает, и запускает экземпляр сервиса.

Для изоляции сервисов друг от друга они запускаются kubelet в контейнерном окружении CRI-O. Также с использованием kubelet возможно отслеживание работоспособности контейнеров, которые были запущены с его помощью.

Cri-tools#

Cri-tools — набор инструментов, используемый в DropApp для взаимодействия с контейнерной средой выполнения, которая соответствует стандарту Container Runtime Interface (CRI). Он содержит утилиты для запуска и остановки контейнеров, создания и удаления образов контейнеров, а также для получения информации о контейнерах и их статусе.

CRI — это интерфейс, который описывает стандартную спецификацию для взаимодействия между DropApp и контейнерной средой выполнения. Это позволяет использовать разные среды выполнения с необходимыми функциями.

Интерфейс командной строки контейнерной среды выполнения (CRI)#

crictl — интерфейс командной строки для сред выполнения контейнеров, совместимых с CRI. Это позволяет разработчикам отлаживать среду выполнения CRI без необходимости настраивать компоненты DropApp. Команда crictl используется для управления контейнерами на кластерах. Она позволяет выполнять различные операции, такие как запуск, остановка, удаление контейнеров, а также получение информации о них.

Список команд crictl и их краткое описание приведены в таблице ниже.

Команды crictl#

Команда

Описание

attach

Прикрепить к запущенному контейнеру

create

Создать новый контейнер

exec

Запустить команду в работающем контейнере

version

Отобразить информацию о версии среды выполнения

images, image, img

Вывести список образов

inspect

Отобразить состояние одного или нескольких контейнеров

inspecti

Отобразить статус одного или нескольких образов

imagefsinfo

Вывести информацию о файловой системе образа

inspectp

Отобразить состояния одного или нескольких pods

logs

Получить журналы контейнера

port-forward

Перенаправить локальный порт на pod

ps

Вывести список контейнеров

pull

Извлечь образ из реестра

run

Запустить новый контейнер внутри тестовой среды

runp

Запустить новый pod

rm

Удалить один или несколько контейнеров

rmi

Удалить один или несколько образов

rmp

Удалить один или несколько pods

pods

Вывести список pods

start

Запустить один или несколько созданных контейнеров

info

Отобразить информацию о среде выполнения контейнера

stop

Остановить один или несколько запущенных контейнеров

stopp

Остановить один или несколько запущенных pod

update

Обновить один или несколько запущенных контейнеров

config

Получить и установить параметры конфигурации crictl

stats

Показать статистику использования ресурсов контейнера (-ов)

statsp

Показать статистику использования ресурсов pods

completion

Вывести код завершения оболочки bash

checkpoint

Вывести контрольную точку одного или нескольких запущенных контейнеров

help, h

Вывести список команд или справку для одной команды

Сценарии использования crictl состоят в применении команд, обозначенных в таблице, и имеют следующий синтаксис:

crictl [global_options] command [command_options] [arguments...]

Например, команда crictl config --set debug=true устанавливает режим отладки при подаче последующих команд crictl.

Сrictl по умолчанию использует один из следующих URI (Uniform Resource Identifier) для подключения к CRI через сокеты Unix:

  • unix:///var/run/dockershim.sock;

  • unix:///run/containerd/containerd.sock;

  • unix:///run/crio/crio.sock;

  • unix:///var/run/cri-dockerd.sock.

Конечная точка может быть установлена:

  • в глобальных опциях --runtime-endpoint( -r) и --image-endpoint( -i);

  • путем назначения переменных окружения CONTAINER_RUNTIME_ENDPOINT и IMAGE_SERVICE_ENDPOINT;

  • в файле конфигурации --config=/etc/crictl.yaml.

Если конечная точка среды выполнения не установлена, crictl по умолчанию будет пытаться подключиться с помощью cri-o.

Если конечная точка образа не задана, по умолчанию будет использоваться конечная точка среды выполнения. В этом можно убедиться, отобразив содержимое файла crictl.yaml:

cat /etc/crictl.yaml

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

runtime-endpoint: unix:///var/run/dockershim.sock
image-endpoint: unix:///var/run/dockershim.sock
timeout: 2
debug: true
pull-image-on-create: false
Сценарий использования crictl#
  1. Загрузите crictl из репозитория, предоставленного разработчиком, используя curl:

    VERSION="v1.26.0" ## check latest version in /releases page
    curl -L https://<example>/cri-tools/releases/download/$VERSION/crictl-${VERSION}-linux-amd64.tar.gz --output crictl-${VERSION}-linux-amd64.tar.gz
    sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
    rm -f crictl-$VERSION-linux-amd64.tar.gz
    

    Примечание

    Выберите архив, соответствующий текущему типу процессора в среде развертывания, в приведенном примере указан архив, соответствующий архитектуре процессоров AMD.

  2. Запустите pod с конфигурационным файлом:

    cat pod-config.json
    {
       "metadata":{
          "name":"nginx-sandbox",
          "namespace":"default",
          "attempt":1,
          "uid":"hdishd83djaidwnduwk28bcsb"
       },
       "log_directory":"/tmp",
       "linux":{
    
       }
    }
    
    crictl runp pod-config.json
    <pod_ID>
    
  3. Убедитесь, что pod находится в состоянии Ready:

    crictl pods
    POD ID              CREATED             STATE               NAME                NAMESPACE           ATTEMPT
    f84dd361f8dc5       17 seconds ago      Ready               nginx-sandbox       default             1
    

    Команда crictl pods показывает список всех установленных pods в контейнере Docker, с указанием имени хоста и порта контейнера Docker, где были установлены pods.

    Например, если контейнер Docker запущен на хосте hostname и порте контейнера port, то команда crictl выведет следующий список установленных pods:

    • default;

    • nginx-sandbox.

  4. Запустите рабочую среду pod:

    cat pod-config.json
    {
       "metadata":{
          "name":"nginx-runsc-sandbox",
          "namespace":"default",
          "attempt":1,
          "uid":"hdishd83djaidwnduwk28bcsb"
       },
       "log_directory":"/tmp",
       "linux":{
    
       }
    }
    
    crictl runp --runtime=runsc pod-config.json
    <pod_ID>
    
    crictl inspectp <pod_ID>
    ...
    "runtime": {
    "runtimeType": "io.containerd.runtime.v1.linux",
    "runtimeEngine": "/usr/local/sbin/runsc",
    "runtimeRoot": "/run/containerd/runsc"
    },
    ...
    

    В приведенном примере показан запуск рабочей среды pod с обработчиком runsc.

  5. Извлеките образ busybox:

    crictl pull busybox
    

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

    Image is up to date for busybox@sha256:<image_hash>
    
  6. Выведите список образов и убедитесь, что выбранный образ busybox загружен:

    crictl images
    

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

    IMAGE               TAG                 IMAGE ID            SIZE
    busybox             latest              8c811b4aec35f       1.15MB
    k8s.gcr.io/pause    3.1                 da86e6ba6ca19       742kB
    
  7. Создайте контейнер с помощью файла конфигурации:

    cat pod-config.json
    {
        "metadata": {
            "name": "nginx-sandbox",
            "namespace": "default",
            "attempt": 1,
            "uid": "hdishd83djaidwnduwk28bcsb"
        },
        "log_directory": "/tmp",
        "linux": {
        }
    }
    
    cat container-config.json
    {
      "metadata": {
          "name": "busybox"
      },
      "image":{
          "image": "busybox"
      },
      "command": [
          "top"
      ],
      "log_path":"busybox.0.log",
      "linux": {
      }
    }
    
    crictl create <pod_ID> container-config.json pod-config.json
    <container_ID>
    
  8. Выведите список контейнеров и убедитесь, что созданный контейнер находится в статусе Created:

    crictl ps -a
    

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

    CONTAINER ID        IMAGE               CREATED             STATE               NAME                ATTEMPT
    3e025dd50a72d       busybox             32 seconds ago      Created             busybox             0
    
  9. Запустите стартовый контейнер:

    crictl start <container_ID>
    

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

    <container_ID>
    
  10. Убедитесь, что контейнер находится в состоянии Running:

    crictl ps
    

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

    CONTAINER ID        IMAGE               CREATED              STATE               NAME                ATTEMPT
    3e025dd50a72d       busybox             About a minute ago   Running             busybox             0
    
  11. Выполните команду в контейнере:

    crictl exec -i -t <container_ID> ls
    

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

    bin   dev   etc   home  proc  root  sys   tmp   usr   var
    
  12. Создайте и запустите контейнер:

    cat pod-config.json
    {
        "metadata":{
          "name":"nginx-sandbox",
          "namespace":"default",
          "attempt":1,
          "uid":"hdishd83djaidwnduwk28bcsb"
        },
        "log_directory":"/tmp",
        "linux":{
    
        }
    }
    
    cat container-config.json
    {
        "metadata":{
          "name":"busybox"
        },
        "image":{
          "image":"busybox"
        },
        "command":[
          "top"
        ],
        "log_path":"busybox.0.log",
        "linux":{
    
        }
    }
    
    crictl run container-config.json pod-config.json
    

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

    <container_ID>
    
  13. Выведите список контейнеров и убедитесь, что busybox находится в состоянии Running:

    crictl ps
    

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

    CONTAINER           IMAGE               CREATED             STATE               NAME                ATTEMPT             POD ID
    b25b4f26e3429       busybox:latest      14 seconds ago      Running             busybox             0                   158d7a6665ff3
    

Выше в шаге 13 представлен вывод команды crictl ps, которая показывает информацию о контейнерах, запущенных в DropApp. В данном случае выводится информация о контейнере busybox, который запущен на основе образа busybox:latest.

В выводе указаны следующие поля:

  • CONTAINER — уникальный идентификатор контейнера, который может быть использован для управления им;

  • IMAGE — имя образа, из которого был запущен контейнер;

  • CREATED — время создания контейнера;

  • STATE — текущее состояние контейнера (Running - запущен);

  • NAME — имя контейнера;

  • ATTEMPT — количество попыток запуска контейнера;

  • POD ID — идентификатор pod, в котором запущен контейнер.

API Server#

API Server — это центральный компонент кластера DropApp. Он является связывающим компонентом для всех остальных сервисов. Все взаимодействие как самих компонентов, так и обращение извне к кластеру проходит через kube-apiserver и проверяется им.

Это единственный компонент кластера DropApp, который общается с базой данных etcd, где хранится состояние кластера DropApp.

В самом API Server нет бизнес-логики. API Server не принимает решения, например, на каком node запустить тот или иной сервис. В нем существует логика проверки формата запросов, аутентификации, проверки прав и т.д. Еще одной функцией API Server является рассылка изменений конфигураций и состояния кластера DropApp. Другие компоненты подписываются на события, отслеживают их и обрабатывают, либо с определенной периодичностью считывают конфигурацию через API Server.

Etcd#

Etcd — это высоконадежное распределенное хранилище данных. DropApp хранит в нем информацию о состоянии существующих кластеров DropApp, сервисах, сети и т.д.

Доступ к данным осуществляется через REST API. При изменениях записей вместо поиска и изменения предыдущей копии, все предыдущие записи помечаются как устаревшие, а новые значения записываются в конец. Позже устаревшие значения удаляются специальным процессом. В небольших временных кластерах etcd можно запускать в единственном экземпляре и на одном node с ведущими компонентами.

В системах, требующих избыточности и высокой доступности, etcd следует создавать в виде кластера DropApp, состоящего из нескольких nodes.

API Server является основной точкой управления всего кластера DropApp. Он обрабатывает операции REST, проверяет их и обновляет соответствующие объекты в etcd. API Server обслуживает DropApp API и задуман как простой сервер, с большей частью бизнес-логики, реализованной в отдельных компонентах или в плагинах. Ниже приведены некоторые примеры API, доступных на API Server.

## pods
api/v1/pods

## services
api/v1/services

## deployments
api/v1/deployments

При работе с кластером DropApp с использованием интерфейса командной строки kubectl взаимодействие осуществляется с основным серверным компонентом API. Команды kubectl преобразуются в HTTP-вызовы REST и вызываются на API Server. API Server также отвечает за механизм аутентификации и авторизации. Все клиенты API должны быть аутентифицированы для взаимодействия с API Server. Возможно написание клиентских библиотек/приложений DropApp, используя API Server (например, аналог kubectl, chaos engineering system и т.д.).

Kube-scheduler#

Kube-scheduler — это компонент управляющего слоя, с его помощью необходимо отслеживать созданные pods без привязанного node и осуществлять выбор node, на котором pods должны работать. При развертывании pods на nodes учитывается множество факторов, включая требования к ресурсам, ограничения, связанные с аппаратными/программными политиками, принадлежности (affinity) и непринадлежности (anti-affinity) nodes/pods, местонахождения данных, предельные сроки.

Используя механизм оповещения об изменениях API Server, kube-scheduler получает сообщения от управляющего слоя, когда необходимо запустить экземпляр сервиса, и принимает решение о том, на каком node он должен быть запущен, а также через API Server обновляет состояние кластера DropApp. Сам kube-scheduler ничего не запускает.

Controller-manager#

Controller-manager — это компонент, отвечающий за запуск контроллеров, которые определяют текущее состояние системы.

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

Эти контроллеры включают:

  • контроллер node (Node Controller): уведомляет и реагирует на сбои node;

  • контроллер репликации (Replication Controller): поддерживает правильное количество pods для каждого объекта контроллера репликации в системе;

  • контроллер конечных точек (Endpoints Controller): заполняет объект конечных точек (Endpoints), то есть связывает сервисы (Services) и pods;

  • контроллеры учетных записей и токенов (Account & Token Controllers): создают стандартные учетные записи и токены доступа API для новых namespace.

CoreDNS#

CoreDNS — это сервер имен, который выступает в качестве ключевого компонента инфраструктуры кластера DropApp, предоставляя расширяемый механизм для разрешения имен внутри кластера DropApp.

Благодаря своей распределенной архитектуре и возможности использования нескольких источников данных, таких как файлы конфигурации, etcd или сетевые службы за пределами кластера DropApp, СoreDNS обеспечивает устойчивость и надежность DNS-сервиса в кластере DropApp. СoreDNS обладает быстрым и эффективным механизмом выполнения DNS-запросов и может быть легко настроен для интеграции с сетевыми политиками DropApp и расширения функциональности с помощью плагинов, что делает его неотъемлемой частью инфраструктуры кластера DropApp.

Запуск etcd#

Распределенное хранилище ключей и значений, предназначенное для безопасного хранения данных в кластере, etcd не поставляется как часть SberLinux OS Core. Чтобы использовать etcd, запустите его, как показано в примере конфигурации Butane для настройки одного node etcd:

variant: sbcos
version: 3.2.0
systemd:
  units:
    - name: etcd-member.service
      enabled: true
      contents: |
        [Unit]
        Description=Run single node etcd
        After=network-online.target
        Wants=network-online.target

        [Service]
        ExecStartPre=mkdir -p /var/lib/etcd
        ExecStartPre=-/bin/crio kill etcd
        ExecStartPre=-/bin/crio rm etcd
        ExecStartPre=-/bin/crio pull quay.io/oscore/etcd
        ExecStart=/bin/crio run --name etcd --volume /var/lib/etcd:/etcd-data:z --net=host quay.io/oscore/etcd:latest /usr/local/bin/etcd --data-dir /etcd-data --name node1 \
                --initial-advertise-peer-urls http://<initial-advertise-peer-URL> \
                --listen-peer-urls http://<listen-peer-URL> \
                --advertise-client-urls http://<advertise-client-URL> \
                --listen-client-urls http://<listen-client-URL> \
                --initial-cluster node1=http://<initial-cluster_node_1_URL>

        ExecStop=/bin/crio stop etcd

        [Install]
        WantedBy=multi-user.target

Настройка доступа SSH и запуск контейнеров при загрузке#

SberLinux OS Core предназначена для запуска приложений/служб в контейнерах, поэтому рекомендуется запускать контейнеры и избегать изменения хоста.

Настройте автоматический вход в систему (автологин) в командной строке, а также:

  • имя хоста;

  • конфигурацию системного пейджера (terminal pager);

  • SSH-ключ для основного пользователя;

  • службу systemd, которая выводит ошибки в случае их наличия при загрузке (failure.service);

  • службу systemd, которая будет использовать контейнер для выведения размещенной службы.

Настройка конфигурации Butane и преобразование в Ignition#

  1. Запишите приведенную конфигурацию Butane в файл под названием containers.bu:

    variant: sbcos
    version: 3.2.0
    passwd:
      users:
        - name: core
          ssh_authorized_keys:
            - ssh-rsa AAAA...
    systemd:
      units:
        - name: serial-getty@ttyS0.service
          dropins:
          - name: autologin-core.conf
            contents: |
              [Service]
              ## Переопределите Execstart в главном блоке
              ExecStart=
              ## Добавьте новый Execstart с префиксом `-`, чтобы игнорировать сбой
              ExecStart=-/usr/sbin/agetty --autologin core --noclear %I $TERM
              TTYVTDisallocate=no
        - name: failure.service
          enabled: true
          contents: |
            [Service]
            Type=oneshot
            ExecStart=/usr/bin/false
            RemainAfterExit=yes
    
            [Install]
            WantedBy=multi-user.target
        - name: etcd-member.service
          enabled: true
          contents: |
            [Unit]
            Description=Run a single node etcd
            After=network-online.target
            Wants=network-online.target
    
            [Service]
            ExecStartPre=mkdir -p /var/lib/etcd
            ExecStartPre=-/bin/crio kill etcd
            ExecStartPre=-/bin/crio rm etcd
            ExecStartPre=-/bin/crio pull quay.io/oscore/etcd
            ExecStart=/bin/crio run --name etcd --net=host \
                        --volume /var/lib/etcd:/etcd-data:z  \
                        quay.io/oscore/etcd:latest /usr/local/bin/etcd              \
                                --data-dir /etcd-data --name node1                  \
                                --initial-advertise-peer-urls <initial-advertise-peer-URL> \
                                --listen-peer-urls http://<listen-peer-URL>            \
                                --advertise-client-urls http://<advertise-client-URL>       \
                                --listen-client-urls http://<listen-client-URL>          \
                                --initial-cluster node1=http://<initial-cluster_node_1_URL>
            ExecStop=/bin/crio stop etcd
    
            [Install]
            WantedBy=multi-user.target
    storage:
      files:
        - path: /etc/hostname
          mode: 0644
          contents:
            inline: |
              tutorial
        - path: /etc/profile.d/systemd-pager.sh
          mode: 0644
          contents:
            inline: |
              ## Попросите systemd не использовать pager при печати информации
              export SYSTEMD_PAGER=cat
    
  2. Запустите Butane, чтобы преобразовать конфигурацию в Ignition:

    butane --pretty --strict containers.bu --output containers.ign
    ## Установите правильную метку SELinux, чтобы разрешить доступ к конфигурации
    chcon --verbose --type svirt_home_t containers.ign
    
    ## Запустите виртуальную машину SberLinux OS Core
    virt-install --name=sbcos --vcpus=2 --ram=2048 --os-variant=sberlinux-oscore-stable \
    --import --network=bridge=virbr0 --graphics=none \
    --qemu-commandline="-fw_cfg name=opt/com.oscore/config,file=${PWD}/containers.ign" \
    --disk=size=20,backing_store=${PWD}/sberlinux-oscore.qcow2
    
  3. Разверните SberLinux OS Core с использованием полученнной конфигурации Ignition.

    В терминале после загрузки будут присутствовать информация о системе, сетевых настройках, SSH-ключах и статусе служб, а также строка-приглашение:

    ...
    [core@tutorial ~]$
    
  4. Чтобы осуществить подключение через SSH, выйдите из bash, нажав комбинацию клавиш CTRL + ], затем используйте предоставленный в информации после загрузки IP-адрес, чтобы войти под пользователем core:

    ssh core@<IP_addr>
    

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

    Last login: Sun Aug 21 01:32:09 2022
    [systemd]
    Failed Units: 1
      failure.service
    

    Сообщение Failed Units поступает от сервиса вспомогательных сообщений. Когда у systemd есть службы с ошибками, они выводятся на экран. В приведенном примере failure.service настроена с excstart =/usr/bin/false, поэтому ошибка происходит намеренно, чтобы проиллюстрировать работу вспомогательных сообщений.

  5. Если система запущена без сбоев, проверьте сервис etcd-member.service:

    systemctl status --full etcd-member.service
    

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

    ● etcd-member.service - Run a single node etcd
        Loaded: loaded (/etc/systemd/system/etcd-member.service; enabled; vendor preset: enabled)
        Active: active (running) since Sun 2022-08-21 01:32:09 UTC; 2min 18s ago
        Process: 1608 ExecStartPre=mkdir -p /var/lib/etcd (code=exited, status=0/SUCCESS)
        Process: 1610 ExecStartPre=/bin/crio kill etcd (code=exited, status=125)
        Process: 1649 ExecStartPre=/bin/crio rm etcd (code=exited, status=1/FAILURE)
        Process: 1657 ExecStartPre=/bin/crio pull quay.io/oscore/etcd (code=exited, status=0/SUCCESS)
      Main PID: 1706 (crio)
          Tasks: 10 (limit: 2254)
        Memory: 91.5M
            CPU: 4.978s
        CGroup: /system.slice/etcd-member.service
                ├─ 1706 /bin/crio run ...
                └─ 1724 /usr/bin/conmon ...
    
    Aug 21 01:32:10 tutorial etcd[1724]: 2022-08-21 01:32:10.719193 N | etcdserver/membership: set the initial cluster version to 3.3
    Aug 21 01:32:10 tutorial etcd[1724]: 2022-08-21 01:32:10.719548 I | etcdserver/api: enabled capabilities for version 3.3
    Aug 21 01:32:10 tutorial crio[1706]: 2022-08-21 01:32:10.719193 N | etcdserver/membership: set the initial cluster version to 3.3
    Aug 21 01:32:10 tutorial crio[1706]: 2022-08-21 01:32:10.719548 I | etcdserver/api: enabled capabilities for version 3.3
    Aug 21 01:32:10 tutorial crio[1706]: 2022-08-21 01:32:10.719595 I | etcdserver: published {Name:node1 ClientURLs:[http://<URL>]} to cluster <cluster_ID>
    Aug 21 01:32:10 tutorial crio[1706]: 2022-08-21 01:32:10.719968 I | embed: ready to serve client requests
    Aug 21 01:32:10 tutorial etcd[1724]: 2022-08-21 01:32:10.719595 I | etcdserver: published {Name:node1 ClientURLs:[http://<URL>]} to cluster <cluster_ID>
    Aug 21 01:32:10 tutorial etcd[1724]: 2022-08-21 01:32:10.719968 I | embed: ready to serve client requests
    Aug 21 01:32:10 tutorial etcd[1724]: 2022-08-21 01:32:10.722332 N | embed: serving insecure client requests on <URL>, this is strongly discouraged!
    Aug 21 01:32:10 tutorial crio[1706]: 2022-08-21 01:32:10.722332 N | embed: serving insecure client requests on <URL>, this is strongly discouraged!
    
  6. Проверьте состояние контейнера, который был запущен службой systemd:

    sudo crio ps -a
    

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

    CONTAINER ID  IMAGE                       COMMAND               CREATED         STATUS             PORTS       NAMES
    9d854474bba7  quay.io/oscore/etcd:latest  /usr/local/bin/et...  11 minutes ago  Up 11 minutes ago              etcd
    
  7. Установите пары ключ=значение в etcd:

    curl -L -X PUT http://<URL>:<port>/v2/keys/sbcos -d value="fun"
    {"action":"set","node":{"key":"/sbcos","value":"fun","modifiedIndex":4,"createdIndex":4}}
    curl -L http://<URL>:<port>/v2/keys/ 2>/dev/null | jq .
    {
      "action": "get",
      "node": {
        "dir": true,
        "nodes": [
          {
            "key": "/sbcos",
            "value": "fun",
            "modifiedIndex": 4,
            "createdIndex": 4
          }
        ]
      }
    }
    

После этих шагов настройка является завершенной.

Очистка#

  1. Для очистки выйдите из bash, нажав комбинацию клавиш CTRL + ], затем удалите виртуальную машину:

    virsh destroy sbcos
    virsh undefine --remove-all-storage sbcos
    

Определение общих переменных среды прокси#

При развертывании в среде, требующей доступа в интернет через прокси, потребуется настроить службы таким образом, чтобы они могли получать доступ к ресурсам по назначению.

Лучше всего это сделать, определив один файл с требуемыми переменными среды в конфигурации Butane и сославшись на него через системные файлы для всех таких сервисов. На этот общий файл должна ссылаться каждая служба, которой требуется доступ в интернет. Пример конфигурации Butane:

variant: sbcos
version: 3.2.0
storage:
  files:
    - path: /etc/example-proxy.env
      mode: 0644
      contents:
        inline: |
          https_proxy="http://example.com:8080"
          all_proxy="http://example.com:8080"
          http_proxy="http://example.com:8080"
          HTTP_PROXY="http://example.com:8080"
          HTTPS_PROXY="http://example.com:8080"
          no_proxy="*.example.com,127.0.0.1,0.0.0.0,localhost"

Определение встраиваемых модулей для демонов контейнеров#

Если используется crio, достаточно добавить crio.service. Если используется containerd (и без crio), может потребоваться подключаемый модуль containerd.service:

variant: sbcos
version: 3.2.0
systemd:
  units:
    - name: crio.service
      enabled: true
      dropins:
        - name: 99-proxy.conf
          contents: |
            [Service]
            EnvironmentFile=/etc/example-proxy.env
    - name: containerd.service
      enabled: true
      dropins:
        - name: 99-proxy.conf
          contents: |
            [Service]
            EnvironmentFile=/etc/example-proxy.env

Определение использования прокси для модулей crio-systemd#

У crio нет демона, поэтому конфигурация запланирована для каждой отдельной службы и может быть выполнена как часть полного определения модуля systemd:

variant: sbcos
version: 3.2.0
systemd:
  units:
    - name: example-svc.service
      enabled: true
      contents: |
        [Unit]
        After=network-online.target
        Wants=network-online.target

        [Service]
        EnvironmentFile=/etc/example-proxy.env
        ExecStartPre=-/bin/crio kill example-svc
        ExecStartPre=-/bin/crio rm example-svc
        ExecStartPre=-/bin/crio pull example-image:latest
        ExecStart=/bin/crio run --name example-svc example-image:latest
        ExecStop=/bin/crio stop example-svc

        [Install]
        WantedBy=multi-user.target

Настройка раскладки клавиатуры#

Чтобы установить раскладку системной клавиатуры, используйте следующую конфигурацию Butane для записи /etc/vconsole.conf:

variant: sbcos
version: 3.2.0
storage:
files:
- path: /etc/vconsole.conf
  mode: 0644
  contents:
  inline: KEYMAP=de

После загрузки убедитесь, что нужная раскладка была установлена с помощью localectl.

Добавление расширений SberLinux OS Core в хост-систему#

SberLinux OS Core сохраняет базовый образ из соображений безопасности и удобства сопровождения. Для этого можно использовать установщик rpm-ostree install: он расширяет функциональность базовой SberLinux OS Core.

Чтобы добавить расширения SberLinux OS Core, внесите модуль systemd, который выполнит команду rpm-ostree для установки нужных пакетов. По умолчанию изменения, вносимые rpm-ostree install, помещаются в очередь для следующей загрузки. Параметр -A/--apply-live можно использовать для применения изменений в реальном времени и их сохранения.

Настройка имен сетевой карты#

Использование файла ссылки systemd#

Файл ссылки systemd можно создать с помощью конфигураций Ignition. Например, чтобы присвоить сетевой карте с MAC-адресом <MAC_addr> имя infra, поместите файл ссылки systemd /etc/systemd/network/25-infra.link с помощью фрагмента конфигурации Butane, как представлено ниже:

variant: sbcos
version: 3.2.0
storage:
  files:
    - path: /etc/systemd/network/25-infra.link
      mode: 0644
      contents:
        inline: |
          [Match]
          MACAddress=<MAC_addr>
          [Link]
          Name=infra

Использование правил Udev#

Аналогично с помощью конфигурации Ignition, чтобы присвоить NIC с MAC-адресом <MAC_addr> имя infra, создайте правило udev в /etc/udev/rules.d/80-ifname.rules с помощью фрагмента конфигурации Butane, как показано ниже:

variant: sbcos
version: 3.2.0
storage:
  files:
    - path: /etc/udev/rules.d/80-ifname.rules
      mode: 0644
      contents:
        inline: |
          SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="<MAC_addr>", ATTR{type}=="1", NAME="infra"'

Сеть в initramfs через аргументы ядра#

Если требуется подключение к сети в initramfs, аргумент ядра ifname= динамически создаст правило udev для изменения имени сетевой карты.

Эти правила udev не сохраняет в реальном корневом каталоге. Если пользовательское имя необходимо применить к реальному корню, создайте файл ссылки или правило udev, как показано выше в разделе «Использование правил Udev».

Например, чтобы задать сетевой карте с MAC-адресом <MAC_addr> имя infra, укажите аргумент ядра: ifname=infra:<MAC_addr>. В initramfs будет создано правило udev, например:

cat /etc/udev/rules.d/80-ifname.rules SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="<MAC_addr>", ATTR{type}=="1", NAME="infra"

Настройка подкачки на ZRAM#

Конфигурация для включения подкачки (swap) в ZRAM по умолчанию не настроена. Чтобы настроить подкачку (swap) на ZRAM, установите файл конфигурации через файл Ignition, который сообщит генератору ZRAM настроить подкачку поверх ZRAM.

Пример самой простой формы конфигурационного файла, который настроит устройство ZRAM для подкачки:

variant: sbcos
version: 3.2.0
storage:
  files:
    - path: /etc/systemd/zram-generator.conf
      mode: 0644
      contents:
        inline: |
          ## Этот конфигурационный файл включает устройство /dev/zram0 с настройками по умолчанию
          [zram0]

После загрузки убедитесь, что устройство подкачки настроено, проверив выходные данные с помощью команды swapon --show.