Kubernetes без Kubelet: рассказываем об инструменте KWOK

от автора

Вы когда-нибудь задумывались, как:

  • настроить кластер из тысяч узлов за считанные секунды

  • имитировать реальные узлы с низким потреблением ресурсов

  • протестировать контроллер K8s в масштабе, но при этом не затратив больших средств инфраструктуры

Если вы ответили «Да» на большинство вопросов, то вам, вероятно, будет интересно узнать о KWOK — инструменте, который позволяет создавать кластер из тысяч узлов.

Что это вообще такое?

KWOK расшифровывается как Kubernetes WithOut Kubelet. В KWOK входит две утилиты:

  • kwok — отвечает за моделирование жизненного цикла узлов, pod’ов и других ресурсов API K8s.

  • kwokctl — это инструмент командной строки, предназначенный для простоты создания и управления кластерами с узлами, созданными kwok

Зачем использовать KWOK?

  • Скорость: вы можете создавать и удалять кластеры и узлы почти мгновенно, не дожидаясь полной загрузки

  • Совместимость: KWOK работает с любыми инструментами или клиентами, совместимыми с API K8s: kubectl, helm, kui и т. д.

  • Портативность: KWOK не предъявляет особых требований к оборудованию или программному обеспечению. Вы можете запустить его с использованием готовых образов Docker, Nerdctl, или бинарных файлов.

  • Гибкость: вы можете настраивать типы узлов, метки, кластеры и прочее, а также настраивать варианты поведения pod’ов, чтобы протестировать различные сценарии и граничные случаи.

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

Для чего использовать KWOK

  • Для обучения: вы можете использовать KWOK, чтобы узнать об особенностях и функциях Kubernetes, но при этом не беспокоиться о потере ресурсов или каких-либо других проблемах.

  • Для разработки: KWOK подойдет для создания новых функций или инструментов Kubernetes, при этом вам не потребуется задействовать реальный кластер.

  • Для тестирования. Вы сможете: 

    • Измерить, насколько хорошо ваше приложение масштабируется с разным количеством узлов и pod’ов.

    • Увеличить нагрузку на кластер, создав множество pod’ов или служб с различными запросами ресурсов или ограничениями.

    • Моделировать сбои узлов или сетевые разделы, изменяя условия для узлов или случайным образом их удаляя.

    • Проверить, как ваш контроллер взаимодействует с другими компонентами K8s, задействовать различные версии API.

Какие есть ограничения?

KWOK не направлен на полную замену других инструментов: у него есть ограничения.

  • Функциональность: KWOK  — это не kubelet, поведение может отличаться при управлении жизненными циклами модулей, монтировании томов и подключаемых модулей устройств. Его основная функция — имитировать обновления узлов и pod’ов.

  • Точность: KWOK не точно отражает производительность или поведение реальных узлов при различных рабочих нагрузках или средах. Вместо этого он приблизительно воспроизводит некоторые модели поведения с помощью простых формул.

  • Безопасность: KWOK не применяет никаких политик или механизмов безопасности.

Начинаем работать с KWOK

Запускаем кластер

docker run --rm -it -p 8080:8080 registry.k8s.io/kwok/cluster:v1.26.0
Creating cluster                                                                                                   cluster=kwok Starting cluster                                                                                                   cluster=kwok Cluster is created                                                                                      cluster=kwok elapsed=1s You can now use your cluster with:      kubectl config use-context kwok-kwok  Thanks for using kwok! ############################################################################### > kubectl -s :8080 version WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version. Client Version: version.Info{Major:"1", Minor:"26", GitVersion:"v1.26.0", GitCommit:"b46a3f887ca979b1a5d14fd39cb1af43e7e5d12d", GitTreeState:"clean", BuildDate:"2022-12-08T19:58:30Z", GoVersion:"go1.19.4", Compiler:"gc", Platform:"linux/amd64"} Kustomize Version: v4.5.7 Server Version: version.Info{Major:"1", Minor:"26", GitVersion:"v1.26.0", GitCommit:"b46a3f887ca979b1a5d14fd39cb1af43e7e5d12d", GitTreeState:"clean", BuildDate:"2022-12-08T19:51:45Z", GoVersion:"go1.19.4", Compiler:"gc", Platform:"linux/amd64"} ############################################################################### # The following kubeconfig can be used to connect to the Kubernetes API server apiVersion: v1 clusters: - cluster:     server: http://127.0.0.1:8080   name: kwok contexts: - context:     cluster: kwok   name: kwok current-context: kwok kind: Config preferences: {} users: null ############################################################################### > kubectl -s :8080 get ns NAME              STATUS   AGE default           Active   0s kube-node-lease   Active   1s kube-public       Active   1s kube-system       Active   1s ############################################################################### # The above example works if your host's port is the same as the container's, # otherwise, change it to your host's port Starting to serve on [::]:8080

Как установить kwokctl и kwok:

  1. На Linux/MacOS: с помощью команды brew

brew install kwok
  1. Для бинарных версий:

  • Подготовьте переменные:

# KWOK repository KWOK_REPO=kubernetes-sigs/kwok # Get latest KWOK_LATEST_RELEASE=$(curl "https://api.github.com/repos/${KWOK_REPO}/releases/latest" | jq -r '.tag_name')
  • Установите kwokctl

wget -O kwokctl -c "https://github.com/${KWOK_REPO}/releases/download/${KWOK_LATEST_RELEASE}/kwokctl-$(go env GOOS)-$(go env GOARCH)" chmod +x kwokctl sudo mv kwokctl /usr/local/bin/kwokctl
  • Установите kwok

wget -O kwok -c "https://github.com/${KWOK_REPO}/releases/download/${KWOK_LATEST_RELEASE}/kwok-$(go env GOOS)-$(go env GOARCH)" chmod +x kwok sudo mv kwok /usr/local/bin/kwok

Как развернуть kwok в кластере:

  1. Подготовьте переменные:

# Temporary directory KWOK_WORK_DIR=$(mktemp -d) # KWOK repository KWOK_REPO=kubernetes-sigs/kwok # Get latest KWOK_LATEST_RELEASE=$(curl "https://api.github.com/repos/${KWOK_REPO}/releases/latest" | jq -r '.tag_name')
  1. Создайте YAML шаблона настройки для ранее определенного временного каталога:

cat <<EOF > "${KWOK_WORK_DIR}/kustomization.yaml" apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images:   - name: registry.k8s.io/kwok/kwok     newTag: "${KWOK_LATEST_RELEASE}" resources:   - "https://github.com/${KWOK_REPO}/kustomize/kwok?ref=${KWOK_LATEST_RELEASE}" EOF

Затем примените шаблон настройки.

kubectl kustomize "${KWOK_WORK_DIR}" > "${KWOK_WORK_DIR}/kwok.yaml"
  1. Теперь можете развернуть kwok

kubectl apply -f "${KWOK_WORK_DIR}/kwok.yaml"

После вы можете запускать кластер на локальном компьютере и следить за его состоянием:

kwok \   --kubeconfig=~/.kube/config \   --manage-all-nodes=false \   --manage-nodes-with-annotation-selector=kwok.x-k8s.io/node=fake \   --manage-nodes-with-label-selector= \   --disregard-status-with-annotation-selector=kwok.x-k8s.io/status=custom \   --disregard-status-with-label-selector= \   --cidr=10.0.0.1/24 \   --node-ip=10.0.0.1

Как запускать kwokctl для управления ложными кластерами:

  1. Установите kwokctl

  2. Создайте кластер

$ kwokctl create cluster --name=kwok kwokctl create cluster Creating cluster "kwok-kwok" Starting cluster "kwok-kwok" Cluster "kwok-kwok" is ready You can now use your cluster with:      kubectl config use-context kwok-kwok  Thanks for using kwok!

Переключаем  конфигурации

kubectl config use-context kwok-kwok
  1. Переводим кластер под контроль kwokctl

$ kwokctl get clusters kwok
  1. Удаляем кластер

$ kwokctl delete cluster --name=kwok Stopping cluster "kwok-kwok" Deleting cluster "kwok-kwok" Cluster "kwok-kwok" deleted

Как управлять узлами и pod’ами с помощью kwok

  1. kwok с аргументами —manage-all-nodes=true

    С аргументом  —manage-all-nodes=true kwok будет отвечать за все узлы в кластере и поддерживать их работу на сервере API. Все узлы будут вести себя как реальные и оставаться в состоянии Ready

  2. kwok с аргументами —manage-nodes-with-annotation-selector=kwok.x-k8s.io/node=fake

    Здесь kwok будет отвечать за все pod’ы с аннотацией kwok.x-k8s.io/node=fake. Если у поля .spec.nodeName pod’а есть значение, kwok будет оставлять их состоянии Running.

  3. С помощью kwok вы можете присоединиться к произвольному узлу или узлам, просто создав объект(объекты) v1.Node:

kubectl apply -f - <<EOF apiVersion: v1 kind: Node metadata:   annotations:     node.alpha.kubernetes.io/ttl: "0"     kwok.x-k8s.io/node: fake   labels:     beta.kubernetes.io/arch: amd64     beta.kubernetes.io/os: linux     kubernetes.io/arch: amd64     kubernetes.io/hostname: kwok-node-0     kubernetes.io/os: linux     kubernetes.io/role: agent     node-role.kubernetes.io/agent: ""     type: kwok   name: kwok-node-0 spec:   taints: # Avoid scheduling actual running pods to fake Node     - effect: NoSchedule       key: kwok.x-k8s.io/node       value: fake status:   allocatable:     cpu: 32     memory: 256Gi     pods: 110   capacity:     cpu: 32     memory: 256Gi     pods: 110   nodeInfo:     architecture: amd64     bootID: ""     containerRuntimeVersion: ""     kernelVersion: ""     kubeProxyVersion: fake     kubeletVersion: fake     machineID: ""     operatingSystem: linux     osImage: ""     systemUUID: ""   phase: Running EOF

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

$ kubectl get node -o wide NAME          STATUS   ROLES   AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE    KERNEL-VERSION   CONTAINER-RUNTIME kwok-node-0   Ready    agent   5s    fake      196.168.0.1   <none>        <unknown>   <unknown>        <unknown>
  1. Создание Pod

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

kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata:   name: fake-pod   namespace: default spec:   replicas: 10   selector:     matchLabels:       app: fake-pod   template:     metadata:       labels:         app: fake-pod     spec:       affinity:         nodeAffinity:           requiredDuringSchedulingIgnoredDuringExecution:             nodeSelectorTerms:               - matchExpressions:                   - key: type                     operator: In                     values:                       - kwok       # A taints was added to an automatically created Node.       # You can remove taints of Node or add this tolerations.       tolerations:         - key: "kwok.x-k8s.io/node"           operator: "Exists"           effect: "NoSchedule"       containers:         - name: fake-container           image: fake-image EOF

После того, как pod создан, мы видим, что все pod’ы размещены на узлах и имеют статус Running.

$ kubectl get pod -o wide NAME                        READY   STATUS    RESTARTS   AGE   IP          NODE          NOMINATED NODE   READINESS GATES fake-pod-59bb47845f-4vl9f   1/1     Running   0          5s    10.0.0.5    kwok-node-0   <none>           <none> fake-pod-59bb47845f-bc49m   1/1     Running   0          5s    10.0.0.4    kwok-node-0   <none>           <none> fake-pod-59bb47845f-cnjsv   1/1     Running   0          5s    10.0.0.7    kwok-node-0   <none>           <none> fake-pod-59bb47845f-g29wz   1/1     Running   0          5s    10.0.0.2    kwok-node-0   <none>           <none> fake-pod-59bb47845f-gxq88   1/1     Running   0          5s    10.0.0.10   kwok-node-0   <none>           <none> fake-pod-59bb47845f-pnzmn   1/1     Running   0          5s    10.0.0.9    kwok-node-0   <none>           <none> fake-pod-59bb47845f-sfkk4   1/1     Running   0          5s    10.0.0.3    kwok-node-0   <none>           <none> fake-pod-59bb47845f-vl2z5   1/1     Running   0          5s    10.0.0.8    kwok-node-0   <none>           <none> fake-pod-59bb47845f-vpfhv   1/1     Running   0          5s    10.0.0.6    kwok-node-0   <none>           <none> fake-pod-59bb47845f-wxn4b   1/1     Running   0          5s    10.0.0.1    kwok-node-0   <none>           <none>
  1. Обновите спецификацию

    В kwok узлы и pod’ы — это чистые объекты API, поэтому вы можете изменять их спецификации, чтобы создать симуляцию или провести тестирование.

Как сохранить или восстановить кластер с помощью kwokctl

  1. Настраиваем политику аудита

cat <<EOF > audit-policy.yaml apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata EOF
  1. Создаем кластер

kwokctl create cluster --kube-audit-policy audit-policy.yaml
  1. Получаем журнал аудита

kwokctl logs audit
  1. Пример журнала аудита по ссылке

Как настроить функции kwok/ kwokctl

Для настройки вам потребуется создать файл конфигурации YAML . Минимальный допустимый файл конфигурации выглядит так:

kind: KwokConfiguration apiVersion: kwok.x-k8s.io/v1alpha1 options: --- kind: KwokctlConfiguration apiVersion: kwok.x-k8s.io/v1alpha1 options:

Эта конфигурация показывает, что мы настраиваем kwok/ kwokctl, используя версию v1alpha1( apiVersion: kwok.x-k8s.io/v1alpha1).

Чтобы задать кластеру правильные параметры, необходимо указать версию kwok

Чтобы использовать эту конфигурацию, поместите содержимое в файл ~/.kwok/kwok.yaml или запустите команду —config=kwok.yaml из того же каталога.

Примечание о флагах CLI, переменных среды и файлах конфигурации

Очередность приоритетов конфигурации для kwok: 

  1. флаги, указанные в командной строке

  2. переменные окружения (с префиксом KWOK_)

  3. значения, указанные в файле конфигурации ( —config= или ~/.kwok/kwok.yaml)

  4. значения по умолчанию

Использование kwok

При использовании kwok берет свою конфигурацию из соответствующего файла и игнорирует все остальные конфигурации.

Использование kwokctl

kwokctl берет свою конфигурацию из файла конфигурации и передает её в kwok.

Конфигурация Stage

Stage API — это kwok-конфигурация , которая позволяет пользователям определять и моделировать различные этапы жизненного цикла ресурсов Kubernetes: узлов и pod’ов . Каждый ресурс Stage задает поле resourceRef, определяющее тип ресурса, к которому он применяется, и поле selector, определяющее, когда этап должен быть выполнен.

kind: Stage apiVersion: kwok.x-k8s.io/v1alpha1 metadata:   name: <string> spec:   resourceRef:     apiGroup: <string>     kind: <string>   selector:     matchLabels:       <string>: <string>     matchAnnotations:       <string>: <string>     matchExpressions:       - key: <expressions-string>         operator: <string>         values:           - <string>   delay:     durationMilliseconds: <int>     durationFrom:       expressionFrom: <expressions-string>     jitterDurationMilliseconds: <int>     jitterDurationFrom:       expressionFrom: <expressions-string>   next:     statusTemplate: <string>     finalizers:       add:         - value: <string>       remove:         - value: <string>       empty: <bool>     delete: <bool>

Установив поля selector и next в spec Stage, вы можете указать условия, при которых применяется конфигурация, а также изменения, которые будут внесены в ресурс при применении этапа. Поле next позволяет пользователям определять новое состояние ресурса с помощью поля statusTemplate, изменять finalizers ресурса или выполнять delete для ресурса. 

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

Настраивая поля delay, selector, и next, вы можете контролировать, когда и как применяется этап. Это позволяет создавать сложные и реалистичные модели для тестирования, проверки и экспериментирования, а также получать представление о поведении и производительности ваших приложений и инфраструктуры.

Примеры

  1. Показываем, как настроить простые узлы для kwok

Стадия node-initialize применяется к узлам, в поле которых не задано никаких условий status.conditions. При применении этот этап задает status.conditionsполе для узла, а также поля status.addresses, status.allocatableи status.capacity.

Этап node-heartbeat применяется к узлам, в поле которых есть условие Ready. При применении этот этап поддерживает поле для узла.Truestatus.conditionsstatus.conditions

  1. Как настроить pod

Stage pod-create-and-ready применяется к pod’ам, у которых нет status.podIP и у которых нет metadata.deletionTimestamp. При применении этот этап устанавливает поля status.conditions, status.containerStatuses, status.initContainerStatuses, status.hostIP и status.podIP для узла. Он также установит поля Phase и startTime, указывающие на то, что узел запущен и работает.

Этап pod-completed-for-job применяется к работающим узлам, не имеющим metadata.deletionTimestamp и принадлежащим заданию. При применении этот этап обновляет status.containerStatuses для узла, устанавливая для полей готовности и запуска значение true, а state.terminated указывает, что узел завершил работу. Он также устанавливает для этапа значение Succeeded: он показывает, что узел завершил работу.

Stage pod-delete применяется к узлам с установленным metadata.deletionTimestamp. При применении этот этап очищает поле metadata.finalizers для узла, позволяя удалить его, а затем и сам узел.

Пример по ссылке.

Освоить работу с Kubernetes

вы можете на наших курсах: Kubernetes База и Kubernetes для разработчиков.

Есть формат самостоятельной работы — вам откроются лекции, практические работы и сертификация, а по Kubernetes База мы запускаем новый поток, который стартует 11 мая. Это формат, где вы будете погружаться в глубины K8s вместе с другими студентами, а на вопросы по инструменту вам будут отвечать спикеры курса.

Узнать больше о курсе Kubernetes для разработчиков и записаться на поток Kubernetes База можно на нашем сайте.


ссылка на оригинал статьи https://habr.com/ru/company/southbridge/blog/721830/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *