Русский
Русский
English
Статистика
Реклама

Kubelet

Перевод Минимально жизнеспособный Kubernetes

31.07.2020 20:21:00 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса DevOps практики и инструменты.





Если вы это читаете, вероятно, вы что-то слышали о Kubernetes (а если нет, то как вы здесь оказались?) Но что же на самом деле представляет собой Kubernetes? Это Оркестрация контейнеров промышленного уровня? Или Cloud-Native Operating System? Что вообще это значит?

Честно говоря, я не уверен на 100%. Но думаю интересно покопаться во внутренностях и посмотреть, что на самом деле происходит в Kubernetes под его многими слоями абстракций. Так что ради интереса, давайте посмотрим, как на самом деле выглядит минимальный кластер Kubernetes. (Это будет намного проще, чем Kubernetes The Hard Way.)

Я полагаю, что у вас есть базовые знания Kubernetes, Linux и контейнеров. Все, о чем мы здесь будем говорить предназначено только для исследования/изучения, не запускайте ничего из этого в продакшене!

Обзор


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



Здесь показано, по крайней мере, восемь компонент, но большинство из них мы проигнорируем. Я хочу заявить, что минимальная вещь, которую можно обоснованно назвать Kubernetes, состоит из трех основных компонент:

  • kubelet
  • kube-apiserver (который зависит от etcd его базы данных)
  • среда выполнения контейнера (в данном случае Docker)


Давайте посмотрим, что о каждом из них говорится в документации (рус., англ.). Сначала kubelet:

Агент, работающий на каждом узле в кластере. Он следит за тем, чтобы контейнеры были запущены в поде.

Звучит достаточно просто. Что насчет среды выполнения контейнеров (container runtime)?

Среда выполнения контейнера это программа, предназначенная для выполнения контейнеров.

Очень информативно. Но если вы знакомы с Docker, то у вас должно быть общее представление о том, что он делает. (Детали разделения ответственностей между средой выполнения контейнеров и kubelet на самом деле довольно тонкие и здесь я не буду в них углубляться.)

И API-сервер?

Сервер API компонент Kubernetes панели управления, который представляет API Kubernetes. API-сервер это клиентская часть панели управления Kubernetes

Любому, кто когда-либо что-либо делал с Kubernetes, приходилось взаимодействовать с API либо напрямую, либо через kubectl. Это сердце того, что делает Kubernetes Kubernetesом мозг, превращающий горы YAML, который мы все знаем и любим (?), в работающую инфраструктуру. Кажется очевидным, что API должен присутствовать в нашей минимальной конфигурации.

Предварительные условия


  • Виртуальная или физическая машина Linux с root-доступом (я использую Ubuntu 18.04 на виртуальной машине).
  • И это все!


Скучная установка


На машину, которую мы будем использовать необходимо установить Docker. (Я не собираюсь подробно рассказывать как работает Docker и контейнеры; если вам интересно, есть замечательные статьи). Давайте просто установим его с помощью apt:

$ sudo apt install docker.io$ sudo systemctl start docker


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

$ curl -L https://dl.k8s.io/v1.18.5/kubernetes-server-linux-amd64.tar.gz > server.tar.gz$ tar xzvf server.tar.gz$ cp kubernetes/server/bin/kubelet .$ cp kubernetes/server/bin/kubectl .$ ./kubelet --versionKubernetes v1.18.5


Что произойдет, если мы просто запустим kubelet?

$ ./kubeletF0609 04:03:29.105194    4583 server.go:254] mkdir /var/lib/kubelet: permission denied


kubelet должен работать от root. Достаточно логично, так как ему надо управлять всем узлом. Давайте посмотрим на его параметры:

$ ./kubelet -h<слишком много строк, чтобы разместить здесь>$ ./kubelet -h | wc -l284


Ого, как много опций! К счастью, нам понадобится только пара из них. Вот один из параметров, который нам интересен:

--pod-manifest-path string


Путь к каталогу, содержащему файлы для статических подов, или путь к файлу с описанием статических подов. Файлы, начинающиеся с точек, игнорируются. (УСТАРЕЛО: этот параметр следует устанавливать в конфигурационном файле, передаваемом в Kubelet через опцию --config. Для дополнительной информации см. kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)

Этот параметр позволяет нам запускать статические поды поды, которые не управляются через Kubernetes API. Статические поды используются редко, но они очень удобны для быстрого поднятия кластера, а это именно то, что нам нужно. Мы проигнорируем это громкое предупреждение (опять же, не запускайте это в проде!) и посмотрим, сможем ли мы запустить под.

Сначала мы создадим каталог для статических подов и запустим kubelet:

$ mkdir pods$ sudo ./kubelet --pod-manifest-path=pods


Затем в другом терминале/окне tmux/еще где-то, мы создадим манифест пода:

$ cat <<EOF > pods/hello.yamlapiVersion: v1kind: Podmetadata:  name: hellospec:  containers:  - image: busybox    name: hello    command: ["echo", "hello world!"]EOF


kubelet начинает писать какие-то предупреждения и кажется, что ничего не происходит. Но это не так! Давайте посмотрим на Docker:

$ sudo docker ps -aCONTAINER ID        IMAGE                  COMMAND                 CREATED             STATUS                      PORTS               NAMES8c8a35e26663        busybox                "echo 'hello world!'"   36 seconds ago      Exited (0) 36 seconds ago                       k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_468f670c3c85f        k8s.gcr.io/pause:3.2   "/pause"                2 minutes ago       Up 2 minutes                                    k8s_POD_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_0$ sudo docker logs k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4hello world!


