Migrating from Swarm to Kubernetes
Migrate your Docker Swarm applications to Kubernetes. Learn to convert docker-compose.yml to Kubernetes manifests using Kompose, package applications with Helm charts, and implement a phased migration strategy.
Docker Swarm is excellent for simple, single-team deployments. However, as applications grow in complexity, teams often need features that Swarm doesn't provide. Kubernetes offers advanced capabilities like auto-scaling, self-healing, rolling updates, service meshes, and a vast ecosystem of tools.
Common reasons to migrate include: need for horizontal pod autoscaling (HPA), advanced rolling update strategies (canary, blue-green), multi-cloud deployments, extensive ecosystem (Helm, operators, service meshes), and larger community support. While Swarm is simpler, Kubernetes provides enterprise-grade features for scaling and resilience.
Migrating from Swarm to Kubernetes involves several steps. The good news is that your Docker images and containerized applications work exactly the same way. The main work is translating Swarm concepts (services, networks, volumes, secrets) to Kubernetes concepts (deployments, services, ingress, persistent volumes, secrets).
# Migration path
1. Audit your current Swarm stack
docker stack ls
docker service ls
docker network ls
docker secret ls
2. Convert docker-compose.yml to Kubernetes manifests
kompose convert -f docker-compose.yml
3. Review and adjust generated YAML files
4. Deploy to a test Kubernetes cluster
kubectl apply -f .
5. Run parallel testing (Swarm + K8s)
6. Gradual traffic shift (load balancer)
7. Decommission Swarm services
| Docker Swarm | Kubernetes |
|---|---|
| Service (with replicas)攀 | Deployment (with replicas)攀 |
| Service (with published ports)攀 | Service (ClusterIP/NodePort/LoadBalancer)攀 |
| Overlay network攀 | Service discovery (DNS) + Network Policies攀 |
| Config (docker config)攀 | ConfigMap攀 |
| Secret攀 | Secret (base64 encoded)攀 |
| Volume (named volumes)攀 | PersistentVolumeClaim + StorageClass攀 |
| Stack (compose file)攀 | Namespace + multiple YAMLs or Helm chart攀 |
Kompose (Kubernetes + Compose) is a tool that converts Docker Compose files to Kubernetes manifests. It's the fastest way to get started with migration.
# Install Kompose
# macOS
brew install kompose
# Linux
curl -L https://github.com/kubernetes/kompose/releases/latest/download/kompose-linux-amd64 -o kompose
chmod +x kompose
sudo mv kompose /usr/local/bin/
# Windows (chocolatey)
choco install kubernetes-kompose
# Basic conversion
kompose convert -f docker-compose.yml
# Convert and output to specific files
kompose convert -f docker-compose.yml -o k8s-manifests/
# Convert with specific options
kompose convert -f docker-compose.yml \
--controller deployment \
--service-node-port-range 30000-32767
# Convert and deploy directly
kompose up -f docker-compose.yml
# Convert with custom namespace
kompose convert -f docker-compose.yml --namespace myapp
# Convert multi-file compose
kompose convert -f docker-compose.yml -f docker-compose.prod.yml
# docker-compose.yml (Swarm)
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
deploy:
replicas: 3
networks:
- webnet
redis:
image: redis:alpine
networks:
- webnet
networks:
webnet:
driver: overlay
# After running: kompose convert -f docker-compose.yml
# Generated: web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
io.kompose.service: web
template:
metadata:
labels:
io.kompose.service: web
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80
# Generated: web-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
spec:
ports:
- port: 80
targetPort: 80
selector:
io.kompose.service: web
type: LoadBalancer
Helm is the package manager for Kubernetes. It helps you define, install, and upgrade complex Kubernetes applications. After converting your Compose file, consider packaging your manifests as a Helm chart for easier management and parameterization.
# Install Helm
# macOS
brew install helm
# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Windows
choco install kubernetes-helm
# Create a new chart
helm create myapp-chart
# Convert kompose output to Helm chart
mkdir myapp-chart/templates
cp *.yaml myapp-chart/templates/
# Edit values.yaml for configuration
cat > myapp-chart/values.yaml <
Swarm named volumes don't translate directly to Kubernetes. You need to understand PersistentVolumes (PV) and PersistentVolumeClaims (PVC). For stateful applications, use StatefulSets instead of Deployments.
# Swarm volume
volumes:
postgres_data:
driver: local
# Kubernetes equivalent: PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# StatefulSet for databases (instead of Deployment)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
Swarm secrets are encrypted. Kubernetes secrets are base64 encoded (not encrypted by default). For production, use external secret managers or encryption at rest.
# Swarm secret
echo "mypassword" | docker secret create db_password -
# Kubernetes secret (base64 encoded)
kubectl create secret generic db-password --from-literal=password=mypassword
# Or from file
kubectl create secret generic db-password --from-file=./password.txt
# Use secret in pod
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-password
key: password
# For better security, use external secret manager like HashiCorp Vault
# or enable encryption at rest in Kubernetes
# Phase 1: Audit and Plan
docker service ls
docker network ls
docker secret ls
docker volume ls
# Phase 2: Convert stateless services first
kompose convert -f docker-compose.yml --controller deployment
kubectl apply -f .
# Phase 3: Test in parallel
# Keep Swarm services running while testing K8s
# Use separate namespace: kubectl create namespace migration-test
# Phase 4: Gradual traffic shift with load balancer
# Configure your load balancer to split traffic:
# 10% to K8s, 90% to Swarm
# Gradually increase K8s percentage
# Phase 5: Migrate stateful services
# Convert volumes to PVCs, use StatefulSets
# Perform backup and restore if needed
# Phase 6: Decommission Swarm
docker service rm $(docker service ls -q)
docker stack rm myapp
docker swarm leave --force
- Network mode differences - Swarm's overlay networks are automatic. In Kubernetes, services discover each other via DNS. Use service names.
- Load balancing - Swarm's routing mesh is built-in. Kubernetes requires Service type LoadBalancer or Ingress.
- Configuration management - Swarm configs become Kubernetes ConfigMaps.
- Secret management - Kubernetes secrets are base64 encoded. Consider external secret managers for encryption.
- Health checks - Swarm health checks become Kubernetes liveness and readiness probes.
- Resource limits - Swarm deploy.resources becomes Kubernetes resources.limits/requests.
- Rolling updates - Swarm update_config becomes Kubernetes strategy.rollingUpdate.
- Start small - Migrate a non-critical service first to learn the process.
- Use namespaces - Isolate migrated services in separate namespaces.
- Version your manifests - Store Kubernetes YAML files in Git.
- Use Helm for complex apps - Makes configuration and upgrades easier.
- Implement monitoring first - Set up Prometheus/Grafana before migration.
- Test rollback procedures - Know how to switch back to Swarm quickly.
- Document everything - Record changes, issues, and solutions.
- Train your team - Ensure everyone understands Kubernetes concepts.
Migrating from Swarm to Kubernetes is a journey. Start small, use Kompose to get started, and adopt Helm for production-ready packaging.