Kubernetes 에서 CSI Driver 를 활용한 ebs storage 사용하기
이전에는 aws 에 Kubernetes Cluster 를 설치한 후 Load Balancer 를 연결한는 방법을 설명하였다. Kubernetes Cluster 를 사용하려면 Load Balancer 외에도 필요한 기능이 있는데 그것이 바로 Storage 이다.
Pod 에서 영구적으로 데이터를 저장하기 위해서는 ebs 와 같은 Block Storage 를 생성해서 연결해야 하는데 Kubernetes 에서는 CSI 로 이를 지원하고 있다.
aws 에서 ebs 를 사용하려면 아래의 순서대로 적용한다.
- IAM Policy 생성
- CSI Driver (Provisioner) 설치
- Storage Class 생성
- PVC, POD 로 테스트
1. IAM Policy 생성
CSI 를 위한 IAM Policy 는 생성하기 전에 이미 만들어서 제공되고 있는 Managed Policy 를 사용해도 된다. arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy
하지만 새로 만든다고 하면 아래와 같이 만들수 있다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateSnapshot",
"ec2:AttachVolume",
"ec2:DetachVolume",
"ec2:ModifyVolume",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInstances",
"ec2:DescribeSnapshots",
"ec2:DescribeTags",
"ec2:DescribeVolumes",
"ec2:DescribeVolumesModifications"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateTags"
],
"Resource": [
"arn:aws:ec2:*:*:volume/*",
"arn:aws:ec2:*:*:snapshot/*"
],
"Condition": {
"StringEquals": {
"ec2:CreateAction": [
"CreateVolume",
"CreateSnapshot"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DeleteTags"
],
"Resource": [
"arn:aws:ec2:*:*:volume/*",
"arn:aws:ec2:*:*:snapshot/*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateVolume"
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:RequestTag/ebs.csi.aws.com/cluster": "true"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateVolume"
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:RequestTag/CSIVolumeName": "*"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DeleteVolume"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/ebs.csi.aws.com/cluster": "true"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DeleteVolume"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/CSIVolumeName": "*"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DeleteVolume"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/kubernetes.io/created-for/pvc/name": "*"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DeleteSnapshot"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/CSIVolumeSnapshotName": "*"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DeleteSnapshot"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/ebs.csi.aws.com/cluster": "true"
}
}
}
]
}
Role 에 Policy 연결
이전 글에서 설명한 control-plane.cluster-api-provider-aws.sigs.k8s.io
와 nodes.cluster-api-provider-aws.sigs.k8s.io
role 에 위의 Policy 를 연결한다.
Role : control-plane.cluster-api-provider-aws.sigs.k8s.io
Role : nodes.cluster-api-provider-aws.sigs.k8s.io
2. CSI Driver (Provisioner) 설치
EBS 용 CSI Driver 를 helm chart repo 를 등록한다.
$ helm repo add aws-ebs-csi-driver https://kubernetes-sigs.github.io/aws-ebs-csi-driver
$ helm repo update
$ helm search repo aws-ebs-csi-driver -l
NAME CHART VERSION APP VERSION DESCRIPTION
aws-ebs-csi-driver/aws-ebs-csi-driver 2.16.0 1.15.0 A Helm chart for AWS EBS CSI Driver
aws-ebs-csi-driver/aws-ebs-csi-driver 2.15.1 1.14.1 A Helm chart for AWS EBS CSI Driver
...
지금 최신 버전 차트는 2.16.0 이다. 해당 차트는 Kubernetes 1.17+ 이상만 호환되는데 현재의 웬만한 Kubernetes 버전은 지원된다고 보면 된다.
Helm chart 로 설치한다.
$ helm upgrade -i aws-ebs-csi-driver -n kube-system aws-ebs-csi-driver/aws-ebs-csi-driver --version 2.16.0
설치가 제대로 되었는지는 아래의 명령어로 확인할 수 있다.
3. Storage Class 설치
ebs volume 이 생성될 때 CSI Driver 에게 필요한 설정 값을 전달해야 하는데 이것이 바로 Storage Class 라고 보면 된다.
아래와 같이 생성한다.
$ vi standard-ebs-sc.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
storageclass.kubernetes.io/is-default-class: "true"
name: standard
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
$ kubectl apply -f standard-ebs-sc.yaml
storage class 에 storage type (gp2, gp3, io1 등), iops, 데이터 암호화 여부, 토폴로지 등을 넣을 수 있는데 이를 적용하면 현재 csi driver 에서 에러가 나므로 추가 확인이 필요하다. (볼륨 생성이 안된다던지, 볼륨 attach 가 안된다든지 하는 문제가 발생했는데 자세히 소스까지 찾아보지는 않았음 ㅠㅠ)
storage class 가 잘 생성되었는지 확인한다.
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path rancher.io/local-path Delete WaitForFirstConsumer false 12d
standard (default) ebs.csi.aws.com Delete WaitForFirstConsumer false 138m
4. PVC, POD 로 테스트
pvc 를 생성하고 pod 에서 이를 mount 하여 활용해본다.
pvc 생성
$ vi pvc-example.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 4Gi
$ kubectl apply -f pvc-example.yaml
sc 설정에서 volumeBindingMode: WaitForFirstConsumer
이기 때문에 pod 가 생성되기 전까지는 pv 는 만들어지지 않는다.
POD 생성
$ vi pod-example.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
$ kubectl apply -f pod-example.yaml
out.txt 에 date 값이 설정된 것을 확인할 수 있다.
$ kubectl exec -it app -- cat /data/out.txt