kubelet прочитал манифест пода и дал Dockerу команду запустить пару контейнеров в соответствии с нашей спецификацией. (Если вам интересно узнать про контейнер pause, то это хакерство Kubernetes подробности смотрите в этом блоге.) Kubelet запустит наш контейнер busybox с указанной командой и будет перезапускать его бесконечно, пока статический под не будет удален.

Поздравьте себя. Мы только что придумали один из самых запутанных способов вывода текста в терминал!

Запускаем etcd


Нашей конечной целью является запуск Kubernetes API, но для этого нам сначала нужно запустить etcd. Давайте запустим минимальный кластер etcd, поместив его настройки в каталог pods (например, pods/etcd.yaml):

apiVersion: v1kind: Podmetadata:  name: etcd  namespace: kube-systemspec:  containers:  - name: etcd    command:    - etcd    - --data-dir=/var/lib/etcd    image: k8s.gcr.io/etcd:3.4.3-0    volumeMounts:    - mountPath: /var/lib/etcd      name: etcd-data  hostNetwork: true  volumes:  - hostPath:      path: /var/lib/etcd      type: DirectoryOrCreate    name: etcd-data


Если вы когда-либо работали с Kubernetes, то подобные YAML-файлы должны быть вам знакомы. Здесь стоит отметить только два момента:

Мы смонтировали папку хоста /var/lib/etcd в под, чтобы данные etcd сохранялись после перезапуска (если этого не сделать, то состояние кластера будет стираться при каждом перезапуске пода, что будет нехорошо даже для минимальной установки Kubernetes).
Мы установили hostNetwork: true. Этот параметр, что неудивительно, настраивает etcd для использования сети хоста вместо внутренней сети пода (это облегчит API-серверу поиск кластера etcd).

Простая проверка показывает, что etcd действительно запущен на localhost и сохраняет данные на диск:

$ curl localhost:2379/version{"etcdserver":"3.4.3","etcdcluster":"3.4.0"}$ sudo tree /var/lib/etcd//var/lib/etcd/ member     snap        db     wal         0.tmp         0000000000000000-0000000000000000.wal


Запуск API-сервера


Запустить API-сервер Kubernetes еще проще. Единственный параметр, который надо передать, --etcd-servers, делает то, что вы ожидаете:

apiVersion: v1kind: Podmetadata:  name: kube-apiserver  namespace: kube-systemspec:  containers:  - name: kube-apiserver    command:    - kube-apiserver    - --etcd-servers=http://127.0.0.1:2379    image: k8s.gcr.io/kube-apiserver:v1.18.5  hostNetwork: true


Поместите этот YAML-файл в каталог pods, и API-сервер запустится. Проверка с помощью curl показывает, что Kubernetes API прослушивает порт 8080 с полностью открытым доступом аутентификация не требуется!

$ curl localhost:8080/healthzok$ curl localhost:8080/api/v1/pods{  "kind": "PodList",  "apiVersion": "v1",  "metadata": {    "selfLink": "/api/v1/pods",    "resourceVersion": "59"  },  "items": []}


(Опять же, не запускайте это в продакшене! Я был немного удивлен, что настройка по умолчанию настолько небезопасна. Но я предполагаю, что это сделано для облегчения разработки и тестирования.)
И, приятный сюрприз, kubectl работает из коробки без каких-либо дополнительных настроек!

$ ./kubectl versionClient Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}$ ./kubectl get podNo resources found in default namespace.


Проблема


Но если копнуть немного глубже, то кажется, что что-то идет не так:

$ ./kubectl get pod -n kube-systemNo resources found in kube-system namespace.


Статические поды, которые мы создали, пропали! На самом деле, наш kubelet-узел вообще не обнаруживается:

$ ./kubectl get nodesNo resources found in default namespace.


В чем же дело? Если вы помните, то несколько абзацев назад мы запускали kubelet с чрезвычайно простым набором параметров командной строки, поэтому kubelet не знает, как связаться с сервером API и уведомлять его о своем состоянии. Изучив документацию, мы находим соответствующий флаг:

--kubeconfig string

Путь к файлу kubeconfig, в котором указано как подключаться к серверу API. Наличие --kubeconfig включает режим API-сервера, отсутствие --kubeconfig включает автономный режим.

Все это время, сами того не зная, мы запускали kubelet в автономном режиме. (Если бы мы были педантичны, то можно было считать автономный режим kubelet как минимально жизнеспособный Kubernetes, но это было бы очень скучно). Чтобы заработала настоящая конфигурация, нам нужно передать файл kubeconfig в kubelet, чтобы он знал, как общаться с API-сервером. К счастью, это довольно просто (так как у нас нет проблем с аутентификацией или сертификатами):

apiVersion: v1kind: Configclusters:- cluster:    server: http://127.0.0.1:8080  name: mink8scontexts:- context:    cluster: mink8s  name: mink8scurrent-context: mink8s


Сохраните это как kubeconfig.yaml, убейте процесс kubelet и перезапустите с необходимыми параметрами:

$ sudo ./kubelet --pod-manifest-path=pods --kubeconfig=kubeconfig.yaml


(Кстати, если вы попытаетесь обратиться к API через curl, когда kubelet не работает, то вы обнаружите, что он все еще работает! Kubelet не является родителем своих подов, подобно Dockerу, он больше похож на управляющего демона. Контейнеры, управляемые kubelet, будут работать, пока kubelet не остановит их.)

Через несколько минут kubectl должен показать нам поды и узлы, как мы и ожидаем:

$ ./kubectl get pods -ANAMESPACE     NAME                    READY   STATUS             RESTARTS   AGEdefault       hello-mink8s            0/1     CrashLoopBackOff   261        21hkube-system   etcd-mink8s             1/1     Running            0          21hkube-system   kube-apiserver-mink8s   1/1     Running            0          21h$ ./kubectl get nodes -owideNAME     STATUS   ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIMEmink8s   Ready    <none>   21h   v1.18.5   10.70.10.228   <none>        Ubuntu 18.04.4 LTS   4.15.0-109-generic   docker://19.3.6


Давайте на этот раз поздравим себя по-настоящему (я знаю, что уже поздравлял) у нас получился минимальный кластер Kubernetes, работающий с полнофункциональным API!

Запускаем под


Теперь посмотрим на что способен API. Начнем с пода nginx:

apiVersion: v1kind: Podmetadata:  name: nginxspec:  containers:  - image: nginx    name: nginx


Здесь мы получим довольно интересную ошибку:

$ ./kubectl apply -f nginx.yamlError from server (Forbidden): error when creating "nginx.yaml": pods "nginx" isforbidden: error looking up service account default/default: serviceaccount"default" not found$ ./kubectl get serviceaccountsNo resources found in default namespace.


Здесь мы видим насколько ужасающе неполна наша среда Kubernetes у нас нет учетных записей для служб. Давайте попробуем еще раз, создав учетную запись службы вручную, и посмотрим, что произойдет:

$ cat <<EOS | ./kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata:  name: default  namespace: defaultEOSserviceaccount/default created$ ./kubectl apply -f nginx.yamlError from server (ServerTimeout): error when creating "nginx.yaml": No APItoken found for service account "default", retry after the token isautomatically created and added to the service account


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

Мы можем обойти эту проблему, установив опцию automountServiceAccountToken для учетной записи службы (так как нам все равно не придется ее использовать):

$ cat <<EOS | ./kubectl apply -f -apiVersion: v1kind: ServiceAccountmetadata:  name: default  namespace: defaultautomountServiceAccountToken: falseEOSserviceaccount/default configured$ ./kubectl apply -f nginx.yamlpod/nginx created$ ./kubectl get podsNAME    READY   STATUS    RESTARTS   AGEnginx   0/1     Pending   0          13m


Наконец, под появился! Но на самом деле он не запустится, так как у нас нет планировщика (scheduler) еще одного важного компонента Kubernetes. Опять же, мы видим, что API Kubernetes на удивление глупый когда вы создаете под в API, он его регистрирует, но не пытается выяснить, на каком узле его запускать.

На самом деле для запуска пода планировщик не нужен. Можно вручную добавить узел в манифест в параметре nodeName:

apiVersion: v1kind: Podmetadata:  name: nginxspec:  containers:  - image: nginx    name: nginx  nodeName: mink8s

(Замените mink8s на название узла.) После delete и apply мы видим, что nginx запустился и слушает внутренний IP-адрес:

$ ./kubectl delete pod nginxpod "nginx" deleted$ ./kubectl apply -f nginx.yamlpod/nginx created$ ./kubectl get pods -owideNAME    READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATESnginx   1/1     Running   0          30s   172.17.0.2   mink8s   <none>           <none>$ curl -s 172.17.0.2 | head -4<!DOCTYPE html><html><head><title>Welcome to nginx!</title>


Чтобы убедиться, что сеть между подами работает корректно, мы можем запустить curl из другого пода:

$ cat <<EOS | ./kubectl apply -f -apiVersion: v1kind: Podmetadata:  name: curlspec:  containers:  - image: curlimages/curl    name: curl    command: ["curl", "172.17.0.2"]  nodeName: mink8sEOSpod/curl created$ ./kubectl logs curl | head -6  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed<!DOCTYPE html><html><head><title>Welcome to nginx!</title>


Довольно интересно покопаться в этом окружении и посмотреть, что работает, а что нет. Я обнаружил, что ConfigMap и Secret работают так, как и ожидается, а Service и Deployment нет.

Успех!


Этот пост становится большим, поэтому я собираюсь объявить о победе и заявить, что это жизнеспособная конфигурация, которую можно назвать Kubernetes". Резюмируя: четыре бинарных файла, пять параметров командной строки и всего лишь 45 строк YAML (не так много по стандартам Kubernetes) и у нас работает немало вещей:

  • Поды управляются с помощью обычного Kubernetes API (с несколькими хаками)
  • Можно загружать публичные образы контейнеров и управлять ими
  • Поды остаются живыми и автоматически перезапускаются
  • Сеть между подами в рамках одного узла работает довольно хорошо
  • ConfigMap, Secret и простейшее монтирование хранилищ работает как положено


Но большая часть из того, что делает Kubernetes по-настоящему полезным, все еще отсутствует, например:

  • Планировщик подов
  • Аутентификация / авторизация
  • Несколько узлов
  • Сеть сервисов
  • Кластерный внутренний DNS
  • Контроллеры для учетных записей служб, развертываний, интеграции с облачными провайдерами и большинство других плюшек, которые приносит Kubernetes


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

Узнать подробнее о курсе на бесплатном вебинаре.



Читать еще:


Подробнее..

Перевод Пять промахов при развертывании первого приложения на Kubernetes

23.09.2020 18:06:49 | Автор: admin
Fail by Aris-Dreamer

Многие считают, что достаточно перенести приложение на Kubernetes (либо с помощью Helm, либо вручную) и будет счастье. Но не всё так просто.

Команда Mail.ru Cloud Solutions перевела статью DevOps-инженера Джулиана Гинди. Он рассказывает, с какими подводными камнями его компания столкнулась в процессе миграции, чтобы вы не наступали на те же грабли.

Шаг первый: настройка запросов пода и лимитов


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

Запросы пода (pod requests) это основное значение, используемое планировщиком для оптимального размещения пода.

Из документации Kubernetes: на шаге фильтрации определяется набор узлов, где можно запланировать под. Например, фильтр PodFitsResources проверяет, достаточно ли на узле ресурсов для удовлетворения конкретных запросов пода на ресурсы.

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

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

Лимиты пода (pod limits) это более четкое ограничение для пода. Оно представляет собой максимальный объем ресурсов, который кластер выделит контейнеру.

Опять же, из официальной документации: если для контейнера установлен лимит памяти 4 ГиБ, то kubelet (и среда выполнения контейнера) введет его принудительно. Среда выполнения не позволяет контейнеру использовать больше заданного лимита ресурсов. Например, когда процесс в контейнере пытается использовать больше допустимого объема памяти, ядро системы завершает этот процесс с ошибкой out of memory (OOM).

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

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

К сожалению, я не могу дать конкретные указания, какие значения устанавливать, но мы сами придерживаемся следующих правил:

  1. Используя инструмент нагрузочного тестирования, моделируем базовый уровень трафика и наблюдаем за использованием ресурсов пода (памяти и процессора).
  2. Устанавливаем запросы пода на произвольно низкое значение (с ограничением ресурсов примерно в 5 раз больше значения запросов) и наблюдаем. Когда запросы на слишком низком уровне, процесс не может начаться, что часто вызывает загадочные ошибки времени выполнения Go.

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

Представьте ситуацию, когда у вас легковесный веб-сервер с очень высоким ограничением ресурсов, например 4 ГБ памяти. Вероятно, этот процесс придется масштабировать горизонтально и каждый новый модуль придется планировать на узле с доступным объемом памяти не менее 4 ГБ. Если такого узла не существует, кластер должен ввести новый узел для обработки этого пода, что может занять некоторое время. Важно добиться минимальной разницы между запросами ресурсов и лимитами, чтобы обеспечить быстрое и плавное масштабирование.

Шаг второй: настройка тестов Liveness и Readiness


Это еще одна тонкая тема, которая часто обсуждается в сообществе Kubernetes. Важно хорошо разбираться в тестах жизнеспособности (Liveness) и готовности (Readiness), поскольку они обеспечивают механизм устойчивой работы программного обеспечения и минимизируют время простоя. Однако они могут нанести серьезный удар по производительности вашего приложения, если не настроены правильно. Ниже приводится краткое изложение, что из себя представляют обе пробы.

Liveness показывает, работает ли контейнер. Если она выходит из строя, kubelet убивает контейнер, и для него включается политика перезапуска. Если контейнер не оснащен Liveness-пробой, то состоянием по умолчанию будет успех так говорится в документации Kubernetes.

Пробы Liveness должны быть дешевыми, то есть не потреблять много ресурсов, потому что они запускаются часто и должны информировать Kubernetes, что приложение запущено.

Если вы установите параметр для запуска каждую секунду, то это добавит 1 запрос в секунду, так что примите во внимание, что для обработки этого трафика понадобятся дополнительные ресурсы.

У нас в компании тесты Liveness проверяют основные компоненты приложения, даже если данные (например, из удаленной базы данных или кэша) не полностью доступны.

Мы настроили в приложениях конечную точку работоспособности, которая просто возвращает код ответа 200. Это показатель того, что процесс запущен и способен обрабатывать запросы (но еще не трафик).

Проба Readiness указывает, готов ли контейнер к обслуживанию запросов. Если проба готовности выходит из строя, контроллер конечных точек удаляет IP-адрес пода из конечных точек всех служб, соответствующих поду. Это также говорится в документации Kubernetes.

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

В сообществе ведется много споров, следует ли обращаться непосредственно к базе данных. Учитывая накладные расходы (проверки выполняются часто, но их можно регулировать), мы решили, что для некоторых приложений готовность обслуживать трафик засчитывается только после проверки того, что из базы данных возвращаются записи. Хорошо продуманные пробы готовности обеспечили более высокий уровень доступности и устранили простои во время развертывания.

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

SELECT small_item FROM table LIMIT 1

Вот пример, как мы настраиваем эти два значения в Kubernetes:

livenessProbe:  httpGet:      path: /api/liveness       port: http readinessProbe:   httpGet:       path: /api/readiness       port: http  periodSeconds: 2

Можно добавить некоторые дополнительные параметры конфигурации:

  • initialDelaySeconds сколько секунд пройдет между запуском контейнера и началом запуска проб.
  • periodSeconds интервал ожидания между запусками проб.
  • timeoutSeconds количество секунд, по истечении которых под считается аварийным. Обычный тайм-аут.
  • failureThreshold количество отказов тестов, прежде чем в под будет отправлен сигнал перезапуска.
  • successThreshold количество успешных проб, прежде чем под переходит в состояние готовности (после сбоя, когда под запускается или восстанавливается).

Шаг третий: настройка дефолтных сетевых политик пода


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

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

Например, ниже приведена простая политика, которая запрещает весь входящий трафик для конкретного пространства имен:

---apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:   name: default-deny-ingressspec:   podSelector: {}   policyTypes:     - Ingress

Визуализация этой конфигурации:


(http://personeltest.ru/aways/miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Более подробно здесь.

Шаг четвертый: нестандартное поведение с помощью хуков и init-контейнеров


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

Особые трудности возникли с Nginx. Мы заметили, что при последовательном развертывании этих подов активные соединения прерывались до успешного завершения.

После обширных изысканий в интернете выяснилось, что Kubernetes не ждет, пока соединения Nginx исчерпают себя, прежде чем завершить работу пода. С помощью pre-stop хука мы внедрили такую функциональность и полностью избавились от даунтайма:

lifecycle:  preStop:   exec:     command: ["/usr/local/bin/nginx-killer.sh"]

А вот nginx-killer.sh:

#!/bin/bashsleep 3PID=$(cat /run/nginx.pid)nginx -s quitwhile [ -d /proc/$PID ]; do   echo "Waiting while shutting down nginx..."   sleep 10done

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

Другой распространенной схемой является доступ к секретам в init-контейнере, который предоставляет эти учетные данные главному модулю, что предотвращает несанкционированный доступ к секретам из самого основного модуля приложения.

Как обычно, цитата из документации: init-контейнеры безопасно запускают пользовательский код или утилиты, которые иначе снизят безопасность образа контейнера приложения. Храня отдельно ненужные инструменты, вы ограничиваете поверхность атаки образа контейнера приложения.

Шаг пятый: настройка ядра


Напоследок расскажем о более продвинутой технике.

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

Однако Kubernetes позволяет запустить привилегированный контейнер, который изменяет параметры ядра только для конкретного пода. Вот что мы использовали для изменения максимального количества открытых соединений:

initContainers:  - name: sysctl     image: alpine:3.10     securityContext:         privileged: true      command: ['sh', '-c', "sysctl -w net.core.somaxconn=32768"]

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

В заключение


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

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

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

Всегда задавайте себе такие вопросы:

  1. Сколько ресурсов потребляют приложения и как изменится этот объем?
  2. Каковы реальные требования к масштабированию? Сколько трафика в среднем будет обрабатывать приложение? А как насчет пикового трафика?
  3. Как часто сервису потребуется горизонтальное масштабирование? Как быстро нужно вводить в строй новые поды, чтобы принимать трафик?
  4. Насколько корректно завершается работа подов? Нужно ли это вообще? Можно ли добиться развертывания без даунтайма?
  5. Как минимизировать риски для безопасности и ограничить ущерб от любых скомпрометированных подов? Есть ли у каких-то сервисов разрешения или доступы, которые им не требуются?

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

К счастью, Kubernetes предоставляет необходимые настройки для достижения всех технических целей. Используя комбинацию запросов ресурсов и лимитов, проб Liveness и Readiness, init-контейнеров, сетевых политик и нестандартной настройки ядра, вы можете добиться высокой производительности наряду с отказоустойчивостью и быстрой масштабируемостью.

Что еще почитать:

  1. Лучшие практики и рекомендации для запуска контейнеров и Kubernetes в производственных средах.
  2. 90+ полезных инструментов для Kubernetes: развертывание, управление, мониторинг, безопасность и не только.
  3. Наш канал Вокруг Kubernetes в Телеграме.
Подробнее..

Recovery mode Мне повезло нужно обновить сертификаты k8s v1.12.3

03.03.2021 22:15:39 | Автор: admin

Неделю назад мне подкинули задачу - обновить сертификаты k8s кластере. С одной стороны задача казалась достаточно тривиальной, НО нетривиальности добавляло моя неуверенность с k8s: до этого момента я пользовался кубером как сервисом и больше чем посмотреть на поды, удалить их написать deployment по шаблону делать ничего не доводилось. Уверенности добавляло наличие инструкции, но как выяснилось она для версии v1.13 а у кластера для, которого требовалось реализовать эту задачу версия была 1.12.3. И тут началось

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

Дано k8s кластер:

  • 3 master ноды

  • 3 etcd ноды

  • 5 worker нод

kubectl get nodesNAME                    STATUS   ROLES    AGE    VERSIONproduct1-mvp-k8s-0001   Ready    master   464d   v1.12.3product1-mvp-k8s-0002   Ready    master   464d   v1.12.3product1-mvp-k8s-0003   Ready    master   464d   v1.12.3product1-mvp-k8s-0007   Ready    node     464d   v1.12.3product1-mvp-k8s-0008   Ready    node     464d   v1.12.3product1-mvp-k8s-0009   Ready    node     464d   v1.12.3product1-mvp-k8s-0010   Ready    node     464d   v1.12.3product1-mvp-k8s-0011   Ready    node     464d   v1.12.3

Срок действия сертификата

echo | openssl s_client -showcerts -connect product1-mvp-k8s-0001:6443 -servername api 2>/dev/null | openssl x509 -noout -enddatenotAfter=Mar  4 00:39:56 2021 GMT

Поехали:

  • на всех MASTER нодах бэкапируем /etc/kubernetes

sudo mkdir backup; sudo cp -R /etc/kubernetes backup/ ; sudo tar -cvzf backup/pki_backup_`hostname`-`date +%Y%m%d`.tar.gz backup/kubernetes/
  • Смотрим в структуру /etc/Kubernetes она будет примерно такой

ls -ltotal 80-rw------- 1 root root 5440 Mar  3 13:21 admin.confdrwxr-xr-x 2 root root 4096 Aug 17  2020 audit-policy-rw-r--r-- 1 root root  368 Mar  4  2020 calico-config.yml-rw-r--r-- 1 root root  270 Mar  4  2020 calico-crb.yml-rw-r--r-- 1 root root  341 Mar  4  2020 calico-cr.yml-rw-r--r-- 1 root root  147 Mar  4  2020 calico-node-sa.yml-rw-r--r-- 1 root root 6363 Mar  4  2020 calico-node.yml-rw------- 1 root root 5472 Mar  3 13:21 controller-manager.conf-rw-r--r-- 1 root root 3041 Aug 14  2020 kubeadm-config.v1alpha3.yaml-rw------- 1 root root 5548 Mar  3 13:21 kubelet.conf-rw-r--r-- 1 root root 1751 Mar  4  2020 kubelet.envdrwxr-xr-x 2 kube root 4096 Aug 14  2020 manifestslrwxrwxrwx 1 root root   28 Mar  4  2020 node-kubeconfig.yaml -> /etc/kubernetes/kubelet.conf-rw------- 1 root root 5420 Mar  3 13:21 scheduler.confdrwxr-xr-x 3 kube root 4096 Mar  3 10:20 ssl

у меня все ключи в ssl, а не в pki , который будет нужен kubeadm , то он должен появиться, в своем случае я сделаю на него symlink

ln -s /etc/kubernetes/ssl /etc/kubernetes/pki
  • отыскиваем файл с конфигурацией кластера, в моем случае это был

    kubeadm-config.v1alpha3.yaml

если такового вдруг нет то его возможно сгенерировать

kubectl get cm kubeadm-config -n kube-system -o yaml > /etc/kubernetes/kubeadm-config.yaml
  • Начинаем перегенерацию сертификатов

kubeadm alpha phase certs apiserver  --config /etc/kubernetes/kubeadm-config.v1alpha3.yaml[certificates] Using the existing apiserver certificate and key.kubeadm alpha phase certs apiserver-kubelet-clientI0303 13:12:24.543254   40613 version.go:236] remote version is much newer: v1.20.4; falling back to: stable-1.12[certificates] Using the existing apiserver-kubelet-client certificate and key.kubeadm alpha phase certs front-proxy-clientI0303 13:12:35.660672   40989 version.go:236] remote version is much newer: v1.20.4; falling back to: stable-1.12[certificates] Using the existing front-proxy-client certificate and key.kubeadm alpha phase certs  etcd-server --config /etc/kubernetes/kubeadm-config.v1alpha3.yaml[certificates] Generated etcd/server certificate and key.[certificates] etcd/server serving cert is signed for DNS names [prod-uct1-mvp-k8s-0001 localhost] and IPs [127.0.0.1 ::1]kubeadm alpha phase certs  etcd-server --config /etc/kubernetes/kubeadm-config.v1alpha3.yaml[certificates] Using the existing etcd/server certificate and key.kubeadm alpha phase certs  etcd-healthcheck-client --config /etc/kubernetes/kubeadm-config.v1alpha3.yaml[certificates] Generated etcd/healthcheck-client certificate and key.kubeadm alpha phase certs  etcd-peer --config /etc/kubernetes/kubeadm-config.v1alpha3.yaml[certificates] Generated etcd/peer certificate and key.[certificates] etcd/peer serving cert is signed for DNS names [product1-mvp-k8s-0001 localhost] and IPs [192.168.4.201 127.0.0.1 ::1]
  • проверяем выпущенные сертификаты на актуальность

find /etc/kubernetes/pki/ -name '*.crt' -exec openssl x509 -text -noout -in {} \; | grep -A2 Validity        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  2 10:29:44 2030 GMT--        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  3 10:07:29 2022 GMT--        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  3 10:07:52 2022 GMT--        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  3 10:06:48 2022 GMT--        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  2 10:29:44 2030 GMT--        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  2 19:39:56 2022 GMT--        Validity            Not Before: Mar  4 10:29:43 2020 GMT            Not After : Mar  2 10:29:43 2030 GMT--        Validity            Not Before: Mar  4 10:29:43 2020 GMT            Not After : Mar  2 19:40:13 2022 GMT--        Validity            Not Before: Mar  4 10:29:44 2020 GMT            Not After : Mar  2 19:36:38 2022 GMT
  • В процессе обновления сертификатов буду выпущены заново файлы admin.conf, controller-manager.conf, kubelet.conf, scheduler.conf а существующие переносим в подпапку tmpи генерим новые файлы

kubeadm alpha phase kubeconfig all  --config /etc/kubernetes/kubeadm-config.v1alpha3.yaml [kubeconfig] Using existing up-to-date KubeConfig file: "/etc/kubernetes/admin.conf"[kubeconfig] Using existing up-to-date KubeConfig file: "/etc/kubernetes/kubelet.conf"[kubeconfig] Using existing up-to-date KubeConfig file: "/etc/kubernetes/controller-manager.conf"[kubeconfig] Using existing up-to-date KubeConfig file: "/etc/kubernetes/scheduler.conf"
  • перезапускаем все контейнеры и kubelet мастер ноды и проверяем что сервис kubelet завершил перезапуск

sudo systemctl stop kubelet; sudo docker stop $(docker ps -aq); sudo docker rm $(docker ps -aq); sudo systemctl start kubeletsystemctl status kubelet -l kubelet.service - Kubernetes Kubelet Server   Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)   Active: active (running) since Wed 2021-03-03 14:00:22 MSK; 10s ago     Docs: https://github.com/GoogleCloudPlatform/kubernetes  Process: 52998 ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volume-plugins (code=exited, status=0/SUCCESS) Main PID: 53001 (kubelet)   Memory: 51.2M   CGroup: /system.slice/kubelet.service
  • проверяем что master нода вернулась нормально в кластер и что доступна конфигурация namespace

kubectl get nodeskubectl get nsNAME STATUS AGEdefault Active 464dproduct1-mvp Active 318dinfra-logging Active 315dinfra-nginx-ingress Active 386dkube-public Active 464dkube-system Active 464dpg Active 318d
  • проверяем что сертификат обновился

notAfter=Mar 3 07:40:43 2022 GMT

Обновление сертификатов на master ноде 1 успешно завершено и повторяем туже процедуру на оставшихся 2-х.


Далее обновляем worker ноды:

  • удаляем или переименовываем kubelet.conf, необходимо для того чтобы при перезапуске подхватился файл bootstrap-kubelet.conf

cd /etc/kubernetes/mv kubelet.conf kubelet.conf_old
  • вносим изменения в файл bootstrap-kubelet.conf если его нет, то создаем по шаблону внизу

apiVersion: v1clusters:- cluster: certificate-authority-data: | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01ETX server: https://192.168.4.201:6443 name: product1contexts:- context: cluster: product1 user: tls-bootstrap-token-user name: tls-bootstrap-token-user@product1current-context: tls-bootstrap-token-user@product1kind: Configpreferences: {}users:- name: tls-bootstrap-token-user user: token: fgz9qz.lujw0bwsdfhdsfjhgds

где мы должны заменить

- certificate-authority-data корневой сертификат центра сертификации PKI CA мастера, берем например из файла /etc/kubernetes/kubelet.conf на master ноде

- server: https://192.168.4.201:6443 - ip api сервера master ноды, или же виртуальный balance ip

token: fgz9qz.lujw0bwsdfhdsfjhgds - токен, который генерим на master ноде

kubeadm token create

  • перезапускаем kubelet и проверяем результат с master ноды, work нода должна ,быть доступна ready в ресурсе кластера

systemctl restart kubeletsystemctl status kubelet -l kubelet.service - Kubernetes Kubelet Server Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2021-03-03 14:06:33 MSK; 11s ago Docs: https://github.com/GoogleCloudPlatform/kubernetes Process: 54615 ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volume-plugins (code=exited, status=0/SUCCESS)Main PID: 54621 (kubelet) Memory: 52.1M CGroup: /system.slice/kubelet.service
  • проверить, что сертификат обновлен посмотреть на обновление сертификатов в папке

ls -las /var/lib/kubelet/pki/total 244 -rw-------. 1 root root 1135 Mar 3 14:06 kubelet-client-2021-03-03-14-06-34.pem0 lrwxrwxrwx. 1 root root 59 Mar 3 14:06 kubelet-client-current.pem -> /var/lib/kubelet/pki/kubelet-client-2021-03-03-14-06-34.pem4 -rw-r--r--. 1 root root 2267 Mar 2 10:40 kubelet.crt4 -rw-------. 1 root root 1679 Mar 2 10:40 kubelet.key

Повторяем подобную процедуру на всех оставшихся work нодах.

Все мы обновили сертификаты на k8s кластере v1.12.3

Подробнее..
Категории: Kubernetes , Kubectl , Kubelet , Kubeadm , Cert

Перевод Как увеличить скорость реакции Kubernetes на отказ узлов кластера?

06.06.2021 14:21:06 | Автор: admin

Kubernetes спроектирован так, чтобы быть надежным и устойчивым к сбоям, а также иметь возможность автоматически восстанавливаться. И он отлично справляется со всем этим! Однако рабочие узлы могут по разным причинам терять подключение к кластеру или выходить из строя. В этих случаях необходимо, чтобы Kubernetes быстро среагировал на инцидент.

Когда узел выходит из строя, pods сломанного узла все еще работают в течение некоторого времени. При этом они продолжают получать запросы, и эти запросы фейлятся. Скорее всего, совсем не то поведение, которое вы ожидали от Kubernetes, верно?

Чтобы разобраться, как Kubernetes реагирует на выход узла из строя, сначала рассмотрим взаимодействие между Kubelet и Controller Manager:

  1. Kubelet периодически уведомляет kube-apiserver о своём статусе с интервалом, заданным в параметре --node-status-update-frequency. Значение по умолчанию 10 секунд.

  2. Controller manager проверяет статус Kubelet каждые -node-monitor-period. Значение по умолчанию 5 секунд.

  3. Если от Kubelet получена информация в пределах --node-monitor-grace-period, Controller manager считает Kubelet исправным. Значение по умолчанию 40 секунд.

В случае отказа узла кластера происходит следующий алгоритм:

  1. Kubelet отправляет свой статус kube-apiserver, используя - node-status-update-frequency = 10 сек.

  2. Узел выходит из строя.

  3. Controller manager будет пытаться проверять статус узла, сообщаемый Kubelet, каждые --node-monitor-period = 5 сек.

  4. Controller manager увидит, что узел не отвечает, и даст ему тайм-аут --node-monitor-grace-period в 40 сек. Если за это время Controller manager не сочтет узел исправным, он установит статус NotReady.

  5. Kube Proxy удалит endpoints, указывающие на pods внутри этого узла из всех сервисов, поэтому pods сбойного узла больше не будут доступны.

В этом сценарии будет возможны ошибки при обращении в pods, работающим на этом узле, потому что модули будут продолжать получать трафик до тех пор, пока узел не будет считаться неработающим (NotReady) через 45 сек.

Есть множество параметров для настройки в Kubelet и Controller Manager.

Быстрое обновление и быстрая реакция

Чтобы увеличить скорость реакции Kubernetes на отказ узлов кластера, вы можете изменить эти параметры:

