[{"data":1,"prerenderedAt":3975},["ShallowReactive",2],{"content:\u002F07-infrastructure\u002F03-k8s-overview":3},{"title":4,"description":5,"path":6,"body":7},"Kubernetes — обзор и архитектура","Kubernetes (K8s) — система автоматизации деплоя и управления контейнеризированными приложениями на кластере машин. Если Docker решает проблему \"как запустить приложение в контейнере\", то Kubernetes решает другую — \"как управлять тысячами контейнеров на десятках серверов\". Проект вырос из внутренних систем Google (Borg\u002FOmega), где обрабатывалось более 2 миллиардов контейнеров в неделю, и стал open source в 2014 году.","\u002F07-infrastructure\u002F03-k8s-overview",{"type":8,"value":9,"toc":3927},"minimark",[10,14,17,25,28,33,36,90,93,177,182,190,192,196,200,211,215,218,222,225,455,458,474,476,480,495,503,506,509,515,520,523,540,543,550,564,568,571,594,598,601,604,658,661,664,670,674,677,691,695,698,718,721,724,738,740,744,747,753,756,758,762,766,772,810,813,815,819,822,897,901,904,1133,1156,1159,1163,1169,1221,1225,1228,1307,1314,1317,1370,1374,1385,1440,1442,1446,1449,1453,1551,1555,1620,1624,1667,1671,1768,1770,1774,1778,1781,1848,1850,1854,1858,1872,1875,1886,1888,1892,1896,1913,1917,1934,1936,1940,1944,1947,1997,2008,2012,2015,2019,2022,2024,2028,2031,2405,2408,2870,2997,2999,3003,3008,3011,3016,3025,3030,3033,3038,3045,3050,3056,3061,3064,3069,3072,3074,3078,3082,3088,3094,3100,3344,3349,3360,3364,3368,3373,3382,3386,3423,3426,3430,3434,3439,3447,3451,3454,3522,3525,3527,3531,3561,3757,3923],[11,12,4],"h1",{"id":13},"kubernetes-обзор-и-архитектура",[15,16,5],"p",{},[15,18,19,20,24],{},"Аналогия: операционная система управляет процессами на одной машине, Kubernetes управляет контейнерами на множестве машин. Ты выступаешь в роли капитана — решаешь ",[21,22,23],"strong",{},"куда"," плыть. K8s выступает рулевым — ведёт корабль по курсу и докладывает обстановку.",[26,27],"hr",{},[29,30,32],"h2",{"id":31},"зачем-нужен-kubernetes","Зачем нужен Kubernetes",[15,34,35],{},"В мире монолитов ручное управление допустимо: одно приложение, один деплой, один сервер. С переходом на микросервисы (десятки и сотни отдельных сервисов) ручной менеджмент становится невозможным.",[37,38,39,55],"table",{},[40,41,42],"thead",{},[43,44,45,49,52],"tr",{},[46,47,48],"th",{},"Аспект",[46,50,51],{},"Монолит",[46,53,54],{},"Микросервисы",[56,57,58,70,79],"tbody",{},[43,59,60,64,67],{},[61,62,63],"td",{},"Приложений",[61,65,66],{},"1",[61,68,69],{},"100+",[43,71,72,75,77],{},[61,73,74],{},"Деплоев",[61,76,66],{},[61,78,69],{},[43,80,81,84,87],{},[61,82,83],{},"Ручное управление",[61,85,86],{},"допустимо",[61,88,89],{},"невозможно",[15,91,92],{},"Kubernetes автоматизирует то, что невозможно делать руками:",[37,94,95,105],{},[40,96,97],{},[43,98,99,102],{},[46,100,101],{},"Возможность",[46,103,104],{},"Описание",[56,106,107,117,127,137,147,157,167],{},[43,108,109,114],{},[61,110,111],{},[21,112,113],{},"Service discovery",[61,115,116],{},"Приложения находят друг друга по имени, без хардкода адресов",[43,118,119,124],{},[61,120,121],{},[21,122,123],{},"Horizontal scaling",[61,125,126],{},"Автоматическое масштабирование по нагрузке (HPA)",[43,128,129,134],{},[61,130,131],{},[21,132,133],{},"Load balancing",[61,135,136],{},"Распределение трафика между репликами",[43,138,139,144],{},[61,140,141],{},[21,142,143],{},"Self-healing",[61,145,146],{},"Перезапуск упавших контейнеров, перенос с упавших нод",[43,148,149,154],{},[61,150,151],{},[21,152,153],{},"Leader election",[61,155,156],{},"Встроенный механизм выбора лидера для stateful-сервисов",[43,158,159,164],{},[61,160,161],{},[21,162,163],{},"Rolling updates",[61,165,166],{},"Обновление приложений без downtime",[43,168,169,174],{},[61,170,171],{},[21,172,173],{},"Config management",[61,175,176],{},"ConfigMaps и Secrets для внешней конфигурации",[178,179,181],"h3",{"id":180},"стандартизация-облака","Стандартизация облака",[15,183,184,185,189],{},"Без Kubernetes: AWS API отличается от GCP API и от Azure API. Миграция между облаками означает переписывание всего деплоя. С Kubernetes: ",[186,187,188],"code",{},"kubectl apply -f app.yaml"," работает одинаково на AWS, GCP, Azure и on-prem. Kubernetes API — единый стандарт деплоя, который устраняет vendor lock-in.",[26,191],{},[29,193,195],{"id":194},"модель-управления-кластером","Модель управления кластером",[178,197,199],{"id":198},"декларативная-модель-desired-state-vs-current-state","Декларативная модель: desired state vs current state",[15,201,202,203,206,207,210],{},"Главный принцип Kubernetes — декларативность. Ты не говоришь системе ",[21,204,205],{},"как"," сделать, ты описываешь ",[21,208,209],{},"что"," хочешь получить.",[178,212,214],{"id":213},"императивный-подход-без-k8s","Императивный подход (без K8s)",[15,216,217],{},"\"Запусти 3 инстанса на сервере A, 2 на сервере B, настрой балансировщик на порту 80, подключи к нему все пять инстансов...\" — ты управляешь каждым шагом.",[178,219,221],{"id":220},"декларативный-подход-k8s","Декларативный подход (K8s)",[15,223,224],{},"\"Хочу 5 инстансов моего приложения, порт 8080, 256MB RAM на каждый\" — ты описываешь желаемое состояние (desired state), а Kubernetes решает, как его достичь и поддерживать.",[226,227,232],"pre",{"className":228,"code":229,"language":230,"meta":231,"style":231},"language-yaml shiki shiki-themes github-dark","apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: my-app\nspec:\n  replicas: 5        # хочу 5 инстансов\n  selector:\n    matchLabels:\n      app: my-app\n  template:\n    metadata:\n      labels:\n        app: my-app\n    spec:\n      containers:\n      - name: my-app\n        image: my-app:1.0\n        ports:\n        - containerPort: 8080\n        resources:\n          requests:\n            memory: \"256Mi\"\n","yaml","",[186,233,234,251,262,271,282,290,306,314,322,332,340,348,356,366,374,382,395,406,414,428,436,444],{"__ignoreMap":231},[235,236,239,243,247],"span",{"class":237,"line":238},"line",1,[235,240,242],{"class":241},"s4JwU","apiVersion",[235,244,246],{"class":245},"s95oV",": ",[235,248,250],{"class":249},"sU2Wk","apps\u002Fv1\n",[235,252,254,257,259],{"class":237,"line":253},2,[235,255,256],{"class":241},"kind",[235,258,246],{"class":245},[235,260,261],{"class":249},"Deployment\n",[235,263,265,268],{"class":237,"line":264},3,[235,266,267],{"class":241},"metadata",[235,269,270],{"class":245},":\n",[235,272,274,277,279],{"class":237,"line":273},4,[235,275,276],{"class":241},"  name",[235,278,246],{"class":245},[235,280,281],{"class":249},"my-app\n",[235,283,285,288],{"class":237,"line":284},5,[235,286,287],{"class":241},"spec",[235,289,270],{"class":245},[235,291,293,296,298,302],{"class":237,"line":292},6,[235,294,295],{"class":241},"  replicas",[235,297,246],{"class":245},[235,299,301],{"class":300},"sDLfK","5",[235,303,305],{"class":304},"sAwPA","        # хочу 5 инстансов\n",[235,307,309,312],{"class":237,"line":308},7,[235,310,311],{"class":241},"  selector",[235,313,270],{"class":245},[235,315,317,320],{"class":237,"line":316},8,[235,318,319],{"class":241},"    matchLabels",[235,321,270],{"class":245},[235,323,325,328,330],{"class":237,"line":324},9,[235,326,327],{"class":241},"      app",[235,329,246],{"class":245},[235,331,281],{"class":249},[235,333,335,338],{"class":237,"line":334},10,[235,336,337],{"class":241},"  template",[235,339,270],{"class":245},[235,341,343,346],{"class":237,"line":342},11,[235,344,345],{"class":241},"    metadata",[235,347,270],{"class":245},[235,349,351,354],{"class":237,"line":350},12,[235,352,353],{"class":241},"      labels",[235,355,270],{"class":245},[235,357,359,362,364],{"class":237,"line":358},13,[235,360,361],{"class":241},"        app",[235,363,246],{"class":245},[235,365,281],{"class":249},[235,367,369,372],{"class":237,"line":368},14,[235,370,371],{"class":241},"    spec",[235,373,270],{"class":245},[235,375,377,380],{"class":237,"line":376},15,[235,378,379],{"class":241},"      containers",[235,381,270],{"class":245},[235,383,385,388,391,393],{"class":237,"line":384},16,[235,386,387],{"class":245},"      - ",[235,389,390],{"class":241},"name",[235,392,246],{"class":245},[235,394,281],{"class":249},[235,396,398,401,403],{"class":237,"line":397},17,[235,399,400],{"class":241},"        image",[235,402,246],{"class":245},[235,404,405],{"class":249},"my-app:1.0\n",[235,407,409,412],{"class":237,"line":408},18,[235,410,411],{"class":241},"        ports",[235,413,270],{"class":245},[235,415,417,420,423,425],{"class":237,"line":416},19,[235,418,419],{"class":245},"        - ",[235,421,422],{"class":241},"containerPort",[235,424,246],{"class":245},[235,426,427],{"class":300},"8080\n",[235,429,431,434],{"class":237,"line":430},20,[235,432,433],{"class":241},"        resources",[235,435,270],{"class":245},[235,437,439,442],{"class":237,"line":438},21,[235,440,441],{"class":241},"          requests",[235,443,270],{"class":245},[235,445,447,450,452],{"class":237,"line":446},22,[235,448,449],{"class":241},"            memory",[235,451,246],{"class":245},[235,453,454],{"class":249},"\"256Mi\"\n",[15,456,457],{},"Изменил описание — K8s приводит систему к новому состоянию:",[459,460,461,465,468,471],"ul",{},[462,463,464],"li",{},"Добавил реплику (replicas: 6) — K8s запустит ещё один pod",[462,466,467],{},"Убрал компонент — K8s остановит его",[462,469,470],{},"Приложение упало — K8s перезапустит",[462,472,473],{},"Нода вышла из строя — K8s переместит поды на здоровые ноды",[26,475],{},[178,477,479],{"id":478},"архитектура-кластера","Архитектура кластера",[15,481,482,483,486,487,490,491,494],{},"Кластер Kubernetes состоит из двух плоскостей: ",[21,484,485],{},"Control Plane"," (мозг, управление) и ",[21,488,489],{},"Worker Nodes"," (тело, выполнение). Все компоненты общаются ",[21,492,493],{},"только через API Server"," — никто не ходит напрямую в etcd или между собой.",[226,496,501],{"className":497,"code":499,"language":500},[498],"language-text","                    Kubernetes Cluster\n    +--------------------------------------------+\n    |            Control Plane                   |\n    |  +----------+ +----------+ +----------+    |\n    |  | Master 1 | | Master 2 | | Master 3 |    |\n    |  +----------+ +----------+ +----------+    |\n    |--------------------------------------------+\n    |           Workload Plane                   |\n    |  +--------+ +--------+ +--------+          |\n    |  |Worker 1| |Worker 2| |Worker 3| ...      |\n    |  +--------+ +--------+ +--------+          |\n    +--------------------------------------------+\n","text",[186,502,499],{"__ignoreMap":231},[178,504,485],{"id":505},"control-plane",[15,507,508],{},"Control Plane — это мозг кластера. Принимает решения, хранит состояние, реагирует на изменения. В production минимум 3 master-ноды для высокой доступности.",[226,510,513],{"className":511,"code":512,"language":500},[498],"+---------------------------------------------+\n|             Control Plane                    |\n|                                              |\n|  +-----------------+   +------------------+  |\n|  |   API Server    |   |   Scheduler      |  |\n|  | единая точка    |   | выбирает ноду    |  |\n|  | входа (REST API)|   | для каждого pod  |  |\n|  +--------+--------+   +------------------+  |\n|           |                                  |\n|  +--------v--------+   +------------------+  |\n|  |     etcd        |   |   Controllers    |  |\n|  | distributed KV  |   | поддерживают     |  |\n|  |store (состояние)|   | desired state    |  |\n|  +-----------------+   +------------------+  |\n+----------------------------------------------+\n",[186,514,512],{"__ignoreMap":231},[516,517,519],"h4",{"id":518},"api-server","API Server",[15,521,522],{},"API Server — единственная точка входа в кластер. Все взаимодействия проходят через него: kubectl, контроллеры, kubelet, внешние системы.",[459,524,525,528,531,534,537],{},[462,526,527],{},"RESTful API для всех операций (CRUD над объектами)",[462,529,530],{},"Stateless — сам ничего не хранит, всё в etcd",[462,532,533],{},"Валидирует объекты перед сохранением",[462,535,536],{},"Уведомляет подписчиков (watch) об изменениях объектов",[462,538,539],{},"Поддерживает аутентификацию, авторизацию, admission control",[516,541,542],{"id":542},"etcd",[15,544,545,546,549],{},"etcd — распределённое key-value хранилище, основанное на алгоритме консенсуса Raft. Хранит ",[21,547,548],{},"всё"," состояние кластера.",[459,551,552,555,558,561],{},[462,553,554],{},"Все объекты K8s (pods, deployments, services, configmaps, secrets)",[462,556,557],{},"Только API Server общается с etcd напрямую",[462,559,560],{},"Потеря etcd = потеря кластера, поэтому бэкапы критичны",[462,562,563],{},"Для production требуется кластер из нечётного количества нод (3, 5, 7) для Raft quorum",[516,565,567],{"id":566},"scheduler","Scheduler",[15,569,570],{},"Scheduler наблюдает за новыми подами без назначенной ноды и выбирает для них лучшее место.",[459,572,573,579,582,588],{},[462,574,575,576],{},"Watch: поды с пустым полем ",[186,577,578],{},"nodeName",[462,580,581],{},"Оценивает ноды по доступным ресурсам, affinity\u002Fanti-affinity правилам, taints\u002Ftolerations",[462,583,584,585,587],{},"Записывает решение (поле ",[186,586,578],{},") через API Server",[462,589,590,593],{},[21,591,592],{},"Не запускает"," pod — только назначает ноду; запуском занимается Kubelet",[516,595,597],{"id":596},"controller-manager","Controller Manager",[15,599,600],{},"Controller Manager запускает набор контроллеров, каждый из которых отвечает за свой тип объекта. Каждый контроллер реализует reconciliation loop.",[15,602,603],{},"Примеры контроллеров:",[37,605,606,616],{},[40,607,608],{},[43,609,610,613],{},[46,611,612],{},"Контроллер",[46,614,615],{},"За что отвечает",[56,617,618,626,634,642,650],{},[43,619,620,623],{},[61,621,622],{},"ReplicaSet controller",[61,624,625],{},"Поддерживает нужное количество реплик pod",[43,627,628,631],{},[61,629,630],{},"Deployment controller",[61,632,633],{},"Управляет ReplicaSet при обновлениях",[43,635,636,639],{},[61,637,638],{},"Node controller",[61,640,641],{},"Следит за здоровьем нод",[43,643,644,647],{},[61,645,646],{},"Job controller",[61,648,649],{},"Запускает задачи до завершения",[43,651,652,655],{},[61,653,654],{},"EndpointSlice controller",[61,656,657],{},"Обновляет endpoints для Service",[178,659,489],{"id":660},"worker-nodes",[15,662,663],{},"Worker-ноды — это машины, на которых запускаются приложения. Каждая нода содержит три обязательных компонента.",[226,665,668],{"className":666,"code":667,"language":500},[498],"+--------------------------------------+\n|           Worker Node                |\n|                                      |\n|  +----------+   +-----------------+  |\n|  | Kubelet  |   |Container Runtime|  |\n|  | агент    |-->| containerd \u002F    |  |\n|  | на ноде  |   | CRI-O           |  |\n|  +----------+   +-----------------+  |\n|                                      |\n|  +----------------------------------+|\n|  |          kube-proxy              ||\n|  |  сетевые правила, load balancing ||\n|  +----------------------------------+|\n|                                      |\n|  +-----+ +-----+ +-----+            |\n|  |Pod 1| |Pod 2| |Pod 3|  ...       |\n|  +-----+ +-----+ +-----+            |\n+--------------------------------------+\n",[186,669,667],{"__ignoreMap":231},[516,671,673],{"id":672},"kubelet","Kubelet",[15,675,676],{},"Kubelet — агент, который запущен на каждой worker-ноде.",[459,678,679,682,685,688],{},[462,680,681],{},"Наблюдает (watch) за подами, назначенными на его ноду",[462,683,684],{},"Инструктирует Container Runtime запустить или остановить контейнеры",[462,686,687],{},"Следит за здоровьем подов (выполняет probes), отправляет статус в API Server",[462,689,690],{},"Не управляет контейнерами, запущенными вне Kubernetes",[516,692,694],{"id":693},"container-runtime","Container Runtime",[15,696,697],{},"Container Runtime — программа, непосредственно запускающая контейнеры.",[459,699,700,706,712,715],{},[462,701,702,705],{},[21,703,704],{},"containerd"," — стандартный runtime начиная с K8s 1.24+ (Docker runtime удалён)",[462,707,708,711],{},[21,709,710],{},"CRI-O"," — альтернативный легковесный runtime",[462,713,714],{},"Общается с Kubelet через CRI (Container Runtime Interface)",[462,716,717],{},"Образ, собранный через Docker, работает на containerd\u002FCRI-O без изменений (OCI стандарт)",[516,719,720],{"id":720},"kube-proxy",[15,722,723],{},"kube-proxy — сетевой компонент на каждой ноде.",[459,725,726,729,732,735],{},[462,727,728],{},"Реализует абстракцию Service (ClusterIP, NodePort, LoadBalancer)",[462,730,731],{},"Настраивает iptables или IPVS правила для балансировки трафика",[462,733,734],{},"Не проксирует трафик сам — настраивает правила в ядре Linux",[462,736,737],{},"Обновляет правила при изменении endpoints (поды появляются\u002Fисчезают)",[26,739],{},[178,741,743],{"id":742},"reconciliation-loop","Reconciliation loop",[15,745,746],{},"Reconciliation loop — фундаментальный паттерн Kubernetes. Каждый контроллер работает по одному принципу: бесконечный цикл \"прочитай желаемое состояние (spec) — сравни с текущим (status) — исправь разницу\".",[226,748,751],{"className":749,"code":750,"language":500},[498],"         Ты                    Controller               Кластер\n          |                        |                        |\n          |  пишешь spec           |                        |\n          |  (replicas: 3)         |                        |\n          |----------------------->|                        |\n          |                        |  читает spec           |\n          |                        |  создаёт 3 Pod'а       |\n          |                        |----------------------->|\n          |                        |                        |\n          |                        |  пишет status          |\n          |                        |  (replicas: 3,         |\n          |  читаешь status        |   ready: 3)            |\n          |\u003C-----------------------|                        |\n",[186,752,750],{"__ignoreMap":231},[15,754,755],{},"Контроллер не выполняет команду один раз — он постоянно следит за состоянием. Если pod упал и осталось 2 реплики вместо 3, контроллер заметит расхождение и создаст новый pod. Это обеспечивает self-healing.",[26,757],{},[29,759,761],{"id":760},"как-запускается-приложение","Как запускается приложение",[178,763,765],{"id":764},"как-k8s-запускает-приложение","Как K8s запускает приложение",[15,767,768,769,771],{},"Когда ты выполняешь ",[186,770,188],{},", происходит цепочка событий:",[773,774,775,781,787,794,799,804],"ol",{},[462,776,777,780],{},[21,778,779],{},"kubectl -> API Server"," — манифест отправляется в API Server, который валидирует объекты и сохраняет их в etcd",[462,782,783,786],{},[21,784,785],{},"Controller"," замечает новый Deployment, создаёт ReplicaSet; ReplicaSet controller создаёт Pod-объекты",[462,788,789,791,792],{},[21,790,567],{}," замечает Pod-ы без назначенной ноды, выбирает лучшую ноду для каждого, записывает ",[186,793,578],{},[462,795,796,798],{},[21,797,673],{}," на назначенной ноде замечает Pod, инструктирует Container Runtime запустить контейнер",[462,800,801,803],{},[21,802,720],{}," замечает готовый Pod, настраивает сетевые правила для Service (load balancing)",[462,805,806,809],{},[21,807,808],{},"Kubelet + Controllers"," постоянно мониторят: pod упал — перезапуск; нода упала — pod перемещён на здоровую ноду",[15,811,812],{},"Каждый компонент выполняет свою задачу и общается только через API Server. Нет центрального оркестратора — есть набор независимых контроллеров, каждый отвечающий за свою часть.",[26,814],{},[178,816,818],{"id":817},"kubernetes-api-и-манифесты","Kubernetes API и манифесты",[15,820,821],{},"Всё в Kubernetes — объект в API. Pods, Deployments, Services, Nodes, ConfigMaps — всё управляется через REST API. kubectl — это просто CLI-клиент к API Server.",[37,823,824,837],{},[40,825,826],{},[43,827,828,831,834],{},[46,829,830],{},"HTTP-метод",[46,832,833],{},"URL",[46,835,836],{},"Действие",[56,838,839,854,869,883],{},[43,840,841,846,851],{},[61,842,843],{},[21,844,845],{},"POST",[61,847,848],{},[186,849,850],{},"\u002Fapis\u002Fapps\u002Fv1\u002Fnamespaces\u002Fdefault\u002Fdeployments",[61,852,853],{},"Создать",[43,855,856,861,866],{},[61,857,858],{},[21,859,860],{},"GET",[61,862,863],{},[186,864,865],{},"\u002Fapis\u002Fapps\u002Fv1\u002Fnamespaces\u002Fdefault\u002Fdeployments\u002Fx",[61,867,868],{},"Прочитать",[43,870,871,876,880],{},[61,872,873],{},[21,874,875],{},"PUT",[61,877,878],{},[186,879,865],{},[61,881,882],{},"Обновить",[43,884,885,890,894],{},[61,886,887],{},[21,888,889],{},"DELETE",[61,891,892],{},[186,893,865],{},[61,895,896],{},"Удалить",[178,898,900],{"id":899},"структура-манифеста","Структура манифеста",[15,902,903],{},"Каждый объект Kubernetes описывается YAML-манифестом из четырёх основных секций:",[226,905,907],{"className":228,"code":906,"language":230,"meta":231,"style":231},"apiVersion: apps\u002Fv1          # --- Type metadata\nkind: Deployment              #     тип объекта и API-группа\n\nmetadata:                     # --- Object metadata\n  name: my-app                #     имя, namespace, labels, annotations\n  namespace: default\n  labels:\n    app: my-app\n\nspec:                         # --- Desired state (ты пишешь)\n  replicas: 3                 #     что ты ХОЧЕШЬ\n  selector:\n    matchLabels:\n      app: my-app\n  template:\n    metadata:\n      labels:\n        app: my-app\n    spec:\n      containers:\n      - name: my-app\n        image: my-app:1.0\n\nstatus:                       # --- Actual state (контроллер пишет)\n  replicas: 3                 #     что СЕЙЧАС на самом деле\n  conditions: [...]\n",[186,908,909,921,933,939,949,961,971,978,987,991,1001,1013,1019,1025,1033,1039,1045,1051,1059,1065,1071,1081,1089,1094,1106,1118],{"__ignoreMap":231},[235,910,911,913,915,918],{"class":237,"line":238},[235,912,242],{"class":241},[235,914,246],{"class":245},[235,916,917],{"class":249},"apps\u002Fv1",[235,919,920],{"class":304},"          # --- Type metadata\n",[235,922,923,925,927,930],{"class":237,"line":253},[235,924,256],{"class":241},[235,926,246],{"class":245},[235,928,929],{"class":249},"Deployment",[235,931,932],{"class":304},"              #     тип объекта и API-группа\n",[235,934,935],{"class":237,"line":264},[235,936,938],{"emptyLinePlaceholder":937},true,"\n",[235,940,941,943,946],{"class":237,"line":273},[235,942,267],{"class":241},[235,944,945],{"class":245},":                     ",[235,947,948],{"class":304},"# --- Object metadata\n",[235,950,951,953,955,958],{"class":237,"line":284},[235,952,276],{"class":241},[235,954,246],{"class":245},[235,956,957],{"class":249},"my-app",[235,959,960],{"class":304},"                #     имя, namespace, labels, annotations\n",[235,962,963,966,968],{"class":237,"line":292},[235,964,965],{"class":241},"  namespace",[235,967,246],{"class":245},[235,969,970],{"class":249},"default\n",[235,972,973,976],{"class":237,"line":308},[235,974,975],{"class":241},"  labels",[235,977,270],{"class":245},[235,979,980,983,985],{"class":237,"line":316},[235,981,982],{"class":241},"    app",[235,984,246],{"class":245},[235,986,281],{"class":249},[235,988,989],{"class":237,"line":324},[235,990,938],{"emptyLinePlaceholder":937},[235,992,993,995,998],{"class":237,"line":334},[235,994,287],{"class":241},[235,996,997],{"class":245},":                         ",[235,999,1000],{"class":304},"# --- Desired state (ты пишешь)\n",[235,1002,1003,1005,1007,1010],{"class":237,"line":342},[235,1004,295],{"class":241},[235,1006,246],{"class":245},[235,1008,1009],{"class":300},"3",[235,1011,1012],{"class":304},"                 #     что ты ХОЧЕШЬ\n",[235,1014,1015,1017],{"class":237,"line":350},[235,1016,311],{"class":241},[235,1018,270],{"class":245},[235,1020,1021,1023],{"class":237,"line":358},[235,1022,319],{"class":241},[235,1024,270],{"class":245},[235,1026,1027,1029,1031],{"class":237,"line":368},[235,1028,327],{"class":241},[235,1030,246],{"class":245},[235,1032,281],{"class":249},[235,1034,1035,1037],{"class":237,"line":376},[235,1036,337],{"class":241},[235,1038,270],{"class":245},[235,1040,1041,1043],{"class":237,"line":384},[235,1042,345],{"class":241},[235,1044,270],{"class":245},[235,1046,1047,1049],{"class":237,"line":397},[235,1048,353],{"class":241},[235,1050,270],{"class":245},[235,1052,1053,1055,1057],{"class":237,"line":408},[235,1054,361],{"class":241},[235,1056,246],{"class":245},[235,1058,281],{"class":249},[235,1060,1061,1063],{"class":237,"line":416},[235,1062,371],{"class":241},[235,1064,270],{"class":245},[235,1066,1067,1069],{"class":237,"line":430},[235,1068,379],{"class":241},[235,1070,270],{"class":245},[235,1072,1073,1075,1077,1079],{"class":237,"line":438},[235,1074,387],{"class":245},[235,1076,390],{"class":241},[235,1078,246],{"class":245},[235,1080,281],{"class":249},[235,1082,1083,1085,1087],{"class":237,"line":446},[235,1084,400],{"class":241},[235,1086,246],{"class":245},[235,1088,405],{"class":249},[235,1090,1092],{"class":237,"line":1091},23,[235,1093,938],{"emptyLinePlaceholder":937},[235,1095,1097,1100,1103],{"class":237,"line":1096},24,[235,1098,1099],{"class":241},"status",[235,1101,1102],{"class":245},":                       ",[235,1104,1105],{"class":304},"# --- Actual state (контроллер пишет)\n",[235,1107,1109,1111,1113,1115],{"class":237,"line":1108},25,[235,1110,295],{"class":241},[235,1112,246],{"class":245},[235,1114,1009],{"class":300},[235,1116,1117],{"class":304},"                 #     что СЕЙЧАС на самом деле\n",[235,1119,1121,1124,1127,1130],{"class":237,"line":1120},26,[235,1122,1123],{"class":241},"  conditions",[235,1125,1126],{"class":245},": [",[235,1128,1129],{"class":300},"...",[235,1131,1132],{"class":245},"]\n",[459,1134,1135,1141,1146,1151],{},[462,1136,1137,1140],{},[21,1138,1139],{},"apiVersion + kind"," — определяют тип объекта",[462,1142,1143,1145],{},[21,1144,267],{}," — идентификация: имя, namespace, labels, annotations",[462,1147,1148,1150],{},[21,1149,287],{}," — желаемое состояние, которое ты описываешь",[462,1152,1153,1155],{},[21,1154,1099],{}," — текущее состояние, которое заполняет контроллер",[15,1157,1158],{},"Не все объекты имеют spec\u002Fstatus. Например, Event, ConfigMap, Secret — это статические данные без контроллера, который бы выполнял reconciliation.",[178,1160,1162],{"id":1161},"apiversion-и-kind","apiVersion и kind",[15,1164,1165,1166,1168],{},"Поле ",[186,1167,242],{}," определяет API-группу и версию:",[37,1170,1171,1180],{},[40,1172,1173],{},[43,1174,1175,1177],{},[46,1176,242],{},[46,1178,1179],{},"Объекты",[56,1181,1182,1192,1201,1211],{},[43,1183,1184,1189],{},[61,1185,1186],{},[21,1187,1188],{},"v1",[61,1190,1191],{},"Pod, Service, ConfigMap, Node, Secret (core-группа)",[43,1193,1194,1198],{},[61,1195,1196],{},[21,1197,917],{},[61,1199,1200],{},"Deployment, ReplicaSet, StatefulSet, DaemonSet",[43,1202,1203,1208],{},[61,1204,1205],{},[21,1206,1207],{},"batch\u002Fv1",[61,1209,1210],{},"Job, CronJob",[43,1212,1213,1218],{},[61,1214,1215],{},[21,1216,1217],{},"networking.k8s.io\u002Fv1",[61,1219,1220],{},"Ingress, NetworkPolicy",[178,1222,1224],{"id":1223},"conditions-состояние-объекта","Conditions — состояние объекта",[15,1226,1227],{},"Status объекта часто содержит массив conditions — независимых друг от друга аспектов состояния:",[226,1229,1231],{"className":228,"code":1230,"language":230,"meta":231,"style":231},"status:\n  conditions:\n  - type: Ready\n    status: \"True\"              # True \u002F False \u002F Unknown\n    reason: KubeletReady        # machine-facing (для автоматики)\n    message: \"kubelet is posting ready status\"  # human-facing\n    lastTransitionTime: \"2024-01-15T10:30:00Z\"\n",[186,1232,1233,1239,1245,1258,1271,1284,1297],{"__ignoreMap":231},[235,1234,1235,1237],{"class":237,"line":238},[235,1236,1099],{"class":241},[235,1238,270],{"class":245},[235,1240,1241,1243],{"class":237,"line":253},[235,1242,1123],{"class":241},[235,1244,270],{"class":245},[235,1246,1247,1250,1253,1255],{"class":237,"line":264},[235,1248,1249],{"class":245},"  - ",[235,1251,1252],{"class":241},"type",[235,1254,246],{"class":245},[235,1256,1257],{"class":249},"Ready\n",[235,1259,1260,1263,1265,1268],{"class":237,"line":273},[235,1261,1262],{"class":241},"    status",[235,1264,246],{"class":245},[235,1266,1267],{"class":249},"\"True\"",[235,1269,1270],{"class":304},"              # True \u002F False \u002F Unknown\n",[235,1272,1273,1276,1278,1281],{"class":237,"line":284},[235,1274,1275],{"class":241},"    reason",[235,1277,246],{"class":245},[235,1279,1280],{"class":249},"KubeletReady",[235,1282,1283],{"class":304},"        # machine-facing (для автоматики)\n",[235,1285,1286,1289,1291,1294],{"class":237,"line":292},[235,1287,1288],{"class":241},"    message",[235,1290,246],{"class":245},[235,1292,1293],{"class":249},"\"kubelet is posting ready status\"",[235,1295,1296],{"class":304},"  # human-facing\n",[235,1298,1299,1302,1304],{"class":237,"line":308},[235,1300,1301],{"class":241},"    lastTransitionTime",[235,1303,246],{"class":245},[235,1305,1306],{"class":249},"\"2024-01-15T10:30:00Z\"\n",[15,1308,1309,1310,1313],{},"Conditions ортогональны: каждый описывает независимый аспект. Это лучше, чем одно поле ",[186,1311,1312],{},"status: healthy\u002Funhealthy",", и легко расширяется новыми условиями.",[15,1315,1316],{},"Примеры Node conditions:",[37,1318,1319,1328],{},[40,1320,1321],{},[43,1322,1323,1326],{},[46,1324,1325],{},"Condition",[46,1327,104],{},[56,1329,1330,1340,1350,1360],{},[43,1331,1332,1337],{},[61,1333,1334],{},[21,1335,1336],{},"Ready",[61,1338,1339],{},"Нода готова принимать pod-ы",[43,1341,1342,1347],{},[61,1343,1344],{},[21,1345,1346],{},"MemoryPressure",[61,1348,1349],{},"Заканчивается RAM",[43,1351,1352,1357],{},[61,1353,1354],{},[21,1355,1356],{},"DiskPressure",[61,1358,1359],{},"Заканчивается диск",[43,1361,1362,1367],{},[61,1363,1364],{},[21,1365,1366],{},"PIDPressure",[61,1368,1369],{},"Заканчиваются PID-ы",[178,1371,1373],{"id":1372},"event-объекты","Event-объекты",[15,1375,1376,1377,1380,1381,1384],{},"Event — отдельный объект в API, создаваемый контроллерами при действиях или проблемах. Events удаляются примерно через час, чтобы не нагружать etcd. Бывают двух типов: ",[21,1378,1379],{},"Normal"," и ",[21,1382,1383],{},"Warning",".",[226,1386,1390],{"className":1387,"code":1388,"language":1389,"meta":231,"style":231},"language-bash shiki shiki-themes github-dark","kubectl get events                                # все события\nkubectl get events --field-selector type=Warning  # только проблемы\nkubectl describe pod my-app                       # события конкретного pod-а\n","bash",[186,1391,1392,1407,1424],{"__ignoreMap":231},[235,1393,1394,1398,1401,1404],{"class":237,"line":238},[235,1395,1397],{"class":1396},"svObZ","kubectl",[235,1399,1400],{"class":249}," get",[235,1402,1403],{"class":249}," events",[235,1405,1406],{"class":304},"                                # все события\n",[235,1408,1409,1411,1413,1415,1418,1421],{"class":237,"line":253},[235,1410,1397],{"class":1396},[235,1412,1400],{"class":249},[235,1414,1403],{"class":249},[235,1416,1417],{"class":300}," --field-selector",[235,1419,1420],{"class":249}," type=Warning",[235,1422,1423],{"class":304},"  # только проблемы\n",[235,1425,1426,1428,1431,1434,1437],{"class":237,"line":264},[235,1427,1397],{"class":1396},[235,1429,1430],{"class":249}," describe",[235,1432,1433],{"class":249}," pod",[235,1435,1436],{"class":249}," my-app",[235,1438,1439],{"class":304},"                       # события конкретного pod-а\n",[26,1441],{},[178,1443,1445],{"id":1444},"kubectl-основные-команды","kubectl — основные команды",[15,1447,1448],{},"kubectl — основной инструмент для работы с кластером. Все команды отправляют HTTP-запросы к API Server.",[178,1450,1452],{"id":1451},"просмотр-объектов","Просмотр объектов",[226,1454,1456],{"className":1387,"code":1455,"language":1389,"meta":231,"style":231},"kubectl get pods                          # список pod-ов в текущем namespace\nkubectl get pods -A                       # pod-ы во всех namespace-ах\nkubectl get pods -o wide                  # расширенный вывод (IP, нода)\nkubectl get deployment my-app -o yaml     # полный YAML-манифест объекта\nkubectl get deployment my-app -o json     # JSON-формат\nkubectl describe pod my-app               # human-readable + events\n",[186,1457,1458,1470,1484,1501,1520,1538],{"__ignoreMap":231},[235,1459,1460,1462,1464,1467],{"class":237,"line":238},[235,1461,1397],{"class":1396},[235,1463,1400],{"class":249},[235,1465,1466],{"class":249}," pods",[235,1468,1469],{"class":304},"                          # список pod-ов в текущем namespace\n",[235,1471,1472,1474,1476,1478,1481],{"class":237,"line":253},[235,1473,1397],{"class":1396},[235,1475,1400],{"class":249},[235,1477,1466],{"class":249},[235,1479,1480],{"class":300}," -A",[235,1482,1483],{"class":304},"                       # pod-ы во всех namespace-ах\n",[235,1485,1486,1488,1490,1492,1495,1498],{"class":237,"line":264},[235,1487,1397],{"class":1396},[235,1489,1400],{"class":249},[235,1491,1466],{"class":249},[235,1493,1494],{"class":300}," -o",[235,1496,1497],{"class":249}," wide",[235,1499,1500],{"class":304},"                  # расширенный вывод (IP, нода)\n",[235,1502,1503,1505,1507,1510,1512,1514,1517],{"class":237,"line":273},[235,1504,1397],{"class":1396},[235,1506,1400],{"class":249},[235,1508,1509],{"class":249}," deployment",[235,1511,1436],{"class":249},[235,1513,1494],{"class":300},[235,1515,1516],{"class":249}," yaml",[235,1518,1519],{"class":304},"     # полный YAML-манифест объекта\n",[235,1521,1522,1524,1526,1528,1530,1532,1535],{"class":237,"line":284},[235,1523,1397],{"class":1396},[235,1525,1400],{"class":249},[235,1527,1509],{"class":249},[235,1529,1436],{"class":249},[235,1531,1494],{"class":300},[235,1533,1534],{"class":249}," json",[235,1536,1537],{"class":304},"     # JSON-формат\n",[235,1539,1540,1542,1544,1546,1548],{"class":237,"line":292},[235,1541,1397],{"class":1396},[235,1543,1430],{"class":249},[235,1545,1433],{"class":249},[235,1547,1436],{"class":249},[235,1549,1550],{"class":304},"               # human-readable + events\n",[178,1552,1554],{"id":1553},"управление-объектами","Управление объектами",[226,1556,1558],{"className":1387,"code":1557,"language":1389,"meta":231,"style":231},"kubectl apply -f manifest.yaml            # создать\u002Fобновить объект из файла\nkubectl delete -f manifest.yaml           # удалить объект\nkubectl delete pod my-app                 # удалить конкретный pod\nkubectl scale deployment my-app --replicas=5  # изменить количество реплик\n",[186,1559,1560,1576,1590,1603],{"__ignoreMap":231},[235,1561,1562,1564,1567,1570,1573],{"class":237,"line":238},[235,1563,1397],{"class":1396},[235,1565,1566],{"class":249}," apply",[235,1568,1569],{"class":300}," -f",[235,1571,1572],{"class":249}," manifest.yaml",[235,1574,1575],{"class":304},"            # создать\u002Fобновить объект из файла\n",[235,1577,1578,1580,1583,1585,1587],{"class":237,"line":253},[235,1579,1397],{"class":1396},[235,1581,1582],{"class":249}," delete",[235,1584,1569],{"class":300},[235,1586,1572],{"class":249},[235,1588,1589],{"class":304},"           # удалить объект\n",[235,1591,1592,1594,1596,1598,1600],{"class":237,"line":264},[235,1593,1397],{"class":1396},[235,1595,1582],{"class":249},[235,1597,1433],{"class":249},[235,1599,1436],{"class":249},[235,1601,1602],{"class":304},"                 # удалить конкретный pod\n",[235,1604,1605,1607,1610,1612,1614,1617],{"class":237,"line":273},[235,1606,1397],{"class":1396},[235,1608,1609],{"class":249}," scale",[235,1611,1509],{"class":249},[235,1613,1436],{"class":249},[235,1615,1616],{"class":300}," --replicas=5",[235,1618,1619],{"class":304},"  # изменить количество реплик\n",[178,1621,1623],{"id":1622},"документация-по-полям","Документация по полям",[226,1625,1627],{"className":1387,"code":1626,"language":1389,"meta":231,"style":231},"kubectl explain pod                       # документация по типу Pod\nkubectl explain pod.spec.containers       # drill down в конкретное поле\nkubectl explain pods --recursive          # полное дерево полей\n",[186,1628,1629,1641,1653],{"__ignoreMap":231},[235,1630,1631,1633,1636,1638],{"class":237,"line":238},[235,1632,1397],{"class":1396},[235,1634,1635],{"class":249}," explain",[235,1637,1433],{"class":249},[235,1639,1640],{"class":304},"                       # документация по типу Pod\n",[235,1642,1643,1645,1647,1650],{"class":237,"line":253},[235,1644,1397],{"class":1396},[235,1646,1635],{"class":249},[235,1648,1649],{"class":249}," pod.spec.containers",[235,1651,1652],{"class":304},"       # drill down в конкретное поле\n",[235,1654,1655,1657,1659,1661,1664],{"class":237,"line":264},[235,1656,1397],{"class":1396},[235,1658,1635],{"class":249},[235,1660,1466],{"class":249},[235,1662,1663],{"class":300}," --recursive",[235,1665,1666],{"class":304},"          # полное дерево полей\n",[178,1668,1670],{"id":1669},"отладка","Отладка",[226,1672,1674],{"className":1387,"code":1673,"language":1389,"meta":231,"style":231},"kubectl logs my-app                       # логи pod-а (stdout\u002Fstderr)\nkubectl logs my-app -f                    # стриминг логов\nkubectl logs my-app -c sidecar            # логи конкретного контейнера\nkubectl logs my-app --previous            # логи предыдущего контейнера (после restart)\nkubectl exec -it my-app -- bash           # shell внутри контейнера\nkubectl port-forward my-app 8080:8080     # проксирование порта на localhost\n",[186,1675,1676,1688,1701,1718,1732,1753],{"__ignoreMap":231},[235,1677,1678,1680,1683,1685],{"class":237,"line":238},[235,1679,1397],{"class":1396},[235,1681,1682],{"class":249}," logs",[235,1684,1436],{"class":249},[235,1686,1687],{"class":304},"                       # логи pod-а (stdout\u002Fstderr)\n",[235,1689,1690,1692,1694,1696,1698],{"class":237,"line":253},[235,1691,1397],{"class":1396},[235,1693,1682],{"class":249},[235,1695,1436],{"class":249},[235,1697,1569],{"class":300},[235,1699,1700],{"class":304},"                    # стриминг логов\n",[235,1702,1703,1705,1707,1709,1712,1715],{"class":237,"line":264},[235,1704,1397],{"class":1396},[235,1706,1682],{"class":249},[235,1708,1436],{"class":249},[235,1710,1711],{"class":300}," -c",[235,1713,1714],{"class":249}," sidecar",[235,1716,1717],{"class":304},"            # логи конкретного контейнера\n",[235,1719,1720,1722,1724,1726,1729],{"class":237,"line":273},[235,1721,1397],{"class":1396},[235,1723,1682],{"class":249},[235,1725,1436],{"class":249},[235,1727,1728],{"class":300}," --previous",[235,1730,1731],{"class":304},"            # логи предыдущего контейнера (после restart)\n",[235,1733,1734,1736,1739,1742,1744,1747,1750],{"class":237,"line":284},[235,1735,1397],{"class":1396},[235,1737,1738],{"class":249}," exec",[235,1740,1741],{"class":300}," -it",[235,1743,1436],{"class":249},[235,1745,1746],{"class":300}," --",[235,1748,1749],{"class":249}," bash",[235,1751,1752],{"class":304},"           # shell внутри контейнера\n",[235,1754,1755,1757,1760,1762,1765],{"class":237,"line":292},[235,1756,1397],{"class":1396},[235,1758,1759],{"class":249}," port-forward",[235,1761,1436],{"class":249},[235,1763,1764],{"class":249}," 8080:8080",[235,1766,1767],{"class":304},"     # проксирование порта на localhost\n",[26,1769],{},[29,1771,1773],{"id":1772},"эксплуатационные-решения","Эксплуатационные решения",[178,1775,1777],{"id":1776},"add-on-компоненты","Add-on компоненты",[15,1779,1780],{},"Не часть ядра Kubernetes, но почти всегда установлены в кластере:",[37,1782,1783,1793],{},[40,1784,1785],{},[43,1786,1787,1790],{},[46,1788,1789],{},"Компонент",[46,1791,1792],{},"Назначение",[56,1794,1795,1805,1815,1825,1838],{},[43,1796,1797,1802],{},[61,1798,1799],{},[21,1800,1801],{},"CoreDNS",[61,1803,1804],{},"DNS-сервер кластера для service discovery по имени",[43,1806,1807,1812],{},[61,1808,1809],{},[21,1810,1811],{},"CNI plugin",[61,1813,1814],{},"Сетевой плагин (Calico, Cilium, Flannel)",[43,1816,1817,1822],{},[61,1818,1819],{},[21,1820,1821],{},"Ingress controller",[61,1823,1824],{},"Входящий HTTP\u002FHTTPS трафик (Nginx, Traefik)",[43,1826,1827,1832],{},[61,1828,1829],{},[21,1830,1831],{},"Metrics Server",[61,1833,1834,1835],{},"Метрики для HPA и ",[186,1836,1837],{},"kubectl top",[43,1839,1840,1845],{},[61,1841,1842],{},[21,1843,1844],{},"Dashboard",[61,1846,1847],{},"Веб-интерфейс (опционально)",[26,1849],{},[178,1851,1853],{"id":1852},"сколько-нод-нужно","Сколько нод нужно",[178,1855,1857],{"id":1856},"control-plane-master","Control Plane (master)",[459,1859,1860,1866],{},[462,1861,1862,1865],{},[21,1863,1864],{},"Dev\u002Ftest:"," 1 нода — single point of failure, но допустимо для разработки",[462,1867,1868,1871],{},[21,1869,1870],{},"Production:"," 3+ ноды — etcd требует Raft quorum (формула 2N+1 для отказоустойчивости)",[178,1873,489],{"id":1874},"worker-nodes-1",[459,1876,1877,1880,1883],{},[462,1878,1879],{},"Зависит от нагрузки приложений",[462,1881,1882],{},"Можно добавлять и убирать без downtime",[462,1884,1885],{},"В облаке: cluster autoscaler добавляет ноды автоматически при нехватке ресурсов",[26,1887],{},[178,1889,1891],{"id":1890},"когда-использовать-kubernetes-а-когда-нет","Когда использовать Kubernetes, а когда нет",[178,1893,1895],{"id":1894},"kubernetes-нужен-когда","Kubernetes нужен когда:",[459,1897,1898,1901,1904,1907,1910],{},[462,1899,1900],{},"20+ микросервисов, которыми невозможно управлять вручную",[462,1902,1903],{},"Требуется автомасштабирование по нагрузке",[462,1905,1906],{},"Multi-cloud или hybrid стратегия (нужна портабельность)",[462,1908,1909],{},"Zero-downtime deploys обязательны",[462,1911,1912],{},"Self-healing критичен для бизнеса",[178,1914,1916],{"id":1915},"kubernetes-не-нужен-когда","Kubernetes НЕ нужен когда:",[459,1918,1919,1922,1925,1928,1931],{},[462,1920,1921],{},"Монолитное приложение (один процесс, один сервер)",[462,1923,1924],{},"Менее 5 микросервисов (overhead Kubernetes превышает пользу)",[462,1926,1927],{},"Нет ресурсов на обучение команды (кривая обучения крутая)",[462,1929,1930],{},"Нет готовности к начальным затратам (K8s потребляет ресурсы сам по себе)",[462,1932,1933],{},"Простой проект, который можно развернуть на одном сервере с Docker Compose",[26,1935],{},[178,1937,1939],{"id":1938},"managed-vs-self-managed","Managed vs Self-managed",[178,1941,1943],{"id":1942},"managed-kubernetes-рекомендуется","Managed Kubernetes (рекомендуется)",[15,1945,1946],{},"Облачный провайдер управляет Control Plane — ты только деплоишь приложения.",[37,1948,1949,1962],{},[40,1950,1951],{},[43,1952,1953,1956,1959],{},[46,1954,1955],{},"Провайдер",[46,1957,1958],{},"Сервис",[46,1960,1961],{},"Особенности",[56,1963,1964,1975,1986],{},[43,1965,1966,1969,1972],{},[61,1967,1968],{},"Google",[61,1970,1971],{},"GKE",[61,1973,1974],{},"Исторически лучшая интеграция (создатели K8s)",[43,1976,1977,1980,1983],{},[61,1978,1979],{},"Amazon",[61,1981,1982],{},"EKS",[61,1984,1985],{},"Глубокая интеграция с AWS-сервисами",[43,1987,1988,1991,1994],{},[61,1989,1990],{},"Azure",[61,1992,1993],{},"AKS",[61,1995,1996],{},"Бесплатный control plane",[15,1998,1999,2000,2003,2004,2007],{},"Преимущества managed: не нужно обновлять control plane, автоматические бэкапы etcd, встроенный мониторинг, SLA на доступность API Server. ",[21,2001,2002],{},"Использовать"," K8s в 10 раз проще, чем ",[21,2005,2006],{},"управлять"," им.",[178,2009,2011],{"id":2010},"self-managed","Self-managed",[15,2013,2014],{},"Инструменты: kubeadm, Rancher, OpenShift. Ты управляешь всем сам — от обновлений etcd до сертификатов. Это сложно и требует глубокой экспертизы. Подходит, когда есть жёсткие требования по безопасности или данные не могут покидать периметр.",[178,2016,2018],{"id":2017},"hybrid","Hybrid",[15,2020,2021],{},"On-prem кластер + облачные worker-ноды при пиках нагрузки. Стабильная нагрузка идёт на свои серверы, пики перетекают в облако.",[26,2023],{},[29,2025,2027],{"id":2026},"пример-go-приложение-в-kubernetes","Пример: Go-приложение в Kubernetes",[15,2029,2030],{},"Рассмотрим полный пример деплоя Go-сервиса. Допустим, у нас есть HTTP-сервер:",[226,2032,2037],{"className":2033,"code":2034,"language":2035,"meta":2036,"style":231},"language-go shiki shiki-themes github-dark","package main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"net\u002Fhttp\"\n    \"os\"\n)\n\nfunc main() {\n    port := os.Getenv(\"PORT\")\n    if port == \"\" {\n        port = \"8080\"\n    }\n\n    http.HandleFunc(\"\u002Fhealthz\", func(w http.ResponseWriter, r *http.Request) {\n        w.WriteHeader(http.StatusOK)\n        fmt.Fprintln(w, \"ok\")\n    })\n\n    http.HandleFunc(\"\u002F\", func(w http.ResponseWriter, r *http.Request) {\n        hostname, _ := os.Hostname()\n        fmt.Fprintf(w, \"Hello from %s\\n\", hostname)\n    })\n\n    log.Printf(\"Starting server on :%s\", port)\n    log.Fatal(http.ListenAndServe(\":\"+port, nil))\n}\n","go","no-run",[186,2038,2039,2048,2052,2060,2071,2080,2089,2098,2103,2107,2118,2140,2157,2168,2173,2177,2228,2239,2255,2260,2264,2303,2318,2339,2343,2347,2368,2399],{"__ignoreMap":231},[235,2040,2041,2045],{"class":237,"line":238},[235,2042,2044],{"class":2043},"snl16","package",[235,2046,2047],{"class":1396}," main\n",[235,2049,2050],{"class":237,"line":253},[235,2051,938],{"emptyLinePlaceholder":937},[235,2053,2054,2057],{"class":237,"line":264},[235,2055,2056],{"class":2043},"import",[235,2058,2059],{"class":245}," (\n",[235,2061,2062,2065,2068],{"class":237,"line":273},[235,2063,2064],{"class":249},"    \"",[235,2066,2067],{"class":1396},"fmt",[235,2069,2070],{"class":249},"\"\n",[235,2072,2073,2075,2078],{"class":237,"line":284},[235,2074,2064],{"class":249},[235,2076,2077],{"class":1396},"log",[235,2079,2070],{"class":249},[235,2081,2082,2084,2087],{"class":237,"line":292},[235,2083,2064],{"class":249},[235,2085,2086],{"class":1396},"net\u002Fhttp",[235,2088,2070],{"class":249},[235,2090,2091,2093,2096],{"class":237,"line":308},[235,2092,2064],{"class":249},[235,2094,2095],{"class":1396},"os",[235,2097,2070],{"class":249},[235,2099,2100],{"class":237,"line":316},[235,2101,2102],{"class":245},")\n",[235,2104,2105],{"class":237,"line":324},[235,2106,938],{"emptyLinePlaceholder":937},[235,2108,2109,2112,2115],{"class":237,"line":334},[235,2110,2111],{"class":2043},"func",[235,2113,2114],{"class":1396}," main",[235,2116,2117],{"class":245},"() {\n",[235,2119,2120,2123,2126,2129,2132,2135,2138],{"class":237,"line":342},[235,2121,2122],{"class":245},"    port ",[235,2124,2125],{"class":2043},":=",[235,2127,2128],{"class":245}," os.",[235,2130,2131],{"class":1396},"Getenv",[235,2133,2134],{"class":245},"(",[235,2136,2137],{"class":249},"\"PORT\"",[235,2139,2102],{"class":245},[235,2141,2142,2145,2148,2151,2154],{"class":237,"line":350},[235,2143,2144],{"class":2043},"    if",[235,2146,2147],{"class":245}," port ",[235,2149,2150],{"class":2043},"==",[235,2152,2153],{"class":249}," \"\"",[235,2155,2156],{"class":245}," {\n",[235,2158,2159,2162,2165],{"class":237,"line":358},[235,2160,2161],{"class":245},"        port ",[235,2163,2164],{"class":2043},"=",[235,2166,2167],{"class":249}," \"8080\"\n",[235,2169,2170],{"class":237,"line":368},[235,2171,2172],{"class":245},"    }\n",[235,2174,2175],{"class":237,"line":376},[235,2176,938],{"emptyLinePlaceholder":937},[235,2178,2179,2182,2185,2187,2190,2193,2195,2197,2201,2204,2206,2209,2211,2214,2217,2220,2222,2225],{"class":237,"line":384},[235,2180,2181],{"class":245},"    http.",[235,2183,2184],{"class":1396},"HandleFunc",[235,2186,2134],{"class":245},[235,2188,2189],{"class":249},"\"\u002Fhealthz\"",[235,2191,2192],{"class":245},", ",[235,2194,2111],{"class":2043},[235,2196,2134],{"class":245},[235,2198,2200],{"class":2199},"s9osk","w",[235,2202,2203],{"class":1396}," http",[235,2205,1384],{"class":245},[235,2207,2208],{"class":1396},"ResponseWriter",[235,2210,2192],{"class":245},[235,2212,2213],{"class":2199},"r",[235,2215,2216],{"class":2043}," *",[235,2218,2219],{"class":1396},"http",[235,2221,1384],{"class":245},[235,2223,2224],{"class":1396},"Request",[235,2226,2227],{"class":245},") {\n",[235,2229,2230,2233,2236],{"class":237,"line":397},[235,2231,2232],{"class":245},"        w.",[235,2234,2235],{"class":1396},"WriteHeader",[235,2237,2238],{"class":245},"(http.StatusOK)\n",[235,2240,2241,2244,2247,2250,2253],{"class":237,"line":408},[235,2242,2243],{"class":245},"        fmt.",[235,2245,2246],{"class":1396},"Fprintln",[235,2248,2249],{"class":245},"(w, ",[235,2251,2252],{"class":249},"\"ok\"",[235,2254,2102],{"class":245},[235,2256,2257],{"class":237,"line":416},[235,2258,2259],{"class":245},"    })\n",[235,2261,2262],{"class":237,"line":430},[235,2263,938],{"emptyLinePlaceholder":937},[235,2265,2266,2268,2270,2272,2275,2277,2279,2281,2283,2285,2287,2289,2291,2293,2295,2297,2299,2301],{"class":237,"line":438},[235,2267,2181],{"class":245},[235,2269,2184],{"class":1396},[235,2271,2134],{"class":245},[235,2273,2274],{"class":249},"\"\u002F\"",[235,2276,2192],{"class":245},[235,2278,2111],{"class":2043},[235,2280,2134],{"class":245},[235,2282,2200],{"class":2199},[235,2284,2203],{"class":1396},[235,2286,1384],{"class":245},[235,2288,2208],{"class":1396},[235,2290,2192],{"class":245},[235,2292,2213],{"class":2199},[235,2294,2216],{"class":2043},[235,2296,2219],{"class":1396},[235,2298,1384],{"class":245},[235,2300,2224],{"class":1396},[235,2302,2227],{"class":245},[235,2304,2305,2308,2310,2312,2315],{"class":237,"line":446},[235,2306,2307],{"class":245},"        hostname, _ ",[235,2309,2125],{"class":2043},[235,2311,2128],{"class":245},[235,2313,2314],{"class":1396},"Hostname",[235,2316,2317],{"class":245},"()\n",[235,2319,2320,2322,2325,2327,2330,2333,2336],{"class":237,"line":1091},[235,2321,2243],{"class":245},[235,2323,2324],{"class":1396},"Fprintf",[235,2326,2249],{"class":245},[235,2328,2329],{"class":249},"\"Hello from ",[235,2331,2332],{"class":300},"%s\\n",[235,2334,2335],{"class":249},"\"",[235,2337,2338],{"class":245},", hostname)\n",[235,2340,2341],{"class":237,"line":1096},[235,2342,2259],{"class":245},[235,2344,2345],{"class":237,"line":1108},[235,2346,938],{"emptyLinePlaceholder":937},[235,2348,2349,2352,2355,2357,2360,2363,2365],{"class":237,"line":1120},[235,2350,2351],{"class":245},"    log.",[235,2353,2354],{"class":1396},"Printf",[235,2356,2134],{"class":245},[235,2358,2359],{"class":249},"\"Starting server on :",[235,2361,2362],{"class":300},"%s",[235,2364,2335],{"class":249},[235,2366,2367],{"class":245},", port)\n",[235,2369,2371,2373,2376,2379,2382,2384,2387,2390,2393,2396],{"class":237,"line":2370},27,[235,2372,2351],{"class":245},[235,2374,2375],{"class":1396},"Fatal",[235,2377,2378],{"class":245},"(http.",[235,2380,2381],{"class":1396},"ListenAndServe",[235,2383,2134],{"class":245},[235,2385,2386],{"class":249},"\":\"",[235,2388,2389],{"class":2043},"+",[235,2391,2392],{"class":245},"port, ",[235,2394,2395],{"class":300},"nil",[235,2397,2398],{"class":245},"))\n",[235,2400,2402],{"class":237,"line":2401},28,[235,2403,2404],{"class":245},"}\n",[15,2406,2407],{},"Манифест для Kubernetes:",[226,2409,2411],{"className":228,"code":2410,"language":230,"meta":231,"style":231},"apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: hello-go\n  labels:\n    app: hello-go\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: hello-go\n  template:\n    metadata:\n      labels:\n        app: hello-go\n    spec:\n      containers:\n      - name: hello-go\n        image: myregistry\u002Fhello-go:1.0\n        ports:\n        - containerPort: 8080\n        env:\n        - name: PORT\n          value: \"8080\"\n        resources:\n          requests:\n            cpu: \"100m\"\n            memory: \"64Mi\"\n          limits:\n            cpu: \"200m\"\n            memory: \"128Mi\"\n        livenessProbe:\n          httpGet:\n            path: \u002Fhealthz\n            port: 8080\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        readinessProbe:\n          httpGet:\n            path: \u002Fhealthz\n            port: 8080\n          initialDelaySeconds: 3\n          periodSeconds: 5\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: hello-go\nspec:\n  selector:\n    app: hello-go\n  ports:\n  - port: 80\n    targetPort: 8080\n  type: ClusterIP\n",[186,2412,2413,2421,2429,2435,2444,2450,2458,2464,2473,2479,2485,2493,2499,2505,2511,2519,2525,2531,2541,2550,2556,2566,2573,2584,2594,2600,2606,2616,2625,2633,2643,2653,2661,2669,2680,2690,2701,2712,2720,2727,2736,2745,2754,2763,2769,2779,2789,2796,2805,2812,2819,2828,2836,2849,2859],{"__ignoreMap":231},[235,2414,2415,2417,2419],{"class":237,"line":238},[235,2416,242],{"class":241},[235,2418,246],{"class":245},[235,2420,250],{"class":249},[235,2422,2423,2425,2427],{"class":237,"line":253},[235,2424,256],{"class":241},[235,2426,246],{"class":245},[235,2428,261],{"class":249},[235,2430,2431,2433],{"class":237,"line":264},[235,2432,267],{"class":241},[235,2434,270],{"class":245},[235,2436,2437,2439,2441],{"class":237,"line":273},[235,2438,276],{"class":241},[235,2440,246],{"class":245},[235,2442,2443],{"class":249},"hello-go\n",[235,2445,2446,2448],{"class":237,"line":284},[235,2447,975],{"class":241},[235,2449,270],{"class":245},[235,2451,2452,2454,2456],{"class":237,"line":292},[235,2453,982],{"class":241},[235,2455,246],{"class":245},[235,2457,2443],{"class":249},[235,2459,2460,2462],{"class":237,"line":308},[235,2461,287],{"class":241},[235,2463,270],{"class":245},[235,2465,2466,2468,2470],{"class":237,"line":316},[235,2467,295],{"class":241},[235,2469,246],{"class":245},[235,2471,2472],{"class":300},"3\n",[235,2474,2475,2477],{"class":237,"line":324},[235,2476,311],{"class":241},[235,2478,270],{"class":245},[235,2480,2481,2483],{"class":237,"line":334},[235,2482,319],{"class":241},[235,2484,270],{"class":245},[235,2486,2487,2489,2491],{"class":237,"line":342},[235,2488,327],{"class":241},[235,2490,246],{"class":245},[235,2492,2443],{"class":249},[235,2494,2495,2497],{"class":237,"line":350},[235,2496,337],{"class":241},[235,2498,270],{"class":245},[235,2500,2501,2503],{"class":237,"line":358},[235,2502,345],{"class":241},[235,2504,270],{"class":245},[235,2506,2507,2509],{"class":237,"line":368},[235,2508,353],{"class":241},[235,2510,270],{"class":245},[235,2512,2513,2515,2517],{"class":237,"line":376},[235,2514,361],{"class":241},[235,2516,246],{"class":245},[235,2518,2443],{"class":249},[235,2520,2521,2523],{"class":237,"line":384},[235,2522,371],{"class":241},[235,2524,270],{"class":245},[235,2526,2527,2529],{"class":237,"line":397},[235,2528,379],{"class":241},[235,2530,270],{"class":245},[235,2532,2533,2535,2537,2539],{"class":237,"line":408},[235,2534,387],{"class":245},[235,2536,390],{"class":241},[235,2538,246],{"class":245},[235,2540,2443],{"class":249},[235,2542,2543,2545,2547],{"class":237,"line":416},[235,2544,400],{"class":241},[235,2546,246],{"class":245},[235,2548,2549],{"class":249},"myregistry\u002Fhello-go:1.0\n",[235,2551,2552,2554],{"class":237,"line":430},[235,2553,411],{"class":241},[235,2555,270],{"class":245},[235,2557,2558,2560,2562,2564],{"class":237,"line":438},[235,2559,419],{"class":245},[235,2561,422],{"class":241},[235,2563,246],{"class":245},[235,2565,427],{"class":300},[235,2567,2568,2571],{"class":237,"line":446},[235,2569,2570],{"class":241},"        env",[235,2572,270],{"class":245},[235,2574,2575,2577,2579,2581],{"class":237,"line":1091},[235,2576,419],{"class":245},[235,2578,390],{"class":241},[235,2580,246],{"class":245},[235,2582,2583],{"class":249},"PORT\n",[235,2585,2586,2589,2591],{"class":237,"line":1096},[235,2587,2588],{"class":241},"          value",[235,2590,246],{"class":245},[235,2592,2593],{"class":249},"\"8080\"\n",[235,2595,2596,2598],{"class":237,"line":1108},[235,2597,433],{"class":241},[235,2599,270],{"class":245},[235,2601,2602,2604],{"class":237,"line":1120},[235,2603,441],{"class":241},[235,2605,270],{"class":245},[235,2607,2608,2611,2613],{"class":237,"line":2370},[235,2609,2610],{"class":241},"            cpu",[235,2612,246],{"class":245},[235,2614,2615],{"class":249},"\"100m\"\n",[235,2617,2618,2620,2622],{"class":237,"line":2401},[235,2619,449],{"class":241},[235,2621,246],{"class":245},[235,2623,2624],{"class":249},"\"64Mi\"\n",[235,2626,2628,2631],{"class":237,"line":2627},29,[235,2629,2630],{"class":241},"          limits",[235,2632,270],{"class":245},[235,2634,2636,2638,2640],{"class":237,"line":2635},30,[235,2637,2610],{"class":241},[235,2639,246],{"class":245},[235,2641,2642],{"class":249},"\"200m\"\n",[235,2644,2646,2648,2650],{"class":237,"line":2645},31,[235,2647,449],{"class":241},[235,2649,246],{"class":245},[235,2651,2652],{"class":249},"\"128Mi\"\n",[235,2654,2656,2659],{"class":237,"line":2655},32,[235,2657,2658],{"class":241},"        livenessProbe",[235,2660,270],{"class":245},[235,2662,2664,2667],{"class":237,"line":2663},33,[235,2665,2666],{"class":241},"          httpGet",[235,2668,270],{"class":245},[235,2670,2672,2675,2677],{"class":237,"line":2671},34,[235,2673,2674],{"class":241},"            path",[235,2676,246],{"class":245},[235,2678,2679],{"class":249},"\u002Fhealthz\n",[235,2681,2683,2686,2688],{"class":237,"line":2682},35,[235,2684,2685],{"class":241},"            port",[235,2687,246],{"class":245},[235,2689,427],{"class":300},[235,2691,2693,2696,2698],{"class":237,"line":2692},36,[235,2694,2695],{"class":241},"          initialDelaySeconds",[235,2697,246],{"class":245},[235,2699,2700],{"class":300},"5\n",[235,2702,2704,2707,2709],{"class":237,"line":2703},37,[235,2705,2706],{"class":241},"          periodSeconds",[235,2708,246],{"class":245},[235,2710,2711],{"class":300},"10\n",[235,2713,2715,2718],{"class":237,"line":2714},38,[235,2716,2717],{"class":241},"        readinessProbe",[235,2719,270],{"class":245},[235,2721,2723,2725],{"class":237,"line":2722},39,[235,2724,2666],{"class":241},[235,2726,270],{"class":245},[235,2728,2730,2732,2734],{"class":237,"line":2729},40,[235,2731,2674],{"class":241},[235,2733,246],{"class":245},[235,2735,2679],{"class":249},[235,2737,2739,2741,2743],{"class":237,"line":2738},41,[235,2740,2685],{"class":241},[235,2742,246],{"class":245},[235,2744,427],{"class":300},[235,2746,2748,2750,2752],{"class":237,"line":2747},42,[235,2749,2695],{"class":241},[235,2751,246],{"class":245},[235,2753,2472],{"class":300},[235,2755,2757,2759,2761],{"class":237,"line":2756},43,[235,2758,2706],{"class":241},[235,2760,246],{"class":245},[235,2762,2700],{"class":300},[235,2764,2766],{"class":237,"line":2765},44,[235,2767,2768],{"class":1396},"---\n",[235,2770,2772,2774,2776],{"class":237,"line":2771},45,[235,2773,242],{"class":241},[235,2775,246],{"class":245},[235,2777,2778],{"class":249},"v1\n",[235,2780,2782,2784,2786],{"class":237,"line":2781},46,[235,2783,256],{"class":241},[235,2785,246],{"class":245},[235,2787,2788],{"class":249},"Service\n",[235,2790,2792,2794],{"class":237,"line":2791},47,[235,2793,267],{"class":241},[235,2795,270],{"class":245},[235,2797,2799,2801,2803],{"class":237,"line":2798},48,[235,2800,276],{"class":241},[235,2802,246],{"class":245},[235,2804,2443],{"class":249},[235,2806,2808,2810],{"class":237,"line":2807},49,[235,2809,287],{"class":241},[235,2811,270],{"class":245},[235,2813,2815,2817],{"class":237,"line":2814},50,[235,2816,311],{"class":241},[235,2818,270],{"class":245},[235,2820,2822,2824,2826],{"class":237,"line":2821},51,[235,2823,982],{"class":241},[235,2825,246],{"class":245},[235,2827,2443],{"class":249},[235,2829,2831,2834],{"class":237,"line":2830},52,[235,2832,2833],{"class":241},"  ports",[235,2835,270],{"class":245},[235,2837,2839,2841,2844,2846],{"class":237,"line":2838},53,[235,2840,1249],{"class":245},[235,2842,2843],{"class":241},"port",[235,2845,246],{"class":245},[235,2847,2848],{"class":300},"80\n",[235,2850,2852,2855,2857],{"class":237,"line":2851},54,[235,2853,2854],{"class":241},"    targetPort",[235,2856,246],{"class":245},[235,2858,427],{"class":300},[235,2860,2862,2865,2867],{"class":237,"line":2861},55,[235,2863,2864],{"class":241},"  type",[235,2866,246],{"class":245},[235,2868,2869],{"class":249},"ClusterIP\n",[226,2871,2873],{"className":1387,"code":2872,"language":1389,"meta":231,"style":231},"# Применение манифеста\nkubectl apply -f hello-go.yaml\n\n# Проверка статуса\nkubectl get pods -l app=hello-go\nkubectl get svc hello-go\n\n# Просмотр логов\nkubectl logs -l app=hello-go --all-containers\n\n# Масштабирование\nkubectl scale deployment hello-go --replicas=5\n\n# Обновление образа\nkubectl set image deployment\u002Fhello-go hello-go=myregistry\u002Fhello-go:2.0\n",[186,2874,2875,2880,2891,2895,2900,2914,2926,2930,2935,2949,2953,2958,2972,2976,2981],{"__ignoreMap":231},[235,2876,2877],{"class":237,"line":238},[235,2878,2879],{"class":304},"# Применение манифеста\n",[235,2881,2882,2884,2886,2888],{"class":237,"line":253},[235,2883,1397],{"class":1396},[235,2885,1566],{"class":249},[235,2887,1569],{"class":300},[235,2889,2890],{"class":249}," hello-go.yaml\n",[235,2892,2893],{"class":237,"line":264},[235,2894,938],{"emptyLinePlaceholder":937},[235,2896,2897],{"class":237,"line":273},[235,2898,2899],{"class":304},"# Проверка статуса\n",[235,2901,2902,2904,2906,2908,2911],{"class":237,"line":284},[235,2903,1397],{"class":1396},[235,2905,1400],{"class":249},[235,2907,1466],{"class":249},[235,2909,2910],{"class":300}," -l",[235,2912,2913],{"class":249}," app=hello-go\n",[235,2915,2916,2918,2920,2923],{"class":237,"line":292},[235,2917,1397],{"class":1396},[235,2919,1400],{"class":249},[235,2921,2922],{"class":249}," svc",[235,2924,2925],{"class":249}," hello-go\n",[235,2927,2928],{"class":237,"line":308},[235,2929,938],{"emptyLinePlaceholder":937},[235,2931,2932],{"class":237,"line":316},[235,2933,2934],{"class":304},"# Просмотр логов\n",[235,2936,2937,2939,2941,2943,2946],{"class":237,"line":324},[235,2938,1397],{"class":1396},[235,2940,1682],{"class":249},[235,2942,2910],{"class":300},[235,2944,2945],{"class":249}," app=hello-go",[235,2947,2948],{"class":300}," --all-containers\n",[235,2950,2951],{"class":237,"line":334},[235,2952,938],{"emptyLinePlaceholder":937},[235,2954,2955],{"class":237,"line":342},[235,2956,2957],{"class":304},"# Масштабирование\n",[235,2959,2960,2962,2964,2966,2969],{"class":237,"line":350},[235,2961,1397],{"class":1396},[235,2963,1609],{"class":249},[235,2965,1509],{"class":249},[235,2967,2968],{"class":249}," hello-go",[235,2970,2971],{"class":300}," --replicas=5\n",[235,2973,2974],{"class":237,"line":358},[235,2975,938],{"emptyLinePlaceholder":937},[235,2977,2978],{"class":237,"line":368},[235,2979,2980],{"class":304},"# Обновление образа\n",[235,2982,2983,2985,2988,2991,2994],{"class":237,"line":376},[235,2984,1397],{"class":1396},[235,2986,2987],{"class":249}," set",[235,2989,2990],{"class":249}," image",[235,2992,2993],{"class":249}," deployment\u002Fhello-go",[235,2995,2996],{"class":249}," hello-go=myregistry\u002Fhello-go:2.0\n",[26,2998],{},[29,3000,3002],{"id":3001},"вопросы-на-собеседовании","Вопросы на собеседовании",[15,3004,3005],{},[21,3006,3007],{},"Что такое Kubernetes и какую проблему он решает?",[15,3009,3010],{},"Kubernetes — система оркестрации контейнеров, автоматизирующая деплой, масштабирование и управление контейнеризированными приложениями на кластере машин. Решает проблему управления большим количеством микросервисов: service discovery, self-healing, rolling updates, auto-scaling. Без K8s ручное управление 100+ микросервисами на множестве серверов невозможно.",[15,3012,3013],{},[21,3014,3015],{},"В чём разница между декларативным и императивным подходом в K8s?",[15,3017,3018,3019,3021,3022,3024],{},"Императивный подход: ты говоришь системе ",[21,3020,205],{}," сделать каждый шаг (создай контейнер, настрой балансировщик, подключи сеть). Декларативный: ты описываешь ",[21,3023,209],{}," хочешь (YAML-манифест с desired state), а Kubernetes сам решает, как достичь этого состояния и постоянно поддерживает его через reconciliation loop. При изменении манифеста K8s вычисляет разницу и приводит систему к новому состоянию.",[15,3026,3027],{},[21,3028,3029],{},"Из каких компонентов состоит Control Plane?",[15,3031,3032],{},"Четыре ключевых компонента: (1) API Server — единая точка входа, RESTful API, stateless; (2) etcd — распределённое key-value хранилище всего состояния кластера (Raft consensus); (3) Scheduler — назначает pod-ы на ноды по ресурсам, affinity, taints; (4) Controller Manager — набор контроллеров (ReplicaSet, Deployment, Node, Job), каждый из которых реализует reconciliation loop для своего типа объекта. Все компоненты общаются только через API Server.",[15,3034,3035],{},[21,3036,3037],{},"Что такое reconciliation loop?",[15,3039,3040,3041,3044],{},"Бесконечный цикл: контроллер читает desired state (spec) из API, сравнивает с actual state (status) в кластере, исправляет разницу. Например, ReplicaSet controller видит ",[186,3042,3043],{},"replicas: 3"," в spec, но обнаруживает только 2 работающих pod-а — создаёт ещё один. Это фундаментальный паттерн, обеспечивающий self-healing: система постоянно стремится к желаемому состоянию.",[15,3046,3047],{},[21,3048,3049],{},"Какова роль Kubelet и чем он отличается от Scheduler?",[15,3051,3052,3053,3055],{},"Scheduler выбирает, на какую ноду разместить pod (записывает ",[186,3054,578],{}," в объект Pod через API Server), но сам не запускает ничего. Kubelet — агент на каждой worker-ноде, который наблюдает за pod-ами, назначенными на его ноду, и инструктирует Container Runtime (containerd) запустить контейнеры. Kubelet также выполняет health-проверки (probes) и отправляет статус обратно в API Server.",[15,3057,3058],{},[21,3059,3060],{},"Когда Kubernetes не нужен?",[15,3062,3063],{},"Когда overhead превышает пользу: монолитное приложение на одном сервере; менее 5 сервисов (Docker Compose достаточно); нет ресурсов на обучение команды (кривая обучения K8s крутая); нет требований к автоскейлингу, self-healing или zero-downtime deploys. K8s потребляет ресурсы сам по себе (control plane, etcd, system pods), что не оправдано для маленьких проектов.",[15,3065,3066],{},[21,3067,3068],{},"В чём отличие Managed Kubernetes (EKS, GKE, AKS) от Self-managed?",[15,3070,3071],{},"В managed-варианте облачный провайдер управляет Control Plane: обновления, бэкапы etcd, мониторинг, сертификаты, HA. Ты управляешь только worker-нодами и деплоишь приложения. В self-managed (kubeadm, Rancher) ты отвечаешь за всё: от установки etcd до ротации сертификатов. Managed рекомендуется в большинстве случаев — использовать K8s в 10 раз проще, чем управлять им.",[26,3073],{},[29,3075,3077],{"id":3076},"задачи","Задачи",[178,3079,3081],{"id":3080},"задача-1-анализ-манифеста","Задача 1. Анализ манифеста",[15,3083,3084,3087],{},[21,3085,3086],{},"Уровень:"," Средняя",[15,3089,3090,3093],{},[21,3091,3092],{},"Что проверяет:"," понимание структуры манифеста и связи между объектами",[15,3095,3096,3099],{},[21,3097,3098],{},"Условие:"," Дан манифест. Определи: сколько pod-ов будет запущено, на каком порту приложение будет доступно внутри кластера через Service, и что произойдёт, если один pod упадёт.",[226,3101,3103],{"className":228,"code":3102,"language":230,"meta":231,"style":231},"apiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: api-server\nspec:\n  replicas: 4\n  selector:\n    matchLabels:\n      app: api\n      version: v2\n  template:\n    metadata:\n      labels:\n        app: api\n        version: v2\n    spec:\n      containers:\n      - name: api\n        image: myregistry\u002Fapi:2.0\n        ports:\n        - containerPort: 3000\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: api-service\nspec:\n  selector:\n    app: api\n  ports:\n  - port: 80\n    targetPort: 3000\n",[186,3104,3105,3113,3121,3127,3136,3142,3151,3157,3163,3172,3182,3188,3194,3200,3208,3217,3223,3229,3239,3248,3254,3265,3269,3277,3285,3291,3300,3306,3312,3320,3326,3336],{"__ignoreMap":231},[235,3106,3107,3109,3111],{"class":237,"line":238},[235,3108,242],{"class":241},[235,3110,246],{"class":245},[235,3112,250],{"class":249},[235,3114,3115,3117,3119],{"class":237,"line":253},[235,3116,256],{"class":241},[235,3118,246],{"class":245},[235,3120,261],{"class":249},[235,3122,3123,3125],{"class":237,"line":264},[235,3124,267],{"class":241},[235,3126,270],{"class":245},[235,3128,3129,3131,3133],{"class":237,"line":273},[235,3130,276],{"class":241},[235,3132,246],{"class":245},[235,3134,3135],{"class":249},"api-server\n",[235,3137,3138,3140],{"class":237,"line":284},[235,3139,287],{"class":241},[235,3141,270],{"class":245},[235,3143,3144,3146,3148],{"class":237,"line":292},[235,3145,295],{"class":241},[235,3147,246],{"class":245},[235,3149,3150],{"class":300},"4\n",[235,3152,3153,3155],{"class":237,"line":308},[235,3154,311],{"class":241},[235,3156,270],{"class":245},[235,3158,3159,3161],{"class":237,"line":316},[235,3160,319],{"class":241},[235,3162,270],{"class":245},[235,3164,3165,3167,3169],{"class":237,"line":324},[235,3166,327],{"class":241},[235,3168,246],{"class":245},[235,3170,3171],{"class":249},"api\n",[235,3173,3174,3177,3179],{"class":237,"line":334},[235,3175,3176],{"class":241},"      version",[235,3178,246],{"class":245},[235,3180,3181],{"class":249},"v2\n",[235,3183,3184,3186],{"class":237,"line":342},[235,3185,337],{"class":241},[235,3187,270],{"class":245},[235,3189,3190,3192],{"class":237,"line":350},[235,3191,345],{"class":241},[235,3193,270],{"class":245},[235,3195,3196,3198],{"class":237,"line":358},[235,3197,353],{"class":241},[235,3199,270],{"class":245},[235,3201,3202,3204,3206],{"class":237,"line":368},[235,3203,361],{"class":241},[235,3205,246],{"class":245},[235,3207,3171],{"class":249},[235,3209,3210,3213,3215],{"class":237,"line":376},[235,3211,3212],{"class":241},"        version",[235,3214,246],{"class":245},[235,3216,3181],{"class":249},[235,3218,3219,3221],{"class":237,"line":384},[235,3220,371],{"class":241},[235,3222,270],{"class":245},[235,3224,3225,3227],{"class":237,"line":397},[235,3226,379],{"class":241},[235,3228,270],{"class":245},[235,3230,3231,3233,3235,3237],{"class":237,"line":408},[235,3232,387],{"class":245},[235,3234,390],{"class":241},[235,3236,246],{"class":245},[235,3238,3171],{"class":249},[235,3240,3241,3243,3245],{"class":237,"line":416},[235,3242,400],{"class":241},[235,3244,246],{"class":245},[235,3246,3247],{"class":249},"myregistry\u002Fapi:2.0\n",[235,3249,3250,3252],{"class":237,"line":430},[235,3251,411],{"class":241},[235,3253,270],{"class":245},[235,3255,3256,3258,3260,3262],{"class":237,"line":438},[235,3257,419],{"class":245},[235,3259,422],{"class":241},[235,3261,246],{"class":245},[235,3263,3264],{"class":300},"3000\n",[235,3266,3267],{"class":237,"line":446},[235,3268,2768],{"class":1396},[235,3270,3271,3273,3275],{"class":237,"line":1091},[235,3272,242],{"class":241},[235,3274,246],{"class":245},[235,3276,2778],{"class":249},[235,3278,3279,3281,3283],{"class":237,"line":1096},[235,3280,256],{"class":241},[235,3282,246],{"class":245},[235,3284,2788],{"class":249},[235,3286,3287,3289],{"class":237,"line":1108},[235,3288,267],{"class":241},[235,3290,270],{"class":245},[235,3292,3293,3295,3297],{"class":237,"line":1120},[235,3294,276],{"class":241},[235,3296,246],{"class":245},[235,3298,3299],{"class":249},"api-service\n",[235,3301,3302,3304],{"class":237,"line":2370},[235,3303,287],{"class":241},[235,3305,270],{"class":245},[235,3307,3308,3310],{"class":237,"line":2401},[235,3309,311],{"class":241},[235,3311,270],{"class":245},[235,3313,3314,3316,3318],{"class":237,"line":2627},[235,3315,982],{"class":241},[235,3317,246],{"class":245},[235,3319,3171],{"class":249},[235,3321,3322,3324],{"class":237,"line":2635},[235,3323,2833],{"class":241},[235,3325,270],{"class":245},[235,3327,3328,3330,3332,3334],{"class":237,"line":2645},[235,3329,1249],{"class":245},[235,3331,2843],{"class":241},[235,3333,246],{"class":245},[235,3335,2848],{"class":300},[235,3337,3338,3340,3342],{"class":237,"line":2655},[235,3339,2854],{"class":241},[235,3341,246],{"class":245},[235,3343,3264],{"class":300},[15,3345,3346],{},[21,3347,3348],{},"Ответ:",[15,3350,3351,3352,3355,3356,3359],{},"Будет запущено 4 pod-а (replicas: 4). Внутри кластера приложение доступно по адресу ",[186,3353,3354],{},"api-service:80"," (Service слушает на порту 80 и перенаправляет трафик на containerPort 3000). Если один pod упадёт, ReplicaSet controller обнаружит, что текущее количество реплик (3) отличается от желаемого (4), и создаст новый pod. Service автоматически перенаправит трафик только на здоровые pod-ы. Обрати внимание: selector Service использует только label ",[186,3357,3358],{},"app: api",", поэтому он будет маршрутизировать трафик ко всем pod-ам с этим label-ом, включая pod-ы других версий, если они существуют.",[178,3361,3363],{"id":3362},"задача-2-порядок-запуска","Задача 2. Порядок запуска",[15,3365,3366,3087],{},[21,3367,3086],{},[15,3369,3370,3372],{},[21,3371,3092],{}," понимание взаимодействия компонентов кластера",[15,3374,3375,3377,3378,3381],{},[21,3376,3098],{}," Опиши пошагово, что происходит от момента выполнения ",[186,3379,3380],{},"kubectl apply -f deployment.yaml"," до момента, когда приложение готово обслуживать трафик. Укажи, какой компонент кластера выполняет каждый шаг и через что компоненты общаются.",[15,3383,3384],{},[21,3385,3348],{},[773,3387,3388,3391,3394,3397,3402,3408,3411,3414,3417,3420],{},[462,3389,3390],{},"kubectl отправляет HTTP POST с манифестом на API Server",[462,3392,3393],{},"API Server валидирует манифест, сохраняет объект Deployment в etcd",[462,3395,3396],{},"Deployment controller (через watch на API Server) замечает новый Deployment, создаёт объект ReplicaSet через API Server",[462,3398,3399,3400],{},"ReplicaSet controller замечает новый ReplicaSet, создаёт N объектов Pod (по числу replicas) через API Server. Pod-ы сохраняются с пустым ",[186,3401,578],{},[462,3403,3404,3405,3407],{},"Scheduler (через watch на API Server) замечает pod-ы без ноды, оценивает ресурсы и ограничения, записывает ",[186,3406,578],{}," для каждого pod-а через API Server",[462,3409,3410],{},"Kubelet на соответствующей ноде (через watch на API Server) замечает pod, назначенный на его ноду, отправляет команду Container Runtime (containerd) через CRI — скачать образ и запустить контейнер",[462,3412,3413],{},"Kubelet выполняет readiness probe; когда probe проходит, обновляет статус pod-а как Ready через API Server",[462,3415,3416],{},"EndpointSlice controller добавляет IP pod-а в endpoints Service",[462,3418,3419],{},"kube-proxy на каждой ноде обновляет iptables\u002FIPVS правила",[462,3421,3422],{},"Трафик, приходящий на Service, балансируется на все Ready pod-ы",[15,3424,3425],{},"Все компоненты общаются исключительно через API Server — прямого взаимодействия между ними нет.",[178,3427,3429],{"id":3428},"задача-3-диагностика-проблемы","Задача 3. Диагностика проблемы",[15,3431,3432,3087],{},[21,3433,3086],{},[15,3435,3436,3438],{},[21,3437,3092],{}," практические навыки отладки",[15,3440,3441,3443,3444,3446],{},[21,3442,3098],{}," После ",[186,3445,188],{}," pod остаётся в статусе Pending более 5 минут. Какие шаги ты предпримешь для диагностики? Назови минимум 3 возможные причины.",[15,3448,3449],{},[21,3450,3348],{},[15,3452,3453],{},"Шаги диагностики:",[226,3455,3457],{"className":1387,"code":3456,"language":1389,"meta":231,"style":231},"kubectl describe pod \u003Cname>       # смотрим Events и Conditions\nkubectl get events --sort-by='.lastTimestamp'  # все события\nkubectl get nodes                 # проверяем состояние нод\nkubectl describe nodes            # смотрим ресурсы и taints\n",[186,3458,3459,3482,3499,3511],{"__ignoreMap":231},[235,3460,3461,3463,3465,3467,3470,3473,3476,3479],{"class":237,"line":238},[235,3462,1397],{"class":1396},[235,3464,1430],{"class":249},[235,3466,1433],{"class":249},[235,3468,3469],{"class":2043}," \u003C",[235,3471,3472],{"class":249},"nam",[235,3474,3475],{"class":245},"e",[235,3477,3478],{"class":2043},">",[235,3480,3481],{"class":304},"       # смотрим Events и Conditions\n",[235,3483,3484,3486,3488,3490,3493,3496],{"class":237,"line":253},[235,3485,1397],{"class":1396},[235,3487,1400],{"class":249},[235,3489,1403],{"class":249},[235,3491,3492],{"class":300}," --sort-by=",[235,3494,3495],{"class":249},"'.lastTimestamp'",[235,3497,3498],{"class":304},"  # все события\n",[235,3500,3501,3503,3505,3508],{"class":237,"line":264},[235,3502,1397],{"class":1396},[235,3504,1400],{"class":249},[235,3506,3507],{"class":249}," nodes",[235,3509,3510],{"class":304},"                 # проверяем состояние нод\n",[235,3512,3513,3515,3517,3519],{"class":237,"line":273},[235,3514,1397],{"class":1396},[235,3516,1430],{"class":249},[235,3518,3507],{"class":249},[235,3520,3521],{"class":304},"            # смотрим ресурсы и taints\n",[15,3523,3524],{},"Возможные причины Pending: (1) недостаточно ресурсов на нодах — requests pod-а (CPU\u002Fmemory) превышают доступное на всех нодах; (2) pod имеет nodeSelector или nodeAffinity, и ни одна нода не соответствует требованиям; (3) все подходящие ноды имеют taint, а у pod-а нет соответствующей toleration; (4) PersistentVolumeClaim не может быть привязан к PersistentVolume (нет доступных PV нужного размера\u002Fкласса); (5) кластер достиг лимита pod-ов на ноду (по умолчанию 110).",[26,3526],{},[29,3528,3530],{"id":3529},"интерактивная-практика","Интерактивная практика",[3532,3533,3536,3539,3556],"quiz",{"answer":1009,"id":3534,"xp":3535},"infra-k8s-overview-q1","10",[15,3537,3538],{},"Где в Kubernetes хранится желаемое состояние кластера, с которым сверяются контроллеры?",[3540,3541,3542],"template",{"v-slot:options":231},[459,3543,3544,3547,3550,3553],{},[462,3545,3546],{},"В kubelet на каждой ноде",[462,3548,3549],{},"В container runtime",[462,3551,3552],{},"В API Server и его хранилище etcd",[462,3554,3555],{},"В локальном kubeconfig разработчика",[3540,3557,3558],{"v-slot:explanation":231},[15,3559,3560],{},"Пользователь и контроллеры работают через API Server, а устойчивое состояние хранится в etcd. Kubelet и runtime приводят конкретную ноду к состоянию, полученному из API.",[3562,3563,3567,3570,3744],"predict",{"answer":3564,"id":3565,"xp":3566},"Pending\\nRunning","infra-k8s-overview-p1","15",[15,3568,3569],{},"Что выведет программа?",[3540,3571,3572],{"v-slot:code":231},[226,3573,3575],{"className":2033,"code":3574,"language":2035,"meta":231,"style":231},"package main\n\nimport \"fmt\"\n\nfunc podPhase(scheduled bool, containersReady bool) string {\n    if !scheduled {\n        return \"Pending\"\n    }\n    if containersReady {\n        return \"Running\"\n    }\n    return \"Running\"\n}\n\nfunc main() {\n    fmt.Println(podPhase(false, false))\n    fmt.Println(podPhase(true, true))\n}\n",[186,3576,3577,3583,3587,3598,3602,3632,3642,3650,3654,3661,3668,3672,3679,3683,3687,3695,3719,3740],{"__ignoreMap":231},[235,3578,3579,3581],{"class":237,"line":238},[235,3580,2044],{"class":2043},[235,3582,2047],{"class":1396},[235,3584,3585],{"class":237,"line":253},[235,3586,938],{"emptyLinePlaceholder":937},[235,3588,3589,3591,3594,3596],{"class":237,"line":264},[235,3590,2056],{"class":2043},[235,3592,3593],{"class":249}," \"",[235,3595,2067],{"class":1396},[235,3597,2070],{"class":249},[235,3599,3600],{"class":237,"line":273},[235,3601,938],{"emptyLinePlaceholder":937},[235,3603,3604,3606,3609,3611,3614,3617,3619,3622,3624,3627,3630],{"class":237,"line":284},[235,3605,2111],{"class":2043},[235,3607,3608],{"class":1396}," podPhase",[235,3610,2134],{"class":245},[235,3612,3613],{"class":2199},"scheduled",[235,3615,3616],{"class":2043}," bool",[235,3618,2192],{"class":245},[235,3620,3621],{"class":2199},"containersReady",[235,3623,3616],{"class":2043},[235,3625,3626],{"class":245},") ",[235,3628,3629],{"class":2043},"string",[235,3631,2156],{"class":245},[235,3633,3634,3636,3639],{"class":237,"line":292},[235,3635,2144],{"class":2043},[235,3637,3638],{"class":2043}," !",[235,3640,3641],{"class":245},"scheduled {\n",[235,3643,3644,3647],{"class":237,"line":308},[235,3645,3646],{"class":2043},"        return",[235,3648,3649],{"class":249}," \"Pending\"\n",[235,3651,3652],{"class":237,"line":316},[235,3653,2172],{"class":245},[235,3655,3656,3658],{"class":237,"line":324},[235,3657,2144],{"class":2043},[235,3659,3660],{"class":245}," containersReady {\n",[235,3662,3663,3665],{"class":237,"line":334},[235,3664,3646],{"class":2043},[235,3666,3667],{"class":249}," \"Running\"\n",[235,3669,3670],{"class":237,"line":342},[235,3671,2172],{"class":245},[235,3673,3674,3677],{"class":237,"line":350},[235,3675,3676],{"class":2043},"    return",[235,3678,3667],{"class":249},[235,3680,3681],{"class":237,"line":358},[235,3682,2404],{"class":245},[235,3684,3685],{"class":237,"line":368},[235,3686,938],{"emptyLinePlaceholder":937},[235,3688,3689,3691,3693],{"class":237,"line":376},[235,3690,2111],{"class":2043},[235,3692,2114],{"class":1396},[235,3694,2117],{"class":245},[235,3696,3697,3700,3703,3705,3708,3710,3713,3715,3717],{"class":237,"line":384},[235,3698,3699],{"class":245},"    fmt.",[235,3701,3702],{"class":1396},"Println",[235,3704,2134],{"class":245},[235,3706,3707],{"class":1396},"podPhase",[235,3709,2134],{"class":245},[235,3711,3712],{"class":300},"false",[235,3714,2192],{"class":245},[235,3716,3712],{"class":300},[235,3718,2398],{"class":245},[235,3720,3721,3723,3725,3727,3729,3731,3734,3736,3738],{"class":237,"line":397},[235,3722,3699],{"class":245},[235,3724,3702],{"class":1396},[235,3726,2134],{"class":245},[235,3728,3707],{"class":1396},[235,3730,2134],{"class":245},[235,3732,3733],{"class":300},"true",[235,3735,2192],{"class":245},[235,3737,3733],{"class":300},[235,3739,2398],{"class":245},[235,3741,3742],{"class":237,"line":408},[235,3743,2404],{"class":245},[3540,3745,3746],{"v-slot:hint":231},[15,3747,3748,3749,3752,3753,3756],{},"Если scheduler ещё не нашёл ноду, pod остаётся ",[186,3750,3751],{},"Pending",". После запуска контейнеров фаза становится ",[186,3754,3755],{},"Running",", а готовность отражается отдельно через readiness.",[3758,3759,3763,3772,3901],"code-task",{"expected":3760,"id":3761,"xp":3762},"describe\\nresources\\ntaints","infra-k8s-overview-ct1","20",[15,3764,3765,3766,3769,3770,1384],{},"Реализуй ",[186,3767,3768],{},"PendingReason",": выбери первый диагностический фокус для pod-а в ",[186,3771,3751],{},[3540,3773,3774],{"v-slot:template":231},[226,3775,3777],{"className":2033,"code":3776,"language":2035,"meta":231,"style":231},"package main\n\nimport \"fmt\"\n\nfunc PendingReason(kind string) string {\n    return \"todo\"\n}\n\nfunc main() {\n    fmt.Println(PendingReason(\"events\"))\n    fmt.Println(PendingReason(\"cpu\"))\n    fmt.Println(PendingReason(\"node\"))\n}\n",[186,3778,3779,3785,3789,3799,3803,3823,3830,3834,3838,3846,3863,3880,3897],{"__ignoreMap":231},[235,3780,3781,3783],{"class":237,"line":238},[235,3782,2044],{"class":2043},[235,3784,2047],{"class":1396},[235,3786,3787],{"class":237,"line":253},[235,3788,938],{"emptyLinePlaceholder":937},[235,3790,3791,3793,3795,3797],{"class":237,"line":264},[235,3792,2056],{"class":2043},[235,3794,3593],{"class":249},[235,3796,2067],{"class":1396},[235,3798,2070],{"class":249},[235,3800,3801],{"class":237,"line":273},[235,3802,938],{"emptyLinePlaceholder":937},[235,3804,3805,3807,3810,3812,3814,3817,3819,3821],{"class":237,"line":284},[235,3806,2111],{"class":2043},[235,3808,3809],{"class":1396}," PendingReason",[235,3811,2134],{"class":245},[235,3813,256],{"class":2199},[235,3815,3816],{"class":2043}," string",[235,3818,3626],{"class":245},[235,3820,3629],{"class":2043},[235,3822,2156],{"class":245},[235,3824,3825,3827],{"class":237,"line":292},[235,3826,3676],{"class":2043},[235,3828,3829],{"class":249}," \"todo\"\n",[235,3831,3832],{"class":237,"line":308},[235,3833,2404],{"class":245},[235,3835,3836],{"class":237,"line":316},[235,3837,938],{"emptyLinePlaceholder":937},[235,3839,3840,3842,3844],{"class":237,"line":324},[235,3841,2111],{"class":2043},[235,3843,2114],{"class":1396},[235,3845,2117],{"class":245},[235,3847,3848,3850,3852,3854,3856,3858,3861],{"class":237,"line":334},[235,3849,3699],{"class":245},[235,3851,3702],{"class":1396},[235,3853,2134],{"class":245},[235,3855,3768],{"class":1396},[235,3857,2134],{"class":245},[235,3859,3860],{"class":249},"\"events\"",[235,3862,2398],{"class":245},[235,3864,3865,3867,3869,3871,3873,3875,3878],{"class":237,"line":342},[235,3866,3699],{"class":245},[235,3868,3702],{"class":1396},[235,3870,2134],{"class":245},[235,3872,3768],{"class":1396},[235,3874,2134],{"class":245},[235,3876,3877],{"class":249},"\"cpu\"",[235,3879,2398],{"class":245},[235,3881,3882,3884,3886,3888,3890,3892,3895],{"class":237,"line":350},[235,3883,3699],{"class":245},[235,3885,3702],{"class":1396},[235,3887,2134],{"class":245},[235,3889,3768],{"class":1396},[235,3891,2134],{"class":245},[235,3893,3894],{"class":249},"\"node\"",[235,3896,2398],{"class":245},[235,3898,3899],{"class":237,"line":358},[235,3900,2404],{"class":245},[3540,3902,3903],{"v-slot:hints":231},[459,3904,3905,3911,3917],{},[462,3906,3907,3908,1384],{},"Для событий pod-а начни с ",[186,3909,3910],{},"describe",[462,3912,3913,3914,1384],{},"Для нехватки CPU или memory проверь ",[186,3915,3916],{},"resources",[462,3918,3919,3920,1384],{},"Для несовпадения с нодами проверь ",[186,3921,3922],{},"taints",[3924,3925,3926],"style",{},"html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":231,"searchDepth":253,"depth":253,"links":3928},[3929,3932,3941,3954,3967,3968,3969,3974],{"id":31,"depth":253,"text":32,"children":3930},[3931],{"id":180,"depth":264,"text":181},{"id":194,"depth":253,"text":195,"children":3933},[3934,3935,3936,3937,3938,3939,3940],{"id":198,"depth":264,"text":199},{"id":213,"depth":264,"text":214},{"id":220,"depth":264,"text":221},{"id":478,"depth":264,"text":479},{"id":505,"depth":264,"text":485},{"id":660,"depth":264,"text":489},{"id":742,"depth":264,"text":743},{"id":760,"depth":253,"text":761,"children":3942},[3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953],{"id":764,"depth":264,"text":765},{"id":817,"depth":264,"text":818},{"id":899,"depth":264,"text":900},{"id":1161,"depth":264,"text":1162},{"id":1223,"depth":264,"text":1224},{"id":1372,"depth":264,"text":1373},{"id":1444,"depth":264,"text":1445},{"id":1451,"depth":264,"text":1452},{"id":1553,"depth":264,"text":1554},{"id":1622,"depth":264,"text":1623},{"id":1669,"depth":264,"text":1670},{"id":1772,"depth":253,"text":1773,"children":3955},[3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966],{"id":1776,"depth":264,"text":1777},{"id":1852,"depth":264,"text":1853},{"id":1856,"depth":264,"text":1857},{"id":1874,"depth":264,"text":489},{"id":1890,"depth":264,"text":1891},{"id":1894,"depth":264,"text":1895},{"id":1915,"depth":264,"text":1916},{"id":1938,"depth":264,"text":1939},{"id":1942,"depth":264,"text":1943},{"id":2010,"depth":264,"text":2011},{"id":2017,"depth":264,"text":2018},{"id":2026,"depth":253,"text":2027},{"id":3001,"depth":253,"text":3002},{"id":3076,"depth":253,"text":3077,"children":3970},[3971,3972,3973],{"id":3080,"depth":264,"text":3081},{"id":3362,"depth":264,"text":3363},{"id":3428,"depth":264,"text":3429},{"id":3529,"depth":253,"text":3530},1781022065166]