Go: Docker и Kubernetes

20 вопросов

1 Чем контейнер отличается от виртуальной машины?

ВМ - полная эмуляция железа, своя ОС, гипервизор. Контейнер - изоляция процессов на общем ядре ОС (namespaces, cgroups). Контейнер легче и быстрее стартует, меньше накладных расходов. В Go бинарник компилируется в статический или с минимальными зависимостями и упаковывается в образ; один процесс в контейнере - типичный сценарий.

Открыть отдельно →
2 Чем образ (image) отличается от контейнера?

Образ - неизменяемый шаблон (слои файловой системы + метаданные). Контейнер - запущенный экземпляр образа (читаемый слой + записываемый слой поверх). Один образ можно запустить много раз - получится несколько контейнеров. В Go собирают образ из Dockerfile (COPY бинарника или multi-stage build с компиляцией внутри).

FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o /server .
FROM scratch
COPY --from=builder /server /server
ENTRYPOINT ["/server"]
Открыть отдельно →
3 Как работает кеширование слоев в Docker?

Каждая инструкция в Dockerfile создает слой. Слои кешируются по хешу контекста; при изменении инструкции или файлов выше по контексту все последующие слои пересобираются. Поэтому копирование go.mod и go.sum и go mod download до COPY кода - частый паттерн: зависимости кешируются отдельно от кода. В Go multi-stage: слой с go build пересобирается при изменении кода, базовый образ и зависимости - из кеша.

COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o app .
Открыть отдельно →
4 Зачем multi-stage build для Go-приложения?

Multi-stage - несколько этапов в одном Dockerfile; итоговый образ содержит только артефакт последнего этапа. В первом этапе компилируют Go-бинарник (нужен golang образ), во втором копируют только бинарник в минимальный образ (scratch, alpine). Итог: маленький образ без компилятора и исходников, быстрый деплой и меньше поверхность атак.

FROM golang:1.21 AS build
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o server .
FROM alpine:3.19
COPY --from=build /app/server /server
EXPOSE 8080
CMD ["/server"]
Открыть отдельно →
5 Что такое Docker Compose? Типичный docker-compose для Go-сервиса.

Compose описывает мультиконтейнерное приложение: сервисы, сети, тома. Один файл docker-compose.yml, запуск docker compose up. Для Go: сервис с билдом из Dockerfile или образом, порты, переменные окружения, зависимости (postgres, redis). Удобно для локальной разработки и тестов.

services:
  app:
    build: .
    ports: ["8080:8080"]
    environment:
      DATABASE_URL: postgres://user:pass@db:5432/app
    depends_on: [db]
  db:
    image: postgres:16
    environment: POSTGRES_PASSWORD: pass
    volumes: [pgdata:/var/lib/postgresql/data]
Открыть отдельно →
6 Что такое health check в Docker?

HEALTHCHECK в Dockerfile или compose - команда, которая периодически проверяет, что контейнер жив. По результату (exit 0 - healthy, 1 - unhealthy) Docker помечает контейнер. В Go приложение отдает HTTP endpoint /health (проверка БД, зависимостей) или выполняет легкую логику. Оркестраторы (Kubernetes) используют те же проверки через probes.

HEALTHCHECK --interval=30s --timeout=3s CMD wget -q -O- http://localhost:8080/health || exit 1
Открыть отдельно →
7 Основы Kubernetes. Pod, Deployment, Service, Ingress.

Pod - минимальная единица запуска (один или несколько контейнеров, общая сеть/тома). Deployment - декларативное управление репликами Pod (rolling update, откат). Service - стабильный сетевой доступ к набору Pod (ClusterIP, NodePort, LoadBalancer). Ingress - маршрутизация HTTP/HTTPS снаружи к сервисам (хосты, пути). В Go деплоят образ в Pod через Deployment; Service дает DNS имя; Ingress - внешний доступ.

Открыть отдельно →
8 Что такое Pod в Kubernetes?

Pod - группа контейнеров с общими сетевым namespace и томами. Обычно один контейнер на Pod (например, Go-сервис). Pod имеет IP в сети кластера, живет на ноде; при падении или пересоздании получает новый IP. В манифесте задают образ, порты, ресурсы (requests/limits), переменные окружения, probes.

spec:
  containers:
  - name: app
    image: myregistry/app:v1
    ports: [{containerPort: 8080}]
    livenessProbe:
      httpGet: {path: /health, port: 8080}
Открыть отдельно →
9 Probes в Kubernetes: liveness, readiness, startup.

Liveness - контейнер жив; при неудаче kubelet перезапускает контейнер. Readiness - контейнер готов принимать трафик; при неудаче Pod убирается из Service. Startup - для медленного старта; до первой успешной проверки liveness/readiness не считаются проваленными. В Go реализуют HTTP endpoint (например /health, /ready) или exec-проверку. Важно: readiness не должен падать при временной потере БД, иначе все Pod перестанут получать трафик.

livenessProbe:
  httpGet: {path: /health, port: 8080}
  initialDelaySeconds: 5
readinessProbe:
  httpGet: {path: /ready, port: 8080}
Открыть отдельно →
10 Что такое Helm? Зачем в Go-проектах?

Helm - пакетный менеджер для Kubernetes: шаблонизация манифестов (values.yaml), версионирование релизов, откат. Chart - каталог с templates и values. В Go-проектах образ упаковывают в chart; один chart может описать Deployment, Service, Ingress, ConfigMap. Удобно для деплоя в разные окружения (dev/stage/prod) подстановкой values.

helm install myapp ./chart -f values-prod.yaml
helm upgrade myapp ./chart --set image.tag=v2
Открыть отдельно →
11 ConfigMap и Secret в Kubernetes. Использование в Go.

ConfigMap - непроекрипционные данные (конфиг, URL). Secret - чувствительные данные (пароли, ключи), хранятся base64. Подключают как переменные окружения или файлы (volumeMounts). В Go читают из env (os.Getenv) или из смонтированного файла. Не коммитить секреты в репозиторий; использовать внешние хранилища (Vault) или CI-секреты при установке.

env:
- name: DATABASE_URL
  valueFrom:
    secretKeyRef: {name: app-secrets, key: database-url}
Открыть отдельно →
12 Что такое HPA (Horizontal Pod Autoscaler)?

HPA автоматически масштабирует число реплик Deployment по метрикам (CPU, memory, custom). Задают min/max реплик и целевое использование (например, 70% CPU). В Go приложение должно отдавать метрики в формате, который собирает метрик-сервер (обычно стандартные cAdvisor метрики с нод). Для кастомных метрик нужен адаптер (Prometheus adapter и т.п.).

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  scaleTargetRef: {apiVersion: apps/v1, kind: Deployment, name: app}
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource: {name: cpu, target: {type: Utilization, averageUtilization: 70}}
Открыть отдельно →
13 Что такое sidecar-контейнер в Pod?

Sidecar - дополнительный контейнер в том же Pod, который дополняет основной (логирование, прокси, синхронизация). Общая сеть: localhost между контейнерами; общие тома для обмена файлами. Примеры: envoy как прокси, fluentd для логов, init-контейнер для миграций перед стартом приложения. В Go-сервисе основной контейнер - бинарник; sidecar - отдельный образ.

containers:
- name: app
  image: myapp
- name: envoy
  image: envoyproxy/envoy
  # проксирует трафик к app
Открыть отдельно →
14 Namespace в Kubernetes. Зачем использовать?

Namespace - виртуальное разделение ресурсов внутри кластера (не изоляция сети по умолчанию). Удобно для окружений (dev, staging, prod) или команд. Ресурсы (Deployment, Service) принадлежат namespace; DNS внутри namespace - по короткому имени сервиса. В Go имена сервисов в конфиге могут включать namespace (svc.namespace.svc.cluster.local) или использовать короткое имя в том же namespace.

kubectl get pods -n production
kubectl create namespace staging
Открыть отдельно →
15 DaemonSet и StatefulSet. Когда применять?

DaemonSet - по одному Pod на каждой ноде (агенты, сбор логов, сетевые плагины). StatefulSet - стабильная идентичность Pod (имена pod-0, pod-1), стабильные тома при пересоздании, порядок деплоя и масштабирования. Для обычного Go-сервиса без состояния используют Deployment. StatefulSet - для БД, очередей с привязкой к диску; DaemonSet - для агентов на нодах.

Открыть отдельно →
16 Volumes в Kubernetes. Типы и использование.

Volume - каталог, доступный контейнеру в Pod. emptyDir - временный, живет пока Pod жив. persistentVolumeClaim - привязка к PVC и диску (сохраняется при пересоздании Pod). configMap/secret - монтирование конфига или секрета как файлы. В Go приложение читает конфиг из смонтированного тома или из env; для состояния (файлы, SQLite) используют PVC.

volumes:
- name: config
  configMap: {name: app-config}
volumeMounts:
- name: config
  mountPath: /etc/app
Открыть отдельно →
17 Resource requests и limits. Влияние на Go-приложение.

requests - гарантированные ресурсы для планирования (scheduler учитывает при размещении Pod). limits - верхняя граница; при превышении CPU throttling, memory - OOMKill. Для Go важно задать разумный memory limit (heap + другие аллокации); при нехватке контейнер убивается. GOMEMLIMIT можно выставить под limit, чтобы GC не дал процессу вырасти выше лимита. CPU request/limit влияют на планировщик и долю CPU.

resources:
  requests: {memory: "128Mi", cpu: "100m"}
  limits:   {memory: "512Mi", cpu: "500m"}
Открыть отдельно →
18 Rolling update и recreate. Стратегия деплоя в Kubernetes.

Rolling update - постепенная замена старых Pod новыми (maxSurge, maxUnavailable). Без даунтайма, откат через kubectl rollout undo. Recreate - все старые Pod убиваются, затем создаются новые; даунтайм есть. По умолчанию Deployment использует RollingUpdate. В Go приложение должно корректно завершаться по SIGTERM (graceful shutdown) и не держать долгие соединения без возможности дождаться дренажа.

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0
Открыть отдельно →
19 Best practices: Go-приложение в Docker.

1) Multi-stage build: итоговый образ только с бинарником. 2) Минимальный базовый образ (scratch, alpine, distroless). 3) Не root пользователь (USER в Dockerfile). 4) Один процесс на контейнер. 5) Health endpoint для liveness/readiness. 6) Graceful shutdown по SIGTERM. 7) Конфиг через env или смонтированные файлы, не хардкод. 8) Версия образа по тегу (не latest в проде). 9) CGO_ENABLED=0 для статической сборки где возможно.

RUN adduser -D -g '' appuser
USER appuser
ENTRYPOINT ["/app/server"]
Открыть отдельно →
20 Что такое distroless образы? Зачем для Go?

Distroless - образы без shell, пакетного менеджера и лишних утилит. Минимальная поверхность атак и размер. Для статического Go-бинарника подходит образ на базе scratch или gcr.io/distroless/static. Отладка сложнее (нет shell) - при необходимости временно переключаются на alpine. Идеально для production Go-сервисов.

FROM gcr.io/distroless/static-debian12
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
Открыть отдельно →
🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.