docs: переработан examples/README.md + комментарии function.tf

This commit is contained in:
“Naeel”
2026-03-11 16:48:01 +04:00
parent 81be52f6ef
commit 5c6a37313b
3 changed files with 157 additions and 90 deletions
+39
View File
@@ -0,0 +1,39 @@
# Created: 2026-03-11
# Purpose: ignore generated artifacts for the `examples` repository
# Terraform
.terraform/
*.tfstate
*.tfstate.*
.terraform.lock.hcl
crash.log
# Terraform plans / backups
*.tfplan
*.backup
*.bak
# Provider plugins / caches
.terraform.d/
# Archives and build artifacts
*.zip
dist/
build/
# Node / Python
node_modules/
__pycache__/
*.pyc
venv/
.venv/
# Editor / OS files
.DS_Store
*.swp
*.swo
# Environment files
.env
*.local
*.log
+104 -76
View File
@@ -1,64 +1,119 @@
# Примеры sless # Примеры использования sless
## Что такое sless ## Обзор платформы
**sless**платформа для запуска serverless-функций в Kubernetes-кластере. **sless**система управления serverless-функциями на базе Kubernetes. Разработчик загружает код функции, платформа собирает из него Docker-образ, разворачивает его в кластере и предоставляет HTTP-эндпоинт для вызова. Всё описывается декларативно через Terraform.
Код на Python или Node.js загружается в платформу, которая собирает Docker-образ, деплоит его в кластер и публикует HTTP-эндпоинт. Всё управляется через Terraform. ### Основные ресурсы провайдера
### Ресурсы | Ресурс | Назначение |
| Ресурс | Что делает |
|---|---| |---|---|
| `sless_function` | Загружает код и собирает Docker-образ. Сама по себе не принимает запросы — нужен триггер или джоб | | `sless_function` | Описывает функцию: язык, точку входа, лимиты, переменные окружения. При создании загружает код и запускает его сборку в образ. Сама по себе недоступна снаружи — нужен триггер или задание. |
| `sless_trigger` | Публикует функцию — либо как HTTP-эндпоинт, либо по расписанию (cron) | | `sless_trigger` | Публикует функцию: тип `http` создаёт публичный URL, тип `cron` — запуск по расписанию. |
| `sless_job` | Запускает функцию один раз (например, для инициализации БД) и ждёт результата | | `sless_job` | Запускает функцию однократно и ожидает завершения. Используется для одноразовых операций: инициализация БД, миграции, пакетная обработка. |
**Типичный сценарий:** `sless_function` с кодом + `sless_trigger` с `type = "http"` → публичный URL вида `https://sless-api.kube5s.ru/fn/default/имя-функции`. Стандартная связка для HTTP API: `sless_function` + `sless_trigger` с `type = "http"` — в результате функция доступна по URL вида `https://sless-api.kube5s.ru/fn/<namespace>/<имя-функции>`.
--- ---
Примеры показывают различные сценарии использования serverless функций через Terraform провайдер `terra.k8c.ru/naeel/sless`.
## Требования ## Требования
- Terraform >= 1.0 - Terraform >= 1.0
- JWT-токен для аутентификации в sless API
- Доступ к `https://sless-api.kube5s.ru` - Доступ к `https://sless-api.kube5s.ru`
## Провайдер ## Конфигурация провайдера
Во всех примерах `main.tf` содержит: Во всех примерах файл `main.tf` содержит блок провайдера. Токен передаётся через переменную, значение которой задаётся в `terraform.tfvars`:
```hcl ```hcl
provider "sless" { provider "sless" {
endpoint = "https://sless-api.kube5s.ru" endpoint = "https://sless-api.kube5s.ru"
token = "dev-token-change-me" token = var.token
nubes_endpoint = "https://deck-api.ngcloud.ru/api/v1"
} }
``` ```
Namespace функций вычисляется автоматически из JWT-токена: `sless-{sha256[:8]}`.
--- ---
## Примеры ## Примеры
### `simple-python` — джоб передаёт результат в HTTP-функцию (Python) ### `hello-node` — минимальный пример на Node.js
При `apply` запускается джоб, его вывод передаётся в HTTP-функцию через `env_vars`. Две независимые функции: HTTP-функция, возвращающая приветствие, и одноразовое задание, суммирующее набор чисел. Хорошая отправная точка для знакомства с платформой.
```bash
cd hello-node
terraform init
terraform apply -auto-approve
# Вызов HTTP-функции с передачей имени:
curl -s -X POST https://sless-api.kube5s.ru/fn/<namespace>/hello-http \
-H 'Content-Type: application/json' -d '{"name":"World"}'
# Результат задания:
terraform output job_message
```
---
### `hello-go` — минимальный пример на Go 1.23
Аналог `hello-node`, но на Go. Демонстрирует поддержку Go-рантайма: HTTP-функция и одноразовое задание. Код пользователя оформляется как пакет `handler` с функцией `Handle(event)`.
```bash
cd hello-go
terraform init
terraform apply -auto-approve
terraform output job_message
terraform output trigger_url
```
---
### `pg-list-python` — выборка данных из PostgreSQL (Python)
Минимальный пример работы с базой данных: одна HTTP-функция читает список записей из таблицы PostgreSQL и возвращает их в JSON. Таблица с тестовыми данными создаётся автоматически при первом вызове. Нет заданий, нет инициализации — только функция и триггер.
**Переменные:**
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| `pg_dsn` | Строка подключения к PostgreSQL | `postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable` |
```bash
cd pg-list-python
terraform init
terraform apply -auto-approve
# URL функции выводится после применения:
terraform output catalog_url
# Запрос к функции:
curl -s $(terraform output -raw catalog_url)
```
---
### `simple-python` — одноразовое задание передаёт данные в HTTP-функцию (Python)
При `apply` выполняется задание, которое фиксирует текущее время. Результат передаётся в HTTP-функцию через переменные окружения и отображается при каждом запросе.
```bash ```bash
cd simple-python cd simple-python
terraform init terraform init
terraform apply -auto-approve terraform apply -auto-approve
# Что вернул джоб (время на момент деплоя):
terraform output job_result terraform output job_result
curl -s https://sless-api.kube5s.ru/fn/<namespace>/simple-py-time-display
# Проверить функцию:
curl -s https://sless-api.kube5s.ru/fn/default/simple-py-time-display
``` ```
--- ---
### `simple-node` — то же самое, но на Node.js 20 ### `simple-node` — то же самое на Node.js 20
```bash ```bash
cd simple-node cd simple-node
@@ -66,95 +121,68 @@ terraform init
terraform apply -auto-approve terraform apply -auto-approve
terraform output job_result terraform output job_result
curl -s https://sless-api.kube5s.ru/fn/default/simple-node-time-display curl -s https://sless-api.kube5s.ru/fn/<namespace>/simple-node-time-display
``` ```
--- ---
### `hello-node` — минимальный пример на Node.js ### `notes-python` — CRUD API на Python с PostgreSQL
Две независимые функции: HTTP-функция (возвращает приветствие) и одноразовый джоб (суммирует числа). Полноценное приложение: инициализация схемы базы данных через задания, CRUD-функция для работы с записями, отдельная функция для получения списка.
```bash
cd hello-node
terraform init
terraform apply -auto-approve
# Проверить HTTP-функцию:
curl -s -X POST https://sless-api.kube5s.ru/fn/default/hello-http \
-H 'Content-Type: application/json' -d '{"name":"World"}'
# Посмотреть результат джоба:
terraform output job_message
```
---
### `notes-python` — CRUD API на Python + PostgreSQL
Полноценное приложение: инициализация схемы БД через джобы, CRUD-функция, read-only функция для списка записей.
**Переменные:** **Переменные:**
| Переменная | Описание | Дефолт | | Переменная | Описание | Значение по умолчанию |
|---|---|---| |---|---|---|
| `pg_dsn` | DSN для подключения к PostgreSQL | `postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable` | | `pg_dsn` | Строка подключения к PostgreSQL | `postgres://sless:sless-pg-password@postgres.sless.svc.cluster.local:5432/sless?sslmode=disable` |
```bash ```bash
cd notes-python cd notes-python
terraform init terraform init
# Опционально — переопределить DSN:
# export TF_VAR_pg_dsn="postgres://user:pass@host:5432/db?sslmode=disable"
terraform apply -auto-approve terraform apply -auto-approve
# Проверить инициализацию БД: # Статус инициализации базы данных:
terraform output db_init_table_status terraform output db_init_table_status
terraform output db_init_index_status terraform output db_init_index_status
# URL функций:
terraform output notes_url # CRUD
terraform output notes_list_url # список всех записей
# Создать запись: # Создать запись:
curl -s -X POST "https://sless-api.kube5s.ru/fn/default/notes/add?title=Hello&body=World" curl -s -X POST "$(terraform output -raw notes_url)/add?title=Hello&body=World"
# Список записей: # Получить список записей:
curl -s https://sless-api.kube5s.ru/fn/default/notes-list curl -s $(terraform output -raw notes_list_url)
# Обновить (id из предыдущего ответа): # Обновить запись (id из предыдущего ответа):
curl -s -X POST "https://sless-api.kube5s.ru/fn/default/notes/update?id=1&title=Updated&body=New+body" curl -s -X POST "$(terraform output -raw notes_url)/update?id=1&title=Updated&body=New+body"
# Удалить: # Удалить запись:
curl -s -X POST "https://sless-api.kube5s.ru/fn/default/notes/delete?id=1" curl -s -X POST "$(terraform output -raw notes_url)/delete?id=1"
``` ```
--- ---
## Общие команды ## Полезные команды
```bash ```bash
# Посмотреть текущее состояние ресурсов: # Посмотреть текущее состояние задеплоенных ресурсов:
terraform show terraform show
# Пересоздать конкретный ресурс: # Принудительно пересобрать функцию (например, после изменения кода):
terraform apply -replace=sless_function.имя -auto-approve terraform apply -replace=sless_function.<имя> -auto-approve
# Повторно запустить джоб — увеличить run_id в .tf файле, затем: # Повторно запустить задание: увеличить значение run_id в .tf-файле, затем:
terraform apply -auto-approve terraform apply -auto-approve
# Удалить все ресурсы примера: # Удалить все ресурсы примера:
terraform destroy -auto-approve terraform destroy -auto-approve
``` ```
## Структура каждого примера ## Структура примера
``` ```
пример/ <пример>/
├── main.tf — провайдер ├── main.tf конфигурация провайдера
├── *.tf — ресурсы (функции, триггеры, джобы) ├── *.tf — ресурсы: функции, триггеры, задания
├── outputs.tf URLs и статусы после apply ├── variables.tf — входные переменные
├── variables.tf — входные переменные (если есть) ├── terraform.tfvars — значения переменных (не коммитится в git)
└── code/ — исходный код функций └── code/ — исходный код функций
``` ```
+14 -14
View File
@@ -2,28 +2,28 @@
# function.tf — HTTP-функция: читает из PostgreSQL и возвращает список записей. # function.tf — HTTP-функция: читает из PostgreSQL и возвращает список записей.
# Нет джобов, нет инициализации — только функция + HTTP триггер. # Нет джобов, нет инициализации — только функция + HTTP триггер.
resource "sless_function" "product_catalog" { resource "sless_function" "product_catalog" { # объявляем serverless-функцию; "product_catalog" — локальное имя в tf-state
name = "product-catalog" name = "product-catalog" # имя функции в кластере; по нему формируется URL и имя k8s-объекта
runtime = "python3.11" runtime = "python3.11" # базовый образ рантайма; определяет как собирается и запускается код
entrypoint = "catalog.list_products" entrypoint = "catalog.list_products" # файл.функция которую вызывает рантайм: catalog.py → def list_products(event)
memory_mb = 128 memory_mb = 128 # лимит памяти пода в мегабайтах
timeout_sec = 10 timeout_sec = 10 # максимальное время выполнения одного запроса в секундах
source_dir = "${path.module}/code" source_dir = "${path.module}/code" # директория с кодом функции; провайдер упакует её в zip и загрузит
# DSN передаётся через env — функция не знает об инфраструктуре # DSN передаётся через env — функция не знает об инфраструктуре
env_vars = { env_vars = {
PG_DSN = var.pg_dsn PG_DSN = var.pg_dsn # строка подключения к PostgreSQL; берётся из переменной (variables.tf)
} }
} }
resource "sless_trigger" "product_catalog_http" { resource "sless_trigger" "product_catalog_http" { # триггер публикует функцию наружу; без него функция существует, но недоступна
name = "product-catalog-http" name = "product-catalog-http" # имя триггера в кластере
type = "http" type = "http" # тип триггера: "http" создаёт публичный URL; альтернатива — "cron"
function = sless_function.product_catalog.name function = sless_function.product_catalog.name # ссылка на имя функции выше; terraform гарантирует порядок создания
enabled = true enabled = true # триггер активен сразу после создания
} }
output "catalog_url" { output "catalog_url" {
value = sless_trigger.product_catalog_http.url value = sless_trigger.product_catalog_http.url # URL вида https://sless-api.../fn/<namespace>/<name>; выводится после apply
} }