Запрос к Kandinsky 2.1 был такой "панк рок караоке в средневековье в поле где идёт сражение и вокруг пиво". Считаю получилось шикарно.
Запрос к Kandinsky 2.1 был такой "панк рок караоке в средневековье в поле где идёт сражение и вокруг пиво". Считаю получилось шикарно.

Вступление

Приветствую всех! Давеча сидел и думал о том что часто хочется что-то попеть, покричать в микрофон и было бы круто иметь какое-то решение у себя дома, скажем домашнее караоке.

В интернете смотрел много разных решений и все казались или странные, или неудобные, так уже и не вспомню что от них меня отталкивало, в общем не цепляло, но в один момент наткнулся на Karaoke Eternal (впервые наткнулся когда еще назывался как Karaoke Forever) и мне так понравилось что решил незамедлительно поднять у себя дома.

Чтобы быстро поднять изучить как это работает я использовал свой любимый LXC, склонил git репозиторий и развернул по инструкции разработчика, кстати написано всё на node.js.

Далее я загрузил кучу видео с караоке которые взял с ютюба, некоторые просто где-то в интернете нашёл и всё закинул на свой сервер. Далее просто запустил и стал изучать.

Что такое Karaoke Eternal?

Karaoke Eternal - это удобный инструмент для создания караоке сервер (веб сервер), через которое мы можем удобно разделить где будет происходить воспроизведение песен (телевизор, пк), а откуда можно будет управлять очередью песен (телефон, планшет).

Давайте рассмотрим более детально функционал:

Окно авторизации и выбора комнаты караоке. (Комнаты создаются за ранее администратором сервера.)

Окно авторизации и выбора комнаты караоке (комнаты создаются за ранее).
Окно авторизации и выбора комнаты караоке (комнаты создаются за ранее).

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

Музыкальная библиотека.
Музыкальная библиотека.

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

  • Смотреть название песен

  • Смотреть сколько времени до воспроизведения любой песни в очереди

Также при выборе любой композиции выдвинется список действия над ней, а именно:

  • Добавить композиции в избранное

  • Передвинуть композиции сразу на самый верх и запустить

  • Информация о композиции

  • Удалить из очереди

Очередь песен
Очередь

И последняя вкладка это окно с настройками где есть управление комнатами, библиотекой и т.д.

Окно настроек
Окно настроек

Теперь покажу как это работает на практики, если коротко.

  1. Загружаем медиафайлы в папку где у нас запущен сервер

  2. Далее добавляем нашу папку и автоматически запускается сканирование файлов

  1. Открываем на телевизор / ПК где угодно где есть браузер наш вебсервер, авторизовываемся и нажимаем Start Player

  2. У нас открывается такое прекрасное окно. В котором и будет воспроизведение композиций.

    Player
    Player
  3. Далее через браузер заходим на сервер с телефона или с устройства с которого планируется управлять воспроизведением композиций, выбираем музыку и жмём Play.

Музыкальная библиотека и Очередь песен с телефона
Музыкальная библиотека и Очередь песен с телефона

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

Данное решение для караоке мне очень понравилось, поэтому в последствии я решил его перенести в свой домашний кластер kubernetes.

В целом я хотел быстро рассказать что это такое и для чего, а те кто хотят себе нечто подобное дома, велком =)

Поднимаем k3s

Для данной задачи в рамках статьи я сделал VM с 2 CPU, 2 RAM, 30 Gb, ОС ubuntu 20.04.

k3s в массы! И так я буду стараться вообще в каждой своей статье проходится от самого начала до полностью развернутого сервиса / приложения и т.д.

Подготовка ВМ или физического сервера не относиться к фазе от самого начала.

Hidden text

K3s (с офф сайт) — это сертифицированный дистрибутив Kubernetes с высокой доступностью, предназначенный для производственных рабочих нагрузок в автоматических, ограниченных по ресурсам, удаленных местах или внутри устройств IoT. (взято с офф сайт).

