Kubernetes в реалния живот: 15 критични сценария и решения
Kubernetes изглежда елегантен в уроците, но production средата разказва различна история. Ето 15 реални сценария, които разделят начинаещите оператори от закалените в битки инженери — с приложими решения за всеки от тях.
⚔️ Задълбочено дебъгване
1. Pod заседнал в CrashLoopBackOff, без логове, без грешки
Как дебъгвате отвъд kubectl logs и describe?
- Проверете логовете на предишния контейнер:
kubectl logs <pod> --previous- контейнерът може да се срине преди да запише логове - Влезте в контейнера с дебъг шел:
kubectl debug -it <pod> --image=busybox --target=<container> - Инспектирайте събития на ниво node:
kubectl get events --field-selector involvedObject.name=<pod> - Проверете init контейнерите: Често виновникът е failing init контейнер, който се изпълнява преди основния контейнер
- Прегледайте entrypoint на контейнера: Процесът може да излезе веднага — тествайте образа локално с
docker run -it <image> sh - Проверете ресурсните лимити: OOMKilled контейнерите не винаги оставят логове — проверете
kubectl describe podзаLast State: OOMKilled
2. StatefulSet pod не се свързва отново с PVC след срив на node
Как възстановявате без пресъздаване на storage?
- Проверете PV статуса:
kubectl get pv- търсетеReleasedилиFailedсъстояние - Принудително изтрийте заседналия pod:
kubectl delete pod <pod> --force --grace-period=0 - Проверете VolumeAttachment обектите:
kubectl get volumeattachments- остарелите attachments могат да блокират повторното свързване - Изтрийте остарелия VolumeAttachment:
kubectl delete volumeattachment <name> - Проверете здравето на CSI драйвера: Проверете CSI драйвер pod-овете в
kube-systemnamespace - Последна опция - patch на PV: Премахнете
claimRefза да позволите повторно свързване:kubectl patch pv <pv-name> -p '{"spec":{"claimRef": null}}'
3. Pod-овете са Pending, Cluster Autoscaler не мащабира нагоре
Топ 3 стъпки за дебъгване:
- Стъпка 1 - Проверете логовете на Autoscaler:
kubectl logs -n kube-system -l app=cluster-autoscaler- търсете "scale up" решения и защо са отхвърлени - Стъпка 2 - Проверете ограниченията на node group: Проверете дали е достигнат лимитът за максимални nodes, дали необходимият тип инстанция е наличен във вашия регион и дали има достатъчно IAM права
- Стъпка 3 - Изследвайте изискванията за планиране на pod: Проверете за nodeSelector, affinity правила или taints, които никоя node група не може да удовлетвори. Изпълнете
kubectl describe podи погледнете секцията Events за грешки при планиране - Чести виновници: PodDisruptionBudget блокиращ scale-down (което блокира scale-up цикли), pod-ове с локално хранилище, които не могат да бъдат препланирани, и недостатъчна квота при облачния доставчик
4. NetworkPolicy блокира трафик между namespaces
Как проектирате правила с минимални привилегии и ги тествате безопасно?
- Започнете с audit режим: Използвайте инструменти като Cilium's policy audit режим, за да видите какво ще бъде блокирано преди прилагане
- Дизайн модел - Default deny + explicit allow:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
- Разрешете трафик между namespaces изрично:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: backend
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
podSelector:
matchLabels:
app: web
- Безопасно тестване: Деплойнете debug pod и използвайте
nc -zv <service> <port>за да тествате свързаност преди и след промени в политиката - Използвайте визуализация на политики: Инструменти като Cilium Hubble или Calico's policy board помагат за визуализиране на трафик потоците
5. Услуга трябва да се свърже с външна DB чрез VPN вътре в клъстера
Как архитектурирате за HA + сигурност?
- Опция 1 - Sidecar VPN контейнер: Стартирайте VPN клиент като sidecar в pod-ове, които имат нужда от DB достъп. Добре за изолация, но дублира връзки.
- Опция 2 - Специализирани VPN gateway pod-ове: Деплойнете DaemonSet или Deployment на VPN gateway pod-ове със Service. Насочете трафика през тези gateways използвайки NetworkPolicy.
- Опция 3 - VPN на ниво node (препоръчително за HA):
# Използвайте DaemonSet с hostNetwork: true
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: vpn-gateway
spec:
selector:
matchLabels:
app: vpn-gateway
template:
spec:
hostNetwork: true
containers:
- name: vpn
image: your-vpn-image
securityContext:
capabilities:
add: ["NET_ADMIN"]
- Съображения за сигурност: Използвайте Kubernetes Secrets за VPN credentials, имплементирайте NetworkPolicy за ограничаване на pod-ове, които могат да достигнат VPN gateway, активирайте mTLS ако се поддържа от вашето VPN решение
- HA архитектура: Стартирайте множество VPN pod-ове в различни availability zones, използвайте headless Service с client-side load balancing, имплементирайте health checks, които проверяват действителна DB свързаност
🧱 Сигурност + Архитектура
6. Управление на multi-tenant EKS клъстер
Как изолирате workloads с RBAC, квоти и мрежова сегментация?
- Namespace изолация: Един namespace за tenant със стриктен RBAC
# Role ограничена до tenant namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: tenant-a
name: tenant-role
rules:
- apiGroups: ["", "apps"]
resources: ["pods", "deployments", "services"]
verbs: ["get", "list", "create", "update", "delete"]
- Ресурсни квоти за tenant:
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
namespace: tenant-a
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "50"
- Мрежова сегментация: Default-deny NetworkPolicy за namespace, explicit allow правила само за необходима cross-tenant комуникация
- Допълнително укрепване: Използвайте PodSecurityAdmission за прилагане на restricted политики, имплементирайте OPA/Gatekeeper за custom политики, разгледайте специализирани node pools за tenant при чувствителни workloads
7. Kubelet продължава да се рестартира на един node
Къде поглеждате първо – systemd, container runtime или cgroups?
- Стъпка 1 - Проверете systemd статуса:
systemctl status kubeletиjournalctl -u kubelet -f - Стъпка 2 - Търсете OOM kills:
dmesg | grep -i "oom\|killed"- kubelet може да бъде OOM killed - Стъпка 3 - Проверете container runtime:
systemctl status containerd(или docker), след товаcrictl psза да проверите дали runtime отговаря - Стъпка 4 - Проверете cgroup конфигурацията: Уверете се, че cgroup driver съвпада между kubelet и container runtime (и двата трябва да използват
systemdилиcgroupfs) - Стъпка 5 - Disk pressure:
df -hна/var/lib/kubeletи/var/lib/containerd - Чести причини: Изтекли сертификати, проблеми със свързаността към API server, повредено kubelet състояние (опитайте да премахнете
/var/lib/kubelet/cpu_manager_state)
8. Критичен pod е евиктиран поради node pressure
Обяснете QoS класове и политики за евикция:
- QoS класове (ред на евикция):
- BestEffort (евиктират се първи): Няма зададени requests или limits
- Burstable (евиктират се втори): Requests < Limits, или само някои контейнери имат limits
- Guaranteed (евиктират се последни): Requests = Limits за ВСИЧКИ контейнери
# Guaranteed QoS пример
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "500m"
- Защитете критични pod-ове: Използвайте PriorityClass с
preemptionPolicy: Neverили висока стойност на priority
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: critical-workload
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "Критични workloads, които не трябва да бъдат евиктирани"
- Прагове за евикция: Конфигурирайте kubelet флагове като
--eviction-hardи--eviction-softза задаване на прагове за memory/disk pressure
9. Rolling update причини downtime
Какво се обърка в readiness/startup probe или deployment конфигурацията?
- Чести виновници:
- Липсваща readiness probe: Трафикът се насочва преди приложението да е готово
- Агресивни probe настройки:
initialDelaySecondsтвърде кратък за бавно стартиращи приложения - Грешен endpoint: Probe удря тежък endpoint, който timeout-ва
# Правилна probe конфигурация
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
startupProbe: # За бавно стартиращи приложения
httpGet:
path: /health/started
port: 8080
failureThreshold: 30
periodSeconds: 10
- Deployment настройки за преглед:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0 # Никога не премахвайте здрави pod-ове
maxSurge: 1 # Добавяйте по един нов pod
minReadySeconds: 30 # Изчакайте преди маркиране като available
- Не забравяйте preStop hooks: Позволете graceful shutdown преди SIGTERM
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
10. Ingress Controller се проваля под натоварване
Как дебъгвате и мащабирате routing ефективно?
- Стъпки за дебъгване:
- Проверете логовете на контролера:
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx - Мониторирайте connection метрики: Търсете
nginx_ingress_controller_nginx_process_connections - Проверете за config reload бури: Честите Ingress промени причиняват reloads
- Стратегии за мащабиране:
- Хоризонтално мащабиране: Увеличете replicas и използвайте pod anti-affinity за дистрибуция
- Настройте worker processes: Задайте
worker-processes: "auto"в ConfigMap - Активирайте keep-alive: Намалете connection overhead с upstream keep-alive
# Ingress ConfigMap настройки
data:
worker-processes: "auto"
max-worker-connections: "65536"
upstream-keepalive-connections: "200"
keep-alive: "75"
- Обмислете разделяне: Използвайте отделни Ingress контролери за различни класове трафик (вътрешен срещу външен)
⚙️ Производителност + Надеждност
11. Istio sidecar консумира повече CPU от вашето приложение
Как профилирате и оптимизирате mesh производителността?
- Първо профилирайте: Използвайте
istioctl proxy-configза инспекция на Envoy конфигурацията - Проверете размера на конфигурацията:
istioctl proxy-statusпоказва статуса на config sync - Стратегии за оптимизация:
- Ограничете sidecar обхвата:
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: default
namespace: my-app
spec:
egress:
- hosts:
- "./*" # Само локален namespace
- "istio-system/*" # Control plane
- Настройте ресурсни лимити:
# В IstioOperator
spec:
values:
global:
proxy:
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
- Деактивирайте ненужни функции: Изключете access logging, намалете tracing sampling rate
- Обмислете sidecar-less: Istio ambient mesh премахва sidecars за L4 трафик
12. etcd забавя операциите на control plane
Основни причини + как го настройвате безопасно?
- Чести основни причини:
- Disk I/O латентност (etcd е много чувствителен към производителността на диска)
- Твърде много обекти (secrets, configmaps, events)
- Мрежова латентност между etcd членове
- Големи размери на обекти (secrets с големи данни)
- Диагностика:
# Проверете etcd метрики
etcdctl endpoint status --write-out=table
etcdctl endpoint health
# Ключови метрики за наблюдение
- etcd_disk_wal_fsync_duration_seconds (трябва да е < 10ms)
- etcd_disk_backend_commit_duration_seconds
- etcd_server_slow_apply_total
- Безопасна настройка:
- Използвайте SSD/NVMe хранилище (IOPS > 3000, латентност < 1ms)
- Увеличете
--quota-backend-bytesако достигате space quota - Активирайте auto-compaction:
--auto-compaction-retention=1 - Редовна дефрагментация (по време на maintenance прозорци)
- Намалете event TTL за ограничаване на натрупването на събития
13. Трябва да наложите образи само от доверен вътрешен registry
Gatekeeper, Kyverno или custom Admission Webhook – какъв е вашият ход?
- Препоръка: Kyverno за простота, Gatekeeper за сложни политики
- Kyverno подход (по-прост):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Образите трябва да идват от вътрешния registry"
pattern:
spec:
containers:
- image: "registry.internal.com/*"
initContainers:
- image: "registry.internal.com/*"
- Gatekeeper подход (по-гъвкав):
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: repo-is-internal
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
repos:
- "registry.internal.com/"
- Custom webhook: Само ако имате нужда от интеграция с външни системи или custom логика, която policy engines не могат да обработят
- Професионален съвет: Също имплементирайте верификация на image signatures с Cosign + Kyverno за supply chain сигурност
14. Pod-ове заседнали в ContainerCreating завинаги
CNI attach забавяне? OverlayFS корупция? Разкажете процеса си за намиране на основната причина:
- Стъпка 1 - Describe на pod:
kubectl describe pod <pod>- проверете секцията Events за специфични грешки - Стъпка 2 - Проверете CNI:
# Проверете CNI plugin pod-ове
kubectl get pods -n kube-system -l k8s-app=calico-node # или вашия CNI
# Проверете CNI логове
kubectl logs -n kube-system -l k8s-app=calico-node
# Проверете дали CNI config съществува
ls /etc/cni/net.d/
- Стъпка 3 - Проверете container runtime:
# Containerd
crictl ps
crictl logs <container-id>
journalctl -u containerd
# Проверете за заседнали sandbox контейнери
crictl pods | grep NotReady
- Стъпка 4 - Проверете storage:
# Overlay filesystem проблеми
df -h /var/lib/containerd
mount | grep overlay
# Почистете ако е повреден
crictl rmi --prune
- Стъпка 5 - Проверете за изчерпване на ресурси: IP адреси изчерпани в CNI subnet, твърде много pod-ове на node, достигнат лимит на inotify watch
15. Случайни DNS грешки в Pod-ове
Как дебъгвате CoreDNS, kube-proxy и conntrack взаимодействия?
- Стъпка 1 - Тествайте DNS от pod:
kubectl run -it --rm debug --image=busybox -- nslookup kubernetes
kubectl run -it --rm debug --image=busybox -- nslookup google.com
- Стъпка 2 - Проверете CoreDNS:
# CoreDNS pod статус
kubectl get pods -n kube-system -l k8s-app=kube-dns
# CoreDNS логове
kubectl logs -n kube-system -l k8s-app=kube-dns
# Проверете CoreDNS метрики
kubectl top pods -n kube-system -l k8s-app=kube-dns
- Стъпка 3 - Проверете kube-proxy:
# Проверете kube-proxy mode
kubectl get cm -n kube-system kube-proxy -o yaml | grep mode
# Проверете iptables/ipvs правила
iptables -t nat -L | grep coredns
ipvsadm -ln | grep <coredns-ip>
- Стъпка 4 - Conntrack проблеми (чест виновник):
# Проверете conntrack таблица
conntrack -S
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# Увеличете ако достигате лимити
sysctl -w net.netfilter.nf_conntrack_max=524288
- Стъпка 5 - Поправката за race condition: Добавете към pod spec за избягване на UDP source port изчерпване:
dnsConfig:
options:
- name: single-request-reopen
- name: ndots
value: "2"
- Професионален съвет: Използвайте NodeLocal DNSCache за намаляване на CoreDNS натоварването и избягване на conntrack проблеми за DNS трафик
Обобщение
Тези 15 сценария представят реалността на работата с Kubernetes в production. Ключовите изводи:
- Винаги първо събирайте данни: Events, логове, метрики и node статус преди да правите промени
- Наслоявайте защитите: RBAC + NetworkPolicy + Resource Quotas + Pod Security
- Проектирайте за отказ: Правилни QoS класове, priority classes и PodDisruptionBudgets
- Мониторирайте control plane: Здравето на etcd и kubelet е критично
- Тествайте преди прилагане: Audit режим за политики, canary deployments за промени
Production Kubernetes изисква систематичен подход за дебъгване и задълбочено разбиране на основните компоненти. Овладейте тези сценарии и ще бъдете готови за каквото и да ви поднесат вашите клъстери.