Курс по Kubernetes с kind — разгърни, настрой, мащабирай и защити услуга на собствената си машина

Контейнери и облакСредно ниво

Преди този курс: Docker

От · основател и главен изпълнителен директор на Hábil. Така обучаваме тези, които изграждат системи, които не могат да се провалят.

За кого е: за този, който вече е минал курса по Docker от същата поредица, или който пакетира услуги в контейнери с лекота: изграждаш образи, пускаш ги, даваш им томове и ги стартираш заедно с Compose. Средно ниво. Не се предполага да си пипал Kubernetes, нито да имаш клъстер: курсът ти дава един, локален, който се създава и се унищожава за минути. Всяко понятие се обяснява, когато се появи, и се обяснява защо съществува, а не само как се пише.

Какво ще знаеш в края: да разгърнеш услуга в клъстер на Kubernetes и да я управляваш —да я конфигурираш, да я наблюдаваш, да я публикуваш, да я ограничаваш, да ѝ пазиш данните, да я мащабираш и да я обновяваш, като измерваш всяко прекъсване—; да четеш какво ти казва клъстерът, когато нещо се провали (Pending, ImagePullBackOff, CrashLoopBackOff), вместо да триеш и да опитваш пак; и да обясниш, без украси, какво е разстоянието между твоя локален клъстер и един продукционен.

Откъде идва: този курс продължава този по Docker от същата поредица и използва като отправна точка неговия завършен образ на revisor. Ако не си минал онзи курс, ти трябва образ на HTTP услуга, която умее да казва дали е жива и която работи без да е root; Урок 2 ти казва точно на какво трябва да отговаря.

Какво ти трябва, преди да започнеш: компютър с Linux Mint 22.x, работещ Docker Engine и администраторски права (sudo). Урок 1 инсталира kubectl и kind и създава клъстера.

Проектът, който ще изградиш

revisor: HTTP сървърът, който проверява едновременно списък от услуги и връща своя отчет, същият като в курсовете по Go, Rust, TypeScript и Docker от същата поредица; неговият сървър е написан на Go и слуша на порт 8080 (GET /salud, GET /api/estados, конфигурация чрез променливи на средата, подкоманда healthcheck). Тук вече не го програмираш и не го пакетираш: караш го да живее в клъстер. Разгръщаш го с няколко реплики, правиш го откриваем по име, конфигурираш го без да изграждаш образа наново, учиш клъстера да го наблюдава, публикуваш го навън, изолираш го с минимални права и затворена мрежа, даваш му място, където да пази отчета си, превръщаш го в планирана задача и го караш да се мащабира според натоварването. В края всичко се разгръща с два kubectl apply -k —платформата и проекта— и изчакване между тях.

Придружен е от тестовата услуга, която се проваля нарочно от курса по Docker (здрава, бавна или паднала), защото един клъстер се разбира наистина, когато нещо се счупи и видиш какво прави.

Единайсетте урока