k3s (описание от меня) - это оркестратор контейнеров который может:

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

  • Ставить лимиты по ресурсам для контейнеров. (Как пример что приложение не сможет потреблять больше 2 Gb RAM или 2 CPU).

  • Задавать политики рестарта контейнеров.

  • Управлять доступностью к приложениям по сети.

  • Позволяет удобно читать логи.

  • Анализировать метрики.

  • Автомасштабированием контейнеров при повышении нагрузки ( к примеру если наше приложение в контейнере начинает грузится скажем под 80% по RAM или CPU оркестратор поднимет еще контейнеры и будет балансировать автоматическим сам нагрузку между ними).

  • И т.д.

  • И самое главное для нас мы можем описать это в манифесте один раз и потом переиспользовать и даже передавать кому угодно чтобы они могли запустить у себя или же наоборот мы можем запустить у себя чужой манифест.

И так я поставил чистую ubuntu 20.04 LTS, выделил ей 2 CPU 2 GB RAM, 20GB Disk и на неё первым делом мы будем ставить k3s.

  1. Открываем сайт https://k3s.io, на нем нам говорят что установка k3s не займет много времени.

  1. Копируем команду и дописываем параметр который понадобится нам потом дальше, выполняем.

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable servicelb" sh -
Hidden text

Как мне ранее указывали в прошлой статье в комментариях, внимательно смотрите что запускаете из интернета! Это важно! Особенно под sudo! Ссылка на комментарий: https://habr.com/ru/articles/703624/#comment_24988416

  1. Далее всего менее 30 секунд и кластер готов.

  1. Прописываем sudo kubectl get nodes и видим что наш кластер готов!

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

Пример сообщения: couldn't get resource list for metrics.k8s.io/v1beta1: the server is currently unable to handle the request

  1. Далее, чтобы мы могли работать удобно из под своей УЗ нам требуется скопировать kubeconfig в свою домашнюю папку и выполнить пару команд:

mkdir ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER .kube/config
echo "export KUBECONFIG=~/.kube/config" >> ~/.bashrc
source ~/.bashrc
kubectl get node
Hidden text

Что делаем в коде выше:

  • Cоздаем папку где будет хранится кубконфиг по умолчанию.

  • Копируем kubeconfig в ранее созданную папку.

  • Задаем права для kubeconfig на нашего пользователя и группу.

  • Загружаем в bashrc строчку которая будет задавать kubeconfig по умолчанию для kubectl при каждом входе в систему.

  • И смотрим готов ли наш кластер с одной нодой.

Все управление кластером осуществляется через утилиту kubeclt

И так буквально пару действий и у нас есть есть готовый кластер k3s почти со всеми преимуществами kubernetes и готовый к работе.

Вы можете также со своего компьютера подключиться к кластеру k3s, для этого нужно скопировать себе config и скачать утилиту kubectl.

После выполненных команд выше у нас должен быть такой вывод.

Поднимаем Karaoke Eternal

Hidden text

И так давайте для тех кто не сильно погружен в специфику kubernetes я обозначу три его сущности с которыми мы будем работать сейчас:

Pods - Это абстрактный объект Kubernetes, представляющий собой «обертку» для одного или группы контейнеров. Контейнеры в поде запускаются и работают вместе, имеют общие сетевые ресурсы и хранилище. Kubernetes не управляет контейнерами напрямую, он собирает их в поды и работает с ими.

Deployments - Это ресурс предназначенный для развертывания приложений и их обновления декларативным образом.

namespace - пространство в котором мы запускаем поды, загружаем конфиги и в общем ведем всю свою деятельность (удобно для разделения разных проектов/приложений в одном кластере).

  1. Начнем с того что создадим namespace karaoke

kubectl create ns karaoke
  1. Перед тем как поднимать караоке сервер следует озаботится тем где будут храниться наши файлы для караоке и конфиги. Я создам в директории var еще две директории и выдам им права для пользователя который будет использоваться в контейнере.

sudo mkdir -p /var/karaoke-eternal/karaoke
sudo mkdir -p /var/karaoke-eternal/config

sudo chown -R 1000:1000 /var/karaoke-eternal 

Вы можете задать и свои пути, тут как удобно.

  1. Теперь нам нужно составить манифест деплоймента для нашего караоке сервера.

Все манифесты для kubernetes описываются в виде yaml, требуется внимательно следить за пробелами.

Откроем наш любимый ви.

vi karaoke-deploy.yaml

