- namespace 생성

  $kubectl create namespace [네임스페이스명]

  

-특정 namespace 에 pod 생성

 $kubectl create -f xxxxx.yaml -n custom-namespace


- pod 삭제

  1)이름으로 삭제시

    $ kubectl delete po [pod명]


  2) 라벨셀렉터로 삭제시

   $kubectl delete po -l [라벨key=값]

  

   3) 현재 네임스페이스의 모든 pod 삭제시

    $kubectl delete po -all


-pod생성

 $kubectl create -f xxxxx.yaml


- pod의 에러로 restart 한 경우 로그 확인

  $kubectl logs [pod명] --previous


- pod 가 다시 시작해야 하는 이유를 알고자 할때 

  $kubectl describe po [pod명]



'DevOps' 카테고리의 다른 글

Docker 명령어  (0) 2018.12.28
쿠버네티스 명령어#3  (0) 2018.12.27
쿠버네티스 명령어 #2  (0) 2018.12.27
kubernetes 명령어#1  (0) 2018.12.27
미니큐브 설치 맥  (0) 2018.12.23
fluentd mac설치  (0) 2018.12.18

- cluser 작동중인지  확인
 $kubectl cluster-info

- pods 정보 확인
 $kubectl get pods

- 특정 pod 의 yaml 정의 확인
 $kubectl get po [pod명] -o yaml

- 리소스 생성
 $kubectl create -f xxxx.yaml

- pod 로그 확인
 $kubectl logs [pod명]

- 디버깅 또는 다른 이유로 서비스를 거치지 않고, 특정포드와 통신하고 싶을때 ....port fowarding
 $kubectl port-forward [pod명] 8888:8080

  Forwarding from [::1]:8888 -> 8080


- pod의 라벨확인
 $kubectl get po --show-labels

- pod에 라벨 붙이기
 $kubectl label po [pod명] creation_method=manual

- pod 의 라벨 변경
  $kubectl label po [pod명] env=debug --overwrite

- 특정 (라벨=값)에 해당되는 pod 조회
 $kubectl get po -l creation_method=manual

- 값에 상관없이 해당 라벨이 있는 pod 조회(env 라벨)
  $kubectl get po -l env

   env in (prod, dev) 
   env notin (prod, dev)

- pod 노드 정보 확인
  $kubectl get node

- pod 노드에 라벨 붙이기

iyeonghoui-MacBook-Pro:k8s ireo$ kubectl get node

NAME                                   STATUS   ROLES    AGE   VERSION

gke-kubia-default-pool-79ce8f08-5rxv   Ready    <none>   1d    v1.10.9-gke.5

gke-kubia-default-pool-79ce8f08-n6xd   Ready    <none>   2d    v1.10.9-gke.5

gke-kubia-default-pool-79ce8f08-tb2j   Ready    <none>   3d    v1.10.9-gke.5

iyeonghoui-MacBook-Pro:k8s ireo$ kubectl label node gke-kubia-default-pool-79ce8f08-5rxv gpu=true

node/gke-kubia-default-pool-79ce8f08-5rxv labeled

iyeonghoui-MacBook-Pro:k8s ireo$ 



- node 라벨=값 이 gpu=true 인  노드 조회

 $kubectl get nodes -l gpu=true



- pod에 주석 추가

 $kubectl annotate pod [pod명] mycompany.com/someannotation="foo bar"


- pod 주석 정보 확인

 $kubectl describe pod [pod명]



- 클러스터에 있는 모든 네임스페이스 나열

 $kubectl get ns



- 특정 네임스페이스에 속한 포드 조회

 $kubectl get po --namespace [namespace명]










'DevOps' 카테고리의 다른 글

쿠버네티스 명령어#3  (0) 2018.12.27
쿠버네티스 명령어 #2  (0) 2018.12.27
kubernetes 명령어#1  (0) 2018.12.27
미니큐브 설치 맥  (0) 2018.12.23
fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30

출처 : https://github.com/kubernetes/minikube/releases


맥에서 미니큐브 설치시 필요한 명령어는 아래 한줄

OSX

curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.32.0/minikube-darwin-amd64 && chmod +x minikube && sudo cp minikube /usr/local/bin/ && rm minikube


이후에 미니큐브 가상머신 시작해 보면 확인 완료

$minikube start



위 실행시 아래 같은 에러 발생되면 거두절미하고, vm 이나 kvm을 설치해 줘야 하는 거임

VBoxManage not found. Make sure VirtualBox is installed and VBoxManage is in the path



