Статьи

Введение в Докер и Кубернетес

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

Виртуализация и, в последнее время, контейнеризация обеспечивают гибкое совместное использование ресурсов и управление ими. Docker сделал контейнеризацию популярной. Ознакомьтесь с этой статьей Envato Tuts +, где вы найдете отличное введение: Руководство автостопом по докеру и модулю .

Google много лет эксплуатирует свои огромные программы и центры обработки данных по контейнеризации и накопила большой опыт и ноу-хау. Kubernetes — это проект Google с открытым исходным кодом, который приносит все эти знания в массы.

В этой статье я кратко расскажу о Docker, а затем углублюсь в Kubernetes. В качестве примера я буду использовать сервис REST API цитаты Python 3. Давай прыгнем.

Сервис цитат — это REST API, который позволяет вам добавлять цитаты и получать список всех цитат. Он реализован в виде веб-службы Python 3 с использованием превосходной библиотеки объятий . Он предоставляет одну конечную точку с именем / quotes. Вы можете получить все цитаты или опубликовать новую цитату. Давайте добавим несколько цитат:

curl http://localhost:8000/quotes -d "quote=TV is chewing gum for the eyes. ~ Frank Lloyd Wright" curl http://localhost:8000/quotes -d "quote=It is better to die on your feet than live on your knees. ~ Emiliano Zapata" curl http://localhost:8000/quotes -d "quote=We must be very careful when we give advice to younger people: sometimes they follow it! ~ Edsger W. Dijkstra"

Если вы перейдете по http://localhost:8000/quotes вы получите: [ "TV is chewing gum for the eyes. ~ Frank Lloyd Wright", "It is better to die on your feet than live on your knees. ~ Emiliano Zapata", "We must be very careful when we give advice to younger people: sometimes they follow it! ~ Edsger W. Dijkstra" ] Если вы просто хотите посмотреть автоматически сгенерированную документацию HUG, перейдите по http://localhost:8000

{ "404": "The API call you tried to make was not defined. Here's a definition of the API to help you get going :)", "documentation": { "/quotes": { "GET": { "examples": [ "http://localhost:8000/quotes" ], "outputs": { "content_type": "application/json", "format": "JSON (Javascript Serialized Object Notation)" } }, "POST": { "outputs": { "content_type": "application/json", "format": "JSON (Javascript Serialized Object Notation)" }, "inputs": { "quote": { "type": "Basic text / string value" } } } } } }

Я не буду объяснять слишком много о Docker, а только применить его к службе цитат.

Сначала нам нужен Dockerfile . Он выполняет следующие шаги:

  1. Основано на последнем образе Ubuntu
  2. Устанавливает Python 3 и несколько других зависимостей
  3. Скопируйте каталог цитатного сервиса
  4. Устанавливает зависимости службы цитат из файла require.txt
  5. Выставляет 8000 порт
  6. Запустите цитатный сервис через hug

Следующим шагом является создание образа Docker. Это так просто, как:

docker build .

Мне также нравится отмечать изображения:

docker tag 715624b7e22a g1g1/quote-service

g1g1 — это мое имя пользователя в Docker Hub.

Чтобы убедиться, что изображение было успешно построено, введите:

Вы должны увидеть новое изображение:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 715624b7e22a g1g1/quote-service "/bin/sh -c 'hug -fa" 4 hours ago Up 35 minutes 0.0.0.0:8000->8000/tcp agitated_northcutt

Когда вы создаете образ, вы также можете отправить его в Docker Hub , чтобы его могли использовать другие люди (или вы сами на другом компьютере).

docker push g1g1/quote-service

Обратите внимание, что вам нужно создать учетную запись в Docker Hub и войти в систему локально, используя:

docker login

Ok. Давайте запустим образ сервиса котировок и выставим порт 8000 хосту.

docker run -i -t -p 8000 g1g1/quote-service

Вы должны увидеть: /#######################################################################\ `.----``..-------..``.----. :/:::::--:---------:--::::://. .+::::----##/-/oo+:-##----::::// `//::-------/oosoo-------::://. ## ## ## ## ##### .-:------./++o/o-.------::-` /#######################################################################\ `.----``..-------..``.----. :/:::::--:---------:--::::://. .+::::----##/-/oo+:-##----::::// `//::-------/oosoo-------::://. ## ## ## ## ##### .-:------./++o/o-.------::-` /#######################################################################\ `.----``..-------..``.----. :/:::::--:---------:--::::://. .+::::----##/-/oo+:-##----::::// `//::-------/oosoo-------::://. ## ## ## ## ##### .-:------./++o/o-.------::-` ## ## ## ## # # ----.-./+o+:..----. .: ///. ######## ## ## ## `----.-::::::------ `.-:::://. ## ## ## ## ## #### ://::--. `----.-::::::------ `.-:::://. ## ## ## ## ## #### ://::--. -: ...-----...` `:--::::::-.` ## ## ## ## ## ## :/:::::::::-:- «.. ::::: -. ## ## #### ###### .--:::::::. .:::. .--:::::::. .:::. « .. ::. . :: ОБЪЯВИТЬ API БУДУЩЕГО :: -.: — — :: ::- VERSION 1.9.6 :: — — :: -::- — :: — ########### ################################################## ########### Copyright (C) 2015 Тимоти Эдмунд Кросли по лицензии MIT

Обслуживание на порте 8000… « `Это довольно круто. Прежде чем пытаться получить доступ к удивительной службе котировок через порт 8000, вам может потребоваться выполнить дополнительную работу в зависимости от вашей среды.

Если вы работаете в Mac OS X с использованием VirtualBox и док-машины , вам может потребоваться опубликовать порт 8000 на VirtualBox, чтобы сделать его доступным на хосте.

Предполагая, что вы попытались перейти по http://localhost:8000/quotes . О нет. Внутренняя Ошибка Сервера! Что произошло?

Давайте посмотрим на код:

redis_host = os.environ.get('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis(host=redis_host, port=6379, db=0)

Служба цитирования пытается подключиться к серверу Redis. Адрес хоста может быть настроен как переменная среды, и если он не установлен, по умолчанию будет использоваться localhost. К сожалению, redis не установлен по умолчанию и не работает внутри контейнера. Давайте это временно исправим. Чтобы получить доступ оболочки в контейнер, введите следующую команду:

docker exec -it 715624b7e22a /bin/bash

Затем вы получите доступ оболочки к контейнеру и сможете установить redis:

root@715624b7e22a:/quote-service# apt-get install redis-server

Наконец, запустите redis: root@715624b7e22a:/quote-service# redis-server [25] 29 Nov 00:14:24.546 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 2.8.4 (00000000/0) 64 bit .-`` .- root@715624b7e22a:/quote-service# redis-server [25] 29 Nov 00:14:24.546 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 2.8.4 (00000000/0) 64 bit .-`` .- root@715624b7e22a:/quote-service# redis-server [25] 29 Nov 00:14:24.546 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 2.8.4 (00000000/0) 64 bit .-`` .- . « `\ / ., » -._ (‘, .- | ,) Запуск в автономном режиме | -._ -… — __...-. -._|' .- ‘| Порт: 6379 | -._ . / .- ‘| PID: 25 -._ -. -./ _.-' _.-' | -. -._ -. .- ‘_.-‘_.-‘ | | -._ -._ _.-‘_.- ‘| http://redis.io -._ -._ -.__.-'_.-' _.-' | -._ -._ -. .- ‘_.-‘ .- ‘| | -._ -._ .- ‘ .-‘ | -._ -. -.__.-'_.-' _.-' -. -.__.-' _.-' -._ _.- ‘`-.__.-‘

[25] 29 ноя. 00: 14: 24.547 # Сервер запущен, версия Redis 2.8.4 [25] 29 ноября 00: 14: 24.547 # ПРЕДУПРЕЖДЕНИЕ overcommit_memory установлено в 0! Фоновое сохранение может завершиться неудачей при нехватке памяти Чтобы устранить эту проблему, добавьте «vm.overcommit_memory = 1» в /etc/sysctl.conf и затем перезагрузите компьютер или выполните команду «sysctl vm.overcommit_memory = 1», чтобы это вступило в силу. [25] 29 ноя. 00: 14: 24.547 * БД загружена с диска: 0,000 секунд. [25] 29 ноября 00: 14: 24.547 * Сервер готов к приему соединений через порт 6379. и получение кавычек через конечную точку http://localhost:8000/quotes .

Размещение приложения (служба цитат) и базы данных (Redis) работает в крайнем случае для одного сервера. Но, очевидно, это не масштабируется. Введите Kubernetes.

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

Есть много способов настроить кластер Kubernetes. Kubernetes может работать на голом железе, на движке Google Container, на AWS, на голом металле (с Linux) и локально на любой ОС, использующей виртуальные машины. Для этой статьи я создал кластер из одного мастера и двух миньонов, используя кластер CoreOS OSX GUI k8s . В Mac OS X имеется небольшое меню, где вы можете получить доступ ко многим инструментам управления кластером.

Следуйте инструкциям, и вам будет хорошо в кратчайшие сроки.

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

Я буду использовать командную строку с этого момента.

kubectl — швейцарский армейский нож Kubernetes. Вы можете полностью контролировать и управлять своим кластером, не выходя из консоли, используя только kubectl.

Вот список команд: get Display one or many resources describe Show details of a specific resource create Create a resource by filename or stdin update Update a resource by filename or stdin. delete Delete a resource by filename, stdin, resource and ID, or by resources and label selector. namespace SUPERCEDED: Set and view the current Kubernetes namespace log Print the logs for a container in a pod. rolling-update Perform a rolling update of the given ReplicationController. resize Set a new size for a Replication Controller. exec Execute a command in a container. port-forward Forward one or more local ports to a pod. proxy Run a proxy to the Kubernetes API server run-container Run a particular image on the cluster. stop Gracefully shut down a resource by id or filename. expose Take a replicated application and expose it as Kubernetes Service label Update the labels on a resource config config modifies kubeconfig files cluster-info Display cluster info api-versions Print available API versions. version Print the client and server version information. help Help about any command get Display one or many resources describe Show details of a specific resource create Create a resource by filename or stdin update Update a resource by filename or stdin. delete Delete a resource by filename, stdin, resource and ID, or by resources and label selector. namespace SUPERCEDED: Set and view the current Kubernetes namespace log Print the logs for a container in a pod. rolling-update Perform a rolling update of the given ReplicationController. resize Set a new size for a Replication Controller. exec Execute a command in a container. port-forward Forward one or more local ports to a pod. proxy Run a proxy to the Kubernetes API server run-container Run a particular image on the cluster. stop Gracefully shut down a resource by id or filename. expose Take a replicated application and expose it as Kubernetes Service label Update the labels on a resource config config modifies kubeconfig files cluster-info Display cluster info api-versions Print available API versions. version Print the client and server version information. help Help about any command

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

Стручок является основной единицей развертывания и управления в Kubernetes. Стручок — это группа из одного или нескольких контейнеров. Вы можете указать модуль, используя выделенный файл YAML или как часть службы Kubernetes (см. Ниже). Модуль всегда развертывается на одном хосте, и все контейнеры в модуле могут обращаться друг к другу через локальный хост. Все контейнеры капсулы всегда запускаются, останавливаются и масштабируются вместе.

Чтобы проверить все модули в кластере, введите:

kubectl get pods

Результат будет примерно таким: NAME READY STATUS RESTARTS AGE quote-frontend-4kyns 1/1 Running 0 1h quote-frontend-v4xk1 1/1 Running 0 1h quote-store-controller-y4ya1 1/1 Running 0 23h ### тома

Контейнеры не должны поддерживать постоянное состояние. Когда контейнер падает или перезапускается, его локальная файловая система стирается. Если вы хотите сохранить постоянное состояние, вы должны использовать постоянные тома. Поскольку все в Kubernetes основано на модулях, вам также необходимо определять объемы в модулях. Вот файл определения модуля с постоянным томом: apiVersion: v1 kind: Pod metadata: name: quote-store labels: app: quote-api role: persistent-storage spec: containers: - name: redis image: redis volumeMounts: - name: quote-store-volume mountPath: /data/redis volumes: - name: quote-store-volume emptyDir: {} Обратите внимание, что постоянные тома ограничены узлом и будут выдерживать сбои и перезапуски контейнеров, но не сбои узла / узла , Вам все еще нужно выполнить работу по репликации и резервному копированию важных данных.

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

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

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

Контроллеры репликации указываются в файле YAML, конечно. Вот пример: « `apiVersion: v1 вид: ReplicationController

metadata: name: quote-frontend spec: replicas: 2 # селектор идентифицирует набор модулей, которые этот контроллер репликации # отвечает за управление селектором: app: quote-api роль: frontend # podTemplate определяет «cookie cookie», используемый для создания # новые модули при необходимости template: metadata: tags: # Важно: эти метки должны соответствовать селектору, указанному выше # Сервер API применяет это ограничение. app: quote-api роль: внешний интерфейс spec: контейнеры: — имя: quote-service image: g1g1 / quote-service env: — имя: GET_HOSTS_FROM # значение: dns значение: env ports: — containerPort: 8000 « `Спецификация шаблона для контейнера quote-service используется образ g1g1 / quote-service, который я ранее отправил в Docker Hub. Обратите внимание на раздел env где обмен информацией между модулями может происходить через DNS или переменные среды.

Чтобы создать контроллер репликации, введите:

kubectl create -f <replication controller filename>

Чтобы просмотреть текущие контроллеры репликации в кластере, введите:

kubectl get rc

Вы должны увидеть что-то вроде: CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS AGE quote-frontend quote-service g1g1/quote-service app=quote-api,role=frontend 2 1h quote-store-controller master redis app=quote-api,role=persistent-storage 1 1d ### Сервисы

Служба предоставляет свой модуль остальной части кластера и, возможно, извне через переменные среды или DNS. Например, служба цитат состоит из двух типов модулей: модуль магазина Redis и интерфейсный модуль. Внешний контейнер должен иметь возможность находить контейнер хранилища, а клиенты должны иметь возможность подключаться к единственной общедоступной конечной точке для доступа к службе.

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

apiVersion: v1 kind: Service metadata: name: quote-frontend spec: type: NodePort ports: - port: 8000 # the port that this service should serve on # the container on each pod to connect to, can be a name # (eg 'www') or a number (eg 80) targetPort: 80 protocol: TCP # just like the selector in the replication controller, # but this time it identifies the set of pods to load balance # traffic to. selector: app: quote-api role: frontend apiVersion: v1 kind: Service metadata: name: quote-frontend spec: type: NodePort ports: - port: 8000 # the port that this service should serve on # the container on each pod to connect to, can be a name # (eg 'www') or a number (eg 80) targetPort: 80 protocol: TCP # just like the selector in the replication controller, # but this time it identifies the set of pods to load balance # traffic to. selector: app: quote-api role: frontend внешний apiVersion: v1 kind: Service metadata: name: quote-frontend spec: type: NodePort ports: - port: 8000 # the port that this service should serve on # the container on each pod to connect to, can be a name # (eg 'www') or a number (eg 80) targetPort: 80 protocol: TCP # just like the selector in the replication controller, # but this time it identifies the set of pods to load balance # traffic to. selector: app: quote-api role: frontend #### srv-quote-store.yaml apiVersion: v1 kind: Service metadata: name: quote-store spec: ports: - port: 6379 # the port that this service should serve on targetPort: 6379 # just like the selector in the replication controller, # but this time it identifies the set of pods to load balance # traffic to. selector: app: quote-api role: persistent-storage apiVersion: v1 kind: Service metadata: name: quote-store spec: ports: - port: 6379 # the port that this service should serve on targetPort: 6379 # just like the selector in the replication controller, # but this time it identifies the set of pods to load balance # traffic to. selector: app: quote-api role: persistent-storage Хост и порт каждой службы доступны для каждого контейнера в кластере. Например, если вы запускаете интерактивную оболочку в одном из контейнеров внешнего интерфейса:

kubectl quote-frontend-4kyns exec -i -t bash

Затем вы можете проверить, что среда содержит необходимую информацию о хосте и порте для подключения к хранилищу котировок. root@quote-frontend-4kyns:/quote-service# env | grep STORE QUOTE_STORE_PORT_6379_TCP_ADDR=10.100.234.192 QUOTE_STORE_PORT_6379_TCP_PROTO=tcp QUOTE_STORE_SERVICE_PORT=6379 QUOTE_STORE_PORT_6379_TCP_PORT=6379 QUOTE_STORE_PORT=tcp://10.100.234.192:6379 QUOTE_STORE_PORT_6379_TCP=tcp://10.100.234.192:6379 QUOTE_STORE_SERVICE_HOST=10.100.234.192 root@quote-frontend-4kyns:/quote-service# env | grep STORE QUOTE_STORE_PORT_6379_TCP_ADDR=10.100.234.192 QUOTE_STORE_PORT_6379_TCP_PROTO=tcp QUOTE_STORE_SERVICE_PORT=6379 QUOTE_STORE_PORT_6379_TCP_PORT=6379 QUOTE_STORE_PORT=tcp://10.100.234.192:6379 QUOTE_STORE_PORT_6379_TCP=tcp://10.100.234.192:6379 QUOTE_STORE_SERVICE_HOST=10.100.234.192 Просто, чтобы освежить вашу память, это именно то, что делает интерфейс: redis_host = os.environ.get('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis(host=redis_host, port=6379, db=0) ## Заключение

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

Что касается Kubernetes, есть несколько других альтернатив для управления несколькими мультиконтейнерами и оркестровки, таких как действующий Mesos и собственный состав Docker. Я считаю, что Кубернетес более архитектурно обоснован, обладает большим импульсом и лучше, чем альтернативы.