Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи?

Написать
Войти
Дайджесты
Архитектура приватного кластера EKS с VPN-доступом

Создание приватного кластера Amazon EKS с помощью Terraform и OpenVPN

Пошаговое руководство по развертыванию полностью приватного кластера Amazon EKS без публичного доступа к API. Настройка автоматизирована с помощью Terraform и включает конфигурацию OpenVPN-сервера для безопасного доступа, kube-prometheus-stack для мониторинга и приватных зон DNS в Route 53.

Создание приватного кластера Amazon EKS с помощью Terraform и OpenVPN

Безопасность является ключевым приоритетом при проектировании облачной инфраструктуры. Стандартное развертывание кластера Amazon EKS (Elastic Kubernetes Service — сервис управления контейнерами от AWS) с публичным доступом к API подвергает панель управления внешним угрозам. Для защиты от сетевых атак необходимо разворачивать приватный кластер EKS без публичного API-эндпоинта, доступ к которому осуществляется только через VPN-туннель.

В данном руководстве описан процесс развертывания такой инфраструктуры с использованием Terraform и шлюза OpenVPN на виртуальном сервере EC2.

Архитектура защищенной сети и распределение ресурсов

Вся инфраструктура разворачивается в рамках одного VPC (Virtual Private Cloud — виртуальное облако в AWS) с адресным пространством 10.0.0.0/16, разделенным на публичные и приватные подсети в двух зонах доступности (AZ).

РесурсСетевой диапазон (CIDR)Тип подсетиНазначение
VPC10.0.0.0/16Виртуальное облакоСеть для всей инфраструктуры
Public Subnet 110.0.1.0/24ПубличнаяOpenVPN инстанс, NAT Gateway
Public Subnet 210.0.2.0/24ПубличнаяРезервная зона
Private Subnet 110.0.10.0/24ПриватнаяНоды EKS, внутренние балансировщики
Private Subnet 210.0.11.0/24ПриватнаяНоды EKS, внутренние балансировщики
VPN Client Range10.8.0.0/24VPN-туннельАдреса для VPN-клиентов

Ноды EKS в приватных подсетях общаются с интернетом (для скачивания образов) через NAT Gateway в публичной подсети. Это ограничивает только входящие соединения: API-сервер EKS доступен только изнутри VPC, а исходящий трафик идет наружу.

Схема прохождения трафика при администрировании:

[ Ноутбук администратора ] (Внешняя сеть)
           | (Secure Tunnel: UDP 1194 / OpenVPN)
           v
[ OpenVPN Server EC2 ] (Public Subnet - 10.0.1.x)
           | (NAT Masquerade - подмена IP на внутренний IP сервера)
           v
[ EKS API Endpoint ] (Private Subnets - HTTPS 443) <--- Управление
           |
[ Grafana Internal Load Balancer ] (HTTP 80/443)   <--- Мониторинг

Подготовка конфигурации провайдеров Terraform

Поскольку API-сервер EKS приватный, провайдеры Helm и Kubernetes должны взаимодействовать с ним через VPN. Ниже представлен файл providers.tf:

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = { source = "hashicorp/aws", version = "~> 5.0" }
    tls = { source = "hashicorp/tls", version = "~> 4.0" }
    helm = { source = "hashicorp/helm", version = "~> 2.0" }
    kubernetes = { source = "hashicorp/kubernetes", version = "~> 2.0" }
  }
}

provider "aws" { region = var.aws_region }

provider "kubernetes" {
  host                   = module.eks.cluster_endpoint
  cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    args        = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
  }
}

provider "helm" {
  kubernetes {
    host                   = module.eks.cluster_endpoint
    cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      command     = "aws"
      args        = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
    }
  }
}

Важное предупреждение при деплое (bootstrap caveat): При запуске terraform apply вне VPC шаги по установке Helm-чартов зависнут, так как Terraform не сможет подключиться к приватному API EKS. Рекомендуется разделить процесс: сначала развернуть VPC, OpenVPN-сервер и кластер EKS, затем подключиться к VPN на локальной машине и повторно запустить terraform apply для деплоя Helm-чартов.

Настройка VPC и EKS в Terraform

Для обнаружения подсетей контроллером AWS Load Balancer Controller необходимо разметить подсети тегами в модуле VPC:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
  name = "eks-secure-vpc"
  cidr = "10.0.0.0/16"
  azs             = ["us-east-1a", "us-east-1b"]
  private_subnets = ["10.0.10.0/24", "10.0.11.0/24"]
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  enable_nat_gateway = true
  single_nat_gateway = true
  enable_dns_hostnames = true
  enable_dns_support   = true

  public_subnet_tags  = { "kubernetes.io/role/elb" = "1" }
  private_subnet_tags = { "kubernetes.io/role/internal-elb" = "1" }
}

