Русский
Русский
English
Статистика
Реклама

Script

CRI-O как замена Docker в качестве исполняемой среды для Kubernetes настройка на CentOS 8

20.08.2020 12:11:50 | Автор: admin
Привет! Меня зовут Сергей, я DevOps в Surf. DevOps-отдел в Surf ставит своей задачей не только налаживание взаимодействия между специалистами и интеграцию рабочих процессов, но и активные исследования и внедрение актуальных технологий как в собственную инфраструктуру, так и в инфраструктуру заказчика.

Ниже я немного расскажу об изменениях в технологическом стеке для контейнеров, с которыми мы встретились при изучении дистрибутива CentOS 8 и о том, что такое CRI-O и как быстро настроить с его помощью исполняемую среду для Kubernetes.



Почему Docker отсутствует в стандартной поставке CentOS 8


После установки последних крупных релизов RHEL 8 или CentOS 8 нельзя не заметить: в этих дистрибутивах и официальных репозиториях отсутствует приложение Docker, которое идеологически и функционально заменяют собой пакеты Podman, Buildah (присутствуют в дистрибутиве по умолчанию) и CRI-O. Это связано с практической реализацией стандартов, разрабатываемых, в том числе, и компанией Red Hat в рамках проекта Open Container Initiative (OCI).

Цель OCI, являющейся частью The Linux Foundation, создание открытых индустриальных стандартов для форматов и исполняемой среды контейнеров, которые бы решали сразу несколько задач. Во-первых, не противоречили как философии Linux (например, в той её части, что каждая программа должна выполнять какое-то одно действие, а Docker представляет собой этакий комбайн всё-в-одном). Во-вторых, могли бы устранить все имеющиеся недостатки в программном обеспечении Docker. В-третьих, были бы полностью совместимыми с бизнес-требованиями, выдвигаемыми ведущими коммерческими платформами для развёртывания, управления и обслуживания контейнеризованных приложений (например, Red Hat OpenShift).

Недостатки Docker и достоинства нового ПО уже были довольно подробно описаны в этой статье, а с подробным описанием как всего предлагаемого в рамках проекта OCI стека ПО и его архитектурными особенностями можно ознакомиться в официальной документации и статьях как от самой Red Hat (неплохая статья в Red Hat blog), так и в сторонних обзорах.

Важно отметить, какую функциональность имеют компоненты предлагаемого стека:

  • Podman непосредственное взаимодействие с контейнерами и хранилищем образов через процесс runC;
  • Buildah сборка и загрузка в реестр образов;
  • CRI-O исполняемая среда для систем оркестрации контейнеров (например, Kubernetes).

Думаю, что для понимания общей схемы взаимодействия между компонентами стека целесообразно привести здесь схему связей Kubernetes c runC и низкоуровневыми библиотеками с использованием CRI-O:



CRI-O и Kubernetes придерживаются одного и того же цикла выпуска и поддержки (матрица совместимости очень проста: мажорные версии Kubernetes и CRI-O совпадают), а это, с учётом ориентира на полное и всестороннее тестирование работы данного стека разработчиками, даёт нам право ожидать максимально достижимой стабильности в работе при любых сценариях использования (здесь на пользу идет и относительная легковесность CRI-O по сравнению с Docker в силу целенаправленного ограничения функциональности).

При установке Kubernetes right way способом (по мнению OCI, конечно) с использованием CRI-O на CentOS 8 мы столкнулись с небольшими затруднениями, которые, однако, успешно преодолели. Буду рад поделиться с вами инструкцией по установке и настройке, которые в совокупности займут от силы 10 минут.

Как развернуть Kubernetes на CentOS 8 с использованием среды CRI-O


Предварительные условия: наличие как минимум одного хоста (2 cores, 4 GB RAM, накопитель не менее 15 GB) с установленной CentOS 8 (рекомендуется профиль установки Server), а также записи для него в локальном DNS (в крайнем случае можно обойтись записью в /etc/hosts). И не забудьте отключить swap.

Все операции на хосте производим от имени пользователя root, будьте внимательны.

  1. На первом шаге настроим ОС, установим и настроим предварительные зависимости для CRI-O.
    • Обновим ОС:

      dnf -y update
      

    • Далее требуется настроить файрволл и SELinux. Здесь у нас всё зависит от окружения, в котором будут работать наш хост или хосты. Вы можете либо настроить файрволл по рекомендациям из документации, либо, если находитесь в доверенной сети или применяете сторонний файрволл, изменить зону по умолчанию на доверенную или выключить файрволл:

      firewall-cmd --set-default-zone trustedfirewall-cmd --reload
      

      Чтобы выключить файрволл можно использовать следующую команду:

      systemctl disable --now firewalld
      

      SELinux требуется выключить либо перевести в режим permissive:

      setenforce 0sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
      

    • загрузим необходимые модули ядра и пакеты, настроим автоматическую загрузку модуля br_netfilter при старте системы:

      modprobe overlaymodprobe br_netfilterecho "br_netfilter" >> /etc/modules-load.d/br_netfilter.confdnf -y install iproute-tc
      

    • для активации форвардинга пакетов и корректной обработки трафика сделаем соответствующие настройки:

      cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOFnet.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1net.bridge.bridge-nf-call-ip6tables = 1EOF
      

      применим сделанные настройки:

      sysctl --system
      

    • зададим необходимую версию CRI-O (мажорная версия CRI-O, как уже упоминалось, совпадают с требуемой версией Kubernetes), так как последняя стабильная версия Kubernetes на данный момент 1.18:

      export REQUIRED_VERSION=1.18
      

      добавим необходимые репозитории:

      dnf -y install 'dnf-command(copr)'dnf -y copr enable rhcontainerbot/container-selinuxcurl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_8/devel:kubic:libcontainers:stable.repocurl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$REQUIRED_VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$REQUIRED_VERSION/CentOS_8/devel:kubic:libcontainers:stable:cri-o:$REQUIRED_VERSION.repo
      

    • теперь мы можем установить CRI-O:

      dnf -y install cri-o
      

      Обратите внимание на первый нюанс, который мы встречаем в процессе инсталляции: необходимо отредактировать конфигурацию CRI-O перед запуском сервиса, так как требуемый компонент conmon имеет отличное от указанного место размещения:

      sed -i 's/\/usr\/libexec\/crio\/conmon/\/usr\/bin\/conmon/' /etc/crio/crio.conf
      


      Теперь можно активировать и запустить демон CRI-O:

      systemctl enable --now crio
      


      Можно проверить статус демона:

      systemctl status crio
      

  2. Установка и активация Kubernetes.
    • Добавим требуемый репозиторий:

      cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearchenabled=1gpgcheck=1repo_gpgcheck=1gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpgexclude=kubelet kubeadm kubectlEOF
      

      Теперь мы можем установить Kubernetes (версии 1.18, как уже указывалось выше):

      dnf install -y kubelet-1.18* kubeadm-1.18* kubectl-1.18* --disableexcludes=kubernetes
      

    • Второй важный нюанс: так как мы не используем демон Docker, а используем демон CRI-O, до запуска и инициализации Kubernetes требуется внести соответствующие настройки в конфигурационный файл /var/lib/kubelet/config.yaml, предварительно создав нужный каталог:

      mkdir /var/lib/kubeletcat <<EOF > /var/lib/kubelet/config.yamlapiVersion: kubelet.config.k8s.io/v1beta1kind: KubeletConfigurationcgroupDriver: systemdEOF
      

    • Третий важный момент, с которым мы сталкиваемся при установке: несмотря на то, что мы указали используемый драйвер cgroup, и его настройка через аргументы передаваемые kubelet устарела (на что прямо указано в документации), нам необходимо добавить в файл аргументы, иначе наш кластер не инициализируется:

      cat /dev/null > /etc/sysconfig/kubeletcat <<EOF > /etc/sysconfig/kubeletKUBELET_EXTRA_ARGS=--container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint='unix:///var/run/crio/crio.sock'EOF
      

    • Теперь мы можем активировать демон kubelet:

      sudo systemctl enable --now kubelet
      

      Чтобы настроить control-plane или worker ноды за считанные минуты, вы можете воспользоваться этим скриптом.

  3. Пора инициализировать наш кластер.
    • Для инициализации кластера выполните команду:

      kubeadm init --pod-network-cidr=10.244.0.0/16
      

      Обязательно запишите команду присоединения к кластеру kubeadm join ..., которой предлагается воспользоваться в конце вывода, либо, как минимум, указанные токены.

    • Установим плагин (CNI) для работы Pod network. Я рекомендую использовать Calico. Возможно, более популярный Flannel имеет проблемы с совместимостью с nftables, да и Calico единственная реализация CNI, рекомендуемая и полностью протестированная проектом Kubernetes:

      kubectl --kubeconfig /etc/kubernetes/admin.conf apply -f https://docs.projectcalico.org/v3.15/manifests/calico.yaml 
      

    • Для подключения worker ноды к нашему кластеру её требуется настроить по пунктам инструкции 1 и 2, либо воспользоваться скриптом, затем выполнить команду из вывода kubeadm init ..., которую мы записали на предыдущем этапе:

      kubeadm join $CONTROL_PLANE_ADDRESS:6443 --token $TOKEN \    --discovery-token-ca-cert-hash $TOKEN_HASH
      

    • Проверим, что наш кластер инициализирован и начал работу:

      kubectl --kubeconfig=/etc/kubernetes/admin.conf get pods -A
      

    Готово! Вы уже можете размещать на вашем K8s кластере полезную нагрузку.

