Serverless на бюджете ч. 1

Intro

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

Если говорить об основных преимуществах бессерверной архитектуры:
— Гибкая горизонтальная и вертикальная масштабируемость (scale-in, scale-out).
— Отсутствие накладных расходов на поддержку, когда нет нагрузки.

Области применения

FaaS отлично подходит для решения задач в разных областях:

  • Аналитика: пакетная обработка данных, для которой запускаются тысячи бессерверных функций отправляющих запросы к разным API.

  • IoT

  • Бэкенды для мобильных приложений

  • Обработка видео файлов и изображений

  • AI

«Киллер фича» OpenWhisk это поддержка сразу нескольких языков программирования: Net, Go, Java, JavaScript, PHP, Python (Tensorflow and PyTorch), Ruby, Swift.
Возможность декомпозиции и распределения обязанностей между разными командами особенно важна для крупных компаний.

Альтернативные варианты

  • AWS Lambda

  • Azure Functions

  • IBM Cloud Functions — это Apache OpenWhisk, эти два проекта используют одну кодовую базу

  • Kubernetes-native платформы (Fission, Kubeless and Open-FaaS)

По сравнению с облачными сервисами OpenWhisk выигрывает в портативности — ваш код будет работать on-prem или в облаке.
Нет необходимости привязываться к какому-то определенному вендору.

Решения основанные на Kubernetes проигрывают в функциональности и производительности при высоких нагрузках.
Некоторые из этих решений используют модель «open core» — часть функционала доступна только в платной версии продукта.

Архитектура

Буквально пару слов об архитектуре OpenWhisk:

  • Nginx терминирует SSL

  • Для взаимодействия с кластером OpenWhisk, пользователь должен использовать специальный CLI — wsk

  • Controller (написан на Scala) сохраняет сущности OpenWhisk в специальное документарное хранилище CouchDB.

  • Для обмена данными между компонентом Invoker используется Kafka

  • Invoker запускает контейнеры Docker с нужным рантаймом (Java, Python, Go etc). По одному топику Kafka на инстанс Invoker. Для каждой функции запускается отдельный контейнер. При этом все компоненты OpenWhisk тоже работают в Docker контейнерах.

    Архитектура

    Архитектура

OpenWhisk может работать с отдельно стоящим функциями (actions).
С помощью триггеров реагировать на внешние сигналы, например на сообщения шине данных:

Архитектура

Архитектура

Более подробно с архитектурой OpenWhisk можно познакомится на сайте проекта, а мы побежали дальше.

Установка

Если верить разработчикам OpenWhisk, Docker стильно выигрывает по производительности по сравнению с инсталляцией в кластер Kubernetes:

https://rutube.ru/video/176bb55742eae383bd07dd6948bd1d26/?t=1149&r=plwd

Но для нас сейчас важнее удобство, чем скорость, поэтому будем использовать именно K8s.

К счастью существует Helm чарт, который поддерживают мейнтейнеры OpenWhisk:

Для работы OpenWhisk обязательно нужно настроить Ingress. Если это тестовый кластер, то можно использовать NodPort.
ingress.yaml:

whisk:
  ingress:
    type: NodePort
    api_host_name: 
    api_host_port: 31001

nginx:
  httpsNodePort: 31001

mycluster.yaml:

affinity:
  enabled: false

toleration:
  enabled: false

invoker:
  options: "-Dwhisk.kubernetes.user-pod-node-affinity.enabled=false"
  containerFactory:
    impl: "kubernetes"

На тестовом кластере можно создать label, чтобы OpenWhisk знал на каких нодах можно запускать invoker:

kubectl label nodes --all openwhisk-role=invoker

Для установки чарта:

git clone https://github.com/apache/openwhisk-deploy-kube.git
helm install openwhisk ./openwhisk-deploy-kube/helm/openwhisk -n openwhisk --create-namespace -f mycluster.yaml

Проверяем как прошла установка:

kubectl get pods --namespace openwhisk

