본문 바로가기
카테고리 없음

개발환경 도입기5편 - Docker Swarm으로 테스트 서버 구축하기

by 난파선 2020. 4. 21.

현재 개발되고 있는 투자플랫폼 테스트 서버를 재구축을 해서 거기에 대한 애기를 할려고 합니다.

다시 서버를 구축하게 된 이유


현재 개발중인 투자플랫폼 같은 경우 정식으로 런칭이 안되었기 때문에 테스트(개발) 서버만 구축이 되어있는 상태였습니다.

그런데 개발되고 있는 투자플랫폼 서비스를 투자자쪽에서 개발상태를 보기를 원했고 문제는 해당서버는 아슬아슬할 정도로 자원을 최대한으로 사용하고 있어 안정적이지 못했습니다.

서버가 안정적이지 못하니 서비스가 죽는 경우가 빈번했고 투자자에게 혹은 다른 사람들에게 소개를 하기 어려웠습니다. 그래서 안정적으로 서버를 바꿔달라는 요청이 있어 서버환경을 수정하게 되었습니다.

이전 테스트 서버


기존의 테스트 서버의 경우 하나의 AWS EC2 인스턴스를 사용하였고 배포의 경우 각 프로젝트마다 도커 이미지를 만들 수 있는 Dockerfile이 존재하여 젠킨스에서 프로젝트를 빌드하고 결과물인 jar파일을 Dockerfile에 내용을 바탕으로 도커 이미지를 만들고 도커 컴포즈를 사용하여 프로젝트를 구동하였습니다.

❗️

문제점

1. 서버가 한대로 해당 서버가 죽으면 해당서비스가 전부 죽는 다.

2. API 서비스 중에 하나가 죽을 경우 자동으로 서비스가 다시 올라가지 않는 다.

3. 에러로그를 수집하는 곳이 없어서 로그를 보기 어렵다.

4. 에러가 났을 경우 노티가 없다.

해결방안

1. 서버를 2대로 운영한다.

경우에 따라 테스트 서버를 실섭으로 변경하고 테스트 서버를 새로 구축할 걸 생각을 하기도 했고 서버가 하나가 죽을 경우를 대비하여 일단은 2대로 구성하기로 했습니다.

2. Docker Swarm을 도입한다.

레플리카의 갯수를 설정하면 서비스가 죽거나 서버가 죽는 경우에 다른 쪽 서버에서 자동으로 설정한 갯수만큼 자동으로 유지를 해줍니다. 나중에 서버를 확장하거나 축소를 할 수 있습니다.

가장 많이 사용하는 쿠버네티스를 생각하지 않은 것은 아니지만 Swarm보다 무겁고 실섭으로 변경할 계획이 있다고 해도 일단은 테스트 서버이기 때문에 Swarm를 선택하게 되었습니다.

수정된 테스트(개발)서버 예상도


1. Jenkins에서 배포 버튼을 누르면 Git에 있는 소스를 pull 받는 다.
2. 넥서스에서 필요한 라이브러리를 가지고 와서 maven 빌드를 한다.
3. 빌드된 파일(jar)을 마스터 테스트 서버로 보내고 해당 서비스의 Dockfile을 바탕으로 도커 이미지를 생성한다.
4. 생성된 이미지 파일을 Nexus Docker Hub에 올린다.
5. 이미지들을 각각의 서버에 보내고 해당 서비스들을 업데이트 한다.

구축과정


1. 여러서버에 배포될 도커이미지를 저장할 Docker Hub 구축 및 설정

가장 먼저 기존에 존재하던 Nexus에 Docker Hub를 구축하려고 했습니다. 하지만 여기서 문제가 발생했습니다. Docker Hub를 구축하려면 하나의 외부포트가 더 필요했습니다.

그런데 문제는 기존에 설치된 Nexus에 경우 도커로 설치가 되어 있는 데 가동 중인 컨테이너에서 새로 외부포트를 추가하는 방법이 없었습니다. 검색을 해보니 기존의 컨테이너를 커밋하고 새로운 컨테이너를 만드는 방식이 있었습니다.

docker stop nexus
docker commit nexus sonatype/nexus3
docker run -name nexus -d -p 8081:8081 -p 5000:5000 sonatype/nexus3

위와 같은 방식 이였는 데 해봤는 데 기존의 nexus에서 설정했던 리파지토리들이 유지가 되지 않았습니다. 그래서 결국 새로 만들게 되었습니다.

Docker Hub 구축


일단 nexus에서 사용되는 기존의 8081번 포트외에 docker hub에서 사용될 포트가 하나 더 필요합니다. 저 같은 경우는 5000번 포트를 열었습니다. 그리고 두개의 Repositories가 필요합니다.

첫번쨰는 docker (hosted) 타입의 Repositories가 필요합니다.

이름은 원하시는 대로 정하시고

HTTP 영역에 외부포트로 연 포트를 입력합니다. 저 같은 경우는 5000번을 열었기 때문에 5000번을 입력했습니다.

그리고 Enable Docker V1 API를 체크해줍니다.

해당 Repositories는 사내에서 올릴 이미지들이 저장될 저장소입니다.

두번째로는 docker(proxy) 타입에 Repositories를 만들어 줍니다.

이름은 원하시는 대로 정하면 됩니다.

Enable Docker V1 API 를 체크해줍니다.

Proxy - Remote storge에 https://registry-1.docker.io를 입력해줍니다.

Proxy - Docker Index: Use Docker Hub를 체크해 줍니다.

프록시해 올 리파지토리를 선택하는 설정입니다.

Realms에서 Docker Bearer Token Realm 을 추가해줍니다.

구축된 Docker Hub 사용 설정


이제 설정한 Docker Hub를 볼 수 있게 설정을 하겠습니다.

  • 윈도우라면 오른쪽 아래 도커 아이콘을 마우스 오른쪽을 클릭해서 Setting을 선택한다.
  • 맥이라면 우측상단에 도커 아이콘을 마우스 오른쪽 클릭하여 Preferences을 선택한다.

그러면 도커 설정관련한 창이 나오는 데 Docker Engine 부분에서 "insecure-registries": ["넥서스 주소:5000"]를 추가해준다.

{
  "debug": true,
  "experimental": false
    "insecure-registries": ["xx.xxx.xx.102:5000"]
}

그리고 적용을 누르면 도커가 재시작을 하게 된다. 그 후에 커맨드 창을 열고 _docker login 넥서스주소:5000_을 입력해준다.

docker login "xx.xxx.xx.102:5000"

이제 서버에도 적용 시켜 보자. (우분투 리눅스 18 기준입니다.) 서버에 접속을 한 후에 daemon.json 파일을 열어서 편집을 한다.

sudo vi /etc/docker/daemon.json

daemon.json

{
    "insecure-registries": ["xx.xxx.xx.102:5000"]
}

저장하고 나온 후에 도커를 재시작하고 로그인 한 후 사용하면 됩니다.

sudo service docker restart
sudo docker login "xx.xxx.xx.102:5000"

2. 도커스윔 서버 구축

1. AWS EC2에서 마스터 서버 하나와 노드 서버로 사용될 서버 하나씩 두개의 우분투 18버전의 인스턴스를 생성한다.

2. 마스터 서버에 ssh로 접속을 하여 docker swarm init 명령어를 입력한다.

```
 ssh -i [키이름].pem ubuntu@[서버주소]

 docker swarm init
```

3. 해당 명령어를 입력하면 노드를 추가하는 명령어가 나온다. 해당 명령어를 노드 서버에 접속하여 입력한다.

```
 예) docker swarm join --token SWMTKN-1-22a6j0ndrbnkkhj2s1kko94h0mwok0yj9wsdgng5jq8xwtbmka-d3826as2lmc5z3dymw0qclzck xx.xxx.xx.99:2377
```

4. 포트 열기 Swarm에서 사용되는 포트들이 몇가지가 있다. Aws에서 사용할려면 여기에 대한 보안정책을 추가해 주어야 한다. 처음에는 잘 몰라서 삽질을 했고 검색해도 잘 안나와서 힘들었다.

-   클러스터 관리용 통신 포트: TCP 2377
-   노드 간 통신용 포트: TCP/UDP 7946
-   오버ㅔ레이 네트워크 트래픽 용 포트: UDP 4789

❗️처음에 잘 모르고 TCP로 열어서 문제가 좀 있었는 데 이 글을 보시는 분은 잘보고 UDP로 열어야 되는 거는 UDP로 열기를 바란다.

3. 기존의 Docker-Compose 파일을 Docker Swarm 에 맞게 수정

  1. 기존의 yaml 버전의 경우 2.1 이였는 데 Docker Swarm에서 docker-compose를 사용하기 위해서는 버전을 3.0으로 변경한다.
  2. 기존의 build 옵션을 image로 변경하고 network 관련된 부분을 수정했다.

version: '2.1'

services:

  company:
  build: ./microservices/company
  mem_limit: 300m
  networks:
    - my-network
  environment:
    - SPRING_PROFILES_ACTIVE=docker
                  .
                  .
                  .

version: '3.0'

services:
company:

  image: [docker hub 주소]/company
  environment:
    - SPRING_PROFILES_ACTIVE=swam-test
        .
        .
        .

networks: {}

4. 마스터 서버에서 도커 스웜 실행

sudo docker stack deploy -c [파일경로/파일명] [stack 이름] --with-registry-auth

도커 스윔과 도커 컴포즈를 연동해서 실행하려면 stack 명령어를 사용해야 합니다.

서비스를 올리는 명령어로는 deploy, 파일 선택 옵션은 -c 파일경로/파일명 그리고 stack 이름을 입력하고 내부적으로 설정한 docker-hub에서 이미지를 가져오려면 —with-registry-auth 옵션을 주면 된다.

docker service ls로 올라간 서비스를 확인할 수 있다.

각각의 서비스에 자세한 정보를 보려면 docker service ps [서비스명]

로그를 보려면 docker service logs [서비스명]을 하면 된다.

개별로 올리고 싶다면 아래 명령어를 참조해서 올리면 됩니다.

sudo docker service create --name [서비스명] -p [포트] -e [환경변수] --replicas=[서비스수] --network [네트워크명] --with-registry-auth [이미지명]

5. Jenkins에서 서비스 업데이트 설정

sudo docker build --tag xx.xxx.xx.102:5000/shop:latest ./invest/microservices/shop
sudo docker push xx.xxx.xx.102:5000/shop:latest 
sudo docker service update --image xx.xxx.xx.102:5000/shop:latest test_shop --with-registry-auth

도커 이미지를 새로 빌드해서 만들고 Docker hub에 올린 후 서비스를 업데이트 합니다.

남은 작업


  1. ELK 도입, 로그를 수집한다.
  2. 에러가 발생하면 채팅프로그램으로 노티를 보낸다.

댓글