Securing Stateful Apps in Kubernetes: MySQL with Persistent Volumes & RBAC
Learn how to deploy stateful applications securely in Kubernetes while enforcing storage security and Pod hardening. We'll deploy MySQL with Persistent Volumes (PVs) while implementing RBAC, Pod Security Admission (PSA), and Secret management.
π Why This Matters
Stateful applications like databases require special attention in Kubernetes:
- Data persistence: Storage must survive Pod restarts
- Security: Sensitive credentials and storage access need protection
- Compliance: Pods should follow security best practices by default
π οΈ Key Security Practices
- RBAC: Limit access to storage resources
- Pod Security Admission: Enforce security contexts
- Secrets Management: Encrypt sensitive credentials
- Persistent Storage: Use PVs/PVCs for data persistence
π Deployment Walkthrough
Prerequisites
- Minikube (with Docker driver)
- kubectl
minikube start --driver=docker
**1. Create Dedicated Namespace**
bash
kubectl create namespace secure-storage
2. RBAC Configuration
Role Definition (rbac-role.yaml):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: secure-storage
name: storage-manager-role
rules:
- apiGroups: [""]
resources: ["pods", "persistentvolumeclaims"]
verbs: ["get", "list", "create", "delete"]
Role Binding (rbac-binding.yaml):
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: storage-manager-binding
namespace: secure-storage
subjects:
- kind: ServiceAccount
name: default
namespace: secure-storage
roleRef:
kind: Role
name: storage-manager-role
apiGroup: rbac.authorization.k8s.io
Apply RBAC rules:
kubectl apply -f rbac-role.yaml
kubectl apply -f rbac-binding.yaml
3. Persistent Storage Setup
Persistent Volume (pv.yaml):
apiVersion: v1
kind: PersistentVolume
metadata:
name: secure-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
Persistent Volume Claim (pvc.yaml):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: secure-pvc
namespace: secure-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
Create storage resources:
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
4. MySQL Deployment with Secrets
Create Database Credentials:
kubectl create secret generic mysql-secret \
--from-literal=mysql-root-password=root_password \
--from-literal=mysql-user=user \
--from-literal=mysql-password=user_password \
--namespace secure-storage
StatefulSet Configuration (mysql-statefulset.yaml):
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: secure-mysql
namespace: secure-storage
spec:
serviceName: "mysql-service"
replicas: 1
template:
metadata:
labels:
app: secure-mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-root-password
# ... full config in GitHub repo
volumeClaimTemplates:
- metadata:
name: mysql-storage
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 500Mi
5. Enforce Pod Security
Apply restricted PSA policy:
kubectl label namespace secure-storage \
pod-security.kubernetes.io/enforce=restricted \
--overwrite
π§ͺ Security Validation
Test PSA Enforcement:
kubectl apply -f non-compliant-pod.yaml -n secure-storage
# Expected error: violates PodSecurity "restricted:latest"
Verify RBAC Restrictions:
kubectl delete pod --namespace kube-system
# Error: User cannot delete resources in kube-system
β Key Outcomes
Secure Storage: PVs/PVCs with RBAC-controlled access
Secret Protection: Sensitive data encrypted at rest
Pod Hardening: PSA enforces security contexts
Auditability: Clear access boundaries through roles
π Full Code & Contribution
Explore the complete implementation and contribute:
π¬ Discussion Points
How do you handle storage security in your Kubernetes clusters?
What additional security measures do you implement for stateful workloads?
Have you tried the new PSA policies in production?
Let's discuss in the comments! π
Top comments (0)