Amazon EKS Storage - Part 3: Monitoring, Troubleshooting, Cost Optimization, and Security
本文档是 Amazon EKS 存储系列的第三部分,也是最后一部分,涵盖存储监控、故障排查、成本优化和安全。
Table of Contents
Storage Monitoring
有效监控 EKS 集群中的存储资源,对于及早发现性能问题并建立容量规划非常重要。
Monitoring with CloudWatch
你可以使用 AWS CloudWatch 监控 EBS、EFS 和 FSx for Lustre 卷的性能指标:
EBS Volume Metrics
关键 EBS 指标:
- VolumeReadBytes/VolumeWriteBytes:读/写吞吐量
- VolumeReadOps/VolumeWriteOps:读/写操作数量
- VolumeTotalReadTime/VolumeTotalWriteTime:读/写延迟
- VolumeQueueLength:待处理 I/O 请求数量
- BurstBalance:突发积分余额(gp2 卷)
CloudWatch dashboard 示例:
aws cloudwatch get-dashboard --dashboard-name EBSVolumeMonitoringEFS File System Metrics
关键 EFS 指标:
- TotalIOBytes:总 I/O 字节数
- DataReadIOBytes/DataWriteIOBytes:读/写吞吐量
- ClientConnections:已连接客户端数量
- PermittedThroughput:允许的吞吐量
- BurstCreditBalance:突发积分余额
FSx for Lustre Metrics
关键 FSx for Lustre 指标:
- DataReadBytes/DataWriteBytes:读/写吞吐量
- DataReadOperations/DataWriteOperations:读/写操作数量
- FreeDataStorageCapacity:可用存储容量
- NetworkThroughputUtilization:网络吞吐量利用率
Monitoring with Prometheus and Grafana
你可以使用 Prometheus 和 Grafana 在 Kubernetes 层面监控存储资源:
- 安装 Prometheus 和 Grafana:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace- 配置用于收集存储相关指标的 ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: csi-metrics
namespace: monitoring
spec:
selector:
matchLabels:
app: ebs-csi-controller
endpoints:
- port: metrics
interval: 30s- 配置 Grafana dashboard:
在 Grafana 中创建包含以下指标的 dashboard:
- PVC 使用量和容量
- 卷供应状态
- CSI driver 操作延迟
- 卷挂载/卸载操作
Custom Monitoring Solutions
你可以针对特定需求实现自定义监控解决方案:
- 卷使用量监控 Pod:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: volume-usage-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: volume-usage-exporter
template:
metadata:
labels:
app: volume-usage-exporter
spec:
containers:
- name: exporter
image: quay.io/prometheus/node-exporter:v1.3.1
args:
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --collector.filesystem
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
- name: root
mountPath: /host/root
readOnly: true
mountPropagation: HostToContainer
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
- name: root
hostPath:
path: /- 告警规则配置:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: storage-alerts
namespace: monitoring
spec:
groups:
- name: storage
rules:
- alert: VolumeUsageHigh
expr: kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
for: 10m
labels:
severity: warning
annotations:
summary: "Volume usage high ({{ $value | humanizePercentage }})"
description: "PVC {{ $labels.persistentvolumeclaim }} is using {{ $value | humanizePercentage }} of its capacity."
- alert: VolumeFullIn24Hours
expr: predict_linear(kubelet_volume_stats_used_bytes[6h], 24 * 3600) > kubelet_volume_stats_capacity_bytes
for: 10m
labels:
severity: warning
annotations:
summary: "Volume will fill in 24 hours"
description: "PVC {{ $labels.persistentvolumeclaim }} is predicted to fill within 24 hours."Storage Troubleshooting
让我们探讨 EKS 集群中可能出现的常见存储问题及其解决方案。
Volume Provisioning Issues
Issue: PVC Remains in Pending State
- 检查 PVC 状态:
kubectl get pvc
kubectl describe pvc <pvc-name>- 检查 StorageClass:
kubectl get sc
kubectl describe sc <storage-class-name>- 检查 provisioner Pod 日志:
kubectl -n kube-system get pods | grep csi
kubectl -n kube-system logs <csi-controller-pod-name>- 常见原因和解决方案:
- StorageClass 不存在:创建正确的 StorageClass
- 未安装 CSI driver:安装该 driver
- IAM 权限不足:授予所需的 IAM 权限
- 超出卷限制:请求提升服务限制
Issue: Volume Not Provisioned with WaitForFirstConsumer Binding Mode
- 检查 Pod 状态:
kubectl get pods
kubectl describe pod <pod-name>- 检查节点可用区:
kubectl get nodes -L topology.kubernetes.io/zone- 解决方案:
- 解决 Pod 调度问题
- 检查 node selector 和 affinity 规则
- 确保 node pool 与 PVC 位于同一可用区
Volume Mount Issues
Issue: Pod Stuck in ContainerCreating State
- 检查 Pod 事件:
kubectl describe pod <pod-name>- 检查节点 kubelet 日志:
kubectl get nodes
ssh ec2-user@<node-ip>
sudo journalctl -u kubelet- 常见原因和解决方案:
- 找不到卷 ID:在 AWS console 中验证卷是否存在
- 设备挂载失败:检查设备路径和文件系统
- 权限问题:检查 IAM roles 和 security groups
Issue: EFS or FSx Mount Failure
检查 security groups:
- EFS:允许 TCP 端口 2049
- FSx for Lustre:允许 TCP 端口 988
检查网络连接:
kubectl debug node/<node-name> -it --image=amazon/aws-cli
ping <efs-dns-name>
telnet <efs-dns-name> 2049- 创建 mount helper Pod:
apiVersion: v1
kind: Pod
metadata:
name: mount-helper
spec:
containers:
- name: mount-helper
image: amazonlinux:2
command: ["sleep", "infinity"]
securityContext:
privileged: true- 手动测试挂载:
kubectl exec -it mount-helper -- bash
yum install -y nfs-utils
mkdir -p /mnt/efs
mount -t nfs4 <efs-dns-name>:/ /mnt/efsPerformance Issues
Issue: Slow I/O Performance
- 检查卷性能指标:
aws cloudwatch get-metric-statistics \
--namespace AWS/EBS \
--metric-name VolumeReadOps \
--dimensions Name=VolumeId,Value=vol-1234567890abcdef0 \
--start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 300 \
--statistics Average- 测试文件系统性能:
kubectl exec -it <pod-name> -- bash
dd if=/dev/zero of=/data/test bs=1M count=1000 oflag=direct
dd if=/data/test of=/dev/null bs=1M count=1000 iflag=direct- 常见原因和解决方案:
- 卷类型不合适:选择适合工作负载的卷类型(例如 gp3、io2)
- IOPS 或吞吐量限制:调整卷性能参数
- 实例限制:使用 EBS-optimized instances
- 文件系统碎片:优化或重新创建文件系统
Issue: EFS Performance Degradation
- 检查 EFS performance mode 和 throughput mode
- 优化客户端挂载选项:
mountOptions:
- nfsvers=4.1
- rsize=1048576
- wsize=1048576
- timeo=600
- retrans=2
- noresvport- 优化访问模式:
- 使用大文件而不是小文件
- 使用顺序访问模式
- 尽量减少元数据操作
Storage Cost Optimization
让我们探讨优化 EKS 集群存储成本的策略。
Volume Type and Size Optimization
选择合适的卷类型:
- 通用工作负载:gp3(比 gp2 更具成本效益)
- 吞吐密集型工作负载:st1
- 不常访问的数据:sc1
优化卷大小:
- 预置略大于需求的卷
- 监控卷使用量,并按需扩展
- 清理或归档不必要的数据
迁移到 gp3 卷:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-gp3
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
type: gp3
encrypted: "true"
allowVolumeExpansion: trueStorage Lifecycle Management
数据分层:
- 频繁访问的数据:EBS 或 EFS
- 不常访问的数据:S3 或 S3 Glacier
自动化 snapshot 策略:
- 定期创建 snapshot
- 自动删除旧 snapshot
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: ebs-snapshot-class
driver: ebs.csi.aws.com
deletionPolicy: Delete- PV reclaim policy:
- 对临时数据使用 Delete policy
- 对重要数据使用 Retain policy
EFS Cost Optimization
选择合适的 throughput mode:
- 可预测的工作负载:Provisioned throughput
- 可变工作负载:Bursting mode
Lifecycle management:
- 自动将不常访问的文件移动到 IA (Infrequent Access) storage class
- 配置 lifecycle policy:
aws efs put-lifecycle-configuration \
--file-system-id fs-1234567890abcdef0 \
--lifecycle-policies '[{"TransitionToIA":"AFTER_30_DAYS"}]'- 使用 access points:
- 使用特定于应用程序的 access points 共享文件系统
FSx for Lustre Cost Optimization
选择合适的 deployment type:
- 临时工作负载:SCRATCH_2
- 长期工作负载:PERSISTENT_1 或 PERSISTENT_2
启用数据压缩:
- 使用 LZ4 数据压缩降低存储成本
与 S3 集成:
- 将 S3 bucket 连接到 FSx for Lustre 以进行数据分层
Cost Monitoring and Analysis
使用 AWS Cost Explorer:
- 分析存储成本趋势
- 按资源分析成本
Kubernetes 成本分配:
- 使用 namespaces 和 labels 分配成本
- 使用 Kubecost 等工具
成本异常检测:
- 设置 AWS budgets 和 alerts
- 为异常成本增长配置 alerts
Storage Security
让我们探讨保护 EKS 集群中存储资源的安全最佳实践。
Data Encryption
- 静态数据加密:
- EBS 卷加密:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-encrypted
provisioner: ebs.csi.aws.com
parameters:
type: gp3
encrypted: "true"
kmsKeyId: arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab- EFS 文件系统加密:
aws efs create-file-system \
--encrypted \
--kms-key-id arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab- FSx for Lustre 加密:
aws fsx create-file-system \
--file-system-type LUSTRE \
--storage-capacity 1200 \
--subnet-ids subnet-1234567890abcdef0 \
--lustre-configuration DeploymentType=SCRATCH_2 \
--security-group-ids sg-1234567890abcdef0 \
--kms-key-id arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab- 传输中数据加密:
- EFS 传输中加密:
mountOptions:
- tls- S3 传输中加密:
aws s3 cp --sse AES256 file.txt s3://my-bucket/Access Control
- IAM roles and policies:
- 应用最小权限原则
- 对 service accounts 使用 IAM roles
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster my-cluster \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve- Security groups:
- 仅允许必需端口
- 限制源 IP
aws ec2 authorize-security-group-ingress \
--group-id sg-1234567890abcdef0 \
--protocol tcp \
--port 2049 \
--source-group sg-0987654321fedcba0- Kubernetes RBAC:
- 限制对 PVs 和 PVCs 的访问
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app-namespace
name: pvc-manager
rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pvc-manager-binding
namespace: app-namespace
subjects:
- kind: ServiceAccount
name: app-service-account
namespace: app-namespace
roleRef:
kind: Role
name: pvc-manager
apiGroup: rbac.authorization.k8s.ioPod Security Context
- 只读 root filesystem:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
containers:
- name: app
image: nginx
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: data-volume
mountPath: /data
readOnly: false- 有限权限:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
allowPrivilegeEscalation: false- SELinux、AppArmor 或 seccomp profiles:
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
seccompProfile:
type: RuntimeDefaultSecurity Policy Enforcement
- OPA Gatekeeper 或 Kyverno:
- 仅允许加密卷
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-ebs-encryption
spec:
validationFailureAction: enforce
rules:
- name: check-ebs-encryption
match:
resources:
kinds:
- PersistentVolumeClaim
validate:
message: "EBS volumes must be encrypted"
pattern:
spec:
storageClassName: "ebs-*"
+(storageClassName): "ebs-encrypted"- Pod Security Standards:
- 将 Pod Security Standards 应用于 namespaces
apiVersion: v1
kind: Namespace
metadata:
name: secure-ns
labels:
pod-security.kubernetes.io/enforce: restrictedStorage Management Best Practices
让我们探讨在 EKS 集群中有效管理存储的最佳实践。
Storage Planning and Design
需求分析:
- 性能需求(IOPS、吞吐量)
- 容量需求
- 访问模式(读/写比例、并发)
- 可用性和持久性需求
存储类型选择:
- Block storage (EBS):数据库、有状态应用程序
- File storage (EFS):共享文件、web servers、CMS
- High-performance file storage (FSx for Lustre):HPC、ML training
- Object storage (S3):备份、归档、静态内容
容量规划:
- 当前需求 + 增长余量
- 实现自动扩展机制
- 定期容量评审
Backup and Disaster Recovery
- 定期备份:
- 自动执行卷 snapshot
- 定义备份保留策略
# Create snapshot daily at midnight
0 0 * * * kubectl create -f snapshot.yamlDisaster recovery plan:
- Multi-AZ 或跨区域复制
- 定义 Recovery Time Objective (RTO) 和 Recovery Point Objective (RPO)
- 定期恢复测试
使用 Velero 进行集群备份:
velero backup create daily-backup --include-namespaces=default,app-namespaceAutomation and IaC (Infrastructure as Code)
- 使用 Terraform 或 CloudFormation:
- 以声明式方式定义存储资源
- 版本控制和变更跟踪
resource "aws_efs_file_system" "example" {
creation_token = "example"
performance_mode = "generalPurpose"
throughput_mode = "bursting"
encrypted = true
lifecycle_policy {
transition_to_ia = "AFTER_30_DAYS"
}
tags = {
Name = "ExampleFileSystem"
}
}- 使用 Helm charts:
- 将 storage classes 和 PVCs 模板化
# values.yaml
storage:
class: ebs-gp3
size: 10Gi
encrypted: true- GitOps workflow:
- 使用 ArgoCD 或 Flux 管理存储配置
Performance and Cost Optimization
定期性能评审:
- 识别并解决瓶颈
- 随着工作负载变化调整存储配置
成本优化评审:
- 识别并移除未使用的卷
- 迁移到具有成本效益的存储类型
- 考虑 Reserved Instances 或 Savings Plans
Auto scaling:
- 根据需求自动扩展存储
- 配置基于使用量的 alerts
Conclusion
在本文档中,我们介绍了 Amazon EKS 存储的监控、故障排查、成本优化和安全。有效的存储管理对于确保 EKS 集群的性能、可靠性和成本效益至关重要。
存储需求因应用程序而异,因此了解工作负载的特征并选择合适的存储解决方案非常重要。此外,你还应通过定期监控、故障排查、成本优化和安全评审来有效管理存储资源。
References
- Amazon EKS Storage Best Practices
- Kubernetes Storage Troubleshooting
- AWS Storage Cost Optimization
- Kubernetes Storage Security
Quiz
要测试你在本章学到的内容,请尝试完成主题测验。