暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

EKS企业实战(二)---如何在EKS上使用AWS原生的持久化存储

耶喝运维 2020-06-04
2620

为什么需要持久化存储

Kubernetes 对于有状态的容器应用或者对数据需要持久化的应用,不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储卷,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应用在重建之后仍然可以使用之前的数据,为了能够屏蔽底层存储实现的细节,Kubernetes从1.0版本就引入PV和PVC两个资源对象来实现对存储的管理子系统

      ------抄自Kerbernetes权威指南第四版509页 


在原生的Kubernetes中我们使用的持久化存储,我们常用的持久化存储一般有

  • local

  • iscsi

  • nfs

  • glusterfs-heketi

  • cephfs

这几种是在原生Kubernetes中经常会被企业选用的方式,而我们接下来需要说的是EKS中我们会选择的持久化存储的类型

  • ebs(SAN)

  • efs(NAS)

  • fsx(对于windows特有的存储这里不用它)

概念

ebs存储

优点:

  • 性能优化: Pod到存储之间有用独立的网络带宽,吞吐量高

  • 低延迟性能:通过使用SSD EBS卷,它可以提供可靠的I/O性能,满足各种存储需求(小文件4k随机读写)

  • 高可用性和安全性:EBS卷支持快照与加密

  • 在线扩容:可以随时动态扩容(无法缩容)

缺点:

  • 每个硬盘只能给一个pod进行挂载

  • 硬盘所在的az要跟pod所在的az相同,否则无法挂载

efs存储

优点:

  • 弹性:efs是一个理论上无限大的存储

  • 全面的托管服务:不需要维护的一个高可用性的nas存储

  • 灵活跨az:efs是一个可以多个pod 一起使用,并且可以跨AZ的nas存储

缺点:

  • 性能不高:iops性能不够高,即使用了MaxIO,我测试了一下大概500iops左右

部署

EBS

将 Amazon EBS CSI 驱动程序部署到 Amazon EKS 集群  
官网上会有一个步骤让我们部署一个IAM把这个IAM附加给EKS的worker节点上,在我上篇文章中在创建nodegroup的时候已经添加了这个权限

iam:
  withAddonPolicies:
    ebs: true

我们可以查看这个IAM的权限

kubectl -n kube-system describe configmap aws-auth

Name:         aws-auth
Namespace:    kube-system
Labels:       <none>
Annotations:  <none>

Data
====
mapRoles:
----
groups:
  - system:bootstrappers
  - system:nodes
  rolearn: arn:aws:iam::xxxx:role/eksctl-nuclearport-tokyo-eks-prod-NodeInstanceRole-xxxx
  username: system:node:{{EC2PrivateDNSName}}
groups:
  - system:bootstrappers
  - system:nodes
  rolearn: arn:aws:iam::xxxx:role/eksctl-nuclearport-tokyo-eks-prod-NodeInstanceRole-xxxx
  username: system:node:{{EC2PrivateDNSName}}

mapUsers:
----
[]

Events:  <none>

复制rolearn 去iam中查看,已经有了ebs的权限


所以我们不需要做这个IAM权限了,接下来直接测试EBS存储
EBS存储有几种模式


  • Dynamic Volume Provisioning:创建一个动态的卷等待pod来加载它

  • Static Provisioning:手动创建一个EBS,把他附加给pod

  • Block Volume:创建一个块存储挂给pod

  • Volume Snapshot:可以为EBS创建快照

部署EBS-CSI驱动程序

kubectl apply -k "github.com/kubernetes-sigs/aws-ebs-csi-driver/deploy/kubernetes/overlays/stable/?ref=master"

创建Dynamic Volume Provisioning(动态扩容)

注:EKS1.16 目前不支持因为aws-ebs-csi-driver 还不支持1.16版本
storageclass.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer

parameters: ## 配置一些可选参数
  csi.storage.k8s.io/fstype: xfs ## ebs文件系统
  type: io1  ## ebs类型
  iopsPerGB: "50"  ## ebs 初始容量
  encrypted: "true"  ## 是否加密

allowVolumeExpansion: true  ## 开启这个参数可以动态扩容

allowedTopologies:  ## 选择ebs创建的分区
- matchLabelExpressions:
  - key: topology.ebs.csi.aws.com/zone
    values:
    - us-east-1a

claim.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: centos
    command: ["/bin/sh"]
    args: ["-c""while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim
  tolerations:
    - key: "uessystem"
      operator: "Equal"
      value: "true"
      effect: "NoSchedule"

创建他们

kubectl apply -f storageclass.yaml
kubectl apply -f claim.yaml
kubectl apply -f pod.yaml

验证一下

kubectl describe pv
kubectl exec -it app cat /data/out.txt

清理资源

kubectl apply -f storageclass.yaml
kubectl apply -f claim.yaml
kubectl apply -f pod.yaml

创建Static Provisioning

如果你有一个EBS硬盘需要挂在给pod,那么就使用这种方法

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-pv
spec:
  capacity:
    storage: 50Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  csi:
    driver: ebs.csi.aws.com
    volumeHandle: {{ vol-id }}
    fsType: xfs
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.ebs.csi.aws.com/zone
          operator: In
          values:
          - us-east-1c 
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 50Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: centos
    command: ["/bin/sh"]
    args: ["-c""while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim

创建Block Volume

storageclass.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer

raw-claim.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-claim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 10Gi

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: app 
spec:
  containers:
  - name: app 
    image: busybox 
    command: ["/bin/sh""-c"]
    args: ["tail -f /dev/null"]
    volumeDevices:
    - name: data
      devicePath: /dev/xvda
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: block-claim
  tolerations:
    - key: "uessystem"
      operator: "Equal"
      value: "true"
      effect: "NoSchedule"

创建他们

kubectl apply -f storageclass.yaml
kubectl apply -f raw-claim.yaml
kubectl apply -f pod.yaml

验证一下

kubectl get pods
kubectl exec -ti app -- ls -al /dev/xvda

brw-rw----    1 root     disk      20223296 Mar 12 04:23 /dev/xvda    
# 写入测试
dd if=/dev/zero of=/dev/xvda bs=1024k count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.0492386 s, 2.1 GB/s

清理资源

kubectl apply -f storageclass.yaml
kubectl apply -f raw-claim.yaml
kubectl apply -f pod.yaml

创建Volume Snapshot

创建Storage Class  
storageclass.yaml

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer

snapshotclass.yaml

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
  name: csi-aws-vsc
driver: ebs.csi.aws.com
deletionPolicy: Delete

创建

kubectl apply -f storageclass.yaml
kubectl apply -f snapshotclass.yaml

创建APP
pod.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi

---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: centos
    command: ["/bin/sh"]
    args: ["-c""while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim

创建

kubectl apply -f pod.yaml

验证该卷已创建并volumeHandle包含EBS volumeID

kubectl describe pv

验证pod成功地将数据写入卷,并注意第一个条目的时间戳记

kubectl exec -it app cat /data/out.txt

创建VolumeSnapshot引用PersistentVolumeClaim名称
snapshot.yaml

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
  name: ebs-volume-snapshot
spec:
  volumeSnapshotClassName: csi-aws-vsc
  source:
    persistentVolumeClaimName: ebs-claim

创建

kubectl apply -f snapshot.yaml

等待VolumeSnapshot的 Ready To Use: true

kubectl describe volumesnapshot.snapshot.storage.k8s.io ebs-volume-snapshot

删除现有的应用程序

kubectl delete -f pod.yaml

还原从快照卷与PersistentVolumeClaim引用VolumeSnapshot它dataSource
pod.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-snapshot-restored-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi
  dataSource:
    name: ebs-volume-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: centos
    command: ["/bin/sh"]
    args: ["-c""while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-snapshot-restored-claim

创建

kubectl apply -f pod.yaml

通过将第一个条目的时间戳与步骤4中的时间戳进行比较,验证新的容器是否具有已还原的数据

kubectl exec -it app cat /data/out.txt

清理资源

kubectl delete -f test

EFS

部署 Amazon EFS CSI 驱动程序

kubectl apply -k "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=master"

创建一个EFS文件系统

----码不动了贴个官网

为您的 Amazon EKS 集群创建 Amazon EFS 文件系统,并记录efsid

  1. 通过 https://console.aws.amazon.com/efs/ 打开 Amazon Elastic File System 控制台。

  2. 选择 Create file system。

  3. 在Configure file system access (配置文件系统访问权限) 页面上,选择您的 Amazon EKS 集群使用的 VPC。

  4. 对于 Security groups (安全组),将您在上一步中创建的安全组添加到各个挂载目标并选择 Next step (下一步)。

  5. 为您的文件系统配置任意可选设置,然后选择 Next step (下一步) 和 Create File System (创建文件系统) 以完成操作。

找到您 Amazon EKS 集群的 VPC ID

aws eks describe-cluster --name cluster_name --query "cluster.resourcesVpcConfig.vpcId--output text

输出

vpc-exampledb76d3e813

查找您集群 VPC 的 CIDR 范围。您可以在 Amazon VPC 控制台中查找此信息,或者使用以下 AWS CLI 命令。

aws ec2 describe-vpcs --vpc-ids vpc-exampledb76d3e813 --query "Vpcs[].CidrBlock--output text

输出

192.168.0.0/16

创建一个安全组,该安全组允许您 Amazon EFS 装载点的入站 NFS 流量。

  1. 打开 Amazon VPC 控制台 https://console.aws.amazon.com/vpc/。

  2. 在左侧导航窗格中,选择安全组,然后选择创建安全组。

  3. 为您的安全组输入名称和描述,然后选择您的 Amazon EKS 集群使用的 VPC。

  4. 选择创建,然后选择关闭以完成操作。

添加规则到您安全组以允许从 VPC CIDR 范围的入站 NFS 流量。

  1. 选择您在上一步中创建的安全组。

  2. 选择入站规则选项卡,然后选择 编辑规则。

  3. 选择添加规则,填写以下字段,然后选择保存规则。

    • Type (类型):NFS

    • Source (源):自定义粘贴 VPC CIDR 范围。

    • 描述:添加描述,如“允许来自 VPC 的入站 NFS 流量”。
      部署一个示例应用程序并验证 CSI 驱动程序是否正常运行
      将 Amazon EFS Container Storage Interface (CSI) 驱动程序 GitHub 存储库克隆到您的本地系统。

git clone https://github.com/kubernetes-sigs/aws-efs-csi-driver.git

导航到 multiple_pods 示例目录。

cd aws-efs-csi-driver/examples/kubernetes/multiple_pods/

检索 Amazon EFS 文件系统 ID。您可以在 Amazon EFS 控制台中查找此信息,或者使用以下 AWS CLI 命令。

aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
输出:

fs-582a03f3

编辑 specs/pv.yaml 文件并将 volumeHandle 值替换为您的 Amazon EFS 文件系统 ID。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-582a03f3

注意
由于 Amazon EFS 是弹性文件系统,它不会强制实施任何文件系统容量限制。在创建系统时,不使用持久性卷和持久性卷声明中的实际存储容量值。但是,由于存储容量是 Kubernetes 中的必需字段,您必须指定有效值,例如,在此示例中为 5Gi。此值不会限制 Amazon EFS 文件系统的大小。

从 specs 目录部署 efs-sc 存储类、efs-claim 持久性卷声明、efs-pv 持久性卷以及 app1 和 app2 示例应用程序。

kubectl apply -f specs/

查看默认命名空间中的 Pod 并等待 app1 和 app2 Pod 进入就绪状态。

kubectl get pods --watch

列出默认命名空间中的持久性卷。查找 default/efs-claim 声明中的持久性卷。

kubectl get pv
输出:

NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
efs-pv   5Gi        RWX            Retain           Bound    default/efs-claim   efs-sc                  2m50s

描述持久性卷。

kubectl describe pv efs-pv
输出:

Name:            efs-pv
Labels:          <none>
Annotations:     kubectl.kubernetes.io/last-applied-configuration:
                   {"apiVersion":"v1","kind":"PersistentVolume","metadata":{"annotations":{},"name":"efs-pv"},"spec":{"accessModes":["ReadWriteMany"],"capaci...
                 pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    efs-sc
Status:          Bound
Claim:           default/efs-claim
Reclaim Policy:  Retain
Access Modes:    RWX
VolumeMode:      Filesystem
Capacity:        5Gi
Node Affinity:   <none>
Message:
Source:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            efs.csi.aws.com
    VolumeHandle:      fs-582a03f3
    ReadOnly:          false
    VolumeAttributes:  <none>
Events:                <none>

Amazon EFS 文件系统 ID 将作为 VolumeHandle 列出。

验证 app1 Pod 成功将数据写入卷。

kubectl exec -ti app1 -- tail /data/out1.txt
输出:

Wed Sep 18 20:30:48 UTC 2019
Wed Sep 18 20:30:53 UTC 2019
Wed Sep 18 20:30:58 UTC 2019
Wed Sep 18 20:31:03 UTC 2019
Wed Sep 18 20:31:08 UTC 2019
Wed Sep 18 20:31:13 UTC 2019

验证 app2 Pod 显示与卷中相同的数据。

kubectl exec -ti app2 -- tail /data/out1.txt
输出:

Wed Sep 18 20:30:48 UTC 2019
Wed Sep 18 20:30:53 UTC 2019
Wed Sep 18 20:30:58 UTC 2019
Wed Sep 18 20:31:03 UTC 2019
Wed Sep 18 20:31:08 UTC 2019
Wed Sep 18 20:31:13 UTC 2019

完成试验时,请删除此示例应用程序来清除资源。

kubectl delete -f specs/

下一篇写什么呢,还没想好不过后续会发一系列的文档,大家也可以在公众号里留言告诉我想看什么

文章转载自耶喝运维,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论