# Load Balancer - HAProxy

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

## 서비스 구성도

<figure><img src="/files/QRRXZkxpHAr55nQH5aPy" 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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://youngtae.gitbook.io/development-reference/server/load-balancer-haproxy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
