Kubeadm: استخدام شهادات خدمة kubelet الموقعة

تم إنشاؤها على ٩ نوفمبر ٢٠١٨  ·  38تعليقات  ·  مصدر: kubernetes/kubeadm

هل هذا تقرير خطأ أم طلب ميزة؟

/ نوع الخطأ

فتح الجانب kubeadm لهذه المشكلة على خادم المقاييس

إصدارات

$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.1", GitCommit:"4ed3216f3ec431b140b1d899130a69fc671678f4", GitTreeState:"clean", BuildDate:"2018-10-05T16:43:08Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}

البيئة :

  • إصدار Kubernetes (استخدم kubectl version ):
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.1", GitCommit:"4ed3216f3ec431b140b1d899130a69fc671678f4", GitTreeState:"clean", BuildDate:"2018-10-05T16:46:06Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.1", GitCommit:"4ed3216f3ec431b140b1d899130a69fc671678f4", GitTreeState:"clean", BuildDate:"2018-10-05T16:36:14Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}
  • مزود السحابة أو تكوين الأجهزة :
    أي
  • نظام التشغيل (على سبيل المثال من / etc / os-release):
    أي
  • Kernel (على سبيل المثال uname -a ):
$ uname -a
Linux ip-172-31-1-118 4.15.0-1023-aws #23-Ubuntu SMP Mon Sep 24 16:31:06 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
  • آخرون :

ماذا حدث؟

يُنشئ kubeadm شهادات أقل من /var/lib/kubelet/pki/kubelet.* موقعة مع مرجع مصدق مختلف عن الشهادة الأقل من /etc/kubernetes/pki/ca.pem

ماذا توقعت أن يحدث؟

نتيجةً لذلك ، لا يمكن لبعض التطبيقات مثل خادم المقاييس جمع الإحصائيات من kubelet المحمي لأن kubelet لديه شهادات موقعة من قبل CA مختلف عن سيد (ق) K8s

عينة الخطأ:

E1108 23:49:32.090084       1 manager.go:102] unable to fully collect metrics: [unable to fully scrape metrics from source kubelet_summary:ip-x-x-x-x: unable to fetch metrics from Kubelet ip-x-x-x-x (ip-x-x-x-x): Get https://ip-x-x-x-x:10250/stats/summary/: x509: certificate signed by unknown authority, unable to fully scrape metrics from source kubelet_summary:ip-x-x-x-x: unable to fetch metrics from Kubelet ip-x-x-x-x (ip-x-x-x-x): Get https://ip-x-x-x-x:10250/stats/summary/: x509: certificate is valid for x.x.x.x not ip-x-x-x-x]

كيف يتم إعادة إنتاجه (بأقل قدر ممكن من الدقة والدقة)؟

قم بتثبيت خادم المقاييس عند التشغيل:

سجلات نظام kubectl $ kube

أي شيء آخر نحن بحاجة إلى معرفته؟

بعض المعلومات الأساسية هنا

هناك أيضًا خطوات هناك اتبعتها لإصلاح المشكلة.


تحرير: neolit123

تكمن المشكلة هنا في أن شهادة العرض موقعة ذاتيًا بشكل افتراضي:
راجع https://github.com/kubernetes/website/pull/27071 لتحديث الوثائق.

aresecurity help wanted kinbug kinfeature lifecyclfrozen prioritimportant-longterm

التعليق الأكثر فائدة

لنلخص المشكلة:

كما هو موضح بواسطة anitgandhi :
https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -454572577

مشكلة kubeadm هنا هي أننا لا نمرر اثنين من الأعلام إلى kubelet:

--tls-cert-file=<some-path>/kubelet.crt
--tls-private-key-file=<some-path>/kubelet.key

بدون هذه العلامات ، يتم تعيين kubelet افتراضيًا للتوقيع الذاتي لشهادة الخدمة عند تشغيله لأول مرة ، والتي يمكن التحقق منها باستخدام:

sudo openssl verify -verbose -CAfile /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.crt

باستخدام شهادة موقعة ذاتيًا بدلاً من الشهادة الموقعة من قبل مجموعة CA ( /etc/kubernetes/ca.crt ) ، لا يمكن لعمليات النشر مثل خادم المقاييس أن تتخلص من kubelet ، لأن شهادة SAN الموقعة ذاتيًا ستتضمن DNS:hostname .

الحلول الممكنة:
أ) تنفيذ الغناء لزوج جديد من kubelet.crt/key ، من الناحية المثالية أقل من /var/lib/kubelet/pki وتعيين أعلام kubelet الإضافية --tls-cert-file ، --tls-private-key-file .

