Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go modules in production [RUS]

Go modules in production [RUS]

Прошёл почти год с релиза Go Modules - новой системы работы с зависимостями.

OZON использует модули в production ещё с пре-релизных версий vgo.
Я хочу рассказать о нашем опыте жизни в мире модулей, ньюансах работы с Athens и Gitlab и отвечу на вопрос, в чём же профит их использования.

Ivan Korolev

July 20, 2019
Tweet

More Decks by Ivan Korolev

Other Decks in Programming

Transcript

  1. go toolchain Изменения в тулчейне: - 1.11 внедрение модулей, работа

    вне GOPATH 
 изменение get, build, run, test, install, list, ...
  2. go toolchain Изменения в тулчейне: - 1.11 внедрение модулей, работа

    вне GOPATH 
 изменение get, build, run, test, install, list, ... - 1.12 багфиксы директива go в go.mod
  3. Директива go в go.mod $ cat <<EOF > hello.go package

    main import "fmt" func main() { fmt.Println("hello") } EOF
  4. Директива go в go.mod $ cat <<EOF > hello.go package

    main import "fmt" func main() { fmt.Println("hello") } EOF $ go version && go mod init example.com/foo/bar go version go1.12.1 darwin/amd64
  5. Директива go в go.mod $ cat <<EOF > hello.go package

    main import "fmt" func main() { fmt.Println("hello") } EOF $ go version && go mod init example.com/foo/bar go version go1.12.1 darwin/amd64 $ cat go.mod module example.com/foo/bar go 1.12
  6. Директива go в go.mod $ gvm use go1.11.3 Now using

    version go1.11.3 $ go build go build example.com/foo/bar: module requires Go 1.12
  7. Директива go в go.mod $ gvm use go1.11.3 Now using

    version go1.11.3 $ go build go build example.com/foo/bar: module requires Go 1.12 $ gvm use go1.11.4 Now using version go1.11.4 $ go build
  8. Директива go в go.mod $ gvm use go1.11.3 Now using

    version go1.11.3 $ go build go build example.com/foo/bar: module requires Go 1.12 $ gvm use go1.11.4 Now using version go1.11.4 $ go build $ echo "BAD COMPILE" >> hello.go $ go build # example.com/foo/bar .\hello.go:12:1: syntax error: non-declaration statement outside function body note: module requires Go 1.12
  9. go toolchain Изменения в тулчейне: - 1.11 внедрение модулей, работа

    вне GOPATH 
 изменение get, build, run, test, install, list, ... - 1.12 багфиксы директива go в go.mod - 1.13 GO111MODULE=auto - модули в GOPATH
 Много изменений

  10. Переработка go get -u • go get -u <packages> -

    нет обновлений транзитивных зависимостей • go get -u обновляет зависимости текущего пакета • go get -u all обновляет зависимости модуля • go get -u -t обновит ещё и тесты • go get -u <module>@patch обновление до патча Эквивалентно go get -u=patch Подробности - #32846
  11. go.mod - псевдоверсии $ cat /home/gopher/foo/bar/go.mod module github.com/foo/bar go 1.12

    require ( github.com/kr/pretty v0.1.0 github.com/sirupsen/logrus v1.4.1 github.com/utrack/clay/v2 v2.3.9 github.com/go-chi/chi v4.0.2+incompatible golang.org/x/tools v0.0.0-20190511041617-99f201b6807e // indirect github.com/foo/buz v0.18.1-0.20190717141926-407f5697e69d )
  12. go.mod - псевдоверсии В go1.13 добавили валидацию псевдоверсий - #27173

    Проблема - не было проверки псевдоверсия <-> тэг require a.com/foo/bar v1.0.0-20180819111657-1c088dc8b6d3 require a.com/foo/bar v1.7.0-alpha.0.20180819111657-1c088dc8b6d3 require a.com/foo/bar v1.9.0-alpha.0.20180819111657-1c088dc8b6d3
  13. go.mod - псевдоверсии Типы псевдоверсий: • vX.0.0-yyyymmddhhmmss-abcdefabcdef
 нет мажора •

    vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
 в дереве существует vX.Y.Z-pre
  14. go.mod - псевдоверсии Типы псевдоверсий: • vX.0.0-yyyymmddhhmmss-abcdefabcdef
 нет мажора •

    vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
 в дереве существует vX.Y.Z-pre • vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef 
 в дереве существует vX.Y.Z Лучшее средство - указать хэш + go mod tidy
  15. go mod go mod <command> [arguments] init инициализация модуля tidy

    добавление/удаление импортов vendor копия зависимостей в ./vendor download скачивает модули в кэш verify проверка хэш-сумм edit редактирование go.mod скриптами why объясняет, откуда та или иная зависимость graph печатает граф зависимостей
  16. go mod why require github.com/pelletier/go-toml v1.4.0 // indirect require golang.org/x/text

    v0.0.0-20190308202827-9d24e82272b4 // indirect "Зачем мне эта зависимость?"
  17. go mod why go mod why [-m] [-vendor] packages... Выдаёт

    кратчайший путь в графе импортов. -vendor исключает анализ тестов зависимостей $ go mod why golang.org/x/text go: finding golang.org/x/text latest # golang.org/x/text (main module does not need package golang.org/x/text)
  18. go mod why $ go mod why -m golang.org/x/text #

    golang.org/x/text/language rsc.io/quote rsc.io/sampler golang.org/x/text/language
  19. Вложенные модули . |-- go.mod |-- b | |-- go.mod

    | `-- b.go `-- a |-- go.mod `-- a.go 
 git tag a/v1.0.1 git tag b/v1.1.0
  20. Использование • отделить мусорные зависимости (example, integration) • монорепы •

    единый репозиторий библиотек (общий CI) • библиотека + бинари вокруг неё (etcd, vault)
  21. Использование • отделить мусорные зависимости (example, integration) • монорепы •

    единый репозиторий библиотек (общий CI) • библиотека + бинари вокруг неё (etcd, vault) • общий интерфейс + разделение зависимостей
  22. Использование • отделить мусорные зависимости (example, integration) • монорепы •

    единый репозиторий библиотек (общий CI) • библиотека + бинари вокруг неё (etcd, vault) • общий интерфейс + разделение зависимостей • микросервис + клиентская либа
  23. Vault module github.com/hashicorp/vault go 1.12 replace github.com/hashicorp/vault/api => ./api //

    Клиент replace github.com/hashicorp/vault/sdk => ./sdk // Плагины require ( cloud.google.com/go v0.39.0 github.com/Azure/azure-sdk-for-go v29.0.0+incompatible github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-autorest v11.7.1+incompatible ... )
  24. handler.go type Handler interface { http.Handler AddLivenessCheck(name string, check Check)

    AddReadinessCheck(name string, check Check) // ... } // Check is a liveness/readiness check. type Check func() error
  25. postgres go.mod module gitlab.ozon.ru/platform/healthcheck-go/checker/db/postgres replace gitlab.ozon.ru/platform/healthcheck-go => ../../../ require (

    github.com/lib/pq v0.0.0-20180523175426-90697d60dd84 gitlab.ozon.ru/platform/healthcheck-go v0.4.0 )
  26. postgres.go package postgres import ( "context" "database/sql" "time" "gitlab.ozon.ru/platform/healthcheck-go" "gitlab.ozon.ru/platform/healthcheck-go/checker/db/internal"

    "github.com/lib/pq" ) // PingCheckByDb returns a Check that validates connectivity to a // database/sql.DB using Ping(). func PingCheckByDb(db *sql.DB, timeout time.Duration) healthcheck.Check { return internal.DatabasePingCheck(db, timeout) }
  27. Микросервисы • зависимости сервиса отдельно от клиентских • тэги либы

    - SemVer
 тэги сервиса - release/2019-07-20 • бонус - версионирование .proto
 $GOPATH/pkg/mod/.../pkg/[email protected]/metatarifficator.proto
  28. Вложенные модули Осторожно: • replace - модификация локального дерева зависимостей

    • не забыть про сборку и тестирование всех подмодулей в CI
 go test ./... тестирует только текущий модуль replace github.com/hashicorp/vault/sdk => ./sdk require github.com/hashicorp/vault/sdk v0.1.12
  29. GitLab - кэширование сборок .gitlab-ci.yml build: cache: key: "go-modules-cache" paths:

    - .cache/go/pkg/mod/cache/download - .cache/gocache/*/* - .cache/gocache/trim.txt before_script: - export GOPATH=${CI_PROJECT_DIR}/.cache/go - export GOCACHE=${CI_PROJECT_DIR}/.cache/gocache #25323, fixed in go1.13 - $GOCACHE/log.txt рос бесконтрольно
  30. GitLab subgroups $ curl -s https://gitlab.com/group/sub-group/repo?go-get=1 <!DOCTYPE html> <html> <head>

    <meta content='gitlab.com/group/sub-group git https:// gitlab.com/group/sub-group.git' name='go-import'> </head> </html> https://gitlab.com/gitlab-org/gitlab-ce/issues/30785
  31. GitLab subgroups Костыли в go.mod require gitlab.ozon.ru/lms/go/service/platform/tsmr/pkg/reader v0.0.2 ... replace

    gitlab.ozon.ru/lms/go/service/platform/tsmr/pkg/reader => gitlab.ozon.ru/ lms/go/service/platform/tsmr.git/pkg/reader v0.0.2 * Уже запилили поддержку .netrc в GitLab и в go 1.13 #29888
  32. GOPROXY • Ускорение сборок • Защита от: • отключения интернета

    • удаления / force push зависимостей • РКН :) • Настройка исключений через GOPRIVATE и GONOPROXY
  33. GOPROXY proxy.golang.org - глобальное зеркало GOPROXY=proxy.example.com,https://proxy.golang.org,direct Опрос в прямом порядке,

    пока не ответит 200 или до direct
 Если ответил 404 или 410 - идём в следующий proxy
 Иначе - ошибка скачивания зависимостей ¯\_(ツ)_/¯ GOPRIVATE=*.corp.example.com,rsc.io/private (или GONOPROXY) Позволяет настроить исключения для проксирования
  34. GOPROXY Пример из документации: GOPRIVATE=*.corp.example.com GOPROXY=proxy.example.com GONOPROXY=none Приватные репы -

    в под-домене corp.example.com Но GONOPROXY=none магически заставляет использовать proxy.example.com
  35. GOSUMDB sum.golang.org - глобальная БД чексумм Защита обновлений через go

    get -u GOSUMDB=sum.golang.org GOSUMDB=off GONOSUMDB=*.corp.example.com,rsc.io/private GOPRIVATE - общие исключения для PROXY и SUMDB
  36. Proxy Альтернативные публичные прокси - https://goproxy.io/ Коробочные решения: • Athens

    - https://docs.gomods.io/ • Artifactory - https://jfrog.com/artifactory/ • github.com/goproxy/goproxy
  37. Athens • первый и самый популярный • настройки приватных репозиториев,

    доступа наружу и исключений • работает поверх go get - имеет все болячки и плюшки • поддержка .netrc
  38. Мифы • go.sum и GOSUMDB не нужны? - Repeatable build

    • сложно откатывать зависимости! - replace и коммуникация
  39. Мифы • go.sum и GOSUMDB не нужны? - Repeatable build

    • сложно откатывать зависимости! - replace и коммуникация • yet another standard? - Смиритесь, за модулями будущее
  40. Мифы • go.sum и GOSUMDB не нужны? - Repeatable build

    • сложно откатывать зависимости! - replace и коммуникация • yet another standard? - Смиритесь, за модулями будущее • сложность установки бинарей. - Уже стало лучше GO111MODULE=on go get golang.org/x/tools/[email protected]
  41. Нерешённые проблемы • глобальная установка бинарей - #30515 • tools.go

    - "официальный костыль" // +build tools package tools import ( _ "golang.org/x/tools/cmd/stringer" )
  42. Что на выходе • поддержка в экосистеме • скорость работы

    • повторяемость сборок • безопасность и контроль • гибкость разработки - вложенные модули • универсальность решения (бинарные зависимости, proto- файлы)