Kubernetes: (1.17) Kubelet tidak akan terhubung kembali ke Apiserver setelah kegagalan NIC (penggunaan koneksi jaringan tertutup)

Dibuat pada 28 Jan 2020  ·  123Komentar  ·  Sumber: kubernetes/kubernetes

Kami baru saja meningkatkan klaster produksi kami ke 1.17.2.

Sejak pembaruan pada hari Sabtu, kami mengalami gangguan aneh ini: Kubelet, setelah ikatan NIC gagal (yang pulih tidak lama setelah itu), semua koneksinya akan terputus dan tidak akan mencoba untuk membangunnya kembali kecuali jika di-restart secara manual.

Berikut adalah timeline terakhir kali itu terjadi:

01:31:16: Kernel mengenali kegagalan pada antarmuka bond. Ini pergi untuk sementara waktu. Akhirnya sembuh.

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

Seperti yang diharapkan, semua jam tangan ditutup. Pesannya sama untuk mereka semua:

...
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
...

Jadi pesan-pesan ini dimulai:

`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`

Yang saya kira seharusnya tidak menjadi masalah untuk sementara waktu. Tapi itu tidak pernah pulih. Acara kami terjadi pada pukul 01:31 pagi, dan harus memulai ulang Kubelet secara manual sekitar jam 9 untuk membuat hal-hal menjadi normal.

# 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

Apiserver aktif dan berjalan, semua node lain aktif dan berjalan, yang lainnya cukup lancar. Yang ini adalah satu-satunya yang terpengaruh (hari ini) oleh masalah ini.

Apakah ada cara untuk mengurangi peristiwa semacam ini?

Apakah ini bug?

kinsupport siapi-machinery sinode

Komentar yang paling membantu

Saya telah memperbaikinya dengan menjalankan skrip bash ini setiap 5 menit:

#!/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

Semua 123 komentar

/tandatangani simpul
/sig api-mesin

Melihat kode kesalahan terjadi di sini

Penjelasan kodenya adalah bahwa ia mengasumsikan kemungkinan EOF (IsProbableEOF) sementara dalam kasus ini sepertinya tidak.

/assign @caesarxuchao

@rikatz dapatkah Anda menguraikan bagaimana Anda melacak kode yang Anda tempel?

Pikiran saya adalah bahwa reflektor akan me-restart arloji tidak peduli bagaimana menangani kesalahan ( code ), jadi itu tidak menjelaskan kegagalan untuk memulihkan.

Persis @caesarxuchao jadi ini pertanyaan kami.

Saya telah melacak kesalahan yang pada dasarnya menangkapnya melalui Kode dan menyeberang dengan apa yang kubelet lakukan saat itu (menonton rahasia) untuk masuk ke bagian itu.

Bukan cara yang canggih, melalui ini tampaknya menjadi titik yang tepat dari kode kesalahan.

Pertanyaannya adalah, karena koneksi ditutup apakah ada suatu tempat yang menandai bahwa ini adalah arloji EOF alih-alih memahami ini adalah kesalahan?

Saya tidak memiliki hal lain yang lebih pintar untuk ditambahkan selain kami memiliki simpul lain yang gagal dengan cara yang sama, meningkatkan kejadian dari 4 hari terakhir menjadi 4.

Akan mencoba memetakan jika peristiwa bond disconects terjadi di node lain dan jika kubelet pulih - mungkin ada nasib buruk pada beberapa pemulihan, dan bukan peristiwa 100%.

Saya pikir kita melihat ini juga, tetapi kita tidak memiliki ikatan, kita hanya melihat pesan "operator hilang" di jaringan ini untuk antarmuka Calico cali* , dan itu adalah perangkat dokter hewan lokal.

Saya telah mengalami ini juga, tanpa ikatan yang terlibat. Restart node memperbaiki masalah, tetapi hanya me-restart layanan Kubelet tidak (semua panggilan API gagal dengan "Tidak Sah").

Saya telah mengalami ini juga, tanpa ikatan yang terlibat. Restart node memperbaiki masalah, tetapi hanya me-restart layanan Kubelet tidak (semua panggilan API gagal dengan "Tidak Sah").

Pembaruan: memulai ulang Kubelet memang memperbaiki masalah setelah waktu yang cukup (1 jam?)

Saya melihat perilaku yang sama. Instalasi bersih Ubuntu 18.04.3 LTS. Cluster dibangun dengan peternak 2.3.4. Saya telah melihat ini terjadi secara berkala akhir-akhir ini dan hanya me-restart kubelet cenderung memperbaikinya untuk saya. Tadi malam ketiga node pekerja saya menunjukkan perilaku yang sama. Saya mengoreksi 2 untuk memunculkan cluster saya. Ketiga masih dalam kondisi ini saat saya menggali.

kami melihat masalah yang sama pada CentOS 7, cluster yang baru dibangun dengan peternak (1.17.2). Kami menggunakan tenun. Semua 3 node pekerja menunjukkan masalah ini. Restart kubelet tidak bekerja untuk kita, kita harus me-restart seluruh node

/tandatangani simpul
/sig api-mesin

Melihat kode kesalahan terjadi di sini

Penjelasan kodenya adalah bahwa ia mengasumsikan kemungkinan EOF (IsProbableEOF) sementara dalam kasus ini sepertinya tidak.

Kami juga melihat masalah yang sama. Dari log, kami menemukan bahwa setelah masalah terjadi, semua permintaan berikutnya masih dikirim pada koneksi yang sama. Tampaknya meskipun klien akan mengirim ulang permintaan ke apiserver, tetapi perpustakaan http2 yang mendasari masih mempertahankan koneksi lama sehingga semua permintaan berikutnya masih dikirim pada koneksi ini dan menerima kesalahan yang sama use of closed connection .

Jadi pertanyaannya adalah mengapa http2 masih mempertahankan koneksi yang sudah ditutup? Mungkin koneksi yang dipertahankannya memang hidup tetapi beberapa koneksi perantara ditutup tiba-tiba?

Saya memiliki masalah yang sama dengan cluster Raspberry Pi dengan k8s 1.17.3 sangat sering. Berdasarkan beberapa masalah yang lebih lama, saya telah menetapkan batas koneksi http server API kube ke 1000 "- --http2-max-streams-per-connection=1000", itu baik-baik saja selama lebih dari 2 minggu setelah itu dimulai sekarang lagi.

Apakah mungkin untuk membangun kembali kube-apiserver https://github.com/kubernetes/apiserver/blob/b214a49983bcd70ced138bd2717f78c0cff351b2/pkg/server/secure_serving.go#L50
menyetel s.DisableHTTP2 ke true secara default?
Apakah ada file docker untuk gambar resmi ( k8s.gcr.io/kube-apiserver:v1.17.3 )?

sama di sini (ubuntu 18.04, kubernetes 1.17.3)

