Kubernetes: (1.17) لن يقوم Kubelet بإعادة الاتصال بـ Apiserver بعد فشل NIC (استخدام اتصال شبكة مغلق)

تم إنشاؤها على ٢٨ يناير ٢٠٢٠  ·  123تعليقات  ·  مصدر: kubernetes/kubernetes

لقد قمنا للتو بترقية مجموعة الإنتاج لدينا إلى 1.17.2.

منذ التحديث يوم السبت ، واجهنا هذا الانقطاع الغريب: Kubelet ، بعد فشل سند NIC (الذي يتعافى بعد فترة وجيزة) ، ستتعطل جميع اتصالاته ولن يحاول إعادة تثبيتها ما لم تتم إعادة تشغيله يدويًا.

هذا هو الجدول الزمني لآخر مرة حدث فيها:

01:31:16: يتعرف Kernel على الفشل في واجهة السندات. يذهب لفترة من الوقت. في النهاية يتعافى.

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 api-machinery

إلقاء نظرة على الكود يحدث الخطأ هنا

تفسير الكود هو أنه يفترض أنه من المحتمل أن يكون EOF (IsProbableEOF) بينما في هذه الحالة لا يبدو كذلك.

/ إسناد caesarxuchao

rikatz ، هل يمكنك توضيح كيفية تعقب الرمز الذي لصقته؟

فكرتي هي أن العاكس كان سيعيد تشغيل الساعة بغض النظر عن كيفية تعامله مع الخطأ ( الرمز ) ، لذلك لا يفسر الفشل في الاسترداد.

بالضبط caesarxuchao لذلك هذا هو سؤالنا.

لقد تتبعت الخطأ بشكل أساسي من خلال الإمساك به من خلال الشفرة والعبور مع ما كان يفعله kubelet في ذلك الوقت (مشاهدة الأسرار) للوصول إلى هذا الجزء.

ليست طريقة متقدمة ، من خلال هذا يبدو أن النقطة الدقيقة من رمز الخطأ.

السؤال هو ، لأن الاتصال مغلق ، هل هناك إشارة في مكان ما على أن هذه هي ساعة EOF بدلاً من فهم هذا خطأ؟

ليس لدي أي شيء أكثر ذكاءً لإضافته بخلاف أن لدينا عقدة أخرى تفشل بنفس الطريقة ، مما أدى إلى زيادة التكرارات من آخر 4 أيام إلى 4 أيام.

سيحاول تحديد ما إذا كانت أحداث السندات قد حدثت على العقد الأخرى وإذا كان kubelet يتعافى - فقد يكون حظًا سيئًا في بعض حالات التعافي ، وليس حدثًا بنسبة 100٪.

أعتقد أننا نشهد هذا أيضًا ، ولكن ليس لدينا سندات ، فنحن لا نرى سوى رسائل "الناقل المفقود" للشبكة هذه لواجهات Calico cali* ، وهي أجهزة veth محلية.

لقد واجهت هذا أيضًا ، بدون أي روابط. تؤدي إعادة تشغيل العقدة إلى إصلاح المشكلة ، ولكن إعادة تشغيل خدمة Kubelet لا تؤدي إلى ذلك (تفشل جميع استدعاءات واجهة برمجة التطبيقات مع "غير مصرح به").

لقد واجهت هذا أيضًا ، بدون أي روابط. تؤدي إعادة تشغيل العقدة إلى إصلاح المشكلة ، ولكن إعادة تشغيل خدمة Kubelet لا تؤدي إلى ذلك (تفشل جميع استدعاءات واجهة برمجة التطبيقات مع "غير مصرح به").

تحديث: إعادة تشغيل Kubelet هل أصلحت المشكلة بعد مرور الوقت الكافي (ساعة واحدة؟).

أنا أرى نفس السلوك. تثبيتات Ubuntu 18.04.3 LTS clean. الكتلة بنيت مع رانشر 2.3.4. لقد رأيت هذا يحدث بشكل دوري مؤخرًا وتميل إعادة تشغيل kubelet إلى إصلاحه بالنسبة لي. الليلة الماضية كل العقد الثلاثة الخاصة بي أظهرت نفس السلوك. لقد صححت 2 لإحضار مجموعتي. الثالث لا يزال في هذه الحالة أثناء الحفر.

