Profile picture

네트워크 망 구축 및 서버 구축

JaehyoJJAng2023년 02월 21일

◾️ 가상화 소프트웨어

  • VMware Workstation Pro 17
  • eve-ng

1. eve-ng VM 생성
image


2. eve-ng 접속
image



◾️ 네트워크 구축

  • 세세한 설정 방법에 대해서는 다루지 않음.
  • 설정 결과만 공유

1. VLAN 설정

1-1. Access Port

show vlan brief

image


1-2. Trunk Port

show interface trunk

image


2. Etherchannel

show etherchannel summary

image
스위치1, 스위치2에서 etherchannel 설정.


3. DHCP 설정 (Router 장비에서 진행)

show ip dhcp pool

image


3-1. DHCP Client(각 서버들)에서 IP 할당 받기

sudo dhclient -v

image


4. NAT 설정

4-1. 정방향 NAT 설정

show ip nat staticstics

image
image


4-2. 역방향 NAT 설정

show ip nat translations

image


◾️ 서버 상세 정보

시스템명 버전
NGINX Ubuntu 22.04.03
nginx: latest
WEB Ubuntu 22.04.03
FastAPI
Github : [https://github.com/JaehyoJJAng/shortenURL
](https://github.com/JaehyoJJAng/shortenURL)
DATABASE Ubuntu 22.04.03
mysql:latest
NFS Ubuntu 22.04.03
nfs-common:latest
SMB Ubuntu 22.04.03
samba:latest
Docker V20.10.15
Docker Compose V2.5.0

◾️ 서버 구축

내부망 서버의 접근 방식은 아래와 같다.
외부망 관리자 PC -> Bastion SSH 접속 -> 내부망 서버 SSH 접속


▪️ 사전 준비

  • 본격적인 서버 구축 전에 해야 할 사전 작업 목록

1. 서버별 hostname 수정

# 모든 서버에서 진행
sudo hostnamectl set-hostname <서버이름>
sudo hostnamectl set-hostname nginx

2. 도커 설치
(도커가 필요한 서버(web,monitoring)에서만 진행합니다)

2-1. 도커 설치
[Docker] 도커 설치하기 - Install Docker [CentOS7] <- 해당 포스팅 참고하여 도커 설치


▪️ bastion

▪️ SSH 설정

외부망 대역(192.168.219.10)에 있는 관리자 PC에서 bastion으로 SSH 접속하여

내부망에 연결되어있는 서버들(nginx,web,db ..)을 관리해 줄 것이다.

먼저, bastion 서버의 /etc/hosts 파일에 각 내부 서버들의 hostname과 IP를 설정해주도록 하자.

Server IP Address
nginx 172.16.0.34
web 172.16.0.37
db 172.16.0.35
nfs 172.16.0.66
samba 172.16.0.67
monitoring 172.16.0.70
sudo sh -c 'cat >> /etc/hosts << EOF
172.16.0.34  nginx
172.16.0.37  web
172.16.0.35  db
172.16.0.66  nfs
172.16.0.67  samba
172.16.0.70 monitoring
EOF'

/etc/hosts의 변경 내용을 적용하기 위해 network 서비스 재시작

sudo systemctl restart systemd-networkd 

빠른 접속을 위해 bastion 머신에서 SSH 인증 키페어 생성

cd ~/.ssh
ssh-keygen -t rsa -b 4096 -f ~/.ssh/bastion_rsa_key

각 서버에 키 복사하기

ssh-copy-id -i ~/.ssh/id_rsa 172.16.0.x

▪ nginx

bastion 서버에서 nginx로 접속

ssh nginx@nginx

1. nginx 설치

sudo apt-get update -y && sudo apt-get install -y nginx

1-1. nginx 설치 확인

sudo apt list --installed | grep "^nginx"

nginx-common/jammy-updates,now 1.18.0-6ubuntu14.4 all [installed,automatic]
nginx-core/jammy-updates,now 1.18.0-6ubuntu14.4 amd64 [installed,automatic]
nginx/jammy-updates,now 1.18.0-6ubuntu14.4 amd64 [installed]

2. nginx 서비스 상태 체크

systemctl status nginx

image


3. Reverse Proxy 설정

# /etc/nginx/sites-available/default

server {
        listen 80;

        location / {
            proxy_pass http://172.16.0.37:80; # 백엔드 서버 IP / PORT 번호 기입
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
}
nginx@nginx:~$ cat /etc/nginx/sites-enabled/default
server {
        listen 80;

        location / {
            proxy_pass http://172.16.0.37:80; # 백엔드 서버 IP / PORT 번호 기입
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
}

3-1. nginx 재시작

sudo nginx -t # nginx 설정 검사
sudo systemctl restart nginx

▪️ web


bastion 서버에서 web로 접속

ssh web@web

1. 프로젝트 clone

git clone https://github.com/JaehyoJJAng/shortenURL

2. Docker Compose 실행

docker-compose up -d --build

2-1. 컨테이너 상태 확인

NAME                COMMAND                  SERVICE             STATUS              PORTS
redis               "docker-entrypoint.s…"   redis               exited (0)
shorten-app         "uvicorn main:app --…"   app                 running             0.0.0.0:80->80/tcp, :::80->80/tcp

▪️ db

bastion 서버에서 db로 접속

ssh db@db

1. MySQL 설치

sudo apt-get update -y && sudo apt-get install -y mysql-server

1-1. mysql 설치 확인하기

sudo apt list --installed | grep "^mysql"

mysql-client-8.0/jammy-updates,jammy-security,now 8.0.35-0ubuntu0.22.04.1 amd64 [installed,automatic]
mysql-client-core-8.0/jammy-updates,jammy-security,now 8.0.35-0ubuntu0.22.04.1 amd64 [installed,automatic]
mysql-common/jammy,now 5.8+1.0.8 all [installed,automatic]
mysql-server-8.0/jammy-updates,jammy-security,now 8.0.35-0ubuntu0.22.04.1 amd64 [installed,automatic]
mysql-server-core-8.0/jammy-updates,jammy-security,now 8.0.35-0ubuntu0.22.04.1 amd64 [installed,automatic]
mysql-server/jammy-updates,jammy-security,now 8.0.35-0ubuntu0.22.04.1 all [installed]

2. MySQL 서비스 체크

systemctl status mysql

image


3. MySQL 유저 생성

CREATE USER 'jaehyo'@'localhost' IDENTIFIED BY 'jaehyo123';
GRANT ALL PRIVILIGES ON *.* 'jaehyo'@'localhost';
FLUSH PRIVILEGES;

4. DB 생성

CREATE DATABASE jaehyo_db;

5. TABLE 생성

CREATE TABLE jaehyo_tbl (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name TEXT
);

▪️ nfs

bastion 서버에서 nfs로 접속

ssh nfs@nfs

패키지 업데이트

sudo apt-get update -y

nfs에 필요한 패키지 설치

sudo apt-get install -y nfs-common nfs-kernel-server rpcbind

공유 폴더 생성

mkdir -p /share

디렉토리 권한 수정

chmod 707 /share

172.16.0.0/24 대역에서 nfs 서버의 /share 폴더를 마운트 할 수 있도록 /etc/exports 파일에 아래 내용 추가

sudo sh -c 'cat >> /etc/exports << EOF
/share 172.16.0.0/24(rw,sync)
EOF'

nfs-server 재시작

sudo systemctl enable --now nfs-server
sudo systemctl restart nfs-server

변경된 /etc/exports 파일 내용 바로 적용 시키기

exportfs -r

exportfs 적용 내용 출력

exportfs -v
/share          172.16.0.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash)

rpcbind가 사용중인 포트 출력

rpcinfo -p | grep -E 'nfs|mountd'

image


▪️ 포트 개방

firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --permanent --add-service=mountd

# 방화벽 재시작
firewall-cmd --reload

▪️ RAID 구성

구성표

RAID 파티션명 장치명 RAID level 묶을 raid 디바이스 수
RAID1 /dev/sdb1
/dev/sdc1
/dev/sdd1
/dev/sde1
/dev/md1 5 4

RAID 5 구성방법은 아래 게시글 참고
RAID 5 구성하기 - WTT Devlog


RAID 5 구성 결과
image


▪️ smb

bastion 서버에서 samba로 접속

ssh samba@samba

samda 패키지 설치

sudo apt-get update && sudo apt-get install -y samba

공유 폴더 생성

mkdir -p /smb-share

디렉토리 권한 수정

chmod 777 /smb-share

samba 접속 유저 생성

# smb 유저 생성
adduser smb

# smb 유저 패스워드 지정
echo "smb:${SMB_PASSWORD}" | chpasswd

# 'smb'라는 이름의 Samba 사용자에 대한 비밀번호를 추가
smbpasswd -a smb

samba 설정 (/etc/samba/smb.conf)

vi /etc/samba/smb.conf
[share]
comment = Share Directory # 설명(주석)
path = /tmp/samba/share # 경로
browserable = yes # yes = 모두가 읽을 수 있음, no = 허가된 사용자만
writable = yes # yes = 모두가 저장할 수 있음, no = 허가된 사용자만
valid users = smb # 인가된 사용자
create mask = 0777 # 파일을 만들면 자동으로 777권한을 부여
directory mask = 0777 # 폴더를 만들면 자동으로 777권한을 부여

samba 서비스 재시작

systemctl enable --now smb.service
systemctl restart smb.service

▪️ 포트 개방

firewall-cmd --permanent --add-service=samba
firewall-cmd --reload

samba 계정 정보를 까먹었다면?
pdbedit 명령으로 조회 가능하다.

sudo pdbedit -L -v

image


▪️ monitoring

각 서버(web,db ..)들의 journal / systemd 로그들을 Grafana로 가독성 있게 조회하기 위해, 도커 기반 Grafana + Loki + Promtail 조합으로 컨테이너를 올려보도록 하자.


bastion 서버에서 monitoring 서버로 ssh 접속

ssh monitoring@monitoring

1. 사전 준비

1-1) 도커 / Docker Compose 설치하기
도커 설치하기 - WTT Devlog


1-2) /etc/rsyslog.conf 파일 아래 처럼 수정

1-2-1) TCP / UDP 포트 열기 (모니터링 서버에서만 진행)

#### MODULES ####
# ...

# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

# Provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
# ...

1-3) 로그 템플릿 지정하기 ((모니터링 서버에서만 진행)

# ...
$template RemoteLogs, "/var/log/remote/%HOSTNAME%/%$YEAR%-%$MONTH%-%$DAY%_%HOSTNAME%.log"
*.* ?RemoteLogs

#### GLOBAL DIRECTIVES ####
# ...

image

💥 rsyslog file format

rsyslog.conf에서 로그 파일 포맷을 지정하는 방법에 대해서 자세히 알고싶다면 아래 게시글을 참고하도록 하자.
rsyslog 서버 구축하기 - WTT Devlog


1-4) rsyslog 재시작

sudo systemctl restart rsyslog.service

2. 컨테이너 볼륨 마운트 포인트 생성

mkdir -p "/home/${USER}/loki/config"
chown 10001:10001 "/home/${USER}/loki"

💥 Permission Denied!

loki 디렉토리 소유권을 변경하지 않고 loki 컨테이너를 실행했을 경우 'Permission denied' 라는 오류가 컨테이너 내부에서 발생하며 컨테이너가 실행되지 않음.


3. 공식 홈페이지에서 docker-compose.yaml 파일과 loki-config.yaml, promtail-config.yaml 파일을 다운로드
https://grafana.com/docs/loki/latest/get-started/

cd /home/${USER}/loki
wget https://raw.githubusercontent.com/grafana/loki/v2.2.1/cmd/loki/loki-local-config.yaml \
-O config/loki-config.yaml
wget https://raw.githubusercontent.com/grafana/loki/v2.2.1/cmd/promtail/promtail-docker-config.yaml \
-O config/promtail-config.yaml
wget https://raw.githubusercontent.com/grafana/loki/v2.2.1/production/docker-compose.yaml \
-O docker-compose.yaml 

4. loki-config 파일을 사용자의 환경에 맞게 수정

table_manager를 설정하여 2주 정도의 log만 보관하도록 설정하였음.

# /home/${USER}/loki/config/loki-config.yaml

auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9096

ingester:
  wal:
    enabled: true
    dir: /tmp/wal
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_sleep: 0s
  chunk_idle_period: 1h       # Any chunk not receiving new logs in this time will be flushed
  max_chunk_age: 1h           # All chunks will be flushed when they hit this age, default is 1h
  chunk_target_size: 1048576  # Loki will attempt to build chunks up to 1.5MB, flushing first if chunk_idle_period or max_chunk_age is reached first
  chunk_retain_period: 30s    # Must be greater than index read cache TTL if using an index cache (Default index read cache TTL is 5m)
  max_transfer_retries: 0     # Chunk transfers disabled

schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /tmp/loki/boltdb-shipper-active
    cache_location: /tmp/loki/boltdb-shipper-cache
    cache_ttl: 24h         # Can be increased for faster performance over longer query periods, uses more disk space
    shared_store: filesystem
  filesystem:
    directory: /tmp/loki/chunks

compactor:
  working_directory: /tmp/loki/boltdb-shipper-compactor
  shared_store: filesystem

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h

chunk_store_config:
  max_look_back_period: 0s

table_manager:
  retention_deletes_enabled: false
  retention_period: 0s

ruler:
  storage:
    type: local
    local:
      directory: /tmp/loki/rules
  rule_path: /tmp/loki/rules-temp
  alertmanager_url: http://localhost:9093
  ring:
    kvstore:
      store: inmemory
  enable_api: true

5. promtail-config 파일을 사용자의 환경에 맞게 수정

syslog receive와 journal / static log를 수집하도록 설정

# /home/${USER}/loki/config/promtail-config.yaml

# cat /loki/config/promtail-config.yaml 
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push # loki_컨테이너_이름:포트번호

scrape_configs:
- job_name: all_logs
  static_configs:
  - targets:
      - localhost
    labels:
      job: all_logs
      __path__: /var/log/remote/*/*log

- job_name: syslog
  syslog:
    listen_address: 0.0.0.0:1514
    labels:
      job: "syslog"
  relabel_configs:
    - source_labels: ["__syslog_connection_ip_address"]
      target_label: "ip_address"
    - source_labels: ["__syslog_message_severity"]
      target_label: "severity"
    - source_labels: ["__syslog_message_facility"]
      target_label: "facility"
    - source_labels: ["__syslog_message_app_name"]
      target_label: "app_name"
    - source_labels: ["__syslog_message_hostname"]
      target_label: "host"

- job_name: journal
  journal:
    max_age: 12h
    labels:
      job: systemd-journal
  relabel_configs:
    - source_labels: ["__journal__systemd_unit"]
      target_label: "systemd_unit"
    - source_labels: ["__journal__hostname"]
      target_label: "nodename"
    - source_labels: ["__journal_syslog_identifier"]
      target_label: "syslog_identifier"

💡 path
모니터링 서버의 /etc/rsyslog.conf 파일에서 설정했던 경로를 지정해주면 된다. 모니터링 서버에 로그가 수집되는 path를 지정해주면 된다.

💡 clients.url
해당 주소에서 사용되는 http://loki:3100.. 이 주소는 loki 컨테이너의 이름과 loki 컨테이너 내부 포트를 지정한 것이다.
loki 서버가 도커가 아닌 외부 물리 서버 또는 가상 서버로 설치된 경우 해당 서버의 IP와 포트번호를 지정해주면 된다.


6. docker-compose.yaml 파일을 아래 내용과 같이 만들어주자.

호스트의 /home/${USER}/loki 경로에 모든 data가 수집될 수 있도록 마운트 경로를 지정해줬음.

# cat docker-compose.yaml 
version: "3.8"

services:
  loki:
    image: grafana/loki
    restart: always
    volumes:
      - type: bind
        source: '/home/${USER}/loki/config'
        target: '/mnt/config'
      - type: bind
        source: '/home/${USER}/loki'
        target: '/loki'
    ports:
      - "3100:3100"
    command: -config.file=/mnt/config/loki-config.yaml
    container_name: gafana-loki
    networks:
      - 'loki-net'

  promtail:
    image: grafana/promtail
    restart: always
    ports:
      - "1514:1514"
    volumes:
      - type: bind
        source: '/var/log'
        target: '/var/log'
      - type: bind
        source: '/home/${USER}/loki/config'
        target: '/mnt/config'
      - type: bind
        source: '/var/log/journal/'
        target: '/var/log/journal/'
      - type: bind
        source: '/run/log/journal/'
        target: '/run/log/journal/'
      - type: bind
        source: '/etc/machine-id'
        target: '/etc/machine-id'
    command: -config.file=/mnt/config/promtail-config.yaml
    container_name: loki-promtail
    networks:
      - 'loki-net'

  grafana:
    container_name: grafana
    image: grafana/grafana
    ports:
      - "3000:3000"
    volumes:
      - type: volume
        source: "grafana-db"
        target: "/var/lib/grafana"
    networks:
      - 'loki-net'

volumes:
  grafana-db: {}

networks:
  loki-net:
    driver: bridge
    external: false

7. 컨테이너 실행

docker-compose up -d --build

image


▪️ 포트 개방

sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --permanent --add-port=3100/tcp
sudo firewall-cmd --permanent --add-port=1514/tcp
sudo firewall-cmd --reload

◾️ 운영 테스트

▪️ web

외부망 브라우저에서 192.168.219.5:80 입력하여 nginx에서 fastapi app으로 reverse proxy가 잘 작동하는지 테스트
image


▪️ nfs

bastion 서버에서 web 서버로 ssh 접속

ssh web@web

nfs 설치

sudo apt-get install -y nfs-common

nfs 서버에서 활성화된 공유 디렉토리 목록 출력
(nfs 서버 IP : 172.16.0.66)

showmount -e 172.16.0.66

image


web 서버에서 공유 폴더 생성

# web
mkdir -p /web-share

nfs 서버의 /share 폴더로 마운트

mount -t nfs 172.20.0.10:/share /web-share

마운트 됐는지 체크

# web
df -h | grep "^172.20.0.10"

image


/etc/fstab에 마운트 정보 등록

vim /etc/fstab

...
172.16.0.66:/share /web-share nfs defaults 0 0

▪️ samba

윈도우 10에서 samba를 이용한 파일 공유 테스트를 진행.

검색창에 \\[samba 서버 주소]"로 검색
image


조금 전에 생성했던 삼바 계정으로 로그인 (smb / ****)
image


정상적으로 로그인 되었음.
image


새로운 텍스트 파일을 하나 만들어보자.
image


samba 서버의 터미널로 이동 한 후에, 윈도우에서 생성한 hello_jaehyo 텍스트 파일이 /smb-share 디렉터리에 있는지 확인해보자.
image


▪️ monitoring

로그를 수집할 클라이언트 서버로 원격 접속하자.

ssh nginx@nginx # web,db,nfs,samba 서버에서도 아래 내용 동일하게 진행 

1. /etc/rsyslog.conf 파일에 아래 내용을 추가해주자.

중괄호 안에는 위에서 설장한 로그를 받는 서버의 IP 기입
* 아래 코드중 ‘@’ 한개는 UDP, ‘@@’ 두개는 TCP를 사용하겠다는 의미

# /etc/rsyslog.conf

# ...

*.* @{IP}:514

#### GLOBAL DIRECTIVES ####
# ...

image


2. rsyslog 재시작

sudo systemctl restart rsyslog

3. 모니터링 서버로 다시 원격접속하여 /var/log/remote 디렉토리 내에 각 클라이언트 서버들의 hostname들이 생성되었는지 확인

sudo ls -lh /var/log/remote

image


4. 외부망 PC에서 브라우저 주소 http://192.168.219.170:3000로 접근

  • 192.168.219.170 : 라우터의 외부 인터페이스 주소
    • 라우터에 역방향 NAT가 설정된 상태여야함.
    • 192.168.219.170:3000 -> 172.16.0.70:3000
  • :3000 : docker proxy로 외부에 오픈된 그라파나 컨테이너 외부 포트 주소 (내부 컨테이너 포트가 아님)

image 초기 로그인 정보: admin/admin


5. Data Source에 Loki 추가
image

💥 URL 주소
http://<로키 컨테이너명>:3100


Explore 탭 이동 - Label filters 지정 후 로그 모니터링
image


Loading script...