Стек классического приложения:
- Функции
- Роутинг урлов
- Окружение приложения
- Раннер приложения (gunicorn, например)
- Конфигурация, секреты
- Контейнер с зависимостями
- Описание деплоя
- Внутрикластерный роутинг
Проблема: приложение слишком много знает про нюансы нашей инфраструктуры и всю эту информацию надо повторять в каждом сервисе и поддерживать её в актуальном состоянии.
Задача: писать только бизнес-логику, всё остальное переложить на инфраструктуру и тулинг.
Стек Лямбды:
- Функция
- Окружение функции
- Конфигурация, секреты
- Зависимости
- Рантайм для конкретного языка программирования
- API гейтвей, триггеры
Типичный пример Лямбды:
def request_handler(event, context):
return 'ok'
Что у лямбда-рантайма под капотом:
while True:
event_request = lambda_runtime_client.wait_next_invocation()
...
result = request_handler(json_input, context)
...
lambda_runtime_client.post_invocation_result(invoke_id, result)
Плюсы:
- система асинхронных эвентов
- множество видов триггеров
Минусы:
- холодный запуск
Функции и serverless-style приложения в контейнерах с автоматическим масштабированием от 0 инстансов.
Состоит из компонентов:
- Serving
- Eventing
В составе был ещё и компонент Build, но его заменил проект tekton.dev.
Tekton заменяет CI систему, после чего вам по сути нужен только репозиторий кода и Kubernetes.
Serving значительно упрощает описание деплоя:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: example
spec:
template:
spec:
containers:
- image: gitlab.evo.dev/example/example
Eventing значительно сложнее и выглядит так:
Что может работать в Knative:
app.run(port=os.environ['PORT'])
-- т.е. по сути любой HTTP сервис, реализованный на любом языке программирования, никаких специальных SDK не требуется.
- Serving == Google Cloud Run
- Eventing ~= Google Cloud Pub/Sub
- Tekton ~= Google Cloud Build
Плюсы:
- request-driven, а не event-driven
- более универсальный чем просто Лямбда (serverless-style микросервисы)
- использует CloudEvents стандарт
- можно использовать gRPC
- работает в любом клауде и на своём железе
- рантайм от TriggerMesh умеет запускать Лямбда функции в Knative
Минусы:
- по простоте и степени интеграции с другими сервисами пока далёк от решений клауд-провайдеров
Чего не решает ни Лямбда ни Knative
- Окружение сервиса/функции
- Конфигурация, секреты
- Зависимости
- Описание деплоя
А это много всё того же бойлерплейта.
Пример конфигурации сервиса:
db:
value: postgres://user:pass@db:5432/users
auth:
host: auth.default.svc.cluster.local
port: 50051
bind:
host: 0.0.0.0
port: 80
Что можно сказать по этой конфигурации?
- нужно проинициализировать соединение к базе данных PostgreSQL
- нужно проинициализировать соединение к сервису аутентификации
- нужно поднять HTTP сервер и слушать на порту 80
Далее:
- нужно создать k8s ресурс Deployment с командой запуска сервиса и прочими деталями
- нужно создать k8s ресурс Service с ClusterIP и портом 80
- нужно создать k8s ресурсы Gateway и VirtualService с портом 80 и стандартным хостом
Вывод: из одной только конфигурации приложения можно много чего узнать о сервисе, и если эту конфигурацию описать должным образом, мы сможем избавиться от большей части бойлерплейта.
message Configuration {
bool debug = 1;
harness.postgres.DSN db = 2 [(harness.wire).input = "python/asyncpg:Connection"];
harness.grpc.Channel auth = 3 [(harness.wire).input = "python/grpclib:Channel"];
harness.grpc.Endpoint bind = 4 [(harness.wire).output = "python/grpclib:Server"];
}
Подробнее тут: https://github.com/vmagamedov/harness