حالت تاریک
فصل ۱۶ — گسترش Kubernetes
از ابتدا روشن بود Kubernetes بیش از مجموعهٔ اصلی APIهایش خواهد بود؛ وقتی برنامهای در cluster orchestrate شد، ابزارها و utilityهای بیشمار دیگری هستند که میتوانند بهعنوان اشیاء API در cluster Kubernetes نمایش داده و deploy شوند. چالش این بود چگونه این انفجار اشیاء و use caseها را بپذیریم بدون APIای که بیحد و حصر گسترش یابد.
برای حل این تنش بین use caseهای گسترشیافته و API sprawl، تلاش قابل توجهی برای extensible کردن API Kubernetes انجام شد. این extensibility یعنی اپراتورهای cluster میتوانند clusterهایشان را با اجزای اضافی مناسب نیازشان سفارشی کنند. این extensibility به مردم امکان میدهد خودشان clusterها را augment کنند، add-onهای cluster توسعهیافته توسط جامعه را مصرف کنند و حتی extensionهایی بسازند که در اکوسیستم plug-inهای cluster bundle و فروخته شوند. extensibility همچنین الگوهای کاملاً جدیدی برای مدیریت سیستمها مثل الگوی operator به وجود آورده است.
صرفنظر از اینکه extensionهای خودتان را میسازید یا operatorها را از اکوسیستم مصرف میکنید، درک نحوهٔ گسترش API server Kubernetes و نحوهٔ ساخت و تحویل extensionها جزء کلیدی برای آزاد کردن قدرت کامل Kubernetes و اکوسیستمش است. با ساخت ابزارها و پلتفرمهای پیشرفتهتر و بیشتر روی Kubernetes با این مکانیزمهای extensibility، دانش عملی نحوهٔ کار آنها برای درک نحوهٔ ساخت برنامهها در cluster Kubernetes مدرن حیاتی است.
گسترش Kubernetes به چه معناست
بهطور کلی، extensionهای API server Kubernetes یا قابلیت جدید به cluster اضافه میکنند یا راههایی که کاربران با clusterهایشان تعامل دارند را محدود و تنظیم میکنند. اکوسیستم غنی plug-inهایی وجود دارد که مدیران cluster میتوانند برای افزودن سرویسها و قابلیتهای اضافی به clusterهایشان استفاده کنند. شایان ذکر است که گسترش cluster کار بسیار پرامتیازی است. قابلیتی نیست که باید به کاربران یا کد دلخواه داده شود، چون برای گسترش cluster امتیازات مدیر cluster لازم است. حتی مدیران cluster باید هنگام نصب ابزارهای third-party مراقب و با دقت عمل کنند. برخی extensionها، مثل admission controllerها، میتوانند برای مشاهدهٔ همهٔ اشیائی که در cluster ساخته میشوند استفاده شوند و بهراحتی vector برای دزدیدن secretها یا اجرای کد مخرب باشند. علاوه بر این، گسترش cluster آن را با Kubernetes استاندارد متفاوت میکند. هنگام اجرا روی چند cluster، ساخت ابزار برای حفظ یکنواختی تجربه در clusterها بسیار ارزشمند است و این شامل extensionهای نصبشده هم میشود.
نقاط Extensibility
راههای زیادی برای گسترش Kubernetes وجود دارد، از CustomResourceDefinitionها تا plug-inهای Container Network Interface (CNI). این فصل روی extensionهای API server از طریق افزودن انواع resource جدید یا admission controllerها به درخواستهای API تمرکز دارد. extensionهای CNI/CSI/CRI (Container Network Interface/Container Storage Interface/Container Runtime Interface) را پوشش نمیدهیم، چون بیشتر توسط ارائهدهندگان cluster Kubernetes استفاده میشوند تا کاربران نهایی Kubernetes که این کتاب برای آنها نوشته شده.
علاوه بر admission controllerها و API extensionها، در واقع راههای زیادی برای «گسترش» cluster بدون تغییر API server وجود دارد. اینها شامل DaemonSetهایی است که logging و monitoring خودکار نصب میکنند، ابزارهایی که سرویسهایتان را برای آسیبپذیری cross-site scripting (XSS) اسکن میکنند و موارد دیگر. اما قبل از شروع گسترش cluster خودتان، ارزش دارد چشمانداز چیزهای ممکن در محدودهٔ APIهای موجود Kubernetes را در نظر بگیرید.
برای درک نقش admission controllerها و CustomResourceDefinitionها، درک جریان درخواستها از طریق API server Kubernetes بسیار مفید است که در شکل ۱۶-۱ نشان داده شده.
شکل ۱۶-۱. جریان درخواست API server
admission controllerها قبل از نوشته شدن شیء API در backing storage فراخوانی میشوند. admission controllerها میتوانند درخواستهای API را رد یا تغییر دهند. چندین admission controller در API server Kubernetes داخلی وجود دارد؛ مثلاً limit range admission controller که limitهای پیشفرض برای Podهای بدون آنها تنظیم میکند. بسیاری سیستمهای دیگر از admission controllerهای سفارشی برای auto-inject کردن sidecar containerها به همهٔ Podهای ساختهشده در سیستم برای تجربههای «خودکار» استفاده میکنند.
شکل دیگر extension، که میتواند همراه admission controllerها هم استفاده شود، custom resourceها است. با custom resourceها، اشیاء API کاملاً جدید به سطح API Kubernetes اضافه میشوند. این اشیاء API جدید میتوانند به namespaceها اضافه شوند، مشمول RBAC هستند و با ابزارهای موجود مثل kubectl و همچنین از طریق API Kubernetes قابل دسترسیاند.
بخشهای زیر این نقاط extension Kubernetes را با جزئیات بیشتر توضیح میدهند و هم use case و هم مثالهای عملی نحوهٔ گسترش cluster را ارائه میکنند.
اولین کاری که برای ساخت custom resource انجام میدهید ساخت CustomResourceDefinition است. این شیء در واقع یک meta-resource است؛ یعنی resourceای که تعریف resource دیگری است.
بهعنوان مثال عملی، تعریف resource جدید برای نمایش load testها در cluster را در نظر بگیرید. وقتی resource LoadTest جدید ساخته میشود، load test در cluster Kubernetes شما spin up میشود و ترافیک را به یک Service هدایت میکند.
اولین گام ساخت این resource جدید، تعریف آن از طریق CustomResourceDefinition است. تعریف نمونه به شکل زیر است:
yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: loadtests.beta.kuar.com
spec:
group: beta.kuar.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: loadtests
singular: loadtest
kind: LoadTest
shortNames:
- ltمیبینید این شیء Kubernetes مثل هر شیء دیگری است. subobject metadata دارد و در آن subobject resource نامگذاری شده. اما در مورد custom resourceها، نام خاص است. باید فرمت زیر را داشته باشد: <resource-plural>.<api-group>. دلیل این است اطمینان از یکتایی هر تعریف resource در cluster، چون نام هر CustomResourceDefinition باید با این الگو مطابقت داشته باشد و هیچ دو شیئی در cluster نمیتوانند نام یکسان داشته باشند. بنابراین تضمین میشود هیچ دو CustomResourceDefinitionی همان resource را تعریف نمیکنند.
علاوه بر metadata، CustomResourceDefinition subobject spec دارد. جایی که خود resource تعریف میشود. در آن شیء spec، فیلد apigroup گروه API برای resource را میدهد. همانطور که قبلاً گفته شد، باید با پسوند نام CustomResourceDefinition مطابقت داشته باشد. علاوه بر این، لیستی از versionها برای resource وجود دارد. علاوه بر نام version (مثلاً v1، v2 و غیره)، فیلدهایی هست که نشان میدهد آیا آن version توسط API server سرو میشود و کدام version برای ذخیرهٔ داده در backing storage API server استفاده میشود. فیلد storage باید برای تنها یک version از resource true باشد. همچنین فیلد scope برای نشان دادن namespaced بودن یا نبودن resource (پیشفرض namespaced) و فیلد names برای تعریف مقادیر singular، plural و kind برای resource وجود دارد. همچنین امکان تعریف «short name»های راحتی برای resource برای استفاده در kubectl و جاهای دیگر را میدهد.
با این تعریف، میتوانید resource را در API server Kubernetes بسازید. اما ابتدا، برای نشان دادن ماهیت واقعی انواع resource پویا، سعی کنید resource loadtests را با kubectl فهرست کنید:
$ kubectl get loadtestsمیبینید که فعلاً چنین resourceای تعریف نشده.
حالا با loadtest-resource.yaml این resource را بسازید:
$ kubectl create -f loadtest-resource.yamlسپس دوباره resource loadtests را بگیرید:
$ kubectl get loadtestsاین بار میبینید نوع resource LoadTest تعریف شده، اگرچه هنوز نمونهای از این نوع resource نیست.
بیایید با ساخت resource LoadTest جدید این را تغییر دهیم.
مثل همهٔ اشیاء API داخلی Kubernetes، میتوانید از YAML یا JSON برای تعریف custom resource (در این مورد LoadTest) استفاده کنید. تعریف زیر را ببینید:
yaml
apiVersion: beta.kuar.com/v1
kind: LoadTest
metadata:
name: my-loadtest
spec:
service: my-service
scheme: https
requestsPerSecond: 1000
paths:
- /index.html
- /login.html
- /shares/my-shares/نکتهای که متوجه میشوید این است که هرگز schema برای custom resource در CustomResourceDefinition تعریف نکردیم. در واقع امکان ارائهٔ مشخصات OpenAPI برای custom resource وجود دارد، اما این پیچیدگی برای انواع resource ساده معمولاً ارزشش را ندارد. اگر validation میخواهید، میتوانید validating admission controller ثبت کنید، همانطور که در بخشهای بعدی توضیح داده میشود.
حالا میتوانید از این فایل loadtest.yaml برای ساخت resource مثل هر نوع داخلی استفاده کنید:
$ kubectl create -f loadtest.yamlحالا وقتی resource loadtests را فهرست کنید، resource تازهساختهٔ خود را میبینید:
$ kubectl get loadtestsاین شاید هیجانانگیز باشد، اما هنوز واقعاً کاری انجام نمیدهد. البته میتوانید از این API ساده CRUD (Create/Read/Update/Delete) برای دستکاری دادهٔ اشیاء LoadTest استفاده کنید، اما هیچ load test واقعی در پاسخ به این API جدید تعریفشده ساخته نمیشود.
دلیلش این است که controllerای در cluster برای واکنش و اقدام هنگام تعریف شیء LoadTest وجود ندارد. custom resource LoadTest فقط نیمی از infrastructure لازم برای افزودن LoadTestها به cluster ماست. دیگری قطعه کدی است که بهطور مداوم custom resourceها را monitor میکند و LoadTestها را در صورت لزوم میسازد، تغییر میدهد یا حذف میکند.
مثل کاربر API، controller با API server تعامل دارد تا LoadTestها را فهرست کند و هر تغییری را watch کند. این تعامل بین controller و API server در شکل ۱۶-۲ نشان داده شده.
شکل ۱۶-۲. تعاملات CustomResourceDefinition
کد چنین controllerای میتواند از ساده تا پیچیده باشد. سادهترین controllerها حلقه for اجرا میکنند و مکرراً برای اشیاء custom جدید poll میکنند و سپس اقداماتی برای ساخت یا حذف resourceهایی که آن اشیاء custom را پیاده میکنند انجام میدهند (مثلاً Podهای worker LoadTest).
با این حال، این رویکرد مبتنی بر polling ناکارآمد است: دورهٔ حلقه polling تأخیر غیرضروری اضافه میکند و سربار polling ممکن است بار غیرضروری روی API server اضافه کند. رویکرد کارآمدتر استفاده از watch API روی API server است که جریانی از بهروزرسانیها هنگام وقوع فراهم میکند و هم تأخیر و هم سربار polling را حذف میکند. با این حال، استفادهٔ صحیح از این API به روش بدون باگ پیچیده است. در نتیجه، اگر میخواهید از watch استفاده کنید، بهشدت توصیه میشود از مکانیزم well-supported مثل الگوی Informer در کتابخانه client-go استفاده کنید.
حالا که custom resource ساختیم و آن را از طریق controller پیاده کردیم، عملکرد پایهٔ resource جدید در cluster را داریم. با این حال، بخشهای زیادی از آنچه به معنای resource کارآمد است کم است. دو مهمترین validation و defaulting هستند. validation فرآیند اطمینان از این است که اشیاء LoadTest ارسالشده به API server خوشفرم هستند و میتوانند برای ساخت load test استفاده شوند، در حالی که defaulting استفاده از resourceهایمان را با ارائهٔ مقادیر خودکار و پرکاربرد بهصورت پیشفرض آسانتر میکند. حالا افزودن این قابلیتها به custom resource را پوشش میدهیم.
همانطور که قبلاً گفته شد، یک گزینه برای افزودن validation از طریق مشخصات OpenAPI برای اشیاء ماست. این برای validation پایهٔ وجود فیلدهای الزامی یا نبود فیلدهای ناشناخته مفید است. آموزش کامل OpenAPI خارج از محدودهٔ این کتاب است، اما منابع زیادی آنلاین وجود دارد، از جمله مشخصات کامل API Kubernetes.
بهطور کلی، schema API برای validation اشیاء API کافی نیست. مثلاً در مثال loadtests ممکن است بخواهیم اعتبارسنجی کنیم شیء LoadTest scheme معتبر دارد (مثلاً http یا https) یا requestsPerSecond عدد مثبت غیرصفر است.
برای دستیابی به این، از validating admission controller استفاده میکنیم. همانطور که قبلاً بحث شد، admission controllerها درخواستها به API server را قبل از پردازش intercept میکنند و میتوانند درخواستها را در حین عبور رد یا تغییر دهند. admission controllerها میتوانند از طریق سیستم dynamic admission control به cluster اضافه شوند. dynamic admission controller یک برنامه HTTP ساده است. API server از طریق شیء Service Kubernetes یا URL دلخواه به admission controller متصل میشود. این یعنی admission controllerها اختیاراً میتوانند خارج cluster اجرا شوند — مثلاً در ارائه Function-as-a-Service ارائهدهنده cloud مثل Azure Functions یا AWS Lambda.
برای نصب validating admission controller ما، باید آن را بهعنوان ValidatingWebhookConfiguration Kubernetes مشخص کنیم. این شیء endpointای که admission controller اجرا میشود و همچنین resource (در این مورد LoadTest) و action (در این مورد CREATE) که admission controller باید اجرا شود را مشخص میکند. تعریف کامل validating admission controller در کد زیر قابل مشاهده است:
yaml
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: kuar-validator
webhooks:
- name: validator.kuar.com
rules:
- apiGroups:
- "beta.kuar.com"
apiVersions:
- v1
operations:
- CREATE
resources:
- loadtests
clientConfig:
# آدرس IP مناسب برای webhook خود را جایگزین کنید
url: https://192.168.1.233:8080
# این باید گواهی CA بهصورت base64-encoded برای cluster شما باشد،
# میتوانید آن را در فایل ${KUBECONFIG} پیدا کنید
caBundle: REPLACEMEخوشبختانه برای امنیت، اما متأسفانه برای پیچیدگی، webhookهایی که API server Kubernetes به آنها دسترسی دارد فقط از طریق HTTPS قابل دسترسیاند. این یعنی باید گواهی برای سرو webhook تولید کنیم. آسانترین راه استفاده از قابلیت cluster برای تولید گواهیهای جدید با certificate authority (CA) خودش است.
ابتدا به private key و certificate signing request (CSR) نیاز داریم. برنامه Go سادهای که اینها را تولید میکند:
go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"net/url"
"os"
)
func main() {
host := os.Args[1]
name := "server"
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
keyDer := x509.MarshalPKCS1PrivateKey(key)
keyBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: keyDer,
}
keyFile, err := os.Create(name + ".key")
if err != nil {
panic(err)
}
pem.Encode(keyFile, &keyBlock)
keyFile.Close()
commonName := "myuser"
emailAddress := "someone@myco.com"
org := "My Co, Inc."
orgUnit := "Widget Farmers"
city := "Seattle"
state := "WA"
country := "US"
subject := pkix.Name{
CommonName: commonName,
Country: []string{country},
Locality: []string{city},
Organization: []string{org},
OrganizationalUnit: []string{orgUnit},
Province: []string{state},
}
uri, err := url.ParseRequestURI(host)
if err != nil {
panic(err)
}
asn1, err := asn1.Marshal(subject.ToRDNSequence())
if err != nil {
panic(err)
}
csr := x509.CertificateRequest{
RawSubject: asn1,
EmailAddresses: []string{emailAddress},
SignatureAlgorithm: x509.SHA256WithRSA,
URIs: []*url.URL{uri},
}
bytes, err := x509.CreateCertificateRequest(rand.Reader, &csr, key)
if err != nil {
panic(err)
}
csrFile, err := os.Create(name + ".csr")
if err != nil {
panic(err)
}
pem.Encode(csrFile, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: bytes})
csrFile.Close()
}میتوانید این برنامه را با دستور زیر اجرا کنید:
$ go run csr-gen.go <URL-for-webook>و دو فایل server.csr و server-key.pem تولید میکند.
سپس میتوانید certificate signing request برای API server Kubernetes با YAML زیر بسازید:
yaml
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: validating-controller.default
spec:
groups:
- system:authenticated
request: REPLACEME
usages:
usages:
- digital signature
- key encipherment
- key agreement
- server authبرای فیلد request مقدار REPLACEME است؛ این باید با certificate signing request بهصورت base64-encoded تولیدشده در کد قبلی جایگزین شود:
$ perl -pi -e s/REPLACEME/$(base64 server.csr | tr -d '\n')/ \
admission-controller-csr.yamlحالا که certificate signing request آماده است، میتوانید آن را به API server بفرستید تا گواهی بگیرید:
$ kubectl create -f admission-controller-csr.yamlسپس باید آن درخواست را تأیید کنید:
$ kubectl certificate approve validating-controller.defaultوقتی تأیید شد، میتوانید گواهی جدید را دانلود کنید:
$ kubectl get csr validating-controller.default -o json | \
jq -r .status.certificate | base64 -d > server.crtبا گواهی، سرانجام آمادهٔ ساخت admission controller مبتنی بر SSL هستید (آه!). وقتی کد admission controller درخواستی دریافت میکند، شامل شیئی از نوع AdmissionReview است که metadata درخواست و همچنین بدنهٔ خود درخواست را دارد. در validating admission controller ما فقط برای یک نوع resource و یک action (CREATE) ثبت کردهایم، پس نیازی به بررسی metadata درخواست نداریم. در عوض، مستقیماً به خود resource میرویم و اعتبارسنجی میکنیم requestsPerSecond مثبت است و scheme URL معتبر است. اگر نباشند، بدنه JSONای برمیگردانیم که درخواست را disallow میکند.
پیادهسازی admission controller برای defaulting مشابه گامهای توصیفشده است، اما بهجای ValidatingWebhookConfiguration از MutatingWebhookConfiguration استفاده میکنید و باید شیء JSONPatch برای mutate کردن شیء درخواست قبل از ذخیره ارائه دهید.
قطعه TypeScript زیر را میتوانید به validating admission controller اضافه کنید تا defaulting اضافه شود. اگر فیلد paths در loadtest طول صفر دارد، یک path برای /index.html اضافه کنید:
typescript
if (needsPatch(loadtest)) {
const patch = [
{ 'op': 'add', 'path': '/spec/paths', 'value': ['/index.html'] },
]
response['patch'] = Buffer.from(JSON.stringify(patch))
.toString('base64');
response['patchType'] = 'JSONPatch';
}سپس میتوانید این webhook را بهعنوان MutatingWebhookConfiguration ثبت کنید با ساده تغییر فیلد kind در شیء YAML و ذخیره فایل بهعنوان mutating-controller.yaml. سپس controller را با اجرای دستور زیر بسازید:
$ kubectl create -f mutating-controller.yamlدر این نقطه مثال کاملی از نحوهٔ گسترش API server Kubernetes با custom resourceها و admission controllerها دیدهاید. بخش بعدی برخی الگوهای کلی برای extensionهای مختلف را توضیح میدهد.
الگوها برای Custom Resourceها
همهٔ custom resourceها یکسان نیستند. دلایل مختلفی برای گسترش سطح API Kubernetes وجود دارد و بخشهای زیر برخی الگوهای کلی که شاید بخواهید در نظر بگیرید را بحث میکنند.
فقط داده
سادهترین الگو برای API extension مفهوم «فقط داده» است. در این الگو، صرفاً از API server برای ذخیره و بازیابی اطلاعات برای برنامهٔ خود استفاده میکنید. مهم است توجه کنید نباید از API server Kubernetes برای ذخیرهٔ دادهٔ برنامه استفاده کنید. API server Kubernetes برای key/value store برنامهٔ شما طراحی نشده؛ در عوض، API extensionها باید اشیاء control یا configuration باشند که به مدیریت deployment یا runtime برنامهٔ شما کمک میکنند. use case نمونه برای الگوی «فقط داده» ممکن است پیکربندی canary deploymentهای برنامه باشد — مثلاً هدایت ۱۰٪ همهٔ ترافیک به backend آزمایشی. در حالی که در تئوری چنین اطلاعات پیکربندی را میتوان در ConfigMap هم ذخیره کرد، ConfigMapها اساساً untyped هستند و گاهی استفاده از شیء API extension با type قویتر وضوح و سهولت استفاده را فراهم میکند.
extensionهایی که فقط دادهاند به controller متناظر برای فعالسازی نیاز ندارند، اما ممکن است validating یا mutating admission controller داشته باشند تا خوشفرم بودن آنها تضمین شود. مثلاً در use case canary، controller validating ممکن است اطمینان دهد همهٔ درصدها در شیء canary جمعاً ۱۰۰٪ شوند.
Compilerها
الگوی کمی پیچیدهتر «compiler» یا «abstraction» است. در این الگو شیء API extension انتزاع سطح بالاتری را نمایش میدهد که به ترکیبی از اشیاء Kubernetes سطح پایینتر «compile» میشود. extension LoadTest در مثال قبلی نمونهٔ این الگوی abstraction compiler است. کاربر extension را بهعنوان مفهوم سطح بالا مصرف میکند، در این مورد loadtest، اما به وجود میآید با deploy شدن بهعنوان مجموعهای از Podها و Serviceهای Kubernetes. برای دستیابی به این، abstraction compileشده به controller APIای نیاز دارد که جایی در cluster اجرا شود تا LoadTestهای فعلی را watch کند و نمایش «compileشده» را بسازد (و بههمینترتیب نمایشهایی که دیگر وجود ندارند را حذف کند). برخلاف الگوی operator که بعد توضیح داده میشود، با این حال، برای abstractionهای compileشده نگهداری سلامت online نیست؛ به اشیاء سطح پایینتر (مثلاً Podها) واگذار میشود.
Operatorها
در حالی که extensionهای compiler انتزاعهای آسانالاستفاده فراهم میکنند، extensionهایی که از الگوی «operator» استفاده میکنند مدیریت online و proactive resourceهای ساختهشده توسط extensionها را فراهم میکنند. این extensionها احتمالاً انتزاع سطح بالاتری (مثلاً پایگاه داده) فراهم میکنند که به نمایش سطح پایینتر compile میشود، اما همچنین قابلیت online مثل snapshot backup از پایگاه داده یا اعلان upgrade وقتی نسخهٔ جدید نرمافزار موجود است ارائه میدهند. برای دستیابی به این، controller نه تنها API extension را monitor میکند تا در صورت لزوم چیزها را اضافه یا حذف کند، بلکه وضعیت running برنامهٔ ارائهشده توسط extension (مثلاً پایگاه داده) را هم monitor میکند و اقداماتی برای رفع پایگاهدادههای unhealthy، گرفتن snapshot یا restore از snapshot در صورت خرابی انجام میدهد. Operatorها پیچیدهترین الگو برای API extension Kubernetes هستند، اما همچنین قدرتمندتریناند و به کاربران دسترسی آسان به انتزاعهای «خودران» میدهند که نه تنها مسئول deployment بلکه health checking و repair هم هستند.
شروع کار
شروع گسترش API Kubernetes میتواند تجربهای دلهرهآور و خستهکننده باشد. خوشبختانه کد زیادی برای کمک وجود دارد. پروژه Kubebuilder کتابخانهای از کد دارد که برای ساخت آسان API extensionهای قابل اعتماد Kubernetes در نظر گرفته شده. منبع عالی برای bootstrap کردن extension شماست.
خلاصه
یکی از «ابرقدرتهای» بزرگ Kubernetes اکوسیستمش است و یکی از مهمترین چیزهایی که این اکوسیستم را تقویت میکند extensibility API Kubernetes است. چه extensionهای خودتان را برای سفارشیسازی cluster طراحی کنید یا extensionهای آماده را بهعنوان utility، سرویس cluster یا operator مصرف کنید، API extensionها کلید ساختن cluster به سلیقهٔ خودتان و ساخت محیط مناسب برای توسعهٔ سریع برنامههای قابل اعتماد هستند.