DevOps

Open API platform Kong 소개

IT오이시이 2018. 9. 25. 13:50
728x90

1. 소개

Kong 은 오픈 소스 API 게이트웨이 및 마이크로 서비스 관리 레이어입니다.

Nginx와 lua-nginx 모듈 (특히 OpenResty )을 기반으로하는 Kong의 플러그 형 아키텍처는 유연하고 강력합니다.

2. 주요 개념

코드 샘플을 살펴보기 전에 Kong의 주요 개념을 살펴 보겠습니다.

  • API 객체 - 특정 작업을 수행하거나 일부 서비스를 제공하는 모든 HTTP 끝점의 속성을 래핑합니다. 구성에는 HTTP 메소드, 엔드 포인트 URI, API 서버를 가리키는 업스트림 URL 및 프록시 요청, 최대 회수, 속도 제한, 시간 초과 등을 위해 사용됩니다.
  • Consumer Object - API 끝점을 사용하는 모든 사용자의 속성을 래핑합니다. 추적, 액세스 제어 등에 사용됩니다.
  • 상향 객체 (Upstream Object) - 가상 호스트 이름으로 표시되는 들어오는 요청을 프록시 또는로드 균형 조정하는 방법을 설명합니다.
  • 대상 객체 - 호스트 이름 (또는 IP 주소) 및 포트로 식별되는 서비스가 구현 및 제공되는 것을 나타냅니다. 모든 업스트림의 대상은 추가 또는 비활성화 만 할 수 있습니다. 목표 변경의 이력은 업스트림에 의해 유지됩니다.
  • Plugin Object - 요청 및 응답 수명주기 동안 애플리케이션의 기능을 풍부하게하는 플러그 가능 기능. 예를 들어 관련 플러그인을 사용하도록 설정하여 API 인증 및 속도 제한 기능을 추가 할 수 있습니다. Kong은 플러그인 갤러리 에서 매우 강력한 플러그인을 제공합니다.
  • 관리 API - Kong 구성, 끝점, 소비자, 플러그인 등을 관리하는 데 사용되는 RESTful API 끝점

아래의 그림은 Kong이 기존 아키텍처와 다른 점을 보여 주며, 이것이 왜 이러한 개념을 도입했는지 이해하는 데 도움이 될 수 있습니다.