Что нас ждёт впереди


Надеюсь, что инструкция выше помогла сэкономить вам немного времени и нервов.
Исход процессов, происходящих в индустрии, зачастую зависит от того, как их принимает основная масса конечных пользователей и разработчиков другого ПО в соответствующей нише. Пока не совсем ясно, к какому итогу через несколько лет приведут инициативы OCI, но мы будем с удовольствием за этим следить. Своим мнением вы можете поделиться прямо сейчас в комментариях.
Stay tuned!

Данная статья появилась благодаря следующим источникам:

Подробнее..

Скрипт на ruby, который с помощью яндекс-сервиса Yandex SpeechKit распознает текст в видео-файле (длинные аудио)

11.01.2021 12:12:41 | Автор: admin

Начну с того, что я совсем недавно начала погружаться в IT в целом и Ruby в частности, и это задание мне выдали в качестве тестового для получения места на стажировке. Заранее скажу, что тут еще есть что приглаживать и улучшать, но в целом код работает.

Однако, возможно, мой опыт может быть для кого то полезен, так что представляю вашему вниманию подробное описание создания этого скрипта. ВАЖНО: Моя операционная система Fedora 32, так же я использую заранее установленный в систему bundler. Так что если вы тоже используете linux-подобные системы, читаем далее.

Суть задания: есть видеофайл в формате mp4 нужно написать скрипт на чистом ruby, который будет конвертировать этот файл в аудио, отправлять его в сервис яндекса Yandex SpeechKit и получив ответ, создавать текстовый файл.

Перед началом работы стоит внимательно изучить документацию Яндекса, на предмет подводных камней и таких нюансов, как читаемый яндексом формат аудио (а их, к слову, всего два: OggOpus и LPCM).

Подготовительный этап:

Теперь можно перейти к составлению плана работы:

  1. Перевод файла из формата mp4 в аудио с помощью утилиты ffmpeg

  2. Отправить получившийся файл в бакет Yandex Service Object

  3. Отправить полученный ответ с адресом файла в бакете на SpeechKit

  4. Получить ответ и преобразовать его в текстовый файл