При настройке модуля EKS (terraform-aws-modules/eks/aws версии ~> 20.0) отключаем публичный доступ к управляющему контуру:

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.0"
  cluster_name    = "secure-prod-cluster"
  cluster_version = "1.29"
  cluster_endpoint_public_access  = false
  cluster_endpoint_private_access = true
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets
  enable_cluster_creator_admin_permissions = true

  eks_managed_node_groups = {
    default = {
      min_size = 2; max_size = 5; desired_size = 2
      instance_types = ["t3.medium"]
    }
  }
}

Параметр enable_cluster_creator_admin_permissions = true автоматически дает права создателю кластера в EKS Access Entries, предотвращая ошибку You must be logged in to the server.

Развертывание и конфигурация OpenVPN-шлюза

Сервер OpenVPN запускается на инстансе EC2 (Ubuntu 22.04 LTS) в публичной подсети с Elastic IP. Группа безопасности разрешает входящий UDP/1194 и ограничивает SSH (TCP/22) вашим IP. На сетевом интерфейсе EC2 необходимо отключить проверку источника и назначения: source_dest_check = false.

Скрипт user-data выполняет следующие шаги:

  1. Устанавливает openvpn, easy-rsa и iptables-persistent.
  2. Включает IP Forwarding: sysctl -w net.ipv4.ip_forward=1 (с записью в /etc/sysctl.conf).
  3. Создает локальный CA, генерирует сертификат сервера и общий ключ ta.key.
  4. Настраивает трансляцию адресов: iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE.
  5. Генерирует клиентский профиль /home/ubuntu/client-configs/client1.ovpn с правами 600.

Ключевые директивы /etc/openvpn/server.conf:

port 1194
proto udp
dev tun
server 10.8.0.0 255.255.255.0
push "route 10.0.0.0 255.255.0.0"
push "dhcp-option DNS 10.0.0.2"
cipher AES-256-GCM
auth SHA256
user nobody
group nogroup

Адрес 10.0.0.2 (AmazonProvidedDNS) передается клиентам для корректного резолва имен приватных DNS-зон в Route 53.

Интеграция DNS и мониторинга

Внутри приватных подсетей разворачивается kube-prometheus-stack (Prometheus, Grafana). Grafana настраивается как внутренний балансировщик (internal Load Balancer) с помощью аннотаций AWS LB Controller. В Route 53 создается Private Hosted Zone devops.private, связанная с VPC, и CNAME-запись grafana.devops.private на внутренний балансировщик Grafana, доступный только внутри VPN.

Пошаговая инструкция по запуску, проверке и подключению

  1. Развертывание сети: Примените Terraform для создания VPC, OpenVPN-сервера, Route 53 и кластера EKS.
  2. Получение профиля: Подключитесь по SSH к VPN-серверу и скачайте профиль: scp -i key.pem ubuntu@<PUBLIC_IP_VPN>:/home/ubuntu/client-configs/client1.ovpn ./client1.ovpn
  3. Подключение к VPN: Запустите OpenVPN-клиент с полученным профилем.
  4. Конфигурация kubectl: Создайте kubeconfig на локальной машине с помощью AWS CLI (требуются права eks:DescribeCluster): aws eks update-kubeconfig --region us-east-1 --name secure-prod-cluster
  5. Проверка сетевого пути:
    • Без VPN: curl -k -m 5 https://<EKS_API_ENDPOINT>/readyz завершается ошибкой.
    • С VPN: Тот же запрос возвращает код 401 или ok.
    • Проверьте доступ к нодам: kubectl get nodes.
  6. Проверка мониторинга: Выполните nslookup grafana.devops.private (должен вернуть IP-адрес 10.0.x.x) и откройте интерфейс в браузере.

Безопасность и ограничения

  • Конфиденциальность ключей: Утеря client1.ovpn компрометирует доступ в приватную сеть. Храните профили в зашифрованном виде.
  • Точки отказа: Одиночный инстанс OpenVPN является единой точкой отказа (SPOF). В production замените его на AWS Client VPN или отказоустойчивую группу VPN за балансировщиком.
  • Стоимость: NAT Gateway тарифицируется поминутно. Для экономии в dev-средах используется single_nat_gateway = true.
  • Права доступа: Используйте именные сертификаты, MFA и настройте регулярное обновление списка отзыва сертификатов (CRL).