링크세상 링크모음
링크세상 링크모음 링크 애니 웹툰 링크 드라마 영화 링크 세상의모든링크

Terraform + LXD를 사용한 로컬 개발 환경

빅 데이터 솔루션 설계자이자 InfraOps로서 소프트웨어를 설치하고 테스트하려면 개발 환경이 필요합니다. 구성 가능하고 유연하며 성능이 뛰어나야 합니다. 분산 시스템으로 작업할 때 이 사용 사례에 가장 적합한 설정은 여러 Linux 인스턴스의 로컬 가상화 클러스터입니다.

몇 년 동안 저는 HashiCorp의 Vagrant를 사용하여 libvirt/KVM 인스턴스를 관리해 왔습니다. 이것은 잘 작동하지만 최근에 나에게 더 잘 맞는 또 다른 설정을 경험했습니다. 인스턴스를 관리하는 LXD와 LXD를 운영하는 Terraform(또 다른 HashiCorp 도구)입니다. 이 기사에서는 후자의 장점이 무엇인지, 그러한 환경을 설정하는 방법에 대해 설명합니다.

용어 사전

방랑자와 Terraform

Vagrant를 사용하면 사용자는 가볍고 재현 가능하며 이식 가능한 개발 환경을 만들고 구성할 수 있습니다. 주로 가상 머신을 로컬로 프로비저닝하는 데 사용됩니다.

Terraform은 거의 모든 클라우드에서 리소스를 프로비저닝할 수 있는 널리 사용되는 코드형 인프라 도구입니다. 퍼블릭 클라우드(AWS, Azure, GCP)부터 프라이빗 자체 호스팅 인프라(OpenStack, Kubernetes, LXD)까지 다양한 공급자를 지원합니다. InfraOps 팀은 Terraform을 통해 GitOps 모범 사례를 적용하여 인프라를 관리합니다.

Linux 가상화/컨테이너화

다음은 이 기사에서 사용하고 혼잡한 Linux 가상화/컨테이너화 생태계를 구성하는 다양한 도구(및 약어)에 대한 간략한 검토입니다.

Vagrant가 KVM 호스트를 운영하게 하려면 vagrant-libvirt 공급자를 사용하면 됩니다. Vagrant를 사용하여 libvirt/KVM을 설정하는 방법은 Archlinux의 Vagrant용 KVM 시스템을 참조하세요.

왜 Terraform인가?

LXD는 CLI에서 다음과 같이 사용됩니다. lxc 리소스(컨테이너 및 VM, 네트워크, 스토리지 풀, 인스턴스 프로필)를 관리하는 명령입니다. 명령 기반 도구이기 때문에 본질적으로 Git 친화적이지 않습니다.

다행히 LXD를 관리하는 Terraform 공급자인 terraform-provider-lxd가 있습니다. 이를 통해 애플리케이션 코드와 함께 LXD 인프라 구성의 버전 관리가 가능합니다.

메모: LXD를 운영하는 또 다른 도구는 Canonical의 Juju일 수 있지만 배우기가 좀 더 복잡해 보입니다.

Terraform + LXD를 선택해야 하는 이유 Vagrant + libvirt/KVM에 비해 장점

인스턴스의 실시간 크기 조정

Linux 컨테이너는 VM보다 유연성이 뛰어나 재부팅 없이 인스턴스 크기를 조정할 수 있습니다. 이것은 매우 편리한 기능입니다.

개발부터 생산까지 통합 툴링

LXD는 여러 호스트에 설치되어 자체 호스팅 클라우드의 기본 계층으로 사용할 수 있는 클러스터를 만들 수 있습니다. 따라서 Terraform + LXD 커플을 사용하여 로컬, 통합 및 프로덕션 환경을 관리할 수 있습니다. 이를 통해 인프라 구성을 테스트하고 배포하는 것이 훨씬 쉬워졌습니다.

Ansible의 LXD 지원

로컬 인스턴스에 소프트웨어를 설치하고 구성하기 위해 Ansible을 자주 사용합니다. 대상 호스트에 연결하기 위해 Ansible에 사용할 수 있는 여러 연결 플러그인이 있으며, 주요 플러그인은 다음과 같습니다. ssh.

LXC 인스턴스를 프로비저닝할 때 표준을 사용할 수 있습니다. ssh 플러그인뿐만 아니라 네이티브 LXC 플러그인: lxc (LXC Python 라이브러리를 사용함) 또는 lxd (LXC CLI를 사용함) 이는 다음 두 가지 이유로 유익합니다.

  • 보안을 위해 OpenSSH 서버를 시작하고 인스턴스에서 SSH 포트를 열 필요가 없습니다.
  • Ansible의 SSH 키를 관리할 필요가 없으므로 단순화를 위해

구성 변경 미리보기

Terraform의 주요 기능 중 하나는 명령이 적용될 변경 사항을 미리 볼 수 있는 기능입니다. 이렇게 하면 원치 않는 구성 배포 및 명령 오류를 방지할 수 있습니다.

LXD 인스턴스 프로파일의 크기 조정 예:

$ terraform plan
...
Terraform will perform the following actions:

  
  ~ resource "lxd_profile" "tdp_profiles" 
      ~ config = 
          ~ "limits.cpu"    = "1" -> "2"
          ~ "limits.memory" = "1GiB" -> "2GiB"
        
        id     = "tdp_edge"
        name   = "tdp_edge"
    

Plan: 0 to add, 1 to change, 0 to destroy.

구성 가독성 및 모듈성

Terraform 언어는 선언적 언어입니다. 목표를 달성하기 위한 단계보다는 의도된 목표를 설명합니다. 따라서 Vagrant 파일에 사용되는 Ruby 언어보다 더 읽기 쉽습니다. 또한 Terraform은 현재 디렉터리의 모든 파일을 구문 분석하고 입력 및 출력이 있는 모듈을 정의할 수 있으므로 구성을 매우 쉽게 분할하여 유지 관리성을 높일 수 있습니다.


$ ls -1 | grep -P '.tf(vars)?$'
local.auto.tfvars
main.tf
outputs.tf
provider.tf
terraform.tfvars
variables.tf

성능 향상

Terraform + LXD를 사용하면 항상 즐거운 로컬 개발 환경에서 일상적인 작업 속도가 빨라집니다.

다음은 다음 사양으로 로컬 개발 클러스터를 운영할 때의 성능 벤치마크입니다.

  • 호스트 OS: 우분투 20.04
  • 게스트 인스턴스 수: 7
  • 할당된 리소스: 24GiB RAM 및 24 vCPU
미터법 방랑자 + libvirt/KVM 테라폼 + LXD 성능 향상
클러스터 생성(초) 56.5 51 1.1배 더 빨라짐
클러스터 시작(초) 36.5 6 6배 더 빨라짐
클러스터 종료(초) 46 13.5 3.4배 더 빨라짐
클러스터 삭제(초) 9 17 2배 느림

최소 Terraform + LXD 환경 설정

이제 최소한의 Terraform + LXD 환경을 설정해 보겠습니다.

전제조건

컴퓨터에는 다음이 필요합니다.

  • LXD(설치 참조)
  • Terraform >= 0.13(Terraform 설치 참조)
  • Linux cgroup v2(Rocky 8과 같은 최신 Linux 컨테이너 실행용)
  • 5GB RAM 사용 가능

또한 다음에서 작업할 디렉터리를 만듭니다.

mkdir terraform-lxd-xs
cd terraform-lxd-xs

리눅스 c그룹 v2

호스트가 cgroup v2를 사용하는지 확인하려면 다음을 실행하세요.

stat -fc %T /sys/fs/cgroup

최근 배포판은 기본적으로 cgroup v2를 사용하지만(여기 목록 확인) 이 기능은 Linux 커널 >= 5.2(예: Ubuntu 20.04)를 실행하는 모든 호스트에서 사용할 수 있습니다. 이를 활성화하려면 cgroup v2 활성화를 참조하십시오.

Terraform 제공업체

우리는 terraform-lxd/lxd LXD 리소스를 관리하는 Terraform 제공업체입니다.

만들다 provider.tf:

terraform 
  required_providers 
    lxd = 
      source  = "terraform-lxd/lxd"
      version = "1.7.1"
    
  


provider "lxd" 
  generate_client_certificates = true
  accept_remote_certificate    = true

변수 정의

사용자가 입력 변수를 통해 Terraform 환경을 구성할 수 있도록 하는 것이 좋습니다. 예상되는 유형을 선언하여 변수 정확성을 강화합니다.

만들다 variables.tf:

variable "xs_storage_pool" 
  type = object(
    name   = string
    source = string
  )


variable "xs_network" 
  type = object(
    ipv4 = object(
      address = string
    )
  )


variable "xs_profiles" 
  type = list(object(
    name = string
    limits = object(
      cpu    = number
      memory = string
    )
  ))


variable "xs_image" 
  type    = string
  default = "images:rocky/8"


variable "xs_containers" 
  type = list(object(
    name    = string
    profile = string
    ip      = string
  ))

다음 변수가 정의됩니다.

  • xs_storage_pool: 컨테이너의 디스크를 저장하는 LXD 스토리지 풀
  • xs_network: 공유 네트워크 내에서 통신하기 위해 컨테이너가 사용하는 LXD IPv4 네트워크
  • xs_profiles: 컨테이너용으로 생성된 LXD 프로필입니다. 프로필을 사용하면 모든 컨테이너에 적용할 수 있는 속성 집합을 정의할 수 있습니다.
  • xs_image: LXD 이미지. 이는 기본적으로 컨테이너가 실행되는 OS를 지정합니다.
  • xs_containers: 생성할 LXD 인스턴스입니다.

기본

기본 Terraform 파일은 변수를 통해 구성된 모든 리소스를 정의합니다. 이 파일은 프로젝트를 처음 구현한 후 개발자가 자주 수정하지 않습니다.

만들다 main.tf:


resource "lxd_storage_pool" "xs_storage_pool" 
  name = var.xs_storage_pool.name
  driver = "dir"
  config = 
    source = "$path.cwd/$path.module/$var.xs_storage_pool.source"
  



resource "lxd_network" "xs_network" 
  name = "xsbr0"

  config = 
    "ipv4.address" = var.xs_network.ipv4.address
    "ipv4.nat"     = "true"
    "ipv6.address" = "none"
  



resource "lxd_profile" "xs_profiles" 
  depends_on = [
    lxd_storage_pool.xs_storage_pool
  ]

  for_each = 
    for index, profile in var.xs_profiles :
    profile.name => profile.limits
  

  name = each.key

  config = 
    "boot.autostart" = false
    "limits.cpu"    = each.value.cpu
    "limits.memory" = each.value.memory
  

  device 
    type = "disk"
    name = "root"

    properties = 
      pool = var.xs_storage_pool.name
      path = "/"
    
  



resource "lxd_container" "xs_containers" 
  depends_on = [
    lxd_network.xs_network,
    lxd_profile.xs_profiles
  ]

  for_each = 
    for index, container in var.xs_containers :
    container.name => container
  

  name  = each.key
  image = var.xs_image
  profiles = [
    each.value.profile
  ]

  device 
    name = "eth0"
    type = "nic"
    properties = 
      network        = lxd_network.xs_network.name
      "ipv4.address" = "$each.value.ip"
    
  

Terraform에서는 다음 리소스를 생성합니다.

  • lxd_network.xs_network: 모든 인스턴스의 네트워크
  • lxd_profile.xs_profiles: 사용자가 정의할 수 있는 여러 프로필
  • lxd_container.xs_containers: 인스턴스 정의(프로파일 적용 및 네트워크 장치 연결 포함)

변수 파일

마지막으로 우리 환경에 특정한 변수를 Terraform에 제공합니다. 우리는 auto.tfvars 다음과 같은 경우 자동으로 변수를 로드하는 확장 terraform 실행됩니다.

만들다 local.auto.tfvars:

xs_storage_pool = 
  name = "xs_storage_pool"
  source = "lxd-xs-pool"


xs_network = 
  ipv4 =  address = "192.168.42.1/24" 


xs_profiles = [
  
    name = "xs_master"
    limits = 
      cpu    = 1
      memory = "1GiB"
    
  ,
  
    name = "xs_worker"
    limits = 
      cpu    = 2
      memory = "2GiB"
    
  
]

xs_image = "images:rockylinux/8"

xs_containers = [
  
    name    = "xs-master-01"
    profile = "xs_master"
    ip      = "192.168.42.11"
  ,
  
    name    = "xs-master-02"
    profile = "xs_master"
    ip      = "192.168.42.12"
  ,
  
    name    = "xs-worker-01"
    profile = "xs_worker"
    ip      = "192.168.42.21"
  ,
  
    name    = "xs-worker-02"
    profile = "xs_worker"
    ip      = "192.168.42.22"
  ,
  
    name    = "xs-worker-03"
    profile = "xs_worker"
    ip      = "192.168.42.23"
  
]

환경 프로비저닝

이제 환경을 프로비저닝하는 데 필요한 모든 파일이 준비되었습니다.


terraform init


mkdir lxd-xs-pool


terraform apply

리소스가 생성되면 모든 것이 제대로 작동하는지 확인할 수 있습니다.


lxc network list
lxc profile list
lxc list


lxc shell xs-master-01

그리고 거기 있어요!

메모: 환경을 파괴하려면: terraform destroy

더 발전된 예

다음을 사용하여 고급 설정을 보려면 tdp-lxd를 살펴볼 수 있습니다.

  • 프로필 더보기
  • 파일 템플릿(Ansible 인벤토리용)
  • 출력 정의

결론

Terraform과 LXD의 결합은 경쟁사(즉, Vagrant)에 비해 몇 가지 장점이 있는 로컬 개발 환경을 관리하는 새로운 방법을 제공합니다. 이런 종류의 환경을 자주 부트스트래핑하는 경우 한 번 시도해 보는 것이 좋습니다!