Collection of cookbooks for Podman Quadlets
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

76 lines
3.7 KiB

[Unit]
Description=vLLM model — %i (CPU smoke test)
Documentation=https://docs.vllm.ai/
# Only usable once the cookbook has been configured: this model's own engine config (models/%i.yaml, mounted below) must exist.
ConditionPathExists=/etc/quadlets/vllm/models/%i.yaml
ConditionPathExists=/etc/quadlets/vllm/models/%i.env
# IMPORTANT: model units are deliberately NOT started at boot and are NOT pulled
# in by vllm.target (no [Install], and the target does not Want/Require them).
# llmsnap owns their lifecycle: it runs `systemctl start/stop
# vllm-model@%i.service` on demand and its swap group keeps a single model
# running at a time (a GPU only fits one). `PartOf=` only makes the model stop
# when the target stops.
PartOf=vllm.target
# `Image=vllm.image` makes Quadlet add the dependency on vllm-image.service, so
# the image is pulled before the model starts.
[Container]
# One template serves every model: systemd expands %i to the instance name (e.g.
# `qwen05` for vllm-model@qwen05.service). The per-model differences live OUTSIDE
# this file:
# - engine parameters -> /etc/quadlets/vllm/models/%i.yaml (mounted below)
# - fixed loopback port -> COOKBOOK_VLLM_MODEL_PORT in models/%i.env, fed to
# vLLM's `--port` in Exec= below. This is a REAL API-server port (Network=host,
# so PublishPort does not apply and VLLM_PORT is NOT the API port).
ContainerName=vllm-%i
Image=vllm.image
AutoUpdate=local
# Hugging Face weights cache (re-downloadable, non-precious). Shared by all models.
Volume=/var/lib/quadlets/vllm/cache:/root/.cache/huggingface:z
Environment=VLLM_CPU_KVCACHE_SPACE=4
ShmSize=4g
# Host network: llmsnap must bind 127.0.0.1:8000 on the HOST (reached by Traefik,
# which runs Network=host) and reach each model on the host loopback
# (127.0.0.1:5801+, published by the model Quadlets). A bridged namespace would
# make 127.0.0.1 the container's own loopback, not the host's.
Network=host
# vLLM engine configuration (read-only). Every model parameter lives in this
# per-model file instead of on the command line; see config/examples/models/.
Volume=/etc/quadlets/vllm/models/%i.yaml:/etc/vllm/config.yaml:ro,Z
EnvironmentFile=/etc/quadlets/vllm/vllm.env
EnvironmentFile=/etc/quadlets/vllm/models/%i.env
# The CPU image ENTRYPOINT is `vllm serve`; these flags are appended to it. vLLM
# reads every engine parameter from the mounted config file; the API server bind
# address is the ONE thing kept on the command line because it is per-instance
# (host loopback + fixed port) and CLI args passed after --config win. systemd
# expands ${COOKBOOK_VLLM_MODEL_PORT} from models/%i.env (loaded into the service
# environment in [Service] below), exactly like Image=vllm.image expands
# COOKBOOK_VLLM_IMAGE. --host 127.0.0.1 keeps the API off external interfaces
# (Network=host); Traefik + API key is the only front door.
Exec=--config /etc/vllm/config.yaml --host 127.0.0.1 --port ${COOKBOOK_VLLM_MODEL_PORT}
# Readiness: vLLM serves /health once the engine is up.
HealthCmd=python3 -c "import urllib.request, os; port = os.environ.get('COOKBOOK_VLLM_MODEL_PORT'); urllib.request.urlopen(f'http://127.0.0.1:{port}/health')"
HealthInterval=30s
HealthTimeout=10s
HealthStartPeriod=600s
HealthRetries=3
[Service]
# vLLM cold start (weights download on first run + slow CPU load). llmsnap does
# its own HTTP health polling on top (healthCheckTimeout in config.yaml).
TimeoutStartSec=1800
# Load COOKBOOK_VLLM_IMAGE (for the Image=vllm.image indirection) and
# COOKBOOK_VLLM_MODEL_PORT (for the ${...} expansion in Exec=) into the SERVICE
# environment. systemd only expands variables it sees here; the [Container]
# EnvironmentFile= lines above feed the CONTAINER, not the unit's own expansion.
EnvironmentFile=/etc/quadlets/vllm/vllm.env
EnvironmentFile=/etc/quadlets/vllm/models/%i.env