(출처 : https://getkong.org/)

3. 설정

공식 문서는 다양한 환경에 대한 자세한 지침 을 제공 합니다.

4. API 관리

로컬에서 Kong을 설정 한 후 간단한 주식 쿼리 끝점을 프록시하여 Kong의 강력한 기능을 한 번 물어 봅시다.

1
2
3
4
5
6
7
8
9
@RestController
@RequestMapping("/stock")
public class QueryController {
 
    @GetMapping("/{code}")
    public String getStockPrice(@PathVariable String code){
        return "BTC".equalsIgnoreCase(code) ? "10000" : "0";
    }
}

4.1. API 추가하기

다음으로 쿼리 API를 Kong에 추가해 보겠습니다.

관리 API는 http : // localhost : 8001을 통해 액세스 할 수 있으므로 모든 API 관리 작업이이 기본 URI로 완료됩니다.

1
2
3
4
5
6
7
APIObject stockAPI = new APIObject(
  "stock-api", "stock.api", "http://localhost:8080", "/");
HttpEntity<APIObject> apiEntity = new HttpEntity<>(stockAPI);
ResponseEntity<String> addAPIResp = restTemplate.postForEntity(
  "http://localhost:8001/apis", apiEntity, String.class);
 
assertEquals(HttpStatus.CREATED, addAPIResp.getStatusCode());

여기에 다음과 같은 구성으로 API를 추가했습니다.

1
2
3
4
5
6
{
    "name": "stock-api",
    "hosts": "stock.api",
    "upstream_url": "http://localhost:8080",
    "uris": "/"
}
  • "name" 은 API의 식별자로, 동작을 조작 할 때 사용됩니다.
  • 호스트" 헤더를 일치시킴으로써 들어오는 요청을 주어진 "upstream_url" 로 라우팅하는 데 "호스트" 가 사용됩니다
  • 상대 경로는 구성된 "uris"

API를 비난하고 싶거나 구성이 잘못 되었으면 간단히 제거 할 수 있습니다.

1
restTemplate.delete("http://localhost:8001/apis/stock-api");

API가 추가 된 후에는 http : // localhost : 8000 :

1
2
3
4
5
6
7
8
9
10
11
12
13
String apiListResp = restTemplate.getForObject(
  "http://localhost:8001/apis/", String.class);
  
assertTrue(apiListResp.contains("stock-api"));
 
HttpHeaders headers = new HttpHeaders();
headers.set("Host", "stock.api");
RequestEntity<String> requestEntity = new RequestEntity<>(
  headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc"));
ResponseEntity<String> stockPriceResp
  = restTemplate.exchange(requestEntity, String.class);
 
assertEquals("10000", stockPriceResp.getBody());

위의 코드 샘플에서는 방금 Kong에 추가 한 API를 통해 주가를 쿼리하려고합니다.

http : // localhost : 8000 / stock / btc 를 요청 하면 http : // localhost : 8080 / stock / btc 에서 직접 쿼리하는 것과 동일한 서비스를 얻을 수 있습니다.

4.2. API 소비자 추가하기

보안에 대해 이야기합니다. 특히 API에 액세스하는 사용자의 인증입니다.

나중에 인증 기능을 활성화 할 수 있도록 주식 쿼리 API에 소비자를 추가합시다.

API에 대한 소비자를 추가하는 것은 API를 추가하는 것만 큼 간단합니다. 소비자의 이름 (또는 id)은 모든 소비자의 유일한 필수 필드입니다.

1
2
3
4
5
6
ConsumerObject consumer = new ConsumerObject("eugenp");
HttpEntity<ConsumerObject> addConsumerEntity = new HttpEntity<>(consumer);
ResponseEntity<String> addConsumerResp = restTemplate.postForEntity(
  "http://localhost:8001/consumers/", addConsumerEntity, String.class);
  
assertEquals(HttpStatus.CREATED, addConsumerResp.getStatusCode());

여기에 새로운 소비자로 "eugenp"를 추가했습니다.

1
2
3
{
    "username": "eugenp"
}

4.3. 인증 사용

여기에 Kong의 가장 강력한 기능인 플러그인이 있습니다.

이제 프록시 된 주식 쿼리 API에 인증 플러그인을 적용 할 것입니다.

1
2
3
4
5
6
PluginObject authPlugin = new PluginObject("key-auth");
ResponseEntity<String> enableAuthResp = restTemplate.postForEntity(
  new HttpEntity<>(authPlugin),
  String.class);
assertEquals(HttpStatus.CREATED, enableAuthResp.getStatusCode());


프록시 URI를 통해 주식 가격을 쿼리하려고하면 요청이 거부됩니다.

1
2
3
4
5
6
7
8
HttpHeaders headers = new HttpHeaders();
headers.set("Host", "stock.api");
RequestEntity<String> requestEntity = new RequestEntity<>(
  headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc"));
ResponseEntity<String> stockPriceResp = restTemplate
  .exchange(requestEntity, String.class);
  
assertEquals(HttpStatus.UNAUTHORIZED, stockPriceResp.getStatusCode());

기억 오이겐은 우리의 API 소비자 중 하나입니다, 그래서 우리는 그 인증 키를 추가하여이 API를 사용할 수 있도록해야합니다 :

1
2
3
4
5
6
7
String consumerKey = "eugenp.pass";
KeyAuthObject keyAuth = new KeyAuthObject(consumerKey);
ResponseEntity<String> keyAuthResp = restTemplate.postForEntity(
  new HttpEntity<>(keyAuth),
  String.class);
assertTrue(HttpStatus.CREATED == keyAuthResp.getStatusCode());

그런 다음 Eugen 은 이전과 마찬가지로이 API를 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
HttpHeaders headers = new HttpHeaders();
headers.set("Host", "stock.api");
headers.set("apikey", consumerKey);
RequestEntity<String> requestEntity = new RequestEntity<>(
  headers,
  HttpMethod.GET,
ResponseEntity<String> stockPriceResp = restTemplate
  .exchange(requestEntity, String.class);
  
assertEquals("10000", stockPriceResp.getBody());

5. 고급 기능

기본 API 프록시 및 관리 외에도 Kong은 API로드 균형 조정, 클러스터링, 상태 확인 및 모니터링 등을 지원합니다.

이 섹션에서는 Kong과의 요청을로드 밸런스하는 방법과 관리 API를 보호하는 방법에 대해 살펴 보겠습니다.

5.1. 로드 균형 조정

Kong은 백엔드 서비스에 대한 요청을로드 밸런싱하는 두 가지 전략, 동적 링 밸런서 및 간단한 DNS 기반 방법을 제공합니다. 간단히하기 위해, 우리는 링 - 밸런서를 사용할 것 입니다.

이전에 언급했듯이 업스트림은로드 균형 조정에 사용되며 각 업스트림에는 여러 대상이있을 수 있습니다.

Kong은 가중 라운드 로빈 및 해시 기반 균형 알고리즘을 모두 지원합니다. 기본적 으로 각 가중치에 따라 요청이 전달되는 가중 라운드 로빈 방식이 사용됩니다 .

먼저, 업스트림을 준비합시다.

1
2
3
4
5
6
7
UpstreamObject upstream = new UpstreamObject("stock.api.service");
ResponseEntity<String> addUpstreamResp = restTemplate.postForEntity(
  new HttpEntity<>(upstream),
  String.class);
  
assertEquals(HttpStatus.CREATED, addUpstreamResp.getStatusCode());

그런 다음 업스트림에 대해 두 개의 대상, 가중치가 10 인 테스트 버전 및 가중치가 40 인 릴리스 버전을 추가합니다 .


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TargetObject testTarget = new TargetObject("localhost:8080", 10);
ResponseEntity<String> addTargetResp = restTemplate.postForEntity(
  new HttpEntity<>(testTarget),
  String.class);
  
assertEquals(HttpStatus.CREATED, ddTargetResp.getStatusCode());
 
TargetObject releaseTarget = new TargetObject("localhost:9090",40);
addTargetResp = restTemplate.postForEntity(
  new HttpEntity<>(releaseTarget),
  String.class);
  
assertEquals(HttpStatus.CREATED, addTargetResp.getStatusCode());

위의 구성으로 요청의 1/5은 테스트 버전으로, 4/5는 버전 출시 예정이라고 가정 할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
APIObject stockAPI = new APIObject(
  "balanced-stock-api",
  "balanced.stock.api",
  "/");
HttpEntity<APIObject> apiEntity = new HttpEntity<>(stockAPI);
ResponseEntity<String> addAPIResp = restTemplate.postForEntity(
  "http://localhost:8001/apis", apiEntity, String.class);
  
assertEquals(HttpStatus.CREATED, addAPIResp.getStatusCode());
 
HttpHeaders headers = new HttpHeaders();
headers.set("Host", "balanced.stock.api");
for(int i = 0; i < 1000; i++) {
    RequestEntity<String> requestEntity = new RequestEntity<>(
      headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc"));
    ResponseEntity<String> stockPriceResp
     = restTemplate.exchange(requestEntity, String.class);
  
    assertEquals("10000", stockPriceResp.getBody());
}
  
int releaseCount = restTemplate.getForObject(
int testCount = restTemplate.getForObject(
 
assertTrue(Math.round(releaseCount * 1.0 / testCount) == 4);

가중치 적용 - 라운드 로빈 방식은 백엔드 서비스에 대한 요청을 대략 가중치와 균형을 맞추기 때문에 비율의 근사값 만 확인할 수 있으며 위 코드의 마지막 줄에 반영됩니다.

5.2. 관리 API 보안

기본적으로 Kong은 로컬 인터페이스의 관리 요청 만 받아들입니다. 이는 대부분의 경우 충분하게 제한됩니다. 우리가 다른 네트워크 인터페이스를 통해 관리 할 경우에, 우리는 변경할 수 있습니다 admin_listen 가치 kong.conf을 하고, 방화벽 규칙을 구성합니다.

또는 Kong을 Admin API 자체의 프록시로 사용할 수 있습니다. "/ admin-api"경로를 사용하여 API를 관리하려는 경우 다음과 같은 API를 추가 할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
APIObject stockAPI = new APIObject(
  "admin-api",
  "admin.api",
  "/admin-api");
HttpEntity<APIObject> apiEntity = new HttpEntity<>(stockAPI);
ResponseEntity<String> addAPIResp = restTemplate.postForEntity(
  apiEntity,
  String.class);
  
assertEquals(HttpStatus.CREATED, addAPIResp.getStatusCode());

이제 프록시 된 관리 API를 사용하여 API를 관리 할 수 ​​있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HttpHeaders headers = new HttpHeaders();
headers.set("Host", "admin.api");
APIObject baeldungAPI = new APIObject(
  "baeldung-api",
  "baeldung.com",
  "/");
RequestEntity<APIObject> requestEntity = new RequestEntity<>(
  baeldungAPI,
  headers,
  HttpMethod.POST,
ResponseEntity<String> addAPIResp = restTemplate
  .exchange(requestEntity, String.class);
 
assertEquals(HttpStatus.CREATED, addAPIResp.getStatusCode());

확실하게, 우리는 프록시 된 API를 안전하게하고 싶습니다. 이것은 프록시 API를위한 인증 플러그 인을 사용하면 쉽게 구현할 수 있습니다.

6. 요약

이 기사에서는 마이크로 서비스 API 게이트웨이 용 플랫폼 인 Kong을 소개하고 API 및 라우팅 요청을 업스트림 서버로 관리하는 핵심 기능과로드 밸런싱과 같은 고급 기능에 중점을 두었습니다.

그러나 우리가 탐구 할 수있는 더 많은 견고한 기능이 있으며 필요한 경우 플러그인을 개발할 수 있습니다 . 여기 에서 공식 문서를 계속 탐색 할 수 있습니다 .

언제나 그렇듯이 전체 구현은 Github 에서 찾을 수 있습니다 .

728x90
반응형