Глава 2. Введение в Kubernetes

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

  • Краткую историю Kubernetes - откуда он пришёл к нам?

  • Как он работает?

  • Каковы варианты применения Kubernetes и кто его применяет?

  • Зачем вам исполнять на серверах решения без сервера?

Краткое изложение истории Kubernetes

Прежде чем мы обсудим откуда Kubernetes появился, мы должны быстро обсудить что это такое. Он произносится как koo-ber-net-eez (ку- бе- не- тиз) и иногда именуется как K8s. Kubernetes является Греческим именем кормчего или управляющего кораблём, что весьма кстатит, если вы полагаете, что Kubernetes предназначен для этого. Веб- сайт проекта, который вы можете найти по ссылке https://kubernetes.io/ описывает его так:

"Система с открытым исходным кодом, для автоматизации развёртывания, масштабирования и управления контейнеризованными приложениями."

Данный продукт восходит своими корнями к внутреннему продукту Google под названием Born. На протяжении длительного времени Google применял её как технологию контейнеров, задолго до того, как появилась шумиха вокруг Docker.

Control groups

Собственное путешествие Google в мир контейнеров началось в 2006, когда два его инженера приступили к проекту с названием control groups (cgroups, группы управления). Это функциональность самого ядра Linux, которая делает возможным изолировать ресурсы, такие как ОЗУ, ЦПУ, сетевую среду и дисковый ввод/ вывод в коллекцию процессов. Первоначально cgroups были реализованы в 2007, а в начале 2008 эта функциональность была влита в основное направление ядра Linux версии 2.6.24.

[Замечание]Замечание

Вы можете найти замечания по выпуску версии 2.6.24 ядра Linux по ссылке https://kernelnewbies.org/Linux_2_6_24. Вы можете обнаружить информацию о введении cgroups в пункте 10 в списке Важных вещей, в котором обсуждается та инфраструктура, которая позволяет cgroups зацепиться в ядре.

lmctfy

Несколько лет спустя, в октябре 2013, Google выпустил версию с открытым исходным кодом своей собственной системы контейнеров с наименованием lmctfy, что на самом деле было сокращением Let Me Contain That For You (Позвольте мне содержать это для вас). Именно этот инструмент они применяли в своих собственных серверах чтобы сделать возможным применение в них контейнеров приложений, и он был разработан как альтернатива для LXC.

lmctfy, LXC и Docker, все они занимали одно и то же место. Чтобы прекратить это, Google остановил все разработки lmctfy в 2015. Соответствующая страница GitHub анонсировала состояние того, что Google вступил в коллаборацию с Docker и они портировали все основные понятия lmctfy в libcontainer.

Borg

Именно здесь на сцену вступает проект с наименованием Borg. Google использует очень много контейнеров, и когда я говорю очень много, это означает очень много. В мае 2014 Джо Бида из Google провёл презентацию в Gluecon с наименованием Контейнеры в масштабе. И вот всего лишь несколько выдернутых из этой презентации цитат:

"В Google всё работает в контейнерах."

И то, о чём больше всего говорят:

"Мы запускаем более двух миллиардов контейнеров в неделю."

Это работает с примерной скоростью в 3 000 в секунду и, между прочим, было упомянуто, что данное число не включает в себя какие бы то ни было долгоживущие контейнеры.

Хотя Джо и вдавался в подробности того, как Google использовал контейнеры в то время, он ничего конкретного не упомянул о проекте Borg, вместо этого просто сославшись на него как некий планировщик кластера.

Самый последним выводом в этой презентации стал слайд с названием Описание поверх обязательств (Declarative Over Imperative), который ввёл следующие концепции:

  • Обязательство (Imperative): Запустите этот контейнер на данном сервере.

  • Описание (Declarative): Исполните 100 копий этого контейнера с нижней целью <= 2 задач в любой момент времени.

Данное понятие объясняет как Google имеет возможность запускать свои 2 миллиарда контейнеров в неделю не имея возможности действенно управлять более чем 2 миллиардами контейнеров.

Только в 2015 году Google опубликовал документ "Крупномасштабное управление кластерами в Google при помощи Borg", который на самом деле пролил свет на те практические приёмы решения архитектуры, которые были приняты в планировщике кластера, упомянутом Джо Бида в предыдущем году.

