Некоторые приложения должны иметь возможность получать информацию о себе. Паттерн Self Awareness (Самоанализ) описывает Kubernetes Downward API — простой механизм для самоанализа и внедрения метаданных в приложения.
Большинство облачных приложений не имеют состояния и отличительной идентичности. Однако иногда даже этим приложениям бывает необходима информация о себе и об окружении, в котором они выполняются. Это может быть информация, известная только во время выполнения, такая как имя пода, IP-адрес и имя хоста, на котором размещено приложение. Или другая статическая информация, определяемая на уровне пода, такая как конкретные запросы и лимиты ресурсов, или динамическая, такая как аннотации и метки, которые могут изменяться пользователем во время выполнения.
Например, в зависимости от ресурсов, доступных контейнеру, приложение может настраивать размер пула потоков выполнения, изменять алгоритм сбора мусора или распределение памяти. Имя пода и имя хоста могут пригодиться для журналирования или отправки метрик на центральный сервер. Также вам может понадобиться отыскать другие поды в том же пространстве имен с определенной меткой и объединить их в кластерное приложение. Для этих и других случаев Kubernetes предоставляет Downward API.
Описанные требования и решение, представленное ниже, относятся не только к контейнерам, но и к любому динамическому окружению, где метаданные ресурсов могут изменяться. Например, AWS предлагает службы Instance Metadata и User Data, которые можно запросить у любого экземпляра EC2. Аналогично, AWS ECS предоставляет API, с помощью которого контейнеры могут запрашивать и получать информацию о кластере.
В Kubernetes используется еще более элегантный и простой подход. Downward API позволяет передавать метаданные о поде в контейнеры и в кластер через переменные окружения и файлы. Это те же механизмы, которые мы использовали для передачи данных, связанных с приложением, из ConfigMap и Secret. Но в этом случае данные создаются не нами. Мы просто указываем ключи, которые нас интересуют, а Kubernetes присваивает им значения динамически. На рис. 13.1 представлена общая схема, как Downward API внедряет в поды информацию о ресурсах и о среде времени выполнения.
Рис. 13.1. Механизмы интроспекции приложений
Суть в том, что Downward API внедряет метаданные в под и они становятся доступными локально. Приложению не нужно использовать клиента и взаимодействовать с Kubernetes API, и оно может оставаться независимым от Kubernetes. Давайте рассмотрим листинг 13.1, демонстрирующий, насколько просто запрашивать метаданные через переменные окружения.
Листинг 13.1. Передача информации из Downward API через переменные окружения
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MEMORY_LIMIT
valueFrom:
resourceFieldRef:
container: random-generator
resource: limits.memory
Переменная окружения POD_IP получает значение из свойств пода и инициализируется во время запуска пода.
Переменная окружения MEMORY_LIMIT получает значение, равное лимиту памяти, выделенной для этого контейнера; фактическое объявление лимита здесь не показано.
Для доступа к метаданным уровня пода в этом примере используется свойство fieldRef. Ключи, перечисленные в табл. 13.1, доступны в fieldRef.fieldPath и в виде переменных окружения, и в виде томов downwardAPI.
По аналогии с fieldRef, для доступа к метаданным, относящимся к конкретному контейнеру в поде, можно использовать resourceFieldRef. Эти метаданные относятся к контейнеру, который можно задать с помощью resourceFieldRef.container. При использовании переменной окружения по умолчанию сообщаются метаданные для текущего контейнера. Возможные ключи для resourceFieldRef.resource перечислены в табл. 13.2.
Таблица 13.1. Информация из Downward API, доступная в fieldRef.fieldPath
Имя | Описание |
spec.nodeName | Имя узла, где размещается под |
status.hostIP | IP-адрес узла, где размещается под |
metadata.name | Имя пода |
metadata.namespace | Пространство имен, в котором действует под |
status.podIP | IP-адрес пода |
spec.serviceAccountName | Учетная запись ServiceAccount, используемая подом |
metadata.uid | Уникальный идентификатор пода |
metadata.labels[‘key'] | Значение метки key пода |
metadata.annotations[‘key'] | Значение аннотации key пода |
Таблица 13.2. Информация из Downward API, доступная в resourceFieldRef.resource
Имя | Описание |
requests.cpu | Число процессоров, запрошенное контейнером |
limits.cpu | Лимит процессоров для контейнера |
requests.memory | Объем памяти, запрошенный контейнером |
limits.memory | Лимит памяти, доступной контейнеру |
Некоторые метаданные, такие как метки и аннотации, могут меняться пользователем во время работы пода. Переменные окружения будут отражать такие изменения только после перезапуска пода. Но тома downwardAPI способны динамически отражать изменения в метках и аннотациях. В дополнение к отдельным полям, перечисленным выше, тома downwardAPI могут хранить все метки и аннотации подов в файлах с именами metadata.labels и metadata.annotations. Листинг 13.2 показывает, как можно использовать такие тома.
Листинг 13.2. Передача информации из Downward API через тома
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
volumeMounts:
- name: pod-info
mountPath: /pod-info
volumes:
- name: pod-info
downwardAPI:
items:
- path: labels
fieldRef:
fieldPath: metadata.labels
- path: annotations
fieldRef:
fieldPath: metadata.annotations
Значения из Downward API можно монтировать как файлы в поде.
Файл labels содержит все метки, по одной в каждой строке, в формате имя=значение. Этот файл обновляется синхронно с изменением меток.
Файл annotations содержит все аннотации в том же формате, что и метки.
Если метаданные изменяются во время работы пода, эти изменения синхронно отражаются на содержимом файлов томов. Но приложение-потребитель само должно определять факт изменения файлов и читать обновленные данные. Если такая возможность в приложении не реализована, может потребоваться перезапустить под.
Во многих случаях приложению необходимо иметь информацию о себе и об окружении, в котором оно работает. Kubernetes предлагает ненавязчивые механизмы для интроспекции и внедрения метаданных. Один из недостатков Downward API — ограниченное количество ключей, на которые можно ссылаться. Если приложению нужно больше данных, особенно о других ресурсах или метаданных, связанных с кластером, оно должно запрашивать их через API Server.
Этот метод используется многими приложениями, которые запрашивают API Server с целью обнаружения других подов в том же пространстве имен, которые имеют определенные метки или аннотации. Затем приложение может сформировать кластер с обнаруженными подами и, например, синхронизировать состояние. Он также используется приложениями мониторинга для поиска интересующих их подов и управления ими.
Существует множество клиентских библиотек на разных языках программирования, предназначенных для взаимодействия с Kubernetes API Server и получения информации о самом приложении, которую нельзя получить с помощью Downward API.
• Пример самоанализа (http://bit.ly/2TYBXpc).
• Получение информации контейнером о поде через файлы (http://bit.ly/2CoZyFy).
• Получение информации контейнером о поде через переменные окружения (http://bit.ly/2JpuHPe).
• Агент интроспекции в Amazon ECS (https://amzn.to/2JnVXgX).
• Службы Instance Metadata и User Data (http://amzn.to/1Cu0fTl).