Kami juga mengamati ini di dua cluster kami. Tidak sepenuhnya yakin tentang akar masalahnya, tetapi setidaknya kami dapat melihat ini terjadi dalam kelompok dengan jumlah tontonan yang sangat tinggi. Saya tidak dapat mereproduksi dengan memaksakan jumlah jam tangan yang tinggi per kubelet (memulai pod dengan 300 rahasia per pod, yang juga menghasilkan 300 jam tangan per pod dalam metrik Prometheus). Juga menyetel nilai http2-max-streams-per-connection sangat rendah tidak memicu masalah, tetapi setidaknya saya dapat mengamati beberapa perilaku pengatur jadwal dan pengontrol yang tidak terduga (mungkin hanya kelebihan beban setelah loop menonton ulang tanpa akhir atau sesuatu seperti ini, meskipun).

Sebagai solusinya, semua node saya memulai ulang setiap malam kublet melalui cronjob lokal. Sekarang setelah 10 hari yang lalu, saya dapat mengatakan itu berfungsi untuk saya, saya tidak memiliki lagi "penggunaan koneksi jaringan tertutup" di node saya.

@sbiermann
Terima kasih telah memposting ini. Interval waktu apa yang Anda gunakan untuk cronjob?

24 jam

Saya juga dapat mengonfirmasi masalah ini, kami belum menggunakan 1.17.3, saat ini menjalankan 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

Saya juga dapat mengonfirmasi hal ini pada Kubernetes 1.17.4 yang disebarkan melalui Rancher 2.3.5 pada node RancherOS 1.5.5. Restart kubelet tampaknya berhasil untuk saya, saya tidak perlu me-restart seluruh node.

Penyebab mendasar bagi saya tampaknya adalah RAM yang hampir habis dan kswapd0 mendapatkan penggunaan CPU hingga 100% karena itu, karena saya lupa mengatur swappiness ke 0 untuk node Kubernetes saya. Setelah mengatur swappiness ke 0 dan menambahkan beberapa RAM ke mesin, masalah belum muncul kembali untuk saya.

Jika masalah dasarnya adalah "http2 menggunakan koneksi mati", maka memulai ulang kubelet akan memperbaiki masalah. https://github.com/kubernetes/kubernetes/pull/48670 menyarankan pengurangan TCP_USER_TIMEOUT dapat mengurangi masalah. Saya telah membuka https://github.com/golang/net/pull/55 untuk menambahkan pemeriksaan kesehatan koneksi sisi klien ke perpustakaan http2, tetapi akan membutuhkan lebih banyak waktu untuk mendarat.

Jika me-restart kubelet tidak menyelesaikan masalah, mungkin penyebabnya adalah penyebab yang berbeda.

Saya memiliki masalah yang sama dengan v1.17.2 ketika memulai ulang jaringan, tetapi hanya satu node yang memiliki masalah ini (cluster saya memiliki lima node), saya tidak dapat mereproduksinya. Mulai ulang kubelet memecahkan masalah ini.

Bagaimana saya bisa menghindari masalah ini? Upgrade versi terbaru atau punya cara lain untuk memperbaikinya?

Saya telah memperbaikinya dengan menjalankan skrip bash ini setiap 5 menit:

#!/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

Saya telah membuat tambalan tanpa me-restart kubelet dan sepertinya masalahnya sudah teratasi.
tambalan tenggat waktu

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 Bisakah Anda menjelaskan cara membangun kembali klien-go?

@mYmNeo Bisakah Anda menjelaskan cara membangun kembali klien-go?

@ik9999 Terapkan tambalan ini, lalu bangun kembali kubelet dan ganti biner

@mYmNeo Bagaimana saya bisa mereproduksi masalah ini dan menguji ini?

Saya telah memperbaikinya dengan menjalankan skrip bash ini setiap 5 menit

@ik9999 Terima kasih, ini berhasil.

cc @liggitt

apakah pengaturan SetReadDeadline berarti semua jam tangan akan ditutup setiap 30 detik?

apakah pengaturan SetReadDeadline berarti semua jam tangan akan ditutup setiap 30 detik?

Ya. Ini cara yang jelek untuk menyelesaikan masalah ini (tutup paksa koneksi).

Hanya kasus lain:

Kami juga melihat ini di klaster Kube 1.16.8. Mem-boot ulang VM dapat digunakan untuk mengembalikan node ke kondisi yang baik (saya menduga kubelet restart juga akan berhasil).

Kubelet setup kami berbicara dengan instance haproxy lokal melalui localhost yang bertindak sebagai penyeimbang beban tcp ke beberapa instance master backend. Kami akan menyelidiki apakah menambahkan

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

Untuk contoh penyeimbang beban kami membantu meringankan kebutuhan untuk reboot eksplisit dan dapat menyebabkan pemulihan penuh. Contoh log berulang

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

Akan memposting pembaruan jika itu menyelesaikan masalah khusus kami jika itu membantu siapa pun di sini untuk sementara.

Ingin tahu apakah ada parameter konfigurasi untuk menetapkan batas atas absolut pada waktu tonton? Saya menemukan --streaming-idle-connection-timeout tetapi tidak ada yang spesifik untuk jam tangan.

Kami melihat ini di kube 1.17.4 setelah server API tidak sehat karena "etcd failed: reason withhold".

Halo kawan-kawan. Saya telah mengkompilasi ulang biner kubernetes dengan golang 1.14. Sepertinya masalahnya hilang

@mYmNeo golang 1.14 + kubernetes v1.17?

@mYmNeo golang 1.14 + kubernetes v1.17 ?

@pytimer Kami menggunakan 1.16.6 tanpa mengubah kode apa pun hanya dengan mengkompilasi ulang. Saya pikir akar penyebabnya mungkin golang.

Hai! Punya masalah yang sama di sini, k8s 1.17.4 apakah menurut kami kami bisa mendapatkan 1.17.5 yang dikompilasi ulang dengan go 1.14 jika itu menyelesaikan masalah?

Sayangnya, pembaruan ke go1.14 memerlukan pembaruan pada beberapa komponen utama, sehingga kemungkinan tidak akan digunakan kembali ke Kube 1.17. Anda dapat melacak masalah dan kemajuan di https://github.com/kubernetes/kubernetes/pull/88638

Senang tahu, thx

@callicles apakah sudah dikonfirmasi bahwa kompilasi ulang dengan go 1.14 menyelesaikan masalah?

Saya melihat masalah yang sama pada 1.16.8 - sangat sering (kadang-kadang setiap beberapa hari sekali, kadang-kadang setiap beberapa minggu) node menjadi NotReady, dengan alasan Kubelet berhenti memposting status node, dan "penggunaan koneksi jaringan tertutup" mengisi log

go mungkin memiliki masalah dengan peningkatan 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
        }

Halo kawan-kawan. Saya telah mengkompilasi ulang biner kubernetes dengan golang 1.14. Sepertinya masalahnya hilang

@mYmNeo apakah Anda pernah mereproduksi masalah setelah mengkompilasi ulang dengan go 1.14

Halo kawan-kawan. Saya telah mengkompilasi ulang biner kubernetes dengan golang 1.14. Sepertinya masalahnya hilang