나는 위 출처 주소에서 hyperkit 설치해 주고, 미니큐브 가상머신 시작하니 정상 기동됨

Hyperkit driver

The Hyperkit driver will eventually replace the existing xhyve driver. It is built from the minikube source tree, and uses moby/hyperkit as a Go library.

To install the hyperkit driver:

curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit \
&& sudo install -o root -g wheel -m 4755 docker-machine-driver-hyperkit /usr/local/bin/


기동은 아래 명령어

$minikube start --vm-driver=hyperkit



'DevOps' 카테고리의 다른 글

쿠버네티스 명령어 #2  (0) 2018.12.27
kubernetes 명령어#1  (0) 2018.12.27
미니큐브 설치 맥  (0) 2018.12.23
fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29

출처 : https://docs.fluentd.org/v0.12/articles/install-by-dmg#step2:-launch-td-agent




For MacOS X, we’re using the OS native .dmg Installer to distribute td-agent.

Step1: Install td-agent

Please download the .dmg file from here, and install the software.

Step2: Launch td-agent

You can launch td-agent with launchctl command. Please make sure the daemon started correctly from the log (/var/log/td-agent/td-agent.log).

$ sudo launchctl load /Library/LaunchDaemons/td-agent.plist
$ less /var/log/td-agent/td-agent.log
2013-04-19 16:55:03 -0700 [info]: starting fluentd-0.10.33
2013-04-19 16:55:03 -0700 [info]: reading config file path="/etc/td-agent/td-agent.conf"

Your configuration file is located at /etc/td-agent/td-agent.conf. Your plugin directory is at /etc/td-agent/plugin. In case you want to stop the agent, please execute the command below.

$ sudo launchctl unload /Library/LaunchDaemons/td-agent.plist

Step3: Post Sample Logs via HTTP

By default, /etc/td-agent/td-agent.conf is configured to take logs from HTTP and route them to stdout (/var/log/td-agent/td-agent.log). You can post sample log records using the curl command.

$ curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test
$ tail -n 1 /var/log/td-agent/td-agent.log
2013-04-19 16:51:47 -0700 debug.test: {"json":"message"}

Uninstall td-agent

td-agent for Mac doesn’t provide uninstallation app unlike rpm / deb. If you want to uninstall td-agent from your Mac, remove these files / directories.

  • /Library/LaunchDaemons/td-agent.plist
  • /etc/td-agent
  • /opt/td-agent
  • /var/log/td-agent

Next Steps

You’re now ready to collect your real logs using Fluentd. Please see the following tutorials to learn how to collect your data from various data sources.

Please refer to the resources below for further steps.


'DevOps' 카테고리의 다른 글

kubernetes 명령어#1  (0) 2018.12.27
미니큐브 설치 맥  (0) 2018.12.23
fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29
MSA-Spring Cloud  (0) 2018.09.28

[macbook 프로메테우스 설치]

손쉬운 방법이 있어서 퍼옴


출처 : https://brewinstall.org/Install-prometheus-on-Mac-with-Brew/

 

  1. ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null
  2. brew install prometheus

'DevOps' 카테고리의 다른 글

미니큐브 설치 맥  (0) 2018.12.23
fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29
MSA-Spring Cloud  (0) 2018.09.28
Hystrix-Isolation  (0) 2018.09.28

계속 뭔가 해야 할일들이 바뀌네요.이게뭔지...


모니터링 툴 찾다가 Prometheus 잘 정리된 사이트가 있어 퍼옵니다.

자료 수집후에...한번 자체 정리 한번 해야겠다...




출처 : https://blog.outsider.ne.kr/1254



Prometheus

모니터링이나 APM 도구를 많이 써보고 잘 아는 것은 아니지만 Prometheus는 다른 모니터링 도구와는 좀 다른 특성을 가진 도구이다.

Prometheus 사이트

From metrics to insight라는 문구가 인상적이다. 주변의 추천도 있고 최근에 관심을 가지고 보고 있어서 그런지 요즘 주목을 많이 받는 것으로 보인다.

Prometheus는 오픈소스이고 Apache 2 라이센스로 공개되어 있어서 유료 걱정 없이 사용할 수 있다.

Prometheus 아키텍처

Prometheus의 구조는 Prometheus 저장소에 나와 있는 아키텍처를 보면 좀 이해하기가 쉽다. 처음에는 꽤 복잡해 보였지만 동작 방식을 이해하면 이 그림을 이해할 수 있게 된다. 다른 모니터링 도구와 가장 다른 점은 대부분의 모니터링 도구가 Push 방식 즉, 각 서버에 클라이언트를 설치하고 이 클라이언트가 메트릭 데이터를 수집해서 서버로 보내면 서버가 모니터링 상태를 보여주는 방식인데 반해서 Prometheus는 Pull 방식이다. 그래서 서버가 각 클라이언트를 알고 있어야 하는게 아니라 서버에 클라이언트가 떠 있으면 서버가 주기적으로 클라이언트에 접속해서 데이터를 가져오는 방식이다.

몇 가지 특징을 짚고 넘어갈 수 있는데 구성을 크게 나누면 Exporter, Prometheus Server, Grafana, Alertmanager로 나눌 수 있다. 뒤에서 실제로 사용해 보면 더 이해가 가겠지만, 사전에 알아두어야 할 특징을 정리해 보자.

  • Exporter는 모니터링 대상의 Metric 데이터를 수집하고 Prometheus가 접속했을 때 정보를 알려주는 역할을 한다. 호스트 서버의 CPU, Memory 등을 수집하는 node-exporter도 있고 nginx의 데이터를 수집하는 nginx-exporter도 있다. Exporter를 실행하면 데이터를 수집하는 동시에 HTTP 엔드포인트를 열어서(기본은 9100 포트) Prometheus 서버가 데이터를 수집해 갈 수 있도록 한다. 이 말은 웹 브라우저 등에서 해당 HTTP 엔드포인트에 접속하면 Metric의 내용을 볼 수 있다는 의미이다.

    • Exporter를 쓰기 어려운 배치잡 등은 Push gateway를 사용하면 된다. 내가 보기에는 Push gateway도 결국 Exporter의 일종이라고 생각된다.
    • 웹 애플리케이션 서버 같은 경우의 Metric은 클라이언트 라이브러리를 이용해서 Metric을 만든 후 커스텀 Exporter를 사용할 수 있다.
  • Prometheus Server는 Expoter가 열어놓은 HTTP 엔드포인트에 접속해서 Metric을 수집한다. 그래서 Pull 방식이라고 부른다.
  • Prometheus Server에 Grafana를 연동해서 대시보드 등의 시각화를 한다.
  • 알림을 받을 규칙을 만들어서 Alert Manager로 보내면 Alert Manager가 규칙에 따라 알림을 보낸다.

내가 그랬듯이 이렇게 특징을 봐도 하나도 이해가 안 갈 텐데 실제로 사용을 해보면 훨씬 쉽게 이해가 되므로 하나씩 살펴보자.

Prometheus Server

Prometheus 서버는 다운로드 페이지에서 OS 별로 다운로드 받을 수 있고 설치 문서를 보면 Docker 이미지로도 제공하고 있다. 편한 방식을 사용하면 되는데 여기서는 설명을 위해서 직접 다운로드를 받아서 사용해 보자. 현재 버전은 1.4.1이다.

다운받아서 압축을 풀면 prometheus 파일과 예시 설정 파일인 prometheus.yml파일이 존재하는데 이 파일을 이용해서 다음과 같이 실행하면 된다.

Bash
$ ./prometheus -config.file=prometheus.yml
INFO[0000] Starting prometheus (version=1.4.1, branch=master, revision=2a89e8733f240d3cd57a6520b52c36ac4744ce12)  source=main.go:77
INFO[0000] Build context (go=go1.7.3, user=root@e685d23d8809, date=20161128-09:59:22)  source=main.go:78
INFO[0000] Loading configuration file prometheus.yml     source=main.go:250
INFO[0000] Loading series map and head chunks...         source=storage.go:354
INFO[0000] 0 series loaded.                              source=storage.go:359
INFO[0000] Starting target manager...                    source=targetmanager.go:63
INFO[0000] Listening on :9090                            source=web.go:248

9090포트로 Prometheus 서버가 실행된 것을 볼 수 있다.

Prometheus 웹 콘솔

서버를 띄운 서버가 52.192.141.64라고 한다면 http://52.192.141.64:9090으로 접속하면 http://52.192.141.64:9090/graph로 리다이렉트가 되는데 위와 같은 화면을 볼 수 있다. 여기서 간단하게 수집된 데이터를 볼 수 있다. 맨 위의 입력 칸은 데이터 조회를 위한 평가식을 입력하는 곳인데 평가식은 뒤에서 좀 더 자세히 설명하고 여기서는 셀렉트박스에서 원하는 값을 선택하고 Execute를 누르면 된다.

Prometheus 웹에서 보이는 Metric 종류

셀렉트박스를 열면 수집하고 있는 매트릭의 목록을 볼 수 있다. 원하는 매트릭을 선택하고 Execute를 누르면 하단에서 그래프를 볼 수 있다.

Prometheus 웹에서 특정 매트릭을 선택해서 그래프를 볼 수 있다

이 화면을 간단한 대시보드처럼 사용할 수도 있다.

prometheus.yml

이제 Prometheus 서버를 띄울 때 사용한 설정 파일인 prometheus.yml를 살펴보자.

# 전역 설정
global:
  scrape_interval:     15s # 15초마다 매트릭을 수집한다. 기본은 1분.
  evaluation_interval: 15s # 15초마다 규칙을 평가한다. 기본은 1분.

  # 외부 시스템에 표시할 이 서버의 레이블
  external_labels:
      monitor: 'codelab-monitor'

# 규칙을 로딩하고 'evaluation_interval' 설정에 따라 정기적으로 평가한다.
rule_files:
  # - "first.rules"
  # - "second.rules"

# 매트릭을 수집할 엔드포인드로 여기선 Prometheus 서버 자신을 가리킨다.
scrape_configs:
  # 이 설정에서 수집한 타임시리즈에 `job=<job_name>`으로 잡의 이름을 설정한다.
  - job_name: 'prometheus'

    # metrics_path의 기본 경로는 '/metrics'이고 scheme의 기본값은 `http`다

    static_configs:
      - targets: ['localhost:9090']

기본으로 제공된 파일에서 주석으로 된 설명만 추가로 달아놨다.

  • global부분은 매트릭 수집을 위한 전역설정 값이다. 프로메테우스 서버를 프로메테우스 서버에 연결하거나 Alert Manager 등에서 이 서버의 데이터를 가져갈 수 있는데 그때 구분할 수 있도록 external_labes로 이름을 지정할 수 있다.
  • rule_files는 Alert 규칙 등 필요한 규칙을 작성해서 사용할 수 있는데 현재는 아무런 규칙을 지정하지 않았다.
  • scrape_configs가 실제 수집 대상을 지정하는 설정이다. 여기서는 prometheus라는 이름으로 한 개만 설정했다. 이는 여러 대상을 설정할 수 있다는 것이고 targets가 배열로 지정하므로 서버군을 모두 여기 지정할 수 있다.
  • targets를 localhost:9090으로 설정했는데 이는 Prometheus 서버 자신을 가리킨다. targets에 지정하는 것은 Prometheus 서버가 접근해서 데이터를 가져올 Exporter의 HTTP 엔드포인트이다. 그래서 localhost:9090으로 지정을 하면 기본값인 metrics_path를 이용해서 localhost:9090/metrics에 접근해서 데이터를 가져온다. 이는 Prometheus 서버가 매트릭을 수집하는 서버인 동시에 매트릭을 노출하는 Exporter이기도 하다는 의미이다.
  • 이 예시에서는 scrapte_configs를 수동으로 지정했는데 실제 사용한다면 이런 식으로 모니터링할 서버를 수동으로 관리할 수는 없다. CONFIGURATION 문서를 보면 모니터링 대상을 Consul, DNS 기반의 서비스 디스커버리를 이용해서 동적으로 설정할 수 있다.

웹 브라우저에서 http://52.192.141.64:9090/metrics에 접근하면 Exporter가 노출한 매트릭 데이터를 볼 수 있다.

Prometheus Exporter가 노출한 매트릭 정보

Prometheus는 클러스터링 기능이 없다. 한대의 Prometheus 서버로 수천 대의 서버를 다 모니터링할 수는 없는데 내가 아는 선에서는 현재 Prometheus 서버를 Prometheus 서버에 연결해서 사용하는 방식으로 확장하는 것으로 알고 있다.(아직 구축해 본 것은 아니라서...) 즉, 100대를 수집하는 Prometheus 서버를 두고 이 서버가 수집한 데이터를 다시 수집하는 Prometheus 서버를 또 뒤에 둔다는 것이다.

Exporter

간단히 Prometheus 서버를 살펴봤으므로 이제 매트릭을 제공하는 Exporter를 살펴봐야 한다. 위에도 얘기했듯이 Exporter는 필요한 매트릭을 수집하고 이를 HTTP 엔트포인트로 Prometheus에 노출하는 역할을 한다. 문서를 보면 Consul exporter, MySQL server exporter, RabbitMQ exporter, HAProxy exporter, Docker Hub exporter, AWS CloudWatch exporter 등 다양한 Exporter를 지원하고 있다. 필요한 곳에 Exporter를 설정해서 Prometheus가 이를 수집하도록 하면 된다.

Exporter를 다 살펴볼 수는 없으므로 서버의 CPU, 메모리, 디스크 등의 상태를 모니터링하는 Node exporter를 사용해 보자. Node exporter는 Docker로도 사용할 수 있으므로로 여기서는 간단히 Docker로 띄워보자.

Bash
$ docker pull prom/node-exporter
Using default tag: latest
latest: Pulling from prom/node-exporter
8ddc19f16526: Pull complete
a3ed95caeb02: Pull complete
8279f336cdd3: Pull complete
81998f54d5a6: Pull complete
Digest: sha256:5655be43374133b9ad72b8761b5661762acf513126c0f147ce1902ac52230f52
Status: Downloaded newer image for prom/node-exporter:latest

$ docker run -d -p 9100:9100 --net="host" prom/node-exporter
cf70bc7297369012ce15683352cf1246c89d1410f44d80758fd69ef58123c838

이 서버의 IP가 52.69.72.174라고 한다면 9100포트로 Node exporter를 띄웠으므로 http://52.69.72.174:9100/metrics에 접속을 하면 다음과 같이 Exporter가 수집한 매트릭 정보를 볼 수 있다.

Node exporter가 노출한 매트릭 정보

이제 모니터링할 서버가 생겼으므로 앞에서 본 prometheus.yml에서 이 서버를 모니터링하도록 추가해 보자.


scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'test-server' scrape_interval: 10s static_configs: - targets: ['52.69.72.174:9100']

기존에 있던 prometheus 잡외에 test-server라는 이름으로 새로운 잡을 추가하고 위에서 설정한 Node-exporter를 바라보도록 했다.

Node exporter에서 수집한 매트릭을 Prometheus 웹에서 본 화면

이제 서버를 다시 띄우고 모니터링을 하면 앞에서 본 Prometheus 서버 페이지인 http://52.192.141.64:9090/graph에서 test-server에 대한 매트릭정보를 볼 수 있다.

표현식 언어

Prometheus에서는 수집한 매트릭 데이터를 조회할 수 있는 함수형 표현식 언어를 제공하고 있다. 이 표현식 언어로 매트릭 데이터를 실시간으로 조회할 수 있고 위에서 셀렉트 박스로 특정 매트릭을 선택해서 데이터나 그래프를 본 것도 이 표현식 언어를 사용한 것이다.

  • 앞에서 조회해 본 process_cpu_seconds_totalnode_cpuhttp_requests_total 등을 인스턴스 벡터라고 부른다. 이 인스턴스 벡터로 쿼리를 할 수 있다.
  • 인스턴스 벡터 뒤에 { }로 레이블을 지정하면 필터링을 할 수 있는데 http_requests_total{job="prometheus",group="canary"}와 같이 사용한다. 이렇게 하면 http_requests_total에서 job 이름이 prometheus이고 group은 canary인 정보만 조회한다.

    • 레이블에서는 =!==~!~같은 논리연산자를 사용할 수 있고 여기서 ~는 정규표현식 비교를 의미한다. 그래서 http_requests_total{environment=~"staging|testing|development",method!="GET"}와 같이 사용할 수 있다.
  • 인스턴스 벡터 뒤에 레인지 벡터라고 부르는 []를 사용할 수 있다. http_requests_total{job="prometheus"}[5m]라고 하면 최근 5분의 값을 조회한다.
  • node_cpu offset 10m처럼 특정 시간의 값을 조회하는 오프셋 모디파이어를 사용할 수 있다.

그 외에 연산자나 함수를 이용해서 조회할 수 있다.

'DevOps' 카테고리의 다른 글

fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29
MSA-Spring Cloud  (0) 2018.09.28
Hystrix-Isolation  (0) 2018.09.28
API Gateway: Zuul  (0) 2018.09.03

apache poi(XSSFWorkbook API)가 갖고 있는 메모리 이슈로 인해 full gc가 발생하는 현상 해결을 위해

엑셀파일 read시에 메모리 사용증대가 발생되지 않는 개선된 api가 필요


구글링 결과 어떤 분이 감사한 모듈을 개발해 놓으셨다.

해결책은 StreamingReader 를 사용하는 것


해결을 위해서는 아래 내용을 참고하면 된다.

해당 블로그에 잘 설명되어 있음

https://github.com/monitorjbl/excel-streaming-reader


회사에서 해당 모듈을 사용하여 고질적 문제를 해결함.


개요는 아래와 같음

  <dependency>
    <groupId>com.monitorjbl</groupId>
    <artifactId>xlsx-streamer</artifactId>
    <version>2.0.0</version>
  </dependency>

Implementation Details

This library will take a provided InputStream and output it to the file system. The stream is piped safely through a configurable-sized buffer to prevent large usage of memory. Once the file is created, it is then streamed into memory from the file system.

The reason for needing the stream being outputted in this manner has to do with how ZIP files work. Because the XLSX file format is basically a ZIP file, it's not possible to find all of the entries without reading the entire InputStream.

This is a problem that can't really be gotten around for POI, as it needs a complete list of ZIP entries. The default implementation of reading from an InputStream in POI is to read the entire stream directly into memory. This library works by reading out the stream into a temporary file. As part of the auto-close action, the temporary file is deleted.

If you need more control over how the file is created/disposed of, there is an option to initialize the library with a java.io.File. This file will not be written to or removed:

File f = new File("/path/to/workbook.xlsx");
Workbook workbook = StreamingReader.builder()
        .rowCacheSize(100)    
        .bufferSize(4096)     
        .open(f);

This library will ONLY work with XLSX files. The older XLS format is not capable of being streamed.




늦게나마 MSA를 학습중이다.

spring cloud를 주로 보고 있는데 양이 방대하구먼...^^;;

영어때문에 괴로워 하다가 한글로 개략적 사항들을 정리해 놓은 깃이 있어서 퍼왔다.

https://coe.gitbook.io/guide/


'DevOps' 카테고리의 다른 글

fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29
MSA-Spring Cloud  (0) 2018.09.28
Hystrix-Isolation  (0) 2018.09.28
API Gateway: Zuul  (0) 2018.09.03

출처 : http://woowabros.github.io/experience/2017/08/21/hystrix-tunning.html


API G/W에서  Clustering 관련사항을 확인하기 위해 hystrix에 접근하고 있다. hystrix에 대해서 잘 정리된 글이 있어 퍼왔고, 
궁금했던 isolation 을 발췌한다.

Isolation 이해

이번에는 application.yml 파일을 살펴봤습니다. 저희가 Hystrix를 어떻게 설정하고 있나 궁금했기 때문입니다.

zuul.ribbonIsolationStrategy: SEMAPHORE

어라, 또 한 번 반갑지 않으신가요? 이것도 위에서 살펴봤던 코드와 관련 있고요. 그림 3의 5번 부분이기도 합니다. 아무래도 격리 전략Isolation Strategy을 살펴봐야겠다고 느꼈습니다. 이 때, Hystrix, How it Works를 주로 참고했고요. 한 문장으로 정리하면 다음과 같습니다.

“일종의 Bulkhead 패턴이며, 각 서비스에 대한 의존성을 격리하고 동시 접근을 제한한다.”

hystrix_isolation

그림 4. Hystrix Isolation

위 그림은 Hystrix가 어떻게 의존 서비스들을 격리하는지 보여줍니다. 빨간색으로 표기된 네모 상자는 특정 서비스의 호출이 지연되고 있다는 뜻인데요. 나머지 서비스에는 영향을 주지 않고 있습니다. 또한, 동시 접근 제한을 서비스별로 다르게 설정하고 있습니다.

격리의 방법으로는 2가지가 존재합니다.

  1. Thread & Thread Pools
  2. Semaphore (Counter라고 표현하기도 하는데, 개인적으로는 이 용어가 더 와닿습니다)

Thread 방식에서는 서비스 호출이 별도의 스레드에서 수행됩니다. 예컨대, Tomcat의 스레드 풀과 서비스에 대한 호출 스레드가 격리되는 거죠. 이렇게 하면 네트워크상의 타임아웃 위에 스레드 타임아웃을 둘 수 있습니다. 하지만 별도의 스레드를 사용하는 만큼 비용이 수반됩니다. 여기서는 이를 가리켜 연산 오버헤드computational overhead라고 표현하네요.

한편, Semaphore 방식에서는 서비스 호출을 위해 별도의 스레드를 만들지 않습니다. 단지 각 서비스에 대한 동시 호출 수를 제한할 뿐입니다. 위에서 살펴봤던 코드 덕분에, 내용을 좀 더 쉽게 이해할 수 있었습니다. 아래 그림은 Thread와 Semaphore의 차이를 보여줍니다.

hystrix_isolation

그림 5. Thread와 Semaphore의 격리 방식 (크게 보기)

Isolation 권장사항

위에서 살펴봤던 코드 중에 executionSemaphore.tryAcquire() 부분이 있습니다. 여기 코드를 좀 더 살펴보면, HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS를 만나게 되는데요. 이는 execution.isolation.semaphore.maxConcurrentRequests 프로퍼티에 대응하는 상수입니다. 처음에는 이 수치를 좀 더 늘리려고 했습니다. 왜냐면 기존에 저희가 SEMAPHORE를 격리 전략으로 사용하고 있었고요. 여기서 Semaphore 구간에 진입할 수 있는 요청의 수만 늘려주면, API Gateway의 동시 처리량이 늘어날 테고, 그러면 502 발생 가능성이 감소할 거로 생각했기 때문입니다. 프로퍼티에 대한 설명은 여기를 참고하세요. (폴백fallback을 설정한 경우도 가용한 Semaphore 개수의 제한을 받습니다.)

하지만 Hystirx Configuration 문서를 좀 더 살펴보면, 아래와 같은 내용이 있습니다.

The default, and the recommended setting, is to run HystrixCommands using thread isolation (중략)

Commands executed in threads have an extra layer of protection against latencies beyond what network timeouts can offer.

Generally the only time you should use semaphore isolation for HystrixCommands is when the call is so high volume (hundreds per second, per instance) that the overhead of separate threads is too high; this typically only applies to non-network calls.

HystrixCommand를 사용할 때는 Thread 격리를 권장한다는 내용입니다. (서비스 호출의) 지연으로부터 보호되는 별도의 계층을 가질 수 있으니까요. 그리고 Semaphore를 써야 하는 경우는 유일하다고 합니다. 꽤 강력한 어조네요. 의구심이 생길 만큼요. 바로 “호출량이 너무 많아서 분리된 스레드의 사용이 주는 오버헤드가 큰 경우”이고요. 네트워크 요청이 발생하지 않는 경우non-network call가 보통 여기에 해당한다고 합니다. 좀 더 찾아보니, Netflix API도 아주 일부만 Semaphore를 사용하는 군요. 인메모리 캐시에서 메타 데이터를 가져오거나, Thread 방식에 대한 퍼사드facade에 한해서요.

'DevOps' 카테고리의 다른 글

fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29
MSA-Spring Cloud  (0) 2018.09.28
Hystrix-Isolation  (0) 2018.09.28
API Gateway: Zuul  (0) 2018.09.03

출처 : https://github.com/KD4/TIL/blob/master/MSA/zuul.md


API Gateway: Zuul

API GATEWAY이란?

Micro Service Architecture(이하 MSA)에서 언급되는 컴포넌트 중 하나이며, 모든 클라이언트 요청에 대한 end point를 통합하는 서버이다. 마치 프록시 서버처럼 동작한다. 그리고 인증 및 권한, 모니터링, logging 등 추가적인 기능이 있다. 모든 비지니스 로직이 하나의 서버에 존재하는 Monolithic Architecture와 달리 MSA는 도메인별 데이터를 저장하고 도메인별로 하나 이상의 서버가 따로 존재한다. 한 서비스에 한개 이상의 서버가 존재하기 때문에 이 서비스를 사용하는 클라이언트 입장에서는 다수의 end point가 생기게 되며, end point를 변경이 일어났을때, 관리하기가 힘들다. 그래서 MSA 환경에서 서비스에 대한 도메인인 하나로 통합할 수 있는 API GATEWAY가 필요한 것이다.

Zuul은 Netflix에서 만든 API Gateway 오픈소스로 Java 프로젝트이다. 다른 오픈소스로는 KONG, API Umbrella, tyk.io 등이 있다.

Zuul

Zuul은 넷플릭스에서 만든 API Gateway로 그루비로 작성되었으며 filter 개념을 통해서 API Gateway에 추가 기능을 넣고 관리할 수 있다.

Zuul은 Filter를 통해서 다음과 같은 기능을 구현하고있다.

  • Authentication and Security : 클라이언트 요청시, 각 리소스에 대한 인증 요구 사항을 식별하고 이를 만족시키지 않는 요청은 거부
  • Insights and Monitoring : 의미있는 데이터 및 통계 제공
  • Dynamic Routing : 필요에 따라 요청을 다른 클러스터로 동적으로 라우팅
  • Stress Testing : 성능 측정을 위해 점차적으로 클러스터 트래픽을 증가
  • Load Shedding : 각 유형의 요청에 대해 용량을 할당하고, 초과하는 요청은 제한
  • Static Response handling : 클러스터에서 오는 응답을 대신하여 API GATEWAY에서 응답 처리

Zuul Core Architecture.png출처 - https://medium.com/netflix-techblog/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee

위는 Zuul 아키텍처를 나타내는 그림이다.

  • Filter File Manager에서는 일정 주기(정해진 시간) 마다 정해진 directory에서 groovy로 정의된 filter 파일을 가져온다.
  • ZuulServlet은 HttpServlet을 재정의 하였다.
  • Request 요청이 들어 올때마다 아래와 같이 preRoute(), route(), postRoute()에서 ZuulFilter Runner를 실행한다.
  • 각 단계에서 Filter들은 비동기로 실행되며 통신을 위해서 RequestContext를 공유한다.
  • ZuulFilter Runner는 Filter에 정의된 기능을 실행한다.
@Override
public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
    try {
        init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);

        // Marks this request as having passed through the "Zuul engine", as opposed to servlets
        // explicitly bound in web.xml, for which requests will not have the same data attached
        RequestContext context = RequestContext.getCurrentContext();
        context.setZuulEngineRan();

        try {
            preRoute();
        } catch (ZuulException e) {
            error(e);
            postRoute();
            return;
        }
        try {
            route();
        } catch (ZuulException e) {
            error(e);
            postRoute();
            return;
        }
        try {
            postRoute();
        } catch (ZuulException e) {
            error(e);
            return;
        }

    } catch (Throwable e) {
        error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
    } finally {
        RequestContext.getCurrentContext().unset();
    }
}

Zuul filter

Zuul은 필터를 통해서 API Gateway에 필요한 기능들을 추가하거나 관리할 수 있다.

각 리퀘스트는 네 가지 라이프사이클 흐름으로 처리되며 아래와 같이 네 가지 필터를 탄다.

  • Pre Filter - 라우팅 전에 실행되는 필터, 인증과 로깅 기능은 주로 여기에 들어간다.
  • Routing Filter - 요청에 대한 라우팅을 다루는 필터, Apache http client를 사용하여 정해진 Url로 보낼수 있고, Neflix Ribbon을 사용하여 동적으로 라우팅 할 수도 있다.
  • Post Filter - 라우팅 후에 실행되는 필터, response에 HTTP header를 추가하거나, response에 대한 응답속도, Status Code, 등 응답에 대한 statistics and metrics을 수집한다.
  • Error Filter - 에러 발생시 실행되는 필터, 필터 실행 후 Post Filter가 실행된다.

Request Lifecycle 출처 - https://medium.com/netflix-techblog/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee

Filter Interface

필터를 정의하려면 ZuulFilter를 상속받아서 아래 네 개의 메소드를 구현해야한다.

String filterType();

int filterOrder();

boolean shouldFilter();

Object run();

To Run, or Maybe Not

shouldFilter는 해당 필터가 실행될 것인가에 대한 로직을 담는다. true를 리턴한다면 필터가 실행된다.

Ordering

filterOrder는 같은 Type에서 실행되는 필터들과의 우선순위를 나타내는 int값을 리턴한다.

Filter Types

이 메소드는 필터 타입에 대한 String 값을 리턴한다. Zuul에서 제공하는 기본 필터타입은 pre, routing, post, error이다. 이 밖에 필터 타입은 GroovyProcessor.runFilters를 직접 구현해서 추가할 수 있다.

Filter Coordination

run() 메소드는 이 필터가 어떤 작업을 하는지 정의한다.

다음은 ZuulFilter를 상속받아서 내부 IP에 대한 접근인지를 확인하는 필터 예제이다.

class InternalCheckFilter : ZuulFilter() {

    private val internalIpRegex = Regex("(0:|127\\.|10\\.|172\\.|192\\.).*")


    override fun filterType() = 'pre'

    override fun filterOrder() = -1

    override fun shouldFilter(): Boolean {
        val uri = RequestContext.getCurrentContext().request.requestURI ?: ""
        return (uri.contains("/internal") || uri.contains("/universal"))
    }

    override fun run(): Any? {
        val ctx = RequestContext.getCurrentContext()
        val request = ctx.request
        val ip = request.remoteAddr

        if (!isInternalIp(ip)) {
            ctx.setSendZuulResponse(false)
            ctx.responseStatusCode = HttpStatus.FORBIDDEN.value()
        }

        return null
    }

    fun isInternalIp(ip: String?): Boolean {
        return ip?.matches(internalIpRegex) ?: false
    }

}


'DevOps' 카테고리의 다른 글

fluentd mac설치  (0) 2018.12.18
macbook에 프로메테우스 설치  (0) 2018.11.30
MSA모니터링-Prometheus개념  (0) 2018.11.29
MSA-Spring Cloud  (0) 2018.09.28
Hystrix-Isolation  (0) 2018.09.28
API Gateway: Zuul  (0) 2018.09.03

+ Recent posts