Infra/cloud

[AFOS] 7주차 네트워크 서비스(ELB) - 실습 : ALB

미니문92 2021. 7. 27. 03:29

3. ALB (Application Load Balancer) 

구축 구성도

  • CloudFormation 스택 생성 - 링크 클릭 후 템플릿 파일로 기본 환경 자동 배포
    • 파라미터(KeyName - 자신의 SSH 키 선택) 다음 클릭 → 다음 클릭 → 스택 생성 클릭

배포 후 기본 환경 도식화

 

SNMP(Simple Network MAnagement Protocol) : 네트워크 관리를 위한 규약

  • OID(Object Identifier)라는 값을 호출하여 디바이스에 대한 정보 파악 가능

Linux OS에 snmpget의 수집할 수 있는 OID 정보 참고 

  • sysDescr 장비에 대한 설명 정보이며, Vendor에 따라 사이즈의 차이가 있으며 장비정보 출력 시 부가정보로 출력 : 1.3.6.1.2.1.1.1.0 - sysDescr
  • sysObjectID 장비의 고유한 ID값을 리턴 하며, 해당 값을 이용하여, 장비의 Vendor, 장비 종류를 고유하게 관리 : 1.3.6.1.2.1.1.2.0 - sysObjectID
  • sysUpTime 장비가 부팅되어 현재까지 동작한 milli-second 값이며, 쿼리 시 업데이트 되는 정보
    : 1.3.6.1.2.1.1.3.0 - sysUpTime
  • sysName 사용자가 장비에 설정한 장비명 이며, 설정하지 않았을 경우 Null 결과값을 출력. Null 값 출력시 해당 장비명 출력은 IP Address, 혹은 장비 Alias 명 : 1.3.6.1.2.1.1.5.0 - sysName

 

SNMP

더보기

 

SNMP 데이터 수집 방식
  • 정의 : IP 네트워크상의 장치로부터 정보를 수집, 관리하고 정보를 수정하여 장치 동작을 변경하는 데에 사용되는 인터넷 표준 프로토콜
  • 이를 활용하여 실제 네트워크 관리 정보를 얻기 위해 관련 프로그램(NMS) 필요
  • 시스템, 네트워크 관리자로 하여금 원격으로 네트워크 장비 모니터링, 환경설정 등을 가능하게 하는 네트워크 관리 프로토콜

MIB

  • Management Information Base : 관리정보 기반
  • 어떤 장비에서 SNMP를 통해 네트워크를 관리할 때 관리되어야 할 특정한 정보나 자원을 객체라고하고 그 객체들을 모아놓은 집합체가 MIB
  • 지속적인 관리가 필요한 장비에 대해 MIB 중 특정 값을 얻어와 그 상태를 파악하기 위한 용도

 

OID

  • Object ID : 객체 아이디
  • MIB 집합체에 정의되어 있는 객체들을 컴퓨터가 알아볼 수 있도록 정수로 나열된 숫자로 분류된 값

 

=> Network 에서 추가 정리 필요

  • 기본 환경 검증 : My-EC2 에서 ELB-EC2-1 과 ELB-EC2-2 로 HTTP서비스와 SNMP서비스를 확인
# ELB-EC2-1
[ec2-user@ELB-EC2-1 ~]$ sudo su -

# 디렉터리(폴더) 트리 구조 출력 
[root@ELB-EC2-1 ~]# tree /var/www/html
/var/www/html
├── dev
│   └── index.html
├── index.html
└── xff.php
cat /var/www/html/xff.php

# ELB-EC2-2
[ec2-user@ELB-EC2-2 ~]$ sudo su -
[root@ELB-EC2-2 ~]# tree /var/www/html
/var/www/html
├── index.html
├── mgt
│   └── index.html
└── xff.php
cat /var/www/html/xff.php
  • xff.php 파일
[root@ELB-EC2-1 ~]# cat /var/www/html/xff.php
AFOS Test Page 입니다 !
    _    _____ ___  ____    _____         _     ____
   / \  |  ___/ _ \/ ___|  |_   _|__  ___| |_  |  _ \ __ _  __ _  ___
  / _ \ | |_ | | | \___ \    | |/ _ \/ __| __| | |_) / _` |/ _` |/ _ \
 / ___ \|  _|| |_| |___) |   | |  __/\__ \ |_  |  __/ (_| | (_| |  __/
/_/   \_\_|   \___/|____/    |_|\___||___/\__| |_|   \__,_|\__, |\___|
                                                           |___/

<?php
date_default_timezone_set("Asia/Seoul");
Print(date(DATE_RFC822));
echo "\n";
echo "\n";
$idleCpu = exec('vmstat 1 2 | awk \'{ for (i=1; i<=NF; i++) if ($i=="id") { getline; getline; print $i }}\'');
echo "Current CPU Load:";
echo 100-$idleCpu;
echo "%";
echo "\n";
echo "\n";
header('Content-Type: text/plain');
echo "Last Client IP: ".$_SERVER['REMOTE_ADDR'];
echo "\nServer Public IP = ".$_SERVER['HTTP_HOST'];
echo "\nServer Private IP: ".$_SERVER['SERVER_ADDR'];
echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR'];
#echo "\nDNS name used by client = ".$_SERVER['SERVER_NAME'];
?>
  • My-EC2에서 확인
[ec2-user@MyEC2 ~]$ EC21=15.165.18.45
[ec2-user@MyEC2 ~]$ EC22=54.180.112.69
[ec2-user@MyEC2 ~]$
[ec2-user@MyEC2 ~]$ curl $EC21
<h1>ELB-EC2-1 Web Server</h1>
[ec2-user@MyEC2 ~]$ curl $EC21/xff.php;echo
AFOS Test Page 입니다 !
    _    _____ ___  ____    _____         _     ____
   / \  |  ___/ _ \/ ___|  |_   _|__  ___| |_  |  _ \ __ _  __ _  ___
  / _ \ | |_ | | | \___ \    | |/ _ \/ __| __| | |_) / _` |/ _` |/ _ \
 / ___ \|  _|| |_| |___) |   | |  __/\__ \ |_  |  __/ (_| | (_| |  __/
/_/   \_\_|   \___/|____/    |_|\___||___/\__| |_|   \__,_|\__, |\___|
                                                           |___/

Tue, 27 Jul 21 02:58:31 +0900

Current CPU Load:0%

Last Client IP: 13.124.88.91
Server Public IP = 15.165.18.45
Server Private IP: 10.0.0.202
X-Forwarded-for:
[ec2-user@MyEC2 ~]$ curl $EC21/dev/
<h1>ELB-EC2-1 Dev Web Page</h1>
[ec2-user@MyEC2 ~]$ snmpget -v2c -c public $EC21 1.3.6.1.2.1.1.5.0
SNMPv2-MIB::sysName.0 = STRING: ELB-EC2-1
[ec2-user@MyEC2 ~]$ snmpget -v2c -c public $EC21 1.3.6.1.2.1.1.3.0
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (16242) 0:02:42.42
[ec2-user@MyEC2 ~]$
[ec2-user@MyEC2 ~]$ curl $EC22
<h1>ELB-EC2-2 Web Server</h1>
[ec2-user@MyEC2 ~]$ curl $EC22/xff.php;echo

AFOS Test Page 입니다 !
    _    _____ ___  ____    _____         _     ____
   / \  |  ___/ _ \/ ___|  |_   _|__  ___| |_  |  _ \ __ _  __ _  ___
  / _ \ | |_ | | | \___ \    | |/ _ \/ __| __| | |_) / _` |/ _` |/ _ \
 / ___ \|  _|| |_| |___) |   | |  __/\__ \ |_  |  __/ (_| | (_| |  __/
/_/   \_\_|   \___/|____/    |_|\___||___/\__| |_|   \__,_|\__, |\___|
                                                           |___/

Tue, 27 Jul 21 02:58:39 +0900

Current CPU Load:0%

Last Client IP: 13.124.88.91
Server Public IP = 54.180.112.69
Server Private IP: 10.0.1.39
X-Forwarded-for:
[ec2-user@MyEC2 ~]$ curl $EC22/mgt/
<h1>ELB-EC2-2 Mgt Web Page</h1>
[ec2-user@MyEC2 ~]$ snmpget -v2c -c public $EC22 1.3.6.1.2.1.1.5.0
SNMPv2-MIB::sysName.0 = STRING: ELB-EC2-2
[ec2-user@MyEC2 ~]$ snmpget -v2c -c public $EC22 1.3.6.1.2.1.1.3.0
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (16892) 0:02:48.92

ALB 생성

기본 구성

  • 이름(ALB-TEST), 인터넷 경계
  • 리스너 : 프로토콜(HTTP), 포트(80)
  • 가용 영역 : ELB-VPC, 2a 와 2c 선택

보안 설정 구성 : skip

보안 그룹 구성 : 기존보안그룹 (###-ELBSG-### , TCP 80, 22 허용) 선택

라우팅 구성

  • 대상 그룹(새 대상 그룹), 이름(ALB-TG), 대상 유형(인스턴스), 프로토콜(HTTP), 포트(80)
  • 상태 검사 → 고급 상태 검사 설정 : 정상 임계 값(3), 간격(10), 나머지는 기본값

대상 등록 : 하단 인스턴스 선택 → 등록된 항목에 추가

검토 → 생성

EC2 → 네트워크 및 보안 → 네트워크 인터페이스 : 설명(ELB app...) 확인


ALB 검증

설정 확인 : 리스너, 대상그룹

  • 부하 분산 처리 동작 확인(라운드 로빈)
  • My-EC2에서 확인 & 자신의 PC 웹브라우저에서 ALB 도메인 접속 후 새로고침(/, /xff.php)
    => 브라우저에서 새로고침하면 번갈아가면서 나타남
[ec2-user@MyEC2 ~]$ ALB=ALB-TEST-2011552698.ap-northeast-2.elb.amazonaws.com
[ec2-user@MyEC2 ~]$ echo $ALB
ALB-TEST-2011552698.ap-northeast-2.elb.amazonaws.com
[ec2-user@MyEC2 ~]$ dig $ALB +short
52.79.70.156
15.165.112.38
[ec2-user@MyEC2 ~]$ while true; do dig $ALB +short && echo "------------------------------" && date; sleep 5; done
15.165.112.38
52.79.70.156
------------------------------
Mon Jul 26 18:21:30 UTC 2021
52.79.70.156
15.165.112.38
------------------------------
Mon Jul 26 18:21:35 UTC 2021
^C
[ec2-user@MyEC2 ~]$ curl $ALB
<h1>ELB-EC2-2 Web Server</h1>
[ec2-user@MyEC2 ~]$ for i in {1..20}; do curl $ALB --silent ; done | sort | uniq -c | sort -nr
     12 <h1>ELB-EC2-2 Web Server</h1>
      8 <h1>ELB-EC2-1 Web Server</h1>
[ec2-user@MyEC2 ~]$ for i in {1..100}; do curl $ALB --silent ; done | sort | uniq -c | sort -nr
     51 <h1>ELB-EC2-1 Web Server</h1>
     49 <h1>ELB-EC2-2 Web Server</h1>
[ec2-user@MyEC2 ~]$ curl $ALB/xff.php ;echo
AFOS Test Page 입니다 !
    _    _____ ___  ____    _____         _     ____
   / \  |  ___/ _ \/ ___|  |_   _|__  ___| |_  |  _ \ __ _  __ _  ___
  / _ \ | |_ | | | \___ \    | |/ _ \/ __| __| | |_) / _` |/ _` |/ _ \
 / ___ \|  _|| |_| |___) |   | |  __/\__ \ |_  |  __/ (_| | (_| |  __/
/_/   \_\_|   \___/|____/    |_|\___||___/\__| |_|   \__,_|\__, |\___|
                                                           |___/

Tue, 27 Jul 21 03:22:13 +0900

Current CPU Load:0%

Last Client IP: 10.0.0.191
Server Public IP = alb-test-2011552698.ap-northeast-2.elb.amazonaws.com
Server Private IP: 10.0.1.39
X-Forwarded-for: 13.124.88.91
[ec2-user@MyEC2 ~]$ curl $ALB/dev/index.html --silent
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
[ec2-user@MyEC2 ~]$ curl $ALB/dev/index.html --silent
<h1>ELB-EC2-1 Dev Web Page</h1>
[ec2-user@MyEC2 ~]$ curl $ALB/mgt/index.html --silent
<h1>ELB-EC2-2 Mgt Web Page</h1>
[ec2-user@MyEC2 ~]$ curl $ALB/mgt/index.html --silent
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>

결과값 해석 : ELB-EC2-1에서 응답, 다른 한 번은 ELB-EC2-2에서 응답을 못 줌
      => 해결을 위해 경로 기반 라우팅 기능 사용

HTTP 접근을 위한 url 경로 정보를 확인하여 원하는 대상으로 라우팅
    - /dev 페이지는 ELB-EC2-1 서버로만 전달
    - /mgt 페이지는 ELB-EC2-2 서버로만 전달
      => 경로 기반 라우팅으로 해결 (포스팅 마지막 ALB 고급 라우팅)

X-Forwarded-for :  End device 의 주소(접근하는 사용자의 출발지 주소, 즉 공인 IP주소)
(설명 : https://sarc.io/index.php/miscellaneous/536-x-forwarded-for-xff-http-header)

Last Client IP : AZ에 배치된 ALB의 주소

 

Apache2 웹서버에서 클라이언트 IP 로그 확인

  • ALB 에서 X-Forwarded-For(=XFF)에 Clinet IP 정보(220.117.X.X)를 담아 서버에서 확인 가능
  • 클라이언트 IP를 보존하지 않으면, 서버입장에서 어떤 대상의 IP가 접근했는지 알 수 없음
  • 따라서 ALB에서는 X-Forwarded-For 헤더라는 곳에 클라이언트 IP정보를 담아서 전달

[root@ELB-EC2-1 ~]# tail -f /var/log/httpd/access_log
10.0.1.139 - - [26/Jul/2021:18:31:54 +0000] "GET / HTTP/1.1" 200 30 "-" "ELB-HealthChecker/2.0"
10.0.0.126 - - [26/Jul/2021:18:31:57 +0000] "GET / HTTP/1.1" 200 30 "-" "ELB-HealthChecker/2.0"
10.0.0.191 - - [26/Jul/2021:18:31:59 +0000] "GET / HTTP/1.1" 200 30 "-" "ELB-HealthChecker/2.0"
10.0.1.138 - - [26/Jul/2021:18:31:59 +0000] "GET / HTTP/1.1" 200 30 "-" "ELB-HealthChecker/2.0"
10.0.1.139 - - [26/Jul/2021:18:32:04 +0000] "GET / HTTP/1.1" 200 30 "-" "ELB-HealthChecker/2.0"
[root@ELB-EC2-1 ~]#
[root@ELB-EC2-1 ~]# tail -f /var/log/httpd/access_log |grep -v "ELB-HealthChecker/2.0"
10.0.0.191 - - [26/Jul/2021:18:36:41 +0000] "GET /dev/index.html HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36"
10.0.0.191 - - [26/Jul/2021:18:36:45 +0000] "GET /dev/index.html HTTP/1.1" 200 32 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36"

# 패킷 덤프 -ELB-EC2-1/2
[root@ELB-EC2-1 ~]# tcpdump tcp port 80 -nn
  • ALB 헬스 체크 정보 확인(시간 간격, 요청 정보, 요청 클라이언트 IP 등) 및 tail 시 필터링 출력
    (HTTP 프로토콜 공부)
# Apache 기본 로그 설정 정보 확인
[root@ELB-EC2-1 conf]# grep -n LogFormat /etc/httpd/conf/httpd.conf
196:    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
~
# Apache 기본 로그 설정 변경 : 196번째 줄에 %{X-Forwarded-For}i 추가
nano /etc/httpd/conf/httpd.conf
 LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
 CTRL+X Y Enter 로 저장하고 빠져나오기

# HTTP 다시 로드 - ## 아재 service httpd reload
systemctl reload httpd

# 실시간 로그 출력 후 외부에서 접속 시도
tail -f /var/log/httpd/access_log |grep -v "ELB-HealthChecker/2.0"
1.230.xxx.xxx 10.0.1.139 - - [26/Jul/2021:18:40:35 +0000] "GET /dev/index.html HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36"
1.230.xxx.xxx 10.0.1.139 - - [26/Jul/2021:18:40:42 +0000] "GET /dev/index.html HTTP/1.1" 200 32 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36"
223.62.162.xxx 10.0.0.191 - - [26/Jul/2021:19:10:37 +0000] "GET /dev/index.html HTTP/1.1" 200 32 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1"
223.62.162.xxx 10.0.0.191 - - [26/Jul/2021:19:10:38 +0000] "GET /dev/index.html HTTP/1.1" 200 32 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1"



# 결과의 제일 앞에 나오는 IP가 X-Forwarded-For IP주소
# 밑에 두개는 iphone에서 접속 결과

 

 


ALB 고급 라우팅

  1. 경로 기반 라우팅 설정
    • 대상 그룹 생성 : Dev-Group(ELB-EC2-1) , Mgt-Group(ELB-EC2-2)
    • 리스너 규칙 편집 : 경로 /dev/* → 전달 대상(Dev-Group) , 경로 /mgt/* → 전달 대상(Mgt-Group)
    대상그룹 생성 완료
    리스너 규칙 편집 완료


  2. 경로 기반 라우팅 확인 - My-EC2에서 확인
    • [ec2-user@MyEC2 ~]$ for i in {1..20}; do curl $ALB/dev/ --silent ; done | sort | uniq -c | sort -nr
           20 <h1>ELB-EC2-1 Dev Web Page</h1>
      [ec2-user@MyEC2 ~]$ for i in {1..20}; do curl $ALB/mgt/ --silent ; done | sort | uniq -c | sort -nr
           20 <h1>ELB-EC2-2 Mgt Web Page</h1>
      [ec2-user@MyEC2 ~]$ for i in {1..20}; do curl $ALB --silent ; done | sort | uniq -c | sort -nr
           11 <h1>ELB-EC2-2 Web Server</h1>
            9 <h1>ELB-EC2-1 Web Server</h1>
    • /dev/index.html은 ELB-EC2-1로만 전달, /mgt/index/html은 ELB-EC2-2로만 전달
    • /index/html은 번갈아 가면서 전달
  3. HTTP 헤더 기반 라우팅 설정 - 고정 응답 반환
    • 목적: HTTP header 에 이름이 user 이고 값이 minimun 인 쿠키(Cookie)가 매칭되면 고정된 응답을 반환
    • 리스너 규칙 편집 : HTTP 헤더 - Cookie 는 user=닉네임 → 고정 응답 반환 200 "Hello 닉네임"
      규칙 생성
      [ec2-user@MyEC2 ~]$ curl --cookie "user=minimun" $ALB ;echo 
      Hello AFOS_minimun
  4. 소스 기반 IP 기반 라우팅 설정 - 고정 응답 반환
    • 목적 : 소스 IP 주소가 매칭되면 고정된 응답을 반환
    • 리스너 규칙 편집 : 소스IP -확장='My-EC2 공인 IP입력' → 고정 응답 반환 200 "Hello EC2 Instance. Your IP address #"
      규칙 생성
      # 인터넷 사용 시 자신의 IP 주소(공인IP)를 확인하는 법
      [ec2-user@MyEC2 ~]$ curl -4 icanhazip.com
      13.124.88.91
      
      # 규칙 확인
      [ec2-user@MyEC2 ~]$ curl $ALB; echo
      Hello EC2 instance, Your IP is 13.124.88.91
  5. Query String 기반 라우팅 설정 - 고정 응답 반환
    • 목적: 쿼리 문자열 값이 매칭되면 고정된 응답을 반환
    • 리스너 규칙 편집 : 쿼리 문자열 - 키 : ABTest 값 : A 입력 → 고정 응답 반환 200 "A or B test, option A selected"
      규칙 생성
      [ec2-user@MyEC2 ~]$ curl $ALB?ABTest=A; echo
      A or B test, option A selected
  6. HTTP Request method 기반 라우팅 설정 - 고정 응답 반환
    • 목적: HTTP 특정 메소드가 매칭되면 고정된 응답을 반환
    • 리스너 규칙 편집 - HTTP 요청 메서드 - READ → 고정 응답 반환 200 "Custom READ method invoked"
      규칙 생성
      [ec2-user@MyEC2 ~]$ curl --request READ $ALB; echo
      Custom READ method invoked
  7. 아이폰, 안드로이드 사용자 차단 → 설정 후 자신의 핸드폰(wifi on & off)에서 ALB DNS로 접속 차단 확인 
    • 리스너 규칙 편집 : HTTP 헤더 기반 라우팅 설정
      • HTTP 헤더 → User-Agent 는 iPhone 혹은 Android
      • 고정 응답 반환 : 503 iPhone or Android Access Deny
        규칙 생성
        아이폰 차단 확인