본문 바로가기
IaC

[IaC] Terraform으로 Kubernetes 다루기 - 1/5

by cloudraw 2024. 9. 19.

안녕하세요, 클라우드로입니다!

앞으로 5회에 걸쳐 Terraform으로 Kubernetes 리소스를 구성하고 서비스를 호스팅하는 방법에 대해 다뤄보고자 합니다.

회차별 주제는 아래와 같습니다.

  1. Kubrernetes Provider 사용 방법, 기본 오브젝트 생성하기(Namespace, Pod, Service, Secret)
  2. 볼륨 리소스 다루기(CSP별 Blob 및 configmap mount)
  3. 네트워크 리소스 다루기(Ingress, Nginx-Ingress(Helm Chart))
  4. DNS 연동 및 인증서 발급(Let's Encrypt 및 Cert Manager(Helm))
  5. CloudStudio로 위 1~4 구성하기

그럼 바로 시작해볼까요?

첫번째, Kubrernetes Provider 사용 방법, 기본 오브젝트 생성하기(Namespace, Pod, Service, Secret)

1. Kubernetes Provider 설정하기

먼저 terraform block을 선언하고 사용할 required_providers를 정의해 주세요.(CSP의 Cluster를 불러와 사용하려면 각 CSP별 Provider를 작성해주어야합니다.)

terraform {
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "<사용할 version>"
    }
  }
}

다음 Terraform으로 Kubernetes 리소스를 다루기 위해 다른 CSP와 마찬가지로 Provider를 선언해주어야 합니다. 

Terraform Kubernetes Repository

  • 로컬 환경에 저장되어 있는 config를 불러와서 설정하려면 아래와 같이 설정할 수 있습니다.
provider "kubernetes" {
  config_path = "~/.kube/config"
  config_context = "<context 이름>" # kubectl config get-contexts
}
  • 원격으로 Kubernetes 정보를 불러와서 설정하려면 아래와 같이 설정할 수 있습니다
provider "kubernetes" {
  host = "<원격 cluster 주소>"

  client_certificate     = file("~/.kube/client-cert.pem")
  client_key             = file("~/.kube/client-key.pem")
  cluster_ca_certificate = file("~/.kube/cluster-ca-cert.pem")
}
  • CSP별 구성되어 있는 Cluster를 불러와서 설정하려면 data block을 사용하여 아래와 같이 설정할 수 있습니다. CSP별로 큰 차이는 없지만 구성이 다르기 때문에 사용하는 값이 다를 수 있습니다.
    - Azure AKS
provider "azurerm" {
  tenant_id       = "<tenant id>"
  subscription_id = "<subscription id>"
  client_id       = "<app client id>"
  client_secret   = "<app secret>"
}

data "azurerm_kubernetes_cluster" "aks" {
  name                = "<cluster 이름>"
  resource_group_name = "<cluster가 속한 resource group 이름>"
}

provider "kubernetes" {
  host                   = data.azurerm_kubernetes_cluster.aks.kube_config.0.host
  client_certificate     = base64decode(data.azurerm_kubernetes_cluster.aks.kube_config.0.client_certificate)
  client_key             = base64decode(data.azurerm_kubernetes_cluster.aks.kube_config.0.client_key)
  cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_config.0.cluster_ca_certificate)
}

     
      - AWS EKS

provider "aws" {
  region     = "<region>"
  access_key = "<access key>"
  secret_key = "<secret key>"

}

data "aws_eks_cluster" "cloudraw" {
  name = "<Cluster 이름>"
}

data "aws_eks_cluster_auth" "cloudraw" {
  name = "<Cluster 이름>"
}

provider "kubernetes" {
  host                   = data.aws_eks_cluster.cloudraw.endpoint
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.cloudraw.certificate_authority[0].data)
  token                  = data.aws_eks_cluster_auth.cloudraw.token
}

   

     - NCloud NKS       

provider "ncloud" {
  region      = "<region>"
  access_key  = "<access key>"
  secret_key  = "<secret key>"
  support_vpc = true
}

data "ncloud_nks_kube_config" "cloudraw" {
  cluster_uuid = "<cluster uuid>"
}

provider "kubernetes" {
  host                   = data.ncloud_nks_kube_config.cloudraw.host
  token                  = "<cluster service account 토큰>"
  cluster_ca_certificate = base64decode(data.ncloud_nks_kube_config.cloudraw.cluster_ca_certificate)
}

  ※ cluster service account token은 다음 명령으로 조회 할 수 있으며 적절한 권한이 할당되어 있어야합니다. 

kubectl describe secret $(kubectl describe serviceaccount default --namespace=default | grep Token | awk '{print $2}') --namespace=default

 

 provider 및 data block 작성 후 Terrafrom 명령을 실행(init, plan, apply)하면 terraform.tfstate파일이 생성되며 연결된 Cluster의 정보를 확인 할 수 있으며 연결된 클러스터상 오브젝트를 생성 할 수 있습니다. 

 

2. Kubernetes 기본 오브젝트 생성하기(Namespace, Pod, Service, Secret)

 다음으로 위에서 설정된 Cluster Provider에 기본 오브젝트를 생성해 보겠습니다.

각 리소스별 작성하는 값은 기존 Kubernetes에 사용하는 Yaml 파일과 유사하며 자세한 내용은 Kubernetes Docs Concept Terraform Kubernetes Docs에서 확인 할 수 있습니다.

 

기본 오브젝트는 Terraform Kubernetes Docs의 Core/v1에서 확인할 수 있습니다.

 

*각 리소스별 옵션은 필수 값 위주로 최소화하여 작성하겠습니다.

 

- Namespace 생성하기(Terraform Kubernetes Namespace)

resource "kubernetes_namespace_v1" "cloudraw" {
  metadata {
    annotations = {}
    labels = {}
    name = "cloudraw-namespace" #생성할 namespace 이름
  }
}

 

- Pod 생성하기(Terraform Kubernetes Pod)

Pod는 CloudStudio프론트엔드 이미지를 Private Repository에서 불러와서 생성하겠습니다.

 

resource "kubernetes_pod_v1" "cloudraw" {
  metadata {
    name        = "cloudraw-pod" # 생성할 pod 이름
    namespace   = kubernetes_namespace_v1.cloudraw.metadata[0].name # pod를 생성할 namespace
    annotations = {}
    labels = {
      app = "cloudraw-pod" # service와 연동을 위한 라벨
    }
  }
  spec {
    container {
      name    = "server" # container 이름
      image   = "cloudraw.azurecr.io/cloudstudio:sha..." # 이미지 이름 및 태그
      args    = []
      command = []
      port {
        container_port = "80" # container port
      }
    }
    image_pull_secrets {
      name = kubernetes_secret_v1.cloudraw.metadata[0].name  # image pull에 사용되는 secret 이름, public image 사용시 불필요
    }
  }
}

 

- Service 생성하기(Terraform Kubernetes Service)

 Service는 외부 서비스 노출 및 향 후 Ingress와의 연결을 위해 생성하여 Pod와 연결하겠습니다.

 

resource "kubernetes_service_v1" "cloudraw" {
  metadata {
    name        = "cloudraw-service" # 생성할 service 이름
    namespace   = kubernetes_namespace_v1.cloudraw.metadata[0].name # service를 생성할 namespace 이름
    annotations = {}
    labels      = {}
  }
  spec {
    selector = {
      app = "cloudraw-pod" # 연결할 pod의 라벨
    }
    session_affinity = "None"
    port {
      name        = "http"
      protocol    = "TCP"
      port        = "80"
      target_port = "80"
    }
    type = "ClusterIP"
  }
}

 

- Secret 생성하기(Terraform Kubernetes Secret)

 Secert은 여러 종류가 있지만 그 중 Pod에 사용하는 이미지를 원격 레지스트리에서 불러오기 위한 imagePullSecret을 생성하여 Pod에 적용해 보겠습니다. 

 

resource "kubernetes_secret_v1" "cloudraw" {
  metadata {
    name        = "cloudraw-secret" # 생성할 secret 이름
    namespace   = kubernetes_namespace_v1.cloudraw.metadata[0].name # secret을 생성할 namespace 이름
    annotations = {}
    labels      = {}
  }

  type = "kubernetes.io/dockerconfigjson" # secret type 
  data = {
    ".dockerconfigjson" = jsonencode(
      {
      "auths" = {
        "<repository url>" = {
            "auth" = base64encode(format("%s:%s", "<registry username>", "<registry password>"))
          }
        }
      }
    )
  }
}

 

위와 같이 구성한 Terraform 템플릿을 Plan, Apply과정을 거쳐 생성해보겠습니다.

- plan 결과 4개의 오브젝트가 추가되는 것임을 확인할 수 있습니다.

 

- apply 결과 4개의 오브젝트가 생성된 것을 확인 할 수 있습니다.

 

- 생성된 각 오브젝트는 terraform.tfstate파일 및 kubectl describe 명령을 통해 상세내용을 확인 할 수 있습니다.

 ※ 위에서 작성한 오브젝트는 terraform destroy 명령을 사용하여 제거할 수 있습니다.

 

 이번 시간에는 Terraform 을 활용하여 Kubernetes를 연결하고, 기본 오브젝트를 생성해 보았습니다. 

다음 시간에는 Volume과 관련된 오브젝트 및 Volume Mount하는 방법에 대해 다뤄보겠습니다.

 

감사합니다.

 

 


 

    

 

Cloudraw는 쉽게 클라우드 인프라를 그리고 사용할 수 있는 서비스를 제공하기 위해 노력하고 있습니다.

 

클라우드가 있는 곳 어디든 Cloudraw가 함께합니다.

 

📨 help@cloudraw.kr