Terraform Provider
지금까지 기본적인 테라폼 명령어를 살펴보았으니,
기본 테라폼 코드를 살펴보고 terraform apply를 통해 리소스를 하나씩 생성해봅시다.
우선, 테라폼에서 가장 먼저 작성되어야 하는 부분 중에 하나인 provider에 대해서 살펴봅시다.
terraform provider는 테라폼이 특정 인프라 혹은 특정 클라우드의 리소스를 관리할 수 있도록 하는
일종의 Plugin으로 볼 수 있습니다. 뭔가 복잡한 얘기같지만 좀 더 쉽게 설명해보겠습니다.
테라폼으로 코드를 짜서 클라우드의 인프라를 만들 수 있다고 했죠?
그러면 내가 이 테라폼 코드를 실행하면 어떤 클라우드의 리소스를 만들지 알아야 하는데,
그걸 결정해주는 것이 바로 provider라고 보면 됩니다.
즉, provider가 AWS라면 terraform init에서 AWS 리소스 생성과 관련된
모듈을 미리 다운로드를 받아서 준비하게 되고
아하! 이 테라폼 코드를 실행시켜서 생기는 리소스는 AWS(혹은 Azure나 GCP)에 있는 리소스구나!
하고 알 수 있습니다.
(클라우드가 아닌 kubernetes 등의 다른 인프라도 provider로 설정될 수 있습니다.)
그러면 3대 클라우드의 provider 코드를 각각 어떻게 설정하는지 한번 살펴보겠습니다.
가장 먼저 AWS입니다.
AWS의 provider는 다음과 같이 설정할 수 있습니다.
provider "aws" {
region = "us-west-2"
access_key = "YOUR_ACCESS_KEY"
secret_key = "YOUR_SECRET_KEY"
}
여기서 access_key와 secret_key는 AWS IAM User 등이 인증을 할 때 자격을 증명하기 위해 필요한 키입니다.
이렇게 키를 인증함으로써 특정 User의 profile을 사용하여 해당 User가 가진 권한으로 테라폼을 실행할 수 있습니다.
좀 더 구체적으로 실제 테라폼 코드를 실행하여 리소스를 생성하는 과정을 생각해보면
Access Key와 Secret Key를 발급받은 User가 terraform 코드를 실행하여 AWS Lambda를 만들려고 할 때,
User가 Lambda를 생성할 수 있는 아래와 같은 IAM policy의 권한을 가지고 있어야 가능하고,
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:UpdateFunctionCode",
"lambda:PublishVersion",
"lambda:AddPermission",
"lambda:GetFunction",
"lambda:ListFunctions",
"lambda:ListTags",
"cloudwatch:PutMetricData",
"cloudwatch:GetMetricData",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
만약 권한이 없다면 테라폼을 실행하더라도
다른 console이나 AWS CLI로 리소스 생성을 시도할 때처럼 권한 부족 이슈가 생긴다는 의미입니다.
이렇게 직접 access key와 secret key를 입력하여 User로 자격증명을 해도 되지만,
IAM Role을 Assume하는 방식으로 자격증명을 할 수도 있습니다.
물론 이 경우에는 해당 role을 assume할 수 있는 자격 증명이 선행되어야 합니다. (아니 그러면 결국 똑같네;;;)
(IAM에 관련한 내용은 링크를 참고하세요)
IAM assume role 방식으로 provider를 작성하면 다음과 같습니다.
provider "aws" {
assume_role {
role_arn = "arn:aws:iam::123456789012:role/ROLE_NAME"
session_name = "SESSION_NAME"
external_id = "EXTERNAL_ID"
}
}
그 밖에도 credntial 파일이나 토큰 발급을 통한 자격증명도 가능하고,
cloud에서 제공하는 k8s cluster의 service account와 role binding을 통한 자격 증명 등의 방법도 있습니다.
(가장 쉬운건 무지성 access key와 secret key를 넣는 방법이지만 키가 노출되어 위험하고 키를 관리해야하는 단점이 있습니다.)
그러면 다른 클라우드도 살펴봅시다.
Azure의 provider는 어떻게 설정하는지 살펴볼까요?
Azure의 경우 좀 특이하게 2개의 provider를 제공하는 방식을 채택하고 있습니다. (하이브리드 두개의 심장)
하나는 azuread이고 다른 하나는 azurerm인데요.
간단하게 생각하면 azuread는 인증과 관련된 리소스들을 제공하는 provider이고,
azurerm은 인증 외에 azure에서 제공하는 다른 리소스들을 제공하는 provider라고 생각하면 됩니다.
에를 들면 Azure에는 인증과 관련된 Service Principal이라는 리소스가 있는데요.
해당 Service Principal을 생성하는 테라폼 코드를 보면
다음과 같이 앞에 azuread라고 prefix가 붙은걸 확인할 수 있습니다.
resource "azuread_service_principal" "example" {
application_id = azuread_application.example.application_id
app_role_assignment_required = false
owners = [data.azuread_client_config.current.object_id]
feature_tags {
enterprise = true
gallery = true
}
}
반면에, 인증과 관련이 없는 Azure의 가상컴퓨팅 서비스인 VM을 생성하는 테라폼 코드를 보면
다음과 같이 앞에 azurerm이라는 prefix가 붙은걸 확인할 수 있죠.
resource "azurerm_linux_virtual_machine" "example" {
name = "example-machine"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
size = "Standard_F2"
admin_username = "adminuser"
network_interface_ids = [
azurerm_network_interface.example.id,
]
admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub")
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-focal"
sku = "20_04-lts"
version = "latest"
}
}
그러면 이제 azuread와 azurerm의 provider를 살펴봅시다.
provider "azurerm" {
features {}
}
provider "azuread" {}
왜 쓰다 말았죠?
하실 수도 있지만 놀랍게도 이게 다입니다.
하지만 아무것도 없이 인증이 되지는 않겠죠?
Azure CLI인 az login 명령어를 통해 azure portal에서 웹으로 인증하면
그 이후에는 azure provider를 이용할 수 있습니다.
하지만 테라폼을 사용하기 위해서 매번 az login을 하는 것은 비효율적이겠죠?
Azure도 AWS의 access key, secret key처럼 아래와 같이 구성하여
secret을 이용하여 인증하는 방법이 있습니다.
provider "azurerm" {
subscription_id = "<subscription_id>"
client_id = "<client_id>"
client_secret = "<client_secret>"
tenant_id = "<tenant_id>"
features {}
}
provider "azuread" {
client_id = "<client_id>"
client_secret = "<client_secret>"
tenant_id = "<tenant_id>"
}
그 밖에도 토큰 인증방식 등도 가능합니다.
(이처럼 인증 방식 지원은 클라우드끼리 비슷합니다.)
마지막으로 GCP를 살펴볼까요?
provider "google" {
project = "my-project-id"
region = "us-central1"
}
GCP도 Azure와 유사하게 gcloud auth login 명령어를 통해 인증을 완료하면
gcloud config set project <PROJECT ID>로 설정된 config project의 ID만
my -project-id에 넣어서 인증을 완료할 수 있습니다.
혹은 GCP의 App이나 VM의 인증수단으로 쓰일 수 있는 Service Account를 생성한 후,
인증을 위한 JSON key file을 다운로드 받아서 해당 파일의 경로를 아래와 같이 넣어 인증하는 방식도 있습니다.
provider "google" {
credentials = file("/path/to/the/json/keyfile.json")
project = "your_project_id"
region = "us-central1"
}
이상으로 3대 클라우드의 terraform provider 설정에 대해서 알아보았습니다.
다음은 terraform state 파일을 저장하는 위치를 설정하기 위한 terraform backend에 대해서 알아보겠습니다.