[TL; DR: запустите Kubernetes на двух микроэффектах на GKE без внешней нагрузки балансировщиков. Настройка кластера с нуля. github.com/nkoson/gke-tutorial ]
Мое волнение бега Kubernetes На платформе Google Cloud была быстро обуздана осознание того, что, несмотря на виртуальные машины Google, начиная с доступных ценовых баллов, их сетевая вступление является другой историей: Допустим, вы хотите настроить простой кластер для ваших личных проектов или малого бизнеса. На момент написания, несколько микрозмуров, работающих в Айове Первые 5 правил пересылки. Для меня это нарушатель сделки, так как есть много других облачных провайдеров с лучшими предложениями для небольших игроков.
Вот когда я наткнулся на Отличная статья о запуске кластера GKE без балансировщиков нагрузки. Благодаря этой недавно подстрекательской мотивации я намеревался создать свой кластер GKE — с требованием, чтобы он был максимально дешевым, наслаждаясь ключевым преимуществом облака: свободным от ручного обслуживания.
Я написал эту статью в качестве пошагового учебника. Основываясь на моем собственном опыте настройки кластера на новой учетной записи GCP, я стараюсь охватить каждую тему от настройки инфраструктуры до обслуживания запросов HTTP (ы) из кластера. Пожалуйста, обратите внимание, что я сделал это в основном, чтобы обучить себя предмету, поэтому критика и исправления искренне приветствуются.
Мы будем использовать Terraform.io для управления нашей облачной инфраструктурой, поэтому зарегистрируйте учетную запись, если вы еще этого не сделали. Очевидно, вам также понадобится доступ к учетной записи Google Cloud Platform.
Давайте продолжим, создав новый проект на консоли GCP:
Селектор проекта (Top Bar) -> New Project -> Введите имя -> Создать
Это создаст для нас хороший пустой проект, который отличается от проекта стартера по умолчанию тем, что недавно созданный бланк не имеет никаких предопределенных учетных записей API или услуг. Мы начнем копать нашу кроличье отверстие, включив вычислительный API двигателя, который нам нужно общаться с GCP с помощью Terraform. Мы также включим API использования услуг, чтобы Terraform мог предоставить нам услуги по мере продвижения вперед.
APIS & Services -> Library API -> Compute Engine API -> включить
APIS & Services -> Библиотека API -> API использования услуг -> включить
После того, как API инициализированы, мы должны обнаружить, что GCP сгенерировал для нас новую учетную запись обслуживания. Удобно названная учетная запись Score Engine по умолчанию предоставляет нам удаленный доступ к ресурсам нашего проекта. Далее нам нужно создать ключ для Terraform для аутентификации с помощью GCP:
IAM & Admin -> Service Accounts -> Compute Engine Service Service Account -> Create Key -> Создать как JSON
Ключ, который мы только что загрузили, может использоваться в нашей консоли Terraform.io в качестве переменной среды или непосредственно с локального диска при запуске команд Terraform CLI. Первый требует новичков, отредактированных из файла JSON, и содержимое, добавленное как Google_cloud_keyfile_json
В нашем рабочем пространстве Terraform.io:
Рабочие пространства -> (Выберите рабочее пространство) -> переменные -> переменные среды
Убедитесь, что вы установили значение как «чувствительное/только писать», если вы решите сохранить ключ в своем рабочем пространстве Terraform.io. Как указано выше, также можно прочитать ключ из вашего локального диска, добавив следующее в ресурсе поставщика Terraform:
provider "google" { version = "3.4.0" credentials = file(".json") }
В этом уроке мы будем использовать последний из двух методов.
Пока мы здесь, стоит отметить, что учетная запись сервиса по умолчанию Compute не имеет разрешений на создание новых ролей и назначение политик IAM в проекте. Это то, что нам понадобится позже как часть нашего процесса терраформирования, так что давайте покончим с этим:
IAM & Admin -> РЕДАКТИРОВАТЬ SOCKETE ENGINE SERVICE SERVICE ACCONTE (ICON) -> Добавить другую роль -> Выберите «Администратор ролей» -> Сохранить
Добавить другую роль -> Выберите «Проект IAM Admin» -> Сохранить
Добавить другую роль -> выберите «Администратор сервиса admin» -> Сохранить
Теперь мы готовы инициализировать Terraform и применить нашу конфигурацию к облаку.
terraform init
Это настроит ваше локальное рабочее пространство Terraform и загрузите плагин Google Provider, который используется для настройки ресурсов GCP.
Мы можем продолжить применить конфигурацию к нашему проекту GCP.
terraform apply
Это будет подавать конфигурацию в облако Terraform.io, проверьте его синтаксис, проверьте состояние нашего проекта GCP и, наконец, попросите подтверждения применить наши изменения. Введите «да» и откиньтесь на спинку. Это займет некоторое время.
module.cluster.google_project_iam_custom_role.kluster: Creating... module.cluster.google_service_account.kluster: Creating.. module.cluster.google_compute_network.gke-network: Creating... module.cluster.google_compute_address.static-ingress: Creating... module.cluster.google_service_account.kubeip: Creating... module.cluster.google_container_node_pool.custom_nodepool["ingress-pool"]: Creating... module.cluster.google_container_node_pool.custom_nodepool["ingress-pool"]: Creation complete after 1m8s
После того, как пыль зарегистрировалась, пришло время проверить повреждение. Мы решили настроить минимальную облачную инфраструктуру для запуска Kubernetes Кластер, так что давайте посмотрим, как мы справились до сих пор.
Вычислить двигатель -> экземпляры виртуальной машины
Эта страница показывает, что теперь у нас работает две виртуальные машины. Эти машины являются частью пула узлов вход и веб-пилота. Пул узлов — это кусок конфигурации, которая сообщает Google Container Engine (GKE), как и когда масштабировать машины в нашем кластере вверх или вниз. Вы можете найти определения пула узлов в cluster.tf и node_pool.tf
Если вы прищущаетесь, вы можете видеть, что на машинах назначены внутренние IP -адреса. Эти адреса являются частью нашего подсеть диапазон. В нашем кластере определено множество других диапазонов адресов, о которых мы сейчас увидим:
subnet_cidr_range = "10.0.0.0/16" # 10.0.0.0 -> 10.0.255.255
Определено в google_compute_subnetwork Это диапазон адресов подсети, в котором будет работать наш кластер GKE.
master_ipv4_cidr_block = "10.1.0.0/28" # 10.1.0.0 -> 10.1.0.15
Мастер -узел нашего Kubernetes Кластер будет работать под этим блоком, используемый Google_container_cluster Анкет
cluster_range_cidr = "10.2.0.0/16" # 10.2.0.0 -> 10.2.255.255
Остальная часть нашего Kubernetes Узлы будут работать в этом диапазоне, определяемые как Вторичный диапазон как часть нашей подсети.
services_range_cidr = "10.3.0.0/16" # 10.3.0.0 -> 10.3.255.255
Также вторичный диапазон в нашей подсети, диапазон сервисов содержит наш Kubernetes Услуги, больше из которых чуть позже.
Понимая основные строительные блоки нашей сети, есть еще несколько деталей, которые нам нужно понять, чтобы это имело смысл в целом. Узлы в нашем кластере могут общаться друг с другом в подсете, которую мы только что обсудили, но как насчет входящего трафика? В конце концов, нам нужно не только принять входящие соединения, но и загружать изображения контейнеров из Интернета. Введите Cloud Nat:
Сеть -> Сетевые сервисы -> Cloud Nat
Часть нашей конфигурации маршрутизатора, Cloud NAT предоставляет наши экземпляры виртуальной машины подключение к Интернету без внешних IP -адресов. Это допускает безопасный способ обеспечения нашего Kubernetes Узлы, как мы можем загрузить изображения контейнеров через NAT, не выявляя машины для общедоступного Интернета. В нашем Определение Мы устанавливаем маршрутизатор, чтобы разрешить автоматически распределенные адреса и работать только в нашей подсети, которую мы настроили ранее.
ОК, наш NAT дает нам исходящее соединение, но нам понадобится входящий адрес для нашего Cheap-O Load Balancer/Ingress/Manager Manager All-In-One Contraption, Трафик . Некоторое время поговорим о приложении, но давайте сначала убедитесь, что наши внешние статические IP -адреса под контролем:
Networking -> VPC Network -> Внешние IP -адреса
В списке должно быть два адреса; Автоматически сгенерированный один, используемый нашим NAT, плюс другой, в настоящее время неиспользованный адрес, который называется Static-Engress. Это важно для нашего кластера принимать соединения без балансировщика внешней нагрузки, поскольку мы можем направить трафик на наш узел входа, используя статический IP. Мы будем запускать приложение, Kubeip, в нашем кластере, чтобы позаботиться о назначении статического адреса нашему узел Ingress, который мы обсудим вскоре.
Это хорошая возможность взглянуть на наши настройки брандмауэра:
Сеть -> VPC Network -> Правила брандмауэра
Мы добавили одно пользовательское правило, которое позволяет входящему трафику через наш узел входа. Обратите внимание, как мы указываем цель для правила, чтобы соответствовать только с экземплярами, которые несут тег входного пула. В конце концов, нам нужно только http (S) трафик, чтобы приземлиться на нашем внутренней балансировщике нагрузки ( traefik ). Пользовательское правило брандмауэра определено Здесь Анкет
Чтобы мы не забыли, еще одна вещь: мы будем использовать инструмент CLI gcloud Чтобы получить наш Kubernetes Учетные данные запускаются на следующем шаге. Конечно, gcloud Также нужна собственная конфигурация, так что давайте покончим с этим:
gcloud init
По правде говоря, ответьте на вопросы, и вы будете вознаграждены хорошей конфигурацией Gcloud.
Kubernetes
Наша настройка облачной инфраструктуры теперь сделана, и мы готовы запустить некоторые приложения в кластере. В этом уроке мы будем использовать kubectl Управлять нашим Kubernetes кластер Чтобы получить доступ к кластеру на GCP, Kubectl нужна допустимая конфигурация, которую мы можем быстро получить, запустив:
gcloud container clusters get-credentials--region
Агрессивные оптимизации
Отказ от ответственности: я не рекомендую делать что -либо из того, что я сделал в этом разделе. Не стесняйтесь запускать Типы машин пула узлов к чему-то мягкому (такому как G1-Small) в пользу поддержания журнала и метрик. На момент написания этого учебника мне пришлось сделать довольно агрессивные оптимизации на кластере, чтобы запустить все на двух микроэффектах. Мы упомянули дешево, не так ли?
Понимая, что, вероятно, не очень хорошая идея для отключения ведения журнала, у нас есть Отключенный журнал на GCP. Теперь, когда мы стремимся к скорости, почему бы нам не пойти дальше и выключить Kubernetes Метрики также:
kubectl scale --replicas=0 deployment/metrics-server-v0.3.1 --namespace=kube-system
Это более 100 МБ памяти, сохранившейся на наших узлах за счет того, что больше не зная общего потребления памяти и процессора. Для меня звучит честная сделка! Мы также масштабируем развертывание услуг Kube-DNS, так как запуск нескольких DNS-сервисов в нашем крошечном кластере кажется излишним:
kubectl scale --replicas=0 deployment/kube-dns-autoscaler --namespace=kube-system kubectl scale --replicas=1 deployment/kube-dns --namespace=kube-system
Kubernetes По умолчанию тоже может пойти. Мы будем использовать nginx Для этой цели:
kubectl scale --replicas=0 deployment/l7-default-backend --namespace=kube-system
На этом этапе я понял, что экземпляр свернулся от веб-пилот застрял в «контейнероне» со всеми Kubernetes развертывание Я просто отключил все еще работает, поэтому я просто удалил экземпляр, чтобы дать ему новое начало:
gcloud compute instances list gcloud compute instances delete
Через несколько минут GCP развернул новый экземпляр из веб-пилот Пул экземпляров, на этот раз без сервера метрик, бэкэнд по умолчанию и только с одной службой DNS.
Развертывание
Кластер, который мы собираемся запустить, имеет три развертывания: nginx Для обслуживания веб -контента, Kubeip за то, чтобы поддерживать реагирование на наш входной узел и Трафик который служит двойной цели; Маршрутизация входящих соединений с nginx , плюс обработка SSL. Мы обсудим каждое развертывание дальше.
nginx-web
Входящий http (ы) трафик в нашем кластере перенаправлен на nginx сервер, который мы используем в качестве нашего веб -бэкэнда. Положите просто в Kubernetes Условия, мы собираемся развернуть изображение контейнера в Пространство имен и отправить его трафиком через услуга . Сначала мы сделаем пространство имен. Перейдите к K8s/nginx- Интернет/
и беги:
kubectl create --save-config -f namespace.yaml
Довольно прямо до сих пор. Пространство имен, которое мы только что создали, определено Здесь Анкет Далее следует развертывание:
kubectl create --save-config -f deployment.yaml
Как вы можете видеть из Определение , мы хотим, чтобы наше развертывание работало в пространстве имен nginx-web
Анкет Нам нужен контейнер для запуска на виртуальной машине, которая развернулась из пула узлов веб-пилот , отсюда Nodeselector параметр. Мы делаем это, потому что хотим запустить все кроме Балансировщик нагрузки на упреждающуюся виртуальную машину для сокращения затрат при обеспечении максимального времени безотказной работы.
Двигаясь дальше, Секция контейнера Определяет изображение Docker, которое мы хотим запустить в нашем частном реестре Google Container Registry (GCR). Ниже мы открываем порты 80 и 443 для трафика и устанавливаем проверку здоровья (зонд жизни) для нашего контейнера. Кластер теперь периодически получает контейнер в конечной точке /здоровье и заставит перезапуск, если он не получит 200 ОК в течение определенного времени. Зонд готовности в основном такой же, но расскажет кластер, когда контейнер готов начать принимать соединения после инициализации.
В этом уроке мы не будем слишком глубоко погрузиться в Docker, но в этом учебнике мы включили базовый контейнер Nginx: Alpine с веб -контентом Placeholder. Нам нужно загрузить изображение контейнера в GCR для Kubernetes Использовать его в соответствии с развертыванием, которое мы только что создали. Перейдите к Docker/nginx-alpine
и беги:
docker build -t eu.gcr.io//nginx-web .
Это создает изображение и соответствующим образом течет для использования в нашем кластере. Нам нужен Docker для аутентификации с GCP, поэтому давайте зарегистрируем GCLOUD в качестве помощника Docker, работая:
gcloud auth configure-docker
Чтобы протолкнуть изображение в наш реестр, запустите:
docker push eu.gcr.io//nginx-web
Мы можем проверить, что все прошло хорошо с развертыванием, работая:
kubectl get event --namespace nginx-web
LAST SEEN TYPE REASON KIND MESSAGE 1m Normal Pulling Pod pulling image "eu.gcr.io/gke-tutorial-xxxxxx/nginx-web:latest" 1m Normal Pulled Pod Successfully pulled image "eu.gcr.io/gke-tutorial-xxxxxx/nginx-web:latest" 1m Normal Created Pod Created container 1m Normal Started Pod Started container
Теперь у нас есть nginx Контейнер, работающий в нужном месте, но нам все еще нужно направить трафик к нему в кластере. Это делается путем создания услуга :
kubectl create --save-config -f service.yaml
Наш Определение службы минимально: мы просто направляем входящий трафик в приложения, которые соответствуют Селектор nginx-web
Анкет Другими словами, трафик, который отправляется в этот сервис в портах 80 и 443, будет направлен на стручки, использующие нашу бэкэнд.
Kubeip
Работая в облачной среде, мы не можем поверить, что наши виртуальные машины остаются бесконечно. Напротив, мы на самом деле принимаем это, запустив наш веб -сервер на Предоплаченное узел. Уребленные узлы дешевле бежать, если мы принимаем тот факт, что они спускаются в течение некоторого периода времени, по крайней мере, один раз в день. Мы могли бы легко обеспечить более высокую доступность в нашем кластере, просто увеличив количество узлов, но ради простоты мы придерживаемся одного из каждого типа, определяемых нашими пулами узлов Ingress-Pool и веб-пилот
Пул узлов — это набор инструкций о том, сколько и каких экземпляров мы должны были работать в нашем кластере в любой момент времени. Мы будем работать Трафик На узле, созданном из Ingress-Pool и остальные наши приложения работают на узлах, созданных из веб-пилот Анкет
Хотя узлы от Ingress-Pool не упреждаются, они могут перезапустить некоторое время. Поскольку в нашем Cheap-O Cluster не используется внешняя балансировщик нагрузки (который Expen \ $ ive), нам нужно найти другой способ убедиться, что у нашего узла входа всегда есть одинаковый IP для подключения. Мы решаем эту проблему, создав Статический IP -адрес и используя Kubeip при необходимости связывать этот адрес с нашего узла входа.
Давайте создадим развертывание для Kubeip Навигация на K8s/Kubeip
и бег:
kubectl create --save-config -f deployment.yaml
Мы определяем Kube-System
как Целевое пространство имен для Kubeip , поскольку мы хотим, чтобы он был напрямую с Kubernetes Мастер и узнай, когда новому созданному узлу нужен статический адрес. Используя Nodeselector , мы принудительно Kubeip развернуть на веб-пилот Узел, как мы это сделали с nginx ранее.
Далее в конфигурации мы определяем кучу переменных среды, которые мы связываемся со значениями в Configmap Анкет Мы обучаем наше развертывание, чтобы извлечь учетные данные Сервиса GCP из A Kubernetes Секрет Анкет Через Сервисная учетная запись , Kubeip может иметь необходимые права доступа для внесения изменений (назначения IPS) в GCP.
Мы создали GCP Сервисная учетная запись для kubeip как часть нашего терраформного процесса. Теперь нам просто нужно извлечь его учетные данные так же, как и с нашей основной учетной записью сервиса в начале этого урока. Для дополнительного разнообразия давайте используем командную строку на этот раз. Из корня нашего проекта запустите:
gcloud iam service-accounts list gcloud iam service-accounts keys create keys/kubeip-key.json --iam-account
Теперь, когда мы сохранили ключ, мы храним его в кластере как Kubernetes секрет:
kubectl create secret generic kubeip-key --from-file=keys/kubeip-key.json -n kube-system
Мы создали учетную запись сервиса GCP для Kubeip и настроен Kubeip Чтобы получить доступ к нему через Kubernetes секрет Нам все еще понадобится Учетная запись службы Kubernetes Чтобы получить доступ к информации об узлах в кластере. Давайте сделаем это сейчас:
kubectl create --save-config -f serviceaccount.yaml
Мы определяем ( kubernetes ) ServiceAccount и под ним Кластеррол и ClusterRoleBinding Ресурсы, которые определяют, что разрешено делать нашей учетной записи услуги и где.
Далее нам нужно создать Configmap Для развертывания Kubeip :
kubectl create --save-config -f configmap.yaml
В конфигурация , мы устанавливаем Kubeip бежать в веб-пилот
и смотреть экземпляры, вращающиеся с Ingress-Pool
Анкет Когда Kubeip Обнаружает такой экземпляр, он проверяет, есть ли незначенный IP -адрес с метка Kubeip и значение Статический-Энгресс в резерве и дает этот адрес экземпляру. Мы ограничили Ingress-Pool
Для одного узла, поэтому нам нужен только один статический IP -адрес в нашем резерве.
Трафик
Внешние балансировщики нагрузки очень полезны для обеспечения отзывчика вашей веб -службы при высокой нагрузке. Они также чрезмерно дорогим для маршрутизации трафика в этот единственный капсул в вашем личном кластере, поэтому мы собираемся обойтись без него.
В нашем учебном кластере мы посвящаем один узел хостингу Трафик , который мы настраиваем, чтобы направить трафик на нашу веб -бэкэнд ( nginx server). Трафик может также получить сертификаты SSL из резолюров, таких как LetsEncrypt
Чтобы защитить наш трафик HTTPS. Мы не собираемся освещать доменное имя и настраивать DNS в этом уроке, но для справки я оставил все, что требуется для настройки задачи DNS, прокомментированного в коде.
Давайте создадим пространство имен и учетную запись службы для Трафик Анкет Перейдите к K8S/TRAEFIK
и беги:
kubectl create --save-config -f namespace.yaml
kubectl create --save-config -f serviceaccount.yaml
Далее мы создадим развертывание и посмотрим, что мы сделали до сих пор:
kubectl create --save-config -f deployment.yaml
Используя Nodeselector Еще раз, мы указываем, что хотим Трафик запустить на машине, которая принадлежит Ingress-Pool
, что значит что в нашем кластере, Трафик будет сидеть на другой машине, чем Kubeip и nginx Анкет Мысль, стоящая за этим, заключается в том, что обе наши машины вряд ли пойдут одновременно. Когда веб-пилот
спускается и перезапускается, без проблем; Трафик найдет его в кластере и нормально резюме подключения маршрутизации. Если наш Ingress-Pool
Происходила, ситуация была бы более серьезной, поскольку нам нужен наш внешний IP, связанный с этой машиной. Как еще наши клиенты приземляются на нашу веб -бэкэнд? Помните, что у нас нет внешней балансировщика нагрузки …
К счастью, у нас есть Kubeip который обнаружит недавно перезагруженную Ingress-Pool
машина и назначьте наш внешний IP обратно в него в кратчайшие сроки. Кризис предотвратил!
Есть пара ключевых вещей в нашем Трафик развертывание, которое отличает его от других наших развертываний. Сначала hostnetwork Что нам нужно для Трафик прослушать сетевые интерфейсы его хост -машины. Во -вторых, мы определяем терпимость , потому что у нас есть испорченный Пул узлов хоста. С нашего Трафик Развертывание является единственным с этой терпимостью, мы можем быть уверены, что никакое другое приложение не развернуто на Ingress-Pool
Анкет
Наконец, мы даем Трафик некоторые аргументы : Точки входа для http, https и проверки здоровья (Ping in traefik lingo). Мы также включим Kubernetes провайдер, который позволяет нам использовать Пользовательские ресурсы Анкет Давайте создадим их сейчас:
kubectl create --save-config -f resource.yaml
Теперь мы можем добавить Маршруты к Трафик Используя наши новые пользовательские ресурсы:
kubectl create --save-config -f route.yaml
Два маршрута теперь соединяют «Интернет» и «Websecure». nginx-web услуга. Теперь мы должны быть в состоянии увидеть HTML -контент, обслуживаемый нам nginx Когда мы подключаемся к нашему статическому IP -адресу.
Пожалуйста, наслаждайтесь вашим кластером-на-бюджетом ответственно!
Оригинал: «https://dev.to/verkkokauppacom/how-to-kubernetes-for-cheap-on-google-cloud-1aei»