Study_note
[3주차] T013 테라폼 스터디 본문
조건문과 함수
- 테라폼에서 조건문은 3항 연산자 형태를 갖는다
<조건 정의> ? <옳은 경우> : <틀린 경우>
var.a != "" ? var.a : "default-a"
아래와 같이 bool 값의 변수 값을 생성
variable "enable_autoscaling" {
description = "If set to true, enable auto scaling"
type = bool
}
조건문 구문은 아래와 같다
count = <condition> ? <true_val> : <false_val> # 컨디션의 bool 값의 변수 넣는다
다음 count 매개변수 조건문 추가
resource "aws_autoscaling_schedule" "scale_in_at_night" {
count = var.enable_autoscaling ? 1 : 0
파일에서 bool 입력 변수 값이 true 즉 1 값이고 false는 0값으로 지정했기 때문에
입력 값에 따라 생성된다.
-----------------------------------
하지만 bool 값이 문자열 등의 더 복잡한 비교의 결과인 경우 아래와 같다.
아래에 bool 값이 아닌 문자열 입력 변수가 있을때
variable "instance_type" {
description = "The type of EC2 Instances to run (e.g. t2.micro)"
type = string
}
아래와 같이 format 함수를 사용하여 var.instance_type에서 첫 번쨰 문자만 추출하여
해당 문자가 "t"일 경우 count를 1로 설정하고 "t"가 아닐 경우 count가 0이 되어 생성되지 않는다.
resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" {
count = format("%.1s", var.instance_type) == "t" ? 1 : 0
-----------------------------------
조금 더 효율적으로 사용하면 if-else 문을 생성할수 있다.
아래와 같이 t계열이면 low_cpu_credit_balance가 생성되고 t가 아니라면 high_cpu_credit_balance 생성
resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" {
count = format("%.1s", var.instance_type) == "t" ? 1 : 0
[config....]
resource "aws_cloudwatch_metric_alarm" "high_cpu_credit_balance" {
count = format("%.1s", var.instance_type) == "t" ? 0 : 1
[config....]
key => upper(value)
if key != "Name"
}
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
Provisioner
local-exec / remote-exec
local-exec : 로컬에서 실행하는 프로비저너로 여기서 로컬은 terraform apply를 실행하는 현재 머신을 의미한다.
즉 terraform이 실행되는 환경에서 수행할 커맨드를 정의하며 아래와 같이 local-exec 값이 실행 된다.
주로 로컬에 스크립트나 프로그램을 실행하거나 할때 사용한다.
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo ${self.private_ip} >> private_ips.txt"
}
}
---
resource "null_resource" "example1" {
provisioner "local-exec" {
command = <<EOF
echo Hello!! > file.txt
echo $ENV >> file.txt
EOF
interpreter = [ "bash" , "-c" ]
working_dir = "/tmp"
environment = {
ENV = "world!!"
}
}
}
remote-exec : 원격 리소스가 생성 된 스크립트를 호출합니다.
다음 인수가 지원됩니다.
- inline- 이것은 명령 문자열의 목록입니다. 셸을 첫 번째 명령으로 지정하지 않는 한 제공자는 기본 셸을 사용합니다 #!/bin/bash. script또는 와 함께 제공할 수 없습니다
- script- 이것은 원격 리소스에 복사된 다음 실행될 로컬 스크립트에 대한 경로(상대 또는 절대)입니다.
- scripts - 이것은 원격 리소스에 복사된 다음 실행될 로컬 스크립트에 대한 경로(상대 또는 절대) 목록입니다.
resource "aws_instance" "web" {
# ...
# Establishes connection to be used by all
# generic remote provisioners (i.e. file/remote-exec)
connection {
type = "ssh"
user = "root"
password = var.root_password
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"puppet apply",
"consul join ${aws_instance.web.private_ip}",
]
}
}
---
resource "aws_instance" "web" {
# ...
# Establishes connection to be used by all
# generic remote provisioners (i.e. file/remote-exec)
connection {
type = "ssh"
user = "root"
password = var.root_password
host = self.public_ip
}
provisioner "file" {
source = "script.sh"
destination = "/tmp/script.sh"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/script.sh",
"/tmp/script.sh args",
]
}
}
위와 같이 원격에 접속해서 실행하려면 connection을 지정해야 한다.
connection은 resource 아래 선언할 수 도있고, provisioner 아래 선언할 수도 있는데 resource 아래 선언하면 해당 리솟스의 모든 프로비저너가 선언한 커넥션을 사용하게 된다.
(이러한 프로비정닝 도구들은 최후싀 수단으로 사용하는것을 권장한다.)
Provider
테라폼이 대상과의 상호작용을 할 수 있도록 하는 것이 프로바이더이며 프로바이더가 제공하는 API를 호출해 상호작용을 한다
아래와 같이 aws 뿐만 아니라 kubernetes, helm, kubectl 등 사용할 수 있으면
실제로 현 회사에서는 많은 프로바이더를 사용하고 있다.
provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1beta1"
command = "aws"
# This requires the awscli to be installed locally where Terraform is executed
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}
provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1beta1"
command = "aws"
# This requires the awscli to be installed locally where Terraform is executed
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}
}
provider "kubectl" {
apply_retry_count = 5
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
load_config_file = false
exec {
api_version = "client.authentication.k8s.io/v1beta1"
command = "aws"
# This requires the awscli to be installed locally where Terraform is executed
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}
실제로 카펜터 모듈에 테라폼 코드를 보면 여러 프로바이더를 사용했다.
아래와 같이 helm, kubecrtl
resource "helm_release" "karpenter" {
namespace = "karpenter"
create_namespace = true
name = "karpenter"
repository = "oci://public.ecr.aws/karpenter"
repository_username = data.aws_ecrpublic_authorization_token.token.user_name
repository_password = data.aws_ecrpublic_authorization_token.token.password
chart = "karpenter"
version = "v0.21.1"
set {
name = "settings.aws.clusterName"
value = module.eks.cluster_name
}
set {
name = "settings.aws.clusterEndpoint"
value = module.eks.cluster_endpoint
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = module.karpenter.irsa_arn
}
set {
name = "settings.aws.defaultInstanceProfile"
value = module.karpenter.instance_profile_name
}
set {
name = "settings.aws.interruptionQueueName"
value = module.karpenter.queue_name
}
}
---
resource "kubectl_manifest" "karpenter_provisioner" {
yaml_body = <<-YAML
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: default
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
limits:
resources:
cpu: 1000
providerRef:
name: default
ttlSecondsAfterEmpty: 30
YAML
Comments