# Load Balancer - HAProxy

{% hint style="info" %}
이 글에서 설명하는 서비스 구성에 필요한 가상 머신, 공인 IP, 도메인은 모두 준비되어 있음을 전제함
{% endhint %}

## 서비스 구성도

<figure><img src="https://2345962418-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUHFbkEcYWGadDil58qUQ%2Fuploads%2Fb7vWZitn2sHOl96RMHR7%2Fimage1.png?alt=media&#x26;token=c6355e87-381e-466d-8f5b-ee4dbe09dbbc" alt=""><figcaption></figcaption></figure>

## 서버 정보

<table><thead><tr><th width="118" align="center">가상머신</th><th width="178">IP</th><th>운영체제</th><th>용도</th></tr></thead><tbody><tr><td align="center">VM1</td><td>192.168.10.116</td><td>Linux (CentOS 7)</td><td>Load Balancer</td></tr><tr><td align="center">VM2</td><td>192.168.10.121</td><td>WindowsServer2016</td><td>웹 서비스 (IIS)</td></tr><tr><td align="center">VM3</td><td>192.168.10.122</td><td>WindowsServer2016</td><td>웹 서비스 (IIS)</td></tr><tr><td align="center">VM4</td><td>192.168.10.123</td><td>WindowsServer2016</td><td>웹 서비스 (IIS)</td></tr><tr><td align="center">VM5</td><td>192.168.10.125</td><td>WindowsServer2016</td><td>웹 서비스 (IIS)</td></tr></tbody></table>

## HAProxy 설정

### 설치

```bash
sudo yum -y install haproxy
```

### 설치가 완료되면 기본적인 설정파일은 다음 경로에 있음

```bash
vi /etc/haproxy/haproxy.cfg
```

### 파일 내용 수정&#x20;

### **백엔드 설정**

```
backend web_main
    balance roundrobin
    server web1 192.168.10.121:80 check
    server web2 192.168.10.122:80 check
	
backend web_abc
    balance roundrobin
    server web1 192.168.10.123:80 check
	
backend web_xyz
    balance roundrobin
    server web1 192.168.10.125:80 check
```

### HTTP **설정**

```
frontend http_front
    bind *:80
    default_backend web_main
```

### WEB UI 설정 <a href="#web-ui" id="web-ui"></a>

```
listen stats
    bind *:9000
    mode http
    stats enable
    stats hide-version
    stats realm Haproxy Statistics
    stats uri /
```

## HAProxy 서비스

&#x20;**시작**

```bash
systemctl start haproxy
```

**부팅 후 자동 실행**

```bash
systemctl enable haproxy
```

**상태 확인**

```bash
systemctl status haproxy
```

**실행 오류 시 확인 방법**: 루트로 포그라운드에서 수동으로 시작하고 오류 메시지를 확인

```bash
haproxy -f /etc/haproxy/haproxy.cfg -db
```

**서비스가 시작되지 않고 아래 오류 메시지와 같이 뜰 경우**

오류메시지:  "Starting frontend mssql\_frontend: cannot bind socket \[0.0.0.0:1433]"

```
setsebool -P haproxy_connect_any=1
```

#### `setsebool -P haproxy_connect_any=1` 명령어의 역할

* **setsebool**: SELinux의 boolean 값을 설정하는 명령어
* **-P**: 변경 사항을 영구적으로 적용하여 시스템 재부팅 후에도 유지
* **haproxy\_connect\_any=1**: HAProxy가 모든 네트워크 서비스에 연결할 수 있도록 허용하는 boolean 값을 활성화

## 방화벽 설정 (포트 및 서비스 등록)

**새로운 zone 생성**

```
firewall-cmd --permanent --new-zone=webserver
```

**방화벽에 서비스 추가**

```
firewall-cmd --permanent --zone=webserver --add-service=http
firewall-cmd --permanent --zone=webserver --add-service=https
```

**방화벽에 포트 추가**

```
firewall-cmd --permanent --zone=webserver --add-port=80/tcp
firewall-cmd --permanent --zone=webserver --add-port=443/tcp
firewall-cmd --permanent --zone=webserver --add-port=9000/tcp
```

**firewalld 재시작 및 새로 등록한 zone 활성화**

```
firewall-cmd --reload
firewall-cmd --set-default-zone=webserver
```

**정상 설정 여부 확인**

```bash
firewall-cmd --list-services --zone=webserver
firewall-cmd --list-ports --zone=webserver
```

**수신중인 포트 확인**

* 방화벽에서 포트를 설정해도 해당 포트로 실제 서비스가 수신되고 있어야 나타남
* 방화벽 오픈은 되었으나 프로세스가 안 떠 있는 것 (포트를 열고 대기하고 있지 않은 상태)

```bash
netstat -tulpn | grep LISTEN
grep -w '80/tcp' /etc/services
```

## certbot SSL 인증서 발급

letsencrypt으로 발급하기 위해서는 certbot 프로세서로 발급할 수 있으며 CentOS7에서는 epel-release를 설치해야 다운로드가 가능

```bash
sudo yum -y install epel-release
sudo yum -y install certbot
```

### 발급하는 방법

```bash
sudo certbot certonly --standalone -d <domain>
```

### Multi-Domain

```bash
sudo certbot certonly --standalone -d <domain1> -d <domain2> -d <domain3>
```

{% hint style="warning" %}
**주의할 점은 80번 포트로 접속하여 ssl을 발급하게 되는데 haproxy를 80번 포트를 사용하고 있다면 서비스를 중단하고 진행**
{% endhint %}

### 설치가 완료되면 다음 경로에 기본적으로 설치

```
/etc/letsencrypt/live/<domain>/
```

### 파일을 불러오는것을 간소화 하기 위해서 다음 명령어로 하나로 합친다

```bash
mkdir /etc/haproxy/certs
cat /etc/letsencrypt/live/<domain>/*.pem > /etc/haproxy/certs/ssl.pem
```

### 인증서 자동 갱신 설정 <a href="#certbot-renew" id="certbot-renew"></a>

#### Bash 쉘 스크립트 파일 작성

```bash
vi /bin/letsencrypt.sh
```

```bash
#!/bin/sh

systemctl stop haproxy
/usr/bin/certbot renew > /var/log/letsencrypt/renew.log
cat /etc/letsencrypt/live/<domain>/*.pem > /etc/haproxy/certs/ssl.pem
fuser -k 80/tcp
systemctl start haproxy
```

#### 스크립트 파일에 권한 부여

```bash
chmod +x /bin/letsencrypt.sh
```

#### 스크립트 파일 실행하고 생성된 로그 파일 마지막 수정 일자 확인

```bash
/bin/letsencrypt.sh
ls -l /var/log/letsencrypt
```

#### crontab을 이용하여 스크립트 파일 자동 실행 설정

```bash
sudo crontab -e
```

**매일 오전 3시 마다 실행**

```bash
0 3 * * * /bin/letsencrypt.sh
```

**crontab 서비스 시작**

```bash
service crond start
```

## HTTPS 및 도메인별 접속할 백엔드 설정 <a href="#https" id="https"></a>

```bash
vi /etc/haproxy/haproxy.cfg
```

**기존 정의한 80 포트 설정을 다음과 같이 변경**

* HTTP 요청을 받아들이는 프론트엔드로, 클라이언트가 HTTPS가 아닌 요청을 보낼 경우에는 redirect 지시어를 사용하여 HTTPS로 리디렉션

```
frontend http-in
    bind *:80
    redirect scheme https if !{ ssl_fc }
```

**HTTPS 설정**

```
forntend https
    bind *:433 ssl crt /etc/haproxy/certs/ssl.pem
    acl host_abc hdr_end(host) -i abc.gsti.co.kr
    acl host_xyz hdr_end(host) -i xyz.gsti.co.kr
    mode http
    use_backend web_abc if host_abc
    use_backend web_xyz if host_xyz
    default_backend web_main
```

## 여러개 인증서 파일(.pem) 세팅 방법 <참고>

```
frontend ft_test
    mode http
    bind 0.0.0.0:443 ssl crt /certs/haproxy1.pem crt /certs/haproxy2.pem 
    use_backend bk_cert1 if { ssl_fc_sni my.example.com } # content switching based on SNI
    use_backend bk_cert2 if { ssl_fc_sni my.example.org } # content switching based on SNI
```

## ※ 리눅스 오픈된 포트 확인 및 등록 <a href="#semanage" id="semanage"></a>

**오픈된 HTTP Port 확인방법**

```bash
semanage port -l | grep http_port_t
```

**HTTP Port 오픈하기 위해 추가해주는 방법**

```bash
semanage port -a -t http_port_t -p tcp 8081
```

**HTTP Port 닫기 위해 제거**

```bash
semanage port -d -t http_port_t -p tcp 8081
```

## 기타

* CentOS 설치 참고: <https://copycoding.tistory.com/269>
