Kubernetes: Wdrażanie pierwszej aplikacji
Praktyczny przewodnik po wdrażaniu aplikacji w Kubernetes. Od instalacji minikube po Deployments, Services i ConfigMaps z konkretnymi przykładami.

Kubernetes (K8s) stał się de facto standardem orkiestracji kontenerów. Zaprojektowany przez Google i obecnie utrzymywany przez CNCF, Kubernetes automatyzuje wdrażanie, skalowanie i zarządzanie aplikacjami konteneryzowanymi. Niniejszy przewodnik prowadzi przez konfigurację lokalnego klastra i wdrożenie pierwszej aplikacji.
Zalecana jest podstawowa znajomość Dockera przed zagłębieniem się w Kubernetes. Kontenery to fundamentalne bloki, którymi zarządza Kubernetes. Wcześniejsze zapoznanie się z przewodnikiem po Dockerze znacznie ułatwia zrozumienie prezentowanych tutaj koncepcji.
Zrozumienie architektury Kubernetes
Kubernetes opiera się na architekturze master-worker. Control Plane podejmuje globalne decyzje dotyczące klastra, podczas gdy Nodes uruchamiają obciążenia.
# Simplified Kubernetes Architecture
┌─────────────────────────────────────────────────────────────┐
│ CONTROL PLANE │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ API Server │ │ Scheduler │ │ Controller Manager │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ etcd ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ NODE 1 │ │ NODE 2 │ │ NODE 3 │
│ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │
│ │ kubelet │ │ │ │ kubelet │ │ │ │ kubelet │ │
│ ├───────────┤ │ │ ├───────────┤ │ │ ├───────────┤ │
│ │ kube-proxy│ │ │ │ kube-proxy│ │ │ │ kube-proxy│ │
│ ├───────────┤ │ │ ├───────────┤ │ │ ├───────────┤ │
│ │ Pods │ │ │ │ Pods │ │ │ │ Pods │ │
│ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘ └─────────────────┘API Server jest punktem wejścia dla wszystkich poleceń. etcd przechowuje stan klastra. Scheduler przypisuje Pody do Nodes. Controllery utrzymują pożądany stan systemu.
Konfiguracja środowiska lokalnego
Istnieje kilka opcji eksperymentowania z Kubernetes lokalnie: minikube, kind, k3d lub Docker Desktop. Minikube pozostaje najpopularniejszym rozwiązaniem do nauki.
# terminal
# Install kubectl (Kubernetes client)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# Verify installation
kubectl version --client
# Client Version: v1.31.0
# Install minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Start the local cluster
minikube start --driver=docker --cpus=2 --memory=4096
# Check status
minikube status
# minikube: Running
# cluster: Running
# kubectl: ConfiguredMinikube tworzy jednowęzłowy klaster Kubernetes wewnątrz maszyny wirtualnej lub kontenera Docker. Przydzielone zasoby (CPU, pamięć) można dostosować do potrzeb.
# terminal
# Access the Kubernetes dashboard (web interface)
minikube dashboard
# Check cluster nodes
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# minikube Ready control-plane 5m v1.31.0
# Detailed cluster information
kubectl cluster-infoKind (Kubernetes in Docker) startuje szybciej i lepiej nadaje się do testów CI/CD. K3d wykorzystuje k3s, lekką dystrybucję Kubernetes. Docker Desktop integruje Kubernetes bezpośrednio, ale zużywa więcej zasobów.
Pody: jednostka podstawowa
Pod jest najmniejszą wdrażaną jednostką w Kubernetes. Pod hermetyzuje jeden lub więcej kontenerów, które współdzielą tę samą sieć i pamięć masową.
# pod-simple.yaml
apiVersion: v1
kind: Pod
metadata:
# Unique Pod name within the namespace
name: nginx-pod
# Labels for organization and selection
labels:
app: nginx
environment: development
spec:
containers:
# Main container definition
- name: nginx
# Docker image to use
image: nginx:1.25-alpine
# Ports exposed by the container
ports:
- containerPort: 80
# Container resource allocation
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"Ten manifest YAML deklaruje Poda zawierającego pojedynczy kontener nginx. Etykiety umożliwiają identyfikację i selekcję Podów. Zasoby określają minimalne gwarancje (requests) i maksymalne limity (limits).
# terminal
# Create the Pod
kubectl apply -f pod-simple.yaml
# pod/nginx-pod created
# List Pods
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# nginx-pod 1/1 Running 0 30s
# Full Pod details
kubectl describe pod nginx-pod
# Container logs
kubectl logs nginx-pod
# Execute a command inside the Pod
kubectl exec -it nginx-pod -- /bin/sh
# Delete the Pod
kubectl delete pod nginx-podPody są z natury efemeryczne. W przypadku awarii lub usunięcia Kubernetes nie tworzy ich automatycznie ponownie. Deploymenty rozwiązują to ograniczenie.
Deploymenty: zarządzanie deklaratywne
Deployment definiuje pożądany stan zestawu identycznych Podów. Kubernetes automatycznie utrzymuje ten stan, tworząc, aktualizując lub usuwając Pody w razie potrzeby.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
# Deployment name
name: webapp-deployment
labels:
app: webapp
spec:
# Desired number of replicas
replicas: 3
# Selector to identify managed Pods
selector:
matchLabels:
app: webapp
# Template for Pod creation
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
# Liveness probe: restarts container on failure
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
# Readiness probe: removes Pod from Service on failure
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5Deployment tworzy ReplicaSet, który utrzymuje 3 identyczne Pody. Sondy sprawdzają stan kontenerów i pozwalają Kubernetes automatycznie reagować na problemy.
# terminal
# Create the Deployment
kubectl apply -f deployment.yaml
# deployment.apps/webapp-deployment created
# Verify the Deployment
kubectl get deployments
# NAME READY UP-TO-DATE AVAILABLE AGE
# webapp-deployment 3/3 3 3 1m
# List Pods created by the Deployment
kubectl get pods -l app=webapp
# NAME READY STATUS RESTARTS AGE
# webapp-deployment-7d9f8b6c4-abc12 1/1 Running 0 1m
# webapp-deployment-7d9f8b6c4-def34 1/1 Running 0 1m
# webapp-deployment-7d9f8b6c4-ghi56 1/1 Running 0 1m
# Manual scaling
kubectl scale deployment webapp-deployment --replicas=5
# Deployment history
kubectl rollout history deployment webapp-deploymentUsunięcie Poda automatycznie wyzwala utworzenie nowego Poda, aby utrzymać pożądaną liczbę replik.
Gotowy na rozmowy o DevOps?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Services: ekspozycja sieciowa
Pody mają efemeryczne adresy IP. Services zapewniają stabilny adres dostępu do zestawu Podów, z wbudowanym równoważeniem obciążenia.
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
# Service type: ClusterIP (internal), NodePort, LoadBalancer
type: ClusterIP
# Selector to identify target Pods
selector:
app: webapp
ports:
# Port exposed by the Service
- port: 80
# Target container port
targetPort: 80
# Protocol (TCP by default)
protocol: TCPTen Service ClusterIP jest dostępny tylko z wnętrza klastra. Żądania do webapp-service:80 są rozdzielane między Pody z etykietą app: webapp.
# terminal
# Create the Service
kubectl apply -f service.yaml
# service/webapp-service created
# List Services
kubectl get services
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# webapp-service ClusterIP 10.96.123.456 <none> 80/TCP 30s
# Test from a temporary Pod
kubectl run curl-test --rm -it --image=curlimages/curl -- curl webapp-service
# Detailed Service description
kubectl describe service webapp-serviceAby udostępnić aplikację poza klastrem, wymagany jest typ NodePort lub LoadBalancer.
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-nodeport
spec:
type: NodePort
selector:
app: webapp
ports:
- port: 80
targetPort: 80
# Port on each Node (30000-32767)
nodePort: 30080Z minikube polecenie minikube service webapp-nodeport automatycznie otwiera przeglądarkę pod właściwym adresem URL.
ConfigMaps: zewnętrzna konfiguracja
ConfigMaps oddzielają konfigurację od kodu. Wartości są wstrzykiwane jako zmienne środowiskowe lub montowane jako pliki.
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: webapp-config
data:
# Simple key-value pairs
APP_ENV: "production"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
# Multiline configuration (complete file)
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
}ConfigMaps przechowują dane niewrażliwe. Dla sekretów (haseł, tokenów) bardziej odpowiednie są Secrets w Kubernetes.
# deployment-with-config.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-configured
spec:
replicas: 2
selector:
matchLabels:
app: webapp-configured
template:
metadata:
labels:
app: webapp-configured
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
# Inject environment variables
envFrom:
- configMapRef:
name: webapp-config
# Or individual variables
env:
- name: SPECIFIC_VAR
valueFrom:
configMapKeyRef:
name: webapp-config
key: LOG_LEVEL
# Mount configuration file
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: webapp-configTa konfiguracja wstrzykuje zmienne środowiskowe i montuje plik nginx.conf wewnątrz kontenera.
# terminal
# Apply resources
kubectl apply -f configmap.yaml
kubectl apply -f deployment-with-config.yaml
# Verify environment variables
kubectl exec deployment/webapp-configured -- printenv | grep APP_ENV
# APP_ENV=production
# Verify mounted file
kubectl exec deployment/webapp-configured -- cat /etc/nginx/conf.d/default.confModyfikacja ConfigMap nie restartuje automatycznie Podów. Aby zastosować zmiany, wymagany jest ręczny restart: kubectl rollout restart deployment webapp-configured. Narzędzia takie jak Reloader automatyzują ten proces.
Secrets: wrażliwe dane
Secrets przechowują wrażliwe informacje, takie jak hasła, tokeny czy klucze SSH. Choć są zakodowane w base64, domyślnie nie są szyfrowane w spoczynku.
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: webapp-secrets
type: Opaque
# Values must be base64-encoded
data:
# echo -n 'admin' | base64
username: YWRtaW4=
# echo -n 'supersecretpassword' | base64
password: c3VwZXJzZWNyZXRwYXNzd29yZA==
---
# Alternative: stringData accepts plain text values
apiVersion: v1
kind: Secret
metadata:
name: webapp-secrets-plain
type: Opaque
stringData:
username: admin
password: supersecretpasswordSecrets są wstrzykiwane w taki sam sposób jak ConfigMaps.
# deployment-with-secrets.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-secure
spec:
replicas: 1
selector:
matchLabels:
app: webapp-secure
template:
metadata:
labels:
app: webapp-secure
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: webapp-secrets
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: webapp-secrets
key: password# terminal
# Create the Secret
kubectl apply -f secret.yaml
# List Secrets (values are not displayed)
kubectl get secrets
# NAME TYPE DATA AGE
# webapp-secrets Opaque 2 10s
# Decode a value
kubectl get secret webapp-secrets -o jsonpath='{.data.password}' | base64 -d
# supersecretpasswordNamespaces: izolacja logiczna
Namespaces dzielą klaster na izolowane środowiska wirtualne. Ten podział pozwala zarządzać wieloma zespołami lub środowiskami w tym samym klastrze.
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
environment: development
---
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: stagingKażdy zasób można utworzyć w określonym namespace.
# terminal
# Create namespaces
kubectl apply -f namespace.yaml
# List namespaces
kubectl get namespaces
# NAME STATUS AGE
# default Active 1d
# development Active 10s
# staging Active 10s
# Create a resource in a specific namespace
kubectl apply -f deployment.yaml -n development
# List Pods in a namespace
kubectl get pods -n development
# Change default namespace
kubectl config set-context --current --namespace=developmentZasoby z różnych namespace są domyślnie odizolowane. Komunikacja między namespace odbywa się poprzez wewnętrzny DNS: service-name.namespace.svc.cluster.local.
Kompletna aplikacja: złożenie zasobów
Poniżej kompletna aplikacja łącząca wszystkie przedstawione koncepcje.
# complete-app.yaml
---
# Dedicated Namespace
apiVersion: v1
kind: Namespace
metadata:
name: myapp
---
# ConfigMap for configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: myapp
data:
APP_NAME: "MyApp"
LOG_LEVEL: "info"
---
# Secret for sensitive data
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
namespace: myapp
type: Opaque
stringData:
api-key: "sk-1234567890abcdef"
---
# Deployment with 3 replicas
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: myapp-config
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: myapp-secrets
key: api-key
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
---
# Service for internal exposure
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: myapp
spec:
type: ClusterIP
selector:
app: myapp
ports:
- port: 80
targetPort: 80
---
# NodePort Service for external access (development)
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
namespace: myapp
spec:
type: NodePort
selector:
app: myapp
ports:
- port: 80
targetPort: 80
nodePort: 30100Ten jeden plik wdraża kompletną aplikację z zewnętrzną konfiguracją, sekretami, wysoką dostępnością i ekspozycją sieciową.
# terminal
# Deploy the complete application
kubectl apply -f complete-app.yaml
# Verify all resources
kubectl get all -n myapp
# NAME READY STATUS RESTARTS AGE
# pod/myapp-7d9f8b6c4-abc12 1/1 Running 0 30s
# pod/myapp-7d9f8b6c4-def34 1/1 Running 0 30s
# pod/myapp-7d9f8b6c4-ghi56 1/1 Running 0 30s
#
# NAME TYPE CLUSTER-IP PORT(S) AGE
# service/myapp-service ClusterIP 10.96.123.456 80/TCP 30s
# service/myapp-nodeport NodePort 10.96.123.789 80:30100/TCP 30s
#
# NAME READY UP-TO-DATE AVAILABLE AGE
# deployment.apps/myapp 3/3 3 3 30s
# Access the application with minikube
minikube service myapp-nodeport -n myappAktualizacje i rollbacki
Kubernetes ułatwia stopniowe aktualizacje i rollbacki.
# terminal
# Update the Deployment image
kubectl set image deployment/myapp myapp=nginx:1.26-alpine -n myapp
# Track deployment in real-time
kubectl rollout status deployment/myapp -n myapp
# Waiting for deployment "myapp" rollout to finish: 1 out of 3 new replicas updated
# Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas updated
# deployment "myapp" successfully rolled out
# Revision history
kubectl rollout history deployment/myapp -n myapp
# REVISION CHANGE-CAUSE
# 1 <none>
# 2 <none>
# Rollback to previous revision
kubectl rollout undo deployment/myapp -n myapp
# Rollback to a specific revision
kubectl rollout undo deployment/myapp --to-revision=1 -n myappDomyślna strategia aktualizacji (RollingUpdate) stopniowo zastępuje stare Pody nowymi, zapewniając ciągłą dostępność.
Kluczowe polecenia kubectl
# terminal
# ========================================
# General Information
# ========================================
kubectl cluster-info # Cluster info
kubectl get nodes -o wide # Nodes with details
kubectl api-resources # List resource types
# ========================================
# Resource Management
# ========================================
kubectl get all # All namespace resources
kubectl get pods -A # Pods from all namespaces
kubectl get pods -o wide # Pods with IP and Node
kubectl get pods -w # Watch mode (real-time)
# ========================================
# Inspection and Debugging
# ========================================
kubectl describe pod <name> # Full details
kubectl logs <pod> -f # Streaming logs
kubectl logs <pod> -c <container> # Specific container logs
kubectl exec -it <pod> -- /bin/sh # Interactive shell
kubectl port-forward <pod> 8080:80 # Local tunnel to Pod
# ========================================
# Editing and Deletion
# ========================================
kubectl edit deployment <name> # Live editing (vi)
kubectl delete -f manifest.yaml # Delete via file
kubectl delete pod <name> --force # Force deletionPodsumowanie
Kubernetes przekształca zarządzanie aplikacjami konteneryzowanymi, dostarczając deklaratywny, odporny i rozszerzalny framework. Przedstawione tu fundamentalne koncepcje stanowią podstawę wdrożeń gotowych do produkcji.
Lista kontrolna pierwszego wdrożenia Kubernetes
- ✅ Działający lokalny klaster (minikube, kind lub k3d)
- ✅ kubectl zainstalowany i skonfigurowany
- ✅ Deployment z replikami i health probes
- ✅ Service do ekspozycji sieciowej
- ✅ ConfigMap dla zewnętrznej konfiguracji
- ✅ Secret dla wrażliwych danych
- ✅ Namespace dla izolacji
- ✅ Zdefiniowane limity zasobów (requests/limits)
- ✅ Opanowana strategia aktualizacji i rollbacku
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.
Opanowanie Kubernetes otwiera drogę do skalowalnych architektur cloud-native. Kolejne kroki obejmują eksplorację Ingress Controllers do routingu HTTP, PersistentVolumes do przechowywania oraz Helm do zarządzania pakietami. Kubernetes staje się ważnym atutem podczas rozmów kwalifikacyjnych DevOps i SRE.
Tagi
Udostępnij
Powiązane artykuły

Kluczowe pytania rekrutacyjne DevOps: kompletny przewodnik 2026
Przygotuj się do rozmowy kwalifikacyjnej DevOps z pytaniami o CI/CD, Kubernetes, Docker, Terraform i praktyki SRE. Szczegółowe odpowiedzi w jednym miejscu.

Docker: od developmentu do produkcji
Kompletny przewodnik po Dockerze do konteneryzacji aplikacji. Dockerfile, Docker Compose, buildy multi-stage i wdrożenie produkcyjne z praktycznymi przykładami.

Rozmowa kwalifikacyjna z Kubernetes: Pods, Services i Deployments w praktyce
Kompletny przewodnik po pytaniach rekrutacyjnych dotyczących Kubernetes Pods, Services i Deployments z przykładami YAML i strategiami skalowania na 2026 rok.