Архив метки: Kubernetes

Сохраняем кластеры Kubernetes в чистоте и порядке

Одновременно с ростом кластера Kubernetes растет количество ресурсов, volume и других API-объектов. Рано или поздно вы упретесь в потолок, будь то etcd, память или процессор. Зачем подвергать себя ненужной боли и проблемам, если можно установить простые — хотя и довольно изощренные — правила? Вы можете настроить автоматизацию и мониторинг, которые будут содержать кластер в аккуратном состоянии. В статье разберемся, как избавиться от лишних нагрузок, через которые утекают ресурсы, и устаревших накопившихся объектов.




Что будет в статье:




  • В чем проблема?



  • Основы



  • Ручная очистка



  • Kube-janitor



  • Мониторинг ограничений кластера



  • Заключение



  • От переводчиков







В чем проблема?




Несколько забытых подов, неиспользуемые volume, завершенные задачи или, возможно, старый ConfigMap/Secret — насколько все это важно? Все это просто где-то лежит и ждет, пока не понадобится.




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




Ограничение количества подов. Каждый кластер Kubernetes имеет несколько основных ограничений. Первое из них — количество подов на узел, которое по документации не рекомендуется делать больше 110. При этом, если у вас достаточно мощные узлы с большим количеством памяти и CPU, вы можете увеличить это количество — возможно, даже до 500, как было протестировано на OpenShift. Но если вы достигнете этих пределов, не удивляйтесь, если что-то пойдет не так, и не только потому, что не хватает памяти или мощности процессора.




Нехватка хранилища ephemeral storage. Все запущенные поды на узле используют по крайней мере часть этого пространства для логов, кэша, рабочего пространства или emptyDir волюмов. Вы можете достичь предела довольно быстро, что приведет к вытеснению уже существующих подов, или невозможности создания новых. Запуск слишком большого количества подов на узле тоже может способствовать этой проблеме: ephemeral storage используется для образов контейнеров и их записываемых слоев. Если узел достигает предела хранилища, он становится нерабочим (на него будет применен taint), о чем вы узнаете довольно быстро. Если вы хотите узнать текущее состояние диска на узле, запустите на нем df -h /var/lib.




Лишние расходы на PVC. Схожим образом источником проблем могут стать persistent volume, особенно если вы запускаете Kubernetes в облаке и платите за каждый предоставленный PVC. Очевидно, что для экономии денег необходимо чистить неиспользуемые PVC. Содержание используемых PVC чистыми тоже важно, потому что позволяет избежать нехватки места для ваших приложений. Особенно, если вы запускаете базы данных в кластере.




Низкая производительность etcd. Еще один источник проблем — чрезмерное количество объектов, поскольку все они находятся в хранилище etcd. По мере роста количества данных в etcd, его производительность может начать снижаться. Этого нужно стараться не допускать всеми силами: etcd — мозг кластера Kubernetes. Учитывая вышесказанное, чтобы упереться в etcd, вам понадобится действительно большой кластер, как продемонстрировано в этом посте OpenAI. В то же время нет какой-то единой метрики для замера производительности etcd, потому что она зависит от количества объектов, их размеров и частоты использования. Так что наилучшим выходом будет профилактика: простое сохранение чистоты и порядка. В противном случае вас могут ждать весьма неприятные сюрпризы.




Нарушение границ безопасности. Наконец, мусор в кластере может стать источником проблем сам по себе. Не забывайте подчищать Role Bindings и учетные записи (Service Account), когда ими никто не пользуется.




Основы




Для решения большинства этих проблем не нужно делать ничего особенно сложного. Лучшим выбором будет совсем не допускать их. Один из вариантов превентивных мер — использование объектных квот, которые вы, как администратор кластера, можете применять в каждом отдельном неймспейсе. 




Первое, что можно решить с помощью квот — количество и размер PVC:




apiVersion: v1
kind: LimitRange
metadata:
  name: pvc-limit
spec:
  limits:
  - type: PersistentVolumeClaim
    max:
      storage: 10Gi
    min:
      storage: 1Gi
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pvc-quota
spec:
  hard:
    persistentvolumeclaims: "10"
    requests.storage: "10Gi"
    # сумма запрошенного хранилища в bronze storage class не может превышать 5 Гб
    bronze.storageclass.storage.k8s.io/requests.storage: "5Gi"




Выше мы имеем два объекта.




LimitRange устанавливает минимальный и максимальный размеры PVC в неймспейсе. Это оградит пользователей от запрашивания слишком больших объемов.




ResourceQuota дополнительно обеспечивает жесткое ограничение на количество PVC и их совокупный размер.




Затем вы можете предотвратить создание кучи объектов и оставление их в качестве мусора после использования. Для этого используйте object count, квоты на количество объектов, которые зададут жесткое ограничение на количество объектов определенного типа в конкретном неймспейсе:




apiVersion: v1
kind: ResourceQuota
metadata:
  name: object-count-quota
spec:
  hard:
    configmaps: "2"
    secrets: "10"
    services: "5"
    count/jobs.batch: "8"




Есть несколько встроенных полей, через которые вы можете задать квоты на количество объектов. Например, configmapssecrets или services, показанные выше. Для всех прочих ресурсов можно использовать формат count/<resource>.<group>, как показано в примере с count/jobs.batch, что может помочь от бесконтрольного создания джоб из-за неправильно настроенного CronJob.




Вероятно, большинству известно о функции установки квот на память и CPU. Но, возможно, для вас станет новостью квота ephemeral storage. Альфа-поддержка квот для эфемерного хранилища была добавлена в v1.18 и дала возможность установить границы ephemeral storage так же, как как для памяти и процессора.




apiVersion: v1
kind: ResourceQuota
metadata:
  name: ephemeral-storage-quota
spec:
  hard:
    requests.ephemeral-storage: 1Gi
    limits.ephemeral-storage: 2Gi




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




Помимо установки квот и границ ресурсов, можно установить ограничение для истории ревизий Deployment — для снижения количества репликасетов, хранящихся в кластере. Для этого используйте .spec.revisionHistoryLimit, который по умолчанию равен 10.




Наконец, вы можете установить время жизни (TTL) для очистки кластера от объектов, которые существуют там слишком долго. Эта процедура использует TTL-контроллер, который находится в стадии бета-тестирования с версии v1.21, и в настоящее время работает только для задач, использующих поле .spec.ttlSecondsAfterFinished. В будущем, возможно, он будет расширен на другие ресурсы, например, поды.




Ручная очистка 




Если превентивных мер уже недостаточно, потому что у вас накопилось достаточно неиспользуемых ресурсов, вы можете попробовать разовое удаление. Это делается просто с помощью kubectl get и kubectl delete. Пара основных примеров того, что вы можете сделать:




kubectl delete all -l some-label=some-value  # Delete based on label
kubectl delete pod $(kubectl get pod -o=jsonpath='{.items[?(@.status.phase=="Succeeded")].metadata.name}')  # Delete all "Succeeded" Pods




Первая команда выполняет базовое удаление с использованием лейблов ресурсов. Поэтому этот метод потребует от вас предварительно пометить все подлежащие удалению объекты некоторой парой ключ-значение.




Вторая показывает, как вы можете удалить тип ресурсов, основанный на некотором поле, как правило, каком-то поле статуса. В примере выше это будут все завершенные/успешные поды. Этот вариант можно применить и к другим ресурсам, например, завершенным задачам.




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




Могу посоветовать такой инструмент, как k8spurger. Он ищет неиспользуемые объекты вроде RoleBinding, ServiceAccounts, ConfigMaps и создает список ресурсов-кандидатов на удаление. Это поможет сузить круг поиска.




Kube-janitor




В разделах выше мы рассмотрели несколько вариантов простой очистки для конкретных случаев. Но лучшим решением для наведения порядка в любом кластере будет использование kube-janitor. Этот инструмент работает в вашем кластере так же, как любая другая рабочая нагрузка, и использует JSON-запросы для поиска ресурсов, которые можно удалить на основе TTL или истечения срока действия.




Для развертывания kube-janitor на вашем кластере запустите:




git clone https://codeberg.org/hjacobs/kube-janitor.git
cd kube-janitor
kubectl apply -k deploy/




Это разложит kube-janitor в default namespace и запустит его с правилами по умолчанию в пробном режиме с использованием флага —dry-run.




Перед отключением dry-run нужно установить собственные правила. Они лежат в config map kube-janitor, которая выглядит примерно так:




apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-janitor
  namespace: default
data:
  rules.yaml: |-
    rules:
      ...




Конечно, для нас самый интересный раздел здесь — правила, rules. Вот несколько полезных примеров, которые вы можете использовать для очистки своего кластера:




rules:
  # Удаление Jobs в development namespaces после 2 дней.
  - id: remove-old-jobs
    resources:
    - jobs
    jmespath: "metadata.namespace == 'development'"
    ttl: 2d
  # Удаление тех подов в development namespaces, которые не в состоянии выполнения (Failed, Completed).
  - id: remove-non-running-pods
    resources:
    - pods
    jmespath: "(status.phase == 'Completed' || status.phase == 'Failed') && metadata.namespace == 'development'"
    ttl: 2h
  # Удаление всех PVC, которые не использует ни один под
  - id: remove-unused-pvcs
    resources:
    - persistentvolumeclaims
    jmespath: "_context.pvc_is_not_mounted"
    ttl: 1d
  # Удаление всех Deployments, чье имя начинается с 'test-'
  - id: remove-test-deployments
    resources:
    - deployments
    jmespath: "starts_with(metadata.name, 'test-')"
    ttl: 1d
  # Удаление всех ресурсов в playground namespace через неделю
  - id: remove-test-deployments
    resources:
    - "*"
    jmespath: "metadata.namespace == 'playground'"
    ttl: 7d




Этот пример показывает несколько базовых вариантов настройки для очистки от временных, устаревших или неиспользуемых ресурсов. Помимо правил такого рода, можно установить абсолютные дату/время истечения срока действия для конкретных объектов. 




Это можно сделать с помощью аннотаций, например:




apiVersion: v1
kind: Namespace
metadata:
  annotations:
    # будет удалено 18.6.2021 в полночь
    janitor/expires: "2021-06-18"
  name: temp
spec: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # будет удалено 20.6.2021 в 17:30
    janitor/expires: "2021-06-20T17:30:00Z"
  name: nginx
spec:
  replicas: 1
  ...




Когда закончите устанавливать правила и аннотации, вам стоит дать kube-janitor поработать какое-то время в dry-run режиме с включенными логами отладки. Это мера предосторожности, чтобы инструмент не удалил то, что удалять было не нужно. 




Другими словами, не обвиняйте меня, если сотрете production волюмы из-за неправильной конфигурации и отсутствия тестирования.




Наконец, при использовании kube-janitor нужно учитывать его потребности в ресурсах. Если в кластере много объектов, ему может потребоваться больше памяти, чем выделенные по умолчанию 100 Мб. Чтобы его под не застревал в CrashLoopBackOff, я выставляю ему лимит 1 Гб.




Мониторинг ограничений кластера




Не все проблемы можно решить ручной или даже автоматической очисткой. В некоторых случаях мониторинг будет лучшим выбором для обеспечения уверенности в том, что вы не упираетесь в лимиты кластера — будь то количество подов, доступное ephemeral storage или количество объектов в etcd.




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







Это только некоторые метрики из тех, которые вы можете использовать. Какие из них будут доступны, зависит также от ваших инструментов мониторинга, т.е. вы можете использовать какие-то специальные метрики, доступные на вашем сервисе.




Заключение




Мы рассмотрели несколько вариантов очистки кластера Kubernetes — некоторые совсем простые, а некоторые посложнее. Независимо от того, что вы выберете, старайтесь не забывать делать уборку в кластере и сохранять порядок. Это может спасти вас от большой головной боли и, по крайней мере, избавит от ненужного хлама в кластере. В конечном счете такая уборка служит тем же целям, что наведение порядка на рабочем столе.




Также имейте ввиду, что если вы оставляете объекты лежать без использования долгое время, вы просто забудете, зачем они там. Это может сильно осложнить понимание, что должно существовать, а что — нет.




Помимо описанных здесь подходов, вы также можете использовать какое-либо решение GitOps — например, ArgoCD или Flux для создания ресурсов и управления ими, что может значительно упростить их очистку. Обычно потребуется удалить только один кастомный ресурс, что вызовет каскадное удаление всех зависимых ресурсов.




Источник: https://habr.com/ru/company/kts/blog/587236/



Удаляем устаревшую feature branch в Kubernetes кластере

Привет! Feature branch (aka deploy preview, review app) — это когда деплоится не только master ветка, но и каждый pull request на уникальный URL. Можно проверить работает ли код в production-окружении, фичу можно показать другим программистам или продуктологам. Пока вы работаете в pull request’е, каждый новый commit текущий deploy для старого кода удаляется, а новый deploy для нового кода выкатывается. Вопросы могут возникнуть тогда, когда вы смерджили pull request в master ветку. Feature branch вам больше не нужна, но ресурсы Kubernetes все еще находятся в кластере.




Еще про feature branch’и




Один из подходов как сделать feature branch’и в Kubernetes — использовать namespace’ы. Если кратко, production конфигурации выглядит так:




kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end
spec:
  replicas: 3
...




Для feature branch создается namespace c ее идентификатором (например, номер pull request’а) и каким-то префиксом/постфиксом (например, -pr-):




kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end-pr-17
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end-pr-17
spec:
  replicas: 1
...




В общем, я написал Kubernetes Operator (приложение, которое имеет доступ к ресурсам кластера), ссылка на проект на Github. Он удаляет namespace’ы, которые относятся к старым feature branch’ам. В Kubernetes, если удалить namespace, другие ресурсы в этом namespace также удаляются автоматически.




$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE            ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7h




Про то как внедрить feature branch’и в кластер, можно почитать тут и тут.




Мотивация




Давайте посмотрим на типичный жизненный цикл pull request’a с непрерывной интеграцией (continuous integration):




  1. Пушим новый commit в ветку.



  2. На билде, запускаются линтеры и/или тесты.



  3. На лету формируются конфигурации Kubernetes pull request’a (например, в готовый шаблон подставляется его номер).



  4. С помощью kubectl apply конфигурации попадают в кластер (deploy).



  5. Pull request сливается в master ветку.




Пока вы работаете в pull request’е, каждый новый commit текущий deploy для старого кода удаляется, а новый deploy для нового кода выкатывается. Но когда pull request сливается в master ветку, будет билдится только master ветка. В итоге получается, что про pull request мы уже забыли, а его Kubernetes ресурсы все еще находятся в кластере.




Как использовать




Установить проект командой ниже:




$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml




Создать файл со следующим содержанием и установить через kubectl apply -f:




apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 3




Параметр namespaceSubstring нужен, чтобы отфильтровать namespace’ы для pull request’ов от других namespace’ов. Например, если в кластере есть следующие namespace’ы: habr-back-endhabr-front-endhabr-back-end-pr-17habr-back-end-pr-33, тогда кандидатами на удаление будут habr-back-end-pr-17habr-back-end-pr-33.




Параметр afterDaysWithoutDeploy нужен чтобы, удалять старые namespace’ы. Например, если namespace создан 3 дня 1 час назад, а в параметре указано 3 дня, этот namespace будет удален. Работает и в обратную сторону, если namespace создан 2 дня 23 часа назад, а в параметре указано 3 дня, этот namespace не будет удален.




Есть еще один параметр, он отвечает за то как часто сканировать все namespace’ы и проверять на дни без deploy’я — checkEveryMinutes. По умолчанию он равен 30 минутам.




Как это работает




На практике, понадобится:




  1. Docker для работы в изолированном окружении.



  2. Minikube поднимет Kubernetes кластер локально.



  3. kubectl — интерфейс командной строки для управления кластером.




Поднимаем Kubernetes кластер локально:




$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Using the docker driver based on existing profile.
Starting control plane node minikube in cluster minikube.




Указываем kubectl использовать локальный кластер по умолчанию:




$ kubectl config use-context minikube
Switched to context "minikube".




Скачиваем конфигурации для production-среды:




$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.yml




Так как production конфигурации настроены проверять старые namespace’ы, а в нашем ново поднятом кластере их нет, заменим переменную окружения IS_DEBUG на true. При таком значении параметр afterDaysWithoutDeploy не учитывается и namespace’ы не проверяются на дни без deploy’я, только на вхождение подстроки (-pr-).




Если вы на Linux:




$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml




Если вы на macOS:




$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml




Устанавливаем проект:




$ kubectl apply -f stale-feature-branch-production-configs.yml




Проверяем, что в кластере появился ресурс StaleFeatureBranch:




$ kubectl api-resources | grep stalefeaturebranches
NAME                 ... APIGROUP                             ... KIND
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch




Проверяем, что в кластере появился оператор:




$ kubectl get pods --namespace stale-feature-branch-operator
NAME                                           ... STATUS  ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s




Если заглянуть в его логи, он готов обрабатывать ресурсы StaleFeatureBranch:




$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operator Version: 0.0.1"}
...
... "msg":"Starting EventSource", ... , "source":"kind source: /, Kind="}
... "msg":"Starting Controller", ...}
... "msg":"Starting workers", ..., "worker count":1}




Устанавливаем готовые fixtures (готовые конфигурации для моделирования ресурсов кластера) для ресурса StaleFeatureBranch:




$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.yml




В конфигурациях указано искать namespace’ы с подстрокой -pr- раз в 1 минуту.:




apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 1 
  checkEveryMinutes: 1




Оператор отреагировал и готов проверять namespace’ы:




$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Stale feature branch is being processing.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}




Устанавливаем fixtures, содержащие два namespace’а (project-pr-1project-pr-2) и их deploymentsservicesingress, и так далее:




$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/first-feature-branch.yml -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/second-feature-branch.yml
...
namespace/project-pr-1 created
deployment.apps/project-pr-1 created
service/project-pr-1 created
horizontalpodautoscaler.autoscaling/project-pr-1 created
secret/project-pr-1 created
configmap/project-pr-1 created
ingress.extensions/project-pr-1 created
namespace/project-pr-2 created
deployment.apps/project-pr-2 created
service/project-pr-2 created
horizontalpodautoscaler.autoscaling/project-pr-2 created
secret/project-pr-2 created
configmap/project-pr-2 created
ingress.extensions/project-pr-2 created




Проверяем, что все ресурсы выше успешно созданы:




$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...
NAME                              ... READY ... STATUS  ... AGE
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1   ... Running ... 67s

NAME                         ... READY ... AVAILABLE ... AGE
deployment.apps/project-pr-1 ... 1/1   ... 1         ... 67s
...




Так как мы включили debug, namespace’ы project-pr-1 и project-pr-2, следовательно и все остальные ресурсы, должны будут сразу удалиться не учитывая параметр afterDaysWithoutDeploy. В логах оператора это видно:




$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-1"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-1"}
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-2"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-2"}




Если проверить наличие ресурсов, они будут в статусе Terminating (процесс удаления) или уже удалены (вывод команды пуст).




$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...




Можете повторить процесс создания fixtures несколько раз и убедиться, что они будут удалены в течение минуты.




Альтернативы




Что можно сделать вместо оператора, который работает в кластере? Подходов несколько, все они неидеальны (и их недостатки субъективны), и каждый сам решает что лучше всего подойдет на конкретном проекте:




  1. Удалять feature branch во время билда непрерывной интеграции master ветки.

    • Для этого надо знать какой pull request относится к commit’у, который билдится. Так как feature branch namespace содержит в себе идентификатор pull request’a — его номер, или название ветки, идентификатор всегда придется указывать в commit’e.



    • Билды master веток фейлятся. Например, у вас следующие этапы: скачать проект, запустить тесты, собрать проект, сделать релиз, отправить уведомления, очистить feature branch последнего pull request’a. Если билд сфейлится на отправке уведомления, вам придется удалять все ресурсы в кластере руками.



    • Без должного контекста, удаление feature branch’и в master билде неочевидно.




  2. Использование webhook’ов (пример).

    • Возможно, это не ваш подход. Например, в Jenkins, только один вид пайплайна поддерживает возможность сохранять его конфигурации в исходном коде. При использовании webhook’ов нужно написать свой скрипт для их обработки. Этот скрипт придется размещать в интерфейсе Jenkins’а, что трудно поддерживать.




  3. Написать Cronjob и добавить Kubernetes кластер.

    • Затрата времени на написание и поддержку.



    • Оператор уже работает в подобном стиле, задокументирован и поддерживается.




Спасибо за внимание к статье. Ссылка на проект на Github.




Источник: https://habr.com/ru/post/508534/



2023-01-03T00:32:43
DevOps

Знакомство с Kubernetes. HorizontalPodAutoscaler

В этой статье рассмотрим использование HorizontalPodAutoscaler — объектов, предназначенных для автоматического масштабирования количества подов (Pods) в Replication ControllerReplica Set или Deployment, основываясь на использовании CPU (или, при поддержке custom metrics, на других метриках приложения). Давайте разберемся!




Сразу стоит отметить, что HorizontalPodAutoscaler не может быть применен к объектам, которые не предназначены для масштабирования, например DaemonSets. Horizontal Pod Autoscaler состоит из Kubernetes ресурса (объекта) и контроллера, поведение которого описывается ресурсом.




C периодичностью 15 секунд (можно изменить с помощью параметра --horizontal-pod-autoscaler-sync-period), контроллер собирает данные по использованию метрик, определенных в манифесте ресурса HorizontalPodAutoscaler. Метрики собираются или с resource metrics API (метрики использования ресурсов подами) или с custom metrics API (остальные метрики, например, метрики приложения).




Для каждого подконтрольного пода, контроллер собирает метрики (например, использования CPU) с resource metrics API (metrics.k8s.io, предоставляется metrics-server). Далее, происходит вычисление текущего значения использования CPU в процентах от запрошенных ресурсов (resource request) контейнерами каждого пода, после чего это значение сравнивается с “целевым” (target) значением — порогом, после которого количество подов должно быть увеличено.




Рассмотрим конкретный пример. Создадим файл test-hpa.yaml с описанием ресурса HorizontalPodAutoscaler такого содержания:




apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: test-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: test-api-deploy
  minReplicas: 10
  maxReplicas: 29
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 80




Создадим данный объект в кластере Kubernetes:




kubectl create -f test-hpa.yaml




Проверим наличие объекта:




kubectl get horizontalpodautoscaler
NAME          REFERENCE                        TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
test-hpa      Deployment/test-api-deploy       <unknown>/80%   10        29        0          7s




Спустя некоторое время, вместо <unknown>, мы должны увидеть текущее использование CPU подами в деплойменте test-api-deploy, однако в моем случае этого не произошло. Начинаем разбираться — для начала, убедимся, что metrics.k8s.io доступно:




kubectl get --raw "/apis/metrics.k8s.io/" | jq
{
  "kind": "APIGroup",
  "apiVersion": "v1",
  "name": "metrics.k8s.io",
  "versions": [
    {
      "groupVersion": "metrics.k8s.io/v1beta1",
      "version": "v1beta1"
    }
  ],
  "preferredVersion": {
    "groupVersion": "metrics.k8s.io/v1beta1",
    "version": "v1beta1"
  }
}




Проверим, что метрики использования CPU доступны. Первый вариант:




kubectl top pod | grep test-api-deploy
test-api-deploy-5f77b79896-2t9x9                        738m         43931Mi
test-api-deploy-5f77b79896-fhr7b                        643m         43999Mi
test-api-deploy-5f77b79896-gcrlc                        700m         44028Mi
test-api-deploy-5f77b79896-lx24k                        666m         44201Mi
test-api-deploy-5f77b79896-mzlzb                        660m         44048Mi
test-api-deploy-5f77b79896-ndjwx                        651m         44136Mi
test-api-deploy-5f77b79896-q2nvw                        654m         44177Mi
test-api-deploy-5f77b79896-qmw4t                        692m         44051Mi
test-api-deploy-5f77b79896-rl4bb                        650m         43979Mi
test-api-deploy-5f77b79896-xhpbx                        752m         44116Mi




Второй вариант (метрики только одного конкретного пода):




kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/default/pods/test-api-deploy-5f77b79896-xhpbx | jq
{
  "kind": "PodMetrics",
  "apiVersion": "metrics.k8s.io/v1beta1",
  "metadata": {
    "name": "test-api-deploy-5f77b79896-xhpbx",
    "namespace": "default",
    "selfLink": "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/test-api-deploy-5f77b79896-xhpbx",
    "creationTimestamp": "2019-06-11T13:50:00Z"
  },
  "timestamp": "2019-06-11T13:49:41Z",
  "window": "30s",
  "containers": [
    {
      "name": "envoy",
      "usage": {
        "cpu": "489151208n",
        "memory": "45692Ki"
      }
    },
    {
      "name": "test",
      "usage": {
        "cpu": "7125240328n",
        "memory": "45515856Ki"
      }
    }
  ]
}




Как видим, метрики доступны. Получим детальное описание нашего HorizontalPodAutoscaler:




kubectl describe hpa test-hpa
Name:                                                  test-hpa
Namespace:                                             default
Labels:                                                app.kubernetes.io/managed-by=spinnaker
                                                       app.kubernetes.io/name=test
Annotations:                                           artifact.spinnaker.io/location: default
                                                       artifact.spinnaker.io/name: test-hpa
                                                       artifact.spinnaker.io/type: kubernetes/horizontalpodautoscaler
                                                       kubectl.kubernetes.io/last-applied-configuration:
                                                         {"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{"artifact.spinnaker.io/location":"default"...
                                                       moniker.spinnaker.io/application: test
                                                       moniker.spinnaker.io/cluster: horizontalpodautoscaler test-hpa
CreationTimestamp:                                     Tue, 11 Jun 2019 11:21:03 +0300
Reference:                                             Deployment/test-api-deploy
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  <unknown> / 80%
Min replicas:                                          10
Max replicas:                                          29
Deployment pods:                                       10 current / 10 desired
Conditions:
  Type           Status  Reason                   Message
  ----           ------  ------                   -------
  AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scale
  ScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: missing request for cpu
Events:
  Type     Reason                        Age                    From                       Message
  ----     ------                        ----                   ----                       -------
  Normal   SuccessfulRescale             7m17s                  horizontal-pod-autoscaler  New size: 10; reason: Current number of replicas below Spec.MinReplicas
  Warning  FailedComputeMetricsReplicas  4m15s (x12 over 7m2s)  horizontal-pod-autoscaler  failed to get cpu utilization: missing request for cpu
  Warning  FailedGetResourceMetric       2m15s (x20 over 7m2s)  horizontal-pod-autoscaler  missing request for cpu




Здесь самое важное — сообщение the HPA was unable to compute the replica count: missing request for cpu. И действительно, в манифесте развертывания (Deployment) не указаны resource requests для одного из контейнеров (с именем envoy):




apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
# From https://www.spinnaker.io/reference/providers/kubernetes-v2/#strategy  
    strategy.spinnaker.io/use-source-capacity: "true"
  name: test-api-deploy
spec:
#  replicas: 15
  selector:
    matchLabels:
      deployment: test-api-deploy
  strategy:
    rollingUpdate:
      maxSurge: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        deployment: test-api-deploy
    spec:
      containers:
      - image: envoyproxy/envoy:v1.10.0
        name: envoy
        ports:
        - containerPort: 8080
          name: http
        volumeMounts:
        - mountPath: /etc/envoy
          name: envoy-config
      - env:
        - name: JAVA_OPTS
          value: -Xms40g -Xmx40g
        image: index.docker.io/ealebed/test:v1
        name: test
        resources:
          limits:
            memory: 55Gi
          requests:
            cpu: "10"
            memory: 55Gi
      volumes:
      - configMap:
          name: envoy-config
        name: envoy-config




Важно! Если не указаны resource request хотя бы для одного из контейнеров в Replication ControllerReplica Set или Deployment, то текущее значение использование CPU подами не может быть корректно определено, и, в результате, HorizontalPodAutoscaler не будет предпринимать никаких действий по масштабированию.




После исправления этой досадной ошибки, HorizontalPodAutoscaler, базируясь на полученных метриках, начинает масштабировать поды в развертывании:




kubectl get horizontalpodautoscaler                                                                                                              
NAME          REFERENCE                       TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
test-hpa      Deployment/test-api-deploy      86%/80%   10        29        29         9m10




Формула, по которой HorizontalPodAutoscaler вычисляет требуемое количество реплик выглядит так:




desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]




Например, если текущее значение метрики (currentMetricValue) равно 200m, а ожидаемое (desiredMetricValue) установлено в 100m, то количество реплик будет удвоено (200.0 / 100.0 == 2.0). Если же текущее значение метрики равно всего лишь 50m, то количество реплик должно быть уменьшено вдвое (50.0 / 100.0 == 0.5). Если соотношение текущего значения метрики к ожидаемому значению достаточно близко к 1, то никаких действий не будет предпринято.




Так как мы указали targetAverageUtilization при описании ресурса HorizontalPodAutoscaler, то текущее значение метрики (currentMetricValue) использования CPU рассчитывается как среднее значение этой метрики для всех подов, контролируемых данным автоскейлером.




После того, как текущее значение использования CPU снизилось и оставалось низким в течении 5 минут (устанавливается с помощью параметра --horizontal-pod-autoscaler-downscale-stabilization), количество реплик было автоматически уменьшено:




kubectl get horizontalpodautoscaler                                                                                                              
NAME          REFERENCE                       TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
test-hpa      Deployment/test-api-deploy      70%/80%   20        29        23         1h




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




Источник: https://ealebed.github.io/posts/2019/знакомство-с-kubernetes-часть-19-horizontalpodautoscaler/



2023-01-03T00:09:28
DevOps

Ресурсы в Kubernetes. Часть 2: Процессор (CPU)

В первой части мы рассмотрели два типа требований (requests и limits) к ресурсам с точки зрения Kubernetes и разобрались с указанием этих параметров применительно к памяти. В данной статье рассмотрим нюансы настройки параметров requests и limits в контексте работы процессора (CPU). Давайте разберемся!




Итак, что имеется в виду под CPU когда мы говорим о Kubernetes? Один CPU это эквивалент “одного процессорного ядра”, предоставляемого операционной системой рабочего узла, вне зависимости от того, какое это ядро — физическое (physical core), поток физического ядра (hyper-thread), виртуальное ядро (например, EC2 vCPU, которое по сути, тоже является потоком физичекого ядра).




В отличие от ограничений (limits) по памяти, лимиты по CPU с точки зрения Kubernetes являются “сжимаемыми”, следовательно может работать так называемый CPU Throttling — снижение частоты процессора, и, как следствие, производительности. Когда вы устанавливаете значение limits для CPU:




...
    resources:
      limits:
        cpu: "1"
        memory: 2Gi
...




вы на самом деле указываете время использования процессора (CPU time) на всех доступных процессорных ядрах рабочего узла (ноды), а не “привязываете” свой контейнер к конкретному ядру (или группе ядер). Это значит, что даже если вы указываете в .limits.cpu число меньшее общего количества ядер ноды, то контейнер все равно будет “видеть” и использовать все ядра, ограничиваясь только временем их использования.




К примеру, если контейнеру, который запускается на рабочем узле с общим количеством ядер 8, в значении CPU limits установить 4, то контейнер будет использовать эквивалент 4-х ядер, распределенных по всем 8 CPU ноды. В данном примере максимально допустимое использование процессора (CPU usage) на рабочем узле будет равняться 50%.




Как это выглядит с точки зрения Docker? Kubernetes управляет ограничениями CPU передавая параметры cpu-period и cpu-quota. Параметр cpu-period определяет период времени, в течении которого отслеживается использование процессора (CPU utilisation) контейнером и он всегда равен 100000µs (100ms). Параметр cpu-quota — это общее количество процессорного времени, которое контейнер может использовать в каждом cpu-period‘е. Эти два параметра влияют на работу CFS (абсолютно честного планировщика ядра, Completely Fair Scheduler). Конкретный пример соответствия значений CPU limits значениям cpu-quota в конфигурации Docker:




limits 1:	cpu-quota=100000
limits 4:	cpu-quota=400000
limits 0.5:	cpu-quota=50000




Здесь limits 1 означает, что каждые 100ms контейнером могут использоваться 100% эквивалента 1 процессорного ядра рабочего узла, limits 4 указывает, что контейнер может использовать 400% эквивалента 1 ядра (ну или 100% процессорных 4-х ядер) и т.д. Не забываем, что это использование “размазывается” на все доступные ядра рабочей ноды, без привязки к конкретным ядрам. Благодаря работе “абсюлютно честного планировщика” (CFS), любому контейнеру, превышающему свою квоту в данный период (имеется в виду cpu-period рассмотренный выше), будет запрещено использовать процессор до наступления следующего периода.




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




Таким образом, при использовании requests, вам гарантирован эквивалент количества указанных CPU, но что произойдет, если рабочий узел кластера будет находиться под чрезмерной нагрузкой (использование процессора на 100% или внезапные скачки LA)? В этом случае приоритет использования процессорного времени будет вычисляться исходя из значения, указанного в CPU requests и умноженного на 1024 — результат будет передан Docker’у как параметр cpu-shares. Это так называемый “вес” — если все контейнеры данного рабочего узла имеют одинаковый вес, то они будут иметь одинаковый приоритет при планировании и использовании процессорного времени при чрезмерной нагрузке; если у контейнеров рабочего узла вес разный, то контейнер с большим весом будет иметь высший приоритет и получит больше процессорного времени при чрезмерной нагрузке процессора на рабочей ноде.




В предыдущей статье мы уже упоминали о QoS (классах качества сервиса) — они справедливы и в контексте CPU. Используя класс Burstable вы можете получить дополнительные периоды времени использования CPU (при условии, что эти же ресурсы не требуются другим контейнерам). Потенциально, это позволяет более эффективно использовать ресурсы кластера, правда, за счет большей непредсказуемости — повышенное использование CPU одним контейнером на рабочем узле повлияет на “соседей”, работающих на той же ноде кластера.




Опять же, если вы новичок в Kubernetes, лучше всего обеспечить класс сервиса Guaranteed QoS, устанавливая значения requests и limits одинаковыми. Когда вы соберете больше данных (метрик) и лучше разберетесь с использованием процессорных ресурсов контейнерами, есть смысл начать использовать класс сервиса Burstable QoS для обдуманной оптимизации расходов на инфраструктуру.




Сколько CPU стоит выделить контейнеру при написании манифеста? К сожалению, не существует универсального ответа на этот вопрос — все зависит от характеристик вашего приложения, требуемой производительности, места размещения контейнера, стоимости и т. д. Но если вы достаточно хорошо знаете, как работает ваше приложение “под капотом” и при наличии приличных инструментов для сбора и анализа метрик (например, Prometheus) можно подобрать оптимальную конфигурацию. В крайнем случае, можно даже получить кое-какие цифры для анализа выполнив внутри контейнера команду:




cat /sys/fs/cgroup/cpu,cpuacct/cpu.stat

nr_periods 345489
nr_throttled 502
throttled_time 109456473902




Так можно получить общее количество периодов запуска, количество раз, когда производительность процессора для данного контейнера была принудительно снижена (CPU Throttled) и общее время троттлинга в наносекундах.




Надеюсь, теперь вы знаете больше о требованиях к ресурсам, классах сервисов и определениях памяти (memory) и процессора (CPU) в контексте работы с Docker и Kubernetes.




Источник: https://ealebed.github.io/posts/2019/ресурсы-в-kubernetes-часть-2-cpu/



2023-01-03T00:08:25
DevOps

Ресурсы в Kubernetes. Часть 1: Память (Memory)

Чтобы Kubernetes смог максимально эффективно использовать доступную инфраструктуру и корректно выделить ресурсы, необходимые для работы вашего приложения, вам следует указать требования в ресурсам каждого контейнера. В данный момент есть возможность задавать два типа требований (requests и limits) для двух типов ресурсов — памяти (memory) и процессора (CPU). В данной статье рассмотрим requests и limits применительно к памяти — давайте разберемся!




При описании пода (Pods) для каждого из его контейнеров могут быть заданы требования к ресурсам в следующем формате:




...
resources:
  limits:
    cpu: "2"
    memory: 2Gi
  requests:
    cpu: "2"
    memory: 2Gi
...




Тип требований requests используется в Kubernetes планировщиком для корректного размещения и запуска подов в существующей инфраструктуре, как бы говоря “запусти контейнеры данного пода там, где есть достаточное количество запрощенных ресурсов”. Limits — жесткое ограничение ресурсов, доступных контейнеру и среде его выполнения (тут и далее имеется в виду Docker container runtime). Превышение указанных лимитов (limits) ресурсов зачастую приводит к троттлингу или остановке (termination) контейнера.




Если значение requests для контейнера не указано, то по умолчанию будет использоваться значение установленное в limits. Если же не указано значение limits, то по умолчанию это значение будет равно 0 (если верить документации — неограниченно. На самом деле ограничивается ресурсами узла, на котором запускается под).




Возникает вопрос, стоит ли указывать значения limits больше, чем requests? Если ваше приложение стабильно использует предсказуемый объем оперативной памяти, то устанавливать разные значения параметров requests и limits для памяти нет смысла. В случае с CPU, разница между заданными значениями requests и limits может не устанавливаться (при условии, что эти же ресурсы не используются другими контейнерами и их не нужно “делить”).




Если вы новичок в Kubernetes, для начала лучше всего использовать значения limits точно такие же как и requests — это обеспечит так называемый “гарантированный класс качества сервиса” (Guaranteed QoS class, об этих классах чуть ниже). С другой стороны, класс Burstable QoS потенциально позволяет более эффективно использовать ресурсы инфраструктуры, правда, за счет большей непредсказуемости — например, рост CPU-latency может повлиять на остальные поды/контейнеры, запущенные на том же рабочем узле (ноде).




В Kubernetes QoS классы используются в соответствии с наличием и конфигурацией requests и limits (детальное описание):




  • если для всех контейнеров пода установлены отличные от 0 requests и limits для всех типов ресурсов, и эти значения равны, то под будет принадлежать к классу Guaranteed;



  • если для одного или нескольких контейнера пода установлены отличные от 0 requests и limits для одного или всех типов ресурсов и эти значения не равны, то под будет принадлежать к классу Burstable;



  • если для всех контейнеров пода не установлены значения requests и limits для всех типов ресурсов, то поду будет присвоен класс Best-Effort.




Поды класса Best-Effort обладают наименьшим приоритетом. Они могут использовать любое количество свободной памяти, доступное на рабочем узле, но будут остановлены в первую очередь, если система испытывает недостаток памяти (under memory pressure). Поды класса Burstable обычно имеют некоторое гарантированное количество ресурсов (благодаря requests), но могут использовать больше ресурсов (если такие доступны). Если система испытывает недостаток памяти (и остановка подов с классом Best-Effort не помогла), то поды данного класса, которые превысили значение заданное в requests будут остановлены. Класс Guaranteed обладает максимальным приоритетом, и поды данного класса будут остановлены только если они используют больше ресурсов, чем установлено в limits.




Итак, что же означает память (memory) в данном контексте? В нашем случае, это общее значение размера страниц памяти (Resident set size, RSS) и использования кэша страниц (page cache) контейнерами.




Примечание. В “чистом” docker’е в это значение также входит своп (swap), который предусмотрительно отключен в Kubernetes.




RSS — размер страниц памяти, выделенных процессу операционной системой и в настоящее время находящихся в ОЗУ. Например, для Java процесса это heap (куча), non-heap (стек) память, оff-heap (она же native memory) и т. д.




Кэш страниц — иногда также называемый дисковый кэшем, используется для кеширования блоков с HDD/SSD. Все операции ввода/вывода обычно происходят через этот кэш (из соображений производительности). Чем больше данных читает/записывает ваше приложение на диск, тем больший объем памяти необходим для кэша страниц. Ядро будет использовать доступную память для кэша страниц, но будет освобождать ее, если память понадобится в другом месте/процессе — таким образом производительность вашего приложения может снижаться при недостаточном объеме оперативной памяти.




Исходя из документации docker, можно сказать, что размер кэша страниц, используемых контейнером, может сильно отличаться в зависимости от того, могут ли некоторые файлы “поделены” между несколькими контейнерами, запущенными на одном рабочем узле (достигается благодаря overlayfs storage driver).




Значения параметров requests и limits измеряются в байтах, однако можно использовать и суффиксы. К примеру, настройка памяти JVM Xmx1g (1024³ bytes) будет соответствовать 1Gi в спецификации контейнера.




Ограничения по памяти (limits) с точки зрения Kubernetes считаются “несжимаемыми” (non-compressible), следовательно при превышении этих ограничений троттлинг невозможен — ядро будет агрессивно очищать кэш страниц (для освобождения ресурсов / достижения желаемого состояния рабочего узла) и контейнеры к конце концов могут быть остановлены (прерваны) хорошо известным Linux Out of Memory (OOM) Killer.




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




На этом все, в следующей статье рассмотрим requests и limits применительно к использованию процессора (CPU).



2023-01-03T00:07:01
DevOps

Kubernetes — установить Cosnul

Consul — это децентрализованный отказоустойчивый discovery-сервис от компании HashiCorp (которая разрабатывает такие продукты как Vagrant, TerraForm, Otto, Atlas и другие).




Consul является децентрализованным сервисом, то есть Consul agent устанавливается на каждый хост и является полноправным участником кластера. Таким образом, сервисам не нужно знать адрес discovery в нашей сети, все запросы к discovery выполняются на локальный адрес 127.0.0.1.




В этом руководстве вы развернете центр обработки данных Consul с официальным чартом Helm.
Вам не нужно обновлять какие-либо значения в чарте Хелма для базовой установки.
Однако вы можете создать файл значений с параметрами, чтобы разрешить доступ к пользовательскому интерфейсу Consul.
Предупреждение о безопасности. Это руководство не для производственного использования. По умолчанию на диаграмме будет установлена небезопасная конфигурация Consul. Пожалуйста, обратитесь к документации Kubernetes, чтобы определить, как вы можете обеспечить безопасность Consul на Kubernetes в производстве. Кроме того, настоятельно рекомендуется использовать правильно защищенный кластер Kubernetes или убедиться, что вы понимаете и включаете рекомендуемые функции безопасности.
Для успешного выполнения этого руководства у вас должен быть существующий кластер Kubernetes и локально настроенные Helm и kubectl.




Разворачиваем Consul




Вы можете развернуть полный центр обработки данных Consul, используя официальный чарт Helm.




По умолчанию в чарте будут установлены три сервера Consul и клиент на всех узлах Kubernetes.




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




Скачать Helm чарт




Во-первых, вам нужно будет клонировать официальный Helm чарт из репозитория Gashub от HashiCorp.




$ git clone https://github.com/hashicorp/consul-helm.git




Вам не нужно обновлять чарт Helm перед развертыванием Консула, т.к. он имеет разумные значения по умолчанию.




Ознакомьтесь с документацией по чартам Helm, чтобы узнать больше информации.




Установка Consul через Helm




Чтобы развернуть Consul, вы должны быть в том же каталоге, что и чарт.




$ cd consul-helm




Теперь вы можете развернуть Консул с помощью установки helm.




Это позволит развернуть три сервера и агента на всех узлах Kubernetes.




Процесс должен быть быстрым, менее 5 минут.




$ helm install .



NAME:   mollified-robin LAST DEPLOYED: Mon Feb 25 15:57:18 2019 NAMESPACE: default STATUS: DEPLOYED

NAME                             READY  STATUS             RESTARTS  AGE

mollified-robin-consul-25r6z     0/1    ContainerCreating  0         0s

mollified-robin-consul-4p6hr     0/1    ContainerCreating  0         0s

mollified-robin-consul-n82j6     0/1    ContainerCreating  0         0s

mollified-robin-consul-server-0  0/1    Pending            0         0s

mollified-robin-consul-server-1  0/1    Pending            0         0s

mollified-robin-consul-server-2  0/1    Pending            0         0s




Вывод, показщанный выше был уменьшен для удобства чтения.




Однако вы можете видеть, что в этом кластере Kubernetes с тремя узлами есть три сервера Consul и три клиента Consul.




Доступ к Consul UI




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




В качестве альтернативы, если вы не хотите обновлять свой кластер, вы можете настроить переадресацию портов с помощью kubectl.




Создайте файл значений




Сначала создайте файл значений, который можно передать в командной строке при обновлении.




# values.yaml

global:

  datacenter: hashidc1

syncCatalog:

  enabled: true

ui:

  service:

    type: 'LoadBalancer'

server:

  affinity: |

    podAntiAffinity:

      requiredDuringSchedulingIgnoredDuringExecution:

        - labelSelector:

            matchLabels:

              app: {{ template "consul.name" . }}

              release: "{{ .Release.Name }}"

              component: server

        topologyKey: kubernetes.io/hostname




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




Параметры синхронизации каталога позволят вам увидеть сервисы Kubernetes в пользовательском интерфейсе Consul.




Инициируйте обновление




Наконец, инициируйте обновление с помощью helm upgrade и флага -f, который передается в ваш новый файл значений.




Этот процесс также должен быть быстрым, менее минуты.




$ helm upgrade consul -f values.yaml




Теперь вы можете использовать kubectl get services для определения внешнего IP-адреса вашего пользовательского интерфейса Consul.




$ kubectl get services

NAME                            TYPE           CLUSTER-IP     EXTERNAL-IP             PORT(S)        AGE

consul                          ExternalName   <none>         consul.service.consul   <none>         11d

kubernetes                      ClusterIP      122.16.14.1    <none>                  443/TCP        137d

mollified-robin-consul-dns      ClusterIP      122.16.14.25   <none>                  53/TCP,53/UDP  13d

mollified-robin-consul-server   ClusterIP      None           <none>                  8500/TCP       13d

mollified-robin-consul-ui       LoadBalancer   122.16.31.395  36.276.67.195           8




Кроме того, вы можете использовать kubectl get pods для просмотра нового процесса синхронизации.




Процесс синхронизации каталога по умолчанию синхронизирует службы Consul и Kubernetes в обоих направлениях.




$ kubectl get pods

NAME                                                 READY   STATUS      RESTARTS   AGE

mollified-robin-consul-d8mnp                          1/1     Running     0         15d

mollified-robin-consul-p4m89                          1/1     Running     0         15d

mollified-robin-consul-qclqc                          1/1     Running     0         15d

mollified-robin-consul-server-0                       1/1     Running     0         15d

mollified-robin-consul-server-1                       1/1     Running     0         15d

mollified-robin-consul-server-2                       1/1     Running     0         15d

mollified-robin-consul-sync-catalog-f75cd5846-wjfdk   1/1     Running     0




Служба должна была добавитьcя по имени развертывания consul-ui.





Обратите внимание, вам не нужно указывать порт при доступе к панели мониторинга.




Доступ к Consul




Помимо доступа к Consul с помощью пользовательского интерфейса, вы можете управлять Consul с помощью HTTP API или напрямую подключаясь к поду с помощью kubectl.




Kubectl




Для доступа к каталогу pod и data вы можете запустить kodectl в pod для запуска сеанса оболочки.




$ kubectl exec -it mollified-robin-consul-server-0 /bin/sh




Это позволит вам перемещаться по файловой системе и запускать консольные команды CLI на поде.




Например, вы можете просмотреть Consul members.




$ consul members

Node                                   Address           Status  Type    Build  Protocol  DC        Segment

mollified-robin-consul-server-0        172.20.2.18:8301  alive   server  1.4.2  2         hashidc1  <all>

mollified-robin-consul-server-1        172.20.0.21:8301  alive   server  1.4.2  2         hashidc1  <all>

mollified-robin-consul-server-2        172.20.1.18:8301  alive   server  1.4.2  2         hashidc1  <all>

gke-tier-2-cluster-default-pool-leri5  172.20.1.17:8301  alive   client  1.4.2  2         hashidc1  <default>

gke-tier-2-cluster-default-pool-gnv4   172.20.2.17:8301  alive   client  1.4.2  2         hashidc1  <default>

gke-tier-2-cluster-default-pool-zrr0   172.20.0.20:8301  alive   client  1.4.2




Consul HTTP API




Вы можете использовать Consul HTTP API , связавшись с локальным агентом, работающим на узле Kubernetes.




Вы можете прочитать документацию, если хотите узнать больше об использовании Consul HTTP API с Kubernetes.




Источник: https://sidmid.ru/kubernetes-установить-cosnul/



2023-01-02T06:18:22
DevOps