Irbisa · Шпаргалка
Go в проде
Docker multi-stage, конфиг и секреты, graceful shutdown, health и readiness, лимиты ресурсов и GOMAXPROCS в контейнере, миграции
Что такое контейнер, чем он отличается от виртуальной машины и что дают ему namespaces и cgroups?
Что делают Pod, Deployment, Service и ConfigMap и как Go-сервис проходит путь от образа до приёма трафика в Kubernetes?
apiVersion: apps/v1kind: Deploymentmetadata: name: ordersspec: replicas: 3 # keep three Pods of this version running…Как Go-сервис должен получать конфигурацию, что говорит о ней 12-factor app и что происходит, если обязательного значения нет?
type Config struct { Addr string DatabaseURL string // a secret: never log it ShutdownTimeout time.Duration}…Чем отличаются
SIGTERM,SIGINTиSIGKILLи какие из них Go-программа может перехватить?Почему Go-контейнер должен работать не от root и как это настроить на
scratchили distroless?# Dockerfile: USER 65532:65532 (numeric, so runAsNonRoot can verify it)spec: securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532…Контейнер на базе Alpine стартует через
entrypoint.sh, который читает секрет и запускает/app/server. Теперь поды останавливаются все 30 с и не пишут лог shutdown. Почему?#!/bin/sh# entrypoint.shset -euDB_PASSWORD="$(cat /run/secrets/db-password)"export DB_PASSWORD…Почему секреты нельзя зашивать в образ контейнера и как Go-сервис должен получать их вместо этого: при сборке и в рантайме?
# syntax=docker/dockerfile:1FROM golang:1.25 AS buildWORKDIR /srcENV GOPRIVATE=github.com/acme/*COPY go.mod go.sum ./# wrong: ARG GITHUB_TOKEN, then RUN git config ... $GITHUB_TOKEN…Что
-ldflags="-s -w"вырезает из Go-бинарника и что после этого продолжает работать: стектрейсы паник,pprof, Delve?Найдите баг в этом graceful shutdown: при
SIGTERMзапросы, которые сейчас обрабатываются, всё равно обрываются.func run(h http.Handler, db *sql.DB) error { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM) defer stop() srv := &http.Server{Addr: ":8080", Handler: h, ReadHeaderTimeout: 5 * time.Second} go func() { <-ctx.Done() sctx, cancel := context.WithTimeout(context.Background(), 25*time.Second) defer cancel() srv.Shutdown(sctx) }() if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { return err } return db.Close()}Найдите баг: при раскатке поды убиваются с кодом 137 посреди дренажа, и
Shutdownтак и не завершается.spec: terminationGracePeriodSeconds: 30 containers: - name: api image: registry.example.com/api:1.5.0 env: - name: SHUTDOWN_TIMEOUT # the context deadline passed to srv.Shutdown value: "25s" lifecycle: preStop: sleep: seconds: 30 # wait until the load balancer stops sending trafficКак безопасно открыть
pprofна продовом сервисе и что атакующий может сделать с открытым/debug/pprof/?import "net/http/pprof" // its init also registers on http.DefaultServeMux func adminServer() *http.Server { mux := http.NewServeMux() mux.HandleFunc("/debug/pprof/", pprof.Index) mux.HandleFunc("/debug/pprof/profile", pprof.Profile)…Под перезапускается с
OOMKilledи кодом выхода 137, а в логах Go пусто. Что произошло и чем это отличается от падения Go сout of memory?Как Horizontal Pod Autoscaler решает, сколько подов запустить, и почему CPU служит плохим сигналом для масштабирования I/O-bound Go API или Kafka-консьюмера?
apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: apispec: scaleTargetRef:…Что должен запускать CI-пайплайн Go-сервиса, в каком порядке и что делает его быстрым (кэши модулей и сборки, шардирование тестов)?
on: pull_request: push: branches: [main]jobs: checks: # seconds: fail before anything slow starts…Чем отличаются rolling, blue-green и canary деплой и что должен поддерживать Go-сервис, чтобы любой из них проходил без простоя?
Запускать миграции БД при старте сервиса или отдельным шагом деплоя, и что ломается в каждом варианте?
Десять реплик запускают одну и ту же часовую задачу на
time.Ticker, и отчёт уходит десять раз. Как выполнять периодическую работу ровно один раз?// Every replica ticks once a minute and calls hourly. The first one to claim// the hour runs the job; the other nine see the claim and skip.func hourly(ctx context.Context, db *sql.DB, job string, run func(context.Context, time.Time) error) error { period := time.Now().UTC().Truncate(time.Hour) // the run's identity: "the 13:00 report" res, err := db.ExecContext(ctx, ` INSERT INTO job_runs (job, period) VALUES ($1, $2)…Как readiness управляет rolling update и как сделать так, чтобы сломанный релиз останавливался на первых подах, а не заменял весь парк?
apiVersion: apps/v1kind: Deploymentmetadata: name: apispec: replicas: 10…За балансировщиком Go-сервис вызывает редкие
502при любой нагрузке, и ни один не виден в его собственных логах. Как к этому приводитIdleTimeoutи как это исправить?Как задать requests и limits по CPU и памяти для Go-сервиса в Kubernetes и что происходит с
GOMAXPROCSиGOMEMLIMIT, если убрать лимит по CPU?containers: - name: api image: registry.example.com/api:1.5.0 resources: requests: cpu: "2"…Сервис держит HTTP API, Kafka-консьюмер, фоновые воркеры и пул БД. В каком порядке их останавливать по
SIGTERMи почему?// Shutdown(ctx) stops taking new work and waits for work already taken.type drainer interface{ Shutdown(ctx context.Context) error } func drain(srv *http.Server, consumer, workers, producer, telemetry drainer, db *sql.DB) error { ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) defer cancel()…