@mYmNeo apakah Anda pernah mereproduksi masalah setelah mengkompilasi ulang dengan go 1.14

AFAIN, masalahnya sudah tidak ada lagi.

Sayangnya, pembaruan ke go1.14 memerlukan pembaruan pada beberapa komponen utama, sehingga kemungkinan tidak akan digunakan kembali ke Kube 1.17. Anda dapat melacak masalah dan kemajuan di #88638

Apakah Anda sudah tahu jika go1.14 akan di-backport ke 1.18?

Apakah Anda sudah tahu jika go1.14 akan di-backport ke 1.18?

Saya tidak berharap begitu. Perubahan pada etcd dan bbolt tampaknya diperlukan untuk mendukung go1.14, yang merupakan perubahan yang lebih besar daripada yang biasanya dibuat di cabang rilis.

@liggitt Oke thx. Sepertinya kami (setidaknya untuk cluster kami) membutuhkan strategi mitigasi untuk sementara :)

Apakah masalah ini hanya terjadi setelah kegagalan NIC? Kami melihat pesan kesalahan yang sama di kluster v1.16.8 kami, tetapi tidak ada kegagalan NIC terkait.

Kami memiliki setidaknya satu contoh di mana VM yang mendasarinya memiliki kesalahan SCSI saat menghubungkan ke SAN. Masalah SCSI teratasi dengan sendirinya, tetapi kubelet tidak pernah pulih.

Opsi --goaway-chance telah ditambahkan di 1.18(#88567). Apakah opsi ini akan mengatasi masalah ini?

Tidak. Itu hanya berpengaruh jika kubelet benar-benar dapat mencapai server API dan mendapatkan respons kembali.

ikatan NIC gagal (yang pulih tidak lama setelah itu), akan membuat semua koneksinya terputus dan tidak akan mencoba lagi untuk membangunnya kembali kecuali di-restart secara manual.

dapatkah Anda memberi tahu mode ikatan apa yang Anda gunakan? Saya tidak dapat mereproduksi ini di cluster saya dengan ikatan cadangan aktif.

Setelah memutakhirkan ke Kubernetes 1.16, kami juga mulai melihat kesalahan use of closed network connection dan kubelet tidak terhubung kembali ke apiserver, membuat node macet di NotReady. Kami tidak dapat mereproduksi masalah dengan menghapus NIC (dengan menyetel tautan ke bawah/atas), tetapi kami menyadari bahwa perilaku ini hanya terjadi pada kluster yang memuat lebih banyak.

Kami melakukan penggalian lebih lanjut dan menemukan bahwa default sisi server default sisi klien adalah 1000 , jadi dugaan saya adalah bahwa sekali kubelet mendapat kesalahan dari apiserver karena mencapai batas streaming http2, itu tidak pernah mencoba untuk menyambung kembali. Setelah menyetel --http2-max-streams-per-connection=1000 kami tidak melihat masalah dengan node yang macet di NotReady sebanyak yang ditemukan selama pengujian. Ini tidak menyelesaikan masalah kubelet yang tidak terhubung kembali, tetapi itu membantu kami mengurangi masalah yang kami lihat.

Setelah memutakhirkan ke Kubernetes 1.16, kami juga mulai melihat kesalahan use of closed network connection dan kubelet tidak terhubung kembali ke apiserver, membuat node macet di NotReady. Kami tidak dapat mereproduksi masalah dengan menghapus NIC (dengan menyetel tautan ke bawah/atas), tetapi kami menyadari bahwa perilaku ini hanya terjadi pada kluster yang memuat lebih banyak.

Kami melakukan penggalian lebih lanjut dan menemukan bahwa default sisi server default sisi klien adalah 1000 , jadi dugaan saya adalah bahwa sekali kubelet mendapat kesalahan dari apiserver karena mencapai batas streaming http2, itu tidak pernah mencoba untuk menyambung kembali. Setelah menyetel --http2-max-streams-per-connection=1000 kami tidak melihat masalah dengan node yang macet di NotReady sebanyak yang ditemukan selama pengujian. Ini tidak menyelesaikan masalah kubelet yang tidak terhubung kembali, tetapi itu membantu kami mengurangi masalah yang kami lihat.

Hai, aliran https sisi server default adalah 1000 di kube-apiserver, ini sama dengan nilai klien.
https://github.com/kubernetes/kubernetes/blob/ae1103726f9aea1f9bbad1b215edfa47e0747dce/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go#L62

@warmchang saya pikir ini berlaku untuk apiextensions apiservers dan sampel apiserver:
https://github.com/kubernetes/kubernetes/blob/ae1103726f9aea1f9bbad1b215edfa47e0747dce/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go#L62

Tes dengan tes curl tanpa pengaturan --http2-max-streams-per-connection memiliki ini di log apiserver kami (menggunakan v1.16):
I0603 10:18:08.038531 1 flags.go:33] FLAG: --http2-max-streams-per-connection="0"

Dan permintaan ikal menunjukkan ini dalam respons:
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!

Ketika saya menggunakan --http2-max-streams-per-connection=1000 permintaan curl kemudian muncul
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!

@jmcmeek @treytabner , Anda benar. Saya salah membaca kode. :+1:

Menggunakan kubernetes 1.17.6 dan sama di sini. Sepertinya kubelet menggunakan koneksi http2 yang mati.
Saya perhatikan bahwa nilai default MAX_CONCURRENT_STREAMS tidak konsisten antara kube-apiserver dan kubelet.

Cukup atur nilai sisi server ke 1000. Akan dilaporkan nanti.

Peternak/RKE

Tambahkan ke definisi cluster:

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

Periksa master-node:

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

Menyetel MAX_CONCURRENT_STREAMS ke 1000 pada APIserver tidak berpengaruh pada masalah ini.
Saya percaya ini disebabkan oleh cacat pada golang http2 Transport . Lihat di atas

Punya masalah ini lagi malam ini.
Sepertinya pengaturan 'MAX_CONCURRENT_STREAMS' tidak membantu☹️

Halo kawan-kawan. Saya pikir akhirnya saya telah melacak masalah ini. Kami memiliki masalah yang sama terjadi tadi malam. Namun berhasil dipulihkan dengan kubelet yang dimodifikasi.

Ini bukan bug Kubernetes, ini tentang paket net/http standar golang yang juga digunakan client-go .
Saya percaya ada cacat di golang.org/x/net/http2/transport.go

Ini sudah dilaporkan ke pejabat golang. Menunggu beberapa diskusi.
https://github.com/golang/go/issues/39750

Untuk saat ini saya memodifikasi kode agar http2: perform connection health check diperkenalkan oleh https://github.com/golang/net/commit/0ba52f642ac2f9371a88bfdde41f4b4e195a37c0 diaktifkan secara default.
Ini terbukti membantu dalam masalah ini. Tapi agak slow respon.

log kubelet v1.17.6 (sesuai dengan paket golang.org/x/net dimodifikasi sendiri)

Itu pulih dari menulis masalah koneksi mati, tetapi membutuhkan waktu sedikit lebih lama dari yang diharapkan.

Perhatikan bahwa performing http2 healthCheck adalah pesan log yang ingin saya tinggalkan di sana untuk membuktikan fungsi healthCheck dipanggil oleh readIdleTimer

 23 Juni 03:14:45 vm10.company.com kubelet[22255]: E0623 03:14:45,912484 22255 kubelet_node_status.go:402] Kesalahan memperbarui status simpul, akan coba lagi: kesalahan mendapatkan simpul "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": tulis tcp 16.155.199.4:39668->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 03:14:45 vm10.company.com kubelet[22255]: E0623 03:14:45.912604 22255 kubelet_node_status.go:402] Kesalahan memperbarui status simpul, akan coba lagi: kesalahan mendapatkan simpul "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": tulis tcp 16.155.199.4:39668->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 03:14:45 vm10.company.com kubelet[22255]: E0623 03:14:45.912741 22255 kubelet_node_status.go:402] Kesalahan memperbarui status simpul, akan mencoba lagi: kesalahan mendapatkan simpul "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": tulis tcp 16.155.199.4:39668->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:46 vm10.company.com kubelet[22255]: E0623 03:14:46.367046 22255 controller.go:135] gagal memastikan node lease ada, akan mencoba lagi dalam 400ms, error: Get "https:// vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s": tulis tcp 16.155.199.4:39668->16.155. 199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:48 vm10.company.com kubelet[22255]: E0623 03:14:47.737579 22255 controller.go:135] gagal memastikan node lease ada, akan coba lagi dalam 800ms, error: Get "https:// vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s": tulis tcp 16.155.199.4:39668->16.155. 199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 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: Gagal mendaftar * v1.Node: Dapatkan "https://vm10.company.com:8443/api/v1/nodes?fieldSelector=metadata.name%3Dvm10.company.com&limit=500&resourceVersion=0": tulis tcp 16.155.199.4:39668-> 16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:48.744770 22255 reflector.go:153] object-"kube-system"/"flannel-token-zvfwn": Gagal mendaftar * v1.Secret: Dapatkan "https://vm10.company.com:8443/api/v1/namespaces/kube-system/secrets?fieldSelector=metadata.name%3Dflannel-token-zvfwn&limit=500&resourceVersion=0": tulis tcp 16.155 .199.4:39668->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.599631 22255 reflector.go:153] object-"kube-system"/"coredns": Gagal membuat daftar *v1.ConfigMap: Dapatkan "https://vm10.company.com:8443/api/v1/namespaces/kube-system/configmaps?fieldSelector=metadata.name%3Dcoredns&limit=500&resourceVersion=0": tulis tcp 16.155.199.4:39668->16.155. 199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.599992 22255 controller.go:135] gagal memastikan node lease ada, akan mencoba lagi dalam 1,6 detik, error: Get "https:/ /vm10.company.com:8443/apis/coordination.k8s.io/v1/namespaces/kube-node-lease/leases/vm10.company.com?timeout=10s": tulis tcp 16.155.199.4:39668->16.155 .199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 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: Gagal mendaftar * v1.Service: Dapatkan "https://vm10.company.com:8443/api/v1/services?limit=500&resourceVersion=0": tulis tcp 16.155.199.4:39668->16.155.199.4:8443: penggunaan jaringan tertutup koneksi
 23 Jun 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.600323 22255 reflector.go:153] object-"kube-system"/"kube-flannel-cfg": Gagal membuat daftar * v1.ConfigMap: Dapatkan "https://vm10.company.com:8443/api/v1/namespaces/kube-system/configmaps?fieldSelector=metadata.name%3Dkube-flannel-cfg&limit=500&resourceVersion=0": tulis tcp 16.155 .199.4:39668->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.600463 22255 reflector.go:153] object-"core"/"registrypullsecret": Gagal mendaftar *v1.Secret: Get " https://vm10.company.com:8443/api/v1/namespaces/core/secrets?fieldSelector=metadata.name%3Dregistrypullsecret&limit=500&resourceVersion=0": tulis tcp 16.155.199.4:39668->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:14:49 vm10.company.com kubelet[22255]: E0623 03:14:49.369097 22255 reflector.go:153] object-"kube-system"/"registrypullsecret": Gagal membuat daftar *v1.Secret: Dapatkan "https://vm10.company.com:8443/api/v1/namespaces/kube-system/secrets?fieldSelector=metadata.name%3Dregistrypullsecret&limit=500&resourceVersion=0": tulis tcp 16.155.199.4:39668->16.155. 199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 03:25:39 vm10.company.com kubelet[22255]: E0623 03:25:39.543880 22255 keinginan_state_of_world_populator.go:320] Kesalahan memproses volume "deployment-log-dir" untuk pod "fluentd-h76lr_core(e95c9200-3a0c -4fea-bd7f-99ac1cc6ae7a)": kesalahan pemrosesan PVC core/itom-vol-claim: gagal mengambil PVC dari server API: Dapatkan "https://vm10.company.com:8443/api/v1/namespaces/core/ persistenvolumeclaims/itom-vol-claim": baca tcp 16.155.199.4:41512->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Jun 03:25:39 vm10.company.com kubelet[22255]: E0623 03:25:39.666303 22255 kubelet_node_status.go:402] Kesalahan memperbarui status simpul, akan mencoba lagi: gagal menambal status "{\"status\": {\"$setElementOrder/conditions\":[{\"type\":\"MemoryPressure\"},{\"type\":\"DiskPressure\"},{\"type\":\"PIDPressure\ "},{\"type\":\"Ready\"}],\"conditions\":[{\"lastHeartbeatTime\":\"2020-06-22T19:25:29Z\",\"type\ ":\"MemoryPressure\"},{\"lastHeartbeatTime\":\"22-06-2020T19:25:29Z\",\"type\":\"DiskPressure\"},{\"lastHeartbeatTime\": \"2020-06-22T19:25:29Z\",\"type\":\"PIDPressure\"},{\"lastHeartbeatTime\":\"22-06-2020T19:25:29Z\",\" ketik\":\"Siap\"}]}}" untuk simpul "vm10.company.com": Patch "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com/ status?timeout=10s": baca tcp 16.155.199.4:41512->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 03:25:49 vm10.company.com kubelet[22255]: E0623 03:25:49.553078 22255 kubelet_node_status.go:402] Kesalahan memperbarui status simpul, akan coba lagi: kesalahan mendapatkan simpul "vm10.company.com": Get "https://vm10.company.com:8443/api/v1/nodes/vm10.company.com?timeout=10s": baca tcp 16.155.199.4:41718->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 03:25:49 vm10.company.com kubelet[22255]: E0623 03:25:49.560723 22255 keinginan_state_of_world_populator.go:320] Kesalahan memproses volume "log-location" untuk pod "fluentd-h76lr_core(e95c9200-3a0c-4fea -bd7f-99ac1cc6ae7a)": kesalahan pemrosesan PVC core/itom-logging-vol: gagal mengambil PVC dari server API: Dapatkan "https://vm10.company.com:8443/api/v1/namespaces/core/persistentvolumeclaims/ itom-logging-vol": baca tcp 16.155.199.4:41718->16.155.199.4:8443: penggunaan koneksi jaringan tertutup
 23 Juni 03:27:29 vm10.company.com kubelet[22255]: I0623 03:27:29.961600 22255 log.go:181] melakukan http2 healthCheck
 23 Juni 03:31:32 vm10.company.com kubelet[22255]: I0623 03:31:31.829860 22255 log.go:181] melakukan http2 healthCheck
 23 Juni 03:31:44 vm10.company.com kubelet[22255]: I0623 03:31:44.570224 22255 log.go:181] melakukan http2 healthCheck
 23 Juni 03:32:13 vm10.company.com kubelet[22255]: I0623 03:32:12.961728 22255 log.go:181] melakukan http2 healthCheck
 23 Juni 03:33:16 vm10.company.com kubelet[22255]: I0623 03:33:15.441808 22255 log.go:181] melakukan http2 healthCheck
 23 Juni 03:33:28 vm10.company.com kubelet[22255]: I0623 03:33:28.233121 22255 log.go:181] melakukan http2 healthCheck

tidak ada lagi use of closed network connection dilaporkan dan kubelet kembali ke status Siap

Kami mendapat beberapa wawasan potensial baru dalam masalah ini di tumpukan kami. Dengan beberapa keyakinan, kami menganggap penurunan koneksi yang jarang terjadi pada tingkat jaringan/infrastruktur karena beban tinggi sehubungan dengan nomor koneksi dalam situasi tertentu, jadi dalam kasus kami itu bukan antarmuka jaringan yang terbalik. Kami terutama memiliki masalah buruk dengan federasi Prometheus karena ini karena mereka beralih ke http2 di sisi klien . Mengaktifkan monitor kesehatan http2 dengan menyetel http2.Transport.ReadIdleTimeout seperti yang diterapkan dengan golang/net#55 sepenuhnya menyelesaikan masalah federasi bagi kami.

Nilai saat ini tidak diekspos karena apimachinery/pkg/util/net/http.go instance http.Transport dan memutakhirkan ini ke http2 secara internal, yang tidak mengekspos opsi sampai golang/net#74 digabungkan.

Apakah ada solusi lain selain cron job kubelet restart? Kami telah memiliki tugas cron selama seminggu dan itu tidak menghentikan masalah terjadi.

Saya memiliki masalah yang sama di v1.17.3.

Apa yang saya temukan adalah bahwa versi k8s yang menggunakan versi golang.org/x/net bermasalah, dan paket ini tampaknya telah diperbaiki.
https://go-review.googlesource.com/c/net/+/198040

Versi dengan masalah ini (v1.16.5 ~ rilis terbaru)
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9

Perbaiki Versi (cabang master)
golang.org/x/net v0.0.0-20200707034311-ab3426394381

Apakah pembaruan paket golang.org/x/net memperbaiki masalah ini?

Apakah ada rilis yang direncanakan untuk versi k8s yang dipertahankan (v1,16, 1.17, v1,18..) untuk memperbaikinya?

Apa yang saya temukan adalah bahwa versi k8s yang menggunakan versi golang.org/x/net bermasalah, dan paket ini tampaknya telah diperbaiki.
https://go-review.googlesource.com/c/net/+/198040

Perubahan yang disebutkan hanya _menawarkan_ kemungkinan untuk mengaktifkan monitor kesehatan HTTP2, tetapi perlu diaktifkan oleh pengembang (default tidak aktif). Selain itu, tidak dapat benar-benar disetel tetapi ada permintaan tarik untuk memberi pengembang akses ke monitor kesehatan .

Saat ini saya sedang mengintegrasikan perbaikan terbaru berbasis refleksi yang memungkinkan monitor kesehatan untuk distribusi Kubernetes kami sendiri, dengan harapan ini membantu menyelesaikan masalah.

--
Jens Erat \ Jejak

@JensErat terima kasih atas jawabannya.
Jika demikian, dapatkah masalah ini juga terjadi pada versi k8s(1.13, 1.15, ..) yang lebih lama?

Saya mengubah distro node dari RancherOS (kernel 4.14.138) ke Ubuntu 18.04 (kernel 5.3.0) lebih dari sebulan yang lalu, masalah belum muncul sejak saat itu.
Salah satu cluster saya tersisa di RancherOS, masalah ini sudah direproduksi 3 kali.

Tidak 100% shure, tapi mungkin versi kernel penting.

Sulit untuk dikatakan. Kami benar-benar mengamati (d) masalah dengan 1,16 hingga 1,18, tetapi jarang terjadi "kejadian macet kubelet" sebelumnya. Kami telah menggali masalah seperti itu setidaknya sejak satu tahun, tetapi tidak pernah dapat menghubungkan apa pun (insiden tunggal selama beberapa minggu, dan kami memiliki beberapa empat digit jumlah kubelet yang berjalan). Menjadi jauh lebih buruk sejak kami menginstal 1.16, tetapi saat ini kami lebih berasumsi bahwa masalah jaringan yang mendasari (juga sangat jarang dan sulit dilacak ...) lebih sering terjadi. Kami menjalankan Ubuntu 19.10 dengan Kernel 5.3.0-46-generic tetapi terpengaruh (sangat mungkin Anda benar-benar mendapatkan patchlevel yang lebih baru). Bisakah Anda memberi petunjuk versi kernel/tingkat tambalan mana yang Anda jalankan?

--
Jens Erat \ Jejak

Ini adalah 5.3.0-59-generic . Tapi kita hanya punya ~ 40 kubletes, jadi mungkin masih kebetulan.

Seperti yang saya katakan di atas. Masalah ini lebih sering terjadi pada kluster yang dimuat berat. Kami mengamati masalah yang sama hampir setiap malam sebelum mengaktifkan h2 transport healthCheck.
Menurut masalah yang dilaporkan ke pejabat golang . Masalahnya terjadi pada loop baca soket, yang seharusnya mengembalikan kesalahan saat membaca soket tertutup tetapi tidak pernah terjadi. Juga, saya sarankan menambahkan logika penanganan kesalahan pada soket penulisan untuk secara aktif mendeteksi masalah koneksi. Namun beberapa hari kemudian, tampaknya mereka tidak peduli dengan masalah langka tersebut.

Agak jauh ke topik, maksud saya, karena masalahnya disebabkan oleh soket jaringan yang sangat dekat dengan kernel. Memperbarui kernel dapat membantu, atau tidak. (PS: kami menggunakan centos 7 dengan kernel 3.10, itu terjadi hampir setiap hari sebelum mengaktifkan healthCheck)
Saya menghabiskan sekitar 3 hari membaca kode sumber net/http, sejauh yang saya lihat, mengaktifkan h2 transport healthCheck harus membantu pulih dari masalah seperti itu, dan kami benar-benar lolos dari situasi aneh ini dengan melakukannya.
@JensErat Apakah Anda memiliki bukti nyata untuk mengaktifkan healthCheck membantu menyelesaikan masalah ini?

@JensErat Apakah Anda memiliki bukti nyata untuk mengaktifkan healthCheck membantu menyelesaikan masalah ini?

Kami menjalankan federasi Prometheus untuk setiap cluster Kubernetes kami. Prometheus 2.19.0 memperkenalkan http2 (mereka lupa menyebutkan ini di changelog dan menyembunyikannya dengan baik di badan pesan komit, saya harus membagi dua, menyebarkan dan menunggu beberapa jam untuk setiap proses ...) selusin insiden dengan federasi macet per hari. Saya pertama kali menambal dukungan http2 lagi (dan masalah hilang), dan kemudian mengatur batas waktu baca langsung di golang/net/x/http2. Sejak itu, kami tidak memiliki insiden turun federasi lagi.

Saat ini saya sedang bersiap untuk meluncurkan rilis Kubernetes yang ditambal di beberapa cluster, jadi kami akan memiliki data dalam beberapa hari. Kami pasti akan membagikan hasil kami segera setelah kami memiliki data yang tepat.

--
Jens Erat \ Jejak

Saat ini saya sedang bersiap untuk meluncurkan rilis Kubernetes yang ditambal di beberapa cluster, jadi kami akan memiliki data dalam beberapa hari. Kami pasti akan membagikan hasil kami segera setelah kami memiliki data yang tepat.

Terima kasih atas tanggapan Anda. Itu pesan yang sangat menyenangkan.
Meskipun akar masalahnya tidak begitu jelas, setidaknya kita menemukan cara untuk pulih dari bencana. :D

Kami memiliki masalah yang sama dengan k8s v1.14.3, dan restart kubelet dapat memperbaiki masalah.

Saya tahu ini konyol, tetapi harus berfungsi sebagai solusi sementara:

Perluas 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


(Ini khusus untuk peternak, tetapi dapat dengan mudah disesuaikan dengan distribusi lain dengan menggunakan wadah khusus dan journalctl/systemctl)

Jumlah waktu untuk sleep dan --since harus kurang dari pod-eviction-timeout cluster (5m secara default)

BTW - docker pause nginx-proxy pada node rancher worker membuat kubelet menghasilkan pesan error yang sama.

Solusi sementara untuk mereka yang menjalankan K8S di VMWare vSphere - nonaktifkan DRS untuk VM K8S, yang akan mencegah vSphere memindahkan VM di antara hypervisor sehingga menghilangkan pemutusan jaringan yang menyebabkan masalah pada Kubelet

Kami memiliki kabar baik tentang mitigasi masalah menggunakan fitur pemeriksaan kesehatan golang http2 yang baru: tidak ada masalah lagi. Sekarang, kami menerapkan "perbaikan" (pengaturan hardcode dari nilai dalam kode x/net dijual) di Prometheus, seluruh Kubernetes dan beberapa komponen internal, dengan mengamati:

  • tidak ada masalah federasi Prometheus lagi
  • kubelet terkadang masih melaporkan satu peristiwa "penggunaan koneksi tertutup" tetapi pulih dalam hitungan detik (kami menetapkan jendela pemeriksaan kesehatan http2 ~30 detik)
  • terkadang kami mengalami masalah dengan jam tangan kubectl -- juga hilang jika menggunakan kubectl
  • kami menjalankan testsuite E2E yang diperluas untuk memverifikasi integrasi kami secara teratur, dan mengamati batas waktu pengujian sporadis dan kerapuhan. Tebak apa? Pergi sekarang.

Selain itu, kami mendapatkan wawasan baru tentang cara memicu masalah. Saya dapat mengonfirmasi pengamatan @ vi7 mengenai migrasi langsung dengan yakin (kami dapat melacaknya), dan setidaknya dengan versi NSX yang kami jalankan juga, perubahan penyeimbang beban dapat memicu masalah seperti itu (kami memiliki tiket dengan VMware ke pastikan mereka mengirim paket reset di masa mendatang). Dan sangat mungkin banyak alasan lain menjatuhkan koneksi di antaranya, seperti tabel koneksi meluap.

Ini adalah masalah yang sangat menjengkelkan dan agak besar bagi beberapa pengguna Kubernetes (tergantung pada semacam "kerusakan" lapisan/jaringan IaaS, saya kira). Meskipun ada diskusi golang tentang mengekspos antarmuka untuk mengatur nilai dengan benar - menurut Anda apakah ada peluang untuk menggabungkan PR dengan mengatur nilai-nilai itu melalui refleksi (masih lebih baik daripada forking x/net, saya kira seperti yang kita lakukan sekarang) ? Kami baik-baik saja dengan memberikan kode (dan memvalidasi perbaikan, kami tidak dapat benar-benar mereproduksi, tetapi cukup sering mengamati untuk dapat mengonfirmasi apakah perbaikan berfungsi).

cc @liggitt

masalah jangka panjang (catatan untuk diri sendiri)

@JensErat terima kasih atas jawabannya.
Jika demikian, dapatkah masalah ini juga terjadi pada versi k8s(1.13, 1.15, ..) yang lebih lama?

Saya dapat mengonfirmasi untuk melihat masalah dengan Kubernetes v1.16.13
Kami tidak melihat masalah dengan Kubernetes v1.15.9

ketika saya memulihkan cluster kubenetes v1.16.14 dari etcd snapshot backup . kesalahan ini muncul di log kubelet.
terima kasih kepada @ik99999 . Saya me-restart kubelet kemudian kesalahan hilang

[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"

Kami menemui masalah yang sama pada 1.17.3, memulai ulang kubelet akan menyelesaikannya. Adakah solusi yang stabil untuk itu atau kapan ini harus diperbaiki?

v1.18.6 sama

@rxwang662001
Hal ini disebabkan oleh masalah golang hulu. Satu hal yang pasti adalah bahwa ini TIDAK AKAN diperbaiki di go 1.15.
Sementara itu, komunitas Kubernetes masih berjuang untuk bermigrasi ke 1,14 LOL.

Biasanya, go rilis setiap 6 bulan. Jika semuanya berjalan dengan baik, mungkin kita bisa melihat masalah ini diselesaikan oleh upstream di tahun depan, dan mungkin satu tahun lagi sampai kubernetes menyesuaikan perbaikannya !
(Hanya untuk bercanda. Jika Anda benar-benar ingin ini diperbaiki di tumpukan Anda sekarang. Retas h2Transport untuk mengaktifkan healthCheck terbukti berfungsi.

Sementara itu, komunitas Kubernetes masih berjuang untuk bermigrasi ke 1,14 LOL.

Sebenarnya, karena kerja keras dengan skalabilitas sig dan rilis sig untuk memenuhi syarat pada prarilis go1.15, Kubernetes 1.19 baru saja dirilis pada go1.15. Sepertinya ada pekerjaan yang sedang berlangsung untuk mengekspos opsi http/2 di go1.16, dan saya berharap kami akan menggunakannya segera setelah tersedia.

Sebenarnya, karena kerja keras dengan skalabilitas sig dan rilis sig untuk memenuhi syarat pada prarilis go1.15, Kubernetes 1.19 baru saja dirilis pada go1.15.

Ups. Maaf untuk lelucon yang canggung. Tidak terlalu memperhatikan rilis v1.19.
Sepertinya kita melewatkan go1.14 sepenuhnya di K8S? Wow. itu lompatan besar 👍

@povsister

Terima kasih telah berbagi solusi Anda. Bisakah Anda menambahkan detail lebih lanjut tentang bagaimana Anda membuatnya bekerja?

Untuk saat ini saya memodifikasi kode agar http2: perform connection health check diperkenalkan oleh golang/ net@0ba52f6 diaktifkan secara default.
Ini terbukti membantu dalam masalah ini. Tapi agak slow respon.

Perubahan kode apa yang Anda lakukan? Dan di mana, di file mana?

@KarthikRangaraju
Rujuk PR ini untuk mengaktifkan healthCheck saat menginisialisasi h2Transport,
atau Anda dapat melakukan refleksi/retas offset tidak aman untuk mengakses bidang yang tidak diekspor saat runtime.

Dan, jangan lupa untuk mengupdate golang/x/net sebelum melakukan hal tersebut.

Kami belum dapat mereproduksi masalah ini meskipun kami menghadapinya dari waktu ke waktu.

Karena kami tidak dapat mengidentifikasi akar penyebab gejala, kami memperbaiki gejalanya.

Solusi kami:

  • Script berikut berjalan setiap 1 jam. Ini berbicara dengan server kube-api melalui kubectl melalui file konfigurasi kube
    kubelet menggunakan (Dengan cara ini tidak ada eskalasi hak istimewa).
  • Menanyakan apakah master node thinks itu sendiri node NotReady. Jika ya, aktifkan kubelet restart dengan menjalankan perintah touch pada sebuah file
    yaitu watched oleh kubelet-watcher.service untuk perubahan sistem file dan restart kubelet sesuai dengan itu.
#!/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]#

Dengan Kubernetes 1.19.0 masalahnya masih ada, tetapi pesannya sedikit berbeda.
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)
Sekarang berisi "(mungkin coba lagi setelah tidur)" dalam pesan kesalahan.

Apakah mungkin untuk memitigasi ini sepenuhnya di kubernetes tanpa menunggu golang pemutakhiran? Misalnya, dapatkah client-go dibuat untuk menukar transportasi jika itu mengenai "penggunaan koneksi jaringan tertutup" atau sesuatu?

Atau, apakah masalah ini masih terjadi jika menggunakan HTTP 1.1, atau murni terkait HTTP 2? Jika HTTP 1.1 akan kebal dan tidak memiliki banyak kekurangan, itu akan menjadi solusi yang sangat sederhana untuk hanya mengatur GODEBUG=http2client=0 pada kubelet, kube-proxy, dan berbagai proses bidang kontrol, atau bahkan mengatur GODEBUG=http2server=0 pada proses apiserver untuk membuat perubahan universal.

Apakah kami pikir ini benar-benar akan mengurangi masalah ini dan tidak menyebabkan jebakan besar lainnya selain beberapa masalah kinerja karena peningkatan jumlah koneksi saat tidak melakukan multiplexing melalui HTTP2?

dapatkah client-go dibuat untuk menukar transportasi jika itu mengenai "penggunaan koneksi jaringan tertutup" atau sesuatu?

tidak terlalu pembedahan... transportasi saat ini dibagi untuk menghindari kelelahan pelabuhan sesaat dalam menghadapi penelepon yang berulang kali membangun klien baru

apakah masalah ini masih terjadi jika menggunakan HTTP 1.1, atau apakah ini murni terkait HTTP 2?

sejauh yang saya tahu, HTTP 1.1 dapat mengalami masalah yang sama karena koneksi idle kembali ke kumpulan keep-alive (dan memiliki lebih sedikit opsi untuk mendeteksi/menguranginya karena mekanisme pemeriksaan kesehatan ping tidak tersedia untuk itu)

Apakah ada solusi yang baik untuk proyek yang menggunakan klien? Bagaimana kami dapat mengidentifikasi kapan klien mati dan apa minimal yang perlu kami lakukan untuk memperbaikinya (terdengar seperti memulai kembali proses kami mungkin satu-satunya pilihan)?

Bagaimana kita bisa mengidentifikasi ketika klien sudah mati?

Ketika Anda mendapatkan kesalahan write tcp xxx use of closed network connection berulang kali untuk URL yang identik. Itu menandakan klien sudah meninggal. Kumpulan koneksi di dalam Transport telah men-cache koneksi tcp yang mati untuk Host:port yang diminta.

Apakah ada solusi yang baik untuk proyek yang menggunakan klien?

Sejauh yang saya tahu, membangun kembali http.Client dapat memperbaiki masalah ini tanpa memulai ulang seluruh aplikasi.

apa minimal yang perlu kita lakukan untuk memperbaikinya

Ini membutuhkan akses tingkat kode sumber ke proyek. Mungkin Anda dapat menggunakan mekanisme yang disebutkan di atas untuk mendeteksi klien mati dan membangun kembali klien baru bila diperlukan. Jika tidak ada yang menggunakan klien lama, itu akan menjadi sampah yang dikumpulkan.

Saya memiliki akses kode sumber ke proyek saya, tetapi kami menggunakan klien kubernetes. Saat kami melakukan jam tangan, tampaknya jam tangan tidak pernah mendeteksi jika koneksi TCP terputus seperti ini (dan karena jam tangan menangani transaksi HTTP, tidak ada kesalahan yang muncul di kode kami untuk ditangani).

Ya. Anda benar, http.Client tidak diekspos oleh klien kubernetes.
Saat ini tidak ada harapan bagi aplikasi tingkat atas untuk melakukan solusi seperti itu dengan sedikit biaya.
Jika klien kubernetes tidak menggunakan http.DefaultClient , itu dapat diperbaiki dengan membangun kembali seluruh Klien kubernetes.

Untuk permintaan menonton, itu semakin buruk. klien kubernetes tampaknya terus mencoba kembali permintaan dan tidak ada kesalahan yang muncul ke aplikasi atas. Saya tidak punya ide bagus tentang situasi seperti itu sekarang.

Solusi yang diusulkan di sini telah bekerja untuk kami selama beberapa minggu. Kami mengubahnya menjadi skrip python yang berjalan sebagai daemonset di semua cluster kami. Kami biasanya melihatnya mengambil tindakan sekali atau dua kali seminggu (secara otomatis memulai ulang kubelet) dan sebagai hasilnya kami tidak memiliki dampak negatif pada operasi cluster kami. Kami membuatnya variabel sehingga hanya me-restart kubelet jika melihat 2+ pesan dalam periode 5 menit. Kami melihat bahwa kadang-kadang kami dapat melihat satu pesan, dan itu tidak menjadi masalah. Ketika masalah terjadi, Anda akan melihat kesalahan use of closed network connection terus-menerus di log kubelet.

Silakan buat pullrequest dan kami akan menyelidiki masalah ini.

Pada satu kluster baremetal, saya melihat ini terjadi sekitar 2-4 kali setiap 24 jam. 1.17.12

itu terjadi ketika pod api-server restart, bahkan pada single node cluster . Koneksi ke apiserver terputus, jadi metode minimalisasi nomor kesalahan memecahkan masalah mengapa apiserver memulai ulang.

Saya menggunakan haproxy di depan master node, apakah menurut Anda ada cara untuk mencegahnya dengan beberapa konfigurasi LB?

@ shubb30 apakah Anda keberatan berbagi dengan saya solusi Anda?

Saya dapat mengonfirmasi bahwa apiserver saya TIDAK memulai ulang ketika saya mengalami masalah. Saya menggunakan daemonset dan trik shell untuk memantau entri log dan kemudian me-restart kubelet, ini telah bekerja dengan cukup baik tetapi saya melihatnya hanya sebagai solusi sementara.

Berikut adalah versi modifikasi dari apa yang telah bekerja dengan baik untuk kami sebagai solusi.

Hei kalian semua!

Apakah menurut kami backport ini dapat membantu?
https://github.com/golang/go/issues/40423

Kabar baik: golang/net master memiliki dukungan untuk mengonfigurasi transport http2, yang sekarang memungkinkan pengaturan batas waktu! https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2

Selesai.
PR dibuka untuk ditinjau.

Kabar baik lainnya: Kubernetes tidak menggunakan paket http2 dalam paket net/http standar, jadi kita tidak perlu menunggu rilis Go berikutnya. Kami dapat langsung menggunakan https://github.com/golang/net/commit/08b38378de702b893ee869b94b32f833e2933bd2 untuk memperbaiki masalah ini.

Diusulkan perbaikan di sini. https://github.com/kubernetes/kubernetes/pull/95898
Ini memperbarui ketergantungan ke versi yang diperlukan dan mengaktifkan pemeriksaan kesehatan Transportasi http2 secara default.
Ini akan membantu aplikasi yang menggunakan client-go untuk berkomunikasi dengan apiserver (misalnya: kubelet) menyingkirkan masalah "aplikasi hang saat menulis tcp xxx: penggunaan koneksi tertutup".

Jangan ragu untuk meninggalkan komentar apa pun.

Tampaknya #95898 yang disebutkan ditutup karena alasan yang tidak perlu kita diskusikan.

Apakah ada pembaruan lain sehubungan dengan masalah ini?

https://github.com/kubernetes/kubernetes/pull/95981 (ditautkan di atas) sedang dalam proses untuk menarik perbaikan http/2

Apakah masalah ini khusus untuk kubernetes versi 1.17.X ?

@krmayankk Tidak sepenuhnya yakin kapan tepatnya dimulai. Tapi setidaknya 1,17-1,19 memiliki masalah ini. #95980 seharusnya memperbaikinya (akan menjadi bagian dari rilis 1.20, belum berhasil menjadi beta kemarin)

@krmayankk Kami juga melihat masalah ini dengan v1.18.9 tetapi dipicu oleh versi Rancher yang bermasalah yang menyebabkan penggunaan jaringan yang sangat tinggi. Setelah memutar kembali ke versi lain tidak ada masalah yang diamati.

Saya mengalami masalah ini tetapi sekarang saya telah "memperbaikinya" di kluster hobi kecil saya menggunakan solusi dalam komentar di atas

Saya menulis buku pedoman kecil yang memungkinkan untuk menyebarkan solusi pada node sebagai unit dan pengatur waktu systemd, mungkin menyelamatkan orang lain dengan pengaturan serupa beberapa waktu

Apakah ada rencana untuk cherry-pick/backport https://github.com/kubernetes/kubernetes/pull/95981 dan https://github.com/kubernetes/kubernetes/issues/87615 ke 1.18 cabang rilis?

Apakah ada rencana untuk memilih cabang rilis #95981 hingga 1,17?

Komentar ini membahas backport ke rilis yang lebih lama: https://github.com/kubernetes/kubernetes/pull/95981#issuecomment -730561539

Saya pikir jawabannya adalah "itu sulit dan bisa merusak barang jadi mungkin tidak". Agak jawaban yang sama yang saya harapkan dari orang-orang yang menjalankan v1.17 ketika ditanya, jadi mengapa tidak memutakhirkan ke v1.20 untuk mendapatkan perbaikannya? :tertawa:

Mencadangkan ini ke setidaknya 1,19 akan sangat bagus karena itu akan membuat perbaikan tersedia relatif segera. Saya menduga beberapa orang akan menunda 1,20 karena penghentian Docker.

Mencadangkan ini ke setidaknya 1,19 akan sangat bagus karena itu akan membuat perbaikan tersedia relatif segera.

Itu sudah dilakukan.

Saya menduga beberapa orang akan menunda 1,20 karena penghentian Docker.

Tidak ada yang berubah di 1.20 sehubungan dengan buruh pelabuhan selain peringatan penghentian. Pada akhir periode penghentian, dukungan buruh pelabuhan akan dihapus.

mendapatkan kesalahan ini pada 1,20 pada raspbian 10. di mana seseorang bahkan mulai dengan mendapatkan perbaikan untuk semua ini? sepertinya biaya menjalankan cluster yang dikelola cloud jauh lebih hemat biaya daripada mencoba menjalankannya di cluster Anda sendiri

Untuk kejelasan saya sendiri, ini sepertinya harus diselesaikan dengan #95981, dan itu membuatnya menjadi 1,20 dan kembali porting ke 1,19?

95981 digabungkan ke 1,20, dan dipilih menjadi 1,19 di #96770.

/Menutup

@caesarxuchao : Menutup masalah ini.

Menanggapi hal ini :

95981 digabungkan ke 1,20, dan dipilih menjadi 1,19 di #96770.

/Menutup

Instruksi untuk berinteraksi dengan saya menggunakan komentar PR tersedia di sini . Jika Anda memiliki pertanyaan atau saran terkait dengan perilaku saya, silakan ajukan masalah pada repositori kubernetes/test-infra .

Apakah akan ada backport/cherry pick untuk v1.16, v1.17 atau atau v1.18?

@chilicat lihat https://github.com/kubernetes/kubernetes/pull/95981#issuecomment -730561539. Saya tidak berencana untuk memilihnya ke versi 1.18 atau yang lebih lama.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

Seb-Solon picture Seb-Solon  ·  3Komentar

rhohubbuild picture rhohubbuild  ·  3Komentar

cooligc picture cooligc  ·  3Komentar

mml picture mml  ·  3Komentar

montanaflynn picture montanaflynn  ·  3Komentar