Как обеспечить безопасный доступ HTTPS к вашим конечным точкам развертывания Kubernetes в Amazon EKS

Оглавление

Introduction
  The idea
Requirements
Setting Up an Ingress Controller
  Installing ingress-nginx
  Setting an external IP
Setting Up a Certificate Issuer
  Installing cert-manager
  Adding support for private VPCs
  Providing DNS access
  Deploying the certificate issuer
Setting Up Your Ingress
Summary

Вступление

Таким образом, вся ваша нагрузка работает в современном кластере Kubernetes, и все работает более гладко, чем когда-либо.

Более того, поскольку все находится внутри VPC, кажется, что проблема безопасности уже решена. На каком-то уровне это верно: если все было настроено правильно, не может быть внешнего доступа к ресурсам кластера.

Но нам все еще нужно обезопасить внутренний трафик. Мы никогда не хотим передавать какие-либо простые данные, особенно когда это касается конфиденциальных данных клиентов.

В своих предыдущих статьях Превратите образ Docker в автоматическое масштабирование развертывания Kubernetes с помощью Amazon EKS и Использование Jenkins при автоматическом масштабировании развертывания Kubernetes на Amazon EKS с помощью спотовых инстансов я продемонстрировал, как настроить Развертывания Kubernetes в среде EKS с автомасштабированием с использованием настраиваемого образа Docker, спотовых экземпляров и многого другого, но мы оставили обсуждение безопасности висящим. Пришло время погрузиться в дело.

Идея

Если вы хоть немного знакомы с Kubernetes, вы уже знаете, что почти все в нем является (или может быть) динамическим. Ваше развертывание может состоять из множества модулей, которые приходят и уходят в зависимости от ввода, нагрузки и т. Д., И ручное отслеживание безопасных конечных точек, особенно с помощью сертификатов, может быть кошмаром. Есть некоторые решения, такие как встраивание сертификатов в ваши изображения, но ими по-прежнему сложно управлять.

К счастью, Kubernetes предлагает еще одну идею в виде концепции под названием Ingress, которая станет краеугольным камнем нашего решения.

Ingress обеспечивает доступ к конечным точкам кластера Kubernetes. Его можно представить как маршрутизатор, который принимает внешний трафик и направляет его в службы кластера:

Требования

В этой статье предполагается, что у вас есть AWS в качестве облачного провайдера и у вас есть доступ к консолям управления EKS и ECR, а также к AWS CLI.

Я также предполагаю, что у вас установлены и настроены eksctl и kubectl, и что у вас есть какое-то развертывание в вашем кластере с конечной веб-точкой.

Еще раз, я попытался сделать минимальные предположения относительно предыдущих знаний и объяснить, что я мог, но я предполагаю некоторое знакомство с концепциями Kubernetes.

Наконец, обратите внимание, что все фрагменты кода и ссылочные файлы в этой статье доступны на GitHub.

Настройка Ingress-контроллера

Прежде чем добавить Ingress, мы собираемся добавить пару компонентов в наш кластер Kubernetes. Первый необходимый нам компонент - это контроллер Ingress, который будет управлять входящим трафиком нашего кластера.

Мы будем использовать ingress-nginx, также известный как nginx Ingress Controller для Kubernetes, который является одним из двух контроллеров Ingress, официально поддерживаемых сообществом Kubernetes (второй - ingress-gce).

Список альтернативных контроллеров входящего трафика можно найти в документации Kubernetes.

Контроллер входящего трафика nginx для Kubernetes - это простой контроллер входящего трафика, основанный на веб-сервере nginx и использующий возможности обратного прокси-сервера и балансировщика нагрузки для обработки трафика.

Установка ingress-nginx

Откройте свой терминал и выполните следующую команду:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/deploy.yaml

Обратите внимание, что эта команда развернет последнюю версию ingress-nginx. Для предыдущих версий или других платформ проверьте https://github.com/kubernetes/ingress-nginx. Для получения дополнительной информации об ingress-nginx посетите домашнюю страницу проекта https://kubernetes.github.io/ingress-nginx/.

Установка внешнего IP

Следующее, что нам нужно, это установить внешнюю точку доступа к службе ingress-nginx-controller, которую мы будем использовать для управления доступом к нашему кластеру.

Если вы читали мои предыдущие статьи о Kubernetes, вы уже знаете, что при использовании EKS на частном VPC вашему сервису не будет автоматически назначаться внешний IP-адрес.

Я уже описал один из способов решения этой проблемы, аннотируя ваш сервис в моей статье «Превратите ваш образ Docker в автоматическое масштабирование развертывания Kubernetes с помощью Amazon EKS». Альтернативное решение - вручную установить внешний IP-адрес балансировщика нагрузки в спецификации службы.

Выполните следующую команду, чтобы найти внешний IP-адрес вашей ingress-nginx-controller службы (если вы его не знаете):

kubectl describe service ingress-nginx-controller -n ingress-nginx | grep Endpoints | awk -F'[ :]+' 'NR==1{print $2}'

Выполните следующую команду, чтобы отредактировать службу ingress-nginx-controller:

kubectl edit svc/ingress-nginx-controller -n ingress-nginx

Добавьте следующие строки в конец раздела спецификации (см. Пример ниже):

externalIPs:
- YOUR_EXTERNAL_IP

Сохраните файл, когда закончите редактирование.

Настройка эмитента сертификата

Следующий компонент, который нам нужен, - это поставщик сертификатов, который будет управлять сертификатом конечной точки нашего кластера для обеспечения безопасного доступа.

Мы будем использовать cert-manager, контроллер управления сертификатами Kubernetes, который может автоматически выдавать и обновлять сертификаты от различных поставщиков.

В этой статье мы настроим автоматически обновляемый сертификат Let’s Encrypt (дополнительные сведения см. В разделе Let's Encrypt).

Установка cert-manager

Откройте свой терминал и выполните следующую команду:

kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.14.2/cert-manager.yaml

Эта команда развернет последнюю версию cert-manager для движка Kubernetes версии 1.15 и выше.

Обратите внимание, что флаг the--validate=false требуется только в том случае, если вы используете Kubernetes 1.15.4 или более раннюю версию, что в противном случае вызывает легкую ошибку проверки.

Для получения информации о различных версиях движка Kubernetes и дополнительной информации о процессе установки обратитесь к руководству по установке Cert-Manager Kubernetes: https://cert-manager.io/docs/installation/kubernetes/.

Дополнительную информацию о cert-manager можно найти на домашней странице проекта https://cert-manager.io.

Добавление поддержки частных VPC

Если вы используете частный VPC, Let's Encrypt будет использовать ваши частные DNS-серверы имен, чтобы попытаться подтвердить ваше право собственности на DNS с помощью задачи ACME. Однако, поскольку эти серверы имен недоступны из Интернета, проверка не удастся.

Нам нужно добавить флаг в cert-manager, чтобы использовать общедоступный DNS-сервер имен (скажем, Google 8.8.8.8) для проверки вашего DNS.

Выполните следующую команду, чтобы изменить развертывание cert-manager:

kubectl edit deployments.apps/cert-manager -n cert-manager

Добавьте следующие строки в раздел аргументов cert-manager:

- --dns01-recursive-nameservers="8.8.8.8:53"
- --dns01-recursive-nameservers-only

Сохраните файл и обратите внимание, что развертывание было отредактировано:

Предоставление доступа к DNS

Мы будем использовать Let's Encrypt для выпуска наших сертификатов. Let’s Encrypt - это центр сертификации (ЦС), который предоставляет бесплатные сертификаты. Сертификаты выдаются на короткий срок, но могут быть легко продлены (и cert-manager автоматически позаботится о продлении за вас).

Чтобы выдать сертификат для домена, ЦС должен подтвердить, что вы владеете этим доменом. Let's Encrypt использует вызовы ACME для проверки. В этом методе ЦС предоставляет вам уникальный текстовый ключ для хранения в вашем домене, а затем пытается получить доступ к вашему домену и прочитать этот ключ, чтобы подтвердить право собственности.

В нашем случае cert-manager заботится об этом за нас, используя объект, называемый издателем сертификата. Однако нам необходимо предоставить издателю сертификата доступ к нашему DNS-серверу, чтобы автоматически разместить там ключ для запроса.

Предположим, что вы используете AWS Route 53 в качестве поставщика DNS, и продемонстрируем, как предоставить издателю сертификата разрешения на доступ к нему.

Обратите внимание, что если вы используете другого поставщика DNS, вы все равно можете использовать Route 53 для публичного управления определенным поддоменом вашего домена.

Наконец, если вы используете Route 53 в качестве частного DNS для своего частного VPC, вам необходимо создать дополнительную публичную размещенную зону DNS для того же поддомена только для решения проблем ACME.

В обоих случаях создайте общедоступную зону хостинга для своего поддомена и настройте серверы имен у внешнего поставщика DNS.

После того, как вы настроили свою общедоступную размещаемую зону на Route 53, скопируйте идентификатор размещенной зоны.

Затем нам нужно создать политику для предоставления доступа к этой размещенной зоне.

Откройте IAM в Консоли управления AWS. В разделе «Управление доступом» выберите «Политики» и нажмите кнопку «Создать политику».

Выберите вкладку JSON и вставьте следующий текст (также доступен в Суть):

{
  "Version": "2012–10–17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "route53:GetChange",
      "Resource": "arn:aws:route53:::change/*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets",
        "route53:ListResourceRecordSets"
      ],
      "Resource": "arn:aws:route53:::hostedzone/YOUR_HOSTED_ZONE_ID"
    }
  ]
}

Обязательно замените заполнитель YOUR_HOSTED_ZONE_ID на идентификатор размещенной зоны, который вы скопировали из Route 53.

Нажмите «Просмотреть политику», введите имя и нажмите «Создать политику», чтобы закончить.

Далее нам нужно создать пользователя и прикрепить эту политику.

По-прежнему в IAM, в разделе «Управление доступом» выберите «Пользователи» и нажмите кнопку «Создать пользователя».

Введите имя и в поле «Тип доступа» выберите «Программный доступ».

Нажмите кнопку «Далее: разрешения» . Выберите «Присоединить существующие политики напрямую» и выберите только что созданную политику.

Продолжайте нажимать «Далее» и, наконец, нажмите кнопку «Создать пользователя».

На следующем экране вы получите идентификатор ключа доступа пользователя и секретный ключ доступа. Держите их под рукой - мы воспользуемся ими в следующий раз. Обратите внимание, что AWS больше не покажет вам секретный ключ доступа, но вы можете легко сгенерировать новый, если потеряете его.

Развертывание издателя сертификата

Теперь нам нужно развернуть эмитент сертификатов, который будет подключаться к Let's Encrypt, чтобы выдать нам сертификаты.

Эмитент будет использовать только что созданного пользователя, чтобы автоматически помещать задачи ACME в Route 53 и подтверждать право собственности на домен.

Следовательно, нам сначала нужно сохранить объект Secret в Kubernetes для хранения учетных данных для доступа к AWS.

Получите файл примера letsencrypt-issuer-secret.yaml из Gist. Сущность Secret включает одну запись "ключ-значение", в которой ключом является имя пользователя AWS, а значением - секретный ключ доступа пользователя. Замените заполнители именем пользователя, которого вы только что создали в IAM, а значение - это секретный ключ доступа, который вы сохранили ранее, закодированный в base64.

Чтобы закодировать свой ключ в base64, откройте терминал и выполните следующую команду:

python3 -c "import base64;print(base64.b64encode(b'YOUR_SECRET_ACCESS_KEY_HERE').decode())"

Выполните следующую команду, чтобы развернуть свой секрет:

kubectl apply -f letsencrypt-issuer-secret.yaml

Наконец, нам нужно развернуть сам издатель сертификата.

Загрузите файл примера letsencrypt-issuer.yaml из Gist. Замените заполнители для вашего доменного имени (для которого вы хотите создать безопасный поддомен), вашего региона AWS, имени пользователя, которого вы только что создали в IAM, и идентификатора ключа доступа этого пользователя, которого вы скопировано ранее (имейте в виду, что это не тот секретный ключ доступа, который мы использовали ранее).

Выполните следующую команду, чтобы развернуть издатель сертификата:

kubectl apply -f letsencrypt-issuer.yaml

Дополнительные сведения о создании эмитентов сертификатов диспетчера сертификатов с помощью AWS Route 53 см. В статье в документации диспетчера сертификатов.

Настройка вашего Ingress

Последний шаг, который нам осталось сделать, - это создать объект Ingress, который обеспечит фактический безопасный доступ к вашей конечной точке.

Загрузите файл примера my-ingress.yaml из Gist. Этот файл создаст сущность Ingress, которая автоматически выдаст сертификат для вашего хоста и направит входящие запросы на этот хост в вашу конечную службу Kubernetes.

В файле конфигурации входа есть два раздела спецификаций: один для настройки сертификата для вашего хоста, а второй для настройки маршрутизации запросов к вашей службе.

Замените заполнители для URL-адреса вашего хоста в двух местах (один для настройки сертификата TLS и один для правила маршрутизации) вместе с заполнителями для имени и порта конечной службы Kubernetes.

Выполните следующую команду, чтобы развернуть Ingress:

kubectl apply -f my-ingress.yaml

Выполните следующую команду, чтобы проверить статус вашего сертификата:

kubectl describe certificate my-ingress-tls

Обратите внимание, что запрос сертификата находится в процессе. Подождите несколько минут, пока cert-manager выдаст ваш сертификат, а затем снова проверьте статус:

kubectl describe certificate my-ingress-tls

Наконец, ваш сертификат готов, и вы можете получить доступ к своей службе через указанный вами URL-адрес хоста и безопасно перенаправиться на конечную точку Kubernetes.

Резюме

Даже внутри вашей частной сети ваши веб-конечные точки по-прежнему являются одними из самых уязвимых частей вашей облачной архитектуры. Независимо от того, насколько надежен ваш дизайн и насколько хорошо защищены ваши объекты Kubernetes, вы должны убедиться, что ваш конвейер данных защищен на каждой конечной точке и в любом месте между ними.

В этой статье я продемонстрировал, как использовать концепцию Kubernetes Ingress и объединить ее с популярными компонентами с открытым исходным кодом и возможностями AWS, чтобы создать простое, но мощное и безопасное решение.

С помощью этого базового варианта использования я попытался познакомить вас с концепциями и возможностями, и я считаю, что его будет относительно легко настроить в соответствии с вашими конкретными потребностями.

Чтобы узнать больше об EKS и его возможностях, посетите документацию AWS EKS https://docs.aws.amazon.com/eks/index.html.

Вам также следует обратиться к этому онлайн-семинару EKS, предоставленному Amazon, который также может помочь вам начать работу и познакомить вас со всеми функциями EKS https://eksworkshop.com/.