我有一个小的Saas应用程序,客户可以注册,他们可以获得自己的实例,与其他客户端完全分离。它是一个简单的REST API,带有一个数据库(postgres)和一个使用docker-compose部署的caddy。
这工作得很好,但需要我创建VPS,部署不同的服务,并且基本上很难管理,因为我的大部分工作都是手动的。
我已经决定使用kubernetes,并且我已经达到了这样的地步:我可以为每个客户端在它自己的独立命名空间上创建系统的单独实例,完全自动化。这将创建不同的部署、服务和pod。另外,我为每个名称空间/客户机创建了一个PVC。
这个问题与持久卷声明以及它们在命名空间中的工作方式有关。因为我想保持数据与其他实例完全分离,所以我想为每个客户端创建一个PVC,这样只有来自该客户端的DB可以访问它(以及服务器,因为它需要将一些数据写入磁盘)。
这在minikube中工作得很好,但问题出在主机提供商身上。我使用DigitalOcean的托管集群,它们不允许创建多个pvc,因此无法实现我想要的隔离级别。它们允许您挂载块存储(无论您需要的大小),然后使用它。这意味着所有数据都存储在"相同的磁盘"上,并且所有名称空间都可以访问它。
我的问题是:是否有一种方法可以实现相同级别的隔离,即为每个DB实例分离挂载点,以这样一种方式,我仍然可以实现(或至少接近)我需要的隔离级别?这个想法可能是这样的:
/pvc-root
/client1
/server
/db
/client2
/server
/db
...
这是我现在的内容:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
labels:
io.kompose.service: database-claim
name: database-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
labels:
io.kompose.service: database
name: database
spec:
ports:
- name: "5432"
port: 5432
targetPort: 5432
selector:
io.kompose.service: database
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
io.kompose.service: database
name: database
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: database
strategy:
type: Recreate
template:
metadata:
labels:
io.kompose.service: database
spec:
containers:
- env:
- name: POSTGRES_DB
value: db_name
- name: POSTGRES_PASSWORD
value: db_password
- name: POSTGRES_USER
value: db_user
image: postgres:10
imagePullPolicy: ""
name: postgres
ports:
- containerPort: 5432
resources: {}
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: database-claim
restartPolicy: Always
serviceAccountName: ""
volumes:
- name: database-claim
persistentVolumeClaim:
claimName: database-claim
---
apiVersion: v1
kind: Service
metadata:
labels:
io.kompose.service: server
name: server
spec:
ports:
- name: "8080"
port: 8080
targetPort: 8080
selector:
io.kompose.service: server
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
io.kompose.service: server
name: server
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: server
template:
metadata:
labels:
io.kompose.service: server
spec:
containers:
- env:
- name: DB_HOST
value: database
- name: DB_NAME
value: db_name
- name: DB_PASSWORD
value: db_password
- name: DB_PORT
value: "5432"
- name: DB_USERNAME
value: db_user
image: <REDACTED>
name: server-image
ports:
- containerPort: 8080
restartPolicy: Always
volumes: null
编辑2012.02
我一直在与DO的客户支持联系,他们澄清了一些事情:
- 由于需要手动将卷挂载到集群,因此忽略了PVC部署文件。然后卷被挂载并可供集群使用,但不是在ReadWriteMany配置中,这可以很好地服务于这种情况
- 他们提供了一个API,所以理论上我可以以编程方式创建卷(为每个客户端),然后为特定客户端附加一个卷,保持ReadWriteOnce
- 这当然把我锁定在他们作为供应商,并使事情更难配置和迁移
我仍在寻找建议,这是否是我的情况下正确的方法。如果你有更好的方法,请告诉我!
理论上这是可以实现的
是否有一种方法可以实现相同级别的隔离,即为每个DB实例分离挂载点,以这种方式,我仍然可以实现(或至少接近)我需要的分离级别?
不要使用单个卷运行生产数据库。您希望运行具有某种形式复制的数据库,以防卷或节点崩溃。
要么在分布式设置中运行数据库,例如使用Crunchy PostgreSQL for Kubernetes,要么使用托管数据库,例如DigitalOcean托管数据库
在这个DBMS中,为每个客户创建逻辑数据库或模式——如果你真的需要这种强隔离。提示:使用更少的隔离可能更容易维护,例如在表中使用多租户。
来得太晚了,但如果您还没有找到解决方案,这里有一个解决方案可能对您的用例来说是个好兆头。
创建一个高可用的NFS/CEPH
服务器,然后以一种您的pod可以连接到它的方式导出它。然后根据需要创建PV
和PVC
,绕过所有DO阻塞。
您有一个与您描述的我支持的应用程序非常相似,我使用DRBD
,Corosync
和Pacemaker
使用高度可用的NFS
服务器,并且它都按预期工作。到目前为止没有问题。