使用 AWS EFS 作为EKS里PV的后端存储 (1)
如何在 EKS 手工创建 AWS EFS 资源
预备知识
AWS 的 EC2 存储,有四种选择:
- Amazon Elastic Block Store
- Amazon EC2 instance store
- Use Amazon EFS with Amazon EC2
- Use Amazon S3 with Amazon EC2
下面的这张概念图很好的描述各种存储的位置层次。
在 EKS 的 node 如果是基于 EC2 的,那么 PV 就可以利用以上除去 S3 之外的其余三种作为底层存储。
参考:https://docs.aws.amazon.com/eks/latest/userguide/storage.html
关于 EC2 可以使用的存储的特性、使用场景,推荐阅读官方文档:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Storage.html。
使用 aws cli 创建一个 EFS 资源
可以在 AWS Console 中创建 EFS https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEFS.html。
也可以通过使用 aws cli 在命令行创建,https://www.eksworkshop.com/beginner/190_efs/launching-efs/。
下面是根据上文得到的,通过 aws cli 创建 EFS 的脚本。
假设,你的 aws profile 是 myAwsProfile、eks 所在 region 是 us-west-2、eks 集群名称是 myCluster,而要创建的 EFS 名称是 my-test-efs
为了使用 EFS 需要创建 SecurityGroup 来允许对 NFS 端口 2049 的使用,这里设置 SG 名称为 SG_efs_demo。
设置环境变量:
# Set the input env vars
export AWS_PROFILE=myAwsProfile
export AWS_REGION=us-west-2
export CLUSTER_NAME=myCluster
# Set the output env vars
export MOUNT_TARGET_GROUP_NAME=perf-test-efs-group
export MOUNT_TARGET_GROUP_DESC="NFS access to EFS from EKS worker nodes"
export EFS_NAME=my-test-efs
获取 VPC ID
# Get eks cluster's VPC ID.
export VPC_ID=$(aws eks describe-cluster --profile $AWS_PROFILE --region $AWS_REGION --name $CLUSTER_NAME --query "cluster.resourcesVpcConfig.vpcId" --output text)
echo $VPC_ID
获取 VPC 里的 subnets
# Get the subnets's CIDR in the VPC.
export CIDR_BLOCK=$(aws ec2 describe-vpcs --profile $AWS_PROFILE --region $AWS_REGION --vpc-ids $VPC_ID --query "Vpcs[].CidrBlock" --output text)
echo $CIDR_BLOCK
创建 Security Group
# Create SG(allow port 2049 in ingress for all of the CIDR in VPC) for EFS
export MOUNT_TARGET_GROUP_ID=$(aws ec2 create-security-group --profile $AWS_PROFILE --region $AWS_REGION --group-name $MOUNT_TARGET_GROUP_NAME --description "$MOUNT_TARGET_GROUP_DESC" --vpc-id $VPC_ID | jq --raw-output '.GroupId')
aws ec2 authorize-security-group-ingress --profile $AWS_PROFILE --region $AWS_REGION --group-id $MOUNT_TARGET_GROUP_ID --protocol tcp --port 2049 --cidr $CIDR_BLOCK
# Get back the security-group informaation.
aws ec2 describe-security-groups --filters Name=group-name,Values=$MOUNT_TARGET_GROUP_NAME
创建 EFS
# Create EFS. https://docs.aws.amazon.com/cli/latest/reference/efs/create-file-system.html
# https://docs.aws.amazon.com/efs/latest/ug/creating-using-create-fs.html#creating-using-fs-part1-cli
# If no creation-token is provied, you'd better go to the AWS EFS Console
# to make sure the EFS is created or not to avoid too many EFS reources are created.
# 使用efs name作为前缀加序号的方式做 creation-token 是个不错的选择,
export FILE_SYSTEM_ID=$(aws efs create-file-system --profile $AWS_PROFILE --region $AWS_REGION \
--performance-mode generalPurpose --throughput-mode bursting --tags Key=name,Value=$EFS_NAME \
--backup --encrypted --creation-token "$EFS_NAME"_0 | jq --raw-output '.FileSystemId')
找到 VPC 中的 pubilc subnets
# Find out the public subtnets from the subnets of the eks cluster.
# 得到eks VPC的所有 subnetIds
# export eksSubnetIDs=($(aws eks describe-cluster --profile $AWS_PROFILE --region $AWS_REGION --name $CLUSTER_NAME --query "cluster.resourcesVpcConfig.subnetIds" --output text))
# 找到 Internet GW
export IGW_ID=`aws ec2 describe-internet-gateways \
--filters Name=attachment.vpc-id,Values=${VPC_ID} \
--query "InternetGateways[].InternetGatewayId" \
| jq -r '.[0]'`
# 找到 public subnets: https://stackoverflow.com/questions/48830793/aws-vpc-identify-private-and-public-subnet
export PUBLIC_SUBNETS=`aws ec2 describe-route-tables \
--query 'RouteTables[*].Associations[].SubnetId' \
--filters "Name=vpc-id,Values=${VPC_ID}" \
"Name=route.gateway-id,Values=${IGW_ID}" \
| jq . -c`
把 EFS mount 到 public subnets,这样 EKS 里的 worker nodes 就都可以访问这些 EFS 了。
for subnet in ${PUBLIC_SUBNETS[@]}
do
echo "creating mount target in " $subnet
aws efs create-mount-target --profile $AWS_PROFILE --region us-west-2 --file-system-id $FILE_SYSTEM_ID --subnet-id $subnet --security-groups $MOUNT_TARGET_GROUP_ID
done
创建 Access Points
有了 EFS 之后就可以创建 AccessPoints 供应用程序使用了。关于更详细的 Access Points 介绍:https://docs.aws.amazon.com/efs/latest/ug/efs-access-points.html
ACCESS_POING_NAME=ap_db2
FILE_SYSTEM_ID=fs-055b5f1fcc7df3e4b
AP_DIR_USER='{"Uid": 70, "Gid": 70, "SecondaryGids": [70]}'
AP_ROOT_DIR='/mydataPath,CreationInfo={OwnerUid=70,OwnerGid=70,Permissions=0755}'
aws efs create-access-point --profile $AWS_PROFILE --region $AWS_REGION \
--tags Key=name,Value=$ACCESS_POING_NAME \
--client-token "$ACCESS_POING_NAME"_2 \
--file-system-id $FILE_SYSTEM_ID \
--posix-user $AP_DIR_USER \
--root-directory Path=$AP_ROOT_DIR
注意:
1)Path 的格式必须满足下面的正则
^(\/|(\/(?!\.)+[^$#<>;`|&?{}^*/\n]+){1,4})$
所以 path 不能以 /
结尾。
2)创建的 access point 可以同名、可以同名同 path,唯一标识 access point 的是 Access point ID
3) 根据 id 删除一个 access point
aws efs delete-access-point –profile $AWS_PROFILE –region $AWS_REGION –access-point-id fsap-0a8b1b7d9e0c1c9c3