RSYNC+SSH 를 이용한 증분 백업 설정 및 Cron을 이용한 자동화

Incremental Backup Using RSYNC+SSH and cron
RSYNC+SSH 를 이용한 증분 백업 설정 및 Cron을 이용한 자동화

관리 하는 서버가 많아지고 서버에 저장되는 데이터의 양이 늘어 날 수록 백업을 어떻게 하여야 하는지 고민이 생긴다. 이 포스트에서는 RSYNC와 SSH를 이용하여 여러 서버의 데이터를 백업하고 이를 자동화 하는 방법에 대하여 기술 한다. 테스트를 위한 서버 구성은 다음과 같다. 아래 예제 에서는 S-01, S-02, S-03의 /home 디렉터리를 BackupBot으로 백업 하고자 한다.

공통 준비 사항

Backup User 생성

백업을 위한 사용자 계정을 생성한다.

$ sudo adduser --disabled-password --gecos 'BackupMan' backupmanCode language: JavaScript (javascript)

SSH 키 생성 및 배포

SSH KEY 생성 (BackupBot)

ssh-keygen 명령으로 SSH KEY를 생성한다.

$ ssh-keygen -t rsa -b 4096 -f backupman -C BackupMan

SSH KEY 배포

private 키를 앞서 생성한 backupman 계정 으로 복사한다.

$ sudo mv backupman ~backupman/.ssh/backupman
$ sudo chown backupman:backupman ~backupman/.ssh/backupman

each 서버로 ssh public key를 배포한다.

scp ~/backupman.pub 172.18.18.100:authorized_keys
scp ~/backupman.pub 172.18.18.101:authorized_keys
scp ~/backupman.pub 172.18.18.102:authorized_keys

SSH public key 설치

각 서버에 접속 하여 앞서 복사한 SSH public KEY를 backupman 계정에 복사한다.

$ sudo mv authorized_keys ~backupman/.ssh/authorized_keys
$ sudo chown backupman:backupman ~backupman/.ssh/authorized_keys
$ sudo chmod 600 ~backupman/.ssh/authorized_keys

서버 설정

백업 하고자 하는 서버에 접속 하여 다음과 같이 설정 한다.

필요 패키지 설치

$ sudo apt-get install -y rsyncCode language: JavaScript (javascript)

권한 설정

/etc/sudoers 파일을 열어 권한을 설정 한다.

$ sudo visudo

아래 내용을 추가

backupman ALL=(ALL) NOPASSWD: /usr/bin/rsync --server --sender -vlogDtprze.iLsfx --numeric-ids . /*
Code language: JavaScript (javascript)

BackupBot 설정

필요 패키지 설치

sudo apt-get install -y rsync uuidCode language: JavaScript (javascript)

Backup 스크립트 설치

$ sudo -H pip install git+https://github.com/harues/python-backupman.git@master
$ backupman --version
\Code language: JavaScript (javascript)


권한 설정

/etc/sudoers 파일을 열어 권한을 설정 한다.

sudo visudo

아래 내용을 추가한다

backupman ALL=(ALL) NOPASSWD: /usr/local/bin/backupmanCode language: JavaScript (javascript)

SSH Client 설정

~/.ssh/config 파일을 열어

sudo -u backupman -H vi ~backupman/.ssh/config

다음과 같이 설정한다. (해당 파일이 없을 경우 생성한다.)

Host S-01-BACKUP
Hostname 172.18.18.100
User backupman
Port 22
SendEnv LANG LC_*
IdentityFile ~/.ssh/backupman
ConnectTimeout 0
HashKnownHosts yes
GSSAPIAuthentication yes
GSSAPIDelegateCredentials no

Host S-02-BACKUP
Hostname 172.18.18.101
User backupman
Port 22
SendEnv LANG LC_*
IdentityFile ~/.ssh/backupman
ConnectTimeout 0
HashKnownHosts yes
GSSAPIAuthentication yes
GSSAPIDelegateCredentials no

Host S-03-BACKUP
Hostname 172.18.18.102
User backupman
Port 22
SendEnv LANG LC_*
IdentityFile ~/.ssh/backupman
ConnectTimeout 0
HashKnownHosts yes
GSSAPIAuthentication yes
GSSAPIDelegateCredentials noCode language: JavaScript (javascript)

SSH Client 접속 확인

다음 명령으로 배포된 KEY로 SSH접속이 정상적으로 되는지 확인한다.(Password를 물어 보지 않으면 성공.)

sudo -u backupman -H ssh S-01-BACKUP
sudo -u backupman -H ssh S-02-BACKUP
sudo -u backupman -H ssh S-03-BACKUP

백업 테스트

백업테스트를 위해 backupman 계정으로 로그인 한다.

sudo -u backupman -i

다음 명령을 통해 백업 스크립트가 정상적으로 동작 하는지 확인한다.

S-01

sudo backupman -i -r ssh://S-01-BACKUP/home /home/backupman/S-01
Code language: JavaScript (javascript)

S-02

sudo backupman -i -r ssh://S-02-BACKUP/home /home/backupman/S-02
Code language: JavaScript (javascript)

S-03

sudo backupman -i -r ssh://S-03-BACKUP/home /home/backupman/S-03
Code language: JavaScript (javascript)


Cron에 Task 등록

위 명령이 정상적으로 수행되어 백업이 완료 되었으면 cron에 등록 하여 주기적으로 백업이 이루어 지도록 한다.

sudo -u backupman -H crontab -e

다음 명령을 03, 04, 05시에 각각 S-01, S-02, S-03에대한 백업을 수행 하도록 job을 등록한 예제 이다.

0 3 * * * sudo /usr/local/bin/backupman -i -r ssh://S-01-BACKUP/home /home/backupman/S-01
0 4 * * * sudo /usr/local/bin/backupman -i -r ssh://S-02-BACKUP/home /home/backupman/S-02
0 5 * * * sudo /usr/local/bin/backupman -i -r ssh://S-03-BACKUP/home /home /home/backupman/S-03Code language: JavaScript (javascript)

Docker Compose 커맨드 사용법

Docker Compose는 여러 개의 컨테이너(container)로 구성된 애플리케이션을 관리하기 위한 간단한 오케스트레이션(Orchestration) 도구입니다. 이번 포스트에서는 Compose 애플리케이션을 터미널에서 제어하기 위해 사용되는 Docker Compose 커맨드에서 대해서 알아보겠습니다.

-f 옵션

Docker Compose는 기본적으로 커맨드가 실행하는 디렉토리에 있는 docker-compose.yml 또는 docker-compose.yaml를 설정 파일로 사용합니다. 다른 이름이나 경로의 파일을 Docker Compose 설정 파일로 사용하고 싶다면 -f 옵션으로 명시를 해줍니다.

$ docker-compose -f docker-compose-local.yml up

-f 옵션은 여러 개의 설정 파일을 사용할 때도 사용할 수 있습니다. 이 때는 나중에 나오는 설정이 앞에 나오는 설정보다 우선하게 됩니다.

$ docker-compose -f docker-compose.yml -f docker-compose-test.yml up

up

docker-compose up 커맨드는 아마도 Docker Compose에서 가장 자주 사용되는 커맨드일 텐데요. Docker Compose에 정의되어 있는 모든 서비스 컨테이너를 한 번에 생성하고 실행하기 위해서 사용합니다.

보통 -d 옵션을 사용하여 백그라운드에서 컨테이너를 띄우는 경우가 많습니다.

$ docker-compose up -d
Creating network "django-app_default" with the default driver
Creating django-app_db_1 ... done
Creating django-app_web_1 ... done
Code language: JavaScript (javascript)

-d 옵션을 사용하지 않으면 현재 터미널이 컨테이너의 로그가 출력되고 Ctrl + C를 눌러서 탈출하는 순간 컨테이너가 모두 정지되기 때문입니다.

down

docker-compose down 커맨드는 docker-compose up 커맨드와 정반대의 동작을 합니다. Docker Compose에 정의되어 있는 모든 서비스 컨테이너를 한 번에 정지시키고 삭제합니다.

$ docker-compose down
Stopping django-app_web_1 ... done
Stopping django-app_db_1  ... done
Removing django-app_web_1 ... done
Removing django-app_db_1  ... done
Removing network django-app_default

start

docker-compose start 커맨드는 내려가 있는 있는 특정 서비스 컨테이너를 올리기 위해서 사용합니다. 대부분의 경우에는 docker-compose up 커맨드를 사용해도 내려간 서비스를 알아서 올려주므로 무방합니다.

$ docker-compose start web
Starting web ... done

stop

docker-compose stop 커맨드는 docker-compose start 커맨드와 정반대의 동작을 합니다. 돌아기고 있는 특정 서비스 컨테이너를 정지시키기 위해서 사용합니다.

$ docker-compose stop web
Stopping django-app_web_1 ... done

ps

docker-compose ps 커맨드는 Docker Compose에 정의되어 있는 모든 서비스 컨테이너 목록을 조회할 때 사용합니다.

$ docker-compose ps
      Name                    Command               State           Ports
----------------------------------------------------------------------------------
django-app_db_1    docker-entrypoint.sh postgres    Up      5432/tcp
django-app_web_1   python manage.py runserver ...   Up      0.0.0.0:8000->8000/tcp

logs

docker-compose logs 커맨드는 서비스 컨테이너의 로그를 확인하고 싶을 때 사용하며, 보통 -f 옵션을 붙여서 실시간 로그를 확인합니다.

$ docker-compose logs -f web
Attaching to django-app_web_1
web_1  | Watching for file changes with StatReloader
web_1  | Performing system checks...
web_1  |
web_1  | System check identified no issues (0 silenced).
web_1  |
web_1  | May 30, 2020 - 22:16:29
web_1  | Django version 3.0.6, using settings 'our_project.settings'
web_1  | Starting development server at http://0:8000/
web_1  | Quit the server with CONTROL-C.Code language: JavaScript (javascript)

exec

docker-compose exec 커맨드는 실행 중인 서비스 컨테이너를 대상으로 어떤 명령어를 날릴 때 사용합니다.

$ docker-compose exec db psql postgres postgres
psql (12.2 (Debian 12.2-2.pgdg100+1))
Type "help" for help.

postgres=#Code language: PHP (php)

run

docker-compose run 커맨드는 서비스 컨테이너의 특정 명령어를 일회성으로 실행할 때 사용합니다.

$ docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=10757eb6642e
TERM=xterm
LANG=C.UTF-8
GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568
PYTHON_VERSION=3.8.2
PYTHON_PIP_VERSION=20.1
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/1fe530e9e3d800be94e04f6428460fc4fb94f5a9/get-pip.py
PYTHON_GET_PIP_SHA256=ce486cddac44e99496a702aa5c06c5028414ef48fdfd5242cd2fe559b13d4348
PYTHONUNBUFFERED=1
HOME=/rootCode language: JavaScript (javascript)

config

docker-compose config 커맨드는 Docker Compose 설정을 확인할 때 사용합니다. -f 옵션으로 여러 개의 설정 파일을 사용할 때, 최종적으로 어떻게 설정이 적용되는지 확인해볼 때 유용합니다.

docker-compose config
services:
  db:
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
    image: postgres
  web:
    build:
      context: /Users/dale/temp/django-app
    command: python manage.py runserver 0:8000
    depends_on:
    - db
    ports:
    - 8000:8000/tcp
    volumes:
    - /Users/dale/temp/django-app:/web:rw
version: '3.0'Code language: PHP (php)

Raspberry PI에 Docker 설치

Raspberry PI 4 (이하, RPi4) 가 국내에도 정식으로 출시를 했습니다.
RPi4 에 설치하는 최신 Raspbian OS 는 ‘buster’ 라는 이름이 붙어 있습니다.
이 buster OS 를 설치한 RPi4 에 docker 를 설치해 보고자 합니다.

Info
apt 명령을 이용해서 docker package 를 쉽게 설치 할 수 있습니다만 최신의 버전을 사용하고자 한다면 아래 방법을 사용하는게 좋습니다. 참고로, buster 현재 버전에는 최신의 docker 버전을 포함하고 있습니다.

1. 사용 기기

  • H/W: Raspberry Pi 4 Model B Rev 1.2 (4GB RAM 모델)
  • OS: Raspbian GNU/Linux 10 (buster)
  • Kernel 4.19.75-v7l+

2. Docker 설치 script 를 다운 받자!

Docker 는 다른 package 와 다르게 apt 로 설치 하지 않고, 다음과 같이 별도의 Script 를 이용해야만 합니다.

$ curl -fsSL get.docker.com -o get-docker.shCode language: JavaScript (javascript)

다운로드 받은 Shell script 를 살짝 열어 보니 이전 버전에서 보이던 Docker 설치 가능 OS 목록이 없어졌습니다. 그럼, RPi4 buster 에 설치가 가능한 지를 어떻게 확인하면 좋을까 하던 차에 다른 Script 가 하나 더 있다는 것을 확인했습니다. 바로 test-docker.sh 입니다.

$ curl -fsSL https://test.docker.com -o test-docker.shCode language: JavaScript (javascript)

3. 일반 계정으로 Docker 사용하도록 설정

원래 docker 는 root 권한으로 실행해야만 합니다. 그러나, root 권한이 아닌 일반 계정(non-root account) 에서 매 번 ‘sudo’ 를 붙여서 명령을 입력하는 것은 매우 귀찮은 일이 아닐 수 없습니다. 일반 계정에서 sudo 없이도 docker 실행이 가능하도록 하기 위해서 일반 계정을 docker group 에 포함 시켜 주도록 합니다.

여기서는 RPi 의 기본 계정인 pi 를 docker group 에 포함시켰습니다.

$ sudo usermod -aG docker pi

설정을 마친 후, logout 하고 다시 login 하면, sudo 없이 docker 명령을 사용 할 수 있습니다. 단, 이 경우, 일반 계정이 root 권한을 부여 받아서 발생할 수 있는 보안상 취약점이 있다는 사실을 명심해야 하겠습니다.

4. test-docker.sh 로 docker 설치 가능 확인 후 설치

다운로드 받은 test-docker.sh 을 실행하면 docker 설치가 가능한 지와 어떤 버전을 설치할지를 확인해서 Docker 를 설치합니다. 설치 정보는 아래와 같이 보여 줍니다.

$ bash test-docker.sh
# Executing docker install script, commit: 6bf300318ebaab958c4adc341a8c7bb9f3a54a1a
+ sudo -E sh -c apt-get update -qq >/dev/null
+ sudo -E sh -c apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sudo -E sh -c curl -fsSL "https://download.docker.com/linux/raspbian/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sudo -E sh -c echo "deb [arch=armhf] https://download.docker.com/linux/raspbian buster test" > /etc/apt/sources.list.d/docker.list
+ sudo -E sh -c apt-get update -qq >/dev/null
+ [ -n ]
+ sudo -E sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sudo -E sh -c docker version
Client: Docker Engine - Community
 Version: 19.03.5
 API version: 1.40
 Go version: go1.12.12
 Git commit: 633a0ea
 Built: Wed Nov 13 07:37:22 2019
 OS/Arch: linux/arm
 Experimental: false
Server: Docker Engine - Community 
Engine:
 Version: 19.03.5
 API version: 1.40 (minimum version 1.12)
 Go version: go1.12.12
 Git commit: 633a0ea
 Built: Wed Nov 13 07:31:17 2019
 OS/Arch: linux/arm
 Experimental: false
containerd:
 Version: 1.2.10
 GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339
runc:
 Version: 1.0.0-rc8+dev
 GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
docker-init:
 Version: 0.18.0
 GitCommit: fec3683Code language: PHP (php)

5. docker 서비스 동작 확인

docker 설치가 제대로 되었다면 docker daemon 이 동작하고 있을 겁니다. ps 명령을 이용해서 확인해 보았습니다.

$ ps auwx|grep docker
root      2744  0.1  1.5 966736 61112 ?        Ssl  13:38   0:01 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sockCode language: JavaScript (javascript)

docker daemon이 잘 동작하고 있습니다.

6. docker container 를 확인해 보자!

docker daemon 이 동작하고 있으므로 다음과 같이 실행 중인 docker container 가 있는지 확인해 보겠습니다.

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS       NAMES

6. “Hello, World”

여기까지 완료하였다면 RPi 에서 docker 사용이 가능합니다. 대표적인 “Hello, World” 를 출력해 볼까요?

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1eda109e4da: Pull complete 
Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm32v7)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/
For more examples and ideas, visit:
 https://docs.docker.com/get-started/Code language: JavaScript (javascript)

이 다음 부터는 일반 Linux machine 과 동일하게 docker 를 사용 할 수 있습니다.