안녕하세요, Cloudraw입니다!
Terraform으로 Kubernetes 다루기 두번째입니다.
- Kubernetes Provider 사용 방법, 기본 오브젝트 생성하기(Namespace, Pod, Service, Secret)
- 볼륨 리소스 다루기(CSP별 Blob 및 configmap mount)
- 네트워크 리소스 다루기(Ingress, Nginx-Ingress(Helm Chart))
- DNS 연동 및 인증서 발급(Let's Encrypt 및 Cert Manager(Helm))
- CloudStudio로 위 1~4 구성하기
두번째, 볼륨 리소스 다루기(CSP별 Blob 및 configmap mount)
이전글의 1. Kubernetes Provider 설정하기를 참고하여 동일하게 Provider를 설정해 줍니다.
1. 외부 Volume 활용을 위한 오브젝트 생성하기
각 리소스별 작성하는 값은 기존 Kubernetes에 사용하는 Yaml 파일과 유사하며 자세한 내용은 Kubernetes Docs Concept 과 Terraform Kubernetes Docs에서 확인 할 수 있습니다.
관련 오브젝트는 Terraform Kubernetes Docs의 Storage/v1과Core/v1에서 확인할 수 있습니다.
리소스 종류설명
Storage Class | 동적 볼륨 생성을 위한 클래스 정의 |
PersistentVolume(PV) | 클러스터 내 실제 스토리지 추상화 |
PersistentVolumeClaim(PVC) | 사용자가 원하는 스토리지 요청 |
ConfigMap | 설정 파일 또는 환경 변수 관리용 리소스 |
- Storage Class(Terraform Kubernetes Storage Class)
Storage Class는 동적 프로비저닝의 기초이며, 클러스터 관리자가 기본 스토리지 플랫폼에 대한 추상화를 정의할 수 있도록 합니다. Storage Class는 스토리지 플랫폼이나 클라우드 제공자에 특정한 프로비저너를 사용하여 Kubernetes가 사용 중인 물리적 미디어에 액세스할 수 있도록 지원합니다.
Disk 방식
resource "kubernetes_storage_class_v1" "cloudraw" {
metadata {
name = "cloudraw-storageclass" # 생성할 StorageClass 이름
}
storage_provisioner = "kubernetes.io/azure-disk" # Azure Disk 사용 시 지정
parameters = {
# Azure Disk 종류 (Standard_LRS, Premium_LRS 등)
storageaccounttype = "Standard_LRS"
kind = "Managed" # Managed Disk 유형
}
reclaim_policy = "Delete" # PVC 삭제 시 PV도 함께 삭제
volume_binding_mode = "Immediate" # PVC 생성 즉시 PV와 바인딩
}
CSP별 provisioner 값
- Azure: kubernetes.io/azure-disk
- AWS: kubernetes.io/aws-ebs
- Naver Cloud: csi.ncloud.com
Azure Blob 방식
resource "kubernetes_storage_class_v1" "cloudraw" {
metadata {
name = "cloudraw-sc" # 생성할 StorageClass 이름
}
storage_provisioner = "blob.csi.azure.com" # Azure Blob 사용 시 지정
parameters = {
containerName = "cloudraw-container" # Azure Blob 컨테이너명
storageAccount = "cloudrawstorageacct" # Azure Storage 계정명
protocol = "fuse2" # blobfuse2 기반
}
reclaim_policy = "Retain"
volume_binding_mode = "Immediate"
}
CSP별 Blob Storage용 CSI provisioner 값
(Azure Blob은 disk와 다르게 별도의 CSI 드라이버를 사용함)
- Azure Blob: blob.csi.azure.com
- AWS S3 (EKS용): s3.csi.aws.com (※ 공식 미지원, EKS 클러스터에 Helm 을 사용해서 S3 CSI 드라이버 설치 및 정적 PV 구성 필요)
- Naver Cloud: 공식 Blob CSI 미제공 (※ NAS 기반 csi 프로비저너인 nas.csi.ncloud.com 사용 권장)
CSP | CSI Provisioner 값 | 비고 |
Azure | blob.csi.azure.com | 공식 지원, AKS 기본 포함 |
AWS | s3.csi.aws.com (공식 Provisioner 아님) | Mountpoint for Amazon S3 CSI Driver 를 Helm으로 설치 후 사용. 정적 PV 방식만 가능하며, InitContainer 또는 S3 SDK를 활용한 Shim 방식도 활용 가능 |
Naver Cloud (NCP) | 공식 Blob CSI 미제공 | NFS 기반 CSI(nas.csi.ncloud.com) 사용 권장. 오브젝트 스토리지(S3 호환)는 직접 마운트는 불가하나, S3 API 기반의 Shim 방식으로 간접 연동 가능. |
💡 참고
Blob CSI는 일반 디스크 프로비저너(kubernetes.io/azure-disk 등)와는 별도로, 파일 기반 스토리지(Blob/Object)를Kubernetes에 마운트하기 위해 사용됩니다.
- Azure AKS에서는 blob.csi.azure.com이 기본 설치되어 있으며, 별도 플러그인 설치 없이 사용 가능합니다.
- AWS EKS에서는 s3.csi.aws.com은 공식 provisioner는 아니지만, AWS가 제공하는 Mountpoint for Amazon S3 CSI Driver를 Helm을 통해 설치해 사용할 수 있습니다. 단, 정적 PV 방식만 지원되며, rclone, s3cmd, InitContainer 기반 Shim 방식이나 분석 파이프라인의 Set 방식(데이터셋 직접 접근) 도 활용 가능합니다.
- Naver Cloud에서는 오브젝트 스토리지 전용 CSI 드라이버는 제공되지 않으며, nas.csi.ncloud.com을 통한 NAS 공유 스토리지 활용을 권장합니다. 다만, S3 호환 API를 활용한 Shim 방식(InitContainer 또는 Sidecar로 S3에서 직접 데이터 pull) 등을 통해 오브젝트 스토리지 연동이 가능합니다.
- Persist Volume (Terraform Kubernetes Persistent Volume)
PersistentVolume (PV) 은 관리자가 프로비저닝하거나 Storage Classes를 사용하여 동적으로 프로비저닝한 클러스터의 스토리지입니다.
Disk 방식
resource "kubernetes_persistent_volume_v1" "cloudraw" {
metadata {
name = "cloudraw-pv" # 생성할 PV 이름
}
spec {
capacity = {
storage = "10Gi" # Azure Disk 크기
}
access_modes = ["ReadWriteOnce"] # 하나의 노드에서 읽기/쓰기 가능
persistent_volume_reclaim_policy = "Delete" # PVC 삭제 시 PV도 삭제
azure_disk {
disk_name = "cloudraw-azuredisk" # Azure에서 생성된 Disk 이름
data_disk_uri = "https://<storage-account>.blob.core.windows.net/vhds/cloudraw-azuredisk.vhd"
fs_type = "ext4"
kind = "Managed"
}
}
}
⚠️ data_disk_uri는 Azure에서 미리 생성된 Managed Disk의 URI를 입력해야 하며, AKS 클러스터와 동일한 리소스 그룹 및 위치에 존재해야 합니다.
Blob 방식
💡 참고:
Azure Blob CSI는 오직 동적 프로비저닝만 지원하므로 기존 Azure Disk 방식과 달리 PersistentVolume(PV)을 직접 정의할 필요가 없습니다. PVC를 정의하면 해당 StorageClass를 기반으로 Kubernetes가 내부적으로 자동 PV를 생성하여 바인딩합니다.
- Persist Volume Claim(PVC) (Terraform Kubernetes Persistent Volume)
PersistentVolumeClaim (PVC) 은 사용자의 스토리지에 대한 요청입니다.
Disk 방식
resource "kubernetes_persistent_volume_claim_v1" "cloudraw" {
metadata {
name = "cloudraw-pvc" # 생성할 PVC 이름
namespace = kubernetes_namespace_v1.cloudraw.metadata[0].name # PVC를 생성할 네임스페이스
}
spec {
access_modes = ["ReadWriteOnce"] # 접근 모드: 단일 노드 읽기/쓰기
resources {
requests = {
storage = "10Gi" # 요청할 스토리지 용량
}
}
# 앞에서 정의한 StorageClass를 사용하여 동적으로 PV를 생성할 수 있습니다.
storage_class_name = kubernetes_storage_class_v1.cloudraw.metadata[0].name
}
}
✅ PVC는 StorageClass 없이도 특정 PV를 직접 요청할 수 있으나, 동적 볼륨 생성을 위해서는 storage_class_name을 지정해주는 것을 추천합니다.
Blob 방식
resource "kubernetes_persistent_volume_claim_v1" "cloudraw_blob_pvc" {
metadata {
name = "cloudraw-blob-pvc" # 생성할 PVC(Pod에서 이 이름을 참조하여 마운트)
# PVC가 생성될 네임스페이스
namespace = kubernetes_namespace_v1.cloudraw.metadata[0].name
}
spec {
access_modes = ["ReadWriteOnce"] # 읽기/쓰기 모드: 하나의 노드에서만 마운트 가능
resources {
requests = {
storage = "10Gi" # 요청하는 스토리지 용량 (Blob 컨테이너에 매핑될 크기)
}
}
# 사용할 StorageClass 지정 (blob.csi.azure.com provisioner 기반)
storage_class_name = kubernetes_storage_class_v1.cloudraw_blob.metadata[0].name
# 위에서 정의한 "cloudraw_blob" StorageClass를 참조
}
}
✅ Azure Disk 외에도 Blob Storage를 CSI 방식으로 연동하여 Pod에 마운트할 수 있습니다.
Blob Storage는 대용량, 저렴한 파일 저장소로 아카이브, 로그 수집 등에 활용됩니다.
Terraform에서는 `blob.csi.azure.com` 프로비저너를 사용하는 StorageClass를 정의하고, 해당 SC를 참조하는 PVC를 생성하여 사용할 수 있습니다.
- ConfigMap(Terraform Kubernetes ConfigMap)
resource "kubernetes_config_map_v1" "cloudraw" {
metadata {
name = "cloudraw-config" # 생성할 ConfigMap 이름
namespace = kubernetes_namespace_v1.cloudraw.metadata[0].name # 생성 위치 네임스페이스
}
data = {
"APP_ENV" = "production" # 애플리케이션 환경 구분 (예: dev, prod)
"APP_DEBUG" = "false" # 디버그 설정 여부
}
}
ConfigMap 주입 방식
envFrom | ConfigMap의 모든 key를 환경변수로 한 번에 주입합니다. (APP_ENV, APP_DEBUG 등이 각각 ENV로 설정됨) |
valueFrom | ConfigMap 내 특정 key 하나만 선택하여 환경변수로 주입합니다. (예: APP_ENV만 주입) |
volume mount | 파일 형태로 컨테이너 내에 마운트합니다. key가 파일 이름, value가 파일 내용이 됨 |
envFrom 예시
env_from {
config_map_ref {
name = kubernetes_config_map_v1.cloudraw.metadata[0].name # 전체 ConfigMap을 주입
}
}
valueFrom 예시
env {
name = "APP_ENV" # 주입할 환경 변수명
value_from {
config_map_key_ref {
name = kubernetes_config_map_v1.cloudraw.metadata[0].name
key = "APP_ENV" # 해당 ConfigMap의 key
}
}
}
2. CSP별 Volume 연결(연결자 및 옵션)
Kubernetes에서 Volume을 사용하기 위해선, 사용하는 CSP(Cloud Service Provider)에 따라 설정 방식이 다릅니다. StorageClass나 PersistentVolume(PV)의 구성 옵션, 프로비저너(provisioner) 값, 연결 방식에 차이가 있으며, Terraform으로 정의할 때 이를 정확히 구분해서 작성해야 합니다.
CSP별 프로비저너 및 주요 차이점
CSP | provisioner | 특징 | 주요 옵션 |
Azure | kubernetes.io/azure-disk | Azure Managed Disk를 사용 | kind, storageaccounttype |
AWS | kubernetes.io/aws-ebs | AWS EBS 사용 | type, fsType, zone |
Naver Cloud (NCP) | csi.ncloud.com | NCP Block Storage CSI 사용 | volumeType, iops, zoneCode 등 |
✅ Terraform으로 구성할 때 CSP마다 요구하는 파라미터와 설정값이 다르므로, 공식 문서와 연계해서 구성하는 것이 중요합니다.
- 새로운 Volume 생성하기
StorageClass와 PVC를 함께 정의하면, Kubernetes가 CSP API를 통해 자동으로 디스크(볼륨)를 생성합니다. Terraform에서는 다음과 같은 방식으로 작성합니다.
🔵 Azure 예시 (Managed Disk 기반)
Azure Disk 방식은 AWS EBS와 유사하게 StorageClass, PVC만 정의하면 자동으로 디스크가 생성되어 Pod에 바인딩됩니다. Availability Zone은 자동으로 할당되며, 반드시 동일 리전 내 리소스만 연결이 가능합니다.
Storage class 정의
# Azure Managed Disk를 동적으로 사용하는 StorageClass 예시
resource "kubernetes_storage_class_v1" "azure_storageclass" {
metadata {
name = "azure-manageddisk-sc" # StorageClass 이름
}
provisioner = "kubernetes.io/azure-disk" # Azure Disk용 프로비저너
parameters = {
kind = "Managed" # 디스크 유형 (Managed 또는 Shared)
storageaccounttype = "Premium_LRS" # 디스크 성능/내구성 옵션 (Standard_LRS, Premium_LRS 등)
cachingmode = "ReadOnly" # 캐싱 모드 (None, ReadOnly, ReadWrite)
}
reclaim_policy = "Delete" # PVC 삭제 시 PV도 삭제
volume_binding_mode = "Immediate"
}
PersistentVolumeClaim 정의
# 위 StorageClass를 사용하는 PVC 예시
resource "kubernetes_persistent_volume_claim_v1" "azure_pvc" {
metadata {
name = "azure-disk-pvc" # PVC 이름
namespace = "default" # PVC가 생성될 네임스페이스
}
spec {
access_modes = ["ReadWriteOnce"] # 단일 노드에서 읽기/쓰기 가능
resources {
requests = {
storage = "10Gi" # 요청할 디스크 크기
}
}
storage_class_name = kubernetes_storage_class_v1.azure_storageclass.metadata[0].name
# 위에서 정의한 StorageClass를 참조
}
}
✅ Azure Disk 방식은 AWS EBS와 유사하게 StorageClass, PVC만 정의하면 자동으로 디스크가 생성되어 Pod에 바인딩됩니다. Availability Zone은 자동으로 할당되며, 반드시 동일 리전 내 리소스만 연결이 가능합니다.
🔵 Azure 예시 (Blob Storage 기반)
Storage Class 정의
# Azure Blob Storage(CSI) 기반 StorageClass 예시
resource "kubernetes_storage_class_v1" "azure_blob_storageclass" {
metadata {
name = "azure-blob-sc" # StorageClass 이름
}
provisioner = "blob.csi.azure.com" # Azure Blob CSI 드라이버
parameters = {
containerName = "cloudraw-container" # Blob 컨테이너 이름 (Azure Portal에서 사전 생성 필요)
storageAccount = "cloudrawstorageacct" # Azure Storage 계정명
protocol = "fuse2" # blobfuse2 기반 (또는 nfs)
}
reclaim_policy = "Retain"
volume_binding_mode = "Immediate"
}
PersistentVolumeClaim 정의
# 위 StorageClass를 사용하는 Blob PVC 예시
resource "kubernetes_persistent_volume_claim_v1" "azure_blob_pvc" {
metadata {
name = "azure-blob-pvc" # PVC 이름
namespace = "default"
}
spec {
access_modes = ["ReadWriteOnce"] # 단일 노드 마운트
resources {
requests = {
storage = "10Gi" # 요청할 Blob 용량
}
}
storage_class_name = kubernetes_storage_class_v1.azure_blob_storageclass.metadata[0].name
# 위에서 정의한 Blob StorageClass 참조
}
}
✅ Azure Blob Storage(CSI)는 Block Storage와 다르게 수동 PV를 작성하지 않으며, StorageClass + PVC 조합만으로 자동 바인딩이 됩니다.
⚠️ Pod에는 파일시스템처럼 마운트되며, Blob 컨테이너와 Storage 계정은 미리 Azure에서 생성해 두어야 합니다.
🟠 AWS 예시 (Amazon EBS 기반)
AWS에서는 kubernetes.io/aws-ebs 프로비저너를 사용하며, type, fsType, zone 같은 파라미터를 통해 원하는 스토리지 유형과 위치를 지정합니다.
Storage Class 정의
resource "kubernetes_storage_class_v1" "aws_storageclass" {
metadata {
name = "aws-ebs-sc"
}
provisioner = "kubernetes.io/aws-ebs" # AWS EBS 프로비저너
parameters = {
type = "gp3" # EBS 타입 (gp2, gp3, io1 등)
fsType = "ext4" # 파일 시스템 형식
zone = "ap-northeast-2a" # 해당 노드가 존재하는 AZ와 반드시 일치해야 함
}
reclaim_policy = "Delete"
volume_binding_mode = "Immediate"
}
PersistentVolumeClaim 정의
resource "kubernetes_persistent_volume_claim_v1" "aws_pvc" {
metadata {
name = "aws-pvc"
namespace = "default"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "10Gi"
}
}
storage_class_name = kubernetes_storage_class_v1.aws_storageclass.metadata[0].name
}
}
⚠️ zone 값은 반드시 Kubernetes 노드가 존재하는 AZ(Availability Zone) 과 일치해야 합니다.
다를 경우 EBS 볼륨을 Pod에 Attach할 수 없어 실패합니다. EKS 노드 그룹이 위치한 AZ를 확인한 뒤 설정해줍니다.
🟢 Naver Cloud (NCP Block Storage 기반)
Naver Cloud에서는 CSI 드라이버(csi.ncloud.com)를 통해 동적 볼륨 생성을 지원합니다. NCP에서는 volumeType, volumeSize, availabilityZoneCode 등을 명시합니다.
Storage Class 정의
resource "kubernetes_storage_class_v1" "ncp_storageclass" {
metadata {
name = "ncp-block-storage-sc"
}
provisioner = "csi.ncloud.com" # Naver Cloud CSI 드라이버
parameters = {
volumeType = "SSD" # HDD 또는 SSD
volumeSize = "100" # 디스크 크기 (GiB 단위)
availabilityZoneCode = "KR-1" # NCP Zone 코드 (예: KR-1, KR-2 등)
}
reclaim_policy = "Delete"
volume_binding_mode = "WaitForFirstConsumer" # Pod이 생성된 후 바인딩 (권장)
}
PersistentVolumeClaim 정의
resource "kubernetes_persistent_volume_claim_v1" "ncp_pvc" {
metadata {
name = "ncp-pvc"
namespace = "default"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "100Gi"
}
}
storage_class_name = kubernetes_storage_class_v1.ncp_storageclass.metadata[0].name
}
}
✅ NCP는 availabilityZoneCode를 명시해야 하며, Kubernetes 클러스터 노드가 위치한 존과 동일해야 정상적으로 연결됩니다.
⚠️ volumeSize 단위는 문자열 "100"처럼 숫자를 문자열로 처리해야 합니다 (Terraform limitation).
WaitForFirstConsumer 모드를 사용하면 실제 Pod이 스케줄링될 때 적절한 Zone으로 자동 연결됩니다.
- 존재하는 Volume 사용하기
Cloud Provider(CSP)에서 이미 생성되어 있는 Block Storage 또는 EBS 디스크를 Kubernetes에서 활용하려면, 해당 디스크를 참조하는 PersistentVolume(PV) 리소스를 먼저 정의한 뒤, PersistentVolumeClaim(PVC) 에서 직접 연결해주어야 합니다. 이 경우, 자동으로 디스크를 생성하지 않고, 사용자가 미리 확보한 디스크를 수동 연결하는 방식입니다.
🔵 Azure 예시 (Managed Disk 기반)
PersistentVolume 정의
# 이미 Azure에서 생성한 Managed Disk를 사용하는 PV 정의
resource "kubernetes_persistent_volume_v1" "azure_pv" {
metadata {
name = "azure-pv" # PV 이름
}
spec {
capacity = {
storage = "10Gi" # 실제 디스크 크기와 동일하게 설정
}
access_modes = ["ReadWriteOnce"] # 단일 노드에서만 읽기/쓰기 허용
persistent_volume_reclaim_policy = "Retain" # PVC 삭제 후에도 PV(디스크) 유지
azure_disk {
disk_name = "my-managed-disk" # Azure에서 생성한 Managed Disk 이름
data_disk_uri = "https://<storage_account>.blob.core.windows.net/vhds/my-managed-disk.vhd"
fs_type = "ext4" # 디스크 포맷 타입
kind = "Managed"
}
}
}
PersistentVolumeClaim 정의
# 위 PV를 PVC에서 직접 참조해 연결
resource "kubernetes_persistent_volume_claim_v1" "azure_pvc_static" {
metadata {
name = "azure-pvc-static" # PVC 이름
namespace = "default"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "10Gi" # PV와 동일하게 설정
}
}
volume_name = "azure-pv" # 위에서 정의한 PV 이름과 동일하게 명시
}
}
💡 참고:
이 방식은 Azure Portal이나 CLI를 통해 미리 Managed Disk를 생성한 경우에 사용합니다.
Blob Storage는 동적 프로비저닝만 지원하므로, 수동 PV 작성이 필요 없습니다.(불가)
🟠 AWS 예시 (기존 Amazon EBS 연결 )
PersistentVolume 정의
# AWS EBS 볼륨을 직접 참조하는 PV 정의
resource "kubernetes_persistent_volume_v1" "aws_pv" {
metadata {
name = "aws-pv" # 생성할 PV 이름 (PVC에서 참조할 이름)
}
spec {
capacity = {
storage = "10Gi" # EBS 볼륨의 크기 (Gi 단위로 PV 정의)
}
access_modes = ["ReadWriteOnce"] # 단일 노드에서 읽기/쓰기 허용
persistent_volume_reclaim_policy = "Retain" # PVC 삭제 시에도 PV 유지 (데이터 보존 목적)
aws_elastic_block_store {
volume_id = "vol-xxxxxxxxxxxx" # 사전에 AWS에서 생성한 EBS 볼륨 ID
fs_type = "ext4" # 파일 시스템 타입 (EBS에 포맷된 타입과 일치해야 함)
}
}
}
⚠️ volume_id에는 AWS 콘솔 또는 CLI로 사전에 생성한 EBS ID를 정확히 입력해야 하며, 해당 볼륨은 EKS 노드와 동일한 Availability Zone (AZ) 에 위치해야 합니다.
PersistentVolumeClaim 정의
# 위 PV 리소스를 참조하여 PVC를 수동으로 바인딩
resource "kubernetes_persistent_volume_claim_v1" "aws_pvc_static" {
metadata {
name = "aws-pvc-static" # PVC 이름
namespace = "default" # PVC가 속할 네임스페이스
}
spec {
access_modes = ["ReadWriteOnce"] # 단일 노드 읽기/쓰기
resources {
requests = {
storage = "10Gi" # PV에서 정의한 용량과 동일해야 함
}
}
volume_name = "aws-pv" # 🔗 위에서 정의한 PV 이름과 직접 연결 (StorageClass 없이 명시적 바인딩)
}
}
✅ 이 방식은 동적 생성이 아닌, 이미 존재하는 EBS 디스크를 Kubernetes에 직접 연결하고자 할 때 사용됩니다.
⚠️ 수동 바인딩 시에는 반드시 StorageClass를 명시하지 않고, volume_name으로 바인딩합니다.
🟢 Naver Cloud (NCP Block Storage 기반)
PersistentVolume 정의 (CSI 기반)
# NCP에서 생성한 Block Storage를 직접 참조하는 PV 정의
resource "kubernetes_persistent_volume_v1" "ncp_pv" {
metadata {
name = "ncp-block-pv" # PV 이름 (PVC에서 참조할 이름)
}
spec {
capacity = {
storage = "100Gi" # Block Storage 크기 (Gi 단위)
}
access_modes = ["ReadWriteOnce"] # 단일 노드에서 읽기/쓰기 가능
persistent_volume_reclaim_policy = "Retain" # 삭제 시 데이터 보존
csi {
driver = "csi.ncloud.com" # Naver Cloud CSI 드라이버 이름
volume_handle = "bvol-xxxxxxxxx" # NCP에서 생성한 Block Storage ID (정확히 입력)
fs_type = "ext4" # 디스크의 파일 시스템 형식
volume_attributes = {
volumeType = "SSD" # Block Storage 유형 (HDD 또는 SSD)
availabilityZoneCode = "KR-1" # Block Storage가 위치한 NCP Zone 코드
}
}
}
}
PersistentVolumeClaim 정의
# 위 PV와 수동으로 연결되는 PVC 정의
resource "kubernetes_persistent_volume_claim_v1" "ncp_pvc_static" {
metadata {
name = "ncp-pvc-static" # PVC 이름
namespace = "default" # 네임스페이스 지정
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "100Gi" # PV와 동일한 스토리지 용량 요청
}
}
volume_name = "ncp-block-pv" # 위 PV와 수동으로 바인딩
}
}
✅ 이 구조는 Block Storage를 수동으로 연동할 때 가장 기본적인 방식이며, StorageClass는 지정하지 않고 volume_name으로 직접 PV와 연결하는 것이 핵심입니다.
정리 요약
항목 | Azure(Disk/Blob) | AWS (EBS) | Naver Cloud (Block Storage) |
프로비저너 | - kubernetes.io/azure-disk - blob.csi.azure.com (Blob 전용) |
kubernetes.io/aws-ebs | csi.ncloud.com |
수동 PV 방식 |
'azure_disk' 블록 | aws_elastic_block_store | 'csi' 블록 |
볼륨 참조 방식 | disk_name, data_disk_uri |
volume_id | volume_handle |
Zone 제약 사항 | 동일 Region 유지 (Blob은 Regional, Disk는 Zonal) |
Node와 동일 AZ 필수 | Node와 동일 availabilityZoneCode 필요 |
수동 PVC 필드 | volume_name | volume_name | volume_name |
특이 사항 | - Blob: PVC만 지원 (정적 PV 불가) - Disk: PV/PVC 모두 지원 |
fsType, partition 등 필수 | volume_attributes로 zone, type 필요 |
💡 참고
이 표는 Block Storage (디스크 기반) CSI 드라이버 기준 비교입니다.
Azure는 Disk와 Blob을 서로 다른 드라이버로 분리하여 제공하며, Blob용은 blob.csi.azure.com으로 PVC만 사용 가능합니다.
AWS S3, Naver Cloud Object Storage는 공식 Blob 방식 CSI 드라이버를 제공하지 않으며, Naver Cloud의 경우 NAS 기반(nas.csi.ncloud.com) CSI 드라이버 사용을 권장합니다.
3. Pod에 Volume Mount 하기
앞서 StorageClass, PersistentVolume, PersistentVolumeClaim, ConfigMap을 모두 정의했다면 이제 실제 애플리케이션 Pod에 이를 연결(Mount) 하여 사용할 수 있습니다. Pod에 볼륨을 연결하기 위해선 다음과 같은 구성 요소가 필요합니다.
구성 요소 | 설명 |
volume_mount | 컨테이너 내부에 마운트할 경로 지정 |
volume | 어떤 PVC를 연결할지 지정 |
env_from 또는 env | ConfigMap을 환경 변수로 주입 |
- 작성 방법
Disk 방식
Pod 리소스 정의 (PVC + ConfigMap)
# PVC와 ConfigMap을 사용하는 Pod 정의
resource "kubernetes_pod_v1" "cloudraw" {
metadata {
name = "cloudraw-pod" # 생성할 Pod 이름
namespace = kubernetes_namespace_v1.cloudraw.metadata[0].name # 배포될 네임스페이스
labels = {
app = "cloudraw" # 서비스 및 셀렉터 연동 시 사용할 라벨
}
}
spec {
container {
name = "cloudstudio" # 컨테이너 이름
image = "cloudraw.azurecr.io/cloudstudio:latest" # 사용할 이미지 (예: ACR에서 가져옴)
# PVC를 컨테이너 내 특정 경로에 마운트
volume_mount {
name = "app-volume" # 아래 volume 블록에서 정의한 이름과 동일해야 함 예시)
mount_path = "/app/data" # 컨테이너 내에서 데이터를 저장할 경로 (현재 경로는 예시)
}
# ConfigMap 전체를 환경변수로 한 번에 주입 (envFrom 방식)
env_from {
config_map_ref {
name = kubernetes_config_map_v1.cloudraw.metadata[0].name
}
}
# (선택) 특정 key만 환경변수로 주입하려면 아래 사용 (valueFrom 방식)
# env {
# name = "APP_ENV"
# value_from {
# config_map_key_ref {
# name = kubernetes_config_map_v1.cloudraw.metadata[0].name
# key = "APP_ENV"
# }
# }
# }
}
# volume 블록에서 PVC를 참조하여 Pod과 연결
volume {
name = "app-volume" # volume_mount 블록과 동일한 이름
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim_v1.cloudraw.metadata[0].name
# 연결할 PVC 이름 (앞서 정의한 cloudraw-pvc)
}
}
}
}
⚠️ 유의사항
volume_mount.name과 volume.name은 정확히 일치해야 합니다. PVC가 Bound 상태가 아니면 Pod 생성 시 Pending 상태로 멈춥니다. PVC는 반드시 사전에 정의되어 있어야 하고, 같은 Namespace 안에 존재해야 합니다. ConfigMap을 환경변수로 사용할 땐 key 이름과 충돌하지 않도록 주의해야 합니다.
Blob 방식
resource "kubernetes_pod_v1" "cloudraw_blob_pod" {
metadata {
name = "cloudraw-pod" # 생성할 Pod의 이름
namespace = kubernetes_namespace_v1.cloudraw.metadata[0].name # Pod가 배포될 네임스페이스
labels = {
app = "cloudraw-blob" # 서비스 선택자 등에서 활용할 수 있는 라벨 지정
}
}
spec {
container {
name = "cloudstudio" # 컨테이너 이름
image = "cloudraw.azurecr.io/cloudstudio:latest" # 사용할 이미지 (예: ACR에서 가져옴)
volume_mount {
name = "blob-volume" # 아래 volume 블록에서 정의한 이름과 일치해야 함
mount_path = "/mnt/blob" # 컨테이너 내부에 마운트될 경로 (현재 경로는 예시)
}
env {
name = "STORAGE_MOUNT" # 환경 변수 이름
value = "/mnt/blob" # 환경 변수 값 (위 마운트 경로와 동일하게 설정)
# 이 값을 통해 애플리케이션이 마운트된 경로를 인식 가능
}
}
volume {
name = "blob-volume" # volume_mount에서 지정한 이름과 동일하게 설정
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim_v1.cloudraw_blob_pvc.metadata[0].name
# 앞서 정의한 Azure Blob PVC를 참조하여 연결
# PVC를 통해 실제 Blob Storage에 접근하게 됨
}
}
}
}
이 Pod는 Azure Blob PVC를 `/mnt/blob` 경로에 마운트하며, 환경 변수 'STORAGE_MOUNT'를 통해 애플리케이션에서 해당 경로를 쉽게 참조할 수 있도록 구성되어 있습니다.
⚠️ 주의할 점:
- 'volume_mount.name'과 'volume.name'은 반드시 일치해야 합니다.
- 'claim_name'으로 참조하는 PVC는 반드시 미리 생성되어 있어야 하며, 같은 네임스페이스에 존재해야 합니다.
- Azure Blob CSI는 파일 시스템 기반으로 마운트되며, NFS나 Blobfuse2를 통해 동작합니다.
- plan 및 apply
Terraform 명령어 실행
terraform plan
terraform apply
Pod, PVC, ConfigMap이 정상적으로 생성되고 연결되었는지 확인합니다.
- Terraform으로 Kubernetes 다루기 - 1/5 과정을 이어서 진행하셨다면
Plan 결과, 4개의 리소스가 새로 추가되고 Pod의 속성 변경으로 인해 1개의 리소스가 destroy되는 것을 확인할 수 있습니다.
- apply 결과 동일하게 Pod의 속성 변경으로 인해 1개의 리소스가 destroy 되고, 개의 리소스가 새로 추가되는 것을 볼 수 있습니다.
- mount folder 확인
마운트 경로 확인
kubectl exec -n cloudraw-namespace cloudraw-pod -- ls /app/data #Disk 방식으로 했을 시
kubectl exec -n cloudraw-namespace cloudraw-pod -- ls /mnt/blob #Blob 방식으로 했을 시
→ /app/data 또는 /mnt/blob 경로가 정상적으로 보이면 마운트 성공
환경 변수 확인
kubectl exec -n cloudraw-namespace cloudraw-pod -- printenv | grep APP_
→ APP_ENV, APP_DEBUG 값이 출력되면 ConfigMap 주입 성공
📌 Pod 내에서 동작 구조 요약
PersistentVolumeClaim (cloudraw-pvc)
│
▼
Volume (app-volume)
│
▼
Pod Container
│
├── /app/data ← 실제 마운트 위치
└── ENV: APP_ENV, APP_DEBUG ← ConfigMap 주입
이로써 Pod 내부에 볼륨을 마운트하고 설정(ConfigMap)을 적용하는 과정까지 Terraform 기반으로 모두 구성 완료되었습니다.
다음 단계에서는 Ingress 및 Helm Chart를 활용해 애플리케이션을 외부에서 접근 가능하도록 노출하는 과정을 다뤄보겠습니다.
감사합니다.
Cloudraw는 쉽게 클라우드 인프라를 그리고 사용할 수 있는 서비스를 제공하기 위해 노력하고 있습니다.
클라우드가 있는 곳 어디든 Cloudraw가 함께합니다.
📨 help@cloudraw.kr
'IaC' 카테고리의 다른 글
[IaC] Terraform Enterprise AKS에 배포하기 (0) | 2025.02.07 |
---|---|
[IaC] Terraform Module 작성 및 사용방법 (2) | 2024.12.03 |
[IaC] Terraform으로 Kubernetes 다루기 - 1/5 (0) | 2024.09.19 |
[IaC] Terraform import 개념 및 사용방법 (0) | 2024.06.03 |
[IaC] Terraform 작성 및 배포(2) - for_each, flatten, local values (1) | 2024.03.05 |