Урок Какво изграждаш Какво научаваш
0 Какво е Kubernetes и какво НЕ е kind засега нищо (четене) контролната равнина и възлите; да декларираш желаното състояние и да оставиш клъстера да го достигне; картата от Docker към Kubernetes; какво може да се тества с kind и какво не
1 Инсталиране на kubectl и kind; първият ти клъстер клъстерът на курса: един контролен възел и два работни kubectl и kind с фиксирана версия и контролна сума; настройката на inotify; контексти и kubeconfig; създаване, разглеждане, изтриване и пресъздаване
2 Pods и Deployments работещият revisor, с реплики, които се раждат наново kind load docker-image; ErrImagePull, който се предизвиква нарочно; Pod, ReplicaSet и Deployment; етикети; rollout; securityContext от първия манифест
3 Services и DNS revisor, откриваем по име ClusterIP; селектори и EndpointSlice; port, targetPort и containerPort; DNS на клъстера; port-forward; един Pod за отстраняване на грешки
4 Конфигурация и тайни revisor, конфигуриран без повторно изграждане ConfigMap като променливи на средата (revisor чете само променливи) и Secret като файл, и защо base64 не е шифроване; Kustomize с генератори и хешът (hash), който задейства rollout
5 Проверки на състоянието, ресурси и подредено изключване revisor, който клъстерът умее да наблюдава проби (probes) за стартиране (startup), готовност (readiness) и жизненост (liveness); защо /salud не пита никого; requests и limits; OOMKilled и Pending нарочно; срокът за изключване
6 Влизане в клъстера revisor, публикуван навън LoadBalancer с MetalLB и Gateway API с Envoy Gateway, инсталирани вътре в клъстера; защо не Cloud Provider KIND на споделена машина (действа върху всички клъстери на kind); Ingress като замразен API; защо не ingress-nginx; какво се излага и откъде
7 Изолиране: пространства, права и мрежа собствено пространство от имена с правила Namespace; Pod Security Admission на ниво restricted; ServiceAccount и минимален RBAC с auth can-i; NetworkPolicy „всичко затворено“ и нейните отваряния (измерва се, че kindnet, CNI на kind, ги прилага; не е нужно да се инсталира друг)
8 Данни и задачи запазеният отчет и revisor като планирана задача PersistentVolumeClaim и класът за съхранение на kind; Job и CronJob; собственикът на файловете с fsGroup; какво се губи при изтриване на Pod
9 Мащабиране и обновяване с измерване на всяко прекъсване revisor, който вдига и сваля реплики според натоварването metrics-server; HorizontalPodAutoscaler и неговата формула; прозорецът за сваляне; разпределение с topologySpreadConstraints; RollingUpdate и preStop, измерени със сондиране; rollout undo; PodDisruptionBudget и drain; прозорецът на паднал възел
10 Завършеният проект и какво се променя в истински клъстер всичко с два kubectl apply -k (платформа и проект) и изчакване Kustomize с база и слоеве (overlays); преглед спрямо нивото restricted; Helm, само споменат; какво не му достига на това, за да бъде продукция

В края на всеки урок има упражнения с решенията им. А дневникът е твой: записвай в него какво ти е струвало усилия.

Три принципа, които минават през целия курс

Сигурността не е урок, а навик. Урок 7 събира права, пространства и мрежа, защото там те се изучават сами по себе си, но останалата част от курса ги прилага на практика още от първия манифест:

Урок Навикът, който се изгражда
0 да знаеш какво защитава един локален клъстер и какво не
1 двоични файлове с контролна сума; фиксиран образ на възела; проверка на контекста преди всяка команда, която променя нещо
2 securityContext в първия Deployment: без root, без повишаване на привилегии, без правомощия (capabilities), файлова система само за четене, профил seccomp
3 по подразбиране ClusterIP; нищо не се публикува просто така; port-forward само към 127.0.0.1
4 един Secret не е шифроване: не се версионира, монтира се като файл и се отбелязва като неизменяем
5 requests и limits във всеки контейнер; пробите (probes) не зависят от външни услуги
6 излага се минимумът, през именувана входна точка, и се казва какво липсва (шифроване при пренос)
7 собствено пространство, ниво restricted, минимални права, затворена по подразбиране мрежа
8 ServiceAccount без монтирани удостоверения, ако не се нуждае от тях; данните със своя собственик
9 граници при мащабирането; обновяванията поддържат услугата работеща, като малкото откази са измерени и обяснени
10 финален преглед спрямо нивото restricted и списъка с онова, което един истински клъстер изисква

Чете се, преди да се трие. Когато нещо не стартира, рефлексът на начинаещия е да го изтрие и да го приложи отново. Тук рефлексът е друг: describe, logs, get events. Всеки урок нарочно предизвиква типичен срив и те учи на реда, по който се чете, защото този ред е занаятът.

