Вы когда-нибудь задумывались, как:
настроить кластер из тысяч узлов за считанные секунды
имитировать реальные узлы с низким потреблением ресурсов
протестировать контроллер 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 База можно на нашем сайте.