Files
k3s/.claude/skills/minio/s3.md
2026-02-05 00:11:05 +08:00

790 lines
18 KiB
Markdown

---
name: minio-s3-expert
description: 提供 MinIO 对象存储的配置、Bucket 管理及 S3 API 调用建议。
---
# MinIO S3 Object Storage Skill
## Architecture Overview
**Setup**: Caddy (HTTPS/SSL) → Traefik (routing) → MinIO (S3 storage)
- **MinIO**: S3-compatible object storage with web console
- **Caddy**: Handles HTTPS (443) with automatic SSL certificates
- **Traefik**: Routes HTTP traffic to MinIO services
- **Policy Manager**: Automatically sets new buckets to public-read (download) permission
- **Flow**: Internet → Caddy:443 (HTTPS) → Traefik:80 (HTTP) → MinIO (9000: API, 9001: Console)
## Quick Deployment Template
### 1. Complete MinIO Deployment YAML
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: minio
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio-data
namespace: minio
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: local-path
---
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
command:
- /bin/sh
- -c
- minio server /data --console-address ":9001"
ports:
- containerPort: 9000
name: api
- containerPort: 9001
name: console
env:
- name: MINIO_ROOT_USER
value: "admin"
- name: MINIO_ROOT_PASSWORD
value: "your-password-here"
- name: MINIO_SERVER_URL
value: "https://s3.yourdomain.com"
- name: MINIO_BROWSER_REDIRECT_URL
value: "https://console.s3.yourdomain.com"
volumeMounts:
- name: data
mountPath: /data
livenessProbe:
httpGet:
path: /minio/health/live
port: 9000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /minio/health/ready
port: 9000
initialDelaySeconds: 10
periodSeconds: 5
- name: policy-manager
image: alpine:latest
command:
- /bin/sh
- -c
- |
# Install MinIO Client
wget https://dl.min.io/client/mc/release/linux-arm64/mc -O /usr/local/bin/mc
chmod +x /usr/local/bin/mc
# Wait for MinIO to start
sleep 10
# Configure mc client
mc alias set myminio http://localhost:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}
echo "Policy manager started. Monitoring buckets..."
# Continuously monitor and set bucket policies
while true; do
# Get all buckets
mc ls myminio 2>/dev/null | awk '{print $NF}' | sed 's/\///' | while read -r BUCKET; do
if [ -n "$BUCKET" ]; then
# Check current policy
POLICY_OUTPUT=$(mc anonymous get myminio/${BUCKET} 2>&1)
# If private (contains "Access permission for" but not "download")
if echo "$POLICY_OUTPUT" | grep -q "Access permission for" && ! echo "$POLICY_OUTPUT" | grep -q "download"; then
echo "Setting download policy for bucket: ${BUCKET}"
mc anonymous set download myminio/${BUCKET}
fi
fi
done
sleep 30
done
env:
- name: MINIO_ROOT_USER
value: "admin"
- name: MINIO_ROOT_PASSWORD
value: "your-password-here"
volumes:
- name: data
persistentVolumeClaim:
claimName: minio-data
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: minio
spec:
type: ClusterIP
ports:
- port: 9000
targetPort: 9000
name: api
- port: 9001
targetPort: 9001
name: console
selector:
app: minio
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minio-api
namespace: minio
spec:
ingressClassName: traefik
rules:
- host: s3.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio
port:
number: 9000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minio-console
namespace: minio
spec:
ingressClassName: traefik
rules:
- host: console.s3.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio
port:
number: 9001
```
### 2. Configuration Checklist
Before deploying, update these values in the YAML:
**Domains (4 places):**
- `s3.yourdomain.com` → Your S3 API domain
- `console.s3.yourdomain.com` → Your console domain
**Credentials (4 places):**
- `MINIO_ROOT_USER: "admin"` → Your admin username
- `MINIO_ROOT_PASSWORD: "your-password-here"` → Your admin password (min 8 chars)
**Architecture (1 place):**
- `linux-arm64` → Change based on your CPU:
- ARM64: `linux-arm64`
- x86_64: `linux-amd64`
**Storage (1 place):**
- `storage: 50Gi` → Adjust storage size as needed
## Deployment Steps
### 1. Prepare DNS
Point your domains to the server IP:
```bash
# Add DNS A records
s3.yourdomain.com A your-server-ip
console.s3.yourdomain.com A your-server-ip
```
### 2. Configure Caddy
Add domains to Caddy ConfigMap:
```bash
kubectl edit configmap caddy-config -n default
```
Add these blocks:
```caddy
s3.yourdomain.com {
reverse_proxy traefik.kube-system.svc.cluster.local:80 {
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
}
}
console.s3.yourdomain.com {
reverse_proxy traefik.kube-system.svc.cluster.local:80 {
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
}
}
```
Reload Caddy:
```bash
kubectl exec -n default deployment/caddy -- caddy reload --config /etc/caddy/Caddyfile
```
### 3. Deploy MinIO
```bash
# Apply the configuration
kubectl apply -f minio.yaml
# Check deployment status
kubectl get pods -n minio
# Wait for pods to be ready
kubectl wait --for=condition=ready pod -l app=minio -n minio --timeout=300s
```
### 4. Verify Deployment
```bash
# Check MinIO logs
kubectl logs -n minio -l app=minio -c minio
# Check policy manager logs
kubectl logs -n minio -l app=minio -c policy-manager
# Check ingress
kubectl get ingress -n minio
# Check service
kubectl get svc -n minio
```
## Access MinIO
### Web Console
- URL: `https://console.s3.yourdomain.com`
- Username: Your configured `MINIO_ROOT_USER`
- Password: Your configured `MINIO_ROOT_PASSWORD`
### S3 API Endpoint
- URL: `https://s3.yourdomain.com`
- Use with AWS CLI, SDKs, or any S3-compatible client
## Bucket Policy Management
### Automatic Public-Read Policy
The policy manager sidecar automatically:
- Scans all buckets every 30 seconds
- Sets new private buckets to `download` (public-read) permission
- Allows anonymous downloads, requires auth for uploads/deletes
### Manual Policy Management
```bash
# Get pod name
POD=$(kubectl get pod -n minio -l app=minio -o jsonpath='{.items[0].metadata.name}')
# Access MinIO Client in pod
kubectl exec -n minio $POD -c policy-manager -- mc alias set myminio http://localhost:9000 admin your-password
# List buckets
kubectl exec -n minio $POD -c policy-manager -- mc ls myminio
# Check bucket policy
kubectl exec -n minio $POD -c policy-manager -- mc anonymous get myminio/bucket-name
# Set bucket to public-read (download)
kubectl exec -n minio $POD -c policy-manager -- mc anonymous set download myminio/bucket-name
# Set bucket to private
kubectl exec -n minio $POD -c policy-manager -- mc anonymous set private myminio/bucket-name
# Set bucket to public (read + write)
kubectl exec -n minio $POD -c policy-manager -- mc anonymous set public myminio/bucket-name
```
## Using MinIO
### Create Bucket via Web Console
1. Access `https://console.s3.yourdomain.com`
2. Login with credentials
3. Click "Buckets" → "Create Bucket"
4. Enter bucket name
5. Wait 30 seconds for auto-policy to apply
### Upload Files via Web Console
1. Navigate to bucket
2. Click "Upload" → "Upload File"
3. Select files
4. Files are immediately accessible via public URL
### Access Files
Public URL format:
```
https://s3.yourdomain.com/bucket-name/file-path
```
Example:
```bash
# Upload via console, then access:
curl https://s3.yourdomain.com/my-bucket/image.png
```
### Using AWS CLI
```bash
# Configure AWS CLI
aws configure set aws_access_key_id admin
aws configure set aws_secret_access_key your-password
aws configure set default.region us-east-1
# List buckets
aws --endpoint-url https://s3.yourdomain.com s3 ls
# Create bucket
aws --endpoint-url https://s3.yourdomain.com s3 mb s3://my-bucket
# Upload file
aws --endpoint-url https://s3.yourdomain.com s3 cp file.txt s3://my-bucket/
# Download file
aws --endpoint-url https://s3.yourdomain.com s3 cp s3://my-bucket/file.txt ./
# List bucket contents
aws --endpoint-url https://s3.yourdomain.com s3 ls s3://my-bucket/
```
### Using MinIO Client (mc)
```bash
# Install mc locally
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
# Configure alias
mc alias set myminio https://s3.yourdomain.com admin your-password
# List buckets
mc ls myminio
# Create bucket
mc mb myminio/my-bucket
# Upload file
mc cp file.txt myminio/my-bucket/
# Download file
mc cp myminio/my-bucket/file.txt ./
# Mirror directory
mc mirror ./local-dir myminio/my-bucket/remote-dir
```
## Common Operations
### View Logs
```bash
# MinIO server logs
kubectl logs -n minio -l app=minio -c minio -f
# Policy manager logs
kubectl logs -n minio -l app=minio -c policy-manager -f
# Both containers
kubectl logs -n minio -l app=minio --all-containers -f
```
### Restart MinIO
```bash
# Graceful restart
kubectl rollout restart deployment/minio -n minio
# Force restart (delete pod)
kubectl delete pod -n minio -l app=minio
```
### Scale Storage
```bash
# Edit PVC (note: can only increase, not decrease)
kubectl edit pvc minio-data -n minio
# Update storage size
# Change: storage: 50Gi → storage: 100Gi
```
### Backup Data
```bash
# Get pod name
POD=$(kubectl get pod -n minio -l app=minio -o jsonpath='{.items[0].metadata.name}')
# Copy data from pod
kubectl cp minio/$POD:/data ./minio-backup -c minio
# Or use mc mirror
mc mirror myminio/bucket-name ./backup/bucket-name
```
### Restore Data
```bash
# Copy data to pod
kubectl cp ./minio-backup minio/$POD:/data -c minio
# Restart MinIO
kubectl rollout restart deployment/minio -n minio
# Or use mc mirror
mc mirror ./backup/bucket-name myminio/bucket-name
```
## Troubleshooting
### Pod Not Starting
```bash
# Check pod status
kubectl describe pod -n minio -l app=minio
# Check events
kubectl get events -n minio --sort-by='.lastTimestamp'
# Common issues:
# - PVC not bound (check storage class)
# - Image pull error (check network/registry)
# - Resource limits (check node resources)
```
### Cannot Access Web Console
```bash
# Check ingress
kubectl get ingress -n minio
kubectl describe ingress minio-console -n minio
# Check service
kubectl get svc -n minio
# Test from inside cluster
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- curl -v http://minio.minio.svc.cluster.local:9001
# Check Caddy logs
kubectl logs -n default -l app=caddy | grep -i s3
# Check Traefik logs
kubectl logs -n kube-system -l app.kubernetes.io/name=traefik
```
### SSL Certificate Issues
```bash
# Check Caddy certificates
kubectl exec -n default deployment/caddy -- caddy list-certificates
# Check Caddy logs for ACME
kubectl logs -n default deployment/caddy | grep -i "s3\|acme\|certificate"
# Verify DNS resolution
nslookup s3.yourdomain.com
nslookup console.s3.yourdomain.com
```
### Policy Manager Not Working
```bash
# Check policy manager logs
kubectl logs -n minio -l app=minio -c policy-manager
# Manually test mc commands
POD=$(kubectl get pod -n minio -l app=minio -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n minio $POD -c policy-manager -- mc ls myminio
# Restart policy manager (restart pod)
kubectl delete pod -n minio -l app=minio
```
### Files Not Accessible
```bash
# Check bucket policy
kubectl exec -n minio $POD -c policy-manager -- mc anonymous get myminio/bucket-name
# Should show: Access permission for `myminio/bucket-name` is set to `download`
# If not, manually set
kubectl exec -n minio $POD -c policy-manager -- mc anonymous set download myminio/bucket-name
# Test access
curl -I https://s3.yourdomain.com/bucket-name/file.txt
```
## Advanced Configuration
### Custom Storage Class
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio-data
namespace: minio
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: fast-ssd # Custom storage class
```
### Resource Limits
```yaml
containers:
- name: minio
image: minio/minio:latest
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
```
### Multiple Replicas (Distributed Mode)
For production, use distributed MinIO:
```yaml
# Requires 4+ nodes with persistent storage
command:
- /bin/sh
- -c
- minio server http://minio-{0...3}.minio.minio.svc.cluster.local/data --console-address ":9001"
```
### Custom Bucket Policies
Create custom policy JSON:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": ["*"]},
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::bucket-name/*"]
}
]
}
```
Apply via mc:
```bash
kubectl exec -n minio $POD -c policy-manager -- mc anonymous set-json policy.json myminio/bucket-name
```
### Disable Auto-Policy Manager
Remove the `policy-manager` container from deployment if you want manual control.
## Best Practices
### Bucket Naming
- Use lowercase letters, numbers, hyphens
- Avoid underscores, spaces, special characters
- Keep names short and descriptive
- Example: `user-uploads`, `static-assets`, `backups-2024`
### Folder Structure
Use prefixes (folders) to organize files:
```
bucket-name/
├── user1/
│ ├── profile.jpg
│ └── documents/
├── user2/
│ └── avatar.png
└── shared/
└── logo.png
```
### Security
- Change default credentials immediately
- Use strong passwords (16+ characters)
- Create separate access keys for applications
- Use bucket policies to restrict access
- Enable versioning for important buckets
- Regular backups of critical data
### Performance
- Use CDN for frequently accessed files
- Enable compression for text files
- Use appropriate storage class
- Monitor disk usage and scale proactively
## Quick Reference Commands
```bash
# Deploy MinIO
kubectl apply -f minio.yaml
# Check status
kubectl get pods -n minio
kubectl get svc -n minio
kubectl get ingress -n minio
# View logs
kubectl logs -n minio -l app=minio -c minio -f
kubectl logs -n minio -l app=minio -c policy-manager -f
# Restart MinIO
kubectl rollout restart deployment/minio -n minio
# Get pod name
POD=$(kubectl get pod -n minio -l app=minio -o jsonpath='{.items[0].metadata.name}')
# Access mc client
kubectl exec -n minio $POD -c policy-manager -- mc ls myminio
# Check bucket policy
kubectl exec -n minio $POD -c policy-manager -- mc anonymous get myminio/bucket-name
# Set bucket policy
kubectl exec -n minio $POD -c policy-manager -- mc anonymous set download myminio/bucket-name
# Delete deployment
kubectl delete -f minio.yaml
```
## Integration Examples
### Node.js (AWS SDK)
```javascript
const AWS = require('aws-sdk');
const s3 = new AWS.S3({
endpoint: 'https://s3.yourdomain.com',
accessKeyId: 'admin',
secretAccessKey: 'your-password',
s3ForcePathStyle: true,
signatureVersion: 'v4'
});
// Upload file
s3.putObject({
Bucket: 'my-bucket',
Key: 'file.txt',
Body: 'Hello World'
}, (err, data) => {
if (err) console.error(err);
else console.log('Uploaded:', data);
});
// Download file
s3.getObject({
Bucket: 'my-bucket',
Key: 'file.txt'
}, (err, data) => {
if (err) console.error(err);
else console.log('Content:', data.Body.toString());
});
```
### Python (boto3)
```python
import boto3
s3 = boto3.client('s3',
endpoint_url='https://s3.yourdomain.com',
aws_access_key_id='admin',
aws_secret_access_key='your-password'
)
# Upload file
s3.upload_file('local-file.txt', 'my-bucket', 'remote-file.txt')
# Download file
s3.download_file('my-bucket', 'remote-file.txt', 'downloaded.txt')
# List objects
response = s3.list_objects_v2(Bucket='my-bucket')
for obj in response.get('Contents', []):
print(obj['Key'])
```
### Go (minio-go)
```go
package main
import (
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
func main() {
client, _ := minio.New("s3.yourdomain.com", &minio.Options{
Creds: credentials.NewStaticV4("admin", "your-password", ""),
Secure: true,
})
// Upload file
client.FPutObject(ctx, "my-bucket", "file.txt", "local-file.txt", minio.PutObjectOptions{})
// Download file
client.FGetObject(ctx, "my-bucket", "file.txt", "downloaded.txt", minio.GetObjectOptions{})
}
```
## Notes
- MinIO is fully S3-compatible
- Automatic SSL via Caddy
- Auto-policy sets buckets to public-read by default
- Policy manager runs every 30 seconds
- Persistent storage required for data retention
- Single replica suitable for development/small deployments
- Use distributed mode for production high-availability
- Regular backups recommended for critical data