Данная статья повествует о том, как внутренний инструментарий Google с названием Borg исполняет тысячи заданий, которые составляют почти все приложения Google в кластерах, составленных из десятков тысяч машин.

Затем выясняется, что ориентированные на клиента службы, такие как Google Mail, Google Docs и Google Search, все они обслуживаются из кластеров под управлением Borg, также как и их собственные внутренние инструменты. В документе подробно описывается язык описания заданий, который могут применять пользователи для определения своих собственных желательных состояний, что делает для пользователя простым развёртывание его приложений не заботясь обо всех шагах, необходимых для развёртывания их приложения в конфигурации с высокой доступностью в инфраструктуре Google.

Я бы порекомендовал вам прочесть всю эту статью, так как она предоставляет исключительный обзор того как Google подходит к своим собственным службам контейнеров.

Кроме того, если вам это будет интересно: название Borg было дано в честь инопланетной гонки из телешоу "Звёздный путь: Следующее поколение".

Седьмой проект

В 2014 Джо Бида, Брендан Бёрнс и Крейг Мак-Лакки были объединены Брайаном Грантом и Тимом Хокином в Седьмой проект.

Этот проект именуемый вслед за персонажем Стар трека как Седьмая из девяти имел целью создать дружественную версию Borg. Ко времени первой фиксации данный проект получид внешнее название, Kubernetes.

[Замечание]Замечание

Вы можете видеть первую фиксацию по адресу https://github.com/kubernetes/kubernetes/commit/2c4b3a562ce34cddc3f8218a2c4d11c7310e6d56, а первая действительно стабильная версия, которая появилась четырьмя месяцами позднее может быть обнаружена по ссылке https://github.com/kubernetes/kubernetes/releases/tag/v0.4.

Изначально основная цель Kubernetes состояла в принятии всего, что было изучено в Born и исполнении его больших кластеров контейнеров, а открытый исходный код для него как некий способ привлечения потребителей в собственную общедоступную Облачную платформу Google - что послужило именно тем, почему всё ещё можно обнаружить ссылку на оригинальную страницу GitHub этого проекта по адресу https://github.com/GoogleCloudPlatform/kubernetes/.

Однако к моменту его выпуска 1.0 в июле 2015 Google осознал, что он быстро становится чем- то большим чем то что они ожидали, и они объединили усилия с Linux Foundation, Twitter, Intel, Docker и VMware (чтобы перечислить часть имён) и оформили Cloud Native Computing Foundation. Как часть этого нового партнёрства, Google пожертвовал свой проект Kubernates в качестве основы для этой новой группы.

С тех пор прочие проекты присоединились к Kubernetes, например:

  • Prometheus (https://prometheus.io/), первоначально разрабатывавшийся SoundCloud, является базой данных временных последовательностей, которая иожет применяться для хранения метрик.

  • Fluentd (https://www.fluentd.org), является коллектором данных, который позволяет вам получать данные из множества различных источников, фильтровать или нормализовывать их, а затем маршрутизировать их в механизм хранения, такой как Elasticsearch, MongoDB или Hadoop (чтобы перечислить только часть из них).

  • containerd (http://containerd.io/), является контейнером времени исполнения с открытым исходным кодом, изначально разрабатывавшимся Docker для реализации стандарта Open Container Initiative.

  • CoreDNS (https://coredns.io/), является некоторой службой DNS, целиком построенной на подключаемых иодулях, что означает что вы можете создавать службы DNS, которые обычно являются чрезвычайно сложными в настройке.

Помимо всего этого новые участники, такие как AWS, Microsoft, Red Hat и Oracle, все они кредитовали собственную поддержку и ресурсы для поддержки проектов.

Обзор Kubernetes

Теперь, когда у нас имеется понимание того как появился Kubernetes, нам следует пройти по всем разнообразным компонентам, которые составляют обычный кластер Kubernetes.

Сам по себе Kubernetes написан на Go. Хотя страница проекта в GitHub показывает, что в настоящее время проект состоит на из 84.9% Go, а прочее из 5.8% HTML, 4.7% Python и 3.3% Shell (а всё оставшееся является файлами настройки/ спецификации и тому подобное), причём всё это снабжено документацией и сценариями подсказок.

[Замечание]Замечание

Go является языком программирования,разработанным и представленным в открытом исходном коде Google, который определяет его как Быстрый, со статической типизацией компилируемым языком, который воспринимается как язык с динамическими типами и наличием интерпретации. Для получения дополнительной информации обратитесь к https://golang.org/.

Компоненты

В Kubernetes имеются две основные роли сервера: хозяев и узлов (masters и nodes); каждая из этих ролей состоит из нескольких компонентов.

Серверы хозяев являются мозгом всего кластера и они принимают решения по поводу того где поды (более подробно о них в следующем разделе) развёртываются в данном кластере, а также воздействуя на и просматривая состояние не только самого кластера, но и подов.

Центральными компонентами сервера хозяина являются:

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

  • etcd: etcd: описывается как хранилище пар ключ- значение, которое Kubernates применяет для хранения значения состояния вашего кластера.

  • kube-controller-manager: эта служба выполняет всю работу за сценой по сопровождению вашего кластера. Она следит со присоединением узлов и покиданием ими кластера, обеспечивая правильное число исполняемых подов, а также того что все они в жизнеспособном состоянии и тому подобное.

  • cloud-controller-manager: эта служба новая в Kubernetes. Она работает совместно с kube-controller-manager и её цель состоит во взаимодействии с API поставщика облачного решения такого как AWS, Google Cloud или Microsoft Azure. Неким примером той задачи, которую ей предстоит выполнить состоит в том, что если некий узел подлежит удалению из вашего кластера, она будет проверять API служб вашего облачного решения чтобы смотреть присутствует ли всё ещё этот узел. Если это так, то в облаке могут иметься проблемы; если нет, тогда скорее всего ваш узел был удалён за счёт эскалации события.

  • kube-scheduler: она выбирает где должны быть запущены поды на основании последовательностей правил, загруженности и доступности.

Следующими мы имеем узлы. После того как он развёрнут, хозяин взаимодействует с компонентами, которые установлены в узлах чтобы оказывать воздействие на сам кластер; имеено здесь исполняются ваши поды.

Вот те компоненты, которые составляют все узлы:

  • kubelet: это основной исполняемый в узле компонент. Он отвечает за приём инструкций и отправки назад серверам хозяев отчётов.

  • kube-proxy: эта служба помогает взаимодействию вашего кластера. Она выступает как основной посредник для всего сетевого обмена между вашими узлами, а также способна настраивать перенаправление TCP/ UDP или же выступать в качестве карусельного (round- robin) балансировщика нагрузки для некоторого числа серверов.

  • docker или rkt: это реальные механизмы контейнеров в ваших узлах. Служба kubelet взаимодействует с ними для запуска контейнеров и управления ими в каждом из ваших узлов кластера. На протяжении последующих глав мы рассмотрим запущенные узлы, исполняющими оба вида этих служб.

  • supervisord: этот процесс управляет и мониторит сопровождение доступности во всех узлах всех прочих служб, таких как kubelet, docker и rkt.

  • fluentd: данная служба осузествляет помощь с регистрацией в журнале уровня кластера.

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

Поды и службы

Как уже упоминалось, Kubernetes не развёртывает контейнеры; вместо этого он запускает поды {Прим. пер.: коконы, стручки}. В его наиболее простом виде некий под и на самом деле может быть отдельным контейнером; однако обычно под составлен из контейнера, хранилища и сетевой среды.

[Замечание]Замечание

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

Представляйте себе под как законченное приложение; например, если вы исполняете простое веб приложение, оно скорее всего будет работать с отдельным контейнером NGINX - файл определения пода для него будет выглядеть как- то так:


apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 8080
 	   

Как вы можете заметить, мы предоставляем некие простые метаданные о своём поде, которые в данном случае всего лишь собственно название чтобы мы могли его идентифицировать. Затем у нас имеется определённым отдельный контейнер, который исполняет самый последний образ NGINX из хаба Docker, а также выставленный порт 8080.

Как только он будет установлен, данный под становится достаточно бесполезным, так как единственное, что он намеревается отображать, так это страницу Welcome to nginx! Далее нам следует добавить некий том для хранения в нём данных нашего вебсайта. Для осуществления этого наш файл определения пода должен бы выглядеть как- то так:


apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - mountPath: /srv/www
      name: web-data
      readOnly: true
    ports:
    - containerPort: 8080
volumes:
- name: web-data
  emptyDir: {}
 	   

Как вы можете видеть, теперь мы создали некий том с названием web-data и смонтировали его доступным только для чтения в /srv/www, что является установленным по умолчанию корнем в нашем контейнере NGINX. всё ещё имеется одна бессмыслица, так как наш том является пустым, что означает,что все посетители будут видеть страницу 404.

Давайте добавим второй контейнер, который будет осуществлять синхронизацию нашего HTML вебсайта из корзины (bucket) Amazon S3^


apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - mountPath: /srv/www
      name: web-data
      readOnly: true
    ports:
    - containerPort: 8080
- name: sync
  image: ocasta/sync-s3:latest
  volumeMounts:
  - mountPath: /data
    name: web-data
    readOnly: false
  env:
  - ACCESS_KEY: "awskey"
    SECRET_KEY: "aws_secret"
    S3_PATH: "s3://my-awesome-website/"
    SYNC_FROM_S3: "true"
volumes:
- name: web-data
  emptyDir: {}
 	   

Теперь у нас имеются два контейнера: собственно сам NGINX, а также теперь и контейнер, исполняющий команду s3 sync (https://github.com/ocastastudios/docker-sync-s3/). Он будет копировать все данные нашего вебсайта из корзины Amazon S3 с названием my-awesome-website в том, который также совместно применяется и самим контейнером NGINX. Это означает, что у нас теперь имеется некий вебсайт; на данный момент заметим, что поскольку мы желаем осуществлять запись в этот том, мы не монтируем его доступным только для чтения.

В данный момент мы представляем себе что всё хорошо; у нас имеется под, обслуживающий наш вебсайт, который оснащается из какой- то корзины Amazon S3, причём всё это так и есть. У нас имеется исполняющийся под, однако нам необходимо выставить этот под в определённую сетевую среду чтобы иметь возможность осуществлять к нему доступ из браузера.

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


apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
 	   

Как вы можете отметить, определение данной службы выглядит аналогично первому поду. Мы устанавливаем название, применяя свой раздел метаданных. Затем мы выбираем наш под NGINX и устанавливаем соответствие порта 80 в порт 8080, который является портом ожидания нашего пода.

Как уже упоминалось, мы рассмотрим всё это более подробно в своей следующей главе, когда мы запустим свой первый кластер Kubernetes, однако на данный момент это должно предоставить вам хорошее понимание того как Kubernetes собирает всё воедино./p>

Рабочие нагрузки

В предыдущей главе мы взглянули на поды и службы. Хотя они могут запускаться вручную, для управления подами вы также можете применять и контроллеры. Такие контроллеры делают возможным исполнение различных типов рабочих нагрузок. Мы собираемся сделать краткий осмотр различных типов контроллеров, а также обсудить когда вы их можете применять.

ReplicaSet

ReplicaSet может применяться для запуска и сопровождения некоторого числа копий одного и того же пода. Например, применяя под NGINX, который мы использовали в предыдущем разделе, мы можем создать ReplicaSet, который запустит три копии одного и того же пода. Затем можно выполнять балансировку нагрузки обмена между этими тремя подами.

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

Развёртывания

Одна из вещей, которую вы полагаете возможным выполнять с помощью ReplicaSet, это накат обновлений и их откат. К сожалению, ReplicaSet может реплицировать только одну и ту же версию некоторого пода; к счастью, именно здесь на помощи приходят Развёртывания (deployments).

Контроллер развёртываний разработан для обновления ReplicaSet или подов. Давайте воспользуемся NGINX в качестве примера. Как вы можете видеть из предыдущего определения, у нас имеются три реплики, причём все они работают с версией 1.9.14 NGINX:


apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.14
        ports:
        - containerPort: 80
 	   
[Замечание]Замечание

kubectl является клиентом командной строки Kubernetes; мы рассмотрим его в деталях в нашей следующей главе.

Мы можем развернуть это воспользовавшись следующей командой:


$ kubectl create -f nginx-deployment.yamlо
		

Теперь, допустим, мы хотим обновить имеющуюся версию применяемого нами образа NGINX. Нам просто нужно выполнить следующую команду:


$ kubectl set image deployment/nginx-deployment nginx=nginx:1.13.5 deployment "nginx-deployment" image updated
		

Она обновит все поды один за другим пока все имеющиеся поды не будут исполнять новую версию NGINX.

StatefulSets

Этот контроллер является новым в Kubernetes и он был разработан на замену PetSets. Как вы можете угадать из его названия, поды сопровождают своё состояние как часть развёртывания. Они разработаны для того чтбы иметь:

  • Согласованные уникальные сетевые идентификаторы на протяжении всего жизненного цикла пода

  • Постоянное хранилище

  • Искусные развёртывание и масштабирование выполняются в определяемом вами порядке

  • Определяемые пользователем и управляемые автоматически накатывающие обновления

Таким образом, хотя и имеется изменение в названии, вам следует представлять себе StatefulSets как домашних питомцев, а ReplicaSets как стадных животных.

Варианты применения Kubernetes

Как мы уже касались этого в данной главе, Kubernetes может работать достаточно много где, начиная просто с вашей машины (что мы рассмотрим в следующей главе), от расположенного на вашей площадке оборудования инфраструктуры виртуальных машин вплоть до потенциального охвата сотен экземпляров общедоступных облачных решений а AWS, Microsoft Azure или Google Cloud. На самом деле вы даже можете охватывать сразу несколько сред при помощи кластера Kubernetes.

Это означает что вы получаете состоятельную практику независимо от того где вы исполняете своё приложение, а помимо этого вы можете воспользоваться преимуществом лежащих в основе ваших платформ функций, таких как балансировка нагрузки, постоянное хранилище, а также автоматическое масштабирование, причём без какой бы то ни было необходимости на самом деле разрабатывать приложение, которое было бы информировано о том, исполняется ли оно, скажем в AWS, либо в Microsoft Azure.

Одна из наиболее распространённых тенденций, которую вы отмечаете при прочтении историй успеха, состоит в том, что люди говорят о том, что они не запераются в одном конкретном поставщике услуг. Так как Kubernetes является решением с открытым исходным кодом, они не блокируются какими- либо затратами на лицензирование. Если у них имеется некая проблема, либо они желают добавить некую функциональность, они могут погрузиться непосредственно в исходный код и внести изменения, они также могут вложить любые свои изменения обратно в этот проект с помощью запроса на активную рассылку (pull request).

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

Другим распространённым вариантом применения являются рабочие команды, применяющие Kubernetes в качестве платформы Инфраструктуры как Службы (IaaS, Infrastructure as Service). Это позволяет им предлагать своим разработчикам ресурсы, которые они могут потреблять через API, всемирный веб, а также CLI, что означает, что они легко могут прицепиться к своему собственному рабочему процессу. Kubernetes также предоставляет состоятельную среду для локальной разработки, начиная с приёмочного тестирования пользователем (UAT, user acceptance testing, вплоть до конечного исполнения их приложений в промышленной среде.

Именно это одна из основных причин, по которой применение Kubernetes для исполнения ваших рабочих нагрузок без серверов является хорошей мыслью. Вы не зашорены одним определённым поставщиком услуг, таким как AWS или Microsoft Azure. На самом деле вы должны представлять себе Kubernetes в качестве облачной платформы сродни одной из тех, что мы рассмотрели в Главе 1, Ландшафт без серверов; она имеет веб- консоль, некий API, а также клиента командной строки.

Ссылки

Имеется ряд рассмотрений конкретных вариантов Kubernetes, в которых пользователи вводятся в подробности их миграции при помощи Kubernetes:

Также имеются обсуждения, интервью и презентации, например, такие:

Наконец, вы можете прочесть дополнительную информацию о Cloud Native Computing Foundation здесь: https://www.cncf.io/.

Выводы

В этой главе мы достаточно много говорили о том, откуда взялся Kubernetes, а также мы обсудили некоторые из вариантов применения. Также мы взглянули на некоторые его основные функции.

В своей следующей главе мы собираемся получить практические навыки Kubernetes посредством локальной установки Minikube. Как только мы получим локальную установку Kubernetes, мы станем готовы проследовать Главой 4, Введение в функционирование Kubeless, в которой мы начнём развёртывать свои первые функции без сервера в Kubernetes.