들어가기 전에
분산된 애플리케이션을 운영하는 MSA(Micro Service Architecture) 환경이 많은 모놀리식을 대체하기 시작한지도 많은 시간이 흘렀습니다.
하지만 Kubernetes와 같은 오케스트레이션 툴이 등장했음에도 불구하고 여전히 마이크로 서비스에서 네트워크 정책을 수립하는 것은 쉽지 않습니다.
이런 문제로 인해 어플리케이션을 개발하는 개발자와 클러스터를 운영하는 운영자 모두 네트워크 레이어의 문제를 해결하기 위해 많은 노력과 시간을 쏟아야 했습니다.
그러자 개발자와 운영자는 모두가 문제를 해결하기 위해 참여하는 대신 어플리케이션 레이어의 비즈니스 로직에만 집중할 수 있는 환경을 원하기 시작했습니다.
이런 환경을 제공하기 위해 나타난 개념이 ”서비스 메쉬(Service mesh)”입니다.
서비스 메쉬는 사이드카 프록시 구조를 통해 네트워크 레이어의 모니터링, 보안 등과 같은 문제들을 단일 네트워크 도구로 해결할 수 있게끔 했습니다.
그리고 이런 서비스메쉬를 오픈소스로 구현한 서비스가 바로 “Istio”입니다.
Istio는 서비스메쉬의 사이드카 구조를 취하면서 기존의 L4에서 L7으로 네트워킹 기능을 강화하고 Observerbility, security 등의 관리성을 높인 Cloud-native 오픈소스 서비스 메쉬입니다.
“Istio”는 마이크로 서비스 아키텍쳐 환경에서 관리의 복잡성을 줄이고 네트워킹 기능을 강화하기 위한 오픈소스 서비스 메쉬이다.
이번 포스팅에서는 istio를 통해 무엇을 해결할 수 있는지, 퍼블릭 클라우드 환경에서 istio 기반의 서비스 메쉬를 사용하면 어떤 장점이 있는지, 또 어떤 점을 주의해서 구성해야 하는지 알아보겠습니다.
Why Istio?
Isito 서비스 메쉬 구조의 가장 큰 특징은 “사이드카 프록시" 를 사용한 네트워킹입니다.
Istio의 사이드카 프록시는 pod마다 하나씩 배치되며 기존의 어플리케이션 컨테이너의 트래픽을 가로채(intercept) 네트워킹을 대신 수행합니다.
이런 특징으로 인해 Kubernetes 환경에서 사용 시 istio의 사이드카 프록시는 기존의 kube-proxy 중심의 트래픽 매니지먼트를 완전히 대체합니다.
이런 차이로 인해 쿠버네티스와 서비스 메쉬 구조의 트래픽 흐름은 큰 차이가 있습니다. 서비스 메쉬 구조의 트래픽 흐름이 기존보다 한 홉(Hop) 더 추가되었지만 사이드카 프록시는 어플리케이션 컨테이너와 네트워크 스택을 공유하기 때문에 큰 비용이 발생하지 않습니다.
이런 Istio 프록시의 자세한 동작은 프록시 로그에서 자세히 볼 수 있습니다.
Grafana 어플리케이션이 169.254.169.254:80을 목적지로 HTTP 요청 트래픽을 보내지만 Istio 프록시가 요청을 가로채 막아버린(block_all) 로그입니다. HTTP 헤더를 감지하는 것으로 보아 L7 기능을 수행할 수 있음을 알 수 있습니다.
어플리케이션은 자신의 요청이 가로채진지 모르지만 위처럼 모든 트래픽은 Istio 프록시가 가로채 어플리케이션과 완전히 분리된 네트워킹 정책을 적용받게 됩니다.
그래서 Istio 프록시는 L7 트래픽을 처리할 수 있는 L7 프록시로써 기존의 L4로 동작하던 네트워킹 레이어에 헬스체크, 라우팅 등의 L7 계층 기능을 추가할 수 있으며,
애플리케이션 레이어를 네트워크 레이어와 완전히 분리하기 때문에 개발자는 네트워크 정책에 구애받지 않고 온전히 개발에 집중할 수 있게 한다는 장점이 있습니다.
Public cloud에서 Istio 사용하기
현재 AWS, Azure, GCP 등의 다양한 Public cloud 환경에서 Istio를 사용할 수 있습니다. 이번 챕터에서는 GCP의 GKE 클러스터를 기준으로 Istio를 설치합니다.
클라우드 벤더 별로 클러스터 제약조건이 다르므로 Istio 설치 전 필히 확인해야 합니다.벤더 별 Istio를 설치할 클러스터 생성 방법은 Istio 공식 도큐먼트에서 확인할 수 있습니다.
- Istio 설치 제약조건을 충족하는 GKE 클러스터를 생성합니다.
1
2
3
4
5
6
7
8
9
10
11
|
$ export PROJECT_ID=`gcloud config get-value project` && \
export M_TYPE=n1-standard-2 && \
export ZONE=us-west2-a && \
export CLUSTER_NAME=${PROJECT_ID}-${RANDOM} && \
gcloud services enable container.googleapis.com && \
gcloud container clusters create $CLUSTER_NAME \
--cluster-version latest \
--machine-type=$M_TYPE \
--num-nodes 4 \
--zone $ZONE \
--project $PROJECT_ID
|
cs |
2. Istio를 설치하기 위해 Istio 관리 툴인 “Istioctl”을 설치합니다.
1
2
3
|
$ curl -L https://istio.io/downloadIstio | sh -
cd istio-1.11.2
export PATH=$PWD/bin:$PATH
|
cs |
3. Istio는 Configuration profile을 제공해 사용 목적 별로 설치할 컴포넌트를 지정할 수 있습니다.Configuration profile 을 지정해 설치를 진행합니다.
1
2
3
4
5
6
|
$ istioctl install --set profile=demo -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete
|
cs |
4. Istio가 어플리케이션에 사이드카 프록시를 주입(injection)할 수 있도록 네임스페이스 라벨을 추가합니다.
1
2
|
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
|
cs |
앞으로 배치되는 어플리케이션은 “istio-injection” 라벨 값으로 사이드카 프록시 주입 여부를 결정할 수 있습니다.
5. Istio가 정상적으로 설치되었는지 확인합니다.
1
2
3
4
5
6
7
8
9
10
11
|
$ kubectl get service -n istio-systemNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-citadel ClusterIP 10.47.245.92 <none> 8060/TCP,9093/TCP 12s
istio-egressgateway ClusterIP 10.47.248.129 <none> 80/TCP,443/TCP 12s
istio-galley ClusterIP 10.47.248.109 <none> 443/TCP,9093/TCP 12s
istio-ingressgateway LoadBalancer 10.47.248.117 <pending> 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30221/TCP,8060:32445/TCP,853:30663/TCP,15030:32010/TCP,15031:32633/TCP 12s
istio-pilot ClusterIP 10.47.251.133 <none> 15010/TCP,15011/TCP,8080/TCP,9093/TCP 12s
istio-policy ClusterIP 10.47.255.244 <none> 9091/TCP,15004/TCP,9093/TCP 12s
istio-sidecar-injector ClusterIP 10.47.240.36 <none> 443/TCP 12s
istio-statsd-prom-bridge ClusterIP 10.47.247.135 <none> 9102/TCP,9125/UDP 12s
istio-telemetry ClusterIP 10.47.242.73 <none> 9091/TCP,15004/TCP,9093/TCP,42422/TCP 12s
promsd ClusterIP 10.47.241.188 <none> 9090/TCP
|
cs |
어플리케이션을 배치해 Istio 프록시가 정상적으로 주입되는지 확인합니다.
grafana 어플리케이션에 Istio 프록시가 자동으로 주입된 모습
다양한 모니터링 툴로 Istio 프록시가 수집한 메트릭 및 로그를 확인할 수 있습니다.
+) GCP의 GKE는 네이티브 옵션으로 Istio를 설치할 수 있는 기능을 제공합니다. 별도의 설치 과정 없이 옵션의 Enable만으로 새 클러스터에 Istio를 설치하거나 기존 클러스터에 Istio를 추가할 수 있습니다.
Public cloud 환경에서 Istio 사용시 주의점
Istio는 기본적으로 Cloud native 기술이기 때문에 Public cloud 환경과 좋은 호환성을 가지고 있습니다.
하지만 Isito의 복잡한 트래픽 관리 기능 때문에 Public cloud 환경에서 istio가 설치된 클러스터를 구성 시 원하는 결과가 나오지 않는 경우가 많습니다.
특히 AWS,Azure,GCP같은 클라우드 플랫폼에서 제공하는 서비스나 기능을 사용하고자 할때 종종 발생합니다.
마지막으로 Public cloud 환경에서 Istio를 사용시 주의해야 할 점을 알아봅니다.
1. 메타데이터 서버 접근 구성
Public cloud 환경에서는 VM 인스턴스의 메타데이터를 관리하기 위한 서버를 따로 두어 보안적으로 중요한 데이터를 인스턴스와 격리시켜 놓습니다.
이때 이 메타데이터를 관리하는 서버를 “메타데이터 서버"라고 합니다.
메타데이터 서버는 서비스 접속에 필요한 Credential을 보관하기 때문에 169.254.169.254의 링크-로컬 주소를 부여해 같은 네트워크의 인스턴스에서만 접근할 수 있도록 구성합니다.
Kubernetes 환경에선 클라우드 프로바이더가 제공하는 IAM역할을 OIDC(OpenID Connect)로 Kubernetes 서비스 계정과 연동하는 기능을 사용할때 메타데이터 서버에 접근하게 됩니다.
이 기능은 IAM 역할 부여를 기존의 Node단위에서 Pod단위로 더 세밀하게 부여하게 해줍니다. 현재는 대부분의 클라우드 프로바이더가 각기 다른 이름으로 제공하고 있습니다.
(AWS의 IAM roles for service account, GCP의 Workload identity, Azure의 AAD pod managed identity 등..)
이 기능을 사용해 IAM와 Kubernetes 서비스 어카운트를 바인딩하는 경우 Pod가 메타데이터 서버에 접근 가능한 상태여야 합니다.
하지만 클러스터에 높은 수준의 네트워크 격리 정책을 적용한 경우 사용자도 모르게 메타데이터 서버로 향하는 트래픽을 거부하는 경우가 발생합니다.
특히 Istio에서 REGISTRY_ONLY 모드를 지정해 화이트리스팅 정책을 적용하는 경우 더 자주 발생합니다.
Istio 프록시 로그를 확인하는 것으로 문제를 정확히 진단할 수 있습니다.
메타데이터 서버로 향하는 트래픽이 block된 경우 아래와 같은 로그가 남게 됩니다.
문제를 해결하려면 아래와 같이 대처합니다.
- 어플리케이션 수준 해결
메타데이터 서버를 접속하고자 하는 어플리케이션에 아래 주석(annotation)을 추가합니다.
1
|
"traffic.sidecar.istio.io/excludeOutboundIPRanges=169.254.169.254/32"
|
cs |
- 글로벌 수준 해결
클러스터에 아래와 같은 서비스엔트리(ServiceEntry)를 추가합니다.
spec.hosts값에 메타데이터 서버의 호스트네임을 입력합니다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: metadata-internal
namespace: istio-egress
spec:
hosts:
- metadata.host.name
addresses:
- 169.254.169.254
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: tls
protocol: TLS
resolution: DNS
location: MESH_EXTERNAL
|
cs |
+) 어플리케이션이 메타데이터 서버의 호스트네임이 아닌 IP 주소로 접근하는 경우 문제가 발생할 수 있습니다.
이 경우 resolution: NONE으로 변경 시 다시 정상적으로 접근할 수 있습니다.
2. 서비스 API 서버 접근 구성
메타데이터 서버와 마찬가지로 클라우드 프로바이더의 서비스 API 서버로 접근할 수 있어야 프로바이더가 제공하는 서비스를 사용할 수 있습니다.
기본 클러스터 구성을 사용한다면 API 서버에 접근할 수 있겠지만, 비공개 클러스터를 운영하거나 화이트리스팅 정책을 사용한다면 서비스 API 서버의 접근이 막히는 경우가 발생합니다.
이 경우에도 서비스엔트리(ServiceEntry) 리소스를 생성하는 것을 포함한 트래픽 매니지먼트 수정을 통해 문제를 해결할 수 있습니다.
아래는 GKE에서 Google Cloud Storage 서비스에 접근하고자 하는 경우의 서비스엔트리 예시입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: private-googleapis-com
namespace: istio-egress
spec:
hosts:
- storage.googleapis.com
ports:
- number: 80
name: http
protocol: HTTP
- number: 443
name: tls
protocol: TLS
resolution: DNS
location: MESH_EXTERNAL
|
cs |
마치며
Istio는 분명히 강력한 서비스메쉬 도구이지만 러닝커브의 벽은 여전히 높은 것 같습니다.
해외에서 이미 Istio를 n년간 도입했던 서비스들도 대부분 “Istio는 너무 복잡하다"는 이유로 도입을 철회하는 경우를 볼 수 있습니다.
하지만 점차 GCP의 Anthos와 같은 Managed Istio 서비스들이 출시되고 있기 때문에 이같은 복잡성 문제는 해결될 것으로 생각합니다.
Istio는 Google, IBM, Redhat 등의 업체가 참여하고 있는 대형 프로젝트이기 때문에 서비스 메쉬는 이미 멈출 수 없는 대세인 듯 합니다.
본 포스팅으로 Istio 서비스 메쉬를 도입하고자 하는 많은 분들이 도움을 받았으면 합니다.
'Network' 카테고리의 다른 글
Minikube로 로컬 환경에서 쿠버네티스 클러스터 구성하기(MacOS, Windows 환경) (3) | 2022.04.30 |
---|---|
Rclone을 이용해 편리하게 Storage간 데이터 전송하기 (6) | 2020.10.01 |
X11 Forwarding을 통해 AWS EC2에서 GUI 사용해보기 (0) | 2020.03.13 |
용어를 확실히- Sharding 이란? (0) | 2019.12.24 |
용어를 확실히- RTO,RPO (0) | 2019.12.24 |