التثبيت
عنقود محلي يمكن التخلص منه بسهولة، وأداة kubectl تشير إلى الوجهة الصحيحة.
التثبيت والإعداد
يُعدّ تعلّم Kubernetes على عنقود إنتاجي فكرة سيئة لسبب بسيط: ستتسبب في تعطيل بعض الأشياء، وهذا بالضبط ما ينبغي فعله. أنت بحاجة إلى عنقود يمكن تدميره بأمر واحد وإعادة إنشائه في دقيقتين، بحيث لا يكلّفك أي خطأ شيئًا.
هناك طريقتان للحصول على ذلك على جهاز العمل، والاختيار بينهما ليس بلا أهمية. يحاكي minikube عنقودًا كاملًا داخل آلة افتراضية أو حاوية، مع إضافات جاهزة للاستخدام — لوحة تحكم، ووحدة تحكم دخول (Ingress controller)، ومحاكي لموازن الأحمال. أما kind (Kubernetes in Docker) فيشغّل كل عقدة بوصفها حاوية Docker: وهو أخف وأسرع في الإقلاع، وهو الخيار المعتاد في التكامل المستمر.
لكن قبل العنقود، هناك kubectl. وهذه نقطة يخطئ فيها المبتدئون كثيرًا: فـ kubectl ليس مكوّنًا من مكوّنات العنقود، بل هو عميل HTTP يتحدث إلى واجهة API بعيدة. يُثبَّت بشكل مستقل، ويعمل مع أي عنقود، ويقرأ من ملف إعداد محلي تحديد العنقود الذي يجب أن يتحدث إليه. وتنشأ نصف عبارات «لا يعمل» في الأيام الأولى من هنا: kubectl يستعلم من عنقود آخر غير الذي نظنه.
يثبّت هذا الدرس الأدوات، ثم يتوقف عند ملف الإعداد هذا — السياقات ومساحات الأسماء — لأنه ما سيجنّبك يومًا ما تطبيق ملف manifest مخصص لجهازك على بيئة الإنتاج.
تثبيت kubectl
kubectl ملف تنفيذي واحد بلا أي اعتماديات. اختر الطريقة المناسبة لنظامك:
# macOS avec Homebrew
brew install kubectl
# Linux (Debian/Ubuntu) : dépôt officiel Kubernetes
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update && sudo apt-get install -y kubectl
# Windows avec winget
winget install -e --id Kubernetes.kubectl
تحقق بعد ذلك من التثبيت. يعرض الأمر التالي إصدار العميل، ثم يحاول الوصول إلى خادم:
kubectl version --client
ما دام لا يوجد عنقود قيد التشغيل، فإن أمرًا مثل kubectl get nodes سيفشل برسالة رفض الاتصال. هذا طبيعي، وهو في حد ذاته معلومة مفيدة: العميل يعمل، لكنه لا يجد من يتحدث إليه.
أي إصدار نعتمد
يتسامح Kubernetes مع فارق إصدار فرعي واحد بين العميل والخادم. فـ kubectl بالإصدار 1.31 يتحدث بشكل سليم إلى عنقود بالإصدار 1.30 أو 1.31 أو 1.32. وما يتجاوز ذلك قد تصبح بعض الموارد غير مرئية للعميل دون رسالة واضحة. وعند ظهور سلوك غير مفهوم، فإن أول تحقق هو التالي:
# Compare la version du client et celle du serveur
kubectl version
الخيار A: minikube
يشغّل minikube عنقودًا ذا عقدة واحدة داخل مشغّل افتراضية (driver). ويُعدّ المشغّل docker الأبسط إذا كان Docker مثبتًا بالفعل.
# Installation (macOS)
brew install minikube
# Démarrage : le premier lancement télécharge l'image du nœud, comptez quelques minutes
minikube start --driver=docker --cpus=2 --memory=4096
# minikube a écrit la configuration de connexion pour kubectl : on vérifie
kubectl get nodes
المخرجات المتوقعة:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 47s v1.31.0
عقدة واحدة فقط، تحمل في آن واحد مستوى التحكم (control plane) وأحمال عملك. في بيئة الإنتاج تُفصل هذه الأدوار؛ أما هنا فالتبسيط لا أثر له على التعلّم.
أوامر إدارة دورة الحياة:
minikube status # état du cluster et de ses composants
minikube stop # arrête sans détruire : l'état est conservé
minikube start # redémarre là où on s'était arrêté
minikube delete # détruit tout, y compris les données
minikube dashboard # ouvre l'interface web dans le navigateur
يوفّر minikube إضافات قابلة للتفعيل. اثنتان منها مفيدتان لبقية الدورة:
# Le contrôleur d'entrée, nécessaire pour les Ingress de la leçon 6
minikube addons enable ingress
# Le serveur de métriques, nécessaire pour kubectl top et l'autoscaling
minikube addons enable metrics-server
minikube addons list # voir tout ce qui est disponible
الخيار B: kind
يجعل kind كل عقدة حاوية Docker. إقلاعه أسرع، واستهلاكه أقل، والأهم أنه يتيح محاكاة عدة عقد — وهو أمر مفيد لملاحظة إعادة جدولة Pod.
# Installation (macOS)
brew install kind
# Cluster à un nœud
kind create cluster --name atelier
# Vérification
kubectl cluster-info --context kind-atelier
لإنشاء عنقود متعدد العقد، يقرأ kind ملف إعداد. انتبه: يستخدم هذا الملف واجهة API الخاصة بـ kind لا واجهة Kubernetes، ولهذا يبدو apiVersion فيه غير مألوف.
# kind-cluster.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: atelier
nodes:
- role: control-plane
- role: worker
- role: worker
kind create cluster --config kind-cluster.yaml
kubectl get nodes
# atelier-control-plane, atelier-worker, atelier-worker2
kind delete cluster --name atelier # suppression
فرق ينبغي معرفته فورًا: لا يرى kind الصور الموجودة في خدمة Docker المحلية لديك. يجب حقن الصورة المبنية محليًا في العنقود صراحةً، وإلا بقي الـ Pod عالقًا في حالة ErrImagePull رغم أن docker images تُظهرها موجودة.
docker build -t mon-api:dev .
kind load docker-image mon-api:dev --name atelier
أما مع minikube، فالمكافئ هو توجيه عميل Docker إلى الخدمة الداخلية للعنقود:
eval $(minikube docker-env)
docker build -t mon-api:dev . # l'image est construite dans le cluster
في الحالتين، حدّد imagePullPolicy: IfNotPresent في ملفات manifest الخاصة بك، وإلا حاول Kubernetes تنزيل الصورة dev من سجل عام لا توجد فيه.
ملف kubeconfig والسياقات
هذا الملف هو القطعة التي يتجاهلها المرء طويلًا. مساره الافتراضي ~/.kube/config، ويحتوي على ثلاث قوائم مستقلة:
clusters: عناوين خوادم API وشهاداتها؛users: الهويات المستخدمة للمصادقة؛contexts: الارتباطات (عنقود، مستخدم، namespace).
وبالتالي فإن السياق (context) ببساطة هو الثلاثية التي يستخدمها kubectl في كل استدعاء. وتغيير السياق يعني تغيير العنقود المستهدف — ومن هنا ضرورة معرفة السياق النشط في كل وقت.
# Lister les contextes ; l'astérisque marque celui qui est actif
kubectl config get-contexts
# Afficher uniquement le nom du contexte actif
kubectl config current-context
# Basculer de cluster
kubectl config use-context kind-atelier
# Voir la configuration complète, secrets masqués
kubectl config view
اعتد التحقق من السياق قبل أي أمر كتابة. إنه ردّ فعل يبدو مبالغًا فيه إلى اليوم الذي يجنّبك فيه تنفيذ kubectl delete على العنقود الخطأ:
# Rendre le contexte visible dans le prompt, ou au minimum le vérifier
kubectl config current-context && kubectl get nodes
مساحات الأسماء (Namespaces)
الـ namespace هو تقسيم منطقي للعنقود. يتيح عزل مجموعات من الموارد حسب الفريق أو البيئة أو التطبيق، ويُعدّ أساسًا للحصص (quotas) وقواعد الوصول.
نقطة مهمة كثيرًا ما تفاجئ: الـ namespace لا يعزل الشبكة. افتراضيًا، يستطيع Pod في namespace باسم dev الوصول إلى Pod في namespace باسم prod. أما هذا النوع من العزل فيتطلب NetworkPolicy، وهي تعتمد على إضافة الشبكة المثبتة.
# Les namespaces créés d'office
kubectl get namespaces
# default, kube-system, kube-public, kube-node-lease
يستضيف kube-system مكوّنات العنقود. لا ننشر فيه أي شيء خاص بنا، ونتجنب تطبيق ملف manifest فيه عن غير قصد — وهذا سبب آخر لمراقبة السياق.
أنشئ namespace للعمل، ويُفضَّل أسلوب التصريح (declarative)، حتى يعيش تعريفه في مستودعك:
apiVersion: v1
kind: Namespace
metadata:
name: atelier
labels:
environnement: developpement
kubectl apply -f namespace.yaml
# Équivalent impératif, pratique pour du jetable
kubectl create namespace atelier
تقبل جميع أوامر القراءة والكتابة الخيار -n (أو --namespace). وبدون هذا الخيار يستخدم kubectl الـ namespace المسجَّل في السياق النشط، وهو default في أغلب الأحيان:
kubectl get pods -n atelier # dans un namespace précis
kubectl get pods --all-namespaces # partout ; alias : -A
# Changer le namespace par défaut du contexte actif
kubectl config set-context --current --namespace=atelier
يوفّر عليك هذا الأمر الأخير تكرار -n atelier خمسين مرة. لكن له مقابلًا: لم تعد ترى في الأمر نفسه أين سيُطبَّق. لذا تحقق بانتظام:
kubectl config view --minify --output 'jsonpath={..namespace}'
وأخيرًا، خاصية ينبغي معرفتها قبل أن تتعلمها على حسابك: حذف namespace يحذف كل ما فيه، بشكل متسلسل ودون تأكيد.
kubectl delete namespace atelier # Pods, Services, Secrets, PVC : tout part
التحقق من جاهزية كل شيء
نفّذ هذه الأوامر الأربعة تباعًا. إذا استجابت جميعها، فبيئتك جاهزة للدرس التالي:
# 1. Le client joint bien le serveur d'API
kubectl cluster-info
# 2. Le ou les nœuds sont Ready
kubectl get nodes
# 3. Les composants du plan de contrôle tournent
kubectl get pods -n kube-system
# 4. Un Pod éphémère peut réellement démarrer et sortir sur le réseau
kubectl run test --image=busybox:1.36 --rm -it --restart=Never -- \
wget -qO- https://kubernetes.io/fr/ | head -n 5
يستحق الأمر الرابع وقفة: الخيار --rm يحذف الـ Pod عند الخروج، و--restart=Never ينشئ Pod منفردًا بدل Deployment، و-it يربط الطرفية. وإذا نجح، فهذا يعني أن بيئة التشغيل (runtime) تنزّل الصور، وأن المجدوِل (scheduler) يضع الـ Pods، وأن الشبكة الخارجة تعمل. ثلاثة تحققات في أمر واحد.
الإكمال التلقائي والأسماء المستعارة
أسماء الموارد التي يولّدها Kubernetes طويلة وعشوائية (mon-api-7d4b8c9f5-xk2mp). وبدون الإكمال التلقائي ستعيد كتابتها يدويًا طوال اليوم.
# bash : ajouter à ~/.bashrc
source <(kubectl completion bash)
alias k=kubectl
complete -o default -F __start_kubectl k
# zsh : ajouter à ~/.zshrc
source <(kubectl completion zsh)
alias k=kubectl
# PowerShell : ajouter au profil ($PROFILE)
kubectl completion powershell | Out-String | Invoke-Expression
Set-Alias -Name k -Value kubectl
خياران للقراءة ينبغي معرفتهما من الآن، لأنهما يُستخدمان باستمرار:
# -o wide ajoute l'IP du Pod et le nœud qui l'héberge
kubectl get pods -o wide
# -w (watch) suit les changements en direct : indispensable pendant un déploiement
kubectl get pods -w
الخلاصة
kubectlعميل مستقل عن العنقود. وهو يخضع للسياق النشط في~/.kube/config، وأكثر أخطاء المبتدئين شيوعًا هو التحدث إلى عنقود آخر غير الذي يظنه.- يوفّر minikube عنقودًا كاملًا مع إضافات (
ingressوmetrics-server)؛ أما kind فهو أخف ويتيح محاكاة عدة عقد. وكلاهما مناسب لهذه الدورة. - الصورة المبنية محليًا غير مرئية للعنقود: استخدم
kind load docker-imageأوeval $(minikube docker-env)، وصرّح بـimagePullPolicy: IfNotPresent. - يقسّم الـ namespace الموارد ويُعدّ أساسًا للحصص، لكنه لا يعزل الشبكة دون
NetworkPolicy. وحذفه يدمّر كل محتواه بشكل متسلسل. - تحقق دائمًا من النشر استنادًا إلى الحالة الملاحَظة (
kubectl getوkubectl describe)، ومن السياق النشط قبل أي أمر كتابة.
نصيحة: دمّر عنقودك المحلي وأعد إنشاءه مرة واحدة على الأقل. إن معرفتك بإمكانية البدء من الصفر في دقيقتين تغيّر علاقتك بالتجريب تمامًا.
التعليقات
التعليقات مدعومة عبر GitHub Discussions
سجّل الدخول باستخدام GitHub للمشاركة في النقاش