docs: переработан examples/README.md + комментарии function.tf
This commit is contained in:
@@ -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
@@ -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/ — исходный код функций
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user