멀티 클라우드
- 멀티 클라우드는 2개 이상의 클라우드 플랫폼에서 하나의 서비스를 운영하는 것
- 한가지 플랫폼에 Lock-In 되는 것을 방지할 수 있다.
- 여러 플랫폼의 경쟁력있는 서비스를 골라서 사용할 수 있다.
- 정말 만약의 사태에 한쪽 클라우드 플랫폼 전체적인 장애 발생시 더 높은 가용성을 제공할 수 있다.
시작 전
- AWS는 많이 사용해보았지만 Azure와 Gcp는 이번이 처음 사용이다.
- 개인 도메인이 없다면 Freenom [프리놈]과같은 사이트 통해 무료로 도메인을 대여할 수 있다고 한다.
GCP 회원가입 안 넘어가질 때
- 구글 로그인 된 상태로 https://console.cloud.google.com/ 해당 주소로 접속하면 아래와 같은 화면이 나온다.
- 다시 콘솔에서 무료로 사용하기를 누르면 약관동의를 체크하고 넘어갈 수 있다.
시행착오 : 이번 실습을 진행하면서 겪은 시행착오와 해결방법등을 적어두었다. 본문 내용들은 해결이 완료된 후 수정된 내용들이다.
1. Azure CLI 환경 구성 - 해결
- 아래 코드 실행
apt update apt install azure-cli
- WSL2에선
az login
명령이 안된다. →az login --device-code
→https://microsoft.com/devicelogin
으로 접속해서 명령 결과로 나온 코드 입력하면 로긴된다.로그인 결과 [ { "cloudName": "AzureCloud", "id": "a573addd-xxxx-xxxx-xxxx-xxxxdataxxxx", "isDefault": true, "name": "무료 체험", "state": "Enabled", "tenantId": "4c6c5d14-xxxx-xxxx-xxxx-xxxxdataxxxx", "user": { "name": "wwdcr2@naver.com", "type": "user" } } ]
az account get-access-token
명령으로 토큰 확인root@jwjung:/web_infra# az account get-access-token { "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC80YzZjNWQxNC1kN2YyLTRjZjgtOWU0Zi0zY2MwYmNjMjlmNmIvIiwiaWF0IjoxNjEyMjU1NTE4LCJuYmYiOjE2MTIyNTU1MTgsImV4cCI6MTYxMjI1OTQxOCwiYWNyIjoiMSIsImFpbyI6IkFVUUF1LzhUQUFBQUo3c3JyaGhYdDFReWVkV05EYUJid0xZdWJwdytBMUlJTUo3NE55bDhvNU91Z0FXandjcjA1YnNlOTR2SGwxck5qM21tM3o2ajlUT3BSMTNEL0ZLeHdnPT0iLCJhbHRzZWNpZCI6IjE6bGl2ZS5jb206MDAwMzAwMDAwQ0JGNzI0NCIsImFtciI6WyJwd2QiXSwiYXBwaWQiOiIwNGIwNzc5NS04ZGRiLTQ2MWEtYmJlZS0wMmY5ZTFiZjdiNDYiLCJhcHBpZGFjciI6IjAiLCJlbWFpbCI6Ind3ZGNyMkBuYXZlci5jb20iLCJmYW1pbHlfbmFtZSI6Ikppd29uIiwiZ2l2ZW5fbmFtZSI6Ikp1bmciLCJncm91cHMiOlsiNjFmMGMxZTYtY2Q5ZS00MTdkLThlMGUtNzViOTIyMjg1N2E5Il0sImlkcCI6ImxpdmUuY29tIiwiaXBhZGRyIjoiMTIxLjEzMy4zNS4yMDQiLCJuYW1lIjoiSml3b25KdW5nIiwib2lkIjoiMWUxY2YwNDgtNTUxMi00MDNkLWJjYjItOTBhOWY0NDRmOTc5IiwicHVpZCI6IjEwMDMyMDAwRjM4RTQ4QTEiLCJyaCI6IjAuQUFBQUZGMXNUUExYLUV5ZVR6ekF2TUtmYTVWM3NBVGJqUnBHdS00Qy1lR19lMFp4QUxjLiIsInNjcCI6InVzZXJfaW1wZXJzb25hdGlvbiIsInN1YiI6ImFDak90eHE5MmN6ZnB3c29IQnlkbEtGTXllSGdKaG5XZjZabHFFXzdGYUUiLCJ0aWQiOiI0YzZjNWQxNC1kN2YyLTRjZjgtOWU0Zi0zY2MwYmNjMjlmNmIiLCJ1bmlxdWVfbmFtZSI6ImxpdmUuY29tI3d3ZGNyMkBuYXZlci5jb20iLCJ1dGkiOiJ1V29KeHB3Mm9VZVlya3RUemxBYUFBIiwidmVyIjoiMS4wIiwid2lkcyI6WyI2MmU5MDM5NC02OWY1LTQyMzctOTE5MC0wMTIxNzcxNDVlMTAiLCJiNzlmYmY0ZC0zZWY5LTQ2ODktODE0My03NmIxOTRlODU1MDkiXSwieG1zX3RjZHQiOjE2MDQ0MjExNDZ9.aoLFCYI0SInSMNiiYqWMs8xDwCySYyVBs0nrEaceaXSc8WICqeMmzAe_Kg_CS1Me3PQKaIzYphP08_kHgQj07sf4cVyO6mP4FJ9n10ft50prgQEOysEXtHZKBSeX-KlM3UEZtAh-EpVywLx7EUb9E0Qp3VJPHpuHiR7yhtv1sh_kwEIDAWsozvmVcXeMvB4wTPJgGBWsF-uqxlbsVLnsNFBgOBJq-yqweGMs9EvQL9BQS2ee1onCVDmE4IGtPsDXRlCBmtTMGvVx1Z-reEM_Vxk1P5Ig2r_D3zIX269scL6ffHOrThaza_dSMT5_LzN1n_WfASO1FKIMhJZkJiN8DA", "expiresOn": "2021-02-02 18:50:14.764144", "subscription": "a573addd-d0a0-4748-a03b-81c5b067d960", "tenant": "4c6c5d14-d7f2-4cf8-9e4f-3cc0bcc29f6b", "tokenType": "Bearer" }
- 아래 코드 실행
2.
terraform apply
결과 Error - 해결- apply 에러 내용 + Cloudflare를 통해 Azure만 접속되는 상황
AWS --- Error: Error associating EIP: Gateway.NotAttached: Network vpc-078cf7dd35449156f is not attached to any internet gateway status code: 400, request id: edab0fd5-9836-4082-9d1c-2476323bbc91 Error: error creating route table: InvalidVpcID.NotFound: The vpc ID 'aws_vpc.aws-vpc.id' does not exist status code: 400, request id: 53a2ff53-3c40-451a-9fc1-a78dc7647dd4 Error: error attaching EC2 Internet Gateway (igw-0cdd1a757913153fb): Error attaching internet gateway: InvalidVpcID.NotFound: The vpc ID 'aws_vpc.aws-vpc.id' does not exist status code: 400, request id: 2f8aa1dd-38f6-47c4-b8bd-2cd8f0970f51 GCP --- Error: Error creating Address: googleapi: Error 403: Compute Engine API has not been used in project 291777465078 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=291777465078 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry., accessNotConfigured Error: Error creating Network: googleapi: Error 403: Compute Engine API has not been used in project 291777465078 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=291777465078 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry., accessNotConfigured
- AWS :
aws_vpc.aws-vpc.id
변수값에 " " 빼주기 (변수를 문자로인식)
- GCP : 3번에서 해결
- apply 에러 내용 + Cloudflare를 통해 Azure만 접속되는 상황
3. GCP Compute Engine API 문제 - 해결
https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=[프로젝트넘버]
사이트로 이동
- Compute Engine API를 사용하기 → 결제를 허용한 계정이 필요하다.
- 결제 계정 설정 및 Compute Engine API 설치 완료된 후 화면 → 개요 옆에 API 사용 중지로 언제든 API를 차단할 수 있다.
4. GCP로 만든 인스턴스의 UserData가 입력되지 않는 문제 - 해결
- 생성된 인스턴스의 IP로 웹서버 접속불가
- SSH 접속을 허용하고 들어갔을 때 apache2가 설치되지 않음 = UserData 적용 안됨
gcp-main.tf
파일의 코드 변경#metadata_startup_script = data.template_file.metadata_startup_script.rendered # 이코드를 아래와 같이 변경 metadata = { startup-script = <<SCRIPT sudo apt-get update sudo apt update sudo apt install -y apache2 sudo systemctl start apache2 sudo systemctl enable apache2 echo "<h1> MultiCloud Demo Google Cloud </ h1>"| sudo tee /var/www/html/index.html SCRIPT }
4. 로드밸런싱 문제 - 해결
- 프로비저닝 완료 후 웹서버에 접속하면 1개의 서버에만 연결된다.
- 브라우저의 private모드, 기록삭제, 다른브라우저사용 등 다양한 시도를 해봤지만 1개의 서버에만 연결
- 하루종일 찾아보다가 오레곤에 생성한 인스턴스를 시작으로 핸드폰, 다른IP의 PC등 여러환경에서 시도해본 결과 로드밸런싱이 정상적으로 작동한다. 하지만 엔드디바이스의 접속정보를 가지고있는지 한서버에서는 한쪽으로만 라우팅이 되었다.
- 무료버전은 failover를 제공하지 않는다.
- 간단한 멀티클라우드 아키텍처 - 사용자는 도메인에 접속하면 Cloudflare가 각 플랫폼의 인스턴스로 연결 해 준다.
Terraform 환경
- 작업 디렉터리 : WSL2 내부의 /web_infra/.
- Terraform 버전 : v0.13.0 (0.14.5 버전은 실습 에러남) →
terraform 0.13upgrade .
명령으로 업그레이드
- Terraform 버전 변경 :
tfswitch
프로그램 사용버전 변경 안될 때
- 혹시나 실행이 잘 안되는 경우 upgrade v0.13.0 과 v0.14.5 버전을 변경해가면서 사용해보자
- 아래와 같이 tfswitc로 v0.13.0 다운그레이드가 안되는경우 terraform.tfstate 파일을 삭제하자
rm /web_infra/terraform.tfstate*
명령으로 삭제 하면 버전변경 가능!
Cloudflare 가입 및 도메인 추가
1. Cloudflare 가입하기
- Cloudflare의 공식 홈페이지에서 무료 플랜 가입
2. 구매한 도메인의 NS 변경 (가비아 기준)
- 가입 후 다음과 같은 창이 뜨면 뒤로가기를 누른다.
- 2021.02.02 기준 이런 창이 나왔다. 이 이름서버에 맞게 가비아 네임서버 변경해주기
- 변경된 가비아 네임서버정보
- 변경 후 파란박스가 있는 위치에서 변경 확인? 눌러주기
3. 도메인 - Cloudflare 연결 (레코드 추가)
- DNS 탭으로 이동
- 연결 완료 메일을 통한 활성화 완료
4. Page Rule 설정을 통한 실제 페이지에 연결
- Page Rule 탭으로 이동
- Cloudflare는 기본 3개의 Page Rules를 무료로 제공한다.
- 내 블로그에 연결하는 Page Rule 생성 후 저장
- 자동으로 cloudest.tistory.com 으로 Redirecting 되며 도메인 연결이 완료됐다.
- Page Rule은 언제든 On/Off와 삭제 및 수정이 가능하다.
5. API Keys - Cloudflare
- cloudflare Overvier탭의 API항목으로 이동
- 이메일 인증
- API Tokens탭으로 이동후 두개의 Key값을 View를 통해 확인하고 메모해둔다.
AWS에 WEB배포 (Terraform)
1. 공통 변수에 대한 파일 생성 (
common-variables.tf
)common-variables.tf
파일에 아래 내용 추가#Define application name variable "app_name" { type = string description = "Application name" default = "kopicloud" } #Define application environment variable "app_environment" { type = string description = "Application environment" default = "demo" }
2. AWS 변수 선언 및 설정값 추가 (
aws-variables.tf
)aws-variables.tf
파일에 아래 내용 추가#AWS authentication variables variable "aws_access_key" { type = string description = "AWS Access Key" } variable "aws_secret_key" { type = string description = "AWS Secret Key" } variable "aws_key_pair" { type = string description = "AWS Key Pair" } #AWS Region variable "aws_region" { type = string description = "AWS Region for the VPC" default = "ap-northeast-2" } #AWS AZ variable "aws_az" { type = string description = "AWS AZ" default = "ap-northeast-2c" } #VPC CIDR variable "aws_vpc_cidr" { type = string description = "CIDR for the VPC" default = "10.1.0.0/16" } #Subnet CIDR variable "aws_subnet_cidr" { type = string description = "CIDR for the subnet" default = "10.1.1.0/24" }
3. AWS 인증정보 파일 생성 (
terraform.tfvars
)terraform.tfvars
파일에 아래 내용 추가#AWS authentication variables / 미리 생성한 액세스키, 비밀키, Key-pair이름 입력 aws_access_key = "[액세스키]" aws_secret_key = "[비밀키]" aws_key_pair = "[키페어 이름]" #SSH 접속을 하지 않기 때문에 생성한 Key-pair 이름만 알면 된다.
4. EC2에 Apache 설치 및
index.html
구성을 위한 파일 생성 (aws-user-data.sh
)- 이 작업은 부트스트랩 파일을 통한 작업이다.
aws-user-data.sh
파일에 아래 내용 추가#! /bin/bash sudo apt-get update sudo apt-get install -y apache2 sudo systemctl start apache2 sudo systemctl enable apache2 echo "<h1>MultiCloud Demo AWS</h1>" | sudo tee /var/www/html/index.html
5. VPC, 네트워크, EC2 및 보안그룹 구성 파일 생성 (
aws-main.tf
)aws-main.tf
파일 내부에 아래 내용 추가#Initialize the AWS Provider provider "aws" { access_key = var.aws_access_key secret_key = var.aws_secret_key region = var.aws_region } #Create the VPC resource "aws_vpc" "aws-vpc" { cidr_block = var.aws_vpc_cidr enable_dns_hostnames = true enable_dns_support = true tags = { Name = "${var.app_name}-${var.app_environment}-vpc" Environment = var.app_environment } } #Define the subnet resource "aws_subnet" "aws-subnet" { vpc_id = aws_vpc.aws-vpc.id cidr_block = var.aws_subnet_cidr availability_zone = var.aws_az tags = { Name = "${var.app_name}-${var.app_environment}-subnet" Environment = var.app_environment } } #Define the internet gateway resource "aws_internet_gateway" "aws-gw" { vpc_id = aws_vpc.aws-vpc.id tags = { Name = "${var.app_name}-${var.app_environment}-igw" Environment = var.app_environment } } #Define the route table to the internet resource "aws_route_table" "aws-route-table" { vpc_id = aws_vpc.aws-vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.aws-gw.id } tags = { Name = "${var.app_name}-${var.app_environment}-route-table" Environment = var.app_environment } } #Assign the public route table to the subnet resource "aws_route_table_association" "aws-route-table-association"{ subnet_id = aws_subnet.aws-subnet.id route_table_id = aws_route_table.aws-route-table.id } #Define the security group for HTTP web server resource "aws_security_group" "aws-web-sg" { name = "${var.app_name}-${var.app_environment}-web-sg" description = "Allow incoming HTTP connections" vpc_id = aws_vpc.aws-vpc.id ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.app_name}-${var.app_environment}-web-sg" Environment = var.app_environment } } #Get latest Ubuntu 18.04 AMI data "aws_ami" "ubuntu-18_04" { most_recent = true owners = ["099720109477"] filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] } filter { name = "virtualization-type" values = ["hvm"] } } #Create Elastic IP for web server resource "aws_eip" "aws-web-eip" { vpc = true tags = { Name = "${var.app_name}-${var.app_environment}-elastic-ip" Environment = var.app_environment } } #Create EC2 Instances for Web Server resource "aws_instance" "aws-web-server" { ami = data.aws_ami.ubuntu-18_04.id instance_type = "t2.micro" subnet_id = aws_subnet.aws-subnet.id vpc_security_group_ids = [aws_security_group.aws-web-sg.id] associate_public_ip_address = true source_dest_check = false key_name = var.aws_key_pair user_data = file("aws-user-data.sh") tags = { Name = "${var.app_name}-${var.app_environment}-web-server" Environment = var.app_environment } } #Associate Elastic IP to Web Server resource "aws_eip_association" "aws-web-eip-association" { instance_id = aws_instance.aws-web-server.id allocation_id = aws_eip.aws-web-eip.id }
- AWS Terraform 배포 확인됨
Azure에 WEB배포 (Terraform)
1. Azure CLI 환경 구성
- 아래 코드 실행
apt update apt install azure-cli
- WSL2에선
az login
명령이 안된다. →az login --device-code
→https://microsoft.com/devicelogin
으로 접속해서 명령 결과로 나온 코드 입력하면 로긴된다.
az account get-access-token
명령으로 토큰 확인root@jwjung:/web_infra# az account get-access-token { "accessToken": "토큰 값", "expiresOn": "2021-02-02 18:50:14.764144", "subscription": "a573addd-d0a0-4748-a03b-81c5b067d960", "tenant": "테넌트 값", "tokenType": "Bearer" }
- 아래 코드 실행
2. Azure 변수 선언 및 설정값 추가 (
azure-variables.tf
)azure-variables.tf
파일에 아래 내용 추가#Location Resource Group variable "rg_location" { type = string description = "Location of Resource Group" default = "Korea Central" } #VNET CIDR variable "azure_vnet_cidr" { type = string description = "Vnet CIDR" default = "10.2.0.0/16" } #Subnet CIDR variable "azure_subnet_cidr" { type = string description = "Subnet CIDR" default = "10.2.1.0/24" } #Linux VM Admin User variable "linux_admin_user" { type = string description = "Linux VM Admin User" default = "tfadmin" } #Linux VM Admin Password variable "linux_admin_password" { type = string description = "Linux VM Admin Password" default = "S3cr3tP@ssw0rd" } #Linux VM Hostname variable "linux_vm_hostname" { type = string description = "Linux VM Hostname" default = "azwebserver1" } #Ubuntu Linux Publisher used to build VMs variable "ubuntu-linux-publisher" { type = string description = "Ubuntu Linux Publisher used to build VMs" default = "Canonical" } #Ubuntu Linux 18.x SKU used to build VMs variable "ubuntu-linux-18-sku" { type = string description = "Ubuntu Linux Server SKU used to build VMs" default = "18.04-LTS" }
3. VM에 Apache 설치 및
index.html
구성을 위한 파일 생성 (azure-user-data.sh
)azure-user-data.sh
파일에 아래 내용 추가#! /bin/bash sudo apt-get update sudo apt-get install -y apache2 sudo systemctl start apache2 sudo systemctl enable apache2 echo "<h1>MultiCloud Demo Azure</h1>" | sudo tee /var/www/html/index.html
4. Virtual Network, Azure 네트워크, VM 및 보안그룹 구성 (
azure-main.tf
)azure-main.tf
파일에 아래 내용 추가#Configure the Azure Provider provider "azurerm" { environment = "public" features {} } #Create Resource Group resource "azurerm_resource_group" "azure-rg" { name = "${var.app_name}-${var.app_environment}-rg" location = var.rg_location } #Create a virtual network resource "azurerm_virtual_network" "azure-vnet" { name = "${var.app_name}-${var.app_environment}-vnet" resource_group_name = azurerm_resource_group.azure-rg.name location = var.rg_location address_space = [var.azure_vnet_cidr] tags = { environment = var.app_environment } } #Create a subnet resource "azurerm_subnet" "azure-subnet" { name = "${var.app_name}-${var.app_environment}-subnet" resource_group_name = azurerm_resource_group.azure-rg.name virtual_network_name = azurerm_virtual_network.azure-vnet.name address_prefix = var.azure_subnet_cidr } #Create Security Group to access Web Server resource "azurerm_network_security_group" "azure-web-nsg" { name = "${var.app_name}-${var.app_environment}-web-nsg" location = azurerm_resource_group.azure-rg.location resource_group_name = azurerm_resource_group.azure-rg.name security_rule { name = "AllowHTTP" description = "Allow HTTP" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "80" source_address_prefix = "Internet" destination_address_prefix = "*" } tags = { environment = var.app_environment } } #Associate the Web NSG with the subnet resource "azurerm_subnet_network_security_group_association" "azure-web-nsg-association" { subnet_id = azurerm_subnet.azure-subnet.id network_security_group_id = azurerm_network_security_group.azure-web-nsg.id } #Get a Static Public IP resource "azurerm_public_ip" "azure-web-ip" { name = "${var.app_name}-${var.app_environment}-web-ip" location = azurerm_resource_group.azure-rg.location resource_group_name = azurerm_resource_group.azure-rg.name allocation_method = "Static" tags = { environment = var.app_environment } } #Create Network Card for Web Server VM resource "azurerm_network_interface" "azure-web-nic" { name = "${var.app_name}-${var.app_environment}-web-nic" location = azurerm_resource_group.azure-rg.location resource_group_name = azurerm_resource_group.azure-rg.name ip_configuration { name = "internal" subnet_id = azurerm_subnet.azure-subnet.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.azure-web-ip.id } tags = { environment = var.app_environment } } #Create web server vm resource "azurerm_virtual_machine" "azure-web-vm" { name = "${var.app_name}-${var.app_environment}-web-vm" location = azurerm_resource_group.azure-rg.location resource_group_name = azurerm_resource_group.azure-rg.name network_interface_ids = [azurerm_network_interface.azure-web-nic.id] vm_size = "Standard_B1s" delete_os_disk_on_termination = true delete_data_disks_on_termination = true storage_image_reference { publisher = var.ubuntu-linux-publisher offer = var.ubuntu-linux-offer sku = var.ubuntu-linux-18-sku version = "latest" } storage_os_disk { name = "${var.app_name}-${var.app_environment}-web-vm-os-disk" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = "Standard_LRS" } os_profile { computer_name = var.linux_vm_hostname admin_username = var.linux_admin_user admin_password = var.linux_admin_password custom_data = file("azure-user-data.sh") } os_profile_linux_config { disable_password_authentication = false } tags = { environment = var.app_environment } } #Output output "azure-web-server-external-ip" { value = azurerm_public_ip.azure-web-ip.ip_address }
GCP에 WEB배포 (Terraform)
1. GCP 변수 선언 및 설정값 추가 (
gcp-variables.tf
)gcp-variables.tf
파일에 아래 내용 추가#GCP authentication file variable "gcp_auth_file" { type = string description = "GCP authentication file" } #Define GCP project name variable "gcp_project" { type = string description = "GCP project name" } #Define GCP region variable "gcp_region" { type = string description = "GCP region" default = "europe-west1" } #Define GCP zone variable "gcp_zone" { type = string description = "GCP zone" default = "europe-west1-b" } #Define subnet CIDR variable "gcp_subnet_cidr" { type = string description = "Subnet CIDR" default = "10.3.1.0/24" }
2. GCP 인증정보 발급
- 사용자 인증정보 서비스 접속 → 사용자 인증 정보 만들기 클릭
- 서비스 계정 이름 지정 → 완료
- IAM → 서비스 계정 → 키만들기
- JSON 파일로 키 생성 및 저장
- WSL2에서 작업 디렉터리에 cp 명령으로 json파일 복사
3. GCP 인증정보 파일 생성 (
terraform.tfvars
)terraform.tfvars
파일에 아래 내용 추가#GCP authentication variables gcp_project = "your-gcp-project" gcp_auth_file = "your-gcp-auth-file.json"
4. Compute Engine에 Apache 설치 및
index.html
구성을 위한 파일 생성 (gcp-user-data.sh
)gcp-user-data.sh
파일에 아래 내용 추가#! / bin / bash sudo apt-get update sudo apt update sudo apt install -y apache2 sudo systemctl start apache2 sudo systemctl enable apache2 echo "<h1> MultiCloud Demo Google Cloud </ h1>"| sudo tee /var/www/html/index.html
5. VPC, GCP 네트워크, Compute Engine 및 보안그룹 구성 (
gcp-main.tf
)gcp-main.tf
파일에 아래 내용 추가#Setup the GCP provider terraform { required_version = ">= 0.12" } provider "google" { project = var.gcp_project credentials = file(var.gcp_auth_file) region = var.gcp_region zone = var.gcp_zone } #Create VPC resource "google_compute_network" "gcp-vpc" { name = "${var.app_name}-${var.app_environment}-vpc" auto_create_subnetworks = "false" routing_mode = "GLOBAL" } #Create subnet resource "google_compute_subnetwork" "gcp-subnet" { name = "${var.app_name}-${var.app_environment}-subnet" ip_cidr_range = var.gcp_subnet_cidr network = google_compute_network.gcp-vpc.name region = var.gcp_region } #Firewall allow http resource "google_compute_firewall" "gcp-allow-http" { name = "${var.app_name}-${var.app_environment}-fw-allow-http" network = google_compute_network.gcp-vpc.name allow { protocol = "tcp" ports = ["80"] } target_tags = ["http"] } #Create a public ip for web server resource "google_compute_address" "gcp-web-ip" { name = "${var.app_name}-${var.app_environment}-web-ip" project = var.gcp_project region = var.gcp_region } #Define bootstrap file data "template_file" "metadata_startup_script" { template = file("gcp-user-data.sh") } #Create VM for web server resource "google_compute_instance" "gpc-web-server" { name = "${var.app_name}-${var.app_environment}-web-server" machine_type = "f1-micro" zone = var.gcp_zone tags = ["http"] boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-1804-lts" } } #metadata_startup_script = data.template_file.metadata_startup_script.rendered #부트 스트랩으로 넣는 방식이 인식이 안됨 metadata = { startup-script = <<SCRIPT sudo apt-get update sudo apt update sudo apt install -y apache2 sudo systemctl start apache2 sudo systemctl enable apache2 echo "<h1> MultiCloud Demo Google Cloud </ h1>"| sudo tee /var/www/html/index.html SCRIPT } network_interface { network = google_compute_network.gcp-vpc.name subnetwork = google_compute_subnetwork.gcp-subnet.name access_config { nat_ip = google_compute_address.gcp-web-ip.address } } } #Output output "external-ip-gcp-web-server" { value = google_compute_address.gcp-web-ip.address }
Cloudflare
1. Cloudflare 자격 증명 정보 추가 (
terraform.tfvars
)terraform.tfvars
파일에 아래 내용 추가#Cloudflare 인증 변수 cloudflare_email = "[이메일]" cloudflare_api_key = "[api 키]" cloudflare_zone_id = "[zone-id]"
2. Provider를 초기화하고 www 및 Root DNS 레코드를 생성 (
cloudflare-dns.tf
)- 원래는 아래 사진처럼 변수를 통해 사용하는데 변수를 못 읽어와서 직접 값 입력했다.
cloudflare-dns.tf
파일에 아래 내용 추가#Define Cloudflare provider provider "cloudflare" { email = "메일" api_key = "API 키" } #Create www record for Amazon Web Services resource "cloudflare_record" "aws-www" { zone_id = "zone 아이디" name = "www" value = aws_eip.aws-web-eip.public_ip type = "A" proxied = true depends_on = [aws_eip.aws-web-eip] } #Create www record for Azure resource "cloudflare_record" "azure-www" { zone_id = "zone 아이디" name = "www" value = azurerm_public_ip.azure-web-ip.ip_address type = "A" proxied = true depends_on = [azurerm_public_ip.azure-web-ip] } #Create www record for Google Cloud resource "cloudflare_record" "gcp-www" { zone_id = "zone 아이디" name = "www" value = google_compute_address.gcp-web-ip.address type = "A" proxied = true depends_on = [google_compute_address.gcp-web-ip] } #Create root record for Amazon Web Services resource "cloudflare_record" "aws-root" { zone_id = "zone 아이디" name = "@" value = aws_eip.aws-web-eip.public_ip type = "A" proxied = true depends_on = [aws_eip.aws-web-eip] } #Create root record for Azure resource "cloudflare_record" "azure-root" { zone_id = "zone 아이디" name = "@" value = azurerm_public_ip.azure-web-ip.ip_address type = "A" proxied = true depends_on = [azurerm_public_ip.azure-web-ip] } #Create root record for Google Cloud resource "cloudflare_record" "gcp-root" { zone_id = "zone 아이디" name = "@" value = google_compute_address.gcp-web-ip.address type = "A" proxied = true depends_on = [google_compute_address.gcp-web-ip] } #Output AWS output "cloudflare-aws-www-record-id" { value = cloudflare_record.aws-www.id } output "cloudflare-aws-www-record-hostname" { value = cloudflare_record.aws-www.hostname } output "cloudflare-aws-root-record-id" { value = cloudflare_record.aws-root.id } output "cloudflare-aws-root-record-hostname" { value = cloudflare_record.aws-root.hostname } # Output Azure output "cloudflare-azure-www-record-id" { value = cloudflare_record.azure-www.id } output "cloudflare-azure-www-record-hostname" { value = cloudflare_record.azure-www.hostname } output "cloudflare-azure-root-record-id" { value = cloudflare_record.azure-root.id } output "cloudflare-azure-root-record-hostname" { value = cloudflare_record.azure-root.hostname } # Output GCP output "cloudflare-gcp-www-record-id" { value = cloudflare_record.gcp-www.id } output "cloudflare-gcp-www-record-hostname" { value = cloudflare_record.gcp-www.hostname } output "cloudflare-gcp-root-record-id" { value = cloudflare_record.gcp-root.id } output "cloudflare-gcp-root-record-hostname" { value = cloudflare_record.gcp-root.hostname }
실행 & 결과
terraform init
명령 실행
terraform plan
으로 확인 후terraform apply
로 프로비저닝
프로비저닝 및 확인
terraform apply
→yes
를 통해서 인프라를 프로비저닝 한다.
- cloudflare에 레코드가 정상적으로 등록되었다.
접속화면들
- 여러 벤더사의 웹서버가 하나의 도메인으로 제공되는 것을 확인했다. 유료 결제를 통해 Failover 기능을 갖추면 벤더사의 장애에 관계없이 가장 가용성 높은 웹서버를 제공할 수 있을 것 같다.
리소스 삭제
terraform destroy
→yes
명령으로 너무 간단하게 모든 리소스가 제거된다.
- 클라우드 올챙이 시절을 겪은 사람이라면 실습 후에 리소스 삭제를 제대로 하지 않아서 불필요한 과금을 한 경험이 있을것이다. Terraform은 삭제의 번거로움과 놓치는 리소스로부터 자유롭다.
결론
- AWS, Azure, GCP를 통해 웹서버 인스턴스의 멀티클라우드 실습을 성공적으로 마쳤다. 단순하게 서버의 인스턴스를 멀티클라우딩하여 가용성을 극대화하는 것을 넘어, 인프라와 플랫폼을 나누거나 플랫폼마다 제공하는 다양한 강력한 서비스를 섞어서 사용하는 것에 멀티클라우딩의 목적이 있을 것 같다.
- 또한 대부분의 기업의 최종 목표가 멀티클라우드 환경이라고는 하지만 모든 전략에 장단점이 있듯이 어려운 설계 및 관리를 비롯한 단점 또한 있을것이다.
Uploaded by Notion2Tistory v1.1.0