Operator kopii zapasowych & przywracania dla Kubernetes · Postgres 15–17 · PostGIS · MySQL 8.4
Trzymaj mocno każdą sekundę.
Tenax tworzy kopie zapasowe baz Postgres i MySQL działających w Kubernetes we własnym buckecie S3 i strumieniuje każdą zmianę na bieżąco. Wybierz sekundę w oknie i odzyskaj dokładnie tę bazę danych w piaskownicy, którą możesz odpytywać. Szyfrowane, zanim opuszczą klaster, zbudowane jako crash-only, więc nigdy się nie zawieszają.
Jeden plik binarny, jeden chart. Twój bucket, Twoje klucze.
- Przywróć do
- 2026-10-10 14:02:37 UTC
- Kopia bazowa
- 20261010T020712Z-4c1e
- Następnie odtwórz
- 114
$ tenax restore team/app --at 2026-10-10T14:02:37Z --wait
Zobacz, jak się cofa, albo sam przeciągnij po oknie. Pomarańczowe znaczniki to nocne pełne kopie zapasowe; cyjanowe pasmo to strumień zmian między nimi. Ilustracja polityki prod: nocne pełne kopie, okno 7 dni.
- 9sna przywrócenie bazy Postgres o rozmiarze 644 MiB do piaskownicy: pobranie, odszyfrowanie, odtworzenie i sprawdzenia
- 4.2×mniej w buckecie: fizyczna kopia zapasowa 683 MiB zapisana jako 161 MiB
- 72MiB/sprzepustowość logicznej pełnej kopii zapasowej na 4 vCPU, strumieniowo, bez plików tymczasowych
- 20msp99 przeglądu w konsoli przy 1000 baz danych i 100 000 kopii zapasowych
Zmierzone przez make test-perf i make test-ui w środowisku testowym k3d (4 vCPU, MinIO w klastrze). Liczby są w pliku docs/PERF.md w repozytorium.
01Jak to działapięć kroków
Od zmiany na żywo do piaskownicy, którą możesz odpytywać.
Bez agenta w bazie danych, bez snapshotów woluminów. Tenax czyta zmiany przez sieć, zabezpiecza je, zanim opuszczą pod, i przywraca dowolną sekundę, gdy o to poprosisz.
- 01
Strumieniowanie
Pełne kopie zapasowe według harmonogramu oraz każda zmiana na bieżąco: własny odbiornik WAL Tenax dla Postgres, mysqlbinlog dla MySQL.
WAL · binlog - 02
Szyfrowanie
Każdy bajt jest kompresowany przez zstd i szyfrowany przez age Twoimi kluczami publicznymi, wewnątrz poda, w jednym przebiegu strumieniowym bez plików tymczasowych.
zstd → age - 03
Zapis
Równoległe uploady multipart do dowolnego bucketu zgodnego z S3, SHA-256 dla każdego obiektu i manifest zapisywany jako ostatni.
*.zst.age · manifest.json - 04
Przywracanie co do sekundy
Podaj czas lub ID kopii zapasowej. Tenax wybiera kopię bazową i odtwarza zmiany aż do tej dokładnej sekundy.
--at 14:02:37 - 05
Otwarcie piaskownicy
Wynik trafia do prywatnej bazy danych z TTL i konsolą zapytań tylko do odczytu. Twoje sprawdzenia uruchamiają się, zanim przywracanie zostanie uznane za udane.
--ttl 6h
02Przywracaniecztery miejsca docelowe
Przywracaj gdziekolwiek, bez dotykania produkcji.
Przywracanie to zasób Kubernetes jak każdy inny. Podaj czas lub ID kopii zapasowej i wybierz, dokąd ma trafić. Tenax planuje kopię bazową i zmiany do odtworzenia, a potem uruchamia Twoje sprawdzenia, zanim uzna przywracanie za udane.
Tymczasowa kopia
Prywatna baza danych z TTL, danymi uwierzytelniającymi i konsolą zapytań tylko do odczytu. Sama po sobie sprząta.
--to sandbox --ttl 6hNowa baza danych
Przywrócona i sprawdzona w piaskownicy pośredniej, a potem skopiowana pod nową nazwę. Istniejące obiekty nigdy nie są nadpisywane.
--to new --database app_copyPrawdziwe wycofanie
Najpierw wykonuje kopię bezpieczeństwa i prosi o wpisanie nazwy celu. Wymaga roli restorer-admin.
--to in-place --confirm appPlik zrzutu
Odszyfrowany, skompresowany zrzut logiczny pod linkiem, który wygasa po godzinie. Rejestrowany w audycie.
--to download03Zobaczjedna minuta
Jedna minuta, od startu do przywrócenia.
Prawdziwe polecenia i prawdziwa konsola na katalogu demonstracyjnym: wyświetl wszystkie bazy danych, zobacz, co zmieniło się w nocy, i przywróć bazę do piaskownicy.
Konsola
Wiedz, co zmieniło się między dwiema wersjami.
Każda kopia zapasowa zawiera inwentarz swoich tabel, wierszy i rozmiarów. Każdy segment zmian zawiera podsumowanie tego, co zrobił. Zanim cokolwiek przywrócisz, widzisz więc, która wersja wciąż miała utracone wiersze.
- Porównania dowolnych dwóch kopii zapasowych. Zmiany schematu, liczba wierszy i rozmiar na tabelę.
- Podsumowania zmian dla każdego segmentu WAL lub binlogu. Wstawienia, aktualizacje, usunięcia i DDL na tabelę, więc TRUNCATE o 22:48 łatwo znaleźć.
- Zamaskowane podglądy. Przykładowe wiersze z zamaskowanymi wskazanymi kolumnami, czytelne kluczem katalogu, który nie może odszyfrować samych danych.
CLI
$ tenax targets TARGET ENGINE ORG/PROJECT/ENV LAST FULL PITR WINDOW STORED HEALTH analytics/events postgres acme/data/staging 2026-10-07 02:11:47Z - 19.1GiB ok auth/users postgres acme/platform/prod 2026-10-07 02:11:06Z 2026-09-23 02:11:06Z → 2026-10-07 18:50:52Z 1.5GiB ok billing/invoices mysql acme/billing/prod 2026-10-07 02:09:03Z 2026-09-23 02:09:03Z → 2026-10-07 18:50:52Z 6.7GiB ok billing/ledger postgres acme/billing/prod 2026-10-07 02:08:22Z 2026-09-23 02:08:22Z → 2026-10-07 18:50:52Z 14.3GiB ok maps/geo postgres acme/maps/prod 2026-10-07 02:10:25Z 2026-09-23 02:10:25Z → 2026-10-07 18:50:52Z 23.3GiB ok shop-dev/orders-db postgres acme/shop/dev 2026-10-07 02:12:28Z - 17.4MiB ok shop/catalog-db postgres acme/shop/prod 2026-10-07 02:07:41Z 2026-09-23 02:07:41Z → 2026-10-07 18:50:52Z 731.0MiB ok shop/orders-db postgres acme/shop/prod 2026-10-07 02:07:00Z 2026-09-23 02:07:00Z → 2026-10-07 18:50:52Z 9.6GiB ok web/wordpress mysql acme/marketing/prod 2026-10-07 02:09:44Z 2026-09-23 02:09:44Z → 2026-10-07 18:50:52Z 607.4MiB ok
$ tenax diff 20261006T020700Z-bd79 20261007T020700Z-6da5 from 20261006T020700Z-bd79 (2026-10-06 02:07:00Z) to 20261007T020700Z-6da5 (2026-10-07 02:07:00Z) 20261007 applied (was 20261006) column orders.gift_note added table audit_log +158,175 rows (+2%) table order_items +62,923 rows (+1%) table orders +15,655 rows (+1%) table coupons −3,120 rows (−100%) table customers +531 rows (+1%) 14 segments in between: 00000001000000A100000000 18:51:32–19:20:32 · 800 commits · audit_log +3348 / ~1116 / −83 · order_items +1327 / ~442 / −33 · orders +330 / ~110 / −8 · customers +11 / ~3 / −0 00000001000000A100000001 19:21:32–19:50:32 · 813 commits · audit_log +3352 / ~1116 / −83 · order_items +1328 / ~442 / −33 · orders +330 / ~110 / −8 · customers +13 / ~3 / −0 00000001000000A100000002 19:51:32–20:20:32 · 826 commits · audit_log +3356 / ~1116 / −83 · order_items +1329 / ~442 / −33 · orders +330 / ~110 / −8 · customers +15 / ~3 / −0
$ tenax restore shop/orders-db --at 20261006T020700Z-bd79 --ttl 6h --reason "coupons truncated" restore orders-db-sandbox-60414a15fc created (sandbox from 20261006T020700Z-bd79, 0 segments) restore shop/orders-db-sandbox-60414a15fc $ tenax sandbox list NAME ENGINE SOURCE OWNER PHASE EXPIRES IN-CLUSTER sbx-7f3a postgres shop/orders-db maria@acme.example Ready 2026-10-08 00:37:32Z tenax-sbx-sbx-7f3a.tenax-sandboxes.svc:5432 sbx-c210 mysql billing/invoices dev@acme.example Provisioning -
Wynik z serwera demonstracyjnego w repozytorium: go run ./hack/demo, a następnie skieruj na niego CLI lub przeglądarkę.
Konsola, CLI i API
Jedno API JSON opisane przez OpenAPI, z rolami z Cloudflare Access. Każdy zapis i każde zapytanie są rejestrowane w audycie.
Natywnie GitOps
Magazyny, polityki, cele i przywracania to CRD. Poziomy retencji, alerty i dashboard Grafana są dostarczane z chartem.
Zweryfikowane, nie wymarzone
Zaplanowane przywracania weryfikacyjne uruchamiają Twoje sprawdzenia SQL na prawdziwym przywróceniu i oznaczają kopię zapasową jako zweryfikowaną. Ich czas przywracania jest eksportowany jako metryka.
04Niezawodnośćcrash-only
Nigdy się nie zawiesza. Nie robi sobie nic z kill -9.
Kopie zapasowe zawodzą nocą w nudny sposób: zawieszony mount, martwy pod, do połowy zapisany plik. Tenax jest zbudowany tak, by żadne z nich nie mogło go zablokować ani udawać kopii zapasowej.
- data/part-00001.zst.age
- data/part-00002.zst.age
- data/part-00003.zst.age
- manifest.json
- data/part-00001.zst.age
- data/part-00002.zst.age
- data/part-00003.zst.age
- manifest.json
Nigdy się nie zawiesza
Bez montowań i urządzeń blokowych; bazy danych tylko przez sieć. Każdy strumień ma watchdog postępu, a każde narzędzie działa we własnej grupie procesów.
Crash-only
Zabij dowolny pod w dowolnej chwili. Kopia zapasowa istnieje dopiero wtedy, gdy jej manifest zostanie zapisany jako ostatni, a zestaw testów chaos zabija Tenax w trakcie kopii, by to udowodnić.
Dane przenoszą Joby, nigdy kontroler.
Kontroler tylko planuje. Movery i streamery przenoszą bajty jednym potokiem strumieniowym prosto do Twojego bucketu, a restorer je przywraca.
Delikatny dla produkcji
Jeden użytkownik bazy danych z minimalnymi uprawnieniami, który nigdy nie zapisuje. Sloty na host, limity przepustowości i ochrona obciążenia, która odkłada kopię, gdy serwer jest zajęty.
Strumieniowanie zmian
Własny odbiornik WAL Tenax na slocie replikacji dla Postgres i mysqlbinlog dla MySQL. Okno sięga teraźniejszości, nawet przy mało aktywnej bazie danych.
Szybki z założenia
Potoki strumieniowe bez plików tymczasowych, równoległe uploady multipart, wielowątkowy zstd i katalog w pamięci za konsolą, która odpowiada w milisekundach.
Tak lekki, że zapomnisz, że tam jest.
Tenax to jeden plik binarny w Go. Kontroler i API tylko planują i czytają; bajty przenoszą krótkotrwałe Joby, które kończą się po wykonaniu pracy, więc między kopiami zapasowymi w klastrze nie zostaje nic ciężkiego.
Working set zgłaszany przez kubelet w testowym klastrze k3d (12 baz danych) po zestawach testów end-to-end i chaos; CPU w spoczynku to kilka milirdzeni. Każda baza danych z odtwarzaniem point-in-time uruchamia też streamer, około 70 MiB podczas strumieniowania.
05Bezpieczeństwoszyfrowane u źródła
Twój bucket widzi wyłącznie szyfrogram.
Szyfrowanie odbywa się w podzie, przed wysłaniem, kluczami, których Tenax nie posiada. Dostęp jest podzielony na role, a każdy zapis i każde zapytanie zostawiają wpis w audycie.
$ head -c 200 data/part-00001.zst.age age-encryption.org/v1 -> X25519 Qm9yZWQ/IE5vdGhpbmcgdG8gc2VlIGhlcmUu… --- 7Hc1kS0zR2QeYc… ÌÞ#ø§ñ¹t¤¢Ý}ϰë։ÿ]Wœ3Ð÷…
Każdy obiekt danych to plik age zaszyfrowany dla Twoich odbiorców (X25519). Tylko manifest jest zwykłym JSON i nie zawiera sekretów.
Szyfrowane przed wysłaniem
Każdy obiekt jest szyfrowany po stronie klienta przez age Twoimi kluczami. Bucket nigdy nie widzi tekstu jawnego, a klucz katalogu konsoli nie może czytać danych.
Klucz katalogu, który nie może czytać danych
Konsola czyta inwentarze i zamaskowane podglądy osobną tożsamością katalogu. Nie może odszyfrować zrzutów, kopii bazowych, WAL ani binlogów.
Sprawdzane od początku do końca
Manifest zawiera SHA-256 każdego zapisanego obiektu, sprawdzane na końcu każdego odczytu, i sam jest zapisywany jako ostatni warunkowym PUT.
Sekrety poza zasięgiem wzroku
Dane uwierzytelniające baz danych trafiają do narzędzi potomnych przez zapieczętowane pliki w pamięci, nigdy przez argv ani środowisko. Logi redagują wszystko, co wygląda na sekret.
Role i ślad audytowy
Logowanie przez Cloudflare Access i cztery role, od viewer do restorer-admin. Przywracanie w miejscu wymaga najwyższej roli i wpisanego potwierdzenia.
Zabezpieczone pody
Bez roota, główny system plików tylko do odczytu, wszystkie capabilities odrzucone, seccomp RuntimeDefault. Pody ścieżki danych montują tylko emptyDir.
06Porównaniez zadaniem cron
Więcej niż nocny zrzut w buckecie.
| Gdy musisz… | skrypt cron + pg_dump | Tenax |
|---|---|---|
| Wrócić do 09:41:27 | Zrzut z ostatniej nocy, do 24 h straty | Dowolna sekunda w oknie |
| Udowodnić, że kopia się przywraca | Dowiedzieć się w trakcie incydentu | Zaplanowane przywracania weryfikacyjne z Twoimi sprawdzeniami |
| Znaleźć wersję z brakującymi wierszami | Przywrócić kilka i porównać | Porównania i podsumowania zmian w konsoli |
| Zajrzeć bez ryzyka | Przywrócić na współdzieloną bazę stagingową | Prywatna piaskownica z TTL |
| Trzymać bucket w niewiedzy | Szyfrowanie po stronie serwera, jeśli skonfigurowane | Szyfrowanie age po stronie klienta Twoimi kluczami |
| Przetrwać awarię węzła w trakcie kopii | Do połowy zapisany plik, który wygląda na kompletny | Nic się nie liczy, dopóki manifest nie zostanie zapisany jako ostatni |
| Wiedzieć, że wciąż działa | Cisza | Alerty o zaległych kopiach, przerwanych łańcuchach i opóźnieniu |
07Instalacjaokoło dziesięciu minut
Od zera do możliwości przywracania.
Zainstaluj chart
CRD, kontroler, API i konsola, RBAC, alerty i dashboard.
helm install tenax charts/tenax -n tenax-system --create-namespace \ --set image.repository=registry.example.com/tenax/tenax --set image.tag=v0.1.0 \ --set 'targetNamespaces={team-a}'Wskaż bucket i swoje klucze
Dowolny magazyn zgodny z S3. Wygeneruj klucz age przez age-keygen i zachowaj kopię offline.
apiVersion: tenax.run/v1alpha1 kind: BackupStore metadata: { name: main } spec: s3: endpoint: https://s3.example.com region: us-east-1 bucket: db-backups credentialsSecret: { namespace: tenax-system, name: tenax-s3 } encryption: ageRecipients: [age1…] # tylko klucz publiczny; klucz prywatny pozostaje offline
Zadeklaruj cel obok bazy danych
Utwórz użytkownika bazy danych tenax za pomocą SQL z docs/sql/, a następnie zatwierdź cel w git.
apiVersion: tenax.run/v1alpha1 kind: BackupTarget metadata: { name: app, namespace: team-a } spec: engine: postgres endpoint: { host: postgres, port: 5432 } databases: [app] policy: prod # nocne pełne kopie, 7-dniowe okno point-in-time credentials: secretRef: { name: tenax-postgres }
Przywróć coś, celowo
Pierwsza pełna kopia zapasowa uruchamia się sama. Potem wypróbuj to, czego masz nadzieję nigdy nie potrzebować.
tenax targets tenax restore team-a/app --at 2026-10-07T09:41:27Z --wait tenax query <sandbox> -e "select count(*) from orders"
Pełny przewodnik, każde pole CRD i REST API znajdziesz w dokumentacji.
08FAQkonkretne odpowiedzi
O co inżynierowie pytają najpierw.
Jakie bazy danych obsługuje Tenax?
Postgres 15, 16 i 17, w tym PostGIS, z fizycznymi lub logicznymi pełnymi kopiami zapasowymi i strumieniowaniem WAL. MySQL 8.4 z logicznymi pełnymi kopiami zapasowymi i strumieniowaniem binlogu.
Jak daleko wstecz i jak precyzyjnie mogę przywracać?
Każdą pełną kopię zapasową zachowaną przez Twoje poziomy retencji i każdą sekundę w oknie point-in-time ustawionym przez politykę. Przykładowa polityka prod utrzymuje okno 7 dni oraz 14 dziennych, 8 tygodniowych, 12 miesięcznych i 5 rocznych pełnych kopii.
Czy Tenax lub mój dostawca storage może czytać moje dane?
Bucket nie może: każdy obiekt jest szyfrowany przez age dla Twoich odbiorców przed wysłaniem. Konsola czyta inwentarze kluczem katalogu, który nie może odszyfrować samych danych. Przywracanie odszyfrowuje tożsamością age, którą dostarczasz, więc przechowuj jej kopię offline.
Co się stanie, jeśli pod zginie w trakcie kopii zapasowej?
Nic, co by się liczyło. Kopia zapasowa istnieje dopiero wtedy, gdy jej manifest zostanie zapisany, po wysłaniu i zsumowaniu kontrolnym każdego obiektu. Niedokończone uruchomienie nie ma manifestu, więc nigdy nie jest oferowane do przywrócenia. Zestaw testów chaos zabija Tenax w trakcie kopii, by to udowodnić.
Czy Tenax montuje woluminy lub używa snapshotów?
Nie. Łączy się z bazami danych tylko przez sieć, a jego pody nie montują niczego poza emptyDir: bez hostPath, FUSE, iSCSI czy urządzeń blokowych i domyślnie bez PVC. Zawieszony sterownik storage nie może zablokować kopii zapasowej.
Czego Tenax potrzebuje od mojej bazy danych?
Jednego użytkownika tenax z minimalnymi uprawnieniami na bazę danych, który nigdy nie zapisuje, utworzonego za pomocą SQL z docs/sql/. Bez uprawnień replikacji Tenax nadal wykonuje logiczne kopie zapasowe i podpowiada, co nadać, aby przywracać do dowolnej sekundy.
Czy Tenax jest open source?
Jest source-available na licencji The Republic Lex Aequa License 1.0. Każdy może go bezpłatnie używać, modyfikować i redystrybuować, także produkcyjnie w firmach komercyjnych, aby chronić własne dane. Sprzedaż lub hosting jako usługi dla osób trzecich są zastrzeżone.