2024. 3. 17. 19:19ใAWS/troubleshooting
๊ฐ์
As-is
- DNS : AWS Route53์ ์ด์ฉํ์ฌ “example.com”์ด๋ผ๋ public hosted zone ์๋น์ค ์ค.
- ๋คํธ์ํฌ : On-Premise์ AWS๋ Direct Connect๋ก ์ฐ๊ฒฐ๋์ด ๋ฌธ์ ์์ด ํต์ ์ค.
Problem
- On-Premise์์ ์ ๊ทผํ๋ ๋ด๋ถ ์ง์ ๋ฐ ํผ๋ธ๋ฆญ์ ์ธ๋ถ ์ง์์ด ๊ณตํต์ผ๋ก ์ ์ํ๋ ์น ์๋ฒ๊ฐ ์กด์ฌ.
- public hosted zone์์ ๋ ์ฝ๋๊ฐ ๋ฑ๋ก๋์ด, ๋ด๋ถ ์ง์์ direct conenct๋ก ์ฐ๊ฒฐ๋์ด ์์์๋ ๋ถ๊ตฌํ๊ณ ์ธํฐ๋ท์ ํตํด ์ธ๋ถ๋ง์ ๋๊ฐ๋ค๊ฐ AWS๋ก ๋ค์ด์ด. ๋ถํ์ํ ๋คํธ์ํฌ ์ค๋ฒํค๋ ๋ฐ์.
To-Be
- ์ธ๋ถ ์ง์์ ํผ๋ธ๋ฆญ์์๋ ๋ฌธ์ ์์ด ์น ์๋ฒ์ ์ ์ํ๋, ๋ด๋ถ ์ง์์ ๋ด๋ถ๋ง์ ์ด์ฉํ์ฌ Direct Connect๋ฅผ ํตํด ์น ์๋ฒ์ ์ ์ ํ์.
- ์ด๋ฅผ ์ํด ๋์ผํ ๋๋ฉ์ธ์ ๋ํด ์ธ๋ถ/๋ด๋ถ ์ก์ธ์ค ๋ถ๋ฆฌ ํ์ (Split-View DNS).
Split-Horizon DNS๋? (= split dns = split-view dns)
๋ด๋ถ/์ธ๋ถ ๋คํธ์ํฌ์ ๋ฐ๋ผ DNS ์ ๋ณด๋ฅผ ๋ถ๋ฆฌํ๋ DNS ๊ตฌ์ฑ. ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ํด๋ผ์ด์ธํธ์ ๋คํฌ์ํฌ์ ๋ฐ๋ผ ๋์ผํ ๋๋ฉ์ธ์ด private ip ๋๋ public ip๋ฅผ ์ถ๋ ฅํ๋ค. ์ด๋ฅผ ํตํด ๋ก์ปฌ ํด๋ผ์ด์ธํธ ์์คํ ์ด ์ธํฐ๋ท์ ํต๊ณผํ ํ์ ์์ด ๋ก์ปฌ ๋คํธ์ํฌ๋ฅผ ํตํด ์ง์ ์๋ฒ์ ์ก์ธ์คํ ์ ์์ผ๋ฉฐ, ๋ ์ ์ ์์ ๋คํธ์ํฌ ์ฅ์น๋ฅผ ํต๊ณผํ๋ฉด์ ๋คํธ์ํฌ ๋๊ธฐ ์๊ฐ์ด ํฅ์๋๋ค.
Route53์ ์ด์ฉํ Split-Horizon DNS ๊ตฌ์ฑ
Route53์ ์ด์ฉํ์ฌ Split-view DNS๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค. ๋์ผํ ์ด๋ฆ์ public / private hosted zone์ ๊ตฌ์ฑํ๊ณ , ๊ฐ ํธ์คํ ์์ญ์์ ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค. public hosted zone์ ๋ ์ฝ๋๋ ์ธํฐ๋ท ํธ๋ํฝ์ด ๋ผ์ฐํ ๋๋ ๋ฐฉ๋ฒ์ ์ ์ดํ๊ณ , private hosted zone์ ์ฐ๊ฒฐ๋ VPC (๋ด๋ถ๋ง)์์ ๋ผ์ฐํ ๋๋ ๋ฐฉ๋ฒ์ ์ ์ดํ๋ค.
๐จ ์ฃผ์ ๐จ
๋จ, VPC(๋ด๋ถ๋ง)์์ ์ฟผ๋ฆฌ ์ ์ผ์นํ๋ private hosted zone์ด ์์ง๋ง ์์ฒญํ ๋๋ฉ์ธ ์ด๋ฆ ๋ฐ type์ด ์ผ์นํ๋ ๋ ์ฝ๋๊ฐ ์๋ ๊ฒฝ์ฐ Resolver๋ ์์ฒญ์ public DNS resolver๋ก ์ ๋ฌํ์ง ์๋๋ค. ๊ทธ ๋์ NXDOMAIN ์ค๋ฅ๋ฅผ ๋ฆฌํดํ๋ค.
ex) ์๋์ ๊ฒฝ์ฐ private hosted zone์ ์ฐ๊ฒฐ๋ VPC์์ “aaa.example.com” ์ฟผ๋ฆฌ ์ NXDOMAIN ๋ฆฌํด.
- private hosted zone “example.com” ๋ด “aaa.example.com”์ A type ๋ ์ฝ๋ ์์.
- public hosted zone “example.com” ๋ด “aaa.example.com”์ A type ๋ ์ฝ๋ ์กด์ฌ.
Split-Horizon DNS vs. Route53 IP ๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฑ
Client IP๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋๋ฉ์ธ์ ๋ผ์ฐํ ํ๋ค๋ ๊ฐ๋ ์ ๋์ผํ๋ค. Route53์ IP๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฑ ์ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ ์ฃผ์๊ฐ ์ํ CIDR ๋ธ๋ก(์๋ธ๋ท)์ ๊ธฐ๋ฐ์ผ๋ก DNS ๋ผ์ฐํ ์ ๋ฏธ์ธ ์กฐ์ ํ ์ ์์ผ๋ Public hosted zone์์๋ง ์ ์ฉํ ์ ์๋ค. ์ ์ด ๋ฒ์ ๋ด์ Resolver์์ ์ฟผ๋ฆฌํ๋์ง์ ์ฌ๋ถ์ ๋ฐ๋ผ ํธ๋ํฝ์ ์ ๋ฌํ๋ ๊ฒฝ์ฐ, Split Horizon DNS๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ์ฆ, Resolver๋ฅผ ์ ์ดํ ์ ์๋ CIDR ๋ธ๋ก์ ๋ํด IP-based Routing Policy๋ฅผ ์ด์ฉํ๋ค.
Route53์ IP ๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฑ ์ ์ด์ฉํ๋ฉด "๋ด๋ถ๋ง"์ผ๋ก ์ ์๋๋ ๋์ญ์ด ์ถ๊ฐ/์ญ์ ๋๋ฉด Route53 Location(CIDR ๋ธ๋ก)์ ์ถ๊ฐ/์ญ์ ํ๋ ๊ด๋ฆฌ point๊ฐ ๋ฐ์ํ๋ค. Route53 Private/Public hosted zone & AD DNS ๋ฑ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ ํด๋ผ์ด์ธํธ๊ฐ ์๋ณ ๊ฐ๋ฅํ๊ณ ๊ฐ Resolver๊ฐ ๊ด๋ฆฌ ๋ฒ์ ๋ด์ ์์๊ธฐ ๋๋ฌธ์ R53์ IP ๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฑ ๋์ Split-Horizon DNS ๊ตฌ์ฑ์ ์ ํํ์๋ค. ๋น์ฉ์ ์ธ ์ธก๋ฉด์์๋ Split-Horizon DNS๊ฐ ์ ๋ฆฌํ๋ค. (2024.03 ๊ธฐ์ค)
R53 Split-Horizon DNS ์ ์ฉ ๋ฐฉ๋ฒ
hosted zone์ ๋ค๋ฅธ AWS ๊ณ์ ์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ด๋ํ๋ AWS์ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ฌ Split-Horizon DNS๋ฅผ ์ ์ฉํ์๋ค.
1. (์ฌ์ ์์ ) ๊ธฐ์กด public hosted zone์ ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ๋ค์ด๋ก๋
private hosted zone์ด ์์ฑ๋๋ ์๊ฐ๋ถํฐ ๋์ด์ public hosted zone์ ์ฐธ์กฐํ์ง ์๊ธฐ ๋๋ฌธ์ public์ ๋ชจ๋ ๋ ์ฝ๋๋ฅผ private์ ์ฝ์ ํ๊ธฐ ์ํด AWS CLI๋ฅผ ์ด์ฉํ์ฌ ํ์ผ๋ก ๋ค์ด๋ฐ์๋ค.
aws route53 list-resource-record-sets --hosted-zone-id {$public-hosted-zone} > ./hostedZone.json
2. (์ฌ์ ์์ ) 1์ ๋ ์ฝ๋ ํ์ผ์ ๋ณํ
๋์ผํ ์ด๋ฆ์ private hosted zone์ด ์์ฑ๋๊ณ ํด๋น zone์ ์ํ๋ ๋ ์ฝ๋๊ฐ ์์ผ๋ฉด nxdomain ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. nxdomain ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ์๊ฐ์ ์ต์ํํ๊ธฐ ์ํด hostedZone.json์ ์ฝ์ ํ๊ธฐ ์ข์ ํํ์ ํ์ผ(createHostedZone.json)์ผ๋ก ๋ณํํ๋ค.
(1) SOA, NS ๋ ์ฝ๋๋ฅผ ์ญ์
(2) AWS CLI " aws route53 change-resource-record-sets" ๋ฅผ ์ํํ๊ธฐ ์ํ ํํ๋ก ๋ณํ
import json
# ์ฃผ์ด์ง JSON ๋ฐ์ดํฐ
with open('./hostedzone.json', 'r') as f:
input_json = json.load(f)
# ๋ณํํ JSON ํ์
output_json = {
"Comment": "string",
"Changes": []
}
# ๊ธฐ์กด ๋ ์ฝ๋ ๊ฐ์
print('๊ธฐ์กด ๋ ์ฝ๋ ๊ฐ์: ', len(input_json["ResourceRecordSets"]))
# ๋ณํ ์์
์ํ
for record_set in input_json["ResourceRecordSets"]:
# Type์ด "SOA" ๋๋ "NS"์ธ ๊ฒฝ์ฐ ์ญ์
if record_set["Type"] in ["SOA", "NS"]:
continue
else:
# ๊ทธ ์ธ์ ๊ฒฝ์ฐ๋ ๋ณํ ์์
์ํ
change = {
"Action": "CREATE",
"ResourceRecordSet": record_set
}
output_json["Changes"].append(change)
print('๋ณํ ํ ๋ ์ฝ๋ ๊ฐ์: ', len(output_json["Changes"]))
# ๋ณํ๋ JSON์ ํ์ผ๋ก ์ ์ฅ
output_file_path = "createHostedZone.json"
with open(output_file_path, "w") as output_file:
json.dump(output_json, output_file, indent=2)
3. ์ ๊ท private hosted zone ์์ฑ ๋ฐ ์ผ๊ด ๋ ์ฝ๋ ์ฝ์
๋์ผํ ์ด๋ฆ์ private hosted zone์ ์์ฑํ๊ณ ์์ฑ๋ hosted zone์ ์๋ AWS CLI๋ฅผ ์ด์ฉํด ๋ ์ฝ๋๋ฅผ ์ผ๊ด ์ฝ์ ํ๋ค. ์ฝ 300๊ฐ์ ๋ ์ฝ๋ ๊ธฐ์ค ์ํ ์๊ฐ์ด 30์ด๋ ์ฑ ๊ฑธ๋ฆฌ์ง ์๋๋ค. ๋ํ A ํ์ ์ Alias ๋ ์ฝ๋๋ ๋์ผํ๊ฒ ์ ์ฝ์ ๋๋ค.
private hosted zone ์์ฑ ์, nxdomain ์ค๋ฅ ์๊ฐ์ ์ต์ํํ๊ธฐ ์ํด ํ๋์ VPC๋ง ์ฐ๊ฒฐํ์์ผ๋ฉฐ, 5๋ฒ ๊ณผ์ ๊น์ง ์ํ ํ ๋๋จธ์ง VPC๋ฅผ ๋ชจ๋ ์ฐ๊ฒฐํ์๋ค.
aws route53 change-resource-record-sets --hosted-zone-id {$private-hosted-zone} --change-batch file://./createHostedZone.json
4. (์ ํ) public hosted zone(1)๊ณผ private hosted zone(3)์ ๋ ์ฝ๋๊ฐ ๋์ผํ์ง ๊ฒ์ฆ
3์์ ์์ฑํ ์ ๊ท private hosted zone๊ณผ ๊ธฐ์กด์ public hosted zone์ ๋ ์ฝ๋๊ฐ ๋์ผํ์ง ๊ฒ์ฆํ๋ค. ์๋ AWS CLI๋ฅผ ์ด์ฉํ์ฌ private hosted zone ๋ ์ฝ๋๋ฅผ ํ์ผ๋ก ๋ค์ด๋ก๋ํ๋ค.
aws route53 list-resource-record-sets --hosted-zone-id {$private-hosted-zone} > ./privateHostedZone.json
์๋ ํ์ด์ฌ ์ฝ๋๋ฅผ ํตํด ๋์ผํ ๊ฐ์ธ์ง ํ์ธํ์๋ค.
import json
def compare_json_files(file_path_a, file_path_b):
try:
with open(file_path_a, 'r', encoding='utf-8') as file_a, open(file_path_b, 'r', encoding='utf-8') as file_b:
data_a = json.load(file_a)
data_b = json.load(file_b)
filtered_data_a = {
"ResourceRecordSets": [record for record in data_a["ResourceRecordSets"] if record["Type"] not in ["NS", "SOA"]]
}
filtered_data_b = {
"ResourceRecordSets": [record for record in data_b["ResourceRecordSets"] if record["Type"] not in ["NS", "SOA"]]
}
if filtered_data_a == filtered_data_b:
print("๋ JSON ํ์ผ์ ๋์ผํฉ๋๋ค.")
else:
print("๋ JSON ํ์ผ์ ๋ค๋ฆ
๋๋ค.")
except FileNotFoundError:
print("ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค.")
except json.JSONDecodeError as e:
print(f"JSON ๋์ฝ๋ฉ ์ค๋ฅ: {e}")
except Exception as e:
print(f"์ค๋ฅ ๋ฐ์: {e}")
file_path_A = './hostedZone.json'
file_path_B = './newHostedZone.json'
compare_json_files(file_path_A, file_path_B)
5. private hosted zone์์ ๋ถ๋ฆฌ๊ฐ ํ์ํ ๋ ์ฝ๋ ๊ฐ ์์
๋ณธ ํฌ์คํ ์ ๊ฒฝ์ฐ, private hosted zone์ ๋ ์ฝ๋ ๊ฐ์ ์์ ํ์ฌ abc.example.com์ ๊ฐ์ด ๊ฐ๊ฐ ์๋์ ๊ฐ์ด ๋ฑ๋ก๋์๋ค.
- public hosted zone : internet-facing NLB ์๋ํฌ์ธํธ (Aํ์ Alias)
- private hosted zone : internal ALB ์๋ํฌ์ธํธ (Aํ์ Alias)
6. AD ์กฐ๊ฑด๋ถ ์ ๋ฌ์ ์ค์
AD DNS๋ฅผ ๋ฐ๋ผ๋ณด๋ ์จํ๋ ์๋ฒ์์ ๊ธฐ์กด์ฒ๋ผ "example.com"์ public์ผ๋ก ์ฟผ๋ฆฌํ์ง ์๊ณ privateํ๊ฒ ์ฟผ๋ฆฌํ๊ณ ๋ด๋ถ๋ง์ ํตํด ํต์ ๋๋๋ก ์กฐ๊ฑด๋ถ ์ ๋ฌ์๋ฅผ ์ค์ ํ์๋ค. AD DNS์ ์กฐ๊ฑด๋ถ ์ ๋ฌ์๋ฅผ ๋ฑ๋กํ์๋ง์ ์ ํ์ ์์๋๋ ์๊ฐ ์์ด ์ฆ์ Route53์ private hosted zone์ผ๋ก ์ฟผ๋ฆฌํ์๋ค. (๊ธฐ์กด์ ์ฟผ๋ฆฌํ์ฌ TTL ๋งํผ์ ์บ์๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ ์ ์ธ)
Route53 ๋ด AD DNS์ ํต์ ํ๋ inbound endpoint ์ด๋ฏธ ์กด์ฌํ์ฌ ํด๋น ๋ด์ฉ์ ์๋ตํ์ง๋ง ์ต์ด ํต์ ํ๋ ๊ฒฝ์ฐ์๋ R53 inbound endpoint ์์ฑ ๋ฐ ๋คํธ์ํฌ ๊ตฌ์ฑ, ๋ณด์๊ทธ๋ฃน ๊ท์น ์ค์ ๋ฑ์ ๊ณผ์ ์ด ํ์ํ๋ค.