MinIO#
Deploy MinIO for S3-compatible object storage on Kubernetes.
Overview#
MinIO is a high-performance, S3-compatible object storage system. Use cases include:
- Data lake storage
- Backup and archival
- Machine learning dataset storage
- Application data storage
- Alternative to AWS S3 for on-premise workloads
Features#
- S3 Compatible: Drop-in replacement for Amazon S3
- High Performance: Optimized for modern hardware
- Erasure Coding: Data protection and redundancy
- Encryption: Server-side and client-side encryption
- Access Control: IAM-compatible policies
- Event Notifications: Webhook, NATS, Kafka integrations
Quick Start#
Development Deployment#
For testing and development:
kubectl apply -f minio/minio-dev.yamlThis creates a single-node MinIO instance with:
- 10Gi ephemeral storage
- Default credentials (change in production!)
- No persistence (data lost on pod restart)
Production Deployment#
For production use with persistent storage:
kubectl apply -f minio/minio.yamlThis creates:
- StatefulSet with persistent volumes
- Service for cluster access
- Optional ingress for external access
- Configurable storage backend
Configuration#
Production Deployment Example#
apiVersion: v1
kind: Namespace
metadata:
name: minio
labels:
name: minio
---
apiVersion: v1
kind: Secret
metadata:
name: minio-secret
namespace: minio
type: Opaque
stringData:
rootUser: minioadmin
rootPassword: changeme123 # Change this!
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio-pvc
namespace: minio
spec:
accessModes:
- ReadWriteOnce
storageClassName: openebs-zfs
resources:
requests:
storage: 100Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio
namespace: minio
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio:latest
args:
- server
- /data
- --console-address
- ":9001"
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: minio-secret
key: rootUser
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: minio-secret
key: rootPassword
ports:
- containerPort: 9000
name: api
- containerPort: 9001
name: console
volumeMounts:
- name: storage
mountPath: /data
volumes:
- name: storage
persistentVolumeClaim:
claimName: minio-pvc
---
apiVersion: v1
kind: Service
metadata:
name: minio-service
namespace: minio
spec:
type: ClusterIP
ports:
- port: 9000
targetPort: 9000
name: api
- port: 9001
targetPort: 9001
name: console
selector:
app: minioCreate Secrets#
# Create namespace
kubectl create namespace minio
# Create secrets
kubectl create secret generic minio-secret \
--from-literal=rootUser=minioadmin \
--from-literal=rootPassword=YourSecurePassword123 \
-n minioAccess MinIO#
Web Console#
Forward port for web console:
kubectl port-forward -n minio service/minio-service 9001:9001Then open http://localhost:9001 in your browser.
API Access#
Forward API port:
kubectl port-forward -n minio service/minio-service 9000:9000Via Ingress#
Create an ingress for external access:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minio-ingress
namespace: minio
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
rules:
- host: minio.carlboettiger.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio-service
port:
number: 9000
tls:
- hosts:
- minio.carlboettiger.info
secretName: minio-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minio-console-ingress
namespace: minio
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
rules:
- host: minio-console.carlboettiger.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio-service
port:
number: 9001
tls:
- hosts:
- minio-console.carlboettiger.info
secretName: minio-console-tlsUsage#
Using MinIO Client (mc)#
Install MinIO client:
# Linux
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
# macOS
brew install minio/stable/mcConfigure client:
# For local port-forward
mc alias set myminio http://localhost:9000 minioadmin YourPassword
# For external access
mc alias set myminio https://minio.carlboettiger.info minioadmin YourPasswordBasic operations:
# Create bucket
mc mb myminio/mybucket
# List buckets
mc ls myminio
# Upload file
mc cp file.txt myminio/mybucket/
# Download file
mc cp myminio/mybucket/file.txt .
# Sync directory
mc mirror local-dir/ myminio/mybucket/Using Python (boto3)#
import boto3
from botocore.client import Config
# Configure S3 client
s3 = boto3.client('s3',
endpoint_url='https://minio.carlboettiger.info',
aws_access_key_id='minioadmin',
aws_secret_access_key='YourPassword',
config=Config(signature_version='s3v4'),
region_name='us-east-1'
)
# Create bucket
s3.create_bucket(Bucket='mybucket')
# Upload file
s3.upload_file('local-file.txt', 'mybucket', 'remote-file.txt')
# Download file
s3.download_file('mybucket', 'remote-file.txt', 'downloaded-file.txt')
# List objects
response = s3.list_objects_v2(Bucket='mybucket')
for obj in response.get('Contents', []):
print(obj['Key'])Using R (aws.s3)#
library(aws.s3)
# Configure
Sys.setenv(
"AWS_S3_ENDPOINT" = "minio.carlboettiger.info",
"AWS_ACCESS_KEY_ID" = "minioadmin",
"AWS_SECRET_ACCESS_KEY" = "YourPassword",
"AWS_DEFAULT_REGION" = "us-east-1"
)
# List buckets
bucketlist()
# Upload file
put_object("local-file.csv", object = "remote-file.csv", bucket = "mybucket")
# Download file
save_object("remote-file.csv", bucket = "mybucket", file = "downloaded.csv")Management#
Create Users#
Via console or mc:
# Create user
mc admin user add myminio newuser newpassword
# Create policy
cat > readonly.json <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::mybucket/*"]
}]
}
EOF
mc admin policy add myminio readonly readonly.json
# Assign policy to user
mc admin policy set myminio readonly user=newuserBucket Policies#
Set public read access:
mc anonymous set download myminio/mybucketCustom policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": ["*"]},
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::mybucket/public/*"]
}
]
}Lifecycle Policies#
Auto-delete old objects:
<LifecycleConfiguration>
<Rule>
<ID>DeleteOld</ID>
<Status>Enabled</Status>
<Filter>
<Prefix>logs/</Prefix>
</Filter>
<Expiration>
<Days>30</Days>
</Expiration>
</Rule>
</LifecycleConfiguration>Integration with JupyterHub#
Configure JupyterHub to provide MinIO credentials:
singleuser:
extraEnv:
AWS_S3_ENDPOINT: "minio.carlboettiger.info"
AWS_HTTPS: "true"
AWS_VIRTUAL_HOSTING: "FALSE"Users can then access MinIO from notebooks:
import boto3
import os
s3 = boto3.client('s3',
endpoint_url=f"https://{os.environ['AWS_S3_ENDPOINT']}",
aws_access_key_id='your-key',
aws_secret_access_key='your-secret'
)Monitoring#
Check Status#
# Pod status
kubectl get pods -n minio
# Service status
kubectl get svc -n minio
# Storage usage
kubectl exec -n minio deployment/minio -- df -h /dataLogs#
kubectl logs -n minio deployment/minio -fMetrics#
MinIO exports Prometheus metrics at /minio/v2/metrics/cluster.
Backup and Recovery#
Backup Data#
# Using mc mirror
mc mirror myminio/mybucket /backup/mybucket
# Incremental backup
mc mirror --newer-than 1d myminio/mybucket /backup/mybucketRestore Data#
# Restore from backup
mc mirror /backup/mybucket myminio/mybucketExport/Import Configuration#
# Export config
mc admin config export myminio > minio-config.json
# Import config
mc admin config import myminio < minio-config.jsonTroubleshooting#
Connection Refused#
- Check service is running:
kubectl get svc -n minio- Test internal connectivity:
kubectl run -it --rm test --image=curlimages/curl --restart=Never -- \
curl http://minio-service.minio.svc.cluster.local:9000/minio/health/liveAuthentication Failed#
- Verify credentials:
kubectl get secret minio-secret -n minio -o yaml- Check environment variables:
kubectl exec -n minio deployment/minio -- env | grep MINIOStorage Issues#
- Check PVC:
kubectl get pvc -n minio
kubectl describe pvc minio-pvc -n minio- Check disk space:
kubectl exec -n minio deployment/minio -- df -hBest Practices#
- Use Strong Credentials: Change default passwords
- Enable Encryption: Use TLS for all connections
- Backup Regularly: Implement automated backups
- Access Control: Use IAM policies for fine-grained control
- Monitoring: Set up alerts for storage usage
- Versioning: Enable bucket versioning for important data
- Lifecycle Policies: Auto-delete old or temporary data