ب) المستند يعني تمكين هذا عند الطلب بشكل مشابه لكيفية قيام @ raravena80 بذلك هنا: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
باستثناء احتمال استخدام أوامر Kubernetes CSRs / kubeadm.

ج) كما علق alexbrand

إذا كان ذلك ممكنًا ، أعتقد أنه يجب علينا استخدام تسهيلات TLS bootstrapping المضمنة في kubelet لطلب / تدوير شهادات الخدمة.

د) ؟

@ kubernetes / sig-الكتلة-دورة حياة
بالنسبة لي يبدو هذا في المسافة بين الخطأ / الميزة.

انظر أيضا:
https://github.com/kubernetes/community/pull/602/files

ال 38 كومينتر

@ raravena80 لست على علم بأي شهادة تم إنشاؤها بواسطة kubeadm تحت /var/lib/kubelet/pki/ .. هل يمكنك التفضل بتقديم مزيد من المعلومات؟ على سبيل المثال ملفات التكوين kubeadm ، خطوات إنشاء الكتلة

fabriziopandini لست متأكدًا تمامًا مما إذا كانت الشهادات قد تم إنشاؤها بواسطة kubeadm ، ولكن الإجراء العام موصوف هنا .

هذا ما يبدو عليه محتوى الدليل:

root@ip-172-31-1-118:/var/lib/kubelet/pki# pwd
/var/lib/kubelet/pki
root@ip-172-31-1-118:/var/lib/kubelet/pki# ls -al
total 24
drwxr-xr-x 2 root root 4096 Jul 23 21:10 .
drwxr-xr-x 7 root root 4096 Nov 12 04:52 ..
-rw------- 1 root root 2810 Jul 23 21:09 kubelet-client-2018-07-23-21-09-53.pem
-rw------- 1 root root 1159 Jul 23 21:10 kubelet-client-2018-07-23-21-10-43.pem
lrwxrwxrwx 1 root root   59 Jul 23 21:10 kubelet-client-current.pem -> /var/lib/kubelet/pki/kubelet-client-2018-07-23-21-10-43.pem
-rw-r--r-- 1 root root 1501 Nov  8 23:53 kubelet.crt
-rw------- 1 root root 1679 Nov  8 23:53 kubelet.key
root@ip-172-31-1-118:/var/lib/kubelet/pki#

هل هي ملفات kubelet.crt و kubelet.key تم إنشاؤها بواسطة kubelet في المرة الأولى التي يتم تحميلها فيها؟

@ raravena80 شكرا للتوضيح
ربما ليس لدي السياق الكامل هنا ، لذا أترك مجالًا للآخرين للإجابة.

ملاحظة جانبية واحدة فقط (قد تكون مفيدة)
قامت Kubeadm بالفعل بإنشاء شهادة باسم apiserver-kubelet-client للسماح لخادم api بالتحدث بأمان مع kubelets ؛ يتم توقيعه من قبل كاليفورنيا ويلتزم بقواعد RBAC الضرورية.

/ تعيين liztio

أعتقد أن هذا يهدف إلى إنشاء شهادات خادم kubelet مسبقًا. لقد تلاعبت بمحاولة استخدام علامات Kubelet لتمهيد خادم TLS وتدوير شهادات الخادم ، لسوء الحظ لم أتمكن من جعل Kubelet يطلب شهادة خادم لنفسه باستخدام رمز التمهيد المميز. ينتهي Kubelet بالتراجع إلى سلوكه الافتراضي لشهادات الخادم ، وهو إنشاء واحدة موقعة ذاتيًا.

على حد علمي ، الطريقة الوحيدة الآن للتغلب على ذلك هي إنشاء شهادات خادم Kubelet خارج النطاق ووضعها في مسار حتمي و kubelet (تم تكوينه بواسطة kubeadm) ستلتقطها ، وتعيين بعض أعلام kubelet وفقًا لذلك ؛ المرجع: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#client -and-serve -ificates

apiserver-kubelet-client هو شهادة العميل التي سيقدمها خادم واجهة برمجة التطبيقات إلى kubelet ، ولكن تم تكوين kubelet للثقة في العملاء الموقعين بواسطة k8s CA:

# cat /var/lib/kubelet/config.yaml 
address: 0.0.0.0
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt

إنها هوية kubelet كخادم يتم تقديمها والتي تحتاج إلى توقيعها من قبل k8s CA ، والتي تأتي حول السؤال الأصلي.

هناك أيضًا بعض المناقشات ذات الصلة في نهاية هذا الموضوع: https://github.com/kubernetes/kubeadm/issues/118

أعتقد أن kubeadm قد يضطر إلى إضافة اعتماد CSR لطلبات شهادة الخادم برمز تمهيد تشغيل صالح ، تمامًا كما يفعل لطلبات شهادة العميل؟

ماذا عن تحميل kubelet كاليفورنيا الموقعة ذاتيًا إلى ملف configmap في مكان ما؟ يمكن أن يقيد المكون الإضافي nodeadmission بخريطة التكوين الخاصة به فقط. يمكن لخادم المقاييس استخدامه للاتصال بالعقدة.

أي أفكار حول ذلك؟

إذا كان ذلك ممكنًا ، أعتقد أنه يجب علينا استخدام تسهيلات TLS bootstrapping المضمنة في kubelet لطلب / تدوير شهادات الخدمة.

alexbrand أوافق على ذلك

ينشئ kubelet TLS bootstrapping شهادات العميل فقط لأي سبب:
--bootstrap-kubeconfig string
Path to a kubeconfig file that will be used to get client certificate for kubelet. If the file specified by --kubeconfig does not exist, the bootstrap kubeconfig is used to request a client certificate from the API server. On success, a kubeconfig file referencing the generated client certificate and key is written to the path specified by --kubeconfig. The client certificate and key file will be stored in the directory pointed by --cert-dir.

و kubeadm يفعل هذا بالفعل. ربما هذا هو طلب ميزة kubelet؟

لنلخص المشكلة:

كما هو موضح بواسطة anitgandhi :
https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -454572577

مشكلة kubeadm هنا هي أننا لا نمرر اثنين من الأعلام إلى kubelet:

--tls-cert-file=<some-path>/kubelet.crt
--tls-private-key-file=<some-path>/kubelet.key

بدون هذه العلامات ، يتم تعيين kubelet افتراضيًا للتوقيع الذاتي لشهادة الخدمة عند تشغيله لأول مرة ، والتي يمكن التحقق منها باستخدام:

sudo openssl verify -verbose -CAfile /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.crt

باستخدام شهادة موقعة ذاتيًا بدلاً من الشهادة الموقعة من قبل مجموعة CA ( /etc/kubernetes/ca.crt ) ، لا يمكن لعمليات النشر مثل خادم المقاييس أن تتخلص من kubelet ، لأن شهادة SAN الموقعة ذاتيًا ستتضمن DNS:hostname .

الحلول الممكنة:
أ) تنفيذ الغناء لزوج جديد من kubelet.crt/key ، من الناحية المثالية أقل من /var/lib/kubelet/pki وتعيين أعلام kubelet الإضافية --tls-cert-file ، --tls-private-key-file .

ب) المستند يعني تمكين هذا عند الطلب بشكل مشابه لكيفية قيام @ raravena80 بذلك هنا: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
باستثناء احتمال استخدام أوامر Kubernetes CSRs / kubeadm.

ج) كما علق alexbrand

إذا كان ذلك ممكنًا ، أعتقد أنه يجب علينا استخدام تسهيلات TLS bootstrapping المضمنة في kubelet لطلب / تدوير شهادات الخدمة.

د) ؟

@ kubernetes / sig-الكتلة-دورة حياة
بالنسبة لي يبدو هذا في المسافة بين الخطأ / الميزة.

انظر أيضا:
https://github.com/kubernetes/community/pull/602/files

أعتقد أن شيئًا ما بين الخيارين B + C يجب أن يتم القيام به نظرًا لأن الكثير من رموز التمهيد / المنطق CSR للعميل kubelet + kubeadm سيكون له منطق مشترك لهذا.

لنلخص المشكلة:

كما هو موضح بواسطة anitgandhi :
# 1223 (تعليق)

مشكلة kubeadm هنا هي أننا لا نمرر اثنين من الأعلام إلى kubelet:

--tls-cert-file=<some-path>/kubelet.crt
--tls-private-key-file=<some-path>/kubelet.key

بدون هذه العلامات ، يتم تعيين kubelet افتراضيًا للتوقيع الذاتي لشهادة الخدمة عند تشغيله لأول مرة ، والتي يمكن التحقق منها باستخدام:

sudo openssl verify -verbose -CAfile /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.crt

باستخدام شهادة موقعة ذاتيًا بدلاً من الشهادة الموقعة من قبل مجموعة CA ( /etc/kubernetes/ca.crt ) ، لا يمكن لعمليات النشر مثل خادم المقاييس أن تتخلص من kubelet ، لأن شهادة SAN الموقعة ذاتيًا ستتضمن DNS:hostname .

الحلول الممكنة:
أ) تنفيذ الغناء لزوج جديد من kubelet.crt/key ، من الناحية المثالية أقل من /var/lib/kubelet/pki وتعيين أعلام kubelet الإضافية --tls-cert-file ، --tls-private-key-file .

ب) المستند يعني تمكين هذا عند الطلب بشكل مشابه لكيفية قيام @ raravena80 بذلك هنا: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
باستثناء احتمال استخدام أوامر Kubernetes CSRs / kubeadm.

ج) كما علقalexbrand

إذا كان ذلك ممكنًا ، أعتقد أنه يجب علينا استخدام تسهيلات TLS bootstrapping المضمنة في kubelet لطلب / تدوير شهادات الخدمة.

د) ؟

@ kubernetes / sig-الكتلة-دورة حياة
بالنسبة لي يبدو هذا في المسافة بين الخطأ / الميزة.

انظر أيضا:
https://github.com/kubernetes/community/pull/602/files

ملخص رائع @ neolit123 . هل تعلم ما إذا كان هذا سينزلق إلى الدورة التالية أم أن العمل جارٍ بينما نتحدث؟ السؤال بشكل أساسي بسبب خادم المقاييس الذي تريد كل عملية نشر الحصول عليه ؛)

ذكر @ randomvariable أن هناك حلًا آخر لذلك.
من المناقشات حتى الآن ، نحن مترددون في توقيع شهادة خدمة kubelet مع الكتلة CA. هذا الموضوع يحتاج إلى مزيد من المناقشة.

/ إزالة المساعدة

لأن الحل المطلوب تنفيذه لم يتم اختياره بعد.

أي حركة على هذا؟ أنا أواجهها لدعم ميزات القياس التلقائي داخل مجموعة منشورة kubeadm.

الحل الحالي هو إيقاف تشغيل فحص CA لشهادة kubelet.

helm install --set 'args={--kubelet-insecure-tls}' --namespace kube-system metrics stable/metrics-serve

ليس حقًا ، إنه محظور على مقترحات التصميم
هناك عدد من الحلول لكن عمل توثيق تلك المتوقفة:
https://github.com/kubernetes/kubeadm/issues/1602

- kubelet-insecure-tls

قد لا يكون هذا مثاليًا لجميع المستخدمين.

تصبح المشكلات قديمة بعد 90 يومًا من الخمول.
ضع علامة على المشكلة على أنها جديدة /remove-lifecycle stale .
تتعفن المشكلات التي لا معنى لها بعد 30 يومًا إضافيًا من عدم النشاط وتغلق في النهاية.

إذا كان إغلاق هذه المشكلة آمنًا الآن ، فيرجى القيام بذلك باستخدام /close .

إرسال التعليقات إلى اختبار سيج ، kubernetes / test-infra و / أو fejta .
/ دورة الحياة التي لا معنى لها

/ دورة الحياة مجمدة

تشغيل هذه المشكلة بالضبط إنشاء مجموعة v1.18.2 مع kubeadm.

عند إعداد خادم المقاييس ، فإنه لا يعمل بدون إعداد علامة kubelet-insecure-tls أو إصدار شهادات لـ kublet "خارج النطاق" ، وتوقيعه مع kubernetes CA.

فكرت في إعادة استخدام شهادة عميل kubelet ولكن هذا بالطبع تم إصداره إلى CN = system:node:nodename ولا توجد شبكات SAN. ولقد قمت باختباره على الرغم من أنه بالطبع يغير الخطأ ليشير إلى ذلك. هل يمكن استخدام نفس الشهادة كخادم / عميل إذا كان لها اسم الاسم كاسم بديل للموضوع؟ لكنني أعتقد أنه سيكون من الأنسب استخدام شهادات منفصلة للخادم / العميل؟

/ إزالة دورة الحياة مجمدة

/ دورة الحياة مجمدة

تم تجميده حتى لا تغلق الروبوتات المشكلة.

هل يمكن استخدام نفس الشهادة كخادم / عميل إذا كان لها اسم الاسم كاسم بديل للموضوع؟

من الناحية النظرية وما لم تتحقق منها kubelet - على سبيل المثال "يجب ألا تحتوي شهادة العميل على شبكات SAN".

لكنني أعتقد أنه سيكون من الأنسب استخدام شهادات منفصلة للخادم / العميل؟

من الشائع استخدامها بشكل منفصل حتى في الحالات التي يبدو فيها أنه يمكن تجنبها. من غير المحتمل أن يقوم مشرفو kubelet / auth {z | n} بتغيير هذه التفاصيل.

مهلا. فعلت المزيد من الحفر. يمكن لخيار تكوين Kubelet serverTLSBootstrap: true إنشاء CSR لشهادة الخدمة. لكنه يتركه غير موافق عليه. الذي قد يكون على ما يرام؟

يبدو أن تعيين كل من rotateCertificates: true و serverTLSBootsrap: true ثم الموافقة على CSR لشهادة الخدمة أسهل طريقة للذهاب إلى هنا. شهادة التقديم التي تم طلبها / إصدارها هي O = system:nodes, CN = system:node:<nodename> مع أسماء بديلة للموضوع مقابل DNS: <nodename>, IP Address: <node IP address>

هل يجب أن يقوم kubeadm بتمكين خيار تكوين serverTLSBootstrap على الأقل حتى تكون الموافقة على شهادة الخادم أمرًا سهلاً؟ أو حتى kubeadm يمكن أن تفعل الموافقة أيضا؟

مهلا. فعلت المزيد من الحفر. يمكن لخيار تكوين Kubelet serverTLSBootstrap: true إنشاء CSR لشهادة الخدمة. لكنه يتركه غير موافق عليه. الذي قد يكون على ما يرام؟

يبدو أن تعيين كل من rotateCertificates: true و serverTLSBootsrap: true ثم الموافقة على CSR لشهادة الخدمة أسهل طريقة للذهاب إلى هنا. شهادة التقديم التي تم طلبها / إصدارها هي O = system:nodes, CN = system:node:<nodename> مع أسماء بديلة للموضوع مقابل DNS: <nodename>, IP Address: <node IP address>

هل يجب أن يقوم kubeadm بتمكين خيار تكوين serverTLSBootstrap على الأقل حتى تكون الموافقة على شهادة الخادم أمرًا سهلاً؟ أو حتى kubeadm يمكن أن تفعل الموافقة أيضا؟

لست متأكدًا من تطبيقات الأمان ولكن يمكنك الجمع بين serverTLSBootstrap مع هذا المشغل للموافقة التلقائية على CSRs https://github.com/kontena/kubelet-rubber-stamp

هل يجب أن يقوم kubeadm بتمكين خيار تكوين serverTLSBootstrap على الأقل حتى تكون الموافقة على شهادة الخادم أمرًا سهلاً؟ أو حتى kubeadm يمكن أن تفعل الموافقة أيضا؟

لا يستطيع kubeadm إجراء الموافقة لأن kubeadm ليس خفيًا. يجب أن تنشر وحدة تحكم / مشغل يدير ذلك للمستخدم. ربما في المستقبل.

يجب أن تذهب شهادات API إلى GA قريبًا ونأمل أن يكون لدينا طريقة أفضل لإدارة هذا في k8s. شاهد رجاءا:
https://github.com/kubernetes/enhancements/issues/267
(لكن من غير الواضح لي ما الذي سننتهي إليه ...)

لدينا أيضًا أفكار بديلة. ولكن إذا كان كل هذا يحاول حل مشكلة الخادم المتري ، فيمكنك أيضًا استخدام https://github.com/brancz/kube-rbac-proxy الذي يمكنه إجراء SAR على طلبات MS إلى kubelet. للأسف لم يتم توثيق هذا من جانبنا بعد:
https://github.com/kubernetes/kubeadm/issues/1602

@ neolit123 لقد بدأت على الأقل في البحث فيه عند محاولة الوقوف على خادم المقاييس على مجموعات kubeadm و "الطريق الصعب" لتجربة التعلم. كان من الأسهل بالطبع وضع علامة على MS باستخدام --kubelet-insecure-tls ، لكنني أردت حقًا معرفة كيفية إصلاحها بطريقة آمنة ثم أصبحت مهتمًا بالمشكلة. 🙂

في الوقت الحالي ، من السهل جدًا بالنسبة لي إضافة علامة serverTLSbootstrap إلى تكوين kubelet واعتماد الشهادات يدويًا. لقد لاحظت جانبًا سلبيًا في ذلك ، وهو أنه لا يمكنك التفاعل بشكل كامل مع البودات الموجودة على العقدة حتى توافق على الشهادة. (فشل kubectl exec في تشغيل الأمر على البودات التي تعمل على عقدة قبل الموافقة على سبيل المثال)

سأتابع على طول قضية التحسينات أيضا. شكرا.

من المحزن حقًا أنه مع kubeadm الذي يبدو ناضجًا بدرجة كافية ، فإن نتيجة الخروج من الصندوق لـ kubeletet cert هي أن تكون موقعة ذاتيًا ويختار العديد من الأشخاص kubelet-insecure-tls لخادم المقاييس بدلاً من القيام بالأشياء بشكل صحيح وما إلى ذلك:

إنها مشكلة معقدة.

أرجوك حاول:
https://github.com/kontena/kubelet-rubber-stamp
أو
https://github.com/brancz/kube-rbac-proxy
كحلول

إنها مشكلة معقدة.

أرجوك حاول:
https://github.com/kontena/kubelet-rubber-stamp
أو
https://github.com/brancz/kube-rbac-proxy
كحلول

في الواقع ، يعمل https://github.com/kontena/kubelet-rubber-stamp جيدًا ويبدو أن imo هو الحل الأكثر صحة بدلاً من الوكيل.

الخطوة 1:
يضيف
serverTLSBootstrap: true حتى نهاية كل /var/lib/kubelet/config.yaml لإعادة تكوين kubelets ولا تنسَ تطبيق config (أو إعادة تشغيلها فقط)

الخطوة 2:
نشر kubelet-rubber-stamp

service_account.yaml
role.yaml
role_binding.yaml
operator.yaml

الخطوه 3:
تحرير نشر خادم المقاييس وإزالة --kubelet-insecure-tls

نتيجة:

kubectl get csr
NAME        AGE   SIGNERNAME                      REQUESTOR          CONDITION
csr-7dvsx   31m   kubernetes.io/kubelet-serving   system:node:u-02   Approved,Issued
csr-d6rvm   31m   kubernetes.io/kubelet-serving   system:node:u-03   Approved,Issued
csr-szblz   31m   kubernetes.io/kubelet-serving   system:node:u-01   Approved,Issued
csr-zjfgj   31m   kubernetes.io/kubelet-serving   system:node:u-04   Approved,Issued

مرحبًا ، فقط للإضافة إلى ذلك @ vainkop
أثناء kubeadm init الأولي لإنشاء الكتلة ، يجب أن تكون قادرًا أيضًا على تمرير ملف كائن KubeletConfiguration API لتعيين serverTLSBootstrap

"" kubeadm-config.yaml
الإصدار: kubeadm.k8s.io/v1beta2
النوع: ClusterConfiguration

...

الإصدار: kubelet.config.k8s.io/v1beta1
النوع: KubeletConfiguration
serverTLSBootstrap: صحيح

`kubeadm init --config=kubeadm-config.yaml`

Then all kubelet's will automatically be set up using the `serverTLSBootstrap` flag.

To get the CSRs

kubectl الحصول على csr
الاسم AGE SIGNERNAME REQUESTOR CONDITION
csr-2qkdw 2m1s kubernetes.io/kube-apiserver-client-kubelet system: bootstrap : fcufbo معتمد ، صدر
csr-9wvgt 114s kubernetes.io/kubelet-serving system: node : worker-1 Pending
csr-lz97v 4m58s kubernetes.io/kubelet-serving system: node : master-1 pending
csr-rsdsp 4m59s kubernetes.io/kube-apiserver-client-kubelet system: node : master-1 معتمد ، صدر
csr-wgxqs 4m49s kubernetes.io/kubelet-serving system: node : master-1 pending

Then either approve them manually or deploy https://github.com/kontena/kubelet-rubber-stamp which approves them automatically. I just tried it with kubelet-rubber-stamp and it works great.

Also I did not seem to need to restart the kubelet's this way, they picked up their certificates as soon as I approvde the CSR, but a caveat is that the kublet's have NO cert until the CSR is approved, it does not get a self signed certificate first.

توافق شهادة kubectl على csr-ab123 # أو انشر ختم مطاطي!

kubectl الحصول على csr
الاسم AGE SIGNERNAME REQUESTOR CONDITION
csr-9wvgt 3m kubernetes.io/kubelet-serving system: node : worker-1 تمت الموافقة عليه وإصداره
...
""

يبدو أن شيئًا غريبًا آخر يحدث هنا بالمناسبة ، وهو أن العقدة الرئيسية يبدو أنها تنشئ CSR مرتين. (على الأقل مرتين حاولت ذلك)

ولكن كما تقول nijave في تعليق أعلاه ، لست متأكدًا من الآثار الأمنية لاستخدام أداة الختم المطاطي.

allir ، vainkop بقدر ما يمكنني رؤية kubelet-rubber-stamp يتحقق فقط مما إذا كان الاسم الشائع لـ CSR يطابق اسم الطالب ولكنه لا يتحقق مما إذا كانت أسماء المضيفين وعناوين IP الإضافية التي طلبها kubelet صالحة. هذا يعني أن المهاجم الذي لديه حق الوصول إلى شهادة عميل kubelet يمكنه إنشاء شهادات لأي اسم مجال أو عنوان IP بشكل أساسي. سيقبل جميع العملاء الذين تم تكوينهم للثقة في المرجع المصدق الجذر هذه الشهادة.
بالطبع ، من الصعب التحقق من صحة اسم المضيف وعناوين IP الصالحة لـ kubelet نظرًا لعدم وجود سلطة حاليًا يمكنها تأكيد ما يُسمح لـ kubelet بطلبه. على سبيل المثال ، استخدام كائن العقدة على خادم API ليس كافيًا لأن kubelets يمكنه تحديث الكائن بدون حدود.

مرحبًا ، فقط للإضافة إلى ذلك @ vainkop
أثناء kubeadm init الأولي لإنشاء الكتلة ، يجب أن تكون قادرًا أيضًا على تمرير ملف كائن KubeletConfiguration API لتعيين serverTLSBootstrap
kubeadm init --config=kubeadm-config.yaml
ثم سيتم إعداد جميع kubelet تلقائيًا باستخدام العلم serverTLSBootstrap .

أو لإعداد K8s الحالي باستخدام Ansible يمكن أن يكون:

  tasks:
    - name: Insert a line at the end of /var/lib/kubelet/config.yaml
      lineinfile:
        path: /var/lib/kubelet/config.yaml
        line: 'serverTLSBootstrap: true'

+ إعادة تشغيل kubelets

واو ، أنا سعيد جدًا لأنني وجدت هذه المشكلة ، ولست وحدي الذي يريد القيام بهذه الطريقة الصحيحة. :)

اسمحوا لي الآن بمشاركة أفكاري حول هذه المشكلة (يرجى تصحيحها إذا كنت مخطئًا في مكان ما) :

أولا رؤيتي للمشكلة الأصلية:
يقوم kubeadm حاليًا بتمكين مصادقة webhook لجميع kubelets بشكل افتراضي ، لذلك يقوم kubelet بالتحقق من صحة شهادات العميل للاتصالات الواردة دون أي مشكلة حتى إذا تم تحديد الخيار --kubelet-insecure-tls .
من الجانب الآخر ، لا يتمتع خادم المقاييس بفرصة للتحقق من شهادة kubelet المحددة لأنها موقعة ذاتيًا على العقدة.

المخاطر المحتملة لاستخدام --kubelet-insecure-tls لخادم المقاييس:
بينما يتم تأمين بيانات kubelet إلى حد ما ولن يتم توفيرها أبدًا لخادم المقاييس بدون مصادقة خطاف الويب الناجحة.
من الناحية النظرية ، يمكن لأي شخص اختراق عنوان IP الخاص بالخادم أو اسم المضيف وتقديم إحصائيات خاطئة. ولكن لإنشاء الاتصالات ، يستخدم خادم القياس عنوان IP وأسماء مضيفين محددة للعقدة عبر kube-apiserver ، لذلك يحتاج المهاجم إلى اختراق خادم API أو DNS أو عنوان IP للعقدة أولاً.

ملاحظة قليلة:
خادم المقاييس ليس خدمة واحدة تصل إلى kubelets مباشرة. يقوم Kube-apiserver أيضًا بذلك لقراءة سجلات الحاوية أو تنفيذ shell عليها. السؤال الجيد هو كيف يتأكد kube-apiserver من أنه ينشئ اتصالًا مع kubelet المحدد بينما لا يحتوي على أي معلومات حول CA الذي أصدر شهادته؟
ألا يسلك نفس سلوك خادم المقاييس مع الخيار --kubelet-insecure-tls في هذه الحالة؟

حل ممكن:
في أيامنا هذه ، تحظى Webhooks وتجميع API بشعبية كبيرة في Kubernetes. كلهم يتصرفون بنفس الطريقة ، من خلال توليد CA و crt / key الخاصين بهما. يتم أيضًا تخزين تجزئة المرجع المصدق (CA) في مورد معين لتزويد kube-apiserver بمعلومات حول الشهادة التي يمكنه الوثوق بها.

على سبيل المثال:

  • تقوم APIServices بتخزين تجزئة CA ذات الصلة في موردها apiservices.apiregistration.k8s.io :

    spec:
    caBundle: <ca-hash>
    
  • تقوم Webhooks بتخزين تجزئة المرجع المصدق ذات الصلة في مواردها validatingwebhookconfigurations.admissionregistration.k8s.io و mutatingwebhookconfigurations.admissionregistration.k8s.io :

    webhooks:
    - clientConfig:
      caBundle: <ca-hash>
    

بالنسبة لي ، من الواضح تمامًا أن كل مورد عقدة يجب أن يكون مشابهًا لـ caBundle في spec ، حيث يمكن لـ kubelets تسجيل CA الخاص بهم للخدمة باستخدام شهادة العميل الخاصة بهم:

spec:
  caBundle: <ca-hash>

يجب أن يستخدم كل من metris-server و kube-apiserver هذه الشهادات للتحقق والثقة بالاتصال مع kubelets.

بفضل @ kfox1111 الذي عبر عن فكرة مماثلة سابقًا https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -460854312

السؤال الجيد هو كيف يتأكد kube-apiserver من أنه ينشئ اتصالًا مع kubelet المحدد بينما لا يحتوي على أي معلومات حول CA الذي أصدر شهادته؟
ألا يسلك نفس سلوك خادم المقاييس مع الخيار --kubelet-insecure-tls في هذه الحالة؟

للإجابة على هذا السؤال يمكنني اقتباس luxas هنا:

حسنًا ، لا يمكننا إجراء الاتصالات من خادم api إلى خوادم kubelet التي تم التحقق منها ، حيث أن لكل kubelet شهادة موقعة ذاتيًا. قد نفكر في اعتماد يدوي لشهادات خدمة wrt kubelet في المستقبل ولكن هذا غير مؤمن افتراضيًا في الوقت الحالي.

من https://github.com/kubernetes/kubeadm/issues/118#issuecomment -407498529

آمل أن يتم حلها يومًا ما

[root<strong i="6">@jenkins</strong> metrics-server]# kubectl -n kube-system logs -f metrics-server-6955d88db9-lftlz
I1120 08:23:09.094132       1 requestheader_controller.go:169] Starting RequestHeaderAuthRequestController
I1120 08:23:09.094234       1 shared_informer.go:240] Waiting for caches to sync for RequestHeaderAuthRequestController
I1120 08:23:09.094270       1 configmap_cafile_content.go:202] Starting client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I1120 08:23:09.094279       1 shared_informer.go:240] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I1120 08:23:09.094307       1 configmap_cafile_content.go:202] Starting client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I1120 08:23:09.094315       1 shared_informer.go:240] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I1120 08:23:09.095064       1 dynamic_serving_content.go:130] Starting serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key
I1120 08:23:09.095207       1 secure_serving.go:197] Serving securely on [::]:4443
I1120 08:23:09.095259       1 tlsconfig.go:240] Starting DynamicServingCertificateController
I1120 08:23:09.194453       1 shared_informer.go:247] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file 
I1120 08:23:09.194660       1 shared_informer.go:247] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::client-ca-file 
I1120 08:23:09.194455       1 shared_informer.go:247] Caches are synced for RequestHeaderAuthRequestController 
E1120 08:23:10.420643       1 server.go:132] unable to fully scrape metrics: [unable to fully scrape metrics from node k8s-master3: unable to fetch metrics from node k8s-master3: Get "https://10.39.140.250:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.250 because it doesn't contain any IP SANs, unable to fully scrape metrics from node k8s-master1: unable to fetch metrics from node k8s-master1: Get "https://10.39.140.248:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.248 because it doesn't contain any IP SANs, unable to fully scrape metrics from node k8s-master2: unable to fetch metrics from node k8s-master2: Get "https://10.39.140.249:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.249 because it doesn't contain any IP SANs, unable to fully scrape metrics from node k8s-node1: unable to fetch metrics from node k8s-node1: Get "https://10.39.140.251:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.251 because it doesn't contain any IP SANs]
I1120 08:23:33.874949       1 requestheader_controller.go:183] Shutting down RequestHeaderAuthRequestController
I1120 08:23:33.874978       1 configmap_cafile_content.go:223] Shutting down client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I1120 08:23:33.874993       1 configmap_cafile_content.go:223] Shutting down client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I1120 08:23:33.875019       1 tlsconfig.go:255] Shutting down DynamicServingCertificateController
I1120 08:23:33.875026       1 dynamic_serving_content.go:145] Shutting down serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key
I1120 08:23:33.875041       1 secure_serving.go:241] Stopped listening on [::]:4443

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

نحن نوثق الحلول هنا:
https://github.com/kubernetes/website/pull/27071
https://github.com/kubernetes/kubeadm/issues/1602

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

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