
Вы когда-нибудь задумывались, как:
настроить кластер из тысяч узлов за считанные секунды
имитировать реальные узлы с низким потреблением ресурсов
протестировать контроллер 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:
На Linux/MacOS: с помощью команды brew
brew install kwok
Для бинарных версий:
Подготовьте переменные:
# 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 в кластере:
Подготовьте переменные:
# 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')
Создайте 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"
Теперь можете развернуть 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 для управления ложными кластерами:
Установите kwokctl
Создайте кластер
$ 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
Переводим кластер под контроль kwokctl
$ kwokctl get clusters kwok
Удаляем кластер
$ kwokctl delete cluster --name=kwok Stopping cluster "kwok-kwok" Deleting cluster "kwok-kwok" Cluster "kwok-kwok" deleted
Как управлять узлами и pod'ами с помощью kwok
kwok с аргументами --manage-all-nodes=true
С аргументом --manage-all-nodes=true kwok будет отвечать за все узлы в кластере и поддерживать их работу на сервере API. Все узлы будут вести себя как реальные и оставаться в состоянии Readykwok с аргументами --manage-nodes-with-annotation-selector=kwok.x-k8s.io/node=fake
Здесь kwok будет отвечать за все pod’ы с аннотацией kwok.x-k8s.io/node=fake. Если у поля .spec.nodeName pod’а есть значение, kwok будет оставлять их состоянии Running.С помощью 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>
Создание 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>
Обновите спецификацию
В kwok узлы и pod’ы — это чистые объекты API, поэтому вы можете изменять их спецификации, чтобы создать симуляцию или провести тестирование.
Как сохранить или восстановить кластер с помощью kwokctl
Настраиваем политику аудита
cat <<EOF > audit-policy.yaml apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata EOF
Создаем кластер
kwokctl create cluster --kube-audit-policy audit-policy.yaml
Получаем журнал аудита
kwokctl logs audit
Пример журнала аудита по ссылке
Как настроить функции 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:
флаги, указанные в командной строке
переменные окружения (с префиксом KWOK_)
значения, указанные в файле конфигурации ( --config= или ~/.kwok/kwok.yaml)
значения по умолчанию
Использование 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, вы можете контролировать, когда и как применяется этап. Это позволяет создавать сложные и реалистичные модели для тестирования, проверки и экспериментирования, а также получать представление о поведении и производительности ваших приложений и инфраструктуры.
Примеры
Показываем, как настроить простые узлы для kwok

Стадия node-initialize применяется к узлам, в поле которых не задано никаких условий status.conditions. При применении этот этап задает status.conditionsполе для узла, а также поля status.addresses, status.allocatableи status.capacity.
Этап node-heartbeat применяется к узлам, в поле которых есть условие Ready. При применении этот этап поддерживает поле для узла.Truestatus.conditionsstatus.conditions
Как настроить 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 База можно на нашем сайте.
