Oracle VM 설치

 

Oracle 사이트에서 Virtual Machine 최신버전을 받는다.

https://www.oracle.com/kr/virtualization/technologies/vm/downloads/virtualbox-downloads.html?source=:ow:o:p:nav:mmddyyVirtualBoxHero_kr&intcmp=:ow:o:p:nav:mmddyyVirtualBoxHero_kr

 


Ubuntu server 이미지 받기

 

https://ubuntu.com/download

- 컨트롤러 IDE에 Ubuntu 이미지 지정

 


Proxy 설정

 

Proxy 문제로 외부 인터넷 연결이 안됌

 

   -> /etc/apt/apt.conf.d 밑에 아무파일이나 만들고 하기 내용 입력

Acquire::http::proxy "http://proxy.server:port/";
Acquire::https::proxy "http://proxy.server:port/";

 

참고 ( https://wlsvud84.tistory.com/26 )

 


Geust Addition 설치

 

VM 호스트 서버와 게스트 서버간에

클립보드 및 복사 붙여넣기 기능을 활성화 하였으나, 작동하지 않음

 

구글링에 Geust Addition 설치해보라는 글 발견하여 설치

 

다운로드 - ( Oracle VM ftp Arcive : http://download.virtualbox.org/virtualbox/ )

 


apt-get 다운로드 서버 변경

 

프록시 연결하여도, 프록시망에서 모든 URL 방화벽이 오픈된게 아니기 때문에

 

가끔 ubuntu 아카이브 서버까지 접근해야하는경우 연결이 안된다.

 

속도 이슈도 있고, 카카오 미러페이지로 다운로드 서버를 변경하자

 

vi /etc/apt/sources.list 內 URL 변경

=> :%s/kr.archive.ubuntu.com/mirror.kakao.com/g 을 통해 전부 치환가능

 


인증서 설정

 

ㅁ 인증서를 구한다음에 openssl을 통해 crt 확장자로 바꿔준다.

openssl x509 -in ABC.pem -inform pem -out ABC.crt

 

ㅁ /usr/share/ca-certificates/extra 디렉토리 생성후, 변환된 crt 인증서 이동

 

ㅁ 인증서 패키지 reconfig후 해당 인증서 추가.

sudo dpkg-reconfigure ca-certificates 

'IT > 서버 구성해보기' 카테고리의 다른 글

로컬서버 (2) WAS - DB 연결  (1) 2021.04.23
로컬서버 (1) 환경 설정  (0) 2021.04.23

내가 생각하는 쿠버네티스. 줄여서 k8s라 부르는 용어에 대한 정의는 아래와 같다.

 

컨테이너 관리를 위한 오픈소스 플랫폼 

 

좀더 다양한 해석이 있을 수 있지만,

아직 아무것도 모르는 단계에서 '컨테이너 관리' 에 집중하려 한다.

 


기능

 

쿠버네티스 공식문서에 따르면, 기능은 아래와 같다.

 

  • 서비스 디스커버리 ( 서비스에 매핑된 IP와 클래스를 찾아줌 )
  • 로드 밸런싱 ( 컨테이너에 대한 트래픽을 분산 )
  • 오케스트레이션 ( 스토리지 , 네트워킹 등 리소스에 대한 관리 )
  • Roll Out & Roll back ( 자동 배포 및 특정버전 롤백기능 )
  • bin 패키징 ( 필요한 컨테이너 리소스를 효율적으로 부여 )
  • 셀프 힐링 ( 기능 체크를 통한 정상여부 확인 및 Fail된 컨테이너에 대해 자동으로 재시작 )
  • 보안 ( 토큰 및 SSH 키 등의 관리 )

 

 

구성요소

 

공식 문서상 아키텍처는 아래 그림과 같다.

 

https://kubernetes.io/ko/docs/concepts/overview/components/

 

봐도 모르는 상태라 

 

먼저 구성요소들에 대해 정리하고, 흐름을 하나씩 파악해보려한다.

 

1) Pod

 

쿠버네티스에서 배포를 하는 최소단위. 하나 이상의 컨테이너를 포함한다.

 

이전 도커에서는, 컨테이너 단위로 배포를 했었으나 쿠버네티스에는 스토리지 및 네트워크가 포함된다.

=> IP:Port 및 디스크 볼륨 공유가능

 

물론 여러개의 컨테이너도 포함될 수 있으며, 배포 시 Pod 단위로 넘어간다

 

https://kubernetes.io/ko/docs/tutorials/kubernetes-basics/explore/explore-intro/

 

 

2) Node

 

이러한 하나 이상의 Pod들이 모여, 노드를 구성한다.

 

노드는 Pod가 배포되고 수행되는 최소한의 하드웨어 단위이며,

 

물리적 혹은 가상화된 개별 머신으로 생각하면 된다.

 

아래 아키텍처를 확인해보면 노드에 Kubelet과 k-proxy가 붙어있다.

 

이에 대해 확인해보자.

 

 

2-1 kubelet

 

위 그림상, Control Plane ( Master Node )와 통신하며 작업을 관리하는 에이전트이다.

 

2-1 kube-proxy

 

iptable 관리 및 네트워크 분산이라고 나와있으나

 

간단하게 Control Plane ( Master Node )와 통신 자체를 담당하는 네트워크 관리 담당이다.

 

 

 

3) Control Plane

 

Master Node라고도 불리며, 클러스터에 대한 관리를 담당함. 이벤트 감지 및 처리, 스케쥴링 등을 수행한다.

 

 

3-1 API Server

 

사용자가 접근할수 있도록, HTTP / REST 등의 API를 제공하며

 

컨트롤 플레인 內 컴포넌트나 Node와 통신하며 요청을 수행함.

 

 

3-2 etcd

 

고가용성 데이터 저장소.

 

key - value 형식이며, 클러스터에 대한 정보등을 저장한다.

 

( ex: Pod 생성시 정보 기록 . 실행 Node , 상태값 등 )

 

https://www.kangwoo.kr/2020/09/05/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4%EC%9D%98-etcd-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0/

 

3-2 Scheduler

 

새로 생성된 Pod를 감지하고, 어느 Node에 부여할지 결정

 

3-3 Kube Controller Manager

 

클러스터 內 오브젝트를 관리 ( 노드, 레플리카 셋, 서비스 등 )

 

 

 

※ Cloud Controller Manager ( c-c-m )

 

AWS, Azure 등 클라우드에 특화된 모듈로,

 

쿠버네티스 컨트롤러들을 클라우드에서 관리할 수 있게 연결해준다.

 

로컬환경에서 VDI로 구성할거라, 자세히는 다루지 않을 예정

 


 

 

정리

 

 

사용자가 Pod를 만드는 상황을 통해, 흐름을 정리해보려 한다.

 

1) API 서버로 Pod 생성 요청

 

 

2) API 서버에서 etcd로, 요청된 Pod 의 Manifest 입력

 

3) API 서버에서 컨트롤러 매니저에 Pod 생성 요청

 

생성된 Pod는 다시 API Server로 전달되고, 이 Pod 정보를 다시 etcd에 입력

 

4. API 서버에서 스케쥴러에 Pod 할당 요청

 

스케쥴러는 할당 가능한 Worker Node를 회신하고, API 서버는 etcd에 입력

 

 

5) 할당받은 Node에 Pod 생성 요청

 

Kube Proxy를 통해 네트워크 통신을 하고, Kubelet 에서 Node에 Pod를 띄운다.

 

Kubelet은 Pod 상태를 주기적으로 회신하고, API Server는 etcd에 기록한다.

 

 

이번에는 유저 요청에따라 동적으로 데이터를 리턴해주려고한다.

 

이를 위해, DBMS를 설치해 데이터를 저장하고, 조건에 맞는 Value 값을 찾아서 회신할 것이다.


1) My sql 설치

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

 

※ 방화벽 설정이 되어있다면, Mysql 포트를 열어주어야 한다. ( 3306 )

 

sudo ufw allow mysql

 

ㅁ 실행 및 DBMS 접속

 

service mysql service
mysql -u root -p

 

ㅁ 데이터베이스 및 유저생성

 

Mysql> CREATE DATABASE USER;
Mysql> CREATE USER 'pyadm'@'localhost' IDENTIFIED BY 'password';

 

ㅁ 권한 부여 및 확인

 

Mysql> GRANT ALL PRIVILEGES ON USER.* to pyadm@localhost;
Mysql> grant all privileges on *.* to 'pyadm'@'localhost';
root> mysql -u pyadm -ppassword

 

2) 데이터 구성

 

ㅁ ID를 KEY 값으로, 이름을 필드로 갖는 user_info 테이블 생성

CREATE table user_info( id int(10) NOT NULL, name char(20) DEFAULT NULL, PRIMARY KEY (id) );

 

ㅁ 테스트 데이터 입력

 

INSERT INTO user_info VALUES(1234,'kim');
INSERT INTO user_info VALUES(123,'Lee');
commit;

 

3) Python - Mysql 연결

 

pip3 iinstall --proxy [proxy_ip] --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org PyMysql

 

ㅁ 테스트 코드 작성 ( 커넥터 설정 및 커서 )

 

import pymysql

user_db = pymysql.connect (
  user='pyadm',
  passwd='password',
  host='localhost',
  db='user',
)

cursor = user_db.cursor()
sql= " select * from user_info"

cursor.execute(sql)
print(cursor.fetchall())

 

4) request 에서 조건값 가져오기

 

http://localhost:80/api/users/1234

 

ㅁ Rest_api 서버 코드 수정

 

@api.route('/api/users/<int:id>')   -- id라는 변수를 만들어 int 값 저장
class HelloWorld(Resource):
  def get(self,id):  -- 멤버 변수 파라미터로 id 설정
    return {"id": id, -- id 변수값
              "name": "kim"}

 

 

5) 가져온 조건값을 DB에 입력하여, 리턴해주도록 수정

 

@api.route('/api/users/<int:id>')
class HelloWorld(Resource):
 def get(self,id):
    cursor = user_db.cursor()
    sql = " select * from user_info where id= " + str(id)
    cursor.execute(sql)
    data=cursor.fetchall()
    return {"id": data[0][0],
              "name": data[0][1]}

 

 

Nginx는 경량 웹 서버로, 가벼움과 높은 성능을 목표로 하는 웹서버이다.

 

주로 정적 웹페이지를 리턴하는 용도나 Reverse Proxy를 통해 로드밸런서로 사용한다.


특징으로는 Event-Driven 구조로 되어있어, Apache 웹서버에 비해 더 작은용량으로 운영이 가능하다.

 ※ Apache 웹서버는 1개의 클라이언트 요청 = 1개의 쓰레드로, 동기화방식.

 

Event-Driven 에서는, 요청을 Event Handler를 통해 이벤트를 발생시키고

 

비동기로 처리하여 다량의 요청을, 효율적으로 처리할 수 있다.

 


Reverse Proxy를 사용해서 아래 그림처럼 아키텍처를 구성해보려한다.

 

1) 기존 80포트로 열려있던 python api 서버를 82포트로 변경

2) Nginx 설치 및 Reverse Proxy 설정

apt-get update
apt-get install nginx

 

/etc/nginx/conf.d/default.conf 

 

server {
 listen 80; // 80포트로 리슨하고
 
 location /api/ { //api 리퀘스트 요청이 온다면
 proxy_pass http://localhost:82; // 파이썬 rest_api 서버로 포워딩
 }
}

3) Nginx reload 및 Python 가동 후 연결

 

nginx -s reload
python3 rest_api.py

=> Nginx 에서 해당 리퀘스트 처리 페이지를 찾지 못하였다.

  => 프로세스가 안떠있는가? ( X )

  => 컨테이너 포트오픈이 안되어있는가? ( X )

 

가정1) rest_api 컨테이너 포트오픈이 안되었다?

 

Nginx 까지는 도달하였으나, rest_api 컨테이너는 오픈이 안되어있어 도달하지 못했다.

=> 같은 컨테이너에 Nginx 와 Python을 띄운거라 네트워크 이슈는 아닌 것으로 예상

 

가정2) rest_api 포트 ( 82 ) 에 대해, 컨테이너 포드 포워딩이 안되어있다.

 

현재 Nginx 포트 ( 80 )은 -p 80:80 설정으로,

Localhost:80으로 오는 리퀘스트를 컨테이너 80포트로 자동 매핑해주고있다.

 

하지만 Rest_api 포트 ( 82 )에 대해서는 매핑되는게 없어

Nginx에서 Localhost:82로 포워딩 하면, 컨테이너의 IP:82와 연결이 되지 않아 발생하지 않을까?

 

현재 컨테이너 커밋후, 포트매핑 추가하여 가동해보자.

 

sudo docker run -it -p 80:80 -p 82:82 sk007001/rest_api:python /bin/bash

=> 똑같이 404 에러가 발생한다.

 

하지만 이번에는, localhost:82 포트로는 바로 rest_api 호출이 가능하다

 

가정3) Reverse Proxy가 제대로 동작하지 않는다.

 

프론트인 Nginx도 문제없고, 백단에 Python도 제대로 리슨중이니

 

중간을 연결해주는 Reverse Proxy가 문제있지 않을까?

 

일단 스택오버플로우에서, /etc/nginx/site-enabled 의 default 링크를 지워보라는 답변을 발견했다.

 

=> 지우고 접속해보니, 80 포트로 접속한 리퀘스트가 82로 포워딩 되는것을 확인했다.

==> 그렇다면, 파이썬에서 받았는데 404 에러가 발생하는 이유는???

 

가정4) Python Rest_api 코드의 문제

 

먼저 발견한 특이점은, Nginx에 localhost:80/api/users 로 보내어도

 

Reverse Proxy를 타면 localhost:82/api/users/ 로 리퀘스트가 보내진다는 것이었다.

 

파이썬 코드를 열어보니 /api/users 로 클래스 매핑이 되어있었고, 이를 수정해준뒤 제대로 리턴해주는것을 확인하였다.

 

 

이번에는 도커위에 Python을 사용하여 Rest Api를 수신하는 서버를 만들어 볼 예정이다.

※ Rest Api에 대해서는 하기 글을 참조
2021.07.29 - [IT/아키텍처] - Rest

대략적인 아키텍쳐는 아래와 같다.

(1) 유저가 HTTP 메소드를 사용해서, 도커에 떠있는 Nginx의 api location 호출하면 ( 80 Port )
(2) Nginx Reverse Proxy를 사용하여, Python으로 Request를 포워딩 해준다 ( 82 Port )
(3) Rest Api를 구현한 Python에서 해당값을 리턴해주고
(4) Nginx는 json 타입으로 유저에게 Response 해줄 계획이다.

 


1) Python Rest Api Server 구성

 

[참조] - https://justkode.kr/python/flask-restapi-1 // Flask로 Rest API 구현하기

 

- Docker 위에 Pyhton 및 라이브러리 설치 

  ※ 이미지 생성 및 프록시 세팅부분은 생략하고 작성

 

ㅁ Python 설치

apt-get update
apt install python3

[설치확인] python3 --version

 

ㅁ Pyhton 라이브러리 설치를 위한 pip 설치

 

apt-get update
apt-get install python3-pip

=> 설치중에 커넥션 에러 발생. security.ubuntu는 접근하나, archive.ubuntu 에는 접근 못하는 것으로 추정

Get:116 http://security.ubuntu.com/ubuntu bionic-updates/main amd64 python3-xdg all 0.25-4ubuntu1.1
[31.3 kB] Fetched 105 MB in 1min 6s (1586 kB/s)
E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/i/isl/libisl19_0.19-1_amd64.deb Could not connect to XXXXX

=> ubuntu repository를 변경하자. ( mirror.kakao.com )

 

vi /etc/apt/sources.list
=> 편집창에서 :%s/archive.ubuntu.com/mirror.kakao.com

apt-get update
apt-get install python3-pip

- Flask 다운로드

 

Flask : Micro web framework로 직역하면 가볍게 사용할수 있는 웹 프레임워크다.

         간단한 rest api 서버 혹은 Web 서버 구성시에 사용한다.

 

pip3 install Flask

이제는 익숙한 프록시, SSL 오류.

 

1) 구글링하니, trusted host 옵션을 주라고 한다.

   => 동일 에러

pip3 install --trusted-host pypi.python.org flask

 

2) 블로그에 프록시 컨피그 적용 후, 수행 가이드

pip3 install --proxy your_proxy_path Flask

=> SSL 문제로 URL 접속 불가 이슈

==>VM 환경이 아닌, 로컬 환경에서는 인터넷 접속 이상없음

 

1,2 옵션을 동시에 주면된다. 

- 프록시를 통해 패키지 Install

- SSL 없이, python host에 대해서는 신뢰

 

-> Flask 및 dependency 패키지 다운로드 성공

 

같은 방법으로 Flask-restx 도 설치해준다.

 

 

- Rest Server Code 작성

 

from flask import Flask  
from flask_restx import Api, Resource 

app = Flask(__name__)  
api = Api(app)  


@api.route('/api/users')  # /api/user 에 클래스 매핑
class HelloWorld(Resource):
    def get(self):  
        return {"id": 123,
        "name": "kim"}

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=80)

 

- 컨테이너 이미지로 커밋하고, 포트 매핑해서 다시 띄워보자

 

sudo docker commit $Container_ID sk007001/rest_api:python

sudo docker run -p 80:80 sk007001/rest_api:python python3 /python/rest_api.py
[ -p ] : 호스트의 80 포트로 오는 요청을 해당 컨테이너 80포트로 연결
[ python3 /python/rest_api.py ] : 위에 만들어둔 rest api 코드 실행

 

- RestClient 를 사용하여, 리퀘스트를 던져보자

 

 

※ 보완할 점

 

- 컨테이너 수행시 명령어가 너무길다.

  이미지에 수행될 명령어를 미리 지정하여, 컨테이너만 수행해도 rest_api 서비스가 올라가도록 변경해볼 것

 

- DB 연결후, /api/users 뒤에 파라미터값에 따라 다른 값을 리턴하는 로직 구현

 

- Nginx 리버스 프록시 기능을 활용하여 위의 그림처럼 연결할 것

리오그에 대해 설명하기전에, 필요성에 대해 언급하고 넘어가자.


특정 Tablespace가 Full이 차서, 테이블 데이터 일부를 지웠다고 가정해보자.

 

과연 아래경우 TBS 용량은 얼마가 될까?

 

1) 60%

2) 100%

 

 

 

 

 

 

 

 

 

 

※ HWM ( High Water Mark ) : 지금까지 점유되었던 공간의 최고점

 

 

1) 60%

2) 100%

 

100% 이다. 기존의 할당된 영역은 그대로고, 사이에 데이터만 지워졌기 때문이다.

 

이런 경우 실제 데이터 양과는 상관없이,

TBS와 HWM이 동일하기 때문에 아래 문제가 예상된다.

- 신규 데이터 Insert 불가
- Full Table scan시에 HWM까지 탐색하므로, 불필요한 작업 발생

 

Truncate 하면 ( 테이블 구조만 남기고, 데이터는 모두 삭제 )

TBS 확보 및 HWM 위치를 조절할 수 있으나

 

일부 데이터만 삭제하려는 위의 케이스에는 맞지않다.

 

해당 케이스에는 비워진 공간만큼 재구성하는 리오그 ( Reorganization ) 작업이 필요한 것이다.

 


Reorg 방법

 

1) ALTER TABLE MOVE

 

- 속도가 빠르다

- 데이터 용량만큼의 TBS 공간 추가로 필요

- TBS 오프라인 필요

 

1) 임시 테이블 스페이스 생성
CREATE TABLESPACE '임시TBS명' DATAFILE 'DB파일_PATH' SIZE 1G;

2) 속도를 위해 해당 테이블 Nologging 모드
ALTER TABLE 테이블이름 NOLOGGING;

3) 데이터 삭제후, 대상 테이블 임시 테이블스페이스로 이동
ALTER TABLE '테이블명' MOVE TABLESPACE '임시TBS명';

4) 기존 테이블스페이스로 원복
ALTER TABLE '테이블명' MOVE TABLESPACE '기존TBS명';

5) 인덱스 상태 확인
SELECT TABLE_NAME, INDEX_NAME, STATUS FROM DBA_INDEXES WHERE TABLE_NAME = '테이블명';
-> 지워진 인덱스의 경우, 실제 delete가 아닌 Unusable 마킹만 되어있다.
    계속 두면 segment가 실 데이터양보다 커질 수 있으니, rebulid 명령어로 정리해주자. 

ALTER INDEX (INDEX_NAME) REBUILD;

 

[참조]

https://positivemh.tistory.com/350

 


2) Shrink

 

- 온라인작업

- 오라클 10g 이상

- Undo TBS 확보 必

- 이동하는 Row에 대해 순간 Lock ( Enqueue ) 가 걸릴 수 있음

 

1) 각 row들 빈공간으로 이동 가능하게 설정
alter table 'Table명' enable row movement;

2) Row 이동
alter table 'Table명' shrink space cascade compact;
=> 실 데이터만 이동하고 HWM은 유지됌

3) HWM 이동 및 TBS 반환
alter table 'Table명' shrink space cascade ;

4) row 이동 X
alter table GSBN.TCOMCR_PRODUCT_VARIANT disable row movement;

 

'DB > Oracle' 카테고리의 다른 글

마이그레이션 (2) DB Link  (1) 2021.07.06
마이그레이션 (1) expdp/impdp  (0) 2021.07.06

우분투는 기본적으로 apt 를 사용하여 패키지를 설치한다.

 

- sudo apt-get update 명령어를 통해, ubuntu의 Repository를 업데이트한다.

여기서 업데이트란, Repository에 존재하는 패키지 버전 업그레이드가 아닌
접근 가능한 패키지들의 리스트를 업데이트를 의미한다.

  

- sudo apt install [패키지] 명령어 수행으로, 패키지 설치

 


에러케이스

 

1) Unable to locate package [패키지] 

 

Repository 에서 해당 패키지명을 찾지 못했다는 이야기이다.

 

없는 패키지명을 설치하려 했거나, 패키지 리스트가 최신 버전이 아닐 때 발생한다.

 

 

[해결]

- 패키지명 정확하게 입력
- sudo apt-get update 명령어로 패키지 리스트 최신화.

 

 

2) Install 속도 이슈

 

패키지 설치시, 속도가 너무 느린경우가 있다.

 

Repository 주소가 해외로 설정되어있는 경우가 대부분으로

 

Ubuntu 기본 Repoitory 인 archive.ubuntu.com 로 되어있을 것이다.

 

 

[ 확인 ]

 

vi /etc/apt/sources.list

 

[ 해결 ] 

 

Mirror 사이트로 Repository 주소를 바꿔준다.
- kr.archive.ubuntu.com ( 한국 )
- mirror.kakao.com ( 카카오 )

sources.list 를 편집기로 열어서, 기존 주소를 미러사이트로 치환해준다.
- :%s/archive.ubuntu.com/mirror.kakao.com
- :%s/security.ubuntu.com/mirror.kakao.com

이후 apt-get update로 변경된 Repository 적용

 

 

3) Repository 접근 불가

 

 

설치 도중에 하기 에러가 발생하는 경우가 있다. ( Connection failed )

 

로그에 남아있는대로, 해당 저장소에 접근하지 못하는 경우다.

 

 

[ 해결 ] 

 

웹페이지 직접 접속
=> 로컬 PC에서 인터넷을 켜, 해당 URL에 직접 접근해본다.

1) 접근이 되지 않는다면, 방화벽 문제로 예상된다. 
   - 커맨드창을 열어 telnet archive.ubuntu.com 80 으로 프롬프트가 떨어지는지 확인 후, 방화벽 체크
   - 혹은 Repository 주소를 접근 가능한 곳으로 바꾸었다. 

2) 접근이 된다면, 프록시를 사용하는지 확인해본다.
=> 나 같은경우네는 가상머신을 사용중이었다.
     가상머신 내에는 프록시 세팅이 되어있지 않아 접근이 불가능하였다.
     

 

※ Ubuntu 프록시 세팅

 

/etc/apt/apt.conf.d 디렉토리내에 아무 파일이나 만들고, 하기 내용을 입력한다

 

vi /etc/apt/apt.conf.d/apt-proxy-set

Acquire::http::Proxy "http://[ProxyIP:Port]"
Acquire::https::Proxy "https://[ProxyIP:Port]"

MSA를 공부하다보면, 서비스간에 REST Api로 통신한다고 나와있다.

여기서 말하는 REST의 정의는 무엇인지 찾아보고, 구현해보려한다

 


REST

자원자원에대한 주소를 지정하는 방법에 대한 아키텍쳐이다.

REST 아키텍쳐를 따르는 시스템을 Restful, API 통신을 Rest Api 라고도 한다.

 

 


특징 6가지

1) Uniform (유니폼 인터페이스)
2) Stateless (무상태성)
3) Cacheable (캐시 가능)
4) Self-descriptiveness (자체 표현 구조)
5) Client - Server 구조
6) 계층형 구조

 

1) 유니폼 인터페이스

 

URI로 지정된 리소스에 대해, 통일된 인터페이스로 수행되는 것을 의미한다.

 

나같은 경우는 통일된 (Uniform) 인터페이스라는 표현의 이해가 어려웠는데,

클라이언트의 환경 ( 플랫폼 / 프로그래밍 언어 )에 종속되지 않는 느슨한 결합 ( Loosly Coupling ) 아키텍쳐가 더 이해하기 쉬웠다.

 

 

2) 무 상태성

 

서버단에서 상태 정보(컨텍스트)를 저장하지 않음을 의미한다.

 

세션이나 쿠키같은 정보를 저장하지않고, Request에 대해 들어온 요청대로 수행하기만한다.

요청에 대해 History 고려 및 정보 저장이 필요없으므로, 구현이 간단해진다는 장점이 있다.

 

 

3) 캐시 가능

 

HTTP 메소드를 사용하기에, 기존 캐시 기능을 그대로 사용할 수 있다.

 

Last-Modified 혹은 E-tag를 사용하여 데이터 갱신유무를 파악하고, 변화가 없으면 클라이언트의 자체 캐시값을 활용한다

 

※ HTTP Cash 프로세스
- 리퀘스트 헤더에 Last Modified를 포함하거나, E-tag를 사용하여 보낸다 ( E-tag가 우선됨 )

1) Last Modified 값을 If-modified-Since 헤더에 포함시켜, 서버측의 시간과 비교한다.
2) E-tag 값을 If-None-Match 에 포함시켜, 서버측의 값과 비교한다
=> 값이 같다면 304 Not Modified 리턴코드를 응답하고, 클라이언트는 가지고있는 캐시값을 사용한다.

 

4) 자체 표현 구조

 

리퀘스트만 보고도 무슨 내용인지 직관적으로 파악이 가능해야한다.

 

예를들어, GET http://localhost/customer/123 라는 리퀘스트가 있다고 하자.

단번에 회원중에 키값(회원ID)가 123인 사람을 조회하는 GET 메소드 라는것을 알 수 있다.

 

 

5) 클라이언트 - 서버구조

 

API를 통해 요청하고, 인증이나 컨텍스트 정보를 직접 관리하는 Client 와

접근가능하도록 API를 제공하는 Server 역할로 나누어 독립적인 개발이 가능하도록 한다.

 

 

6. 계층형 구조

 

클라이언트 입장에서는 Api를 통해 서버로 요청하지만,

서버 내부적으로 다양한 계층을 지닐수 있다.

 

스위치 , WEB 서버등을 통해 사용자 인증, SSL, 로드밸런싱 등을 구현할 수 있으며

Apache Reverse Proxy나 HA Proxy 등을 통해 Host 분리없이 구현할 수 있다.

 


구현 가이드

 

1. 자원에 대한 행위는 CRUD를 사용한다.

 

Create - [HTTP Post] 해당 리소스를 생성한다.
Read   - [HTTP Get] 해당 리소스를 조회한다.
Update - [HTTP Put] 해당 리소스를 수정한다.
Delete  - [HTTP DELETE] 해당 리소스를 삭제한다.

 

2. URI는 정보를 표현해야한다. ( 명사형 )

 

1번과도 연관된 내용이다.

동사는 CRUD로 제한하고, 나머지 자원에 대한 정보는 모두 명사로 표시한다.

 

 

3. /로 리소스 계층을 식별한다

 

ex ) GET http://localhost/customer/123

      마지막에 /는 혼동을 줄수있기에 넣지 않는다.

 

 

4. 모든 경로에는 소문자를 사용한다.

 

대소문자에 따라 리소스를 다르게 인식하기 때문에, 대문자는 사용하지 않는다.

 

 

5. 하이픈 ( - )을 통한 가독성 

 

언더바 ( _ )는 환경에 따라 보기 힘들수도 있기때문에,

URI 내의 가독성을 높이고 싶으면 하이픈을 사용한다.

 

ex) GET http://localhost/vip-customer/123 ( O )
    GET http://localhost/vip_customer/123  ( X )


※ HTTP Response Code

 

Rest Api를 통해 리퀘스트에 단순 응답만 하는것이 아닌

다양한 Response Code 들을 통해, 처리결과를 좀더 정확하게 회신주어야한다.

 

대표적인 값은 

2xx (성공): 요청을 성공적으로 받았으며 인식했고 수용하였다
 - 200 : 클라이언트 요청을 정상적으로 수행함
 - 201 : 서버가 요청한 리소스 생성작업을 성공함

3xx (리다이렉션): 요청 완료를 위해 추가 작업 조치가 필요하다
 - 301 : 사용자가 요청한 페이지에 대해 URI가 변경되었다.

4xx (클라이언트 오류): 요청의 문법이 잘못되었거나 요청을 처리할 수 없다
 - 400 : 사용자가 요청이 어떤것인지 인식하지 못했을 때
 - 401 : 사용자의 권한이 부족하거나 인증이 완료되지 않음
 - 403 : 금지된 리소스에 사용자가 접근할 때
 - 404 : 존재하지 않는 리소스를 요청했을 때
 - 405 : 잘못된 메소드로 서버에 요청했을 때

5xx (서버 오류): 서버가 명백히 유효한 요청에 대해 충족을 실패했다
 - 500 : 내부 서버오류로 인해 요청 수행 불가

 

https://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C

 

HTTP 상태 코드 - 위키백과, 우리 모두의 백과사전

아래는 HTTP(하이퍼텍스트 전송 프로토콜) 응답 상태 코드의 목록이다. IANA가 현재 공식 HTTP 상태 코드 레지스트리를 관리하고 있다. 모든 HTTP 응답 코드는 5개의 클래스(분류)로 구분된다. 상태 코

ko.wikipedia.org

 

 

[참조]

https://meetup.toast.com/posts/92

'IT > 아키텍처' 카테고리의 다른 글

MSA ( MicroService Architecture )  (0) 2021.07.13
Monolithic  (0) 2021.07.03

이번에는 Hello Wolrd를 출력하는 웹페이지를 만들어보려고 한다.

다양한 방법으로 만들어볼껀데, 아래 3가지 방식으로 구현 할 것이다.

1) front 페이지만 만들고, nginx 이미지를 받아 페이지만 적용
2) 제로 베이스에서, 우분투위에 Nginx를 올려 커스텀 이미지를 만드는 방식
3) Docker File을 통한 구현

 

1) Nginx 이미지에 home 화면만 바꾸어서 적용

 

- 홈 화면인 index.jsp 페이지 작성

 

- Nignx 이미지 다운로드 및 사용법 확인

 

나처럼 페이지 컨텐츠만 바꿔서 띄우려는 사람들이 많았는지, 설명 가장 위에 적혀있었다.

$ docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx

※ 옵션

--name : 컨테이너의 이름을 지정

-v : {PATH1}:{PATH2} Host의 디렉토리를 Conatiner에 마운트

 

 

여기에 Host:Conatiner 포트매핑만 해서 가동시켜보겠다.

sudo docker run --name hello-nginx -v /docker:/usr/share/nginx/html:ro -p 80:80 -d nginx

 

 

이상하게 페이지 접근시, 화면이 나오지 않고 파일 다운로드가 된다.

 

jsp 확장자를 인식못하는것 같아, html로 변경해보고 다시 접근해보려한다

 

sudo docker exec -it $Container_ID /bin/bash  
=> 해당 컨테이너에 접속

 

접속해서 해당 컨텐츠 확장자 변경하려했으나, 컨테이너 내부에서는 Mount 된 디렉토리 內 변경 불가

 

Host 에서 직접 변경 및 컨테이너 내부에서 변경된 것 확인

 

 

변경후에 잘 되는것 확인


2) 커스텀 이미지 만들기

 

우분투 기반의 Hello World2를 출력하는 커스텀 이미지를 생성하려한다.

 

 

- 베이스이미지 ( 우분투 ) pull

 

docker run -it --rm --name hello_nginx_v2 ubuntu:18.04

 

- 컨테이너 내에 nginx 설치

 

apt-get install nginx

 

nginx 패키지를 못찾았다... 패키지 인스톨시에는 저장소 업데이트를 항상 먼저해주자

 

??? 

저장소에 접근을 못하고있다. 프록시 문제로 예상된다

2021.06.30 - [IT/도커도커] - (1) Ubuntu에 도커 설치하기 - 프록시 설정 참조

 

기존 VM Host에는 프록시 설정을 해주었으나

Conatiner는 새로운 Ubuntu OS를 띄운셈이므로, 다시 적용해주어야한다.

 

그런데 우분투 컨테이너에는 기본 편집기가 없다 ( nano, vim 등등 )

그래서 귀찮지만 conf.d 파일을 Host 에서 Container로 옮겨줘야한다.

sudo docker cp /etc/apt/apt.conf.d/90curtin-aptproxy hello_nginx_v2:/etc/apt/apt.conf.d/

 

 

프록시 설정 완료후, 저장소 업데이트 및 nginx Install

 

Index.html 파일 변경

 

sudo docker cp /docker/index.html hello_nginx_v2:/usr/share/nginx/html

 

 

컨테이너 Commit 하여 이미지 생성

 

sudo docker commit hello_nginx_v2 sk007001/hello-world:v0.2

 

 

컨테이너 수행

 

sudo docker run -p 80:80 -d sk007001/hello-world:v0.2

 

 

이미지 Hub에 Push

 

정상 동작하는것을 확인했으니, Hub에 올리자

 


3) Dockerfile를 통한 구현

 

FROM ubuntu:18.04

RUN apt-get update
RUN apt-get install -y nginx

ADD /docker/index.html /usr/share/nginx/html

EXPOSE 80

WORKDIR /etc/nginx

CMD ["nginx", "-g", "daemon off;"]

 

FROM : ubuntu를 베이스로 지정

 

RUN apt-get update : ubuntu 패키지 리스트를 업데이트

RUN apt-get install -y nginx: nignx 패키지를 인스톨 ( 모든것에 동의함. -y )

 

ADD : Host에 만들어둔 index 파일을 컨테이너로 복사

 

EXPOSE : 컨테이너의 80포트로 접속할 수 있게 오픈

 

WORKDIR : 커맨드 실행할 Path 지정

 

CMD : nginx를 백그라운드로 실행

 

 

- Docker Build

 

 

패키지 업데이트 실패하였다...

프록시 설정안해줘서 일텐데, 매번 설정해주기 귀찮다. 디폴트 지정하는법이 있는지 찾아봐야겠다.

 

일단 수동으로 옮겨주자.

- 프록시 컨피그 파일을 컨테이너로 수정

 

ADD /etc/apt/apt.conf.d/90curtin-aptproxy /etc/apt/apt.conf.d/

 

 

해당 파일을 못찾는다고 나온다.

/Docker 에서 빌드했는데 하위 디렉토리에서 파일을 못찾은듯 하다.

 1) /에서 빌드하고 image Path 수동지정

 2) 해당 파일들 /Docker 하위로 이동

 

2번 방법을 사용해서 진행하자

 

 

이번에는 호스트의 81포트를 열어서, 컨테이너 80포트로 연결해주자

 

sudo docker run -p 81:80 -d sk007001/hello-world:v0.3

 

 

정상적으로 컨테이너가 올라갔으나, 404 not found 발생

 

1) index.html 파일 부재

 

- sudo docker exec -it bfe /bin/bash 접속
- /usr/share/nginx/html 밑의 커스텀 index 파일 확인
- 존재하는 것 확인

2) root 디렉토리 확인

- 컨테이너의 nginx conf 확인 ( /etc/nginx/nginx.conf -> /etc/nginx/sites-enabled/default )
- root : /var/www/html로 되어있는데 혹시 이거때문에...?

- root 디렉토리 위치를 /usr/share/nginx/html로 바꾼후 nginx reload 수행

 

- 81포트/index.html 접속

 

+ Recent posts