NAME                                         READY   STATUS      RESTARTS   AGE
openwhisk-alarmprovider-84cdc4c966-xjjwp                         1/1     Running     0          3m59s
openwhisk-apigateway-858b4b948d-v626q                            1/1     Running     0          3m59s
openwhisk-controller-0                                           1/1     Running     0          3m59s
openwhisk-couchdb-f879f9c4f-rcjxg                                1/1     Running     0          3m59s
openwhisk-gen-certs-f6tj2                                        0/1     Completed   0          3m59s
openwhisk-init-couchdb-k2bqn                                     0/1     Completed   0          3m59s
openwhisk-install-packages-wrpvc                                 1/1     Running     0          3m59s
openwhisk-invoker-0                                              1/1     Running     0          3m59s
openwhisk-kafka-0                                                1/1     Running     0          3m59s
openwhisk-kafkaprovider-6fc76d7b45-64qnb                         1/1     Running     0          3m58s
openwhisk-nginx-74545f49c7-vdnbm                                 1/1     Running     0          3m59s
openwhisk-redis-656c76cfff-ts59t                                 1/1     Running     0          3m59s
openwhisk-wskadmin                                               1/1     Running     0          3m59s
openwhisk-zookeeper-0                                            1/1     Running     0          3m59s
wskopenwhisk-invoker-00-1-prewarm-nodejs14                       1/1     Running     0          88s
wskopenwhisk-invoker-00-2-prewarm-nodejs14                       1/1     Running     0          88s
wskopenwhisk-invoker-00-3-whisksystem-invokerhealthtestaction0   1/1     Running     0          88s

Теперь можно приступить к установке пользовательских компонентов.

OpenWhisk CLI

Для работы с actions и triggers используется утилита командной строки wsk.

Для установка на Mac можно использовать homebrew:

brew install wsk

для Linux надо скачать бинарный файл:

wget https://github.com/apache/openwhisk-cli/releases/download/1.2.0/OpenWhisk_CLI-1.2.0-linux-amd64.tgz
tar -xzvf OpenWhisk_CLI-1.2.0-linux-amd64.tgz
mv wsk /usr/local/bin/

Для того, чтобы wsk мог связаться с кластером необходимо указать адрес apiserver, порт и auth.
По-умолчанию wsk берет их из файла ~/.wskprops:

cat ~/.wskprops

APIHOST=:
AUTH=26fd5813-72c1-489c-ad9b-997799698bce:WSIUsVihGStkvDvEsx5eHHYvFEowKQczDNOX8bFT1rat6q7JFgizQTsqXhaqY5wN
NAMESPACE=owuser

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

kubectl -n openwhisk  -ti exec openwhisk-wskadmin -- wskadmin user create owuser

26fd5813-72c1-489c-ad9b-997799698bce:WSIUsVihGStkvDvEsx5eHHYvFEowKQczDNOX8bFT1rat6q7JFgizQTsqXhaqY5wN
kubectl -n openwhisk  -ti exec openwhisk-wskadmin -- wskadmin user whois 26fd5813-72c1-489c-ad9b-997799698bce:WSIUsVihGStkvDvEsx5eHHYvFEowKQczDNOX8bFT1rat6q7JFgizQTsqXhaqY5wN

subject: owuser
namespace: owuser

Теперь можно преступать к работе — например вывести список с сущностями в целевом пространстве имен:

wsk -i list

Entities in namespace: default
packages
actions
triggers
rules

Флаг -i нужен для того, чтобы отключить проверку сертификата.

Test

Для того, чтобы убедится, что установка прошла успешно, давайте создадим hello world.

hello.js:

function main(params) {
    msg = "Hello, " + params.name + " from " + params.place;
    return { greeting:  msg };
}

Создаем action:

wsk -i action create hellojs hello.js

ok: created action hellojs

С помощью invoke запускаем нашу функцию и получаем результат:

wsk -i action invoke hellojs --result
{
    "greeting": "Hello, undefined from undefined"
}

Теперь с параметрами:

wsk -i action invoke hellojs --result --param name Anton --param place Habr

{
    "greeting": "Hello, Anton from Habr"
}

End

PS. В следующей части сделаем полноценное приложение с фронтендом и бэкендом, а OpenWhisk будет запускать интересные экшены.

© Habrahabr.ru