처음 Mac 을 구매하게 되면 제일 먼저 하는 것이 Iterm2 를 설치하는 것이다. Mac 에서 제공하는 Term 보다 사용하기 편해서 기본적으로 다 설치를 하게 된다. Iterm2 는 테마, 폰트등을 설정할 수 있고 Git 을 이용할 경우에 터미널에서 Branch 상태등을 잘 보여줘서 거의 필수로 설치를 하게된다.
기본상태
Iterm2 를 설치하면 다음과 같다.
프롬프트나 이런것들이 기본상태이다.
oh-my-zsh 설치
oh-my-zsh 는 zsh 에 많은 기능을 부여해준다. 대표적인 것이 Themes, Fonts 등이다. 다음과 같이 설치할 수 있다.
Application Gateway 를 위한 전용의 서브넷이 있어야 한다. 서브넷에 다른 서비스가 있다면 선택이 되지 않는다. 예를들어 Subnet1 에 VM 을 생성했다고 하면 Application Gateway 서브넷으로 사용할 수 없다.
따라서 네트워크 설계를 할때에는 Application Gateway 를 위한 전용의 서브넷을 미리 생성을 해야 한다.
Private Subnet 도 가능
Application Geteway 를 생성할때에 Subnet 을 지정하게 된다.
위와같이 Private Subnet 을 지정할 수 있다. 이렇게 지정하고 난후에도 Application Gateway 에 동작하는데에는 아무런 문제가 되지 않는다.
Azure Subnet 에서는 Private Subnet 을 지정하는 옵션이 존재한다. 다음과 같이 설명되어 있다.
Private subnets enhance security by not providing default outbound access. To enable outbound connectivity for virtual machines to access the internet, it is necessary to explicitly grant outbound access. A NAT gateway is the recommended way to provide outbound connectivity for virtual machines in the subnet.
OutBound Access 에 제한이 걸릴 뿐 Application Gateway 의 동작에는 아무런 문제가 되지 않는다.
Azure 를 하면서 여러가지 차이점을 느끼지만, 그 중 Azure Load Balancer 만큼 차이를 보여주는 것도 없어보인다. AWS 에서는 Network Load Balancer 에 대응되지만 기능이 몇가지 더 있음으로 해서 아키텍쳐에도 차이를 보인다.
SNAT
Azure LoadBalancer 는 SNAT 기능을 지원한다. Source NAT 라고 하는 것으로 내부 사설IP 를 외부 공인IP 로 변경해 주는 기능이다. 이 기능은 내부 사설망에서 외부 공인 인터넷망으로 통신을 가능하게 해주는 중요한 기능이다.
VM 기반 리소스를 생성할때에 보안상 대부분 사설 서브넷(Private Subnet) 에 위치시킨다. 그리고 서비스를 위해서 VM 앞단에 Load Balancer 를 위치킨다. 문제는 VM 자체적으로 인터넷 통신을 하려고할 때다. 공인IP 가 있다고 하더라도 사설 서브넷에 위치된 VM 은 라우팅으로 인해서 외부로 나갈 수 없어 인터넷 통신을 할 수 없다. AWS 의 경우 이 문제를 해결 하기 위해서 NAT Gateway 서비스를 이용해야 한다.
Azure 에서는 Load Balancer 를 이용하면 이러한 문제를 해결 할 수 있다. 물론 Azure 에서도 NAT Gateway 서비스가 존재하지만 Azure 아케텍쳐상 베스트 프렉티스(Best Practice) 가 아닌 것으로 보인다.
Azure VM 기준 아케텍쳐인데(Azure 공인문서), Frontend 와 Backend 에 위치한 VM들은 모두 사설 서브넷이며 인터넷 통신을 위해서 Load Balancer 를 이용하고 있다. NAT Gateway 를 이용하면 더 좋아 보이는데, 베스트 프렉티스로 되어 있지 않은 모양이다.
Load Balancer 생성
Azure 에 Load Balancer 는 L4 Layer 다. AWS 에 Network Load Balancer 에 대응되지만 SNAT 기능을 제공함으로써 인터넷 통신을 가능하게 해준다.
Load Balancer 생성화면에서 많은 절차가 필요하다는 것을 알수 있는데, Outbound rules 이 SNAT 기능을 사용하는 것이다. 물론 이 기능을 사용하기 위해서는 Inbound rules 설정에서 SNAT 기능을 사용하겠다고 활성화를 해줘야만 한다.
Port allocation
SNAT 설정할때에 문제가 되는 항목이 바로 Port allocation 이다. SNAT 자체가 VM 에서 출발하는 IP 를 변환해주는 것인데, 어쨋거나 Load Balancer 가 대신 공인 인터넷으로 접속을 하게 해주는 것임으로 결국에는 Load Balancer 가 출발지로 되고 결국에는 Client Port 가 있어야 한다.
문제는 VM 에서 인터넷 접속을 이것저것 하게 되면 단 하나의 Client Port 가지고는 되지 않는다. 브라우져를 통해 웹사이트 접속을 하더라도 동시에 몇십게의 Client Port 가 생성된다. 따라서 Load Balancer 입장에서는 뒷단에 있는 VM 들에게 무제한 접속을 허용, 다시 말해서 Client Port 를 할당해 줄수가 없게 된다.
이를 위해서 Azure 는 Port allocation 설정을 하도록 하고 있다. Load Balancer 의 Frontend IP 당 뒷단 VM 수를 조합해 VM 하나에 할당가능한 Port 의 개수를 정하도록 해 놨다.
Port allocation 의 방식을 Manually 로 하지 않고, Azure 에 위임할 경우에 Scale out 시에 뒷단 VM 의 연결이 안될 수도 있다. 위와같이 수동으로 하고 뒷단 인스턴스 개수를 지정해주는 것을 권장하고 있다.
이 설정을 하게되면 SNAT 설정이 완료된다. 이제 VM 에서 인터넷이 되는지 확인해보면 된다.
DNAT
Azure Load Balancer 는 DNAT 기능을 제공한다. 이 기능일 이용하면 Load Balancer 뒷단 VM 에 접속을 할 수 있다. 하지만 이 기능은 잘 사용하지 않는 것으로 보인다. 베스트 프렉티스 아키텍쳐에서는 Bastion 서버를 구성해서 사용하는 것으로 보이는데, 어쨌든 DNAT 기능을 제공한다.
SNAT 기능은 Outbound rule 이라고 한다면 DNAT 는 Inbound NAT rule 이라고 한다.
테스트를 위해서 SSH(22 port) 를 활성해서 뒷단 VM 에 접속하도록 했다. 이렇게 되면 Load Balancer 의 공인IP 를 기반으로 VM 에 22 포트로 접속이 가능해 진다. Frontend Port 의 경우에는 잘 알려진 포트가 아닌 다른 포트를 이용하는 것이 좋다.
결론
Azure Load Balancer 는 L4 Layer 장비다. AWS 와 달리 SNAT, DNAT 기능을 모두 지원함으로써 뒷단 VM 에 특정한 기능을 제공한다.
Azure 기술 문서에는 사설 서브넷에 위치한 VM 의 인터넷 연결을 위해서 Load Balancer 를 이용하고 있다. VM 접속을 위해서는 Bastion 서비스를 이용하도록 구성하고 있어서 Inbound NAT Rule 은 임시적으로 긴급한 상황이 아니라면 크게 사용할 일은 없어보인다.
nodeSelector 에 system.rule: monitoring 이 보이는데, 이는 Worker 노드에 라벨을 말한다. 선택된 라벨을 가지고 있는 Worker 노드에 Prometheus 가 설치된다. 단, 이것도 상황에 따라서 달라지는데 Node exporter 의 경우에는 각 노드에 설치가 되어야 하기 때문에 라벨을 설정하지 않는다.
과거 Metallb 의 버전이 0.10 이였고 K8S 버전도 1.32 이여서 최신 버전으로 다시 설치를 해봤다.
환경
K8S 환경에서 설치를 하지만 CNI 등을 고려해 설치를 진행해야 한다. 내가 설치한 환경은 좀 더 특이한데, K8S 를 Hand Way 방법으로 설치한 상태다. Hand Way 로 설치를 하게 되면 Kube-apiserver, controller, kubelet, kube-scheduler, kube-proxy 같은 것을 컨테이너 방법이 아닌 OS 프로그램 방법으로 설치를 하게 된다. K8S 에서 사용하는 인증서도 수동으로 해줘야 한다.
Normal nodeAssigned54mmetallb-speaker announcing from node"kworker3.systemv.local"with protocol"layer2"
Normal nodeAssigned53m(x4 over54m)metallb-speaker announcing from node"kworker2.systemv.local"with protocol"layer2"
Normal IPAllocated8m35smetallb-controller Assigned IP["192.168.111.3"]
Normal nodeAssigned3m29smetallb-speaker announcing from node"kworker1.systemv.local"with protocol"layer2"
EndPoints 는 Nodes IP가 보이고 Port 도 할당된게 보인다. 이건 아마도 Hand Way 설치로 인한 것으로 보인다. 원래 kubeadm 으로 설치를 하게 될 경우에 Node IP 조차도 K8S IP 여야 하는데, 여기서는 Node IP 자체가 OS 자체에 할당된 IP로 나타난다.
리눅스에서 OpenVPN 서버 구축해 보도록 한다. 리눅스 서버는 Ubuntu 24.04 LTS 이다.
아키텍쳐
현재 AWS 아키텍쳐는 다음과 같다.
OpenVPN 를 설치할 서버는 AWS 에 Public Subnet 에 있으며 외부에서 접속을 위해서 EIP(Elastic IP) 를 할당 해줬다. VPC 내에 모든 서버들은 172.31.0.0/16 대역폭에 자동으로 IP를 할당받아 Private IP 를 구성하도록 되어 있다.
이제 사내망 PC 에서 server1 에 Private IP 로 접속을 하기 위한 방법으로 OpenVPN 서버를 설치해보도록 한다.
OpenVPN 작동 방식
OpenVPN 의 작동방법은 NAT 기능을 이용하는 것이다. 먼저, OpenVPN 서버를 설치하고 기동하면 OpenVPN 서버는 서버에 tun0 라고 하는 네트워크 인터페이스 생성한다. 물론 이렇게 생성한 NIC에 네트워크 서브넷을 할당한다. tun0 에 IP를 할당하고 서브넷 라우팅도 함께 구성하게 된다.
이제 OpenVPN 클라이언트를 설치하고 설정파일을 읽어 연결을 하게 되면, OpenVPN 클라이언트는 PC 에 tap0 라고 하는 네트워크 인터페이스를 생성한다. 그리고 이 tap0 에는 OpenVPN 서버로부터 네트워크 관련 정보를 전달 받아서 tun0 와 동일네트워크에 IP, Defaut GW 를 구성하게 된다. 이를 다이어그램으로 표현하면 다음과 같다.
OpenVPN 을 이용하는 이유는 172.31.0.0/16 대역에 있는 서버에 접속하기 위해서다. AWS 아키텍쳐 그림상 server1 에 사내PC가 직접 접속할 방법이 없다. 하지만 OpenVPN 을 이용하면 가능하다. 다음과 같이 접속이 이루어진다.
사내PC(192.168.96.112.66) -> tap(192.168.200.56) —– 인터넷 —–> OpenVPN 서버 tun0(192.168.96.200.1) — NAT –> server1(172.31.0.43)
이러한 흐름을 보면 OpenVPN 서버의 설정에서 OpenVPN 서버와 Client 연결을 위한 네트워크 대역 할당과 server1 의 접속은 OpenVPN 서버를 거쳐서 와야하기 때문에 AWS VPC 네트워크 대역을 알려줘야 하고 OpenVPN 서버는 NAT 서버로 동작해야 한다는(그래서 iptables 을 이용한 MASQUERADE 설정을 한다.) 걸 알게 된다.
OpenVPN 2.6
현 시점에서 OpenVPN 은 2.5 를 기준으로 구분이 된다. 2.6 은 현재 최신 버전으로 사용되고 있는데, 2.5 를 기준으로해서 설정에 많은 변화가 있음으로 만일 처음 구축한다면 2.6으로 하고 호환성을 고려한다면 2.4 를 기준으로 구축하는 걸 권장 한다.
OpenVPN 설치
설치는 Ubuntu 24.04 LTS 에서 기본으로 제공하는 패키지로 설치가 가능하다. 이때 OpenVPN 이 사용할 인증서 생성을 위해서 easy-rsa 명령어도 함께 설치해야 한다.
openvpn 설치
ZSH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
~# apt install openvpn easy-rsa
Reading packagelists...Done
Building dependency tree...Done
Reading state information...Done
The following additional packages will be installed:
내용이 많지만, 맨 아래 두줄이 핵심이다. tun0 네트워크 장치로부터 192.168.200.0/24 대역으로 들어온 IP에 대해서 enX0 장치를 이용해 172.31.0.0/16 대역으로 패킷을 포워딩 하고 MASQUERADE 설정을 해주고 있다.
OpenVPN 서버가 정지하면 초기화 해주는 remove-bridge.sh 파일을 만들어 준다.
remove-bridge.sh 파일 생성
ZSH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
if[!-x/usr/sbin/iptables];then
exit0
fi
IPTABLES=/usr/sbin/iptables
# flush a default policy of rules
$IPTABLES-F
$IPTABLES-X
$IPTABLES-PINPUT ACCEPT
$IPTABLES-POUTPUT ACCEPT
$IPTABLES-PFORWARD ACCEPT
# general nat
$IPTABLES-tnat-DPOSTROUTING1
모든 체인을 플러쉬하고 POSTROUTING 룰을 삭제한다.
이렇게 만들어진 파일을 systemd unit 파일인 openvpn@server 에 override 설정으로 추가해준다. override 설정은 파일을 일반 편집으로 해서 추가해주면 자동으로 알아서 추가가 된다.
ZSH
1
2
3
4
5
6
]# export SYSTEMD_EDITOR=vim
]# systemctl edit openvpn@server
[Service]
ExecStartPost=/etc/openvpn/add-bridge.sh
ExecStopPost=/etc/openvpn/remove-bridge.sh
이렇게 하면 openvpn 시작/중지 때마다 쉘 스크립트가 실행 된다.
시작/중지
이제 시작과 중지를 해보자. 다음과 같이 한다.
openvpn 시작/중지
ZSH
1
2
]# systemctl start openvpn@server
]# systemctl stop openvpn@server
OpenVPN 클라이언트 설정
OpenVPN 홈페이지에서 Windows 용 클라이언트를 다운받아 설치한다. 설정 파일은 개인마다 가지고 있어야 해서 전체 시스템에 액세스하는 디렉토리에 넣으면 좋지 않다. 이는 설치가 끝나면 팝업으로 알려주는데, C:\Users\계정ID\OpenVPN\config 이다.
이 디렉토리에 서버에서 작성한 파일을 복사해줘야 한다. 복사해야 할 파일은 다음과 같다.
linux.crt (클라이언트 인증서)
linux.key (클라이언트 인증서 암호화 키)
ca.crt (CA 인증서)
ta.key (TLS-Auth Key)
이제 linux.ovpn 파일을 다음과 같이 작성한다.
linux.ovpn
ZSH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
client
dev tun
proto udp
remote<openvpn공인IP>1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert linux.crt
key linux.key
remote-cert-tls server
comp-lzo yes
tls-auth ta.key1
verb3
위와같이 작성하고 OpenVPN Client 에서 설정 파일을 지정하고 연결하기 하면 연결이 된다.
인증서의 사용기간은 730 일이다. 그리고 -extensions v3_ca 를 인자로 줬는데, 명세서 파일인 RootCA.cnf 파일에 v3_ca 섹션을 사용하라는 뜻이다. v3_ca 섹션에는 인증서에 대한 사용범위, RootCA 임을 증명하는 CA:TRUE 등이 있다.