Преподава се само актуалното, а онова, което е премахнато, се назовава, за да го разпознаеш. Поддръжката на ingress-nginx беше прекратена през март 2026 г., а уроците отпреди две години все още го преподават; Ingress е замразен API, а Gateway API е неговият наследник. Курсът казва кое какво е. И всяка версия се дава с датата ѝ: тези в този курс са измерени на 7 октомври 2026 г. (Kubernetes 1.37.1; kind v0.33.0, чийто възел по подразбиране е 1.37.0). Онова, което зависи от външна част (MetalLB, Envoy Gateway, прилагането на NetworkPolicy, metrics-server в kind), се проверява на живо при писането на всеки урок и не се твърди предварително.

Как разбираш, че си приключил

Курсът не свършва, когато си прочел урок 10, а когато проектът ти изпълнява тези седем неща. Те са проектни цели: измерват се и се прецизират при писането на уроците, а всеки урок повтаря своята вече измерена.

  1. В току-що създаден клъстер revisor заработва с три стъпки, винаги в един и същ ред: kubectl apply -k за платформата (MetalLB и Envoy Gateway, с техните CRD), kubectl wait, докато тя е готова, и kubectl apply -k на проекта. Редът има значение, защото CRD и webhook-ите трябва да съществуват преди ресурсите, които ги използват. А kind delete cluster, последван от същите три стъпки, го изгражда наново, без да поправяш нищо ръчно.
  2. Пространството от имена на revisor е на ниво restricted на Pod Security Admission и не получава нито едно предупреждение при прилагане.
  3. Спираш контейнера на един работен възел (docker stop) и услугата продължава да отговаря чрез репликата на другия възел, с измерен прозорец: в продължение на десетки секунди —времето, за което клъстерът обявява възела за изгубен (node-monitor-grace-period, 50 s по подразбиране): в четирите кръга на урок 10 услугата отговори отново от 34 до 51 s след спирането на възела, а в урок 9 възелът премина в NotReady на 57-ата секунда— заявките, които попаднат на мъртвата реплика, се провалят (измерено в един кръг, с 2 реплики: 7 от 42 заявки се провалиха, а последният срив беше 53 s след спирането). Можеш да кажеш какво скъсява или смекчава този прозорец (повече разпределени реплики, повторни опити в клиента, по-кратък срок за откриване в контролната равнина) и какво не (пробите, които се изпълняват от самия паднал възел, нито tolerationSeconds, който решава само кога се заменят Pod-овете). А обновяване с preStop намалява прекъсванията, но не гарантира нула: в четири кръга измери 0, 4, 0 и 1 неуспеха, общо 5 от 2 049 заявки, срещу 29 от 1 569 без preStop в три кръга (измерено отвътре на клъстера, през Service и kube-proxy, не през входната врата; с четири нишки curl на споделена машина и без редуване на кръговете). Когато стартираш възела отново, клъстерът се възстановява сам.
  4. Променяш списъка с услуги в ConfigMap и клъстерът извършва rollout сам, без да изграждаш образа наново.
  5. Под натоварване kubectl get hpa --watch показва как репликите се покачват, а минути по-късно спадат, и можеш да обясниш защо спадането отнема толкова време, колкото отнема.
  6. Външен за revisor Pod не може да говори с него (NetworkPolicy го спира; цел, която зависи от това клъстерът да я прилага) и сервизният акаунт на revisor не може да прави нищо, от което не се нуждае (kubectl auth can-i ти го доказва).
  7. Можеш да изброиш писмено пет причини, поради които онова, което си изградил, не е продукция, и какво би се направило за всяка от тях в един истински клъстер.

Уроци

  1. Урок 0 — Какво е Kubernetes и какво НЕ е kind
  2. Урок 1 — Инсталиране на kubectl и kind; първият ти клъстер
  3. Урок 2 — Pods и Deployments
  4. Урок 3 — Services и DNS
  5. Урок 4 — Конфигурация и тайни
  6. Урок 5 — Проверки на състоянието, ресурси и подредено изключване
  7. Урок 6 — Влизане в клъстера
  8. Урок 7 — Изолиране: пространства, права и мрежа
  9. Урок 8 — Данни и задачи
  10. Урок 9 — Мащабиране и обновяване с измерване на всяко прекъсване
  11. Урок 10 — Завършеният проект и какво се променя в истински клъстер