Cloud Service Practice 09
두 번째 EC2와 사용자 데이터로 반복 작업을 줄이는 방법
첫 번째 서버와 거의 같은 EC2를 또 만들면서 왜 사용자 데이터를 쓰는지, 또 왜 두 번째 서브넷에 놓는지 목적이 흐릿하다.
근거 · 교안 p63-p75
1장: 반복 작업, 왜 사용자 데이터가 필요한가?
솔라는 모니터 화면의 AWS 콘솔과 자신의 노트를 번갈아 보았다. 방금 전, 첫 번째 EC2 가상 서버를 만들고 그 안에 웹 서버를 설치하는 데 성공했다. 터미널에 직접 접속해 명령어를 하나씩 입력하고, 마침내 브라우저에 ‘Hello World’가 떴을 때의 뿌듯함이 아직 남아 있었다.
그런데 다음 단계가 이상했다. ‘두 번째 EC2 인스턴스 생성.’ 거의 똑같은 사양의 서버를 하나 더 만들라는 지시였다. 솔라는 고개를 갸웃거렸다. 화면을 아래로 스크롤하자 ‘고급 세부 정보’ 섹션 아래에 ‘사용자 데이터’라는 낯선 입력 칸이 보였다.
“두 번째 인스턴스는 사용자 데이터 부분에 웹서비스 설정 스크립트를 입력합니다.”
가이드의 한 문장이 솔라의 머릿속을 맴돌았다. 왜 똑같은 서버를 또 만들지? 그리고 사용자 데이터는 또 뭐람. 그냥 아까 했던 대로 똑같이 작업하면 안 되나? 솔라는 마우스 커서를 ‘인스턴스 시작’ 버튼 위에서 멈춘 채, 옆에서 조용히 책을 읽고 있던 루나를 불렀다.
“언니, 질문. 방금 웹 서버 하나 만들었는데, 왜 거의 똑같은 걸 또 만들라고 하는 걸까? 심지어 이번에는 ‘사용자 데이터’라는 걸 쓰라는데, 이건 그냥 설정 단계 중 하나인 거지?”
솔라의 목소리에는 약간의 불평이 섞여 있었다. 첫 번째 성공의 기쁨이 불필요해 보이는 반복 작업 앞에서 희미해지는 참이었다.
루나는 책에서 눈을 떼고 솔라의 화면을 잠시 들여다보았다. 그러고는 아무 말 없이 솔라의 노트를 자기 앞으로 끌어당겼다.
“솔라, 아까 첫 번째 서버 만들고 나서 웹 서버가 동작하게 하려고 터미널에 어떤 명령어들을 순서대로 입력했는지, 여기 한번 쭉 적어볼래?”
“음… 갑자기? 알았어.”
솔라는 잠시 기억을 더듬으며 펜을 들었다. 처음에는 쉬웠다. 서버에 접속하고, 패키지를 업데이트하고. 하지만 곧이어 웹 서버 프로그램을 설치하고, 서비스가 항상 켜져 있도록 설정하고, 테스트용 웹페이지 파일을 만드는 과정까지 떠올리자 점점 적어야 할 목록이 길어졌다.
솔라는 자신이 입력했던 명령어들을 기계적으로 노트에 옮겨 적었다.
# 1. 서버에 접속해서
ssh -i "my-key.pem" ec2-user@...
# 2. 패키지 업데이트
sudo yum update -y
# 3. 웹 서버(Apache) 설치
sudo yum install -y httpd
# 4. 웹 서버 실행
sudo systemctl start httpd
# 5. 재부팅 시에도 웹 서버가 켜지도록 설정
sudo systemctl enable httpd
# 6. 테스트 페이지 만들기
echo "<h1>Hello from EC2-1</h1>" | sudo tee /var/www/html/index.html
목록을 다 쓰고 나자 솔라는 잠시 멍하니 노트를 내려다보았다. 여섯 단계, 여섯 번의 명령어 입력. 서버 한 대를 설정하는 데 이만큼의 수고가 들었다.
“다 적었어. 이렇게 했지.”
“만약 이런 서버가 열 대 필요하면 어떡할까? 백 대가 필요하다면?”
루나의 나직한 질문에 솔라는 할 말을 잃었다. 상상만 해도 끔찍했다. 백 번의 접속, 수백 번의 명령어 입력. 복사해서 붙여넣기를 한다 해도, 그 과정에서 실수가 없을 리 없었다. ‘EC2-1’ 대신 ‘EC2-2’라고 적어야 할 곳을 놓치거나, 명령어 하나를 빠뜨리는 순간 원인을 찾기 위해 또 한참을 헤맬 것이다.
그제야 솔라의 눈에 ‘반복’이라는 단어가 선명하게 들어왔다. 방금 전까지는 그저 ‘한 번 더 하는 작업’이었지만, 이제는 ‘앞으로 수십, 수백 번 해야 할지도 모르는 비효율적인 과정’으로 보였다.
솔라는 다시 모니터의 ‘사용자 데이터’ 입력 칸을 쳐다보았다. 이전과는 전혀 다른 눈빛이었다.
“설마… 저기에다가 내가 방금 노트에 적은 명령어들을 넣어두는 거야?”
루나가 조용히 고개를 끄덕였다.
“맞아. 솔라가 방금 ‘만약 이걸 또 해야 한다면?’ 하고 느꼈던 바로 그 귀찮음을 해결해 주는 장치야. EC2 인스턴스가 처음 부팅될 때, 사용자 데이터에 적힌 명령어들을 딱 한 번, 스스로 실행해 줘.”
아. 솔라의 입에서 작은 탄성이 터져 나왔다. 사용자 데이터는 그저 거쳐 가는 설정 창이 아니었다. 반복적인 수동 작업을 없애주는 자동화 도구였던 것이다. 내가 접속해서 명령어를 일일이 칠 필요 없이, 인스턴스가 생성되자마자 웹 서버가 설치되고 실행 준비까지 마친 상태로 나를 기다리게 만드는 것.
솔라는 ‘두 번째 인스턴스는 사용자 데이터 부분에 웹서비스 설정 스크립트를 입력합니다’라는 문장을 다시 떠올렸다. 이제 그 문장은 ‘두 번째부터는 똑같은 작업을 반복하지 말고, 사용자 데이터로 자동화하세요’라는 친절한 조언으로 들렸다.
솔라는 신이 나서 사용자 데이터 입력 칸에 웹 서버 설치 스크립트를 붙여 넣었다. 하지만 이내 새로운 궁금증이 고개를 들었다.
“정말 신기하다. 그냥 텍스트를 넣어두는 것뿐인데, 어떻게 컴퓨터가 처음 켜질 때 이걸 알아서 명령으로 실행하는 거지? 무슨 원리로 동작하는 걸까?”
2장: 사용자 데이터, 어떻게 초기 설정을 자동화하나?
솔라의 마우스 커서는 ‘인스턴스 시작’ 버튼 위를 맴돌았다. AWS 콘솔 화면의 ‘고급 세부 정보’ 섹션, 그중에서도 ‘사용자 데이터’ 입력 칸에는 방금 전 솔라가 겪었던 번거로움을 해결해 줄 스크립트가 가지런히 입력되어 있었다.
#!/bin/bash
# Use this for your user data (script from top to bottom)
# install httpd (Linux 2 version)
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from EC2-2</h1>" > /var/www/html/index.html
분명 솔라 자신의 손으로 붙여 넣은 텍스트인데도, 여전히 비현실적으로 느껴졌다. 정말 이 글자들이 컴퓨터를 만들자마자 저절로 웹 서버를 설치하고 실행까지 시켜준다고? 솔라는 고개를 갸웃하며 혼잣말처럼 중얼거렸다.
“그냥 텍스트일 뿐인데… 무슨 원리일까?”
루나는 솔라의 질문에 바로 답하는 대신, 화면을 턱짓으로 가리켰다.
“일단, 시작해 볼까? 마법이 정말 일어나는지 직접 확인해 봐야지.”
솔라는 루나의 말에 ‘인스턴스 시작’ 버튼을 클릭했다. 잠시 후, 인스턴스 목록에 ‘EC2-2’라는 이름의 새로운 가상 서버가 나타나기 시작했다. 상태는 ‘pending’에서 ‘running’으로 바뀌었지만, 아직 초기화 작업이 진행 중일 것이다. 솔라는 초조하게 화면을 바라보았다.
“기다리는 동안 간단한 비유를 들어볼까?”
루나가 조용히 입을 열었다.
“마치 이사를 앞둔 빈 집에 미리 쪽지를 남겨두는 것과 같아. ‘새 주인님, 이 집에 도착하면 가장 먼저 이 쪽지를 읽고, 여기에 적힌 대로 집을 꾸며주세요.’ 하고 말이야.”
“쪽지?”
“응. EC2 인스턴스로 만들어지는 가상 컴퓨터 안에는, 맨 처음 전원이 켜졌을 때 딱 한 번 실행되는 특별한 프로그램이 심어져 있어. 클라우드-init(cloud-init) 같은 것들이지. 그 프로그램이 ‘사용자 데이터’라는 이름의 쪽지를 찾아서, 거기에 적힌 명령어들을 순서대로 실행해 주는 거야. 마치 우리가 처음 컴퓨터를 샀을 때 초기 설정을 진행하는 것처럼.”
아하. 솔라는 무릎을 쳤다. 마법이 아니었다. 그냥 텍스트 덩어리를 컴퓨터가 알아서 해석하는 게 아니라, ‘사용자 데이터’라는 이름의 약속된 쪽지를 읽어주는 전담 프로그램이 처음부터 내장되어 있었던 것이다. EC2 인스턴스가 생성되는 과정에 포함된 자동화된 절차였다.
솔라는 이제 ‘고급 세부 정보의 사용자 데이터에 웹서비스 설정 스크립트를 넣어, 부팅 시 웹 서버가 자동 준비되게 한다’는 문장을 이해할 수 있었다. 그건 단순히 설정 항목 하나를 채우는 행위가 아니었다. ‘갓 태어난 서버에게 첫 번째 임무를 부여하는’ 행위였던 것이다.
“자, 이제 확인해 볼 시간이야.”
루나의 말에 솔라는 정신을 차렸다. 인스턴스의 상태 검사가 통과되었다는 표시가 떴다. 첫 번째 서버였다면, 이제 막 터미널에 접속해서 기나긴 명령어 입력을 시작할 시간이었다. 하지만 이번에는 달랐다.
솔라는 망설임 없이 두 번째 인스턴스의 퍼블릭 IP 주소를 복사해 웹 브라우저 주소창에 붙여넣고 엔터 키를 눌렀다.
화면에 나타난 것은…
Hello from EC2-2
솔라의 입가에 환한 미소가 번졌다. 터미널에 접속하지도, 명령어를 한 줄도 입력하지 않았는데 웹 서버가 완벽하게 작동하고 있었다. 수동으로 했던 여섯 단계의 작업이 단 몇 분 만에 자동으로 완료된 것이다. 이것이 자동화의 힘이었다. 반복의 고통에서 해방된 짜릿한 순간이었다.
“성공이네!”
솔라는 의기양양하게 외치며 인스턴스 목록 화면으로 돌아왔다. 수동으로 만든 첫 번째 인스턴스와, 사용자 데이터로 자동화한 두 번째 인스턴스가 나란히 ‘running’ 상태로 빛나고 있었다. 목적은 같았지만, 과정은 완전히 달랐다.
문득, 두 인스턴스의 정보가 나란히 표시된 화면에서 다른 점 하나가 눈에 띄었다. ‘서브넷 ID’. 첫 번째 인스턴스와 두 번째 인스턴스는 서로 다른 서브넷에 속해 있었다. 인스턴스를 만들 때 무심코 다음 단계로 넘어갔던 네트워크 설정이었다.
“어? 언니, 이건 왜 다르지? 그냥 같은 곳에 만들어도 되는 거 아니었어? 왜 굳이 다른 네트워크 구역에 만든 거야?”
3장: 두 번째 서브넷, 왜 비교 환경이 필요한가?
자동화의 성공에 취해 있던 솔라의 시선이 AWS 콘솔의 한 지점에 머물렀다. 수동으로 만든 EC2-1과 사용자 데이터로 만든 EC2-2. 두 인스턴스의 정보가 나란히 펼쳐진 테이블에서, 유독 다른 값을 가진 열이 있었다.
| 인스턴스 ID | 서브넷 ID |
|---|---|
| i-0123…abc | user**-subnet1 |
| i-0456…def | user**-subnet2 |
‘서브넷 ID’. 솔라는 인스턴스를 만들 때 ‘네트워크 설정’ 단계에서 무심코 다음을 눌렀던 것을 기억했다. 가이드는 분명 ‘두 번째 서브넷을 선택하라’고 지시했다. 하지만 왜?
옆에 있던 루나는 솔라의 시선이 머무는 곳을 보고, 말없이 책상 위 메모지를 가져왔다. 그리고 큰 사각형 하나를 그린 뒤, 그 안에 작은 사각형 두 개를 나란히 그렸다.
“이 큰 사각형이 우리가 가진 가상의 개인 공간, VPC라고 해보자.”
루나는 큰 사각형 위에 VPC라고 썼다. 그리고 작은 사각형들에는 각각 서브넷-1, 서브넷-2라고 적었다. 그녀는 첫 번째 인스턴스를 가리키며 서브넷-1 상자 안을 펜으로 톡 쳤다.
“우리가 처음 만든 서버는 여기 있어.”
그리고 두 번째 인스턴스를 가리키며 서브넷-2 상자 안을 쳤다.
“자동으로 만든 두 번째 서버는 여기.”
그림으로 보니 분리된 모습이 한눈에 들어왔다. 솔라는 바로 이전의 궁금증을 입 밖으로 꺼냈다.
“응, 그건 알겠는데… 왜? 그냥 서브넷-1에 같이 두면 안 되는 거였어? 똑같은 웹 서버인데, 굳이 다른 방에 둘 필요가 있나 싶어서. 그냥 파일을 정리하는 폴더 같은 거 아니야?”
솔라에게 서브넷은 그저 자원을 구분하기 위한 이름표나 폴더처럼 느껴졌다. 불필요하게 복잡성을 더하는 단계 같았다.
루나는 대답 대신 질문을 던졌다.
“좋아. 그럼 시나리오를 하나 만들어보자. 서브넷-1에 있는 첫 번째 서버가 지금 우리 회사의 공식 홈페이지라고 생각해봐. 아주 잘 돌아가고 있어. 그런데 솔라, 네가 이 홈페이지에 아주 멋진 신기능을 추가하고 싶어졌어. 코드를 완전히 새로 짜야 할 수도 있는 큰 작업이야. 이 새로운 버전을 어디서 테스트해볼래?”
“음… 당연히 두 번째 서버에서 테스트해야지. 그러려고 만든 거니까.”
솔라는 당연하다는 듯이 대답했다.
“맞아. 그런데 만약 솔라가 만든 새 코드가 엄청난 버그를 품고 있어서, 그 코드를 실행하는 순간 네트워크에 엄청난 부하를 준다면? 심지어 같은 네트워크 구역 안에 있는 다른 서버들까지 느려지게 만들 정도라면?”
루나의 말에 솔라의 표정이 굳어졌다. 생각지도 못한 시나리오였다. 만약 두 서버가 같은 서브넷-1 안에 있었다면? 테스트하던 서버 하나의 문제가 잘 운영되던 공식 홈페이지에까지 영향을 미칠 수 있었다. 최악의 경우, 둘 다 먹통이 될 수도 있다.
그제야 솔라는 루나가 그린 그림 속 두 개의 분리된 상자를 다른 눈으로 보게 되었다. 서브넷-1과 서브넷-2를 가르는 선은 단순한 구분선이 아니었다. 한쪽의 문제가 다른 쪽으로 번지지 않게 막아주는 방화벽이자 안전장치였다.
“아…! 따로 둔다는 게, 그냥 이름만 분리하는 게 아니라, 서로 영향을 주지 않도록 격리하는 거구나. 테스트는 안전한 놀이터에서 하고, 다 완성되면 그때 진짜 서비스에 반영하라는 뜻이네.”
루나는 조용히 고개를 끄덕였다.
“그런 목적도 있고, 또 다른 중요한 이유도 있어. 만약 서브넷-1이 위치한 데이터 센터 전체에 정전이 발생하면 어떻게 될까?”
“서버가… 꺼지겠지?”
“응. 그럼 우리 홈페이지는 접속이 안 될 거야. 그런데 만약 서브넷-2가 물리적으로 전혀 다른 건물, 다른 데이터 센터에 있다면?”
솔라의 눈이 커졌다.
“서브넷-1이 멈춰도, 서브넷-2에 있는 서버는 살아남으니까… 서비스를 계속할 수 있겠네!”
단순히 폴더를 나누는 수준이 아니었다. 서브넷을 나눈다는 것은 실험 환경을 만들고, 장애에 대비하고, 서비스의 안정성을 높이는 매우 전략적인 행위였다. 솔라는 ‘네트워크는 같은 VPC지만 두 번째 서브넷 user**-subnet2를 선택한다’는 문장을 다시 떠올렸다. 이제 그 문장은 ‘만약을 대비해, 격리된 안전한 공간을 하나 더 확보하세요’라는 깊은 뜻을 담은 조언으로 읽혔다.
사용자 데이터가 ‘어떻게’의 문제를 해결하는 자동화 도구였다면, 서브넷 분리는 ‘어디에’를 결정하는 안정성 도구였던 것이다.
솔라는 다시 AWS 콘솔 화면으로 돌아갔다. 그리고 두 인스턴스의 ‘태그(Tags)’를 편집하기 시작했다. EC2-1에는 Purpose라는 키에 Baseline-Manual이라는 값을, EC2-2에는 같은 키에 Test-Auto라는 값을 입력했다.
단순히 ‘1번’, ‘2번’으로 보이던 서버들이 이제는 명확한 역할을 가진 존재로 보였다. 하나는 수동으로 구축한 기준점, 다른 하나는 자동화된 테스트 환경. 솔라는 이제 클라우드 자원을 만들 때, 단순히 ‘무엇을’ 만들지 뿐만 아니라, ‘어떤 목적으로’, ‘어디에’ 배치할지를 고민해야 한다는 사실을 깨달았다. 그것이야말로 반복을 줄이고 유연성을 확보하는 진짜 시작이었다.