И наполним его по примеру ниже.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: karaoke
  namespace: karaoke
  labels:
    app: karaoke
spec:
  replicas: 1
  selector:
    matchLabels:
      app: karaoke
  template:
    metadata:
      labels:
        app: karaoke
    spec:
      containers:
      - name: karaoke-eternal
        image: radrootllc/karaoke-eternal
        resources:
          requests:
            memory: "500Mi"
            cpu: "250m"
          limits:
            memory: "500Mi"
            cpu: "1000m"
        volumeMounts:
          - mountPath: /mnt/karaoke
            name: karaoke
          - mountPath: /config
            name: config
        securityContext:
          runAsUser: 1000
        ports:
        - containerPort: 8080
          protocol: TCP
      volumes:
      - name: karaoke
        hostPath:
          path: /var/karaoke-eternal/karaoke
          type: Directory
      - name: config
        hostPath:
          path: /var/karaoke-eternal/config
          type: Directory
Hidden text
  • spec - под первым мы описываем параметры deployment, по втором мы описываем работу нашего pod.

  • containers - описываем с какими параметрами будет подниматься наш контейнер.

  • image - какой образ нужно будет использовать.

  • selector - задаем по ним лейбл который нам понадобится дальше.

  • resources - описываем сколько выделяем фиксированно ресурсов для пода и сколько максимум он может забрать, то есть его лимиты и реквесты.

  • volumeMounts - прописываем куда монтировать наши PVC.

  • volumes - объявляем откуда с хоста где запущен k3s будут монтироватьcя папки.

  • port - указываем какие порты открыть из контейнеры.

  1. Применим манифест

kubectl apply -f karaoke-deploy.yaml
  1. Теперь нужно проверить что приложение запустилось, для этого выполним команду

kubectl get pods -n karaoke

Отлично всё работает! Теперь нам нужно вывести сервер наружу, чтобы мы могли к нему подключаться через браузер.

MetalLB

Для того чтобы вывести наш сервер наружу нужен service который будет перенаправлять трафик с пода наружу и наоборот.

Hidden text

Собственно он так и называется service, через него мы и можем перенаправить трафик наружу, и так service бывает:

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

NodePort - открывает определенный порт на всех узлах в кластере, и любой трафик, отправляемый на этот порт, перенаправляется в службу. Доступ к службе невозможен с IP-адреса кластера. 

LoadBalancer — это стандартный способ предоставления службы Kubernetes извне, чтобы к ней можно было получить доступ через Интернет. Если вы используете Google Kubernetes Engine (GKE), это создает балансировщик сетевой нагрузки с одним IP-адресом, к которому могут получить доступ внешние пользователи, а затем они перенаправляются на соответствующий узел в вашем кластере Kubernetes. Доступ к LoadBalancer можно получить так же, как к ClusterIP или NodePort.

И тут снова на помощь как в моей прошлой статье приходит metalLB! Мы развернем дома свой servicelb, направим его на наш домашний роутер и наш под будет прям с него получать свой IP и в нашей сети нам не придется мучиться с NodePort, пробросом портов и мы сможем сделать всё это красиво.

Кстати если на первом шаге не был отключен встроенный servicelb то будет конфликт и MetalLB не будет работать, тут описано как его отключить если вы не отключили его ранее.

Hidden text

Helm — это средство упаковки с открытым исходным кодом, которое помогает установить приложения Kubernetes и управлять их жизненным циклом.

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

  1. И так, шаг первый нужно установить helm.

helm вы можете просто скачать как бинарный файл и положить руками в /usr/bin и сделать его исполняемым.

Ниже команды взяты отсюда https://helm.sh/docs/intro/install/

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
  1. Далее клонируем репозиторий и запускаем helm с metalLB.

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

git clone https://github.com/general-rj45/metallb.git
helm install metallb metallb --create-namespace --namespace metallb
Hidden text

в команде helm мы указываем

  • install - установить

  • metallb - какое имя будет у хелм чарта когда он установиться

  • metallb - папка откуда нужно установить

  • --create-namespace --namespace metallb - создать неймспейс если его нет

Чтобы удалить хелм нужно ввести команду по примеру ниже:

helm delete -n metallb metallb

  1. Проверим что metallb запустился и нет с ним проблем.

kubeclt get pods -n metallb
  1. Теперь требуется задать пул IP адресов для metallb которые он будет присваивать для LoadBalancer.

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb
spec:
  addresses:
  - 192.168.1.100-192.168.1.200

---

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb
Hidden text
  • IPAddressPool - задаем диапазон ip для подов.

  • addresses - указываем диапазон ip.

  • L2Advertisement - для нас сейчас достаточно просто запустить, чтобы более конкретно погрузиться что это и для чего стоит почитать на офф сайте.

  1. Применим манифест.

kubectl apply -f metallb-IPAddressPool.yaml
  1. Теперь нам нужно создать service типа loadbalancer и вывести наружу наш сервер.

vi service-karaoke.yaml
apiVersion: v1
kind: Service
metadata:
  name: karaoke-service-lb
  namespace: karaoke
spec:
  type: LoadBalancer
  loadBalancerIP: 192.168.1.115
  selector:
    app: karaoke
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
      name: karaoke-http
Hidden text
  • type - тут задается тип service.

  • port - порт который будет выведен наружу.

  • targetPort - порт пода который будет перенаправляться.

  • protocol - задаем протокол tcp или udp

  • selector - тут указывается лейб по которому service сможет понять к какому поду подключить и перенаправлять трафик.

Применим

kubectl apply -f service-karaoke.yaml
  1. Проверяем что всё поднялось и мы можем зайти на сервер.

Далее обычная процедура регистрации, проходим её и у нас готовый сервер к работе.

Но вот теперь возникает еще проблема, а как закидывать файлы на сервер без костылей и лишней боли?

Samba-server

Так как большая часть машин у меня дома очень хорошо дружит с smb протоколом, то я подумал, а может это классное решение и я вам скажу да! К тому же очень удобное.

Про samba можно почитать по ссылке

И так что нам понадобится.

1. Требуется создать секрет, в нём будем содержать пароль и логин для входа в наш samba-server.

vi secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: karaoke-creds-samba
  namespace: karaoke
type: Opaque
data:
  password: a2FyYW9rZQ==
  username: a2FyYW9rZQ==
Hidden text

При создании секрета он всегда указывается в base64

Почитать про секреты более подробно можно тут https://kubernetes.io/docs/concepts/configuration/secret/

Но если коротко для чего секреты в kubernetes, это для того чтобы секьюрные данные спрятать в отельную сущность и подгружать их только по необходимости в поды.

kubectl apply -f secret.yaml
  1. После нам нужно прописать в нашем деплойменте еще один контейнер. Для него следует прописать ранее заданный секрет и папку где хранятся медиафайлы.

vi karaoke-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: karaoke
  namespace: karaoke
  labels:
    app: karaoke
spec:
  replicas: 1
  selector:
    matchLabels:
      app: karaoke
  template:
    metadata:
      labels:
        app: karaoke
    spec:
      containers:
      - name: karaoke-eternal
        image: radrootllc/karaoke-eternal
        resources:
          requests:
            memory: "100Mi"
            cpu: "100m"
          limits:
            memory: "300Mi"
            cpu: "400m"
        volumeMounts:
          - mountPath: /mnt/karaoke
            name: karaoke
          - mountPath: /config
            name: config
        securityContext:
          runAsUser: 1000
        ports:
        - containerPort: 8080
          protocol: TCP
      - name: smb-server
        image: andyzhangx/samba:win-fix
        resources:
          requests:
            memory: "100Mi"
            cpu: "100m"
          limits:
            memory: "300Mi"
            cpu: "400m"
        env:
          - name: PERMISSIONS
            value: "0777"
          - name: USERNAME
            valueFrom:
              secretKeyRef:
                name: karaoke-creds-samba
                key: username
          - name: PASSWORD
            valueFrom:
              secretKeyRef:
                name: karaoke-creds-samba
                key: password
        args: ["-u", "$(USERNAME);$(PASSWORD)", "-s", "share;/smbshare/;yes;no;no;all;none", "-p"]
        volumeMounts:
          - mountPath: /smbshare
            name: karaoke
      volumes:
      - name: karaoke
        hostPath:
          path: /var/karaoke-eternal/karaoke
          type: Directory
      - name: config
        hostPath:
          path: /var/karaoke-eternal/config
          type: Directory
Hidden text

Рекомендую внимательно посмотреть как мы добавили новый контейнер и какие параметры передали ему.

Применяем и проверяем что у нас корректно всё запустилось.

kubectl apply -f karaoke-deploy.yaml
kubectl get pods -n karaoke
  1. И заключительно это подправить LoadBalancer чтобы мы также по сети могли зайти на samba-server.

vi service-karaoke.yaml
apiVersion: v1
kind: Service
metadata:
  name: karaoke-service-lb
  namespace: karaoke
spec:
  type: LoadBalancer
  loadBalancerIP: 192.168.1.115
  selector:
    app: karaoke
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
      name: karaoke-http
    - port: 445
      targetPort: 445
      protocol: TCP
      name: karaoke-smb
Hidden text

В данном манифесте тоже есть интересный момент, мы подняли ранее два контейнера в одном поде, а теперь их двоих мы привязали к одному LoadBalancer и используя один ip мы можем по разным портам подключиться как к вебсерверу, так и к samba-server

И применяем

kubectl apply -f service-karaoke.yaml
  1. Проверяем, заходим через проводник по пути \\192.168.1.115 и вас должно встретить окно авторизации. (я заходил через windows, похожим способом можно и с mac и с linux зайти)

  2. Попробуем авторизоваться ранее заданным логином и паролем. В нашем случае karaoke/karaoke.

  1. Если всё корректно было сделано по инструкции то у нас выходит авторизоваться и мы видим папку share, теперь нужно вложить свои медиафайлы в папку.

Загружаем файлы и запускаем.

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

Я знаю что вроде бы не точно но можно использовать Download Master и через него скачивать видео с ютюба и даже целые альбомы, я конечно не пробовал, но вдруг у вас получиться. А так за подробностями можете в личку стучаться как и где доставать медиафайлы для караоке =)

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

  1. Как ранее писал создаем пользователя на сервере.

  1. Идём в настройки и выбираем Media Folders

  1. Нажимаем Add folder

  1. После проходим по пути /mnt/karaoke и нажимаем Add Folder

  1. Далее автоматически начнется сканирование и прогресс будет показан сверху экрана.

Примечание. Треки лучше называть по типу Author - Track, тире служит разделителем между исполнителем и названием песни.

Примечание 2. Треки не стоит называть кириллицей так как одни названия будут затирать другие и не все песни будут показываться.

  1. Заходим на вебсервер через телевизор/пк и в самом вверху нажимаем start player (так как я уже в самом начале описывал как это выглядит не хочу дублировать скрины сильно).

  2. Заходим с телефона на сервер и ставим песни в очередь и запускаем через play.

Вот и всё =)

В заключение

Тут бы хотел еще добавить как у меня выглядит коммутация дома для караоке, может кому-то будет полезно

  • Есть микшерный пульт в который идёт звук с Микрофона 1 и 2, а также в него идёт звук с тв приставки по aux.

  • С тв приставки в телевизор идёт hdmi только для вывод картинки, на нём я запускаю плеер с браузера.

  • С микшера уже все вместе идёт на отдельно стоящие мониторы (колонки).

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

Спасибо что дочитали мою статью, надеюсь кому-то это будет интересно. Будут вопросы не стесняйтесь задавайте, постараюсь ответить)

Вот единственное фото смог найти как у меня выглядит, конечно 6 из 10 шакалов, но норм)

Комментарии (2)


  1. molnij
    12.04.2023 07:58
    +3

    Эм, я правильно понимаю, вот эти вот все телодвижения чтобы на телевизоре запустить "видео с караоке которые взял с ютюба, некоторые просто где‑то в интернете нашёл"? о_О

    Чувствуется лёёёёгкий оверхед :D


    1. General_RJ-45 Автор
      12.04.2023 07:58

      Удобно запустить что немало важно) В целом да замудрённо, но когда у тебя дома много всего поднято то понимаешь что так проще и удобнее становиться поддерживать всё, к тому же если убрать часть с metallb и k3s, статья становится в два раза короче .