-node-status-update-frequency установить значение 1 сек (по умолчанию 10 сек)

--node-monitor-period установить значение 1 сек (по умолчанию 5 сек )

--node-monitor-grace-period установить значение 4 сек (по умолчанию 40 сек)

Протестируем изменения

Чтобы проверить изменения в тестовой среде, мы можем создать кластер Kubernetes с помощью Kind или любого другого инструмента. Мы создали конфигурационный файл для Kind Cluster с параметрами, указанными в предыдущем разделе, чтобы протестировать поведение кластера.

kind: ClusterapiVersion: kind.x-k8s.io/v1alpha4kubeadmConfigPatches:- |  apiVersion: kubelet.config.k8s.io/v1beta1  kind: KubeletConfiguration  nodeStatusUpdateFrequency: 1snodes:- role: control-plane  kubeadmConfigPatches:  - |    kind: ClusterConfiguration    controllerManager:        extraArgs:          node-monitor-period: 1s          node-monitor-grace-period: 4s- role: worker

Затем мы устанавливаем deployment с двумя репликами Nginx, размещенными в control-plane и на worker. Также мы дополнительно создали на control-plane pod с Ubuntu, чтобы проверить доступность Nginx, когда worker станет недоступен.

#!/bin/bash# create a K8S cluster with Kindkind create cluster --config kind.yaml # create a Ubuntu pod in control-plane Nodekubectl run ubuntu --wait=true --image ubuntu --overrides='{"spec": { "nodeName": "kind-control-plane"}}' sleep 30d# untaint control-plane node in order to schedule pods on itkubectl taint node kind-control-plane node-role.kubernetes.io/master-# create Nginx deployment with 2 replicas, one on each nodekubectl create deploy ng --image nginxsleep 30kubectl scale deployment ng --replicas 2# expose Nginx deployment so that is reachable on port 80kubectl expose deploy ng --port 80  --type ClusterIP# install curl in Ubuntu podkubectl exec ubuntu -- bash -c "apt update && apt install -y curl"

Чтобы проверить доступность Nginx, мы обратились к сервису с помощью curl из pod с Ubuntu, размещенного в control-plane, а также наблюдали за endpoints, принадлежащими сервису Nginx из терминала.

# test Nginx service access from Ubuntu podkubectl exec ubuntu -- bash -c 'while true ; do echo "$(date +"%T.%3N") - Status: $(curl -s -o /dev/null -w "%{http_code}" -m 0.2 -i ng)" ; done'# show Nginx service endpointswhile true; do  gdate +"%T.%3N"; kubectl get endpoints ng -o json | jq '.subsets' | jq '.[] | .addresses' | jq '.[] | .nodeName'; echo "------";done

Наконец, чтобы смоделировать сбой узла, мы остановили контейнер Kind, в котором запущен рабочий узел. Мы также добавили отметки времени, чтобы узнать когда узел был отключен и когда узел был обнаружен как NotReady.

#!/bin/bash# kill Kind worker nodeecho "Worker down at $(gdate +"%T.%3N")"docker stop kind-worker > /dev/nullsleep 15# show when the node was detected to be downecho "Worker detected in down state by Control Plane at "kubectl get event --field-selector reason=NodeNotReady --sort-by='.lastTimestamp' -oyaml | grep time | tail -n1# start worker node againdocker start kind-worker > /dev/null

После запуска теста мы заметили, что узел отключился в 12:50:22, а Controller manager обнаружил, что он отключился в 12:50:26, что и следовало ожидать через 4 секунды.

Worker down at 12:50:22.285Worker detected in down state by Control Plane at      time: "12:50:26Z"

Аналогичный результат при тестировании с терминала. Служба начала возвращать сообщения об ошибках в 12:50:23, потому что трафик был направлен на отказавший узел. А в 12:50:26.744 Kube Proxy удалил endpoint, указывающую на отказавший узел, и доступность службы была полностью восстановлена.

...12:50:23.115 - Status: 20012:50:23.141 - Status: 20012:50:23.161 - Status: 20012:50:23.190 - Status: 00012:50:23.245 - Status: 20012:50:23.269 - Status: 20012:50:23.291 - Status: 00012:50:23.503 - Status: 20012:50:23.520 - Status: 00012:50:23.738 - Status: 00012:50:23.954 - Status: 00012:50:24.166 - Status: 00012:50:24.385 - Status: 20012:50:24.407 - Status: 00012:50:24.623 - Status: 00012:50:24.839 - Status: 00012:50:25.053 - Status: 00012:50:25.276 - Status: 20012:50:25.294 - Status: 00012:50:25.509 - Status: 20012:50:25.525 - Status: 20012:50:25.541 - Status: 20012:50:25.556 - Status: 20012:50:25.575 - Status: 00012:50:25.793 - Status: 20012:50:25.809 - Status: 20012:50:25.826 - Status: 20012:50:25.847 - Status: 20012:50:25.867 - Status: 20012:50:25.890 - Status: 00012:50:26.110 - Status: 00012:50:26.325 - Status: 00012:50:26.549 - Status: 00012:50:26.604 - Status: 20012:50:26.669 - Status: 00012:50:27.108 - Status: 20012:50:27.135 - Status: 20012:50:27.162 - Status: 20012:50:27.188 - Status: 200......------12:50:26.523"kind-control-plane""kind-worker"------12:50:26.618"kind-control-plane""kind-worker"------12:50:26.744"kind-control-plane"------12:50:26.878"kind-control-plane"------...

Заключение

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

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

Подробнее..

Категории

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

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru