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

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

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

  • протестировать контроллер 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 База можно на нашем сайте.

Комментарии (0)