Rumah >pembangunan bahagian belakang >Golang >Bagaimanakah Pengendali Kubernetes Mengendalikan Concurrency?

Bagaimanakah Pengendali Kubernetes Mengendalikan Concurrency?

Barbara Streisand
Barbara Streisandasal
2024-10-10 06:07:29324semak imbas

Asal disiarkan di blog saya

Secara lalai, pengendali yang dibina menggunakan Kubebuilder dan masa jalan pengawal memproses satu permintaan penyelarasan pada satu masa. Ini adalah tetapan yang munasabah, kerana lebih mudah bagi pembangun pengendali untuk memikirkan dan menyahpepijat logik dalam aplikasi mereka. Ia juga mengekang daya pemprosesan daripada pengawal kepada sumber teras Kubernetes seperti ectd dan pelayan API.

Tetapi bagaimana jika baris gilir kerja anda mula membuat sandaran dan purata masa penyesuaian meningkat disebabkan permintaan yang dibiarkan duduk dalam baris gilir, menunggu untuk diproses? Nasib baik bagi kami, struct Pengawal masa larian pengawal termasuk medan MaxConcurrentReconciles (seperti yang saya nyatakan sebelum ini dalam artikel Petua Kubebuilder saya). Pilihan ini membolehkan anda menetapkan bilangan gelung selaras serentak yang berjalan dalam satu pengawal. Jadi dengan nilai di atas 1, anda boleh menyelaraskan berbilang sumber Kubernetes secara serentak.

Awal perjalanan pengendali saya, satu soalan yang saya ada ialah bagaimana kami boleh menjamin bahawa sumber yang sama tidak diselaraskan pada masa yang sama oleh 2 atau lebih goroutine? Dengan MaxConcurrentReconciles ditetapkan di atas 1, ini boleh membawa kepada semua jenis keadaan perlumbaan dan tingkah laku yang tidak diingini, kerana keadaan objek di dalam gelung perdamaian boleh berubah melalui kesan sampingan daripada sumber luaran (gelung perdamaian berjalan dalam utas yang berbeza) .

Saya memikirkan perkara ini seketika, malah melaksanakan penyegerakan.Pendekatan berasaskan peta yang akan membolehkan goroutine memperoleh kunci untuk sumber tertentu (berdasarkan ruang nama/namanya).

Ternyata semua usaha ini adalah sia-sia, kerana saya baru-baru ini mengetahui (dalam saluran slack k8s) bahawa baris gilir kerja pengawal sudah menyertakan ciri ini! Walaupun dengan pelaksanaan yang lebih mudah.

Ini ialah cerita ringkas tentang cara baris gilir kerja pengawal k8s menjamin bahawa sumber unik diselaraskan secara berurutan. Jadi walaupun MaxConcurrentReconciles ditetapkan di atas 1, anda boleh yakin bahawa hanya satu fungsi penyesuaian yang bertindak pada mana-mana sumber pada satu masa.

klien-go/util

Controller-runtime menggunakan pustaka client-go/util/workqueue untuk melaksanakan baris gilir penyesuaian asasnya. Dalam fail doc.go pakej, ulasan menyatakan bahawa baris gilir kerja menyokong sifat ini:

  • Adil: item diproses mengikut susunan ia ditambahkan.
  • Kedekut: satu item tidak akan diproses beberapa kali serentak, dan jika item ditambah beberapa kali sebelum boleh diproses, ia hanya akan diproses sekali.
  • Berbilang pengguna dan pengeluar. Khususnya, item dibenarkan untuk dimasukkan semula dalam baris gilir semasa ia diproses.
  • Pemberitahuan penutupan.

Tunggu sebentar... Jawapan saya ada di sini dalam peluru kedua, sifat "Kedekut"! Menurut dokumen ini, baris gilir akan mengendalikan isu konkurensi ini secara automatik untuk saya, tanpa perlu menulis satu baris kod. Mari kita jalankan pelaksanaannya.

Bagaimanakah baris gilir kerja berfungsi?

Struktur giliran kerja mempunyai 3 kaedah utama, Tambah, Dapatkan dan Selesai. Di dalam pengawal, pemberi maklumat akan Menambahkan permintaan yang mendamaikan (nama ruang nama sumber k8s generik) pada baris gilir kerja. Gelung mendamaikan berjalan dalam goroutine berasingan kemudiannya Dapatkan permintaan seterusnya daripada baris gilir (menyekat jika ia kosong). Gelung akan melaksanakan apa sahaja logik tersuai yang ditulis dalam pengawal, dan kemudian pengawal akan memanggil Selesai pada baris gilir, menghantar permintaan pendamaian sebagai hujah. Ini akan memulakan proses sekali lagi dan gelung pendamaian akan memanggil Dapatkan untuk mendapatkan semula item kerja seterusnya.

Ini serupa dengan memproses mesej dalam RabbitMQ, di mana pekerja mengeluarkan item dari baris gilir, memprosesnya dan kemudian menghantar "Ack" kembali kepada broker mesej yang menunjukkan bahawa pemprosesan telah selesai dan selamat untuk mengalih keluar item daripada beratur.

Namun, saya mempunyai pengendali yang sedang menjalankan pengeluaran yang memperkasakan infrastruktur QuestDB Cloud dan ingin memastikan baris gilir kerja berfungsi seperti yang diiklankan. Jadi a menulis ujian pantas untuk mengesahkan kelakuannya.

Ujian sikit

Berikut ialah ujian mudah yang mengesahkan sifat "Kedekut":

package main_test

import (
    "testing"

    "github.com/stretchr/testify/assert"

    "k8s.io/client-go/util/workqueue"
)

func TestWorkqueueStingyProperty(t *testing.T) {

    type Request int

    // Create a new workqueue and add a request
    wq := workqueue.New()
    wq.Add(Request(1))
    assert.Equal(t, wq.Len(), 1)

    // Subsequent adds of an identical object
    // should still result in a single queued one
    wq.Add(Request(1))
    wq.Add(Request(1))
    assert.Equal(t, wq.Len(), 1)

    // Getting the object should remove it from the queue
    // At this point, the controller is processing the request
    obj, _ := wq.Get()
    req := obj.(Request)
    assert.Equal(t, wq.Len(), 0)

    // But re-adding an identical request before it is marked as "Done"
    // should be a no-op, since we don't want to process it simultaneously
    // with the first one
    wq.Add(Request(1))
    assert.Equal(t, wq.Len(), 0)

    // Once the original request is marked as Done, the second
    // instance of the object will be now available for processing
    wq.Done(req)
    assert.Equal(t, wq.Len(), 1)

    // And since it is available for processing, it will be
    // returned by a Get call
    wq.Get()
    assert.Equal(t, wq.Len(), 0)
}

Memandangkan baris gilir kerja menggunakan mutex di bawah hud, tingkah laku ini selamat untuk benang. Jadi, walaupun saya menulis lebih banyak ujian yang menggunakan berbilang goroutin secara serentak membaca dan menulis daripada baris gilir pada kelajuan tinggi dalam usaha untuk memecahkannya, gelagat sebenar baris kerja akan sama seperti ujian satu benang kami.

Semuanya tidak hilang

How do Kubernetes Operators Handle Concurrency?

Kubernetes 표준 라이브러리에는 이와 같은 작은 보석이 많이 숨겨져 있으며 그 중 일부는 그다지 눈에 띄지 않는 위치(예: go 클라이언트 패키지에 있는 컨트롤러 런타임 작업 대기열)에 있습니다. 이 발견과 과거에 제가 이룩한 다른 유사한 발견에도 불구하고 저는 여전히 이러한 문제를 해결하려는 이전의 시도가 완전한 시간 낭비가 아니라고 생각합니다. 이는 분산 시스템 컴퓨팅의 근본적인 문제에 대해 비판적으로 생각하게 만들고 내부에서 무슨 일이 일어나고 있는지 더 많이 이해하도록 도와줍니다. 그래서 "Kubernetes가 해냈다"는 사실을 알게 되었을 때 코드베이스를 단순화하고 불필요한 단위 테스트를 일부 제거할 수 있다는 사실에 안도감을 느꼈습니다.

Atas ialah kandungan terperinci Bagaimanakah Pengendali Kubernetes Mengendalikan Concurrency?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn