В предыдущей статье мы рассмотрели преимущества кастомизации и настройки облачной инфраструктуры, основанные на гибкости и масштабируемости Kubernetes. Разобрали, как этот подход способствует повышению адаптивности бизнес-задач в облачной среде. Однако мы лишь немного коснулись аспекта персонализации. В этой статье предлагаю более детально рассмотреть компоненты Kubernetes, которые позволяют создать еще более индивидуализированную инфраструктуру для развертывания приложений.
Подробнее о Custom Resource Definitions
Custom Resource Definitions (CRD) являются центром расширяемости Kubernetes. CRD позволяет разработчикам создавать и использовать их собственные специализированные ресурсы, вместо того чтобы полагаться только на стандартные, предоставляемые Kubernetes. CRD стали основой для общения разнообразных сторонних приложений и инструментов с кластерами Kubernetes.
Одно из наиболее важных преимуществ CRD — возможность полностью управлять ими с помощью существующих команд kubectl
. Это делает их относительно простыми для использования и интеграции в имеющиеся рабочие процессы. Однако CRD не могут функционировать самостоятельно. Они работают вместе с Kubernetes API Aggregation Layer, который соединяет CRD с основным Kubernetes API Server. Как следствие, управление и контроль доступа к CRD можно настроить точно так же, как и для встроенных ресурсов.
Важность CRD в экосистеме Kubernetes можно увидеть во множестве Operators, которые созданы с использованием CRD и Operator SDK. Операторы представляют собой приложения, развернутые на кластере, которые извлекают всю пользу из CRD для расширения функционала Kubernetes, дающего возможность адаптировать его под свои уникальные приложения и сервисы.
Важно отметить, что несмотря на огромные возможности, которые открываются благодаря использованию CRD, они также могут представлять собой риск. Неудачное использование или ошибки в CRD могут привести к проблемам в кластере. Поэтому всегда рекомендуется тщательно тестировать CRD в безопасной среде перед их выпуском в проде.
Давайте рассмотрим CRD более подробно на примере создания ресурса «User», который будет для хранить информацию о пользователях в нашем приложении.
В первую очередь нужно создать описание CRD. Создайте файл под названием
user_crd.yaml
со следующим содержимым:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: users.custom.example.com
spec:
group: custom.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
firstName:
type: string
lastName:
type: string
email:
type: string
scope: Namespaced
names:
plural: users
singular: user
kind: User
shortNames:
- usr
Теперь создайте CRD в вашем кластере с помощью
kubectl
и проверьте его создание:
kubectl apply -f user_crd.yaml
kubectl get crd
Следующим шагом будем создание объекта нового типа «User». Создайте новый файл
user_object.yaml
и добавьте следующий код:
apiVersion: "custom.example.com/v1"
kind: User
metadata:
name: user-sample
spec:
firstName: Ivan
lastName: Petrov
email: ivan.petrov@example.com
Создайте новый объект «User» с помощью
kubectl
и проверьте создание объекта:
kubectl apply -f user_object.yaml
kubectl get users
Вы также можете проверить полную информацию об этом пользователе:
kubectl describe user user-sample
Создание собственных CRD может быть сложным процессом. Но с правильным пониманием Kubernetes и подходящими инструментами создание качественной CRD становится достижимой задачей. Просто помните, что лучший CRD — это CRD, которую вы создали сами и полностью контролируете.
Создание собственных версий объектов API
Обычно, чтобы добавить собственные методы в API Kubernetes, разработчики используют Aggregated API Servers. Они обрабатывают дополнительные API методы и, в отличие от CRD, позволяют вручную управлять всем процессом. При использовании Aggregated API Servers вы получаете контроль над всем процессом управления и обработки дополнительных API методов. Это позволяет точно определить, каким образом будут обрабатываться запросы и какая логика будет применяться к этим методам. Aggregated API Servers предоставляют возможность создания своего собственного API пути и определения, какие версии, группы и пространства имен будут использоваться в их методах API.
Предлагаю рассмотреть несколько общих сценариев использования Aggregated API Servers:
Пользовательские методы для объектов API. Агрегированные API-серверы можно использовать, чтобы добавить пользовательские методы для объектов API в Kubernetes. Например, можно создать API-сервер, который добавляет методы для работы с пользовательским типом данных.
Расширения для существующих ресурсов API. Можно создавать новые функции и методы к существующим ресурсам API. Это будет полезным, если вам нужно изменить поведение существующего ресурса или добавить новую функциональность.
Интеграция с внешними сервисами. Агрегированные API-серверы могут быть использованы для интеграции Kubernetes с внешними сервисами. Например, можно создать API-сервер, который взаимодействует с внешней базой данных или другим API.
Создание собственных контроллеров. Контроллеры в Kubernetes следят за состоянием кластера и принимают меры для поддержания желаемого состояния. Путем создания собственных контроллеров вы можете добавлять свою логику для управления кастомными ресурсами или изменением поведения существующих ресурсов.
Давайте рассмотрим пример, где мы создадим простой контроллер на языке Go для мониторинга подов. При создании собственных контроллеров API в Kubernetes вам понадобится описать две части: контроллер и его манифест YAML.
Пример кода контроллера на Go:
package main
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"path/filepath"
"time"
)
func main() {
// Подключение к кластеру Kubernetes
home := homedir.HomeDir()
kubeconfig := filepath.Join(home, ".kube", "config")
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
panic(err.Error())
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// Запуск бесконечного цикла мониторинга
for {
// Получение списка подов из кластера
pods, err := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
// Вывод информации о каждом поде
fmt.Println("Pods in the cluster:")
for _, pod := range pods.Items {
fmt.Printf("- %s\n", pod.Name)
}
// Задержка перед следующим мониторингом
time.Sleep(30 * time.Second)
}
}
Данный контроллер мониторит и выводит список подов в кластере каждые 30 секунд.
Пример манифеста для развертывания контроллера my-controller:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-controller
spec:
selector:
matchLabels:
app: my-controller
template:
metadata:
labels:
app: my-controller
spec:
containers:
- name: my-controller
image: my-controller:latest
command:
- /bin/sh
- -c
- /usr/local/bin/my-controller
Кроме этого примера, вы можете добавить логику масштабирования, обновления или любые другие действия в ваш контроллер в зависимости от ваших требований. Не забудьте также настроить правильные разрешения и сервисные аккаунты для вашего контроллера API. Создание полноценного Aggregated API Server также включает такие шаги, как создание и регистрация маршрутов API, работу с объектами схемы Kubernetes API и механизмы аутентификации и авторизации.
Операторы Kubernetes
Операторы Kubernetes обеспечивают специфичную для домена логику управления и обновления сложных системных сценариев, как правило, выходящих за рамки примитивов, доступных в Kubernetes через стандартные API.
Вспомним, что операторы в Kubernetes используются для автоматизации управления, установки и обновления экземпляров приложений или сложных состояний в Kubernetes. Они активно используются в области управления состоянием приложения, например, в случае баз данных, серверов, очереди сообщений и других сложных системных компонентов. Все это требует специфических знаний о процессах установки, настройки, обновления и масштабирования данных систем, которые включены прямо в оператор.
Для иллюстрации давайте рассмотрим операторы Postgres и Prometheus, которые хорошо иллюстрируют используемые концепции.
Пример с оператором базы данных
Установка Postgres operator
Операторы обычно предоставляются как Helm-чарты, что позволяет просто их установить.
helm install postgres-operator zalando/postgres-operator
Теперь внутри Kubernetes у нас есть оператор PostgreSQL, который принимает контроль и автоматизирует управление базами данных PostgreSQL.
Использование оператора
Создавая заявки на базу данных через Custom Resource Definition (CRD), Kubernetes и оператор заботятся о всем остальном, например, о поднятии настроенной базы данных, бэкапах, обновлениях и масштабировании. Это делается путем создания конфигурации в формате YAML и развертывания ее в кластере:
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: mydb
namespace: default
spec:
teamId: "myteam"
volume:
size: 1Gi
numberOfInstances: 2
users:
admin:
- superuser
- createdb
databases:
mydb: admin
postgresql:
version: "12"
После развертывания этого конфигурационного файла оператор создаст две реплики базы данных PostgreSQL. Система будет автоматически масштабироваться и обновляться по мере необходимости, а оператор будет обрабатывать всю эту сложную логику.
Оператор PostgreSQL также обрабатывает резервное копирование и восстановление, обслуживание и устранение неисправностей. Он может автоматически заменять узлы базы данных при сбоях и обеспечивать высокую доступность и надежность.
В качестве еще одного примера действий этого оператора — значение numberOfInstances. Если это значение в спецификации CRD увеличено, оператор автоматически добавит новые реплики к существующей базе данных.
Пример с оператором мониторинга
Еще одним полезным примером оператора Kubernetes является оператор мониторинга, который автоматизирует процесс настройки и управления инфраструктурой мониторинга.
Например, Prometheus Operator — это оператор для управления экземплярами Prometheus и других компонентов связанного стека мониторинга.
Установка Prometheus Operator
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml
kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.48/example/prometheus-operator-deployment.yaml
Использование оператора
После установки оператора можно создавать экземпляры мониторинга, определяя их через Custom Resource Definitions (CRD). Например, создание экземпляра мониторинга для приложения:
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: app-prometheus
spec:
replicas: 1
serviceAccountName: prometheus
securityContext:
fsGroup: 2000
serviceMonitorSelector:
matchLabels:
app: myapp
ruleSelector:
matchLabels:
prometheus: myapp
resources:
requests:
memory: 400Mi
alerting:
alertmanagers:
- namespace: monitoring
name: alertmanager-main
port: web
В приведенном примере replicas: 1 указывает на существование только одной реплики Prometheus. ServiceMonitorSelector конфигурирует Prometheus, чтобы он «подключался» ко всем ServiceMonitors в неймспейсе, имеющим метку «app: myapp», что позволяет Prometheus автоматически обнаруживать и использовать цели мониторинга.
resources определяет необходимость ресурсов для подов Prometheus, в данном случае «memory: 400Mi».
В секции alerting мы указываем, куда Prometheus должен посылать сигналы тревоги. В этом случае сигналы будут направлены на экземпляр Alertmanager, находящийся в неймспейсе «monitoring».
После создания этого CRD, оператор Prometheus создаст экземпляр Prometheus с указанными конфигурациями и начнет слежение за указанными сервисами. Это обеспечит надежный и управляемый контроль вашего приложения.
Операторы Kubernetes способны управлять жизненным циклом сложных приложений и состояний, предоставляя уровень автоматизации, который ранее был доступен только в рамках управляемых сервисов облака.
Заключение
Custom Resource Definitions (CRD), собственные версии объектов API и Operators — это мощные инструменты, которые позволяют настраивать инфраструктуру под определенные потребности и достигать высокой производительности и эффективности приложений. Хотя создание персонализированной инфраструктуры может потребовать значительных усилий, которые будут вложены в настройку и управление, в итоге вы сможете в значительной степени сэкономить ресурсы и время благодаря детальной оптимизации ваших процессов.
Спасибо за внимание! Надеюсь, статья была интересна всем, кто стремится извлечь максимум пользы из облачных вычислений и создать настраиваемое окружение для своих приложений. Пишите ваши предложения и замечания в комментариях.
Автор статьи @exzvor
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
— 15% на заказ любого VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.