CDK를 사용하여 EKS에서 NFS 볼륨 자동 프로비저닝
목차
소개
I recently set up an EKS cluster for a client. From the cluster we wanted to autoprovision EFS volumes based on persistent volume claims. We wanted to do all of this using CDK.
I assume you're already somewhat familiar with CDK , Kubernetes , EKS 그리고 ~/.aws/credentials configured 를 가지고 있습니다.CDK 설정
Let's get started!
Create an empty working directory:
mkdir eks-efs && cd eks-efs
Then create a basic CDK TypeScript app:
npx cdk@^2.32 init app --language typescript
If this is the first time you use CDK on this AWS account, you need to bootstrap it (= creating some S3 buckets etc) by running:
npx cdk bootstrap
Next let's add a variable to keep the naming prefix used with all our resources. (If you already have similarly named resources, change it to something else.) Add this to the top of the file, after the imports:
// lib/eks-efs-stack.ts
...
const prefix = "my";
...
EKS 클러스터 설정
Add this (and all code snippets following this one) to the end of the constructor:
// lib/eks-efs-stack.ts
...
const vpc = new aws_ec2.Vpc(this, `${prefix}-vpc`, {
vpcName: `${prefix}-vpc`,
});
const cluster = new aws_eks.Cluster(this, `${prefix}-eks`, {
clusterName: `${prefix}-eks`,
version: aws_eks.KubernetesVersion.V1_21,
vpc,
});
...
The explicit VPC is strictly not needed, but we will use it later.
Now deploy the cluster by running:
npx cdk@^2.32 deploy
Creating all the required resources usually takes around 20-25 minutes.
The result should look something like this (I have removed sensitive information, such as my AWS account number):
✅ my-stack
✨ Deployment time: 1373.08s
Outputs:
my-stack.myeksConfigCommand76382EC1 = aws eks update-kubeconfig --name my-eks --region eu-west-1 --role-arn arn:aws:iam::...:role/my-stack-myeksMastersRole...-...
my-stack.myeksGetTokenCommand0DD2F5A8 = aws eks get-token --cluster-name my-eks --region eu-west-1 --role-arn arn:aws:iam::...:role/my-stack-myeksMastersRole...-...
Stack ARN:
arn:aws:cloudformation:eu-west-1:...:stack/my-stack/bbb03590-05cf-11ed-808a-02bd3ce8aca3
kubectl 구성
이제 클러스터를 가동하고 실행했으므로 kubectl을 사용하여 일반적인 방식으로 클러스터를 관리할 수 있습니다. 먼저 이전 단계에서 ConfigCommand 출력 값을 복사하여 클러스터를 kubeconfig에 추가해야 합니다. 또한 컨텍스트 이름이 그다지 기억에 남지 않는 클러스터 ARN이 되므로 --alias 플래그를 추가하는 것이 좋습니다.
제 경우에는 다음을 실행합니다.
aws eks update-kubeconfig --name my-eks --region eu-west-1 --role-arn arn:aws:iam::...:role/my-stack-myeksMastersRoleD2A59038-47WE3AI9OHS3 --alias my-eks
다음과 같은 몇 가지 간단한 확인이 뒤따릅니다.
kubectl get pod -A
그리고 얻다:
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-node-nmwzs 1/1 Running 0 36m
kube-system aws-node-r2hjk 1/1 Running 0 36m
kube-system coredns-7cc879f8db-8ntfk 1/1 Running 0 42m
kube-system coredns-7cc879f8db-dsrs9 1/1 Running 0 42m
kube-system kube-proxy-247kc 1/1 Running 0 36m
kube-system kube-proxy-6g45p 1/1 Running 0 36m
지원되는 Kubernetes 버전
여기에서 꽤 오래된 Kubernetes 1.21을 사용하기로 선택한 것을 눈치채셨을 것입니다. 작성 당시에는 불행하게도 CDK와 함께 사용할 수 있는 Kubernetes의 최신 버전입니다. (콘솔을 사용하는 경우 1.22까지 올라갈 수 있습니다.) 1.21은 Kubernetes 프로젝트에서 더 이상 지원되지 않지만I recently learned AWS 자체에서 여전히 지원하므로 보안 수정 사항을 백포트합니다.
PVC를 EBS에 바인딩
EBS autoprovisioning support is already built into EKS, via a storage class called gp2.
If we create a persistent volume claim (PVC):
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-rwo
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 1Gi
EOF
And a pod that uses the PVC:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: ebs-rwo
spec:
containers:
- name: nginx
image: nginx
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-rwo
EOF
Wait a few seconds, then check the status of the new PVC:
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS
ebs-rwo Bound pvc-71606839-b2d9-4f36-8e1c-942b8d7e38f1 1Gi RWO gp2
And the associated newly created persistent volume (PV):
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS
pvc-71606839-b2d9-4f36-8e1c-942b8d7e38f1 1Gi RWO Delete Bound default/ebs-rwo gp2
However, there are some reasons why we won't want to use EBS for persistent storage. One of them is that EBS doesn't support access mode ReadWriteMany. EFS to the rescue!
EFS 자동 프로비저닝 설정
However, EFS is not supported out-of-the-box as EBS is, and needs some setting up to work as smoothly. The are complete instructions AWS 웹 사이트에 있지만 최신 IaC(Infrastructure-as-Code) 접근 방식과 잘 맞지 않는 명령형 CLI 명령을 사용합니다.EFS 파일 시스템 추가
먼저 네트워크 보안 그룹을 만들어야 합니다.
// lib/eks-efs-stack.ts
...
const efsInboundSecurityGroup = new aws_ec2.SecurityGroup(
this,
`${prefix}-efs-inbound-security-group`,
{
securityGroupName: `${prefix}-efs-inbound`,
vpc,
},
);
...
수신 EFS 트래픽을 허용하는 수신 규칙 사용:
// lib/eks-efs-stack.ts
...
new aws_ec2.CfnSecurityGroupIngress(
this,
`${prefix}-efs-inbound-security-group-ingress`,
{
ipProtocol: "tcp",
cidrIp: vpc.vpcCidrBlock,
groupId: efsInboundSecurityGroup.securityGroupId,
description: "Inbound EFS",
fromPort: 2049,
toPort: 2049,
},
);
...
포트 2049는 표준 EFS 포트입니다. (fromPort 및 toPort는 단순히 포트 범위를 2049에서 2049로 정의하며 TCP 세계의 소스 및 대상 포트와 혼동하지 마십시오.)
그런 다음 EFS 파일 시스템을 만듭니다.
// lib/eks-efs-stack.ts
...
const efs_fs = new aws_efs.FileSystem(this, `${prefix}-efs`, {
fileSystemName: `${prefix}`,
vpc,
securityGroup: efsInboundSecurityGroup,
removalPolicy: RemovalPolicy.DESTROY,
});
...
파일 시스템이 나머지 CDK 스택과 함께 삭제되도록 RemovalPolicy.DESTROY를 지정합니다.
IAM 역할 추가
먼저 EFS 액세스 포인트를 보고 만드는 데 필요한 권한을 부여하는 정책을 만듭니다.
// lib/eks-efs-stack.ts
...
const efsAllowPolicyDocument = aws_iam.PolicyDocument.fromJson({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:DescribeAccessPoints",
"elasticfilesystem:DescribeFileSystems",
],
"Resource": "*",
},
{
"Effect": "Allow",
"Action": [
"elasticfilesystem:CreateAccessPoint",
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:RequestTag/efs.csi.aws.com/cluster": "true",
},
},
},
{
"Effect": "Allow",
"Action": "elasticfilesystem:DeleteAccessPoint",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/efs.csi.aws.com/cluster": "true",
},
},
},
],
});
...
다음으로 이 역할을 맡을 수 있는 사람을 지정합니다(AWS 콘솔에서 신뢰 관계라고 함).
// lib/eks-efs-stack.ts
...
const efsAssumeRolePolicyDocument = aws_iam.PolicyDocument.fromJson({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": cluster.openIdConnectProvider.openIdConnectProviderArn,
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": new CfnJson(
this,
`${prefix}-assume-role-policy-document-string-equals-value`,
{
value: {
[`${cluster.openIdConnectProvider.openIdConnectProviderIssuer}:aud`]:
"sts.amazonaws.com",
[`${cluster.openIdConnectProvider.openIdConnectProviderIssuer}:sub`]:
"system:serviceaccount:kube-system:efs-csi-controller-sa",
},
},
),
},
},
],
});
...
클러스터와 함께 생성된 IODC 공급자를 참조합니다. 또한 특별한 마법의 CfnJson 구성을 사용하여 JSON에서 동적 키를 사용할 수 있습니다. (이것을 알아내는 데 꽤 오랜 시간이 걸렸습니다.)
마지막으로 IAM 역할을 생성하여 모두 하나로 묶습니다.
// lib/eks-efs-stack.ts
...
const efsRole = new aws_iam.CfnRole(
this,
`${prefix}-efs-csi-controller-sa-role`,
{
roleName: `${prefix}-efs-csi-controller-sa-role`,
assumeRolePolicyDocument: efsAssumeRolePolicyDocument,
policies: [
{
policyName: `${prefix}-efs-csi-controller-sa-policy`,
policyDocument: efsAllowPolicyDocument,
},
],
},
);
...
EFS CSI 드라이버 설치
이제 EFS CSI 드라이버를 설치해야 합니다. 바인딩되지 않은 PVC를 확인하고 PV 및 EFS 액세스 포인트를 생성하는 Kubernetes 컨트롤러입니다. 가장 쉬운 방법은 Helm 차트를 이용하는 것입니다.
// lib/eks-efs-stack.ts
...
cluster.addHelmChart(`${prefix}-aws-efs-csi-driver`, {
repository: "https://kubernetes-sigs.github.io/aws-efs-csi-driver/",
chart: "aws-efs-csi-driver",
version: "2.2.7",
release: "aws-efs-csi-driver",
namespace: "kube-system",
values: {
controller: {
serviceAccount: {
annotations: {
"eks.amazonaws.com/role-arn": efsRole.attrArn,
},
},
},
},
});
...
eks.amazonaws.com/role-arn은 해당 서비스 계정을 지정된 IAM 역할과 연결하는 EKS에서 인식하는 특수 주석입니다. 이는 해당 서비스 계정에서 실행되는 모든 포드/컨테이너가 해당 역할로 AWS API를 호출할 수 있음을 의미합니다. (IAM 역할을 EC2 인스턴스와 연결하는 것과 거의 같은 방식입니다.)
스토리지 클래스 추가
마지막으로 해야 할 일은 PVC가 사용할 Kubernetes 스토리지 클래스(SC)를 추가하는 것입니다.
// lib/eks-efs-stack.ts
...
cluster.addManifest(`${prefix}-k8s-efs-storageclass`, {
apiVersion: "storage.k8s.io/v1",
kind: "StorageClass",
metadata: {
name: "efs",
},
provisioner: "efs.csi.aws.com",
parameters: {
directoryPerms: "700",
provisioningMode: "efs-ap",
fileSystemId: efs_fs.fileSystemId,
uid: "1001",
gid: "1001",
},
});
...
SC가 새로 설정한 EFS 파일 시스템을 참조하고 일부 Linux 관련 매개변수를 지정하는 방법에 주목하십시오.
EFS에 PVC 바인딩
Let's add a PVC which uses the SC:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: efs-rwx
spec:
accessModes:
- ReadWriteMany
storageClassName: efs
resources:
requests:
storage: 1Gi
`EOF`
And a pod that uses the PVC:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: efs-rwx
spec:
containers:
- name: nginx
image: nginx
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: efs-rwx
`EOF`
Now check the status of the new PVC:
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS
ebs-rwo Bound pvc-71606839-b2d9-4f36-8e1c-942b8d7e38f1 1Gi RWO gp2
efs-rwx Bound pvc-5743b62a-1e1a-4b0b-b930-921465fd9d9b 1Gi RWX efs
And the associated newly created PV:
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS
pvc-71606839-b2d9-4f36-8e1c-942b8d7e38f1 1Gi RWO Delete Bound default/ebs-rwo gp2
pvc-5743b62a-1e1a-4b0b-b930-921465fd9d9b 1Gi RWX Delete Bound default/efs-rwx efs
Notice that the new one is bound, uses SC efs and has access mode RWX (ReadWriteMany).
We can also view the EFS access point that was created:
aws efs describe-access-points
AccessPoints:
- AccessPointArn: arn:aws:elasticfilesystem:eu-west-1:...:access-point/fsap-082fd6323a789739d
AccessPointId: fsap-082fd6323a789739d
ClientToken: pvc-5743b62a-1e1a-4b0b-b930-921465fd9d9b
FileSystemId: fs-0a724fe641cbd9da7
LifeCycleState: available
OwnerId: '...'
PosixUser:
Gid: 1001
Uid: 1001
RootDirectory:
CreationInfo:
OwnerGid: 1001
OwnerUid: 1001
Permissions: '700'
Path: /pvc-5743b62a-1e1a-4b0b-b930-921465fd9d9b
Tags:
- Key: efs.csi.aws.com/cluster
Value: 'true'
청소
In order to avoid further costs, let's clean up the resources we just created. This is as simple as:
npx cdk destroy
Again, this will take around 20-25 minutes.
요약
That's it! We set up autoprovisioning of NFS volumes in EKS using CDK. Full working code will soon be available on GitHub.
Any comments or questions are welcome!
Reference
이 문제에 관하여(CDK를 사용하여 EKS에서 NFS 볼륨 자동 프로비저닝), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/memark/autoprovisioning-nfs-volumes-in-eks-with-cdk-4fn9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)