نشهد نفس المشكلة على CentOS 7 ، الكتلة التي تم بناؤها حديثًا باستخدام مزرعة (1.17.2). نحن نستخدم نسج. تعرض جميع العقد العاملة الثلاثة هذه المشكلة. لا تعمل إعادة تشغيل kubelet بالنسبة لنا ، وعلينا إعادة تشغيل العقدة بأكملها

/ عقدة سيج
/ sig api-machinery

إلقاء نظرة على الكود يحدث الخطأ هنا

تفسير الكود هو أنه يفترض أنه من المحتمل أن يكون EOF (IsProbableEOF) بينما في هذه الحالة لا يبدو كذلك.

نحن نشهد أيضًا نفس المشكلة. من السجل ، وجدنا أنه بعد حدوث المشكلة ، لا تزال جميع الطلبات اللاحقة تُرسل على نفس الاتصال. يبدو أنه على الرغم من أن العميل سيعيد إرسال الطلب إلى الخادم ، إلا أن مكتبة http2 الأساسية لا تزال تحتفظ بالاتصال القديم ، لذلك لا تزال جميع الطلبات اللاحقة تُرسل على هذا الاتصال وتلقيت نفس الخطأ use of closed connection .

لذا فإن السؤال هو لماذا لا يزال http2 يحتفظ باتصال مغلق بالفعل؟ ربما كان الاتصال الذي احتفظ به على قيد الحياة بالفعل ولكن تم إغلاق بعض الاتصالات الوسيطة بشكل غير متوقع؟

لدي نفس المشكلة مع مجموعة Raspberry Pi مع k8s 1.17.3 كثيرًا. استنادًا إلى بعض المشكلات القديمة ، قمت بتعيين حد اتصال HTTP لخادم kube API على 1000 "- --http2-max-streams-per-connection = 1000" ، كان جيدًا لأكثر من أسبوعين بعد ذلك يبدأ الآن مرة أخرى.

هل من الممكن إعادة بناء 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 ساعة لكل جراب في مقاييس بروميثيوس). كما أن تعيين قيم منخفضة جدًا من http2-max-streams-per-connection لم يتسبب في حدوث المشكلة ، ولكن على الأقل كنت قادرًا على ملاحظة بعض السلوك غير المتوقع لمدير الجدولة ومدير وحدة التحكم (ربما كان مجرد تحميل زائد بعد حلقات إعادة المشاهدة التي لا نهاية لها أو شيء من هذا القبيل ، على أية حال).

كحلل ، يتم إعادة تشغيل جميع العقد الخاصة بي كل ليلة عبر cronjob المحلي. الآن بعد 10 أيام مضت ، يمكنني القول أنه يعمل بالنسبة لي ، لم يعد لدي "استخدام اتصال الشبكة المغلقة" على العقد الخاصة بي.

تضمين التغريدة
أشكركم على نشر هذا. ما الفاصل الزمني الذي تستخدمه في 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 ٪ من استخدام وحدة المعالجة المركزية بسبب ذلك ، حيث نسيت تعيين Swappiness على 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 إلى حل المشكلة ، فمن المحتمل أن يكون السبب الجذري مختلفًا.

لدي نفس المشكلة مع الإصدار 1.17.2 عند إعادة تشغيل الشبكة ، ولكن هناك عقدة واحدة فقط بها هذه المشكلة (تحتوي مجموعتي على خمس عقد) ، ولا يمكنني إعادة إنتاجها. إعادة تشغيل kubelet حل هذه المشكلة.

كيف يمكنني تجنب هذه المشكلة؟ هل تريد ترقية أحدث إصدار أم لديك طريقة أخرى لإصلاحه؟

لقد أصلحته عن طريق تشغيل هذا البرنامج النصي 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 كانت ستنجح أيضًا).

يتحدث kubelet الخاص بالإعداد إلى مثيل haproxy محلي عبر مضيف محلي يعمل بمثابة موازن تحميل 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

سننشر تحديثًا إذا أدى ذلك إلى حل مشكلتنا المحددة في حالة مساعدة أي شخص هنا في هذه الأثناء.

هل تريد معرفة ما إذا كانت هناك معلمة تهيئة لتعيين حد أعلى مطلق لوقت المشاهدة؟ لقد وجدت - تدفق - الخمول - اتصال - مهلة ولكن لا شيء محدد للساعات.

