В этой статье я расскажу про практический случай одной конфигурационной ошибки, которая привела к неожиданному эффекту, заняла меня на пару часов исследований и показала как важно понимать, что скрывает под собой тотальная автоматизация. Я подумал, что процесс отлова был достаточно интересным, чтобы им поделиться. Началось все со следующей задачи: в k8s инфраструктуре был развернут minio кластер с публичным ингрессом для s3 api (на всякий случай уточню, minio - это S3 хранилище на самообслуживании). И требовалось перевести взаимодействие компонентов внутри кластера на приватную сеть. В деталях это означало завести внутренний CA, выписать сертификат на внутри-кластерное имя (вида minio.minio.svc.cluster.local), отдать его напрямую TLS серверу minio и разложить CA сертификат в доверительные хранилища сертификатов на стороне приложений. Задача была выполнена, все заработало, трафик перебросился на внутренние сетевые интерфейсы, сертификат был не самоподписанный, всё выглядело красиво. Однако логи приложений стали бросать периодические ошибки вида: При этом приложение почти полностью работало, и проявлялись ошибки в случайных непрогруженных картинках то там, то тут. Поведение было нестабильным. Переключение minio клиента назад на публичный ендпоинт ошибки убирало. Было непонятно, в первую очередь, отчего такое непостоянное поведение? Азарт возрастал. Моя первая мысль: подозрение падает на сторону клиента, как-то некорректно он работает с доверяемыми CA. Чтобы проверить это за рамками приложения, воспользовался инструментом SSLPoke и, в общем-то, получил искомое: Итак, мы видим, что один из двадцати вызовов к нашему серверу падает. Повторяя эксперимент, это случайное поведение оставалось стабильным в своей случайности.  Следующий шаг: исключим из уравнения Java и перейдем на уровень чистого Linux. А именно, произведем тот же эксперимент с чистым curl, что увидим? Результат оказался тем же - примерно один раз из десяти получаю ошибку сертификата: В этот момент в голову полезли стандартные мысли: это точно какие-то глюки сети kubernetes, ведь всем известно, что там могут происходить невероятные вещи...  Идем дальше, можем смело отбросить сеть, если произведем тот же эксперимент локально с ноды в контейнер и внутри самого контейнера. Результат остался тем же, сеть как таковая не причем. Проблема находится внутри самого minio server.  Следующая мысль: раз у нас ошибка сертификата, надо уже наконец посмотреть, что за сертификат мы получаем. Смотрим на хороший и плохой случай с помощью openssl: сертификат здорового человека сертификат курильщика Видим необычное имя system:node:*.example-1-hl.minio.svc.cluster.local и при этом группа system:nodes намекает на сертификат, выписанный самим k8s. Не очень люблю сидеть и гадать, откуда что появляется, поэтому расчехлил старое ружье на стене обратился к strace, он меня никогда не подводил. Натравив его на процесс minio во время того же цикла curl, увидел, что он действительно обращается в разный момент времени к разным файлам: Дальше меня насторожил один нюанс, что при старте minio получает не точный путь до конкретных файлов сертификата, а просто директорию, в которой они лежат: И внутри по какой-то причине лежат два разных сертификата. Исходники minio как бы поясняют, что это скорее фича, а не баг, чтобы упростить работу с предоставляемыми сертификатами. Когда стало понятно, что все идет по плану и так и было задумано, после очередного прочтения tls.md я уже стал догадываться, что в нашу картину вмешивается автоматизированный процесс, и так как он описан в секции Automatic TLS я наконец осознал, что именно пошло не так. Once you enable requestAutoCert field and create the Tenant, MinIO Operator creates a CSR for this instance and sends to the Kubernetes API server. Когда я переходил к своему сертификату, в настройках объекта Minio Tenant я убрал ключ requestAutoCert и добавил externalCertSecret, и ожидал, что я таким образом выключил автогенерацию. Но я просто оставил значение true по умолчанию. Если побродить по их прочим инструкциям этот момент проскальзывает, например так: MinIO Operator can automatically generate TLS secrets and mount these secrets to the MinIO, Console, and/or KES pods (enabled by default). To disable this, set the requestAutoCert field to false. Но когда я шел по тем шагам, что нужны были мне, этот момент был упущен.  Получается, minio operator производил одновременно два процесса: брал мой сертификат из секрета, а также автоматически запрашивал сертификат у k8s и добавлял в этот же секрет. Для полноты всей этой картины, выяснилось, что я дал имя секрету ровно такое, какое зашито в автогенерации. Занавес! Для успокоения своей совести и защиты от дурака в будущем, я оформил PR на то, чтобы улучшить этот момент в документации: https://github.com/minio/operator/pull/1184. Благодарю за внимание!