1. 背景
用户通过 Deployment, Replication Controller 能够不便地在 Kubernetes 中部署一套高可用、可扩大的分布式无状态服务。这类利用不在本地存储数据,通过简略的负载平衡策略可实现申请散发。
Deployment 以及 Replication Controller 是为无状态服务而设计的,它们中 Pod 的名称、主机名、存储都是不稳固的,且 Pod 的启动、销毁程序随机,并不适宜数据库这样的有状态利用。
亚马逊云科技开发者社区为开发者们提供寰球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、流动与比赛等。帮忙中国开发者对接世界最前沿技术,观点,和我的项目,并将中国优良开发者或技术举荐给寰球云社区。如果你还没有关注 / 珍藏,看到这里请肯定不要匆匆划过,点这里让它成为你的技术宝库! |
为此,Kubernetes 推出了面向有状态服务的工作负载 StatefulSet,治理的 Pod 具备如下特点:
- 唯一性 – 对于蕴含 N 个正本的 StatefulSet,每个 Pod 会被调配一个 [0,N] 范畴内的惟一序号。
- 程序性 – StatefulSet 中 Pod 的启动、更新、销毁默认都是按程序进行的。
- 稳固的网络身份标识 – Pod 的主机名、DNS 地址不会随着 Pod 被从新调度而发生变化。
- 稳固的长久化存储 – 当 Pod 被从新调度后,依然能挂载原有的 PersistentVolume,保障了数据的完整性和一致性。
本文针对有状态服务业务场景的数据保护平安需要,旨在从 Amazon EKS 外部联合采纳 StatefulSet, Snapshot Controller 的形式实现有状态服务的存储加密启用,并在测试环境下验证了本计划的可行性。
2. 场景案例
2.1 场景架构
业务场景:
该业务平台构建在亚马逊云上,服务客群次要为全国各医院,外围业务价值在于简化医院洽购结算环节,帮忙医院方降本增效。该平台通过联合医院,医院供应商提供的订单、结算单、发票信息,进行三单验证,并集成银行侧银企直连,进而实现医院的疾速通明领取结算、无效晋升洽购效率。
部署架构:
之前客户在本地 IDC 的 Kubernetes 集群中除了部署了无状态的微服务利用外,还部署了有状态的中间件服务,包含 Redis, Kafka, MySQL,存储应用的是本地磁盘。因为自建 Kubernetes 集群的降级、治理、平安等各方面的运维工作简单,须要消耗大量的运维资源;并且在 Kubernetes 集群中运行有状态的利用,特地是业务数据库,存在很大的潜在危险,因此在迁徙至亚马逊云上的过程中,承受我方倡议做了相应的架构优化及调整:
自建 Kubernetes 调整为托管的 EKS 服务;
- 从 Kubernetes 集群中移除关系数据库 MySQL,替换为托管的 RDS Aurora 服务;
- EKS 中各业务组件采纳无状态部署;
- EKS 中保留 Redis 和 Kafka 等中间件,并采纳有状态部署,长久化采纳 EBS;
- EKS 中采纳 EFS 作为共享存储,实现存储的平安高可用。
架构示意图:
2.2 问题及解决方案
问题形容:
因为波及到订单、结算单、发票等敏感数据的传输及存储,在业务上线后不久,客户心愿增强云上数据安全爱护,联合 KMS 对长久化数据进行主动存储加密。之前有状态服务 Redis, Kafka 等在部署上线时所挂载的 EBS 并未启用加密,因为 EBS 在初始未启用加密的状况下无奈间接开启加密(见上面技术束缚示意图),那么在对业务的影响降至最低的前提下如何实现 EBS 存储加密的开启及业务的平滑迁徙呢?
技术束缚示意图:
初始未加密 EBS 无奈间接启用加密,需对未加密 EBS 做快照,再将未加密快照还原成加密 EBS,如下图所示:
解决方案:
- 计划一:需应用层做数据迁徙,EKS 中原 Redis 等有状态服务放弃不动,采纳 StatefulSet 形式新建 Redis 等有状态服务并启用 EBS 存储加密,在应用层做数据迁徙(将敏感数据从原服务未加密 EBS 迁徙至新建服务已加密 EBS)后将中间件服务切换至新建 Redis 等有状态服务并下线原服务以实现有状态服务的存储加密;
- 计划二:不波及应用层数据迁徙,从亚马逊云科技控制台间接对 EBS 进行相干操作,将未加密 EBS 制作快照后还原成加密 EBS,并将加密 EBS 动态挂载回正确的 Redis 等有状态服务;
- 计划三:不波及应用层数据迁徙,从 EKS 外部进行相干操作,首先启用 Snapshot Controller,之后通过该 Controller 对未加密 pvc 制作快照后还原成加密 pvc,新建 Redis StatefulSet 并挂载加密 pvc,引流至新建 Redis 测试一切正常后做服务迁徙;
因为客户不心愿应用层做数据迁徙,以及从亚马逊云科技控制台操作后如何正确动态挂载回对应的 Pod 存在较大危险,最终采纳了计划三进行了相应的测试及部署,并胜利启用了 EKS 下 EBS 的存储加密。
3. 部署与测试
接下来咱们会依照上述计划三进行部署测试,整体的过程如下:
3.1 环境筹备
装置 Amazon CLI, eksctl, kubectl 和 helm;装置并配置 Amazon CLI:https://docs.AWS.amazon.com/cli/latest/userguide/getting-started-install.html 装置 eksctl:https://docs.AWS.amazon.com/eks/latest/userguide/eksctl.html 装置 kubectl:https://docs.AWS.amazon.com/eks/latest/userguide/install-kubectl.html Helm 装置:https://docs.AWS.amazon.com/eks/latest/userguide/helm.html 运行以下命令创立 EKS 集群,本试验环境中的集群版本为 V1.21
eksctl create cluster --name test-cluster
创立实现后,查看集群连接性,应该会看到两个 Ready 状态的节点;
kubectl get node
装置 EBS CSI Driver 插件,将 arn 中的 111122223333 替换为您的账户 ID;
eksctl utils associate-iam-oidc-provider \
--cluster test-cluster \
--approve
eksctl create iamserviceaccount \
--name ebs-csi-Controller-sa \
--namespace kube-system \
--cluster test-cluster \
--attach-policy-arn arn:AWS:iam::AWS:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
eksctl create addon --name AWS-ebs-csi-driver --cluster test-cluster --service-account-role-arn arn:AWS:iam::111122223333:role/AmazonEKS_EBS_CSI_DriverRole --force
作为生产环境 EBS 卷加密前的模仿,接下来创立一个 StorageClass,和一个 Redis 的 StatefulSet:
curl -LJO https://raw.githubusercontent.com/henghengha/hello-world/master/sc.yml
curl -LJO https://raw.githubusercontent.com/henghengha/hello-world/master/sts.yml
curl -LJO https://raw.githubusercontent.com/henghengha/hello-world/master/rbac.yml
curl -LJO https://raw.githubusercontent.com/henghengha/hello-world/master/cm.yml
kubectl apply -f sc.yml
kubectl apply -f rbac.yml
kubectl apply -f cm.yml
kubectl apply -f sts.yml
查看部署状态
查看 EBS 卷均未加密
3.2 计划实现
EBS 卷是否加密的属性是在 StorageClass 对象中申明的,通过重建 StorageClass 能够保障从新创立进去的 pv 即 EBS 卷是加密的,然而不会作用到之前曾经存在的 EBS 卷。本局部将重点展现针对有状态对象在启用存储加密后,如何将原有 Pod 的数据备份,从而确保所有的 EBS 卷都已加密。操作步骤如下:
装置 Snapshot Controller,默认装置在 kube-system 命名空间,确保运行失常,参考:
https://aws.amazon.com/cn/blogs/containers/using-ebs-snapshots-for-persistent-storage-with-your-eks-cluster/
留神:配置文件中 Snapshot-Controller 应用的镜像地址为 gcr.io/Kubernetes-staging-sig-storage/Snapshot-Controller:v5.0.1,如果在中国区部署,请将该镜像下载下来,能够上传至 ECR,而后批改配置文件中的地址为中国区 ECR 的地址。
生产环境中为了尽可能的缩小业务受影响的工夫,咱们前面将应用雷同的配置创立一个新的 StatefulSet 对象,命名为 redis1,依据命名规定(该示例 StatefulSet 中的 volumeClaimTemplates 的名字为 data),redis1 生成的 pvc 名字将是 data-redis1-0 和 data-redis1-1。留神这里先不做真正的 StatefulSet 的部署;
删除原有 StorageClass,并应用如下配置重建:
apiVersion: storage.Kubernetes.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.AWS.com
parameters:
encrypted: 'true'
volumeBindingMode: WaitForFirstConsumer
本示例应用托管的 Amazon KMS Key aws/ebs 来进行加密,因而在 StorageClass 的配置中未指定具体的 Key ID。如果须要应用自定义 KMS 密钥,能够在 StorageClass 中增加 KMS Key ID 配置。与此同时,遵循最小权限准则,还须要给 EBS CSI Driver 受权 KMS 的对应权限。创立 IAM policy 并关联至 AmazonEKS_EBS_CSI_DriverRole,策略内容可参考官网文档进行配置:https://docs.aws.amazon.com/eks/latest/userguide/csi-iam-role.html
为原有的未加密 EBS 卷创立快照,并进行快照复原到加密卷。首先,为 pvc data-redis-0 和 data-redis-1 创立 Snapshot:
a. 创立 Volume Snapshot Class;
cat <<"EOF" > Snapshot-class.yaml
apiVersion: Snapshot.storage.Kubernetes.io/v1
kind: VolumeSnapshotClass
metadata:
name: test-snapclass
driver: ebs.csi.AWS.com
deletionPolicy: Delete
EOF
kubectl apply -f Snapshot-class.yaml
b. 创立 YAML 文件,volume-Snapshot-redis.yaml 内容如下;
留神:VolumeSnapshot 中的 persistentVolumeClaimName 要保障与 Pod 对应的 pvc 名称雷同,此处别离为 data-redis-0 和 data-redis-1。部署该文件来创立快照;
cat <<"EOF" > volume-Snapshot-redis.yaml
apiVersion: Snapshot.storage.Kubernetes.io/v1
kind: VolumeSnapshot
metadata:
name: redis-0-Snapshot
spec:
volumeSnapshotClassName: test-snapclass
source:
persistentVolumeClaimName: data-redis-0
---
apiVersion: Snapshot.storage.Kubernetes.io/v1
kind: VolumeSnapshot
metadata:
name: redis-1-Snapshot
spec:
volumeSnapshotClassName: test-snapclass
source:
persistentVolumeClaimName: data-redis-1
EOF
kubectl apply -f volume-Snapshot-redis.yaml
c. 查看快照信息;
应用快照作为数据源创立 pvc,给下一步新创建的 StatefulSet 中的 Pod 应用:
cat <<"EOF" > volume-from-Snapshot.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-redis1-0
spec:
storageClassName: ebs-sc
dataSource:
name: redis-0-Snapshot
kind: VolumeSnapshot
apiGroup: Snapshot.storage.Kubernetes.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-redis1-1
spec:
storageClassName: ebs-sc
dataSource:
name: redis-1-Snapshot
kind: VolumeSnapshot
apiGroup: Snapshot.storage.Kubernetes.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
EOF
kubectl apply -f volume-from-Snapshot.yaml
部署新的 StatefulSet redis1,并查看状态:
确认 pv 对应的 EBS 卷已加密,并验证数据备份无误之后能够依据具体的配置状况将连贯信息切到新的对象上。
如果确认所有流量都已转移到新的 Pod 上,即可删除原有的 StatefulSet 资源。
3.3 环境革除
删除集群中部署的资源,并删除 pvc 和 pv 对象:
kubectl delete -f sts.yml
kubectl delete -f rbac.yml
kubectl delete -f cm.yml
删除集群:
eksctl delete iamserviceaccount --cluster test-cluster --name ebs-csi-Controller-sa
eksctl delete nodegroup {your-node-group-name} --cluster test-cluster
eksctl delete cluster --name test-cluster
4. 参考
https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/ebs-csi.html
https://aws.amazon.com/blogs/containers/using-ebs-snapshots-for-persistent-storage-with-your-eks-cluster/
https://eksctl.io/
5. 小结
本文咱们针对 Amazon EKS 上有状态服务的数据保护平安需要,介绍了联合 KMS 服务,在 Amazon EKS 中如何应用 StatefulSet, Snapshot Controller 的形式实现有状态服务的存储加密启用,该形式通过从底层存储解决数据加密存储及迁徙,无需应用层染指数据迁徙,从而简略无效解决了 Amazon EKS 上有状态服务的存储加密需要。
本篇作者
李锐 亚马逊云科技金融行业资深解决方案架构师,负责基于亚马逊的云计算计划架构征询和设计,善于平安畛域。曾任职互联网公司,领有多年金融云产品及架构设计教训。
孙彦巧 亚马逊云科技金融行业解决方案架构师,负责云计算解决方案的架构设计和征询。有多年亚马逊云科技从业教训,热衷于容器、微服务架构及 Devops 方面的钻研和利用。
浏览原文
文章起源:https://dev.amazoncloud.cn/column/article/631478a1323d8e18f89…