نحن نرى هذا في 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 هل تم التأكيد على أن إعادة

أرى مشكلة مماثلة في 1.16.8 - في كثير من الأحيان (أحيانًا مرة كل يومين ، وأحيانًا كل أسبوعين) تصبح العقدة NotReady ، لسبب توقف Kubelet عن نشر حالة العقدة ، و "استخدام اتصال شبكة مغلق" ملء السجلات

قد يكون لديك مشكلة في التعامل مع ترقية 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 أم لا؟

لا أتوقع ذلك. يبدو أن التغييرات على etcd و bbolt مطلوبة لدعم go1.14 ، وهو تغيير أكبر مما يتم إجراؤه عادةً في فروع الإصدار.

تضمين التغريدة يبدو أننا (على الأقل بالنسبة لمجموعاتنا) نحتاج إلى استراتيجية تخفيف في هذه الأثناء :)

هل تحدث هذه المشكلة فقط بعد فشل NIC؟ نشاهد نفس رسالة الخطأ في مجموعات الإصدار 1.16.8 الخاصة بنا ، ولكن لا يوجد فشل مصاحب لبطاقة واجهة الشبكة (NIC).

كان لدينا مثيل واحد على الأقل حيث يوجد خطأ SCSI في الجهاز الظاهري الأساسي عند الاتصال بشبكة SAN. تم حل مشكلة SCSI من تلقاء نفسها ، ولكن لم يتم استرداد kubelet .

تمت إضافة الخيار --goaway-chance في 1.18 (# 88567). هل سيخفف هذا الخيار من هذه المشكلة؟

لا ، هذا له تأثير فقط إذا كان kubelet قادرًا بالفعل على الوصول إلى خادم API والحصول على استجابة مرة أخرى.

فشل سند NIC (الذي يتعافى بعد فترة وجيزة) ، سوف تتعطل جميع اتصالاته ولن يحاول إعادة تأسيسها ما لم تتم إعادة تشغيلها يدويًا.

هل يمكنك أن تخبرني ما هو وضع السندات الذي تستخدمه؟ لا يمكنني إعادة إنتاج هذا على مجموعتي باستخدام روابط احتياطية نشطة.

بعد الترقية إلى Kubernetes 1.16 ، بدأنا أيضًا في رؤية الخطأ use of closed network connection و kubelet لا يعيد الاتصال بـ apiserver ، تاركًا العقد عالقة في NotReady. لم نتمكن من إعادة إنتاج المشكلة عن طريق إزالة بطاقات NIC (عن طريق تعيين الروابط لأسفل / لأعلى) ، لكننا لاحظنا أن هذا السلوك يحدث فقط في المجموعات التي تم تحميلها بشكل أكبر.

لقد قمنا بمزيد من البحث ووجدنا أن الافتراضي من جانب الخادم الافتراضي من جانب العميل هو 1000 ، لذلك أعتقد أنه بمجرد حصول kubelet على خطأ من apiserver للوصول إلى حد دفق http2 ، لم يحاول أبدًا إعادة الاتصال. بعد تعيين --http2-max-streams-per-connection=1000 لم نلاحظ مشكلة تعلق العقد في NotReady بقدر ما تم العثور عليه في الأصل أثناء الاختبار. لم يحل هذا مشكلة عدم إعادة الاتصال kubelet ، لكنه ساعدنا في التخفيف من المشكلة التي كنا نراها.

بعد الترقية إلى Kubernetes 1.16 ، بدأنا أيضًا في رؤية الخطأ use of closed network connection و kubelet لا يعيد الاتصال بـ apiserver ، تاركًا العقد عالقة في NotReady. لم نتمكن من إعادة إنتاج المشكلة عن طريق إزالة بطاقات NIC (عن طريق تعيين الروابط لأسفل / لأعلى) ، لكننا لاحظنا أن هذا السلوك يحدث فقط في المجموعات التي تم تحميلها بشكل أكبر.

لقد قمنا بمزيد من البحث ووجدنا أن الافتراضي من جانب الخادم الافتراضي من جانب العميل هو 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 بدون تعيين --http2-max-streams-per-connection هذا في سجلات apiserver الخاصة بنا (باستخدام الإصدار 1.16):
I0603 10:18:08.038531 1 flags.go:33] FLAG: --http2-max-streams-per-connection="0"

ويظهر طلب الضفيرة هذا في الرد:
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!

عندما أستخدم --http2-max-streams-per-connection=1000 يظهر طلب الضفيرة
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!

treytabnerjmcmeek، أنت على حق. لقد أخطأت في قراءة الكود. : +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" لم يساعد

اهلا ياجماعة. أعتقد أنني أخيرًا قد تعقبت هذه المشكلة. لدينا نفس المشكلة حدثت الليلة الماضية. لكن تعافى بنجاح مع kubelet معدلة.

إنه ليس خطأ Kubernetes ، إنه يتعلق بحزمة golang القياسية net/http التي يستخدمها 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": احصل "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": احصل "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": احصل "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 مللي ثانية ، الخطأ: احصل على "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 مللي ثانية ، الخطأ: احصل على "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 reflector.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 reflector.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 reflector.go: 153] object- "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 ثانية ، الخطأ: احصل على "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 reflector.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 reflector.go: 153] object- "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 reflector.go: 153] الكائن- "core" / "registerpullsecret": فشل في القائمة * 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 reflector.go: 153] الكائن- "kube-system" / "registerpullsecret": فشل في القائمة * 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 required_state_of_world_populator.go: 320] خطأ في معالجة حجم "publish-log-dir" لـ pod "fluentd-h76lr_core (e95c9200-3a0c -4fea-bd7f-99ac1cc6ae7a) ": خطأ معالجة PVC core / 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 / condition \": [{\ "type \": \ "MemoryPressure \"} ، {\ "type \": \ "DiskPressure \"} ، {\ "type \": \ "PIDPressure \ "}، {\" type \ ": \" Ready \ "}]، \" terms \ ": [{\" lastHeartbeatTime \ ": \" 2020-06-22T19: 25: 29Z \ "، \" type \ ": \" MemoryPressure \ "}، {\" lastHeartbeatTime \ ": \" 2020-06-22T19: 25: 29Z \ "، \" type \ ": \" DiskPressure \ "} ، {\" lastHeartbeatTime \ ": \ "2020-06-22T19: 25: 29Z \"، \ "type \": \ "PIDPressure \"}، {\ "lastHeartbeatTime \": \ "2020-06-22T19: 25: 29Z \"، \ " اكتب \ ": \" جاهز \ "}]}}" للعقدة "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 kubelet vm10.company.com [22255]: E0623 03: 25: 49.553078 22255 kubelet_node_status.go: 402] خطأ في تحديث حالة العقدة ، ستعيد المحاولة: خطأ في الحصول على العقدة "vm10.company.com": احصل "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 required_state_of_world_populator.go: 320] خطأ في معالجة حجم "موقع السجل" للقرص "fluentd-h76lr_core (e95c9200-3a0c-4fea -bd7f-99ac1cc6ae7a) ": خطأ في معالجة PVC core / 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 إلى حالة الاستعداد

حصلنا على بعض الأفكار الجديدة المحتملة في هذه المشكلة في أكوامنا. مع بعض الثقة ، نفترض حدوث انخفاض نادر في الاتصال على مستوى الشبكة / البنية التحتية بسبب الحمل العالي فيما يتعلق بأرقام الاتصال في مواقف محددة ، لذلك في حالتنا لم تكن واجهات الشبكة تقلب. لقد واجهنا مشكلات سيئة مع اتحاد بروميثيوس بشكل خاص بسبب ذلك نظرًا لتحولهم إلى http2 من جانب العميل . أدى تمكين http2 health monitor من خلال تعيين http2.Transport.ReadIdleTimeout كما تم تنفيذه مع golang/net#55 حل مشكلات الاتحاد تمامًا بالنسبة لنا.

لم يتم عرض القيم حاليًا لأن apimachinery/pkg/util/net/http.go بإنشاء مثيل http.Transport ويقوم بترقية هذا إلى http2 داخليًا ، والذي لا يعرض الخيار حتى يتم دمج golang / net # 74.

هل هناك أي حلول أخرى إلى جانب وظيفة kubelet لإعادة تشغيل cron؟ لدينا وظيفة 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 (kernel 4.14.138) إلى Ubuntu 18.04 (kernel 5.3.0) منذ أكثر من شهر ، ولم تظهر المشكلة منذ ذلك الحين.
واحدة من مجموعتي المتبقية على RancherOS ، لقد أعيد إنتاج هذه المشكلة 3 مرات بالفعل.

ليس صحيحًا بنسبة 100٪ ، ولكن من المحتمل أن يكون إصدار النواة مهمًا.

من الصعب القول. نحن بالتأكيد نلاحظ (د) المشكلة مع 1.16 إلى 1.18 ، ولكن قبعة نادرة نادرة "kubelet stuck الظهور" من قبل. لقد بحثنا بالفعل في مثل هذه المشكلات منذ عام على الأقل ، لكن لا يمكننا أبدًا ربط أي شيء (حوادث فردية كل بضعة أسابيع ، ولدينا عدد من أربعة أرقام من kubelets قيد التشغيل). لقد ساءت الأمور كثيرًا منذ أن قمنا بتثبيت 1.16 ، لكننا حاليًا نفترض أن مشكلات الشبكات الأساسية (أيضًا نادرة جدًا ويصعب تتبعها ...) تحدث في كثير من الأحيان. نحن نشغل Ubuntu 19.10 مع Kernel 5.3.0-46-generic لكننا متأثرون (من المحتمل جدًا أنك حصلت بالفعل على مستوى Patchlevel أحدث). هل يمكنك إعطاء تلميح عن مستوى إصدار / تصحيح kernel الدقيق الذي تقوم بتشغيله؟

-
ينس إرات \ بصمة

إنه 5.3.0-59-generic . لكن لدينا فقط 40 كوبلت ، لذلك قد يكون الأمر مجرد صدفة.

كما قلت أعلاه. تحدث هذه المشكلة بشكل متكرر أكثر في الكتل المحملة بكثافة. لاحظنا نفس المشكلة كل ليلة تقريبًا قبل تمكين h2 Transportation healthCheck.
وفقا لقضية أبلغت لمسؤول جولانج . تحدث المشكلة في حلقة قراءة المقبس ، والتي يجب أن تُرجع خطأ عند قراءة المقبس المغلق ولكنها لا تفعل ذلك أبدًا. أيضًا ، أقترح إضافة منطق معالجة الخطأ على مقبس الكتابة لاكتشاف مشكلة الاتصال بنشاط. لكن بعد عدة أيام ، يبدو أنهم لا يهتمون بمثل هذه القضايا النادرة.

بعيدًا عن الموضوع ، أعني ، نظرًا لأن المشكلة ناتجة عن مقبس الشبكة وهو قريب جدًا من النواة. قد يساعد تحديث kernel أو لا. (ملاحظة: نحن نستخدم centos 7 مع kernel 3.10 ، وهذا يحدث كل يوم تقريبًا قبل تمكين healthCheck)
لقد أمضيت حوالي 3 أيام في قراءة الكود المصدري لـ net / http ، بقدر ما رأيت ، تمكين h2 transport healthCheck shoud للمساعدة في التعافي من هذه المشكلة ، وقد هربنا حقًا من هذا الموقف الغريب من خلال القيام بذلك.
JensErat هل لديك دليل ملموس على تمكين healthCheck للمساعدة في حل هذه المشكلة؟

JensErat هل لديك دليل ملموس على تمكين healthCheck للمساعدة في حل هذه المشكلة؟

نحن ندير اتحاد بروميثيوس لكل مجموعة من مجموعات Kubernetes الخاصة بنا. قدم Prometheus 2.19.0 http2 (لقد نسوا ذكر هذا في سجل التغيير على الرغم من أنه تم إخفاؤه جيدًا في نص رسالة الالتزام ، كان علي أن أقوم بالتقسيم ونشر وانتظر بضع ساعات لكل تشغيل ...) ولاحظنا ذلك دزينة من الحوادث مع الاتحاد عالق في اليوم. قمت أولاً بتصحيح دعم http2 مرة أخرى (واختفت المشكلة) ، ثم قمت بتعيين مهلة القراءة مباشرة في golang / net / x / http2. منذ ذلك الحين ، لم يعد لدينا أي حادثة فيدرالية واحدة.

أنا أستعد حاليًا لطرح إصدار Kubernetes مصحح على بعض المجموعات ، لذلك من المفترض أن نحصل على البيانات في غضون أيام قليلة. سنقوم بالتأكيد بمشاركة نتائجنا بمجرد حصولنا على البيانات المناسبة.

-
ينس إرات \ بصمة

أنا أستعد حاليًا لطرح إصدار Kubernetes مصحح على بعض المجموعات ، لذلك من المفترض أن نحصل على البيانات في غضون أيام قليلة. سنقوم بالتأكيد بمشاركة نتائجنا بمجرد حصولنا على البيانات المناسبة.

شكرا لملاحظاتك. هذه رسالة مبهجة للغاية.
على الرغم من أن السبب الجذري ليس واضحًا تمامًا ، فإننا على الأقل نجد طريقة للتعافي من الكارثة. :د

لدينا نفس المشكلة مع k8s v1.14.3 ، وإعادة تشغيل kubelet يمكن أن يحل المشكلة.

أعلم أن هذا سخيف ، لكن يجب أن يعمل كحل مؤقت:

قم بتوسيع yaml

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 VMs ، والذي سيمنع vSphere من نقل VMs بين برامج Hypervisor وبالتالي التخلص من أي انقطاع في الاتصال بالشبكة يسبب مشاكل لـ Kubelets

لدينا بعض الأخبار السارة فيما يتعلق بتخفيف المشكلة باستخدام ميزة التحقق الصحي الجديدة لـ golang http2: لم تعد هناك مشكلات. حتى الآن ، قمنا بتنفيذ "الإصلاح" (الإعداد الثابت للقيمة في رمز x/net المباع) في Prometheus ، و Kubernetes بالكامل والعديد من المكونات الداخلية ، مع ملاحظة:

  • لا يوجد اتحاد بروميثيوس يصدر بعد الآن
  • لا يزال kubelet في بعض الأحيان يبلغ عن أحداث "استخدام اتصال مغلق" منفرد ولكنه يتعافى في غضون ثوان (قمنا بتعيين نافذة فحص صحة http2 لمدة 30 ثانية تقريبًا)
  • في بعض الأحيان نواجه مشكلات مع ساعات kubectl - اختفت أيضًا في حالة استخدام kubectl المصحح
  • نحن نجري مجموعة اختبارات E2E ممتدة للتحقق من تكاملنا بانتظام ، ولاحظنا فترات زمنية متقطعة للاختبار والتقشر. خمين ما؟ رحل الآن.

علاوة على ذلك ، تمكنا من الحصول على رؤى جديدة حول كيفية إثارة المشكلات. يمكنني تأكيد ملاحظة @ vi7 فيما يتعلق

هذه مشكلة مزعجة للغاية وضخمة إلى حد ما بالنسبة لبعض مستخدمي Kubernetes (على ما أعتقد ، اعتمادًا على نوع من "وساطة" طبقة / شبكة IaaS). على الرغم من وجود مناقشات golang حول الكشف عن واجهة لتعيين القيم بشكل صحيح - هل تعتقد أن هناك أي فرصة للحصول على علاقات عامة مدمجة في المنبع لتعيين هذه القيم من خلال الانعكاس (لا يزال أفضل من تفرع 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 . أقوم بإعادة تشغيل kubelet ثم تختفي الأخطاء

[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 المنبع. شيء واحد يجب التأكد منه هو أن هذا لن يتم إصلاحه في go 1.15.
وفي الوقت نفسه ، لا يزال مجتمع Kubernetes يكافح من أجل الهجرة للوصول إلى 1.14 LOL.

عادةً ، يتم إصدار إصدارات كل 6 أشهر. إذا كان كل شيء يعمل بشكل جيد ، فربما نتمكن من رؤية هذه المشكلة تم حلها عن طريق المنبع في العام المقبل ، وربما عام آخر حتى يقوم kubernetes بتعديل الإصلاح 🥇!
(فقط من أجل المزاح. إذا كنت تريد حقًا إصلاح هذا في مكدس الآن. أثبت اختراق h2Transport لتمكين healthCheck أنه يعمل.

وفي الوقت نفسه ، لا يزال مجتمع Kubernetes يكافح من أجل الهجرة للوصول إلى 1.14 LOL.

في الواقع ، نظرًا للعمل الرائع من خلال قابلية التوسع وإصدار التوقيع للتأهل عند الإصدار 1.15 من الإصدار التجريبي ، تم إصدار Kubernetes 1.19 للتو عند go1.15. يبدو أن هناك عملًا قيد التقدم لكشف خيارات http / 2 في go1.16 ، وأتوقع أننا سنستفيد من ذلك بمجرد توفره.

في الواقع ، نظرًا للعمل الرائع من خلال قابلية التوسع وإصدار التوقيع للتأهل عند الإصدار 1.15 من الإصدار التجريبي ، تم إصدار Kubernetes 1.19 للتو عند go1.15.

مقابل. آسف على النكتة المحرجة. لم يلتفت كثيرًا لإصدار v1.19.
يبدو أننا تخطينا go1.14 تمامًا على K8S؟ رائع. هذه قفزة كبيرة 👍

تضمين التغريدة

شكرا لتقاسم الحل الخاص بك. هل يمكنك إضافة المزيد من التفاصيل حول كيفية عملها؟

في الوقت الحالي ، قمت بتعديل الكود لتمكين http2: perform connection health check المقدم بواسطة golang / net @ 0ba52f6 افتراضيًا.
يثبت أن يكون بعض المساعدة في هذه المشكلة. ولكن قليلا بطيئة الاستجابة.

ما هي التغييرات البرمجية التي أدخلتها؟ وأين ، في أي ملف؟

تضمين التغريدة
قم بإحالة PR هذا لتمكين healthCheck عند تهيئة h2Transport ،
أو يمكنك القيام ببعض الانعكاس / الاختراق غير الآمن للوصول إلى الحقول غير المصدرة في وقت التشغيل.

ولا تنس تحديث golang / x / net قبل القيام بمثل هذه الأشياء.

لم نتمكن من إعادة إظهار هذه المشكلة على الرغم من أننا نواجهها من وقت لآخر.

نظرًا لأننا غير قادرين على تحديد السبب الجذري للأعراض ، فنحن نصلح الأعراض بغض النظر.

حلنا:

  • يتم تشغيل البرنامج النصي التالي كل ساعة. يتحدث إلى خادم 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 مطابق. هذا يشير إلى أن العميل قد مات. قام تجمع الاتصال داخل Transport بتخزين اتصال tcp خامد مؤقتًا للمضيف: المنفذ المطلوب.

هل هناك حل جيد للمشاريع التي تستخدم العميل؟

على حد علمي ، يمكن أن تؤدي إعادة إنشاء http.Client حل هذه المشكلة دون إعادة تشغيل التطبيق بالكامل.

ما هو الحد الأدنى الذي يتعين علينا القيام به لإصلاحه

يتطلب الوصول إلى مستوى كود المصدر للمشروع. ربما يمكنك استخدام الآلية المذكورة أعلاه لاكتشاف العميل الميت وإعادة بناء عميل جديد عند الحاجة. إذا لم يكن هناك أحد يستخدم العميل القديم ، فسيتم جمع القمامة.

لدي وصول إلى شفرة المصدر لمشروعي ، لكننا نستخدم عميل kubernetes. عندما نقوم بالساعات ، يبدو أنه لا يكتشف أبدًا ما إذا كان اتصال TCP قد تم قطعه بهذه الطريقة (وبما أن الساعة تتعامل مع معاملات HTTP ، فلا توجد أخطاء في الكود الخاص بنا للتعامل معها).

نعم. أنت محق ، لم يتم الكشف عن http.Client بواسطة عميل kubernetes.
في الوقت الحالي ، لا أمل أن يقوم تطبيق المستوى الأعلى بمثل هذا الحل بتكلفة قليلة.
إذا كان عميل kubernetes لا يستخدم http.DefaultClient ، فيمكن إصلاحه بإعادة تكوين عميل kubernetes بالكامل.

لطلب المراقبة ، يزداد الأمر سوءًا. يبدو أن عميل kubernetes يستمر في إعادة المحاولة ولا يظهر أي خطأ في التطبيق العلوي. ليس لدي فكرة جيدة عن مثل هذا الوضع الآن.

الحل البديل المقترح هنا يعمل منذ عدة أسابيع. قمنا بتحويله إلى نص بيثون يتم تشغيله كمجموعة شيطان في جميع مجموعاتنا. عادة ما نرى أنه يتخذ إجراء مرة أو مرتين في الأسبوع (إعادة تشغيل kubelet تلقائيًا) ولم يكن لدينا أي تأثير سلبي على عملية الكتلة لدينا نتيجة لذلك. لقد جعلناها متغيرة بحيث لا تعيد تشغيل kubelet إلا إذا شاهدت رسالتين أو أكثر في فترة 5 دقائق. لقد رأينا أنه في بعض الأحيان كان بإمكاننا رؤية رسالة واحدة ، ولم تكن مشكلة. عندما تحدث المشكلة ، سترى الخطأ use of closed network connection باستمرار في سجلات kubelet.

الرجاء إنشاء pullrequest وسنحقق في هذا الموضوع.

على كتلة واحدة باريمتال ، أرى هذا يحدث حوالي 2-4 مرات كل 24 ساعة. 1.17.12

يحدث ذلك عند إعادة تشغيل جراب خادم api ، حتى في مجموعة العقدة الفردية. تم فقد الاتصالات مع apiserver ، لذا فإن طريقة تقليل رقم الخطأ تعمل على حل مشكلة إعادة تشغيل الخادم.

أنا أستخدم haproxy أمام العقدة الرئيسية ، هل تعتقد أنه يوجد على أي حال لمنع ذلك من خلال بعض تهيئة LB؟

@ shubb30 هل تمانع

يمكنني أن أؤكد أن خوادمي لا يتم إعادة تشغيلها عندما واجهت المشكلة. أنا أستخدم خدعة daemonset و shell لمراقبة إدخال السجل ثم إعادة تشغيل kubelet ، لقد نجح هذا بشكل جيد ولكني أرى أنه مجرد حل مؤقت.

إليك نسخة معدلة لما كان يعمل جيدًا بالنسبة لنا كحل بديل.

مرحبا بكم جميعا!

هل نعتقد أن هذا المنفذ الخلفي يمكن أن يساعد؟
https://github.com/golang/go/issues/40423

أخبار سارة: يتمتع golang / net master بدعم لتكوين عمليات نقل http2 ، والتي تتيح الآن ضبط المهلات! https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2

منتهي.
فتح العلاقات العامة للمراجعة.

خبر سار آخر: لا تستخدم 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

هل هذه المشكلة خاصة بإصدارات 1.17.X من kubernetes؟

krmayankk لست متأكدًا تمامًا متى بدأت بالضبط. ولكن ما لا يقل عن 1.17-1.19 لديهم هذه المشكلة. # 95980 كان يجب أن يصلحه بالرغم من ذلك (سيكون جزءًا من الإصدار 1.20 التالي ، ولم يدخل في النسخة التجريبية بالأمس)

krmayankk لقد رأينا هذه المشكلة مع الإصدار 1.18.9 أيضًا ولكن تم تشغيلها بواسطة إصدار عربات التي تجرها الدواب من Rancher والتي تسببت في استخدام عالٍ جدًا للشبكة. بعد التراجع إلى إصدار آخر ، لم تتم ملاحظة أي مشكلات.

واجهت هذه المشكلة ولكنني الآن "أصلحتها" في مجموعة الهوايات الصغيرة الخاصة بي باستخدام الحل البديل في تعليق أعلاه

لقد كتبت كتابًا صغيرًا للتشغيل لنشر الحل البديل على العقد كوحدة systemd وجهاز ضبط وقت ، قد يوفر البعض الآخر بإعداد مماثل لبعض الوقت

هل هناك خطة لالنتقاء / backport 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 عند سؤالك ، فلماذا لا تقوم بالترقية إلى الإصدار 1.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.

/أغلق

تعليمات للتفاعل معي باستخدام تعليقات العلاقات العامة متوفرة هنا . إذا كانت لديك أسئلة أو اقتراحات تتعلق بسلوكي ، فيرجى تقديم مشكلة ضد

هل سيكون هناك أي خيار backport / cherry للإصدار v1.16 أو v1.17 أو v1.18؟

chilicat @ انظر https://github.com/kubernetes/kubernetes/pull/95981#issuecomment -730561539. لا أخطط لاختياره إلى 1.18 أو الإصدارات الأقدم.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات