CKA (Certified Kubenetes Administrator) 시험을 꽤 실무적인 시험으로 알려져 있습니다. 단답형 지식을 묻는 질문이 주류를 이루고 있어 스펙을 많이 기억해야 하는 다른 시험과 달리 실제 터미널 환경에서 쿠버네티스에 대한 컨트롤을 얼마나 잘 하고 이해하고 있는지를 확인하는 시험입니다. 네, 아직 취득한건 아닙니다 ㅎㅎ
원격으로 감독관이 컴퓨터 환경을 감시(?)하며 시험이 진행된다고 알려져 있어서 따로 정리한 레퍼런스를 활용하는 것이 어렵다고 합니다. 따라서 유용한 커맨드들을 기억해 두고 시험에 임하면 좋다고 하네요. 듣고 있는 강의에서 정리해준 몇 가지 커맨드를 잊지 않기 위해 정리해 봅니다.
예제 시험문제를 몇 가지 풀다보니 손으로 Yaml 파일을 구성해야 하는 시나리오가 종종 나오는 것 같습니다. 시행착오를 줄이고 시간을 단축하기 위해, 위의 명령들로 템플릿을 생성해서 변경하는 방식이 아무래도 시험 볼 때 마음을 편안하게 해주겠죠? 기초적인 명령들이지만 익숙하지 않다보니... 일단 여기까지!
2021년이 밝았습니다. 새해가 되면 여러가지 계획을 세우기 마련인데요, 작심삼일이 되지 않도록 3일마다 마음을 다잡을 필요가 있습니다. 계획성 있게 하기에 좋은 것이 역시 자격증 취득인지라, 기술 습득과 자격 취득을 한번에 할 수 있는 좋은 자격 프로그램들이 많습니다.
그 중에서도 IT 직군에 계신 분들이 가장 관심이 많은 것이 AWS 의 자격증들일 것입니다. 그 시작점이라고 할 수 있는 자격증이 Solutions Architet Associate 라고 생각합니다. 저 역시 2019년 11월에 취득을 했는데요, 공부 방법을 간단하게 정리해 보았습니다.
AWS SAA 시험의 개요
AWS 의 Solutions Architect 시험은 AWS 의 제품들을 잘 이해하여 비즈니스 요구사항을 수용할 수 있는 인프라 환경을 설계할 수 있는 능력을 시험합니다. 방대한 AWS 제품들을 공부해야 하기 때문에 계획성 있게 학습하는 것이 중요합니다.
특히 SAA 시험은 고객의 비즈니스 상황, 문제 시나리오에 대하여 어떤 식으로 대응할 것인지를 묻는 문제들이 여럿 출제됩니다. 따라서 문제 상황을 잘 이해하고 적절한 해결 방안을 AWS 의 제품, 그리고 제품의 특징을 활용하여 해소할 수 있는 방법을 제시해야 합니다. 이같은 시험 문제 패턴은 시험 요강에서도 확인할 수 있습니다.
상당히 실무적인 시험이기 때문에 실전 경험이 많다면 자격증을 준비하는 것이 훨씬 수월합니다. 하지만 실전 경험이 부족하다 하더라도 다양한 자료를 통해서 학습하고 시험에 응시하여 충분히 취득할 수 있는 자격이기도 합니다. 어떤 방향으로 공부를 해야 하는지 역시 공식 가이드에 잘 나타나 있습니다.
공식 시험 가이드 및 자료
시험에 대한 공식 가이드가 상당히 자세히 제공됩니다. 가장 먼저 보면 좋은 자료는 예제 문항과 시험 안내서입니다. 흔히 자격시험은 기출문제 풀이나 족보를 찾기 십상인데요 제대로 실력을 함양하기 위해서는 덤프는 가능한 보지 않을 것을 권장드립니다. 대신 온라인 강의 등에서 챕터별로 제공되는 연습문제를 충실히 풀어내면 합격하는데 큰 지장은 없습니다.
> AWS 공식 시험 준비 가이드 [바로가기] > AWS 시험 안내서 [바로가기] - 출제 비중에 관한 내용이 언급되어 있습니다 > SAA 시험 공식 예제 [바로가기] - 공부 시작전에 꼭 읽어보시기 바랍니다!
글을 적으며 Udemy 에 들어가보니 2021 년 새해를 맞이하여 Udemy 에서 연습문제를 20달러에서 9.99달러로 할인 판매를 하고 있습니다. 1월 4일까지 할인이라고는 하지만 연장될 수도 있으니 관심 있는 분들은 구입해 보시는 것도 좋겠습니다! 참고로 AWS 공식 시험 등록 센터에서는 20달러에 판매됩니다. (65문항씩 6개의 시험 자료가 들어가 있습니다)
유튜브나 블로그에도 좋은 자료를 정리해 주신 분들이 많습니다. 하지만, 개인적으로 추천드리는 것은 Udemy 의 아래 강의입니다. 영어 발음도 또렷해서 듣기에 어렵지 않고, 시험을 영어로 치는 경우에 많은 도움이 됩니다. 짧은 동영상들로 구성되어 있어 출퇴근길에 한 두개씩 듣거나, 화장실, 산책길에 틈틈히 학습하기에 좋습니다.
요즘 강의 시장도 경쟁이 치열하다보니 구입한 강의에 대한 유지보수(?)도 잘 됩니다. AWS 는 지속적으로 개선되고 진화하고 있기 때문에 주기적으로 시험도 갱신이 됩니다. 이 강의를 제공하는 Ryan 님도 [SAA-C02] 등으로 최신 시험 범위에 맞추어 컨텐츠를 계속 업데이트 해주고 있습니다.
지금 보니 제가 구입한 이 강의도 9.99 달러로 2021년 얼리버드 할인이 진행중이네요! 저는 거의 2만원돈 주고 샀던것 같은데... 여러분 꿀 기회를 놓치지 마십시오! 뭘 하던간에 연초에 하나 정도 몰아쳐야 한다는 것, 다들 아시죠? 인간의 의지는 박약합니다!
(2021.08 업데이트) Cloudguru가 Pluralsight에 인수되면서 강의들이 Udemy에서 일단 다 빠진 것 같습니다. 그 다음으로 대권(?)을 잡은 강의를 추천해 드립니다! Cloudguru의 Ryan님이 미국 스타일의 발음으로 유쾌한 강의를 해주었다면, Stephane님의 아래 강의는 제2외국어로 영어를 배운 사람의 느낌으로 조금 더 편안한(?) 발음으로 강의를 해주고 있습니다. 그래도 꼼꼼히 시험에 필요한 것들과 AWS의 기초 지식을 잘 챙겨주고 있다는 점에서는 동급 최강이라 하겠습니다! 2021년 버전으로 업데이트가 되었으니 한 번 살펴보시기 바랍니다!
재미있는 것은 시험을 위한 연습 시험도 유료로 볼 수 있습니다. 최근에 취득한 자격이 AWS 자격증 하나이다보니 다른 기술 자격증도 이런 유료 연습 시험이 있는지는 잘 모르겠습니다. 비용은 20달러로 크게 부담되지 않지만 꼭 쳐봐야 하는 것은 아닙니다. 앞서 말씀드린 것처럼 연초 얼리버드 할인 9.99 달러 행사중이니 필요하신분은 공식 사이트 대신 Udemy 에서 구입하시면 좋을 것 같습니다.
시험은 150 달러로 비싼편은 아닙니다. 한국어로 시험을 볼 수도 있지만 그냥 영어로 보는 것이 훨씬 편합니다. AWS 의 한글 자료들이 잘 되어 있는 편이긴 하지만 꼼꼼히 보다보면 번역기를 돌렸거나 비전공자가 번역하여 문제가 있는 경우들이 종종 발견됩니다. 영어로 보고, 영어로 시험 보는 것이 베스트입니다.
두 번의 포스팅을 통해 VPC 와 Gateway 를 생성했습니다. 그럼 EC2 를 바로 만들면 되나요? 라고 생각하실 수 있겠습니다만 일단은 생성한 VPC 가 Gateway 를 통해 인터넷과 교감을 할 수 있도록 라우팅 테이블 Routing Table 을 설정하는 작업을 먼저 진행해 보겠습니다. 사실 순서는 큰 상관이 없지만 <네트워크에 대한 작업> 을 마무리하고 <서버에 대한 작업>을 한다고 생각하시면 좋겠습니다.
Gateway 구성 : Internet Gateway / Egress Only Internet Gateway ("OpenVPN 구축 #2" 포스팅)
Routing Table 조정 (본 포스팅!)
IPv6 주소를 갖는 EC2 배포 (본 포스팅!)
OpenVPN 설치 및 구성
VPN 접속 시험
기타
라우팅 조정
1.4 Routing Table 조정
라우팅 테이블 Routing Table 은 VPC 로 들어오는 트래픽과 나가는 트래픽에 대한 경로를 지정해 주는 역할을 합니다. 물론 라우팅 테이블만 설정했다고 하여 모든 통신이 정상적으로 이루어지는 것은 아닙니다. 말 그대로 경로에 대한 지정일 뿐, 실제 트래픽을 허용할 것인지는 Network ACL 과 Security Group 을 통해 IP 주소 대역, 포트 단위로 결정됩니다.
VPC 하위의 Route Tables 메뉴입니다
라우팅 테이블을 설정하기 위해서는 VPC 제품 하위 메뉴에 위치한 <Route Tables> 를 통해 진행할 수 있습니다. 기본적으로 VPC 가 생성되면 VPC 에 대한 기본 라우팅 테이블이 자동으로 생성됩니다. 기본 라우팅 테이블은 VPC 에 할당된 IPv4, IPv6 주소를 대상으로 VPC 내에서 (=local) 통신이 가능하도록 하는 정책만 들어 있는 상태입니다.
우리가 해야하는 일은 위 이미지의 핑크색 상자에 들어 있는 내용과 같이 외부로 부터의 트래픽 송수신을 위한 정책을 추가하는 것입니다. IGW (Internet Gateway) 로는 SSH 접근을 위해 IPv4 에 대한 정책을 추가했고, EIGW (Egress Only Internet Gateway) 에는 실제 v6 주소 목적지에 대한 VPN 터널링을 위해 IPv6 주소에 대한 정책을 추가했습니다.
정책 추가를 위해 라우팅 테이블 목록에서 IPv6 용으로 만든 VPC 에 할당된 기본 라우팅 테이블을 선택합니다. Actions 버튼을 누르지 않아도 화면 아랫쪽에서 <Routes> 탭을 선택하면 라우팅 테이블에 대한 상세 정책 목록이 출력됩니다. 정책 추가를 위해 <Edit routes> 버튼을 누르겠습니다.
IPv4 의 모든 주소를 나타내는 CIDR block 은 0.0.0.0/0 으로 표기되며, IPv6 의 모든 주소를 나타내는 CIDR block 은 ::/0 으로 표기합니다. 목적지 주소에 v4, v6 에 대한 CIDR block 을 추가하고 v4 는 IGW 로, v6 는 EIGW 를 이용하도록 대상(Target) 제품을 지정해 줍니다. 이미 생성한 IGW 와 EIGW 가 드롭 다운 목록에 노출되기 때문에 설정은 쉽게 하실 수 있습니다. 경로 입력이 끝나면 우측 하단의 <Save Routes> 버튼을 누릅니다.
라우팅 테이블 업데이트가 완료되었습니다!
1.5 IPv6 주소를 갖는 EC2 인스턴스 배포
네트워크의 구성이 끝났으니 이제 실제 OpenVPN 바이너리가 구동되고 목적이 v6 주소까지 터널링을 해줄 EC2 인스턴스를 생성해 보도록 하겠습니다. 사용자가 얼마나 많은지, 트래픽 규모가 어떠한지에 따라 인스턴스 타입이 결정되어야 하겠지만, 이 포스팅에서는 AWS 무료 티어에서도 사용할 수 있는 t2.micro 타입의 인스턴스를 사용하도록 하겠습니다. 소규모의 사용량이라면 이 인스턴스로도 큰 문제가 없습니다.
EC2 인스턴스의 생성은 많이들 해보셨을 작업이기 때문에 주의할 점을 중심으로 설명드리겠습니다. EC2 생성 마법사의 세번째 단계에는 IP 주소 할당에 대한 정책을 선택하도록 되어 있습니다. 우리가 진행하는 OpenVPN 은 단일 인스턴스 환경이기 때문에, 해당 서버가 사용자들로부터 IPv4 를 통해 VPN 연결을 시도할 수 있어야 하고, IPv6 주소를 보유하여 v6 주소를 갖고 있는 목적지 서버와 연결할 수 있어야 합니다.
이 목적을 달성하기 위해서는 <3. Configure Instance> 단계에서 하단에 있는 <Auto-assign Public IP> 와 <Auto-assign IPv6 IP> 를 Enable 로 선택하여 v4 와 v6 를 통해 공인 IP 를 사용할 수 있도록 해야 합니다. 그런데 IPv6 는 왜 <Public> 이라는 말이 없을까요? 기본적으로 IPv6 주소 체계는 Private / Public 를 가지고 있지 않습니다. 따라서 옵션의 이름도 단순히 <Auto-assign IPv6 IP> 라고 되어 있다는 점 참고하시기 바랍니다!
EC2 생성 마법사를 완료하고 인스턴스 생성을 기다립니다. 생성이 완료되면 위와 같은 화면을 볼 수 있게 됩니다. 다른 기본적인 사항은 특별히 확인할 내용이 없고, 네트워킹 Networking 탭을 중심으로 살펴보면 됩니다. 설명했던 것처럼 v4 는 Private, Public 의 주소가 할당되지만 v6 는 하나의 주소만 할당된 것이 보입니다. 이제 인프라의 준비가 끝났습니다.
9월에 첫 포스팅을 올리고 시간이 너무 많이 흘렀습니다. 기억이 더 가물가물 해지기 전에 OpenVPN 구축 포스팅을 마무리 해볼까 합니다. 지난 포스팅에서 우리는 `IPv6 대역을 갖고 있는 VPC 생성` 을 했고 `VPC 내에 Public Subnet 생성` 까지 완료했습니다. 자세한 내용은 아래 링크를 통해 지난 포스팅을 참고하시기 바랍니다!
Gateway 구성 : Internet Gateway / Egress Only Internet Gateway (본 포스팅!)
Routing Table 조정
IPv6 주소를 갖는 EC2 배포
OpenVPN 설치 및 구성
VPN 접속 시험
기타
라우팅 조정
1.3. Gateway 구성
1.3.1. Internet Gateway
OpenVPN 을 이용한 IPv6 VPN 구성시 VPC 에는 두개의 Gateway 가 필요합니다. 보통 v4 주소 환경에서 인터넷으로 나가고 들어오는 트래픽 처리를 위해 사용하는 Internet Gateway 가 첫번째 요소입니다. v4 주소라고 명기한 것은 다 이유가 있겠죠? Internet Gateway 는 나가는 트래픽, 즉 아웃바운드 트래픽에 대하여 IPv6 주소를 처리하지 못합니다. 이 때문에 별도로 Egress Only Gateway 를 구성해야 합니다.
정리를 잘 해두기 위하여 위의 내용은 취소선으로만 표기하고 나두었습니다. AWS 에서 제공하는 Gateway 에는 Internet Gateway 와 Egress Only InternetGateway 가 있습니다. Internet Gateway 는 양방향 (Inbound, Outbound) 의 인터넷 트래픽을 위해 사용하는 구성 요소이고 Egress Only InternetGateway 는 단방향 (Outbound) 전용 게이트웨이 입니다.
왜 그렇게 기억하고 있었는지 모르겠지만 OpenVPN 을 통해 실제 IPv6 를 사용하는 서버까지 터널링을 위해서 꼭 Egress Only Internet Gateway 를 사용할 필요는 없습니다. 다만, 각 인스턴스로 IPv6 로 요청이 들어오지 않도록 확실히 분리할 필요가 있다면 IPv6 터널링 용으로 Egress Only Internet Gateway 를 사용하면 됩니다.
Internet Gateway : OpenVPN EC2 인스턴스로 SSH, OpenVPN 접속을 처리하기 위한 목적 Egress Only Internet Gateway : 터널링을 통해 IPv6 목적지로 연결 (EC2 <-> Dest. IPv6 서버) 하기 위한 용도
Internet Gateway 를 생성하기 위해 VPC 제품 페이지에서 Internet Gateway 메뉴로 들어갑니다. 별도의 VPC 를 만들었기 때문에 Default VPC 에 있는 Internet Gateway 를 사용할 수는 없습니다. Internet Gateway 는 VPC 단위로 연결할 수 있다는 것도 기억해 두면 좋겠습니다. 제 경우 구분을 위해 Tag 에 "ipv6" 를 넣어주었습니다.
Internet Gateway 가 생성되면 어떤 VPC 와도 연결되어 있지 않은 상태입니다. 아래의 화면에서 보이는 것처럼 Detached 라는 메세지가 연결된 VPC 가 없다는 것을 알려줍니다. 우측 상단의 "Actions" 버튼을 눌러 앞서 생성한 VPC 에 연결(Attach) 해보도록 하겠습니다.
State 는 Detached, VPC ID 도 공란입니다. Attach to VPC 를 선택합니다.
앞서 가이드 했던 것처럼 VPC 생성시에도 Tag 를 잘 달아두었다면 Attach to VPC 를 하는 과정에 어려움 없이 VPC 를 잘 선택할 수 있습니다. 물론 제 경우 VPC 가 하나라서 Tag 가 있고 없고 상관은 없습니다만 규모가 좀 되는 인프라를 운영중이시면 Tag 가 확실히 도움이 될 겁니다. VPC 를 선택후 <Attach internet gateway> 버튼을 눌러 연결 작업을 마무리 합니다.
IPv6 용으로 만든 VPC 를 선택합니다
연결 작업이 정상적으로 완료되면 아래와 같은 Summary 화면을 보게 됩니다. 연결한 내용에 이상이 없는지 한 번 살펴보고 지나가시면 됩니다.
생성한 Internet Gateway 의 State 가 Attached 로 바뀌었습니다.
1.3.2. Egress Only Internet Gateway
설명했던 것처럼 VPN 연결은 IPv4 로만 허용하고 터널링은 IPv6 를 쓰기 위해 Egress Only Internet Gateway 를 따로 만들어 보도록 하곘습니다. AWS 의 제품 설명 페이지를 유심히 읽어 보셨다면 아시겠지만 Egress Only Internet Gateway 는 IPv6 전용입니다. IPv4 를 터널링 한다면 Internet Gateway 만 사용하는 것으로 충분합니다.
VPC 화면의 메뉴중 <Egress Only Internet Gateway> 를 선택합니다. 새로운 Egress Only Internet Gateway 를 아래 화면처럼 생성하도록 하겠습니다. 일반 Internet Gateway 와 특별히 차이가 없기 때문에 Tag 지정만 유의해서 진행하시면 되겠습니다. VPC 목록에도 Tag 가 표시되기 때문에 VPC 생성시 Tag 를 잘 달아두었다면 어려움 없으실 겁니다.
생성된 Egress Only Internet Gateway 는 eigw 로 시작되는 고유 ID 를 갖게 됩니다. Internet Gateway 의 생성 화면과 달리 생성 할때 이미 VPC 를 지정했기 때문에 별로도 Attach 하는 과정이 나오지는 않습니다. 비슷한 제품인데 담당 조직이 다른지 생성 화면과 절차가 차이가 있네요? Egress Only Internet Gateway 가 훨씬 편한 것 같습니다 ^^
이번 포스팅에서는 두개의 Internet Gateway 를 생성해 보았습니다. 다음 포스팅에서는 VPC 의 라우팅 테이블을 설정하여 OpenVPN 트래픽이 정상적으로 EC2 를 통해 연결되고 터널링 될 수 있도록 해보겠습니다.
Redhat 계열(가령 CentOS)의 운영체제를 쓰면 패키지 매니저로 yum 을 기본적으로 사용합니다. 사전에 쉘 환경에 Path 가 잘 잡혀 있다면 면 yum 으로 설치한 패키지 실행에 큰 문제가 없지만, 간혹 다른 사람이 운영하던 환경의 서버에서 작업시, 패키지가 실행되지 않아 곤란하던 경험들이 다들 있으실 겁니다.
이런 경우에는 Full Path 를 같이 사용하여 어플리케이션을 실행해야 합니다. 하지만, 어디에 설치되었는지 잘 모르겠다 싶은 경우에 패키지 설치 경로를 확인할 필요가 있겠죠? 몇 번 비슷한 상황을 겪을때마다 검색해서 찾았던 내용을 간단하게 정리해 봅니다.
yum 으로 패키지 설치하기
yum 은 Redhat 계열의 운영체제에 기본적으로 탑재되어 있습니다. 설치 방법을 계정 권한에 따라 sudo 를 넣어야 하는가, 그렇지 않은가 정도의 차이만 있고 install [패키지명] 으로 대부분 해결이 됩니다.
$ yum install mtr
혹은
$ sudo yum install mtr
설치된 패키지 확인하기
기존에 설치된 패키지가 있는 경우 install 명령을 이용했을 때, 이미 패키지가 설치되어 있다는 안내를 만나게 됩니다. 주의할 것은 어플리케이션에 따라 버전의 영향을 받는 경우가 종종 있기 때문에 설치된 패키지의 버전을 확인할 필요가 있습니다. 설치된 패키지를 확인하는 명령은 아래와 같습니다.
// 설치된 모든 패키지를 확인
$ yum list | less
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
* epel: d2lzkl7pfhq30w.cloudfront.net
Installed Packages
ConsoleKit.x86_64 0.4.1-6.el6 @anaconda-CentOS-201703281317.x86_64/6.9
ConsoleKit-libs.x86_64 0.4.1-6.el6 @anaconda-CentOS-201703281317.x86_64/6.9
ConsoleKit-x11.x86_64 0.4.1-6.el6 @base
...
// 설치된 특정한 패키지를 확인
$ yum list | grep mtr
mtr.x86_64 2:0.75-5.el6 @anaconda-CentOS-201703281317.x86_64/6.9
mtr-gtk.x86_64 2:0.75-5.el6 base
패키지 설치 경로 확인하기
그런데 문제가 있습니다. 패키지가 설치된 것을 확인헀고 버전까지 알아볼 수 있었지만 실제 어느 경로에 설치되어 있는지는 yum 으로는 알기가 어렵습니다. 이때 사용하는 것이 또 다른 패키지 관련 명령인 rpm 입니다. rpm 은 -q 로 시작하는 명령을 통해 다양한 조회 기능을 제공합니다. 눈치 채셨을 것 같습니다만 -q 는 query 의 앞 글자입니다.
// 설치한 패키지가 실행이 안된다...
$ mtr
-bash: mtr: command not found
// 설치된 모든 패키지를 조회
$ rpm -qa | less
ftp-0.17-54.el6.x86_64
fipscheck-1.2.0-7.el6.x86_64
strigi-libs-0.7.0-2.el6.x86_64
libgcc-4.4.7-23.el6.i686
...
// 특정 패키지로 한정하여 조회
$ rpm -qa | grep mtr
mtr-0.75-5.el6.x86_64
// 특정 문자열을 가진 패키지의 설치 경로를 조회
$ rpm -ql mtr
/usr/sbin/mtr
/usr/share/doc/mtr-0.75
...
// Full Path 로 실행!
$ sudo /usr/sbin/mtr -v
mtr 0.75
결과를 보니 mtr 이 /usr/sbin 경로에 위치한 것을 확인할 수 있었습니다. 보통 /usr/sbin 은 PATH 에 잡혀 있을 가능성이 높습니다만, 환경에 따라 다를 수 있는 부분입니다. 패키지를 설치했는데 실행되지 않는다면, 경로를 조회해서 실행하시기 바랍니다! 자주 써야 한다면 .bash_rc 나 .bash_profile 등에 PATH 환경 변수에 추가해 주면 되겠습니다!
CORS (Cross Origin Resource Sharing) 은 서로 다른 도메인 간에 리소스를 활용할 필요가 있을때, 어떤 규칙으로 누구에게 허용할 것인지를 정의하는 HTTP 표준의 일부입니다. 모던 브라우저들은 CORS 헤더에 대한 지원을 충실히 하고 있습니다만, 서버측에서는 어떤식의 구현이 필요한지, 그리고 커스텀 클라이언트를 사용하는 경우에는 어떤 요청을 보내는 것이 적절한지에 대해 오해도 많고 시행착오도 많습니다.
CORS 에 대한 기본적인 정의를 먼저 살펴보고 CORS 구현을 위한 RFC 규격을 살펴보면서 어떤 요청 헤더와 응답이 필요한지 살펴봄으로써, 혹시나 CORS 에 대하여 시행착오를 겪는 분들이 적어지기를 바라며 포스팅을 시작해 보도록 하겠습니다.
CORS 란 무엇일까?
웹이 태동하고 급성장하던 시기에는 서로 다른 리소스를 가져다 쓰는 것에 대하여 큰 제약이 없었습니다. 하지만 리소스를 사용하는 것은 분명 서버측의 비용이 발생하는 일이고, 보안 관점에서도 접근하는 사용자를 적절히 통제할 필요가 생겼습니다. 이런 요구사항을 수용하기 위하여 정의된 것이 CORS (Cross Origin Resource Sharing, 서로 다른 원본 서버간의 리소스 공유에 관한 규칙) 입니다.
2009년경에 출시된 파이어폭스 Firefox 3.5 와 사파리 Safari 4.0 에서부터 강화된 동일 오리진 정책 SOP (Same Origin Policy) 이 적용되기 시작했고 현재 시장에서 사용되는 대부분의 브라우저는 이 정책을 준수하고 있습니다. 이 즈음부터 XHR (XML Http Request) 을 이용해 서로 다른 원본 서버에서 리소스를 <비동기> 로 가져다 쓰는 것에 대한 혼란(?)이 시작되었다고 봐도 무방합니다.
근래의 브라우저들에서는 Fetch 도 제공하기 시작했고 Fetch 역시 XHR 과 마찬가지로 CORS 의 영향권 아래에 있습니다. 따라서 CORS 에 대한 정확한 이해를 바탕으로 구현을 해야 커머셜 브라우저는 물론이고 커스텀 클라이언트 개발에 대응할 때도 불필요한 시행착오를 줄일 수 있습니다.
브라우저보다 조금 늦게 (늘 그렇듯) 2010년에 Drafting 된 CORS
다른 Origin 에서 리소스를 가져오는 두가지 방법
JSONP 는 논외로 두고 다른 Origin 에서 리소스를 가져오는 방법은 앞서 이야기 한 것처럼 XHR 을 이용한 방식와 Fetch 를 이용한 방식으로 나뉘어 집니다. 많은 자바스크립트 프레임웍 (jquery, axios...) 도 이들을 래핑하고 있기 때문에 동일하게 CORS 규칙의 영향을 받게 됩니다.
비동기로 리소스를 가져오는 방식은 다른 관점에서 보면 단순 요청 Simple Request 와 예비 요청 Pre-flight Request 로 다시 나뉘어 집니다. 이 두가지의 차이점은 간단합니다. 메소드와 헤더에 관한 규격들이 더 있지만, 일단 크게 아래의 구분이 있다는 점을 인식하는 것이 중요합니다.
구분
내용
단순 요청 Simple Request
- GET, POST, HEAD 메소드로 하나의 요청에 필요한 CORS 요청 헤더를 포함하여 전송
예비 요청 Pre-flight Request
- OPTIONS 메소드를 이용하여 본 요청에 대한 스펙을 CORS 요청 헤더를 포함하여 전송 - 성공 응답을 받은 경우 본 요청을 전송
CORS 의 기본, Origin 요청 헤더
앞서 설명한 두 요청의 상세한 차이점은 다음 포스팅에서 소개할까 합니다. 절단 신공이라기 보다는... 두 요청의 공통 요소 중 하나인 Origin 헤더의 규격에 대해서 살펴보고 가는 것이 더 중요하기 때문입니다. 다른 Origin 으로 리소스를 요청하는 경우, 원래의 요청이 어떤 도메인에서 시작된 것인지를 다른 Origin 으로 알려주어야 할 필요가 있습니다. 이 때 사용하는 것이 Origin 요청 헤더입니다.
이 요청을 받은 두번째 서버(b-server)는 Origin 값에 해당하는 정책을 확인하여 이를 CORS 응답 헤더로 내려주게 됩니다. 이 과정에서 Origin 헤더 값이 사전에 약속된 원본 도메인이 아니라면 에러 응답을 하거나 CORS 헤더 없이 응답하게 되어 결과적으로 브라우저에서는 응답을 사용하지 못하는 상황이 되게 됩니다.
출처 : 모질라 CORS 문서
그런데 말입니다, 모질라의 CORS 문서에서 발췌한 위의 내용은 한가지가 잘못되어 있습니다. RFC 의 규격 문서에 따르면 Origin 헤더의 값은 반드시 스킴 Scheme (http 혹은 https) 을 포함해야만 합니다. 위의 그림처럼 `Origin: foo.example` 로 던지면 규격에 대한 위반이 되게 됩니다. 왜냐하면 http://foo.example 과 https://foo.example 은 서로 다른 Origin 으로 활용될 수 있기 때문입니다. WHATWG 의 규격 문서를 보면 이 헤더의 규격은 아래와 같습니다.
특정한 포트를 지정해주는 ":port" 는 필요 없는 경우 생략해 줄 수 있지만, 스킴은 생략 가능한 항목으로 명기되어 있지 않습니다. 따라서 Origin 요청 헤더는 위의 규격을 준수하여 전송할 필요가 있습니다. 모질라의 문서 그림도 업데이트가 되어야 하겠죠? ^^ 이렇게 Origin 헤더가 중요합니다.
다행히도 근래의 모던 브라우저들은 CORS 요청을 하는 경우 항상 스킴을 포함한 Origin 요청 헤더를 보내주고 있습니다. 따라서 Origin 헤더 값은 상용 브라우저가 아닌 클라이언트를 사용하는 경우에 유의해 주시면 큰 문제는 발생하지 않을 것으로 생각됩니다. 다음 포스팅에서는 Simple Request 와 Pre-flight Request 의 요건에 대하여 보다 자세히 살펴보도록 하겠습니다.
Cloud Platform 을 사용할 때 가장 조심해야 하는 것 중 하나가, 각 플랫폼이 가지고 있는 QoS (Quality of Service) 수치를 넘지 않도록 해야 한다는 것입니다. 물론, 이 수치는 Support Ticket 등을 통해 늘리는 것이 가능하지만 시간이 소요될 수 있기 때문에 이벤트 등 대규모 사용자가 몰리는 이벤트가 준비중이라면 미리 체크를 해두어야 합니다.
CDN 제품인 AWS CloudFront 도 마찬가지인데요, 적용되고 있는 여러가지 제한 중 이벤트 트레픽에 대한 고려사항은 크게 1) 대역폭에 대한 Limit 과 2) 요청수에 대한 Limit 이 있습니다. AWS 공식 문서에서는 `할당량` 또는 `Quotas` 로 제품 문서에서 확인할 수 있는 내용입니다.
대역폭과 전송량 제한
CloudFront 의 할당량 정책은 기본적으로 Distribution 당으로 적용됩니다. 참고로 시장 지배 사업자인 아카마이 Akamai 의 경우 Bucket 이라는 컨셉이 있고 CP Code 단위로 대역폭에 대한 관리만 하고 있습니다. 아카마이와 달리 CloudFront 의 경우 대역폭과 요청량의 두가지 제한이 있습니다.
출처 : CloudFront 개발자 안내서
Distribution 을 `배포` 라고 표현하고 있는 부분은 늘 적응이 잘 안되네요. API 에서도 distid 등을 사용하니 Distribution 으로 인지하는 것이 편합니다. 공식 문서에 나온 것처럼 대역폭은 150Gbps 가 기본 제한이고 요청량은 250,000rps 가 기본 제한으로 들어가 있습니다. 바로 아래에 있는 `더 높은 할당량 요청`이 있는 이유는 조정이 가능하기 때문이겠죠? ^^
`더 높은 할당량 요청`을 누르면 Support 페이지로 넘어가고 `Service Limit Increase` 타입의 티켓을 열어 할당량을 높이는 방식입니다. 느낌이 오시겠지만 시간이 좀 걸릴 수 있는 부분이라 예측하지 못한 트레픽 Burst 가 아니고 계획된 이벤트라면 미리 할당량을 조정해 두시는 것이 정석입니다.
할당량 초과는 어떻게 알 수 있을까?
CloudFront 에서는 위의 할당량이 초과 되었다 하더라도 알려주는 것은 없습니다. 요행히 CloudWatch 로 Distribution 의 에러 비율에 대한 알람을 걸어두었다면 메일을 통하여 한템포 늦게 인지할 수 있는 방법이 있긴 합니다. 다른 방법으로는 CloudFront 의 Monitoring 화면에서 사용자의 트레픽이 급격히 늘면서 5xx 에러가 증가했는지를 확인하는 방법이 있습니다.
후행적으로 확인하는 방법은 (이미 장애는 났고... 사용자는 영향을 받았고...) CloudFront 의 Access Log 를 통하는 방법이 있습니다. Access Log 의 필드중 2020년 12월 3일 기준으로 14번째 컬럼인 `x-edge-result-type` 이나 23번째 컬럼인 `x-edge-response-result-type` 의 값을 이용해서 확인할 수 있습니다.
14번째 컬럼의 값23번째 컬럼의 값
이 필드의 값으로 `LimitExceeded` 가 특히 할당량, Limit 초과에 대한 부분입니다. 문제는 LimitExceeded 가 어떤 Limit 을 초과한 것인지를 알려주지 않습니다. 알고 싶다면 <또> Support Ticket 을 열어야 합니다. 해보신 분들은 아시겠지만 Ticket 을 열면서 꼭 샘플 로그를 추출해서 제공해 주셔야 합니다.
용량관리는 인프라에서 무척 중요한 부분입니다. 우리가 클라우드 서비스를 이용하는 이유중 하나는 그런 용량 관리로부터 조금이나마 자유롭고 싶어서 이지만, 결국 클라우드 서비스도 그들 입장에서는 용량관리를 해야만 합니다. 때문에 위와 같은 제한들이 존재하고 사용하고 있는 사업자의 숫자들을 기억해 둘 필요가 있습니다.
VPN 과 관련한 여러가지 시험, 환경을 구축하다보니 로컬 라우팅 테이블이 꼬이는 현상이 발생하여 조사를 해보았습니다. 평소 사용하고 있던 IPv4 VPN 와 IPv6 VPN, 그리고 개별 과제로 만들고 있는 OpenVPN 기반의 IPv6 까지 아주 난장판이라 이런 문제가 생긴다고 생각해서 트러블슈팅 방법을 좀 정리해 보고자 합니다. (미래의 내가, 과거의 나를 찾을 것이 분명하니...)
지저분해지는 IPv6 라우팅 테이블
안그래도 복잡했던 로컬 IPv6 라우팅 테이블이 심하게 꼬인 것은 로컬 환경에서 OpenVPN Web UI 디버깅을 위해 OpenVPN 을 설치하고 구동하면서 부터였습니다. 오늘 아침 개발조직에 IPv6 접근 가이드를 해주기 위해 WIKI 를 정리하다보니 평소 사용하던 IPv6 VPN 에 연결하더라도 v6 웹 사이트 (가령 v6.google.com) 에 접근이 안되는 것을 확인했습니다.
미처 캡쳐를 해두진 못했지만 netstat -nr 로 로컬의 라우팅 테이블을 살펴보니 스태틱으로 잡힌 테이블이 너무 많았습니다. VPN 연결시 생성되는 인터페이스인 utun 시리즈도 무려 6개나 존재하더군요. 인터페이스를 down 으로 하는 것과 라우팅 테이블은 별개라 한땀 한땀 삭제를 해주어야 했습니다. 사용한 명령들은 대략 아래의 패턴입니다.
// 한 땀, 한 땀 삭제...
sudo route delete -inet6 ##v6주소##%utun0
// default 를 잠식한 utun 시리즈 삭제는 -ifscope 으로...
sudo route delete -inet6 default -ifscope utun1
이렇게 삭제를 하고나니 라우팅 테이블이 깔끔해졌습니다. 이제 라우팅 테이블을 지저분하게 만든 범인을 찾기 위해 간단한 스크립트로 리눅스 환경에서의 watch 를 구현하여 netstat -nr 명령을 반복하도록 해보았습니다. 우리가 기대하는 것은 VPN 연결시 필요한 라우팅 테이블이 추가 되었다가 VPN 연결을 종료하면 라우팅 테이블이 정리되는 것이겠죠!?
// Mac 환경에서 리눅스 watch 스타일로 명령 구동하기
while true; do clear; netstat -nr; sleep 2; done;
회사가 제공한 VPN 시험
먼저 회사가 제공한 IPv6 VPN 을 살펴보았습니다. 심증은 <범인은 OpenVPN 이다!> 였지만 확실하게 하기 위해서죠. 개발팀도 분명 비슷한 증상을 겪을 수 있으니 FAQ 를 준비하는 목적도 있었습니다. 자, 우선 IPv6 VPN 연결전에는 아래와 같이 깔끔한 라우팅 테이블 목록을 볼 수 있습니다. 물론... 앞서 이야기 한 것처럼 한 땀, 한 땀 라우팅 테이블을 정리한 상태입니다 ㅜㅜ
회사에서 셋업한 IPv6 VPN 을 연결해 보니 utun 인터페이스로 다수의 라우팅 테이블이 추가되는 것을 확인할 수 있었습니다.
다시 VPN 연결을 끊었을때 v4, v6 쪽으로 추가된 라우팅 테이블이 깔끔하게 정리되는 것을 확인할 수 있었습니다. 범인은 OpenVPN 일까요? 확인해 보았습니다.
AWS 에 구축한 IPv6 OpenVPN 시험
이번에는 AWS 에 구축해 둔 IPv6 OpenVPN 을 시험해 보았습니다. VPN 에 연결되면 이전의 다른 VPN 과 마찬가지로 다량의 라우팅 테이블이 추가되는 것을 확인할 수 있었습니다. 이번에도 동일하게 utun4 를 사용했군요. 터널 인터페이스가 만들어지고 삭제되는 과정도 좀 궁금하지만 따로 알아보기로 하고...
자 이제... 대망의 연결 종료의 시간이 되었습니다. OpenVPN 연결을 종료했을때 깔끔하게 라우팅 테이블이 정리되었으면 하는 바램을 갖고... 도전!
이런... 예상과 다르게 너무 깔끔하게 라우팅 테이블이 정리가 되었습니다. 문제가 생기길 기대(?)했는데 깔끔해진 걸 보니... 뭔가 OpenVPN 에 등록해 둔 Profile 들을 시험하는 과정에, 연결이 깔끔하지 못했거나 강제 종료된 경우 등 예외 상황에서 문제의 현상이 나오는 것일 가능성이 생겼습니다.
AWS EC2 를 이용한 OpenVPN 구축 연재는 아래 글타래로... (2편은 아직 못쓴...)
내친김에 로컬 환경의 시험도 해보았습니다. 조금 까리한 것은 로컬에서는 초기에 proto udp 로 시험하다보니 AF_INET6 로 서버가 구동되는 문제가 있어서 proto udp4 로 설정해둔 상태였습니다. 만약, 이 상태에서도 문제가 없다면 proto udp 일때 AF_INET6 로 구동되는 과정, 종료되는 과정의 문제라고 생각해도 될 것 같았습니다.
참고로 utun4 는 로컬의 OpenVPN 서버가 점유하고 있는 터널이고, utun7 은 로컬의 Tunnelblick 이 연결을 맺으면서 생성한 인터페이스입니다. 자, 이제 연결을 끊어보겠습니다.
오오... 찾은 것 같습니다. Tunnelblick 종료시 utun7 이 빠졌고, OpenVPN 서버 종료시 utun4 가 빠졌지만, Internet6 쪽에 추가된 스태틱 라우팅 하나가 빠지지 않은 것을 확인할 수 있었습니다. 설정의 문제인지는 조금 더 조사해 봐야하고 로컬 환경에서만 생기는 문제인지 명확하진 않습니다만, 최소한 FAQ 에 기술해두고 개발자 분들께 가이드 하는데는 문제 없을것 같습니다.
뭔가 완전히 잘 알지 못하는 분야는 늘 시행착오가 생기는 것 같습니다. 오늘도 몇 가지 시행착오를 겪으면서 한 걸음, 한 걸음, 뚜벅 뚜벅 걸어나가 봅니다!