블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

리눅스 방화벽과 NAT를 위한 ipTables


서버에서 라우팅 설정을 하다보면, 다른 포트로 받아야 하는데, 로드밸런서나 방화벽등의 문제로 포트를 변경할 수 없는 경우가 있어서 A포트로 들어오는 트래픽을 B포트로 변경하고 싶을때가 있다.

또는 서버로 들어오는 트래픽을 IP등으로 선별적으로 받는 것과 같은 방화벽 역할이 필요한 경우가 있는데, 방화벽을 설치하지 않고 서버단에서 간단하게 하는 방법이 필요한 경우가 있는데, 이러한 용도를 위해서 사용할 수 있는 것이 ipTables이다. 


ipTables는 리눅스 firewall로 incoming & outgoing traffic을 rule에 따라 filtering 하는 기능을 가지고 있다. ipTables는 table이라는 단위를 가지고 있는데, 이 table 마다 룰을 정해서 룰에 매치되는 트래픽에 대해서 핸들링할 수 있는 기능이 있다. 

주로 사용되는 테이블은 다음과 같다

  • Filter table :  가장 많이 사용되는 테이블로, 트래픽에 대한 컨트롤을 하는 방화벽 역할로 사용된다.

  • NAT table :  들어오는 패킷을 다른 포트나 다른 호스트 서버로 라우팅 하는 역할을 한다.

  • Mangle table : 패킷의 헤더를 변경하는데 사용할 수 있다. (예 TTL 등)


각 테이블은 체인(CHAIN)으로 구성이 되는데, 각 단계별로 하는 역할이 다르다.


Filter table

먼저 Filter Table을 보면 다음과 같다. 

%iptabls -L -v

명령어를 이용하면 필터 테이블을 볼 수 있는데, 크게 Input,Forward,Output 체인으로 구성이 되어 있다. 

예를 들어 보면

%sudo iptables -A INPUT -i lo -j ACCEPT

는 모든 들어오는 트래픽에 대해서 Loopback interface는 모든 트래픽을 허용하도록 INPUT CHAIN을 설정한 것이다. 

만약 http,https,SSH 만 허용하려면 다음과 같이 사용하면 된다. 

%sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

%sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

%sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT


특정 IP에서 들어오는 트래픽을 허용하고자 하면 

sudo iptables -A INPUT -s 192.168.1.3 -j ACCEPT

게 설정하면 된다. 

반대로 특정 IP에서 들어오는 트래픽만 막고자 한다면 DROP을 하면 되는데, 

sudo iptables -A INPUT -s 192.168.1.3 -j DROP

명령을 사용하면 된다. 


등록된 rule을 삭제하려면

sudo iptables -L --line-numbers

명령을 사용하면, 등록된 룰이 번호와 함께 나오고 

sudo iptables -D INPUT 3

명령으로 3번째 룰을 삭제할 수 있다. 


iptables 명령어는 수정한 테이블과 룰은 메모리에만 남아 있기 때문에 재기동하면 삭제된다. 

그래서 영구 반영하기 위해서는

sudo /sbin/iptables-save

명령으로 저장해야 한다. 

NAT table

다음으로 유용하게 사용할 수 있는것이 NAT 테이블인데 들어온 트래픽을 다른 호스트로 라우팅 시키거나 또는 같은 호스트내의 다른 포트로 포워딩 시키는 것이 가능하다. 

패킷은 들어오면 아래와 같은 체인들을 거쳐가는데, 그림에서 보면 nat와 filter 체인이 섞여 있는 것을 볼 수 있다. 


트래픽은 들어오면 NAT의 PRE ROUTING을 거쳐, FILTER의 INPUT을 거쳐서 애플리케이션으로 들어갔다가 나올때 FILTER의 OUTPUT 체인과, NAT의 OUTPUT 체인을 거쳐서 최종적으로 NAT의 POSTROUTING 체인을 거쳐서 목적지로 라우팅 된다. 



그림 출처 : https://www.systutorials.com/816/port-forwarding-using-iptables/


이 과정에서 NAT 테이블의 체인 중 주로 사용되는 CHAIN을 보면

  • PREROUTING : 들어온 트래픽을 다른 호스트나 또는 같은 호스트의 다른포트로 포워딩 할때 사용된다.

  • POSTROUTING : 호스트에서 아웃바운드로 나가는 트래픽을 다른 IP나 포트로 포워딩 한다. 


예를 들어보면 아래는 80포트로 들어온 트래픽을 같은 호스트의 4000포트로 포워딩하는 설정이다. 


sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 4000


참고로 이렇게 하면 외부에서 80 포트로 들어오는 트래픽은 4000으로 라우팅 되지만, localhost:80 으로 호출을하면 이는 라우팅이 되지 않는데, 이유는 localhost는 PREROUTING CHAIN을 타지 않기 때문이다. 그래서 만약 localhost에도 동일하게 작동하게 하려면 Output chain을 아래와 같이 설정해줘야 한다.

iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

참고 : https://askubuntu.com/questions/444729/redirect-port-80-to-8080-and-make-it-work-on-local-machine


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

API 게이트 웨이

What is API 게이트웨이

API 게이트웨이는 API 클라이언트와 서비스 사이에 프록시 처럼 위치하여, 클라이언트로 부터 온, API 요청을 받아서, 서비스로 라우팅 하는 역할을 한다. 

각각의 서비스에서 구현해야 하는 기능을 API 게이트웨이단으로 통합함으로써, 서비스 개발을 간편하게 할 수 있고, 메세지 포맷 변경이나, 플로우 컨트롤과 같은 고급 기능을 사용하여, 기존 API 호출에 추가적인 기능을 더할 수 있는 유연성을 더할 수 있게 된다.


여러가지 기능이 있겠지만, 크게 아래와 같이 5가지로 나눠볼 수 있다.

  • 인증

  • 모니터링,로깅

  • 플로우 컨트롤

  • 메시지 변경

  • 오케스트레이션(매쉬업)





<출처 : 마이크로소프트 애저 홈페이지>


인증

API를 호출할때, API 호출에 대한 인증을 수행한다. 서버간의 API 통신일 경우에는 간단하게 API 키를 사용하는 방법등이 있고, 다수의 클라이언트 (모바일 단말, 웹 자바스크립트 클라이언트)의 경우에는 사용자 계정 인증 후에, JWT 토큰을 발급하는 방식이 있다. 

모니터링 & 로깅

API 호출에 대한 모니터링을 통해서 API 별 응답시간, 장애율,호출 횟수를 모니터링 할 수 있게 하고, 경우에 따라서 개별 API 호출을 로깅한다. 

Metering & Charging

API를 대외로 서비스 하는 경우, API의 호출량을 모니터링 해야 하는데, 이 양을 기반으로 해서 API 서비스 호출 횟수를 통제하거나 또는 유료 API의 경우에는 과금을 해야 하기 때문에, 대외로 서비스를 하는 오픈 API 플랫폼인 경우에는 이러한 기능이 필요하다. 

메시지 플로우 컨트롤

메시지 플로우 컨트롤은 클라이언트로 부터 들어온 메시지의 흐름을 바꾸는 방법인데, 예를 들어 같은 API라도 버전에 따라서 구버전과 새버전으로 트래픽을 9:1로 라우팅하는 카날리 배포 방식이라던지, 들어온 API를 클라이언트의 위치에 따라 미국이나,한국에 있는 서비스로 라우팅을 하는 등의 로직을 구현할 수 있다. 

Limiting (throttling)

조금 더 고급화된 구현방법으로는 Limiting 기법이 있는데, 특정 API에 대해서 정해진 양 이상의 트래픽을 받지 못하도록 하여, 서비스를 보호하거나 또는 유료 API 서비스인 경우 QoS (Quality Of Service)를 보장하기 위해서 특정 양까지만 트래픽을 허용하도록 컨트롤할 수 있다. 

메시지 변환

메시지 변환은 고급 기능 중의 하나인데, 헤더에 있는 내용을 메시지 바디로 붙이거나, 다른 API를 호출해서 응답메시지를 두 API를 합해서 응답을 해주는 기능등을 구현할 수 있다. 

프로토콜 변환

그외에도 서로 다른 프로토콜에 대한 변환이 가능한데, 예를 들어 클라이언트로 부터는 gRPC로 호출을 받고, API서버로는 REST로 호출한다던가. SOAP/XML 기반의 메시지를 REST로 변환하는 등의 기능 구현이 가능하다. 

호출 패턴 변환

API 서버가 큐를 기반으로한 비동기 메시지 처리 패턴일때, API 게이트 웨이에서 이를 동기화 처리 패턴으로 바꿔서, 클라이언트 입장에서는 동기로 호출을 하면, API 서버에서는 비동기로 호출하는 형태와 같이 호출 패턴을 변화시킬 수 있다. 

오케스트레이션(매시업)

API 클라이언트가 한번 호출을 할때, 동시에 여러개의 API를 호출하도록 API 게이트웨이에서 호출을 해주는 방식이다. 예를 들어 API 클라이언트가 “상품 구매" 라는 API를 호출 하였을때, API 게이트웨이가 “상품 구매" API 서비스를 호출하고, “상품 추천" 이라는 API도 호출해서, 클라이언트로 구매 완료 메시지와 함께 추천 상품 리스트를 한번에 리턴하는 방식이다. 


경량형 게이트웨이와 중량형 게이트웨이

API 게이트 웨이는 근래에 마이크로 서비스가 각광을 받으면서 언급되기 시작하고 있지만, 사실 API 게이트 웨이라는 기술 자체는 오래된 기술이다. API 게이트 웨이 이전에는 SOA 제품군의 일부로 ESB (Enterprise Service Bus)가 SOAP/XML 웹서비스 기반으로 이러한 역할을 해주었는데, 잘못된 구현 패턴을 사용해서 문제가 된 케이스가 많다. 예를 들어서 과도하게 오케스트레이션 기능을 사용하였을 경우 API 게이트웨이 자체에 부하가 걸려서 전체 API 서비스에 성능 문제를 야기 하거나, 또는 파일 업로드 요청을 API 게이트 웨이를 통해서 함으로써 게이트웨이의 부하때문에 성능 문제가 생기는 경우가 있었다. 

SOAP/XML에서 REST API로 오면서, API 게이트웨이도 이러한 문제를 피하는 패턴형식으로 API 게이트 웨이가 포지셔닝이 달라졌다. 사실 매시업이나, 메시지 라우팅, 메시지 변환등과 같은 기능들은 사실 사용되는 일이 그렇게 많지 않고, 클라이언트단에서 처리해도 충분하기 때문에, 이러한 고급 기능 보다는 API 인증, 로깅/모니터링 위주의 최소한의 기능만 가지면서 경량화된 형태로 배포 및 운영이 간편한 경량형 API 게이트 웨이들이 소개 되기 시작하였고, 반대로 오픈 API를 고객을 대상으로 제공하면서 메시지 변환이나, 과금등 고급 기능을 제공하는 중량형 API 게이트 웨이들도 꾸준히 제품들이 제공되고 있다.


이러한 제품들에 대한 명시적인 구분은 없지만, 필자의 기준으로 봤을때, 경량형 API 게이트 웨이는 Kong등을 들 수 있고, 중량형 API 게이트 웨이는 APIgee, MuleSoft 등을 들 수 있다. 


전통적으로 중량형 API 게이트웨이의 아키텍쳐 구조는 API 게이트웨이가 클러스터 형태로 배포 된 후에, 그 뒤에 API 서버들이 배포되는 형태라면, 경량형 API 게이트웨이는 nginx나 node.js와 같은 가벼운 프록시 서버로 배포하고, 용량이 필요하다면 개별의 인스턴스들을 스케일링으로 늘리는 방법을 사용한다. 근래에는 중량형 API 게이트 웨이도 이러한 구조를 많이 참고해서 구조를 개선하고 있다. 

쿠버네티스와 API 게이트 웨이

이러한 API 게이트웨이들이 쿠버네티스의 등장과 함께 주목 받으면서, 쿠버네티스 지원을 넓혀나가고 있는데, 이 과정에서 흥미로운 아키텍쳐 구성을 보인다. 쿠버네티스는 이미 Service라는 리소스를 통해서 마이크로 서비스를 정의할 수 있고, Service를 묶어서 로드밸런싱을 하는 Ingress라는 리소스를 가지고 있다. 즉 Ingress는 Service간의 라우팅을 할 수 있는 일종의 초경량 API 게이트웨이로써의 기능을 가지는 구조인데, API 게이트웨이의 쿠버네티스 연동은, 새롭게 애플리케이션을 배포하고 설정하는 방식이 아니라 쿠버네티스 리소스 자체에 API 게이트웨이를 녹이는 방식으로 접근하고 있다.


아래 Kong API 게이트웨이의 구조를 보면, Kong 전용으로 컨테이너를 배포하지 않고, Kong API 게이트웨이용 Ingress를 정의해서 사용자가 Ingress를 사용하게 되면 API 게이트웨이를 사용할 수 있게 하였고, 메시지 변환이나 기타 기능이 필요할 경우 이를 CRD(Custom Resource Definition) 로 미리 등록해놔서 이를 사용하도록 하고 있다. 



<Kong API 게이트 웨이 아키텍처 출처  > 


구글의 Apigee의 경우에는 Apigee Hybrid라는 이름으로 Kubernetes를 지원하는데, 구조는 Istio Ingress를 앞단에 둬서 라우터로 이용하고 API 게이트웨이에서 처리하는 각종 로직을 Ingress 뒤에 Pod(아래 그림 4번)로 배포하여 기능을 수행하도록 하고 있다. 

API 호출을 통과 시키는 프록시는 이렇게 단순화 시키고, 관리 콘솔은 구글 클라우드로 위치 시켜서 운영을 최대한 단순화 시켰다. 


<출처 : 구글 apigee hybrid 문서 > 

구글의 API 게이트 웨이 - Cloud Endpoint

구글의 Cloud Endpoint는 경량형 API이다. 

기본적으로 nginX로 배포되서 프록시 처럼 동작하며, 기능은 API 인증과 모니터링/로깅정도 밖에 없지만 구조와 기능이 단순하기 때문에 사용이 편리하며, 또한 nginX 기반의 배포 방식으로 인해서 구글 클라우드 뿐만 아니라, 다른 클라우드나 ON-PREM에도 사용이 가능하다는 장점이 있다. 


구조는 다음과 같이 되어 있다.



<그림. Cloud Endpoint ESP 아키텍쳐 / 출처 >


ESP는 Cloud Endpoint의 Proxy, 즉 nginX를 이야기 한다. 프록시는 실제로 쿠버네티스 클러스터에 배포되고, 모니터링과 로깅, 컨트롤러는 구글 클라우드의 콘솔을 이용하게 된다. 

쿠버네티스에 배포하는 형태는 다음 그림과 같다. 

애플리케이션 컨테이너와 함께, 같은 Pod로 패키징 되고, ESP에서는 애플리케이션으로 트래픽을 localhost로 포워딩한다. 


<그림. ESP의 쿠버네티스 배포 형태 >


이런 구조를 가지기 때문에, Ingress, Istio 등 다른 쿠버네티스 플랫폼들과 유연하게 통합이 된다. 

API 인증은 여러가지 방법을 지원하는데, Firebase authentication, Google ID,SAML(SSO) 방식으로 사용자를 인증한후에, API 키(JWT)를 발급하는 방법이나, 서버간일 경우 Service Account를 사용하는 방법 또는 단순하게 API KEY를 사용하는 방법이 있고 또는 Custom 인증을 구현하여 JWT 토큰으로 인증할 수 있다. 인증 방식은 이 문서를 참고하면 된다.

로깅/모니터링

로깅과 모니터링은 End Point 콘솔에서 볼 수 있으며, 아래와 같이 서비스 단위로 응답 시간과 에러율등을 출력해준다


OPEN API (Swagger) 기반 포탈

그리고 중요한 기능중의 하나인데, API 스펙 문서를 포탈 형태로 보여준다. Swagger 문서 형태로 작성을 하면 아래와 같이 독립된 웹사이트 형태로 API 스펙 문서를 보여준다.


<그림. Cloud endpoint developer portal / 출처


멀티/하이브리드 클라우드

마지막으로, Cloud End Point는 ngnix 기반으로 배포가 가능하기 때문에, 구글 클라우드 뿐 아니라 타 클라우드나 온프렘 데이타 센터내에도 프록시(ESP)를 배포해서 사용하는 것이 가능하다. 


참고 문서


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

오픈소스 API 게이트웨이 Kong

#3 쿠버네티스 Kong

조대협 (http://bcho.tistory.com)


Kong Kubernetes

API 게이트웨이가 마이크로서비스의 중요 컴포넌트이다 보니, Kong이 마이크로 서비스에 적합한 K8S (aka. 쿠버네티스)에 어떻게 적용될 수 있는지가 궁금해서 아키텍쳐 관련 설명 내용을 찾아보았다. https://konghq.com/blog/kong-kubernetes-ingress-controller/ (아래 그림은, 이 동영상에서 캡춰하여 사용하였다.) 에 보면 Kong summit에서 발표된 영상이 있는데, 정리가 매우 잘되어 있다. 


기본 컨셉을 먼저 요약해보자면, Kong의 리소스들은 K8S의 리소스로 등록되어 사용되게 된다. API 게이트 웨이는 Ingress로 등록되고, Plugin들은 CRD (Kubernetes Custom Resource Definition)으로 등록되어 적용된다. 즉 별도의 Kong 설정을 하는 것이 아니라 쿠버네티스 리소스로 쿠버네티스 아키텍쳐에 따라서 등록이 된다는 이야기이다. 별도의 서비스나 서버를 기동하는 것이 아니라 K8S의 일부로 사용할 수 있도록 하고 있다. (동영상에서도 나오지만 Kong이 K8S 1’st citizen임을 계속 강조하고 있다.)


Kong의 쿠버네티스내의 배포 아키텍쳐는 다음과 같다. 

먼저 관리 서버 부분인 Control plane과, API 게이트 웨이 부분인 Data plane으로 나뉘어 진다. 


Control plane에는 Ingress controller가 있고, 이는 K8S의 API 서버와 통신을 통해서 명령을 받는다. 그리고 이 설정 정보를 psql 데이타 베이스에 저장한다. 

저장된 설정 정보는 Data plane 즉, API 게이트웨이 인스턴스에 반영이 된다. 

(만약에 psql이 죽어도 dataplane에 있는 프록시는 설정을 저장하고 있기 때문에 문제 없다.)


Kong의 리소스 맵핑

그러면 Kong API 게이트웨이에서 사용하는 리소스들은 어떻게 쿠버네티스 리소스로 맵핑이 될가?

쿠버네티스의 리소스를 Kong의 리소스로 맵핑(Translate) 해서 서비스 한다. 

아래는 Kong에서 사용하는 리소스들이다. 


이를 쿠버네티스 리소스로 맵핑한것은 다음과 같다. 




  • Route는 Ingress rule로 맵핑이 되고

  • Service 는 쿠버네티스의 Service로 맵핑 된다.

  • Target은 쿠버네티스의 pod가 되고

  • Upstream은 healthcheck와 LB로 정의 된다. 


게이트웨이에서 사용되는 플러그인 (라우팅이나 RateLimiting, Logging, 인증등)은 K8S의 CRD로 정의되어 있다.  CRD를 사용하게 되면 Ingress 에 반영되어서 사용된다.  

아래는 Rate limiting 플러그인을 K8S에서 CRD로 정의해서 사용한 예제이다

플러그인 CRD들은 ingress에 붙어서 사용된다. 




Ingress는 CRD와 함께 Limit rating, Logging, Routing등을 제공한다. 이러한 기능들은 대부분 Istio와 같은 Service mesh에도 있는데, Istio와 같은 서비스 메쉬와 비교할 경우, JWT 등  인증이 안되는 부분이 있는데, 이 부분을 보면 다소 차이가 있다. 


결론적으로 정리를 해보자면, Kong API 게이트웨이는 K8S에서는 Ingress로 정의되고, 플러그인은 CRD로 제공된다. Control Plane을 통해서 설정 정보가 저장되는 형태이다. 


쿠버네티스에 Kong을 설치하는 가이드는  https://docs.konghq.com/install/kubernetes/ 있는데, 설치는 Helm이나 Kustomize로 도 가능한데, 데이타 베이스에 대한 내용을 보면, 다음과 같다. 


"We recommend running Kong in the in-memory (also known as DB-less) mode inside Kubernetes as all the configuration is stored in Kubernetes control-plane. This setup drastically simplifies Kong’s operations as one doesn’t need to worry about Database provisioning, backup, availability, security, etc."


별도의 데이타 베이스 설치는 권장하지 않고, DB-less 모드로 설정하기를 권장하고 있다. 

YAML 파일로 설정을 정의해서 변경할 경우, 설정이 어떻게 전체 게이트웨이로 전파가되는지 등은 실제 테스트를 해봐야 알 수 있을듯



본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

오픈소스 API 게이트웨이 Kong

#2 아키텍쳐와 간단한 테스트

조대협 (http://bcho.tistory.com)

Kong 아키텍쳐

Kong API 서버의 배포 아키텍쳐는 다음과 같다. 


출처 : stackoverflow.com

Kong API 게이트웨이 각각 nginx 로 되어 있고, DB 모드의 경우에는 별도의 데이타 베이스 인스턴스를 사용한다. 지원되는 데이타 베이스로는 카산드라나 postgres를 사용할 수 있다. 

데이타 베이스를 사용하더라도 변경된 설정은 인스턴스에 바로 반영되지 않는다. 각 인스턴스가 설정 내용을 캐슁하기 때문인데, 캐쉬가 리프레쉬되어야 설정 내용이 반영된다. 

클러스터에서 Kong API 게이트웨이 인스턴스간의 로드 밸런싱을 하기 위해서는 각 인스턴스 앞에 로드밸런서를 배치 시킨다. 만약에 Session Affinity가 필요하다면 L4에서 IP나 Session based affinity를 설정해야 한다. 


Kong API 게이트웨이에서 각종 기능들은 nginX의 Lua 스크립트 모듈은 OpenResty를 이용한다. 

간단한 API 테스트

개념 이해가 끝났으면 간단한 테스트를 해보자

파이썬으로 간단한 API 서버를 구현하였다. app.py로 simpleapi:9001/api URL로 HTTP GET으로 간단하게 서빙하는 API가 있다고 할때


kong.yml을 다음과 같이 구현한다. 

_format_version: "1.1"


services:

- name: simpleapi

  url: http://simpleapi:9001

  routes:

  - name: simpleapi-route

    paths:

    - /simpleapiservice



simpleapi라는 이름으로 서비스를 등록하고 API 서버의 호스트 경로는 http://simpleapi:9001로 등록한다.

위의 설정은 {Kong IP}/simpleapiservice URL을 —> http://simpleapi:9001로 라우팅하도록 한 설정이다.

%curl localhost:8000/simpleapiservice/api


실행하면 http://simpleapi:9001/api 를 호출한 결과가 리턴된다. 


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요


xip.io is dns proxing service. It is easy to assign dns name to ip address.

This is way to assign Domain to Knative Service


kubectl patch configmap config-domain --namespace knative-serving --patch \

  '{"data": {"example.com": null, "35.225.xxx.216.xip.io": ""}}'



본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

Kong API gateway #1 - 설치와 둘러보기

카테고리 없음 | 2019. 11. 10. 23:58 | Posted by 조대협

오픈소스 API 게이트웨이 Kong

조대협 (http://bcho.tistory.com)


Kong API 게이트 웨이를 설치 하는 방법은 여러가지가 있지만, 여기서는 테스트 환경용으로 로컬 환경에 도커 이미지로 간단하게 설치 하는 방법에 대해서 알아본다. 

(도커 기반 Kong API 게이트 웨이 설치 방법 참고 :  https://docs.konghq.com/install/docker/)

전체 설치 방법은 https://docs.konghq.com/install 를 참고하기 바란다. 

설치 하기

Kong 설치하기

Kong API 게이트웨이는 데이타베이스가 필요하지만, 간편하게 데이타 베이스가 없는 dbless 모드로 설치를 한다. 웹 인터페이스를 이용하기 위해서 Konga (https://pantsel.github.io/konga/) 를 추가로 설치할 것인다. Konga도 도커 컨테이너로 설치한다. 이때 Konga도 가 Kong API 게이트웨이로 통신을 해야 하기 때문에,둘을 같은 네트워크로 묶어서 서로 통신하도록 하겠다.

(참고 : 도커 컨테이너는 네트워크 공간이 각각 분리되기 때문에, 다른 컨테이너간에 통신을 하기 위해서는 네트워크 공간을 묶어줄 필요가 있다. )

네트워크 생성하기

Kong API 게이트 웨이 Admin API를  Konga에서 호출할 수 있도록 같은 네트워크로 묶기 위해서 “kong-net”이라는 네트워크를 생성한다

$ docker network create kong-net

디스크 볼륨 생성하기

여기서는 데이타베이스 없이 Kong API 게이트웨이를 설치하기 때문에, 디스크 볼륨을 정의하여 디스크에 설정 정보를 저장하도록 한다. 아래와 같이 디스크 볼륨을 생성한다.  

$ docker volume create kong-vol

설정 파일 작성하기 

디폴트 설정 파일이 있어야 게이트웨이가 기동이 되기 때문에 디폴트 설정 파일을 만든다.

설정 파일은 앞서 만든 kong-vol 볼륨에 kong.yml 로 저장이 된다. 파일을 생성하기 위해서 볼륨의 호스트 파일상의 경로를 알아보기 위해서 docker volume inspect 명령을 사용한다. 


$ docker volume inspect kong-vol


[

     {

         "CreatedAt": "2019-05-28T12:40:09Z",

         "Driver": "local",

         "Labels": {},

         "Mountpoint": "/var/lib/docker/volumes/kong-vol/_data",

         "Name": "kong-vol",

         "Options": {},

         "Scope": "local"

     }

 ]


디렉토리가 /var/lib/docker/volumes/kong-vol/_data임을 확인할 수 있다. 호스트(로컬 PC)의 이 디렉토리에서 아래와 같이 kong.yml 파일을 생성한다. 

kong.yml 파일 (주의 kong.yaml이 아님)

_format_version: "1.1"


services:

- name: my-service

  url: https://example.com

  plugins:

  - name: key-auth

  routes:

  - name: my-route

    paths:

    - /


consumers:

- username: my-user

  keyauth_credentials:

  - key: my-key


생성이 끝났으면 아래 도커 명령어를 이용해서 Kong API 게이트웨이를 기동 시킨다.

% docker run -d --name kong \

     --network=kong-net \

     -v "kong-vol:/usr/local/kong/declarative" \

     -e "KONG_DATABASE=off" \

     -e "KONG_DECLARATIVE_CONFIG=/usr/local/kong/declarative/kong.yml" \

     -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \

     -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \

     -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \

     -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \

     -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \

     -p 8000:8000 \

     -p 8443:8443 \

     -p 8001:8001 \

     -p 8444:8444 \

     kong:latest


설치가 제대로 되었는지

%curl http://localhost:8001 

명령을 이용하여 확인한다. 

Konga설치 하기

다음은 웹 UI를 위해서 Konga를 설치한다. https://pantsel.github.io/konga/

여러가지 설치 방법이 있지만 간단하게 하기 위해서 역시 도커로 설치한다. 

% docker run -d -p 1337:1337 --network=kong-net --name konga -v /var/data/kongadata:/app/kongadata -e "NODE_ENV=production"              pantsel/konga


이때, Kong API 서버 8001 포트로 통신을 해서 관리 API를 호출해야 하기 때문에, network를 "kong-net”으로 설정해서 실행한다. 설치가 끝나면 http://localhost:1337을 접속하면 Konga UI가 나오고, 관리자 계정과 비밀 번호를 입력할 수 있다.


로그인을 하면 Kong API 게이트웨이와 연결을 해야 하는데, 이름(임의로 적어도 된다.) Kong API 게이트웨이 Admin URL을 적어야 한다. 이때 http://kong:8001 을 적는다. (kong은 Kong API 게이트 웨이를 도커 컨테이너로 기동할때 사용한 컨테이너 이름이다. localhost로 하면 Konga 컨테이너의 로컬 호스트를 찾기 때문에 정상적으로 작동하지 않는다. )


이제 설정할 준비가 되었다. 


참고 : kong-dashboard 도 테스트 해봤지만, UI가 Konga가 훨씬 나은듯 해서, 글 내용을 변경함

% docker run --network=kong-net -itd --rm -p 8080:8080 pgbi/kong-dashboard start --kong-url http://kong:8001 --basic-auth {사용자이름}={비밀번호}


쿠버네티스와 Kong 통합 둘러보기

Kong API 게이트웨이를 사용하는 방법은 VM 기반의 일반 서버 앞에 설치해서 사용해도 되지만 쿠버네티스에 같이 사용할 경우 쿠버네티스 기반의 마이크로 서비스 아키텍쳐 패턴 구현에 더 용이 한다. 생각보다 잘 되어 있어서 놀랐다. 

설치 방법은 https://docs.konghq.com/install/kubernetes/ 에 설명되어 있는데, Helm이나 Kustomize로 설치가 가능하고, Kong은 CRD 형태로 지정된 Ingress로 프로비저닝이 된다. 

그리고 설정은 별도의 데이타 베이스 설치가 필요 없고 쿠버네티스의 컨트롤 플레인(마스터)에 저장되기 때문에 운영이 비교적 간단하다.


데이타베이스가 없을 경우, API 메트릭 저장하는 부분에 대해서 우려를 했는데, 아래와 같이 외장 플러그인을 지원한다. 




데이타 독 통합이 지원되고, 프로메테우스를 통하여 메트릭 저장이 가능하다. 그리고 Kong 용 프로메테우스/그라파나 대쉬보드도 훌륭하게 지원되고 있고, 분산 트렌젝션 추적을 위한 ZipKin도 이미 지원하고 있다. 


반면 로깅이 약간 애매한데, ELK(EFK)지원은 직접적으로는 보이지는 않는다. 



대신 파일 로그가 있기 때문에, 이 파일을 읽을 수 있는 Fluentd를 설치하면 될것으로 보이지만, 아무래도 컨테이너를 새로 말아야 하는 부담이 있기도 하고, 이를 통해서 메트릭이나 API 전용 로깅을 하는데는 별도의 설정이 필요할듯 하다. 


일단 GKE (구글 클라우드)의 경우에는 마켓 플레이스를 통해서 쉽게 설치가 가능하니 한번 테스트해볼만한 가치는 있을듯


11월 10일 업데이트

DBless 모드를 사용하게 되면, 동적으로 설정 변경이 불가능하다. Konga를 설치하더라도 설정 내용을 볼수만 있고 설정 변경은 불가능하다. 그외에도 지원되는 플러그인등에 대한 제약 사항이 있기 때문에 이 부분을 주의해야 한다.

제약 사항


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

도커 볼륨

클라우드 컴퓨팅 & NoSQL/도커 & 쿠버네티스 | 2019. 11. 10. 21:38 | Posted by 조대협

도커 볼륨에 대한 메모


도커 컨테이너에서 파일을 저장하게 되면 디폴트로는 도커 컨테이너 Writable 레이어에 저장된다. 컨테이너 레이어에 저장이 되기 때문에, 영속적이지 못하고 컨테이너가 내려가게 되면 지워지는 임시 저장소 이다. 


컨테이너의 디스크를 컨테이너가 내려가더라도 영속적으로 저장하고 관리할 수 있는데, 이를 볼륨(Volume)이라고 한다.


%docker create volume {볼륨 이름} 

명령어를 이용해서 생성이 가능하다.

생성된 볼륨들은


% docker volume ls 

명령으로 확인이 가능하다

볼륨에 대한 상세 설정을 보려면 


%docker volume inspect {볼륨 이름}

을 사용하면 된다. 

docker volume inspect myvol

[

    {

        "CreatedAt": "2019-11-10T21:28:26+09:00",

        "Driver": "local",

        "Labels": {},

        "Mountpoint": "/var/lib/docker/volumes/myvol/_data",

        "Name": "myvol",

        "Options": {},

        "Scope": "local"

    }

]


위의 예제를 보면 생성된 볼륨의 내용을 볼 수 있는데, 로컬(호스트머신)의 어느 디렉토리에 볼륨이 저장되는지 확인할 수 있다. 위의 예제에서는 /var/lib/docker/volumes/myvol/_data 에 저장이 된다.
생성된 볼륨을 컨테이너의 파일 시스템에 마운트 시키는 방법은 다음과 같다.
$ docker service create \
     --mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>,"volume-opt=o=addr=<nfs-address>,vers=4,soft,timeo=180,bg,tcp,rw"'
    --name myservice \
    <IMAGE>

src에 생성한 볼륨 이름을 dst에는 이 볼륨을 마운트 시킬 컨테이너 내부의 디렉토리를 지정하면 된다. 

Bind Mount
볼륨의 경우에는 도커 컨테이너에서만 그 파일을 내용을 볼 수 있고, 다른 컨테이너나 또는 호스트에서는 그 파일(디렉토리)의 내용을 볼 수 없다. 호스트나 다른 컨테이너에서도 접근할 수 있는 볼륨이 있는데, 이를 Bind mount라고 한다.


<그림. 도커 컨테이너 디스크 볼륨 종류와 개념 >


볼륨 생성 방법 자체는 동일하나 도커 컨테이너에 마운트 할때 Type을 "type=bind" 라고 



$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app,readonly \
  nginx:latest


tmpfs


볼륨 종류중에는 tmpfs라는 타입이 있는데, 일반 볼륨과는 다르게 호스트의 디스크 공간을 사용하는 것이 아니라 내용을 메모리에 저장하는 일종의 램 디스크라고 보면 된다.


storagedriver

마지막으로, 호스트의 디스크 이외의 다른 디스크, 예를 들어 NFS, iSCSI 등을 사용할 수 있는데, 이는 이 디스크 타입을 접근하기 위한 storagedriver를 사용해야 한다. 



참고 자료 & 이미지 예제 출처 : https://docs.docker.com/storage/https://docs.docker.com/storage/bind-mounts/

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요