Два вопроса возникают у любого сервиса, как только он выходит за пределы «работает на моём ноутбуке»: где хранить секреты (пароли к базе, ключи, токены) и как понять, что происходит внутри, когда что-то идёт не так. Первое — про безопасность, второе — про наблюдаемость. В GCP под каждую задачу есть сервис. Доступ ко всем ним выдаётся через Cloud IAM.
Секреты и наблюдаемость закрывают четыре сервиса, и ко всем приложение ходит по сервисному аккаунту. Из записей журнала делают метрики, из метрик оповещения, а связывает всё идентификатор трассы в каждой записи.
Secret Manager
Secret Manager — управляемое хранилище секретов: паролей, ключей, токенов. Идея простая: секреты не живут в коде, в конфигах и в git, а лежат в Secret Manager, откуда приложение забирает их по правам своего сервисного аккаунта.
Зачем так, а не «положить пароль в переменную окружения и забыть»:
- секрет в одном месте, а не размазан по десяти конфигам и репозиториям;
- доступ к нему выдаётся ролями IAM: отобрать право читать пароль так же просто, как выдать;
- секреты версионируются: новую версию заводят рядом со старой, переключаются на неё и при беде откатываются — не переклеивая пароль по всем сервисам руками.
Две вещи Secret Manager не делает, хотя от него их обычно ждут.
Первая — он не меняет пароль за вас. Расписание ротации у него есть, но это расписание напоминаний: в назначенный срок сервис кидает сообщение в тему Pub/Sub, мол, пора. Сходить в базу, завести новый пароль, положить его новой версией секрета и переключить потребителей — ваша работа, обычно её делает обработчик, подписанный на эту тему. Если вы пришли из AWS, где у Secrets Manager ротация встроенная, ожидание придётся поправить: здесь автоматики нет, есть будильник.
Вторая — по умолчанию не видно, кто читал секрет. Чтения попадают в журналы доступа к данным (Data Access audit logs), а они в GCP выключены и включаются отдельно. Хотите знать, кто и когда взял пароль, — включайте их заранее, а не в день разбора инцидента.
Правило новичку: любой пароль или ключ, попавший в git, считается скомпрометированным. Даже если удалить его следующим коммитом — он останется в истории. Secret Manager снимает соблазн «просто захардкодить».
Как секрет попадает в приложение
Хранилище секретов заведено — остаётся решить, в какой момент приложение берёт значение, потому что от этого зависит поведение при смене пароля.
При старте. Значение читается один раз и живёт в памяти. Самый дешёвый способ (одно обращение на запуск) и правильный для пароля базы: пул соединений всё равно создаётся один раз. Цена: смена секрета не доезжает без перезапуска.
При каждом обращении. Честно свежее значение, но каждое чтение — платный вызов и лишние миллисекунды. Для ключа, который используется в каждом запросе, это заметно.
С кэшем на несколько минут. Золотая середина: значение держится в памяти и обновляется по истечении срока. Смена секрета доезжает за минуты без перезапуска, обращений немного.
Что происходит при смене версии на живом сервисе. У секрета есть версии: добавление новой не отменяет прежнюю. Если приложение читает latest, оно получит новую версию при следующем чтении — то есть при перезапуске или по истечении кэша. Если читает конкретную версию, ничего не изменится, пока вы не поправите настройку.
Отсюда рабочая схема смены пароля базы: добавить новую версию секрета → у базы одновременно действуют два пароля (или две учётные записи) → выкатить приложение, которое читает новую версию → отключить прежний пароль → отключить старую версию секрета. Тогда простоя нет вовсе, а «читается при старте» перестаёт быть проблемой.
И две практические детали: версии секрета стоит отключать, а не удалять (отключённую можно вернуть, удалённую нет), и число хранимых версий ограничивают — иначе через год их сотня, и непонятно, какая действует.
Cloud KMS
Диск и так шифруется, но ключом Google, а аудитор требует, чтобы ключ был ваш и его можно было отозвать. Этим занимается Cloud KMS (Key Management Service). Тут важно не смешать два разных вопроса. Шифруются ли ваши данные в облаке — да, всегда: всё хранимое Google шифрует своими ключами по умолчанию, включать ничего не нужно. KMS отвечает на другой вопрос — чей это ключ. Он позволяет завести собственный ключ и шифровать им диски, бакеты, базы (такую схему называют CMEK): ключ лежит в KMS, доступ к нему — отдельное право IAM, и, отобрав это право, вы отрезаете доступ к данным независимо от прав на сами данные. Берут это, когда так требует регламент или когда нужно уметь «выключить» данные одним движением.
Cloud Logging и Cloud Monitoring
Эти сервисы (исторически известные как Stackdriver, теперь Cloud Operations) закрывают наблюдаемость.
Cloud Logging собирает логи со всех ресурсов в одно место, где их можно искать и фильтровать. Управляемые платформы — Cloud Run, Cloud Functions, GKE — пишут туда сами: всё, что сервис вывел в стандартный поток, оказывается в Logging. А вот на обычной виртуальной машине Compute Engine само ничего не поедет: пока на неё не поставлен агент (Ops Agent), логи вашего приложения остаются лежать на диске машины, и в консоли их не будет. Обычно об этом узнают в тот момент, когда ищут логи упавшего запроса. Практический совет: пишите логи структурированно (с полями — уровень, идентификатор запроса, сервис), а не сплошным текстом — по структурированным логам можно искать и строить фильтры.
Cloud Monitoring показывает картину во времени — метрики (загрузку процессора, задержку, число ошибок), из которых собирают дашборды и алерты — правила вида «если ошибок больше стольки-то за минуту — разбудить дежурного». А Cloud Trace показывает, как запрос проходит сквозь сервисы, и где именно тормозит.
Ключевая мысль для новичка: наблюдаемость нужна до аварии, а не после. Метрики и алерты, настроенные заранее, превращают «пользователи жалуются, а мы не понимаем почему» в «нам пришло уведомление, и мы уже чиним». Общие правила логирования не зависят от облака — их разбирает Observability style guide.
Audit Logs и Security Command Center
Cloud Audit Logs пишет журнал действий — только это не один журнал, а два разных, и разницу между ними лучше знать до инцидента, а не после:
- Admin Activity — кто создал, изменил или удалил ресурс, кто поменял права. Включён всегда, выключить его нельзя, платить за него не надо. Это он отвечает на вопрос «откуда взялся этот публичный бакет?»;
- Data Access — кто читал и писал сами данные: скачал объект из бакета, прочитал секрет, сходил в базу. По умолчанию выключен (исключение — BigQuery), включается адресно по сервисам, и за объём этих логов вы платите.
Отсюда практический вывод: на вопрос «кто трогал инфраструктуру» журнал ответит всегда, а на вопрос «кто унёс данные» — только если вы включили вторую половину заранее.
Security Command Center оценивает состояние безопасности: находит открытые наружу ресурсы, слабые настройки, уязвимости и подсказывает, что исправить.
Где это применяется
Эта связка — секреты в Secret Manager, шифрование на KMS, логи в Cloud Logging, метрики и алерты в Cloud Monitoring — базовый гигиенический минимум любого боевого сервиса. Без неё сервис вроде бы работает, но при первой же проблеме вы оказываетесь слепы.
Типичные ошибки новичков:
- хранят пароли в коде или конфигах вместо Secret Manager;
- логируют бессистемно — сплошным текстом, без идентификатора запроса, и потом ничего не находят;
- настраивают наблюдаемость после первой аварии, а не до неё;
- логируют секреты и персональные данные — и утечка переезжает в логи.
Глубже: журналы стоят денеграсширенное
Самая частая неожиданность в счёте за наблюдаемость, и она устроена так.
Платят за приём записей сверх бесплатного объёма (у журналов это порядка 50 гигабайт на проект в месяц бесплатно, дальше — около полудоллара за гигабайт). Хранение сверх срока по умолчанию тоже платное.
Срок хранения по умолчанию у основного журнала — 30 дней; у журнала административного аудита он дольше (около 400 дней) и не тарифицируется. То есть обычные логи приложения живут месяц, если не настроить иначе.
Что раздувает объём: отладочный уровень в боевом контуре, журналирование тел запросов, подробные журналы платформы (записи о сетевых потоках, журналы правил фильтрации, журналы доступа к данным), и журналы кластера Kubernetes, если включить в них всё.
Три рычага, которые сокращают счёт в разы:
Исключения (exclusion filters). Правило, которое отбрасывает записи до приёма — то есть они не тарифицируются вовсе. Исключают шум: успешные проверки работоспособности, служебные обращения балансировщика, отладочные записи в боевом контуре.
gcloud logging sinks update _Default --add-exclusion=name=drop-health,\
filter='resource.type="cloud_run_revision" AND httpRequest.requestUrl:"/health"'
Отвод в дешёвое хранилище (sinks). То, что нужно хранить долго (аудит, события безопасности), отправляют в хранилище объектов или в аналитическое хранилище: там гигабайт стоит в десятки раз дешевле. Поиск по такому архиву медленнее, зато год хранения перестаёт быть проблемой.
Срок хранения по журналам. Для разных журналов настраивают свои сроки: неделя-две для стендов, месяц для приложений, дольше — только там, где требует регулятор.
И то, что стоит сделать в первый же день: посмотреть, сколько вы принимаете. В отчёте по затратам это отдельная позиция, а в самом сервисе есть панель с разбивкой объёма по источникам — обычно выясняется, что 80 % объёма даёт один-два источника.
Глубже: метрики на основе логов: мостик к оповещениямрасширенное
Совет «настраивайте оповещения заранее» превращается в действие, когда есть механизм, который делает из записей в журнале число: это метрики на основе логов.
Идея простая: вы описываете фильтр, а платформа считает, сколько записей ему соответствует, — и получается обычная метрика, на которую можно построить график и оповещение.
gcloud logging metrics create payment_failures \
--description="Отказы платежей" \
--log-filter='resource.type="cloud_run_revision" AND jsonPayload.event="payment_failed"'
Дальше на эту метрику ставят правило: «больше десяти за пять минут — оповестить». То есть путь от «мы это логируем» до «нас об этом предупредят» оказывается коротким и не требует отдельной системы метрик.
Два вида таких метрик. Счётчик — сколько записей подошло под фильтр (отказы, исключения, определённые события). Распределение — числовое значение, извлечённое из записи (длительность операции, размер пачки): по нему считаются процентили.
Практическая польза, из-за которой этим пользуются: бизнес-события часто есть только в журнале — «платёж отклонён», «заказ отменён пользователем», «повтор списания». Заводить под каждое отдельную метрику в коде долго, а фильтр по журналу пишется за минуту. Правило: если в журнале есть структурированное поле, из него можно сделать оповещение.
Оговорка про стоимость: сами метрики на основе логов тарифицируются отдельно от приёма, и метрика с большим числом меток (например, с идентификатором пользователя) даёт множество временных рядов и заметный счёт. В метках держат только значения из короткого списка.
Глубже: трассировка: доля запросов и сквозной идентификаторрасширенное
Про трассировку сказано одним предложением, и ей нужны две детали.
Не все запросы отслеживаются. Собирать трассы для каждого запроса дорого и не нужно: обычно берут выборку — долю запросов (проценты) плюс все запросы с ошибками и все медленные. Настраивается это в библиотеке трассировки; значение по умолчанию у части библиотек очень низкое (десятые доли процента), и это первое, что стоит проверить, если «трассы почему-то пустые».
Трассировка требует сквозного идентификатора. Он передаётся заголовком между сервисами: в GCP это исторически X-Cloud-Trace-Context, в стандарте OpenTelemetry — traceparent. Библиотека читает его на входе и добавляет к исходящим вызовам; если хоть один сервис в цепочке этого не делает, трасса обрывается.
И главная связка, ради которой всё это: идентификатор трассы попадает в записи журнала. Тогда запрос из журнала открывается как трасса, а трасса — как набор записей. В структурированной записи для этого есть специальное поле (logging.googleapis.com/trace), и библиотеки заполняют его сами, если трассировка подключена.
Практический минимум: подключить трассировку с выборкой 5–10 % плюс все ошибки, убедиться, что идентификатор попадает в журнал, и возвращать его клиенту в заголовке ответа — тогда обращение пользователя превращается в готовую точку входа для разбора.
Глубже: чего не логироватьрасширенное
Тема персональных данных заслуживает больше, чем строки в списке ошибок, потому что в облаке цена ошибки выше: журнал доступен всем, у кого есть права на чтение (а их выдают широко), живёт месяцами и уезжает в архивы.
Что не пишут никогда: адреса электронной почты и телефоны, имена и фамилии, адреса доставки, номера документов и карт, содержимое запросов и ответов целиком, токены и заголовки авторизации, пароли в любом виде (в том числе в текстах ошибок подключения).
Что пишут вместо: идентификаторы (customerId, orderId), маскированные значения для диагностики (u***@example.com) одной общей функцией, шаблон адреса запроса (GET /api/customers/{id}) вместо фактической строки с параметрами.
И тот же канал — метрики и трассы. Метка метрики с адресом электронной почты — это и утечка, и взрыв числа временных рядов; атрибут спана с персональными данными уезжает в то же хранилище. Правило одно: идентификаторы, а не данные.
Отдельно стоит знать про журналы доступа к данным: они по умолчанию выключены, и включают их выборочно — они дают полный след обращений к данным (кто прочитал какой объект), и это и полезно для аудита, и опасно объёмом и содержанием. Подробный разбор темы — в статье про персональные данные и секреты.
Коротко
- Secret Manager хранит секреты с версиями и правами IAM, но пароль за вас не меняет: расписание ротации это напоминание в Pub/Sub, а чтения видны только с включёнными журналами доступа к данным.
- Секрет берут при старте, при каждом обращении или с кэшем на минуты; новая версия доезжает при следующем чтении, пароль базы меняют с двумя действующими, версии отключают, а не удаляют.
- Cloud KMS отвечает на вопрос «чей ключ и можно ли его отозвать», а шифрование диска и так есть, только ключом Google.
- Cloud Logging собирает логи управляемых платформ сам, Cloud Monitoring строит графики и оповещения; наблюдаемость настраивают до аварии.
- Журналы платные сверх 50 ГБ в месяц и хранятся 30 дней: исключения отбрасывают шум до приёма, отводы уводят долгое в дешёвое хранилище, сроки хранения ставят по журналам.
- Метрики на основе логов превращают записи в числа для оповещений: счётчик или распределение, без меток с высокой мощностью.
- Трассировку собирают выборкой 5–10 % плюс ошибки, идентификатор трассы кладут в записи журнала и возвращают клиенту.
- В логи, метрики и трассы не пишут персональные данные и секреты: идентификаторы, маскирование одной функцией, шаблон адреса вместо адреса.
- Admin Activity пишется всегда и бесплатно, Data Access выключен по умолчанию и включается адресно; Security Command Center находит открытые наружу ресурсы.
Что почитать дальше
- Cloud IAM — как приложение получает доступ к секретам без ключей.
- Подключение SDK — как секрет попадает в свойства приложения.
- Оптимизация затрат в GCP — журнал как статья расхода и разбор счёта запросом.
- Наблюдаемость и секреты в облаке — та же модель без привязки к провайдеру.