Далее будем двигаться по пунктам с пояснениями интересных (и не всегда очевидных мест)

1. Перевод файла из формата mp4 в аудио с помощью утилиты ffmpeg

Для форматирования видео файла устанавливаем в нашу систему ffmpeg

sudo dnf install ffmpeg

И, если вы этого еще не сделали, кладем требующий форматирования видеофайл в папку нашего небольшого проекта (в моём случае это будет test_task)

В этой же папке создаем рубишный файлик (например, run.rb), в котором будем писать скрипт:

touch run.rb

В скрипте нам необходимо вызывать команды оболочки изнутри программы ruby (bash-команды, такие как: system, exec, popen, ` `) Мельком ознакомиться с этими командами можно здесь (https://www.rubyguides.com/2018/12/ruby-system/)

Я решила использовать заключение в ` `:

`ffmpeg -i test.mp4 -vn -acodec libopus audio.ogg`
Где:

test.mp4 название и формат форматируемого видеофайла.

Флажок -vn используется, чтобы указать, что нам нужен именно аудио формат (без видео).

Библиотеку libopus мы используем, так как для SpeechKit нужен именно OggOpus формат.

audio.ogg название для нового аудиофайла, который мы получим в результате форматирования и его формат (в нашем случае ogg)

Теперь, если запустить наш файл в консоли, мы должны получить на выходе аудиофайл в нужном нам формате.

2. Отправить получившийся файл в бакет Yandex Service Object

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

Согласно документации яндекса, мы не можем загрузить в сервис непосредственно файл, нам нужно использовать ссылку на загруженный в Yandex Object Storage (яндекс хранилище) объект.

Так как Yandex Object Storage имеет HTTP API, совместимый с Amazon S3, мы можем воспользоваться инструментами, созданными для работы с объектными хранилищами Amazon S3.

Для Amazon S3 реализован руби гем aws-sdk-s3, мы можем применить его для загрузки нашего файла в Yandex Object Storage.

Устанавливаем гем aws-sdk-s3. Создаём в папке с тестовым заданием Gemfile и в нем прописываем:

 source 'https://rubygems.org' gem 'aws-sdk-s3'

gem 'aws-sdk-s3' Далее в консоли запускаем команду:

bundle install

И подключаем этот гем в наш файлик run.rb, прописывая в нём:

require 'aws-sdk-s3'

Как пример кода использовала эту статью.

На этом этапе нам понадобится создать API-ключ в яндексе и сохранить его.

Важный момент: создать нужно именно статический ключ доступа для Object Storage и Message Queue.

Так как, светить свои приватные ключи всему интернету - дурной тон, воспользуемся гемом dotenv. Этот гем нужен нам для введения переменных окружения, их мы заботливо поместим в файлик .env , который никому не покажем.

Устанавливаем гем, записываем его в Gemfile:

gem 'dotenv'

И запускаем команды в терминале:

bundle install

Теперь инклюдим его в наш файлик:

require 'dotenv/load'

И создаем в нашей папке со скриптом файлик .env с переменными, в которые заносим ключ и идентификатор:

AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXAWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXX

Далее просто меняем пример из статьи выше под наш случай. Cначала прописываем конфигурацию для aws, указывая регион и ключ с идентификатором:

 Aws.config.update(   region: 'ru-central1',   credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']) )

Добавляем эндпоинт яндекс хранилище:

region: 'ru-central1',   credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'],    ENV['AWS_SECRET_ACCESS_KEY']) s3 = Aws::S3::Client.new(endpoint: "https://storage.yandexcloud.net")

И, наконец, открываем и отправляем отформатированный ранее аудиофайл в созданный нами бакет. (Здесь, разумеется можно обойтись без вывода результата(puts pp), но так нагляднее)

 File.open('audio.ogg', 'r') do |file|   pp = s3.put_object({     bucket: 'teststask',     key: 'audio.ogg',     body: file   })     puts pp end

Теперь мы можем проверить работу кода запустив run.rb и обновив страницу бакета (в нем должен появится новый файл).

3. Отправить полученный ответ с адресом файла в бакете на SpeechKit

Для работы с http запросами в руби есть гем httparty (https://github.com/jnunemaker/httparty/blob/master/examples/basic.rb)

И примеры работы с этим гемом.

Устанавливаем гем, записываем его в Gemfile:

gem 'httparty'

И запускаем команды в терминале:

bundle install

Теперь инклюдим его в наш файлик:

require 'httparty'

Далее можно воспользоваться им в написании кода для отправки ссылки из предыдущего этапа.

Необходимо сформировать ссылку, так как реализовывать ее получение внутри скрипта не является частью задачи , то прибегнем к хитрости. Ссылка состоит из сервиса, имени бакета и имени файла, которое обычно является путем к файлу: https://storage.yandexcloud.net/<имя-бакета>/<путь-к-файлу>

Значит мы можем самостоятельно сформировать эту ссылку, так как все это у нас уже есть:

https://storage.yandexcloud.net/teststask/audio.ogg


Конечно, эту часть можно довольно легко автоматизировать, но время не ждало и задачи улучшить скрипт не стояло)) Так что здесь можете применить все свои навыки!

Далее переходим к формированию post запроса на SpeechKit.

Нам необходимо составить запрос с хедером, содержащим API-ключ для авторизации и телом, включающим нашу ссылку и язык. Подробнее можно посмотреть в документации яндекса.

Важно: здесь нам необходим другой API-ключ (API-ключ для упрощенной аутентификации вместо IAM-токена)

Положим всё это в переменную options.

 options = {   headers: {"Authorization" => "Api-Key #{ENV['API_KEY']}"},   body: {     "config" => {         "specification" => {             "languageCode" => "ru-RU"         }     },     "audio" => {         "uri" => "https://storage.yandexcloud.net/teststask/audio.ogg"     }   }.to_json }
 response = HTTParty.post('https://transcribe.api.cloud.yandex.net/speech/stt/v2/longRunningRecognize', options).to_h

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

Теперь нам нужно отправить запрос на получение информации об операции.

Создаем параметр для нового запроса в котором оставляем только авторизацию:

 option = {    headers: {"Authorization" => "Api-Key #{ENV['API_KEY']}"} }

И создаём цикл, который будет проверять, закончена ли обработка аудио и, в случае положительного результата выводить ответ в виде хеша. Здесь в качестве одного из параметров мы и передаем тот самый идентификатор операции распознавания (это #{response['id']} в ссылке "https://operation.api.cloud.yandex.net/operations/#{response['id']}").

Интервал в 2 секунды между запросами, необходим, чтобы система яндекса не посчитала нас вредоносной программой)

 done = false until done   yandex_answer = HTTParty.get("https://operation.api.cloud.yandex.net/operations/#{response['id']}", option).to_h   puts yandex_answer   done = yandex_answer['done']   sleep 2 end

4. Получить ответ и преобразовать его в текстовый файл

Так как здесь вступет в дело ruby, многим эта часть покажется менее интересной. Просто работаем с хешами и массивами:

 yandex_array = yandex_answer["response"]["chunks"] yandex_text = []  yandex_array.each do |elem|   yandex_text << elem["alternatives"].first["text"] end

pp yandex_text.uniq!

Создаем через bash-команду новый файлик:

`touch test.txt`

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

File.open("test.txt", 'w') { |file| file.write(":#{yandex_text.join(' ')}") }

Итого мы имеем три файла: .env (с переменными окружения), Gemfile (с тремя гемами: httparty, aws-sdk-s3, dotenv), run.rb (с кодом).

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

Подробнее..
Категории: Ruby , Script , Yandex.ru , Speechkit , Ffm , Aws sdk , Dotenv

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru