使用EFS存储服务的EKS Kubernetes持久存储

时间:2020-02-23 14:30:23  来源:igfitidea点击:

在本教程中,我们将讨论如何为Kubernetes集群使用EFS Amazon服务配置EKS持久存储。最好使用的存储后端服务是EFS,这将是我们用于有状态应用程序使用的卷声明的默认持久性存储。 StorageClass为管理员提供了一种描述他们提供的存储类别的方法,以允许动态配置持久卷。

在Kubernetes中,PersistentVolume(PV)是集群中的一块存储,而PersistentVolumeClaim(PVC)是用户(通常是Pod)对存储的请求。我们需要一个有效的EKS群集,然后才能使用本教程为容器化工作负载设置持久性存储。

设置准备工作:

EKS群集:使用eksctlAWS CLI设置EKS群集

这是本教程中将使用的EKS群集的名称。

$eksctl get cluster
NAME			REGION
prod-eks-cluster	eu-west-1

将群集名称另存为变量,该变量将在其余步骤中使用。

EKS_CLUSTER="prod-eks-cluster"

使用EFS CSI驱动程序创建持久卷

Amazon Elastic File System容器存储接口(CSI)驱动程序为容器协调器实施CSI规范,以管理Amazon EFS文件系统的生命周期。

创建Amazon EFS文件系统

Amazon EFS CSI驱动程序支持Amazon EFS访问点,这些访问点是Amazon EFS文件系统中特定于应用程序的入口点,使在多个Pod之间共享文件系统更加容易。

我们可以从Amazon控制台或者终端执行这些操作。我在所有操作中均使用AWS CLI界面。

找到Amazon EKS集群的VPC ID:

EKS_CLUSTER="prod-eks-cluster"
EKS_VPC_ID=$(aws eks describe-cluster --name $EKS_CLUSTER --query "cluster.resourcesVpcConfig.vpcId" --output text)

确认有效的VPC ID。

$echo $EKS_VPC_ID
vpc-019a6458a973ace2b

找到群集VPC的CIDR范围:

EKS_VPC_CIDR=$(aws ec2 describe-vpcs --vpc-ids $EKS_VPC_ID --query "Vpcs[].CidrBlock" --output text)

确认VPC CIDR:

$echo $EKS_VPC_CIDR
192.168.0.0/16

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

aws ec2 create-security-group --group-name efs-nfs-sg --description "Allow NFS traffic for EFS" --vpc-id $EKS_VPC_ID

记下安全组ID。我的是:

{
    "GroupId": "sg-0fac73a0d7d943862"
}
# You can check with
$aws ec2 describe-security-groups --query "SecurityGroups[*].{Name:GroupName,ID:GroupId}"

将规则添加到安全组:

SG_ID="sg-0fac73a0d7d943862"
aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 2049 --cidr $EKS_VPC_CIDR

要查看对安全组的更改,请运行describe-security-groups命令:

$aws ec2 describe-security-groups --group-ids $SG_ID
{
    "SecurityGroups": [
        {
            "Description": "Allow NFS traffic for EFS",
            "GroupName": "efs-nfs-sg",
            "IpPermissions": [
                {
                    "FromPort": 2049,
                    "IpProtocol": "tcp",
                    "IpRanges": [
                        {
                            "CidrIp": "192.168.0.0/16"
                        }
                    ],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "ToPort": 2049,
                    "UserIdGroupPairs": []
                }
            ],
            "OwnerId": "253859766502",
            "GroupId": "sg-0fac73a0d7d943862",
            "IpPermissionsEgress": [
                {
                    "IpProtocol": "-1",
                    "IpRanges": [
                        {
                            "CidrIp": "0.0.0.0/0"
                        }
                    ],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "UserIdGroupPairs": []
                }
            ],
            "VpcId": "vpc-019a6458a973ace2b"
        }
    ]
}

为Amazon EKS集群创建Amazon EFS文件系统:

# Not encrypted
$aws efs create-file-system --region eu-west-1

# Encrypted EFS file system
$aws efs create-file-system --encrypted --region eu-west-1

注意文件系统ID:

{
    "OwnerId": "253759766542",
    "CreationToken": "c16c4603-c7ac-408f-ac4a-75a683ed2a29",
    "FileSystemId": "fs-22ac06e8",
    "FileSystemArn": "arn:aws:elasticfilesystem:eu-west-1:253759766542:file-system/fs-22ac06e8",
    "CreationTime": "2017-08-16T15:17:18+03:00",
    "LifeCycleState": "creating",
    "NumberOfMountTargets": 0,
    "SizeInBytes": {
        "Value": 0,
        "ValueInIA": 0,
        "ValueInStandard": 0
    },
    "PerformanceMode": "generalPurpose",
    "Encrypted": true,
    "KmsKeyId": "arn:aws:kms:eu-west-1:253759766542:key/6c9b725f-b86d-41c2-b804-1685ef43f620",
    "ThroughputMode": "bursting",
    "Tags": []
}

用户界面视图:

创建EFS挂载目标

在运行EC2实例的VPC中获取子网。在我的情况下,所有EKS实例都在专用子网中运行。

EKS_VPC_ID=$(aws eks describe-cluster --name $EKS_CLUSTER --query "cluster.resourcesVpcConfig.vpcId" --output text)
aws ec2 describe-subnets --filter Name=vpc-id,Values=$EKS_VPC_ID --query 'Subnets[?MapPublicIpOnLaunch==`false`].SubnetId'

我的输出:

[
    "subnet-0977bbaf236bd952f",
    "subnet-0df8523ca39f63938",
    "subnet-0a4a22d25f36c4124"
]

创建挂载目标。

# File system ID
EFS_ID="fs-22ac06e8"

# Create mount targets for the subnets - Three subnets in my case
for subnet in subnet-0977bbaf236bd952f subnet-0df8523ca39f63938 subnet-0a4a22d25f36c4124; do
  aws efs create-mount-target \
    --file-system-id $EFS_ID \
    --security-group  $SG_ID \
    --subnet-id $subnet \
    --region eu-west-1
done

使用EFS CSI驱动程序

在创建EFS文件系统和Mount Target之后,我们可以通过创建静态持久卷并通过测试容器声明它来测试EFS CSI驱动程序。

部署EFS CSI预配器。

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

daemonset.apps/efs-csi-node created
csidriver.storage.k8s.io/efs.csi.aws.com created

列出可用的CSI驱动程序:

$kubectl get csidrivers.storage.k8s.io
NAME              CREATED AT
efs.csi.aws.com   2017-08-16T19:10:35Z

首先获取EFS文件系统ID:

$aws efs describe-file-systems --query "FileSystems[*].FileSystemId"
[
    "fs-22ac06e8"
]

创建存储类:

kubectl apply -f - <<EOF
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
EOF

列出可用的存储类别:

$kubectl get sc
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
efs-sc          efs.csi.aws.com         Delete          Immediate              false                  28s
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  4d21h

创建并修改以下列表文件以设置正确的文件系统ID:

$vim efs-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: efs-pv
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: fs-22ac06e8 # Your EFS file system ID

应用文件创建资源:

$kubectl apply -f efs-pv.yml
persistentvolume/efs-pv created

$kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
efs-pv   1Gi        RWO            Retain           Available           efs-sc                  19s

创建索赔资源:

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: efs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: efs-sc
  resources:
    requests:
      storage: 1Gi
EOF

列出声明以确认它已创建且状态为"绑定":

$kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
efs-claim   Bound    efs-pv   1Gi        RWO            efs-sc         7s

创建使用体积声明的测试容器。

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: efs-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: efs-claim
EOF

验证Pod是否正在运行:

$kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
efs-app   1/1     Running   0          34s

内部容器检查安装点。

$kubectl exec -ti efs-app -- bash
[theitroad@localhost /]# df -hT
Filesystem     Type     Size  Used Avail Use% Mounted on
overlay        overlay   80G  3.4G   77G   5% /
tmpfs          tmpfs     64M     0   64M   0% /dev
tmpfs          tmpfs    1.9G     0  1.9G   0% /sys/fs/cgroup
127.0.0.1:/   nfs4     8.0E     0  8.0E   0% /data
/dev/nvme0n1p1 xfs       80G  3.4G   77G   5% /etc/hosts
shm            tmpfs     64M     0   64M   0% /dev/shm
tmpfs          tmpfs    1.9G   12K  1.9G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs          tmpfs    1.9G     0  1.9G   0% /proc/acpi
tmpfs          tmpfs    1.9G     0  1.9G   0% /sys/firmware

将一些测试文件写入安装了EFS文件系统的/data。

[theitroad@localhost /]# touch /data/testfile1
[theitroad@localhost /]# touch /data/testfile2
[theitroad@localhost /]#
[theitroad@localhost /]# ls /data/
out.txt  testfile1  testfile2
[theitroad@localhost /]# exit
exit

清理测试数据。

kubectl delete pod efs-app
kubectl delete pvc efs-claim
kubectl delete pv efs-pv