Kubernetes: (1.17) Kubelet не будет повторно подключаться к Apiserver после сбоя сетевой карты (использование закрытого сетевого подключения)

Созданный на 28 янв. 2020  ·  123Комментарии  ·  Источник: kubernetes/kubernetes

Мы только что обновили наш производственный кластер до версии 1.17.2.

После обновления в субботу у нас был этот странный сбой: у Kubelet после сбоя связи сетевого адаптера (который восстанавливается вскоре после этого) будут разорваны все его соединения, и он не будет пытаться восстановить их, если не перезапустится вручную.

Вот хронология последнего случая:

01:31:16: Ядро распознает сбой в интерфейсе связи. Это продолжается какое-то время. В конце концов он выздоравливает.

Jan 28 01:31:16 baremetal044 kernel: bond-mngmt: link status definitely down for interface eno1, disabling it
...
Jan 28 01:31:37 baremetal044  systemd-networkd[1702]: bond-mngmt: Lost carrier
Jan 28 01:31:37 baremetal044  systemd-networkd[1702]: bond-mngmt: Gained carrier
Jan 28 01:31:37 baremetal044  systemd-networkd[1702]: bond-mngmt: Configured

Как и ожидалось, все часы закрыты. Сообщение для всех одинаково:

...
Jan 28 01:31:44 baremetal044 kubelet-wrapper[2039]: W0128 04:31:44.352736    2039 reflector.go:326] object-"namespace"/"default-token-fjzcz": watch of *v1.Secret ended with: very short watch: object-"namespace"/"default-token-fjzcz": Unexpected watch close - watch lasted less than a second and no items received
...

Итак, эти сообщения начинаются:

`Jan 28 01:31:44 baremetal44 kubelet-wrapper[2039]: E0128 04:31:44.361582 2039 desired_state_of_world_populator.go:320] Error processing volume "disco-arquivo" for pod "pod-bb8854ddb-xkwm9_namespace(8151bfdc-ec91-48d4-9170-383f5070933f)": error processing PVC namespace/disco-arquivo: failed to fetch PVC from API server: Get https://apiserver:443/api/v1/namespaces/namespace/persistentvolumeclaims/disco-arquivo: write tcp baremetal44.ip:42518->10.79.32.131:443: use of closed network connection`

Думаю, какое-то время это не должно быть проблемой. Но никогда не выздоравливает. Наше событие произошло в 01:31, и пришлось вручную перезапустить Kubelet около 9 часов, чтобы все нормализовалось.

# journalctl --since '2020-01-28 01:31'   | fgrep 'use of closed' | cut -f3 -d' ' | cut -f1 -d1 -d':' | sort | uniq -dc
   9757 01
  20663 02
  20622 03
  20651 04
  20664 05
  20666 06
  20664 07
  20661 08
  16655 09
      3 10

Apiservers были запущены и работали, все остальные узлы были запущены и работали, все остальное было довольно гладко. Этот был единственным (сегодня), затронутым этой проблемой.

Есть ли способ смягчить последствия такого рода событий?

Было бы это ошибкой?

kinsupport siapi-machinery sinode

Самый полезный комментарий

Я исправил это, запустив этот сценарий bash каждые 5 минут:

#!/bin/bash
output=$(journalctl -u kubelet -n 1 | grep "use of closed network connection")
if [[ $? != 0 ]]; then
  echo "Error not found in logs"
elif [[ $output ]]; then
  echo "Restart kubelet"
  systemctl restart kubelet
fi

Все 123 Комментарий

/ sig узел
/ sig api-machinery

Взглянув в код ошибки происходит здесь

Объяснение кода заключается в том, что он предполагает, что это, вероятно, EOF (IsProbableEOF), в то время как в этом случае это не так.

/ assign @caesarxuchao

@rikatz, не могли бы вы рассказать, как вы

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

Именно @caesarxuchao, так что это наш вопрос.

Я отследил ошибку, в основном просматривая ее через Код и пересекаясь с тем, что kubelet делал в то время (просматривая секреты), чтобы добраться до этой части.

Не продвинутый способ, кажется, что это точная точка кода ошибки.

Вопрос в том, что из-за того, что соединение закрыто, есть ли где-то отметка о том, что это EOF часов, вместо того, чтобы понимать, что это ошибка?

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

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

Я думаю, мы тоже это видим, но у нас нет облигаций, мы видим только эти сетевые сообщения о потере оператора связи для интерфейсов Calico cali* , и они являются локальными veth-устройствами.

Я тоже столкнулся с этим без каких-либо связей. Перезапуск узла решает проблему, но простой перезапуск службы Kubelet - нет (все вызовы API завершаются с ошибкой «Неавторизовано»).

Я тоже столкнулся с этим без каких-либо связей. Перезапуск узла решает проблему, но простой перезапуск службы Kubelet - нет (все вызовы API завершаются с ошибкой «Неавторизовано»).

Обновление: перезапуск Kubelet устранил проблему после того, как прошло достаточно времени (1 час?).

Я наблюдаю такое же поведение. Чистая установка Ubuntu 18.04.3 LTS. Кластер построен с помощью Rancher 2.3.4. В последнее время я наблюдал, как это происходит периодически, и простой перезапуск kubelet может исправить это для меня. Прошлой ночью все 3 моих рабочих узла показали такое же поведение. Я исправил 2, чтобы поднять мой кластер. Третий все еще в этом состоянии, пока я копаюсь.

мы наблюдаем ту же проблему в CentOS 7, кластер, недавно созданный с помощью ранчо (1.17.2). Мы используем переплетение. Все 3 рабочих узла показывают эту проблему. Перезапуск kubelet у нас не работает, мы должны перезапустить весь узел

/ sig узел
/ sig api-machinery

Взглянув в код ошибки происходит здесь

Объяснение кода заключается в том, что он предполагает, что это, вероятно, EOF (IsProbableEOF), в то время как в этом случае это не так.

Мы также наблюдаем ту же проблему. Из журнала мы обнаружили, что после возникновения проблемы все последующие запросы по-прежнему отправлялись через одно и то же соединение. Похоже, что хотя клиент повторно отправит запрос в apiserver, но базовая библиотека http2 по-прежнему поддерживает старое соединение, поэтому все последующие запросы по-прежнему отправляются через это соединение и получают ту же ошибку use of closed connection .

Возникает вопрос, почему http2 все еще поддерживает уже закрытое соединение? Может быть, соединение, которое он поддерживает, действительно живое, но некоторые промежуточные соединения неожиданно закрываются?

У меня очень часто возникает такая же проблема с кластером Raspberry Pi с k8s 1.17.3. Основываясь на некоторых старых проблемах, я установил ограничение HTTP-соединения сервера API kube равным 1000 "- --http2-max-streams-per-connection = 1000", это было нормально в течение более 2 недель, после чего он запускается снова сейчас.

Можно ли пересобрать kube-apiserver https://github.com/kubernetes/apiserver/blob/b214a49983bcd70ced138bd2717f78c0cff351b2/pkg/server/secure_serving.go#L50
установка s.DisableHTTP2 на true по умолчанию?
Есть ли файл докеров для официального образа ( k8s.gcr.io/kube-apiserver:v1.17.3 )?

то же самое здесь. (ubuntu 18.04, kubernetes 1.17.3)

Мы также наблюдали это в двух наших кластерах. Не совсем уверен в основной причине, но, по крайней мере, мы смогли увидеть, что это произошло в кластере с очень большим количеством наблюдений. Я не смог воспроизвести, форсировав большое количество часов на кубелет (запускал модули с 300 секретами на модуль, что также привело к 300 часам на модуль в метриках Prometheus). Также установка очень низких значений http2-max-streams-per-connection не вызывала проблемы, но, по крайней мере, я смог наблюдать некоторое неожиданное поведение планировщика и диспетчера контроллера (возможно, это была просто перегрузка после бесконечных циклов повторного просмотра или что-то в этом роде, хотя).

В качестве обходного пути все мои узлы перезагружаются каждую ночь через локальный cronjob. Теперь, по прошествии 10 дней назад, я могу сказать, что это работает для меня, у меня больше нет «использования закрытого сетевого соединения» на моих узлах.

@sbiermann
Спасибо за публикацию. Какой временной интервал вы используете для cronjob?

24 часа

Я также могу подтвердить эту проблему, мы еще не на 1.17.3, в настоящее время работает Ubuntu 19.10:

Linux <STRIPPED>-kube-node02 5.3.0-29-generic #31-Ubuntu SMP Fri Jan 17 17:27:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

NAME                  STATUS   ROLES    AGE   VERSION       INTERNAL-IP   EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION     CONTAINER-RUNTIME
STRIPPED-kube-node02   Ready    <none>   43d   v1.16.6   10.6.0.12     <none>        Ubuntu 19.10   5.3.0-29-generic   docker://19.3.3

Я также могу подтвердить это на Kubernetes 1.17.4, развернутом через Rancher 2.3.5 на узлах RancherOS 1.5.5. Мне кажется, что перезапуск kubelet работает, мне не нужно перезапускать весь узел.

Основная причина для меня, похоже, заключается в том, что оперативная память приближается к исчерпанию, а kswapd0 из-за этого достигает 100% использования ЦП, поскольку я забыл установить подкачку на 0 для моих узлов Kubernetes. После установки параметра swappiness на 0 и добавления некоторого количества оперативной памяти на машины проблема еще не возникала для меня.

Если основная проблема заключалась в «http2 с использованием мертвых соединений», то перезапуск kubelet должен решить проблему. https://github.com/kubernetes/kubernetes/pull/48670 предложил уменьшить TCP_USER_TIMEOUT, чтобы уменьшить проблему. Я открыл https://github.com/golang/net/pull/55, чтобы добавить проверку работоспособности клиентского соединения в библиотеку http2, но для этого потребуется больше времени.

Если перезапуск kubelet не решил проблему, возможно, это другая основная причина.

У меня такая же проблема с v1.17.2 при перезапуске сети, но только на одном из узлов эта проблема (в моем кластере пять узлов), я не могу ее воспроизвести. Перезапуск кубелет решил эту проблему.

Как я могу избежать этой проблемы? Обновить последнюю версию или есть другой способ исправить?

Я исправил это, запустив этот сценарий bash каждые 5 минут:

#!/bin/bash
output=$(journalctl -u kubelet -n 1 | grep "use of closed network connection")
if [[ $? != 0 ]]; then
  echo "Error not found in logs"
elif [[ $output ]]; then
  echo "Restart kubelet"
  systemctl restart kubelet
fi

Я создал патч без перезапуска kubelet и, похоже, проблема решена.
крайний срок патч

diff --git a/staging/src/k8s.io/client-go/transport/cache.go b/staging/src/k8s.io/client-go/transport/cache.go
index 7c40848c79f..bd61b39551a 100644
--- a/staging/src/k8s.io/client-go/transport/cache.go
+++ b/staging/src/k8s.io/client-go/transport/cache.go
@@ -38,6 +38,8 @@ const idleConnsPerHost = 25

 var tlsCache = &tlsTransportCache{transports: make(map[tlsCacheKey]*http.Transport)}

+type dialFunc func(network, addr string) (net.Conn, error)
+
 type tlsCacheKey struct {
        insecure   bool
        caData     string
@@ -92,7 +94,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
                TLSHandshakeTimeout: 10 * time.Second,
                TLSClientConfig:     tlsConfig,
                MaxIdleConnsPerHost: idleConnsPerHost,
-               Dial:                dial,
+               Dial:                setReadDeadlineAfterDial(dial, 30*time.Second),
        })
        return c.transports[key], nil
 }
@@ -111,3 +113,18 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) {
                serverName: c.TLS.ServerName,
        }, nil
 }
+
+func setReadDeadlineAfterDial(dialer dialFunc, timeout time.Duration) dialFunc {
+       return func(network, addr string) (net.Conn, error) {
+               c, err := dialer(network, addr)
+               if err != nil {
+                       return nil, err
+               }
+
+               if err := c.SetReadDeadline(time.Now().Add(timeout)); err != nil {
+                       return nil, err
+               }
+
+               return c, nil
+       }
+}

@mYmNeo Не могли бы вы объяснить, как пересобрать client-go?

@mYmNeo Не могли бы вы объяснить, как пересобрать client-go?

@ ik9999 Примените этот патч, затем пересоберите kubelet и замените двоичный файл

@mYmNeo Как я могу воспроизвести эту проблему и протестировать ее?

Я исправил это, запустив этот сценарий bash каждые 5 минут

@ ik9999 Спасибо, работает.

cc @liggitt

означает ли установка SetReadDeadline все часы закрываются каждые 30 секунд?

означает ли установка SetReadDeadline все часы закрываются каждые 30 секунд?

да. Это уродливый способ решить эту проблему (принудительно закрыть соединение).

Еще один случай:

Мы также наблюдаем это в кластерах Kube 1.16.8. Перезагрузка виртуальной машины может использоваться для возврата узла в хорошее состояние (я подозреваю, что перезапуск kubelet тоже сработал бы).

Наш setup kubelet общается с локальным экземпляром haproxy через localhost, который действует как балансировщик нагрузки tcp для нескольких основных экземпляров серверной части. Мы собираемся выяснить, добавляется ли

option clitcpka    # enables keep-alive only on client side
option srvtcpka    # enables keep-alive only on server side

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

Apr  8 00:04:25 kube-bnkjtdvd03sqjar31uhg-cgliksp01-cgliksp-00001442 kubelet.service[6175]: E0408 00:04:25.472682    6175 reflector.go:123] object-"ibm-observe"/"sysdig-agent": Failed to list *v1.ConfigMap: Get https://172.20.0.1:2040/api/v1/namespaces/ibm-observe/configmaps?fieldSelector=metadata.name%3Dsysdig-agent&limit=500&resourceVersion=0: write tcp 172.20.0.1:22501->172.20.0.1:2040: use of closed network connection
Apr  8 00:04:25 kube-bnkjtdvd03sqjar31uhg-cgliksp01-cgliksp-00001442 kubelet.service[6175]: E0408 00:04:25.472886    6175 reflector.go:123] object-"default"/"default-token-gvbk5": Failed to list *v1.Secret: Get https://172.20.0.1:2040/api/v1/namespaces/default/secrets?fieldSelector=metadata.name%3Ddefault-token-gvbk5&limit=500&resourceVersion=0: write tcp 172.20.0.1:22501->172.20.0.1:2040: use of closed network connection

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

Интересно, есть ли параметр конфигурации для установки абсолютной верхней границы времени просмотра? Я нашел --streaming-idle-connection-timeout, но ничего особенного для часов.

Мы наблюдаем это в kube 1.17.4 после того, как сервер API вышел из строя из-за ошибки etcd: причина не указана.

Привет, народ. Я перекомпилировал двоичный файл kubernetes с golang 1.14. Похоже, проблема исчезла

@mYmNeo golang 1.14 + kubernetes v1.17?

@mYmNeo golang 1.14 + kubernetes v1.17?

@pytimer Мы используем 1.16.6 без изменения кода, просто перекомпилируя. Я думаю, что первопричина может быть в голанге.

Привет! Возникла та же проблема, k8s 1.17.4, можем ли мы получить версию 1.17.5, перекомпилированную с go 1.14, если это решит проблему?

К сожалению, обновление до go1.14 требует обновления нескольких ключевых компонентов, поэтому вряд ли вернется к Kube 1.17. Вы можете отслеживать проблемы и прогресс на https://github.com/kubernetes/kubernetes/pull/88638.

Полезно знать, спасибо

@callicles было ли подтверждено, что перекомпиляция с помощью go 1.14 решила проблему?

Я вижу идентичную проблему в 1.16.8 - время от времени (иногда раз в пару дней, иногда каждые пару недель) узел становится NotReady, по причине того, что Kubelet перестал публиковать статус узла и «использование закрытого сетевого подключения» заполнение журналов

у go могут возникнуть проблемы с обновлением h2.
golang.org/x/net/http2/transport.go

    upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
        addr := authorityAddr("https", authority)
        if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
            go c.Close()
            return erringRoundTripper{err}    <--- "use of closed network connection"  rised
        }

Привет, народ. Я перекомпилировал двоичный файл kubernetes с golang 1.14. Похоже, проблема исчезла

@mYmNeo вы когда-нибудь воспроизводили проблему после перекомпиляции с помощью go 1.14

Привет, народ. Я перекомпилировал двоичный файл kubernetes с golang 1.14. Похоже, проблема исчезла

@mYmNeo вы когда-нибудь воспроизводили проблему после перекомпиляции с помощью go 1.14

AFAIN, проблема больше не существует.

К сожалению, обновление до go1.14 требует обновления нескольких ключевых компонентов, поэтому вряд ли вернется к Kube 1.17. Вы можете отслеживать проблемы и прогресс в # 88638

Вы уже знаете, будет ли go1.14 обратно перенесен на 1.18?

Вы уже знаете, будет ли go1.14 обратно перенесен на 1.18?

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

@liggitt Хорошо,

Эта проблема возникает только после сбоя сетевой карты? Мы видим то же сообщение об ошибке в наших кластерах v1.16.8, но сбой сетевого адаптера не связан.

У нас был как минимум один экземпляр, в котором базовая виртуальная машина имела ошибку SCSI при подключении к SAN. Проблема SCSI разрешилась сама собой, но kubelet так и не удалось исправить.

Опция --goaway-chance была добавлена ​​в 1.18 (# 88567). Решит ли этот вариант эту проблему?

Нет. Это действует только в том случае, если кубелет действительно может связаться с сервером API и получить ответ.

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

Подскажите, пожалуйста, какой режим облигации вы используете? Я не могу воспроизвести это на моем кластере с связями с активным резервным копированием.

После обновления до Kubernetes 1.16 мы также начали видеть ошибку use of closed network connection и kubelet не подключается повторно к apiserver, в результате чего узлы застревают в NotReady. Нам не удалось воспроизвести проблему, отключив сетевые адаптеры (путем установки ссылок вниз / вверх), но мы заметили, что такое поведение наблюдается только в кластерах, которые были более сильно загружены.

Мы больше копали и обнаружили, что значение по умолчанию на стороне сервера умолчанию на стороне клиента - 1000 , поэтому я предполагаю, что как только kubelet получил ошибку от apiserver для достижения предела потока http2, он никогда не пытался переподключиться. После установки --http2-max-streams-per-connection=1000 мы не увидели проблемы с застреванием узлов в NotReady, как это было первоначально обнаружено во время тестирования. Это не решило проблему, когда kubelet не подключается повторно, но помогло нам смягчить проблему, которую мы наблюдали.

После обновления до Kubernetes 1.16 мы также начали видеть ошибку use of closed network connection и kubelet не подключается повторно к apiserver, в результате чего узлы застревают в NotReady. Нам не удалось воспроизвести проблему, отключив сетевые адаптеры (путем установки ссылок вниз / вверх), но мы заметили, что такое поведение наблюдается только в кластерах, которые были более сильно загружены.

Мы больше копали и обнаружили, что значение по умолчанию на стороне сервера умолчанию на стороне клиента - 1000 , поэтому я предполагаю, что как только kubelet получил ошибку от apiserver для достижения предела потока http2, он никогда не пытался переподключиться. После установки --http2-max-streams-per-connection=1000 мы не увидели проблемы с застреванием узлов в NotReady, как это было первоначально обнаружено во время тестирования. Это не решило проблему, когда kubelet не подключается повторно, но помогло нам смягчить проблему, которую мы наблюдали.

Привет, по умолчанию потоки https на стороне сервера - 1000 в kube-apiserver, это равно значению клиента.
https://github.com/kubernetes/kubernetes/blob/ae1103726f9aea1f9bbad1b215edfa47e0747dce/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go#L62

@warmchang Я думаю, это относится к apiextensions apiservers и образцу apiserver:
https://github.com/kubernetes/kubernetes/blob/ae1103726f9aea1f9bbad1b215edfa47e0747dce/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go#L62

Тест с curl test без установки --http2-max-streams-per-connection имеет это в наших журналах apiserver (с использованием v1.16):
I0603 10:18:08.038531 1 flags.go:33] FLAG: --http2-max-streams-per-connection="0"

И запрос curl показывает это в ответе:
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!

Когда я использую --http2-max-streams-per-connection=1000 запрос curl показывает
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!

@jmcmeek @treytabner , ты прав. Я неправильно прочитал код. : +1:

Используем kubernetes 1.17.6 и здесь. Похоже, что kubelet использует мертвое соединение http2.
Я заметил, что несовместимое значение по умолчанию MAX_CONCURRENT_STREAMS между kube-apiserver и kubelet.

Просто установите значение на стороне сервера на 1000. Сообщу позже.

Владелец ранчо / RKE

Добавить в определение кластера:

 kube-api:
      extra_args:
        http2-max-streams-per-connection: '1000'

Проверить на мастер-узле:

docker exec -it kubelet bash
apt update && apt-get install -y nghttp2
nghttp -nsv https://127.0.0.1:6443
#Look for SETTINGS_MAX_CONCURRENT_STREAMS

Установка MAX_CONCURRENT_STREAMS на 1000 на сервере API не влияет на эту проблему.
Я полагал, что это вызвано ошибкой в golang http2 Transport . См. Выше

Этой ночью снова возникла эта проблема.
Похоже, установка MAX_CONCURRENT_STREAMS не помогла☹️

Привет, народ. Думаю, наконец, я нашел эту проблему. У нас та же проблема, что и прошлой ночью. Но успешно восстановился модифицированным кубелетом.

Это не ошибка Kubernetes, это касается стандартного пакета net/http golang, который тоже использует client-go .
Я считаю, что в golang.org/x/net/http2/transport.go есть ошибка

Об этом уже доложили официальному лицу Голанга. Жду обсуждения.
https://github.com/golang/go/issues/39750

На данный момент я изменил код, чтобы по умолчанию был включен параметр http2: perform connection health check https://github.com/golang/net/commit/0ba52f642ac2f9371a88bfdde41f4b4e195a37c0 .
Это помогает решить эту проблему. Но немного заторможен.

логи kubelet v1.17.6 (соблюдаются с самомодифицируемым пакетом golang.org/x/net )

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

Обратите внимание, что performing http2 healthCheck - это сообщение журнала, которое я намеревался оставить там, чтобы доказать, что healthCheck func вызывается readIdleTimer

 23 июня, 03:14:45 vm10.company.com kubelet [22255]: E0623 03: 14: 45.912484 22255 kubelet_node_status.go: 402] Ошибка обновления статуса узла, повторная попытка: ошибка при получении узла "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": напишите tcp 16.155.199.4:39668->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:45 vm10.company.com kubelet [22255]: E0623 03: 14: 45.912604 22255 kubelet_node_status.go: 402] Ошибка обновления статуса узла, повторная попытка: ошибка при получении узла "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": напишите tcp 16.155.199.4:39668->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:45 vm10.company.com kubelet [22255]: E0623 03: 14: 45.912741 22255 kubelet_node_status.go: 402] Ошибка обновления статуса узла, повторная попытка: ошибка при получении узла "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": напишите tcp 16.155.199.4:39668->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:46 vm10.company.com kubelet [22255]: E0623 03: 14: 46.367046 22255 controller.go: 135] не удалось убедиться в наличии аренды узла, повторите попытку через 400 мс, ошибка: Get "https: // vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s ": напишите tcp 16.155.199.4:39668->16.155. 199.4: 8443: использование закрытого сетевого подключения
 23 июня, 03:14:48 vm10.company.com kubelet [22255]: E0623 03: 14: 47.737579 22255 controller.go: 135] не удалось убедиться в наличии аренды узла, повторите попытку через 800 мс, ошибка: Get "https: // vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s ": напишите tcp 16.155.199.4:39668->16.155. 199.4: 8443: использование закрытого сетевого подключения
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.113920 22255 отражатель.go: 153] k8s.io/kubernetes/pkg/kubelet/kubelet.go:458: Не удалось добавить в список * v1.Node: получите "https://vm10.company.com:8443/api/v1/nodes?fieldSelector=metadata.name%3Dvm10.company.com&limit=500&resourceVersion=0": напишите tcp 16.155.199.4:39668-> 16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 48.744770 22255 refctor.go: 153] объект- "kube-system" / "flannel-token-zvfwn": не удалось добавить в список * v1.Secret: получите "https://vm10.company.com:8443/api/v1/namespaces/kube-system/secrets?fieldSelector=metadata.name%3Dflannel-token-zvfwn&limit=500&resourceVersion=0": напишите tcp 16.155 .199.4: 39668-> 16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.599631 22255 refctor.go: 153] объект- "kube-system" / "coredns": не удалось перечислить * v1.ConfigMap: Получите "https://vm10.company.com:8443/api/v1/namespaces/kube-system/configmaps?fieldSelector=metadata.name%3Dcoredns&limit=500&resourceVersion=0": напишите tcp 16.155.199.4:39668->16.155. 199.4: 8443: использование закрытого сетевого подключения
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.599992 22255 controller.go: 135] не удалось убедиться в наличии аренды узла, повторите попытку через 1,6 с, ошибка: Get "https: / /vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s ": напишите tcp 16.155.199.4:39668->16.155 .199.4: 8443: использование закрытого сетевого соединения.
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.600182 22255 refctor.go: 153] k8s.io/kubernetes/pkg/kubelet/kubelet.go:449: Не удалось добавить в список * v1.Service: получите "https://vm10.company.com:8443/api/v1/services?limit=500&resourceVersion=0": напишите tcp 16.155.199.4:39668->16.155.199.4:8443: использование закрытой сети связь
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.600323 22255 refctor.go: 153] объект- "kube-system" / "kube-flannel-cfg": не удалось добавить в список * v1.ConfigMap: получите "https://vm10.company.com:8443/api/v1/namespaces/kube-system/configmaps?fieldSelector=metadata.name%3Dkube-flannel-cfg&limit=500&resourceVersion=0": напишите tcp 16.155 .199.4: 39668-> 16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.600463 22255 refctor.go: 153] объект- "core" / "registrypullsecret": не удалось перечислить * v1.Secret: Get " https://vm10.company.com:8443/api/v1/namespaces/core/secrets?fieldSelector=metadata.name%3Dregistrypullsecret&limit=500&resourceVersion=0 ": напишите tcp 16.155.199.4:39668->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:14:49 vm10.company.com kubelet [22255]: E0623 03: 14: 49.369097 22255 refctor.go: 153] объект- "kube-system" / "registrypullsecret": не удалось добавить в список * v1.Secret: Получите "https://vm10.company.com:8443/api/v1/namespaces/kube-system/secrets?fieldSelector=metadata.name%3Dregistrypullsecret&limit=500&resourceVersion=0": напишите tcp 16.155.199.4:39668->16.155. 199.4: 8443: использование закрытого сетевого подключения
 23 июня, 03:25:39 vm10.company.com kubelet [22255]: E0623 03: 25: 39.543880 22255 желаемое_state_of_world_populator.go: 320] Ошибка обработки тома «журнал-каталог-развертывания» для модуля «fluentd-h76lr_core» (e95c9200-3a0c) -4fea-bd7f-99ac1cc6ae7a) ": ошибка обработки ядра PVC / itom-vol-Claim: не удалось получить PVC с сервера API: получить" https://vm10.company.com:8443/api/v1/namespaces/core/ persistentvolumeclaims / itom-vol -claim ": прочтите tcp 16.155.199.4:41512->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:25:39 vm10.company.com kubelet [22255]: E0623 03: 25: 39.666303 22255 kubelet_node_status.go: 402] Ошибка обновления статуса узла, повторная попытка: не удалось исправить статус "{\" status \ ": {\ "$ setElementOrder / conditions \": [{\ "type \": \ "MemoryPressure \"}, {\ "type \": \ "DiskPressure \"}, {\ "type \": \ "PIDPressure \ "}, {\" тип \ ": \" Готов \ "}], \" условия \ ": [{\" lastHeartbeatTime \ ": \" 2020-06-22T19: 25: 29Z \ ", \" тип \ ": \" MemoryPressure \ "}, {\" lastHeartbeatTime \ ": \" 2020-06-22T19: 25: 29Z \ ", \" type \ ": \" DiskPressure \ "}, {\" lastHeartbeatTime \ ": \ "2020-06-22T19: 25: 29Z \", \ "type \": \ "PIDPressure \"}, {\ "lastHeartbeatTime \": \ "2020-06-22T19: 25: 29Z \", \ " введите \ ": \" Ready \ "}]}}" для узла "vm10.company.com": Патч "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com/ status? timeout = 10s ": читать tcp 16.155.199.4:41512->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:25:49 vm10.company.com kubelet [22255]: E0623 03: 25: 49.553078 22255 kubelet_node_status.go: 402] Ошибка обновления статуса узла, повторная попытка: ошибка при получении узла "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": прочтите tcp 16.155.199.4:41718->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:25:49 vm10.company.com kubelet [22255]: E0623 03: 25: 49.560723 22255 desire_state_of_world_populator.go: 320] Ошибка обработки тома "расположение журнала" для модуля fluentd-h76lr_core (e95c9200-3a0c-4fea -bd7f-99ac1cc6ae7a) ": ошибка обработки ядра PVC / itom-logging-vol: не удалось получить PVC с сервера API: получить" https://vm10.company.com:8443/api/v1/namespaces/core/persistentvolumeclaims/ itom-logging-vol ": читать tcp 16.155.199.4:41718->16.155.199.4:8443: использование закрытого сетевого подключения
 23 июня, 03:27:29 vm10.company.com kubelet [22255]: I0623 03: 27: 29.961600 22255 log.go: 181] выполнение http2 healthCheck
 23 июня, 03:31:32 vm10.company.com kubelet [22255]: I0623 03: 31: 31.829860 22255 log.go: 181] выполнение http2 healthCheck
 23 июня, 03:31:44 vm10.company.com kubelet [22255]: I0623 03: 31: 44.570224 22255 log.go: 181] выполнение http2 healthCheck
 23 июня, 03:32:13 vm10.company.com kubelet [22255]: I0623 03: 32: 12.961728 22255 log.go: 181] выполнение http2 healthCheck
 23 июня, 03:33:16 vm10.company.com kubelet [22255]: I0623 03: 33: 15.441808 22255 log.go: 181] выполнение http2 healthCheck
 23 июня, 03:33:28 vm10.company.com kubelet [22255]: I0623 03: 33: 28.233121 22255 log.go: 181] выполнение http2 healthCheck

use of closed network connection сообщается, и kubelet возвращается в состояние готовности

У нас есть несколько новых потенциальных идей по этой проблеме в наших стеках. С некоторой уверенностью мы предполагаем редкие обрывы подключения на уровне сети / инфраструктуры из-за высокой нагрузки на номера подключений в определенных ситуациях, поэтому в нашем случае это не было переключением сетевых интерфейсов. Из-за этого у нас были особенно серьезные проблемы с федерацией Prometheus, поскольку они перешли на http2 на стороне клиента . Включение монитора работоспособности http2 путем установки http2.Transport.ReadIdleTimeout как реализовано с помощью golang/net#55 полностью решило для нас проблемы с федерацией.

Значения в настоящее время не отображаются, поскольку apimachinery/pkg/util/net/http.go создает экземпляр http.Transport и обновляет его до http2 внутренне, что не раскрывает параметр до тех пор, пока golang / net # 74 не будет объединен.

Существуют ли какие-либо другие обходные пути, кроме задания cron для перезапуска kubelet? У нас есть работа cron в течение недели, и это не помешало возникновению проблемы.

У меня такая же проблема в версии 1.17.3.

Я обнаружил, что версия k8s, использующая конкретную версию golang.org/x/net имеет проблемы, и этот пакет, похоже, исправлен.
https://go-review.googlesource.com/c/net/+/198040

Версия с этой проблемой (v1.16.5 ~ последний выпуск)
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9

Исправить версию (основная ветка)
golang.org/x/net v0.0.0-20200707034311-ab3426394381

Поможет ли обновление пакета golang.org/x/net решить эту проблему?

Планируется ли выпуск поддерживаемой версии k8s (v1,16, 1.17, v1,18 ..), чтобы исправить это?

Я обнаружил, что версия k8s, использующая конкретную версию golang.org/x/net имеет проблемы, и этот пакет, похоже, исправлен.
https://go-review.googlesource.com/c/net/+/198040

Упомянутое изменение только _ предлагает_ возможность включить монитор состояния HTTP2, но разработчики должны включить его (по умолчанию выключено). Кроме того, его нельзя установить на самом деле, но есть запрос на вытягивание, чтобы предоставить разработчикам доступ к монитору работоспособности .

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

-
Йенс Эрат \ Отпечаток

@JensErat спасибо за ответ.
Если да, может ли эта проблема возникать и в более старых версиях k8s (1.13, 1.15, ..)?

Я сменил дистрибутив узлов с RancherOS (ядро 4.14.138) на Ubuntu 18.04 (ядро 5.3.0) более месяца назад, с тех пор проблема не возникала.
Один из моих кластеров остался на RancherOS, эта проблема воспроизводилась уже 3 раза.

Не на 100% уверен, но, вероятно, имеет значение версия ядра.

Тяжело сказать. Мы определенно наблюдаем (d) проблему с 1.16 по 1.18, но до этого мы не сталкивались с редкими странными «зависаниями». Мы уже копались в таких проблемах как минимум год, но так и не смогли ничего сопоставить (единичные инциденты за несколько недель, и у нас есть какое-то четырехзначное количество запущенных кубелец). Хотя с тех пор, как мы установили 1.16, стало намного хуже, но в настоящее время мы больше склонны предполагать, что основные (также очень редкие и трудно отслеживаемые ...) проблемы с сетью возникают чаще. Мы запускаем Ubuntu 19.10 с ядром 5.3.0-46-generic, но это затронуто (так что вполне возможно, что у вас действительно есть более новый уровень исправлений). Можете ли вы подсказать, какую именно версию ядра / уровень исправления вы используете?

-
Йенс Эрат \ Отпечаток

Это 5.3.0-59-generic . Но у нас всего ~ 40 кублетов, так что это все равно может быть совпадением.

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

Я имею в виду, что немного далеко от темы, поскольку проблема вызвана сетевым сокетом, который очень близок к ядру. Обновление ядра может помочь или нет. (PS: мы используем centos 7 с ядром 3.10, это происходит почти каждый день до включения healthCheck)
Я потратил около 3 дней на чтение исходного кода net / http, насколько я видел, включение h2 transport healthCheck, чтобы помочь справиться с такой проблемой, и мы действительно избежали этой странной ситуации, сделав это.
@JensErat У вас есть конкретные доказательства того, что включение healthCheck поможет решить эту проблему?

@JensErat У вас есть конкретные доказательства того, что включение healthCheck поможет решить эту проблему?

Мы запускаем федерацию Prometheus для каждого из наших кластеров Kubernetes. Prometheus 2.19.0 представил http2 (они забывают упомянуть об этом в журнале изменений и хорошо скрывают его в теле сообщения фиксации, мне пришлось git bisect, развернуть и ждать несколько часов для каждого запуска ...), и мы наблюдали за дюжина инцидентов с застрявшей федерацией в день. Сначала я снова исправил поддержку http2 (и проблема исчезла), а затем установил тайм-аут чтения непосредственно в golang / net / x / http2. С тех пор у нас больше не было ни одного инцидента в федерации.

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

-
Йенс Эрат \ Отпечаток

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

Спасибо за ваш отзыв. Это очень приятное послание.
Хотя основная причина не очень ясна, по крайней мере, мы находим способ восстановиться после катастрофы. : D

У нас такая же проблема с k8s v1.14.3, и перезапуск kubelet может решить проблему.

Я знаю, что это глупо, но должно работать как временное решение:

Развернуть ямл

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kubelet-face-slapper
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: kubelet-face-slapper
  template:
    metadata:
      labels:
        app: kubelet-face-slapper
    spec:
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods    
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/controlplane
        operator: Equal
        value: "true"
      - effect: NoExecute
        key: node-role.kubernetes.io/etcd
        operator: Equal
        value: "true"
      containers:
      - command:
        - /bin/sh
        - -c
        - while true; do sleep 40; docker logs kubelet --since 1m 2>&1 | grep -q "use
          of closed network connection" && (docker restart kubelet ; echo "kubelet
          has been restarted due to connection error") || echo "kubelet connection
          is ok" ;done
        image: docker:stable
        name: kubelet-face-slapper
        volumeMounts:
        - mountPath: /var/run/docker.sock
          name: docker-sock
      volumes:
      - hostPath:
          path: /var/run/docker.sock
          type: File
        name: docker-sock


(Это специфично для владельцев ранчо, но может быть легко адаптировано к другим дистрибутивам с помощью привилегированного контейнера и journalctl / systemctl)

Количество времени для sleep и --since должно быть меньше pod-eviction-timeout кластера (по умолчанию 5 миллионов)

Кстати - docker pause nginx-proxy на рабочем узле ранчера заставляет kubelet выдавать такое же сообщение об ошибке.

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

У нас есть очень хорошие новости относительно решения проблемы с помощью новой функции проверки работоспособности golang http2: проблем больше нет. К настоящему моменту мы реализовали «исправление» (жестко запрограммированное значение в поставленном коде x/net ) в Prometheus, целиком Kubernetes и нескольких внутренних компонентах, соблюдая:

  • Федерация Прометея больше не выпускает
  • kubelet иногда по-прежнему сообщает об одном событии "использование закрытого соединения", но восстанавливается в течение нескольких секунд (мы установили окно проверки работоспособности http2 ~ 30 секунд)
  • иногда у нас были проблемы с часами kubectl - также исчезали при использовании исправленного kubectl
  • мы запускаем расширенный набор тестов E2E, чтобы регулярно проверять нашу интеграцию, и наблюдали спорадические тайм-ауты тестирования и нестабильность. Угадай, что? Ушел сейчас.

Кроме того, мы смогли получить новые сведения о том, как вызывать проблемы. Я могу с некоторой уверенностью подтвердить наблюдение @ vi7 относительно живой миграции (хотя мы могли бы отследить это), и, по крайней мере, с версией NSX, которую мы запускаем, также изменения балансировщика нагрузки могут вызвать такие проблемы (у нас есть билет с VMware для убедитесь, что они отправляют пакеты сброса в будущем). И, скорее всего, существует множество других причин, по которым разрываются промежуточные соединения, например, переполнение таблицы соединений.

Это очень раздражающая и довольно серьезная проблема для некоторых пользователей Kubernetes (я полагаю, это зависит от какой-то «ломкости» уровня / сети IaaS). Хотя ведутся голанговые дискуссии о предоставлении интерфейса для правильной установки значений - как вы думаете, есть ли шанс получить объединенный PR, устанавливающий эти значения посредством отражения (все же лучше, чем разветвление x / net, я думаю, что мы делаем прямо сейчас) ? Мы в порядке с предоставлением кода (и проверкой исправления мы не можем воспроизвести, но наблюдаем его достаточно часто, чтобы убедиться, что исправление работает).

cc @liggitt

долгосрочная проблема (примечание для себя)

@JensErat спасибо за ответ.
Если да, может ли эта проблема возникать и в более старых версиях k8s (1.13, 1.15, ..)?

Я могу подтвердить, что вижу проблему с Kubernetes v1.16.13
Мы не видели проблемы с Kubernetes v1.15.9

когда я перезагружаю кластер kubenetes v1.16.14 из резервной копии моментального снимка etcd. эта ошибка появляется в журнале kubelet.
спасибо @ ik9999 . Я перезапускаю кубелет, ошибки исчезают

[root@dev-k8s-master ~]# journalctl -u kubelet -n 1 | grep "use of closed network connection"
Aug 22 11:31:10 dev-k8s-master kubelet[95075]: E0822 11:31:10.565237   95075 reflector.go:123] k8s.io/client-go/informers/factory.go:134: Failed to list *v1beta1.CSIDriver: Get https://apiserver.cluster.local:6443/apis/storage.k8s.io/v1beta1/csidrivers?limit=500&resourceVersion=0: write tcp 192.168.160.243:58374->192.168.160.243:6443: use of closed network connection
[root@dev-k8s-master ~]# systemctl restart kubelet
[root@dev-k8s-master ssh]# journalctl -u kubelet -n 1 | grep "use of closed network connection"

Мы встретили ту же проблему на 1.17.3, перезапуск kubelet решит. Какое-либо стабильное решение для этого или когда это должно быть исправлено?

v1.18.6 то же

@ rxwang662001
Это вызвано проблемой вышестоящего golang. Следует быть уверенным в том, что это НЕ будет исправлено в версии 1.15.
Тем временем сообщество Kubernetes все еще пытается перейти на версию 1.14 LOL.

Обычно выпускаются каждые 6 месяцев. Если все будет работать хорошо, возможно, мы сможем увидеть, как эта проблема будет решена апстримом в следующем году, а может быть, еще через год, пока kubernetes не внесет исправление 🥇!
(Просто для шуток. Если вы действительно хотите, чтобы это было исправлено в вашем стеке прямо сейчас. Взломайте h2Transport, чтобы включить healthCheck, оказалось, что он работает.

Тем временем сообщество Kubernetes все еще пытается перейти на версию 1.14 LOL.

На самом деле, благодаря большой работе над sig-scaleability и sig-release для квалификации на предварительных версиях go1.15, Kubernetes 1.19 только что вышел на go1.15. Похоже, что в go1.16 идет работа по раскрытию параметров http / 2, и я ожидаю, что мы воспользуемся ими, как только они станут доступны.

На самом деле, благодаря большой работе над sig-scaleability и sig-release для квалификации на предварительных версиях go1.15, Kubernetes 1.19 только что вышел на go1.15.

Оппс. Простите за неловкую шутку. На выпуск v1.19 особого внимания не обратил.
Кажется, мы полностью пропустили go1.14 на K8S? Вот это да. это большой скачок 👍

@povsister

Спасибо, что поделились своим решением. Не могли бы вы рассказать подробнее о том, как вы заставили это работать?

На данный момент я изменил код, чтобы по умолчанию было включено http2: perform connection health check введенное golang / net @ 0ba52f6 .
Это помогает решить эту проблему. Но немного заторможен.

Какие изменения в коде вы внесли? А где, в каком файле?

@KarthikRangaraju
Обратитесь к этому PR, чтобы включить проверку работоспособности при инициализации h2Transport,
или вы можете сделать некоторую рефлексию / небезопасное смещение, чтобы получить доступ к неэкспортируемому полю во время выполнения.

И не забудьте обновить golang / x / net перед тем, как делать такие вещи.

Нам не удалось воспроизвести эту проблему, хотя время от времени мы сталкиваемся с ней.

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

Наше решение:

  • Следующий сценарий запускается каждые 1 час. Он общается с сервером kube-api через kubectl через файл конфигурации kube.
    kubelet использует (при этом нет повышения привилегий).
  • Спрашивает, является ли главный узел thinks его собственным узлом NotReady. Если да, запускает перезапуск kubelet, запустив команду touch для файла.
    то есть watched от kubelet-watcher.service для изменений файловой системы и, соответственно, перезапускает kubelet.
#!/bin/bash

while true; do
  node_status=$(KUBECONFIG=/etc/kubernetes/kubelet.conf kubectl get nodes | grep $HOSTNAME | awk '{print $2}')
  date=$(date)
  echo "${date} Node status for ${HOSTNAME}: ${node_status}"
  if [ ${node_status} == "NotReady" ]; then
    echo "${date} Triggering kubelet restart ..."
    # Running touch command on /var/lib/kubelet/config.yaml. This will trigger a kubelet restart.
    # /usr/lib/systemd/system/kubelet-watcher.path & /usr/lib/systemd/system/kubelet-watcher.service
    # are responsible for watching changes in this file
    # and will restart the kubelet process managed by systemd accordingly.
    touch /var/lib/kubelet/config.yaml
  fi

  # Runs ever 1 hour
  sleep 3600
done
# cat  /usr/lib/systemd/system/kubelet-watcher.path
[Path]
PathModified=/var/lib/kubelet/config.yaml

[Install]
WantedBy=multi-user.target

# cat /usr/lib/systemd/system/kubelet-watcher.service
[Unit]
Description=kubelet restarter

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart kubelet.service

[Install]
WantedBy=multi-user.target[root@den-iac-opstest-kube-node02 karthik]#

В Kubernetes 1.19.0 проблема все еще существует, но сообщения немного другие.
Sep 11 18:19:39 k8s-node3 kubelet[17382]: E0911 18:19:38.745482 17382 event.go:273] Unable to write event: 'Patch "https://192.168.1.150:6443/api/v1/namespaces/fhem/events/fhem-7c99f5f947-z48zk.1633c689ec861314": read tcp 192.168.1.153:34758->192.168.1.150:6443: use of closed network connection' (may retry after sleeping)
Теперь он содержит в сообщении об ошибке «(может повторить попытку после сна)».

Можно ли полностью смягчить это в kubernetes, не дожидаясь обновления golang? Например, можно ли сделать так, чтобы client-go заменял транспорт, если он обнаруживает «использование закрытого сетевого соединения» или что-то в этом роде?

В качестве альтернативы, будет ли эта проблема возникать при использовании HTTP 1.1, или это связано исключительно с HTTP 2? Если бы HTTP 1.1 был невосприимчивым и не имел бы огромных недостатков, было бы очень простым обходным путем просто установить GODEBUG=http2client=0 в kubelet, kube-proxy и различных процессах уровня управления или даже установить GODEBUG=http2server=0 в процессе apiserver, чтобы сделать изменение универсальным.

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

Можно ли сделать так, чтобы client-go заменял транспорт, если он обнаруживает «использование закрытого сетевого соединения» или что-то в этом роде?

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

будет ли эта проблема возникать при использовании HTTP 1.1, или это связано исключительно с HTTP 2?

Насколько мне известно, HTTP 1.1 может столкнуться с той же проблемой, поскольку неактивные соединения возвращаются в пул поддержки активности (и имеет меньше возможностей для обнаружения / смягчения его, поскольку механизм проверки работоспособности ping недоступен для него)

Есть ли хороший обходной путь для проектов, в которых используется клиент? Как мы можем определить, когда клиент мертв и какой минимум нам нужно сделать, чтобы исправить это (похоже, перезапуск нашего процесса может быть единственным вариантом)?

Как определить, что клиент мертв

Когда вы неоднократно получали ошибку write tcp xxx use of closed network connection для идентичного URL. Это означает, что клиент мертв. Пул соединений внутри транспорта кэшировал неработающее TCP-соединение для запрошенного хоста: порт .

Есть ли хороший обходной путь для проектов, в которых используется клиент?

Насколько мне известно, повторное построение http.Client может решить эту проблему без перезапуска всего приложения.

какой минимум нам нужно сделать, чтобы это исправить

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

У меня есть доступ к исходному коду моего проекта, но мы используем клиент kubernetes. Когда мы выполняем часы, кажется, что они никогда не обнаруживают, разорвано ли TCP-соединение таким образом (и поскольку часы обрабатывают HTTP-транзакции, в наш код не всплывают ошибки для обработки).

Ага. вы правы, http.Client не отображается клиентом kubernetes.
В настоящее время для приложения верхнего уровня безнадежно найти обходной путь с небольшими затратами.
Если клиент kubernetes не использует http.DefaultClient , это можно исправить, перестроив весь клиент kubernetes.

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

Предлагаемый здесь обходной путь работает у нас в течение нескольких недель. Мы превратили его в скрипт python, который работает как демон во всех наших кластерах. Обычно мы видим, что он принимает меры один или два раза в неделю (автоматически перезапускает kubelet), и в результате мы не оказали негативного влияния на работу нашего кластера. Мы сделали его переменным, чтобы он перезапускал kubelet только в том случае, если он видит 2+ сообщения за 5 минут. Мы видели, что иногда мы могли видеть одно сообщение, и это не было проблемой. Когда возникает проблема, вы постоянно будете видеть ошибку use of closed network connection в журналах kubelet.

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

Я наблюдаю, как на одном кластере baremetal это происходит примерно 2–4 раза каждые 24 часа. 1.17.12

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

Я использую haproxy перед главным узлом, как вы думаете, есть ли способ предотвратить это с помощью некоторой конфигурации LB?

@ shubb30 не могли бы вы поделиться со мной своим решением?

Я могу подтвердить, что мои apiservers НЕ перезагружаются, когда у меня возникает проблема. Я использую трюк с демонами и оболочкой для отслеживания записи в журнале, а затем перезапускаю kubelet, это сработало довольно хорошо, но я рассматриваю это как временное решение.

Вот модифицированная версия того, что хорошо работает для нас в качестве временного решения.

Привет всем!

Считаем ли мы, что этот бэкпорт может помочь?
https://github.com/golang/go/issues/40423

Хорошие новости: golang / net master поддерживает настройку транспорта http2, который теперь позволяет устанавливать таймауты! https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2

Выполнено.
PR открыт для ознакомления.

Еще одна хорошая новость: Kubernetes не использует связанный http2 в стандартном пакете net / http, поэтому нам не нужно ждать следующего выпуска Go. Мы можем напрямую использовать https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2, чтобы исправить эту проблему.

Предложил исправление здесь. https://github.com/kubernetes/kubernetes/pull/95898
Он обновляет зависимость до требуемой версии и по умолчанию включает проверку работоспособности транспорта http2.
Это должно помочь приложениям, которые используют client-go для связи с apiserver (например, kubelet), избавиться от проблемы «приложение зависает при записи tcp xxx: использование закрытого соединения».

Не стесняйтесь оставлять любые комментарии.

Похоже, что упомянутый номер 95898 был закрыт по причинам, которые нам не нужно обсуждать.

Есть ли какие-либо другие обновления по этой проблеме?

https://github.com/kubernetes/kubernetes/pull/95981 (ссылка выше) находится в процессе загрузки исправления http / 2

Является ли эта проблема специфической для версий Kubernetes 1.17.X?

@krmayankk Не совсем уверен, когда именно это началось. Но хоть 1.17-1.19 есть такая проблема. # 95980 должен был исправить это (будет частью следующей версии 1.20, вчера не попал в бета-версию)

@krmayankk Мы видели эту проблему и в версии 1.18.9, но она была вызвана ошибочной версией Rancher, которая вызвала очень интенсивное использование сети. После отката на другую версию проблем не наблюдалось.

У меня была эта проблема, но теперь я "исправил" ее в своем небольшом хобби-кластере, используя обходной путь в комментарии выше.

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

Есть ли план по выбору вишни / обратному переносу https://github.com/kubernetes/kubernetes/pull/95981 и https://github.com/kubernetes/kubernetes/issues/87615 в ветку выпуска 1.18?

Есть ли планы выбрать ветку выпуска от # 95981 до версии 1.17?

В этом комментарии обсуждаются резервные копии для более старых выпусков: https://github.com/kubernetes/kubernetes/pull/95981#issuecomment -730561539

Я думаю, что ответ - «это сложно и может что-то сломать, поэтому, вероятно, нет». Какого-то такого же ответа я ожидал бы от людей, использующих v1.17, когда их спросят, так почему бы не перейти на v1.20, чтобы получить исправление? :смеющийся:

Было бы здорово перенести это как минимум на 1.19, поскольку это сделает исправление доступным относительно скоро. Я подозреваю, что некоторые люди воздержатся от версии 1.20 из-за устаревания Docker.

Было бы здорово перенести это как минимум на 1.19, поскольку это сделает исправление доступным относительно скоро.

Это уже сделано.

Я подозреваю, что некоторые люди воздержатся от версии 1.20 из-за устаревания Docker.

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

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

Для моей ясности это похоже на то, что это должно быть решено с помощью # 95981, и это превратилось в 1.20 и было обратно портировано на 1.19?

95981 был объединен с 1.20 и был выбран до 1.19 в # 96770.

/близко

@caesarxuchao : закрытие этого вопроса.

В ответ на это :

95981 был объединен с 1.20 и был выбран до 1.19 в # 96770.

/близко

Инструкции по взаимодействию со мной с помощью PR-комментариев доступны здесь . Если у вас есть вопросы или предложения, связанные с моим поведением, отправьте сообщение о проблеме в репозиторий kubernetes / test-infra .

Будет ли выбор backport / cherry для v1.16, v1.17 или или v1.18?

@chilicat см. https://github.com/kubernetes/kubernetes/pull/95981#issuecomment -730561539. Я не планирую выбирать его до версии 1.18 или более ранней.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги