PS1팀 조웅기
istio 사용하기
이스티오(Istio)란?
- 서비스 메쉬 오픈소스
- 기존의 응용프로그램 위에 레이어링되어 다양한 동작들을 수행
- GCP에서는 이를 완전 관리해주는 서비스를 Anthos라고 함
- 서비스 메쉬 설명 전 마이크로서비스란?
- 소프트웨어를 구축하기 위한 아키텍처이자 하나의 접근 방식으로, 애플리케이션을 상호 독립적인 최소 구성 요소로 분할하는 방식
- 모든 요소를 하나의 애플리케이션에 구축하는 전통적인 접근 방식 대신 마이크로서비스에서는 모든 요소가 독립적이며 연동되어 테스크를 수행
- 이러한 각각의 구성 요소 또는 프로세스가 마이크로 서비스
- 그렇다면 서비스 메쉬란 무엇인가?
- 마이크로 서비스를 위한 인프라 계층
- 레거시 코드의 변경 없이 각 서비스에 대해 가시성, 트래픽 관리, 보안 기능 등을 추가
- 복잡하고 방대한 규모의 마이크로서비스에 대한 관리 용이
- 마이크로서비스를 적용한 시스템의 내부 통신이 Mesh 네트워크 형태를 띄는 것에 빗대어 서비스 메쉬라고 말하고 있음
- 서비스 간의 통신을 추상화를 통해 복잡한 내부 구조를 제어, 추적, 내부 네트워크 관련 로직을 추가함으로써 안정성, 신뢰성, 탄력성, 표준화, 가시성, 보안성 등을 확보
- Service Mesh 는 URL 경로, 호스트 헤더, API 버전 또는 기타 응용 프로그램 수준 규칙을 기반으로 하는 계층 7 네트워크 Layer
- Service Mesh 의 구현체인 경량화 Proxy를 통해 다양한 Routing Rules, Circuit breaker 등 공통기능을 설정할 수 있습니다.
- 이는 서비스 간 통신에 연관된 기능 뿐만 아니라, 서비스의 배포 전략에도 도움을 줍니다.
이스티오가 제공하는 기능들
- 클러스터 내부에서 TLS 암호화를 이용한 서비스간 안전한 통신 제공
- HTTP, gRPC, WebSocket 및 TCP 트래픽에 대한 로드 밸런싱
- 재시도, 다양한 라우팅 규칙, fault injection 등을 통해 세부 트래픽 동작을 제어
- 클러스터 내의 모든 트래픽에 대한 메트릭 수집과 로그 추적
이스티오의 아키텍처
<Istio 활용 전 아키텍쳐)
<Istio 활용 후 아키텍쳐)
- 데이터 플레인
- 데이터 플레인은 데이터 전송과 처리를 담당하는 부분
- 각 서비스를 Envoy proxy와 함께 배포(사이드카 패턴 방식)
- 각 서비스 앞단에 프록시 서버를 두어 서비스로 또는 서비스로부터 나가는 모든 네트워크 패킷을 변환, 전달 및 모니터링
- Envoy proxy란?
- 클라우드 네이티브용으로 Lyft 사에서 C++로 개발해서 2016년 12월 14일 공개한 L7 프록시
- 2017년 5월에 Google, Lyft, IBM에서 공동으로 개발해서 내놓은 Service Mesh 오픈소스인 Istio의 메인 프록시가 됨
- 주요 기능
- OUT OF PROCESS ARCHITECTURE
- Envoy proxy는 그 자체로 메모리사용량이 적은 고성능의 서버입니다.
- 모든 프로그래밍 언어, 프레임워크와 함께 실행될 수 있습니다.
- 이는 다양한 언어,프레임워크를 함께 사용하는 Architecture에 유용히 사용될 수 있습니다.
- HTTP/2(1) AND gRPC SUPPORT
- HTTP/1.1은 물론 HTTP/2도 지원합니다.
- 이는 HTTP/1.1과 HTTP/2 클라이언트와 서버간 모든 조합을 연결할 수 있음을 의미합니다.
- 권장하는 구조는 모든 Envoy간에 HTTP/2를 사용하는 것입니다.
- 또한 gRPC를 지원하여 HTTP/2기능을 보완할 수 있습니다.
- L3/L4 Architecture : Envoy의 주요 기능은 L7이지만 핵심은 L3/L4 네트워크 프록시 입니다. TCP프록시, HTTP프록시, TLS인증과 같은 다양한 작업을 지원합니다.
- L7 Architecture : 버퍼링, 속도제한, 라우팅/전달 등과 같은 다양한 작업을 수행할 수 있게 합니다.
- ADVANCED LOAD BALANCING
- 자동 재시도, circuit break, 외부 속도 제한 서비스를 통한 글로벌 속도제한, 이상치 탐지 등의 기능을 제공합니다.
- APIS FOR CONFIGURATION MANAGEMENT
- Envoy는 구성을 동적으로 관리하기 위한 강력한 API를 제공합니다.
- OBSERVABILITY
- L7 트래픽의 심층 관찰 성, 분산 추적에 대한 기본 지원, MongoDB, DynamoDB 등의 와이어 수준 관찰성을 제공합니다.
- OUT OF PROCESS ARCHITECTURE
- 사이드카 패턴이란?
- 사이드카 패턴은 원래 사용하려고 했던 기본 컨테이너의 기능을 확장하거나 보조하는 용도의 컨테이너를 추가하는 패턴
- 즉, 기본 컨테이너와 독립적으로 동작하는 별도의 컨테이너를 붙이는 패턴이기 때문에 어플리케이션 컨테이너의 변경이나 수정 없이 독립적으로 동작하는 컨테이너를 붙였다 뗐다 할 수 있다.
- 컨트롤 플레인
- 컨트롤 플레인은 네트워크의 제어와 관리를 담당하는 부분
- 회로 차단, 로드 밸런싱, 타임아웃 등의 기본 구성 정보를 저장
- 기본 구성 정보에 맞게 각 서비스의 프록시를 동
istio 테스트
테스트 환경 구성
1. 테스트용 이미지 생성
$ dotnet --version # 닷넷 기반 테스트 이미지 생성을 위한 설치 확인
$ dotnet new mvc -o HelloWorldAspNetCore # 닷넷 기반 웹 응용 프로그램 생성
$ vim Dockerfile # 도커 파일 생성
# Use Microsoft's official build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS build
WORKDIR /app
# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore
# Copy local code to the container image.
COPY . ./
WORKDIR /app
# Build a release artifact.
RUN dotnet publish -c Release -o out
# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine AS runtime
WORKDIR /app
COPY --from=build /app/out ./
# Make sure the app binds to port 8080
ENV ASPNETCORE_URLS http://*:8080
# Run the web service on container startup.
ENTRYPOINT ["dotnet", "HelloWorldAspNetCore.dll"]
# 아래 코드 실행하기 전 Artifact Registry 저장소 생성
$ docker build -t asia-northeast3-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/<생성한 저장소 이름>/hello-dotnet:v1 .
$ docker push asia-northeast3-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/<생성한 저장소 이름>/hello-dotnet:v1
2. GKE 생성
$ gcloud services enable container.googleapis.com # GKE API 설정
gcloud container clusters create istio-test \
--cluster-version=latest \
--machine-type=n1-standard-2 \
--num-nodes=1 \
--region asia-northeast3
3. Istio 클라이언트 다운
$ curl -L https://istio.io/downloadIstio | sh -
# cli 창에서 뜬 istio 버전의 디렉토리가 생성됨 (테스트 현재 기준 istio-1.20.0)
$ cd istio-1.20.0
# istioctl을 사용하기 위해 환경 변수 지정
$ export PATH="$PATH:/home//istio-1.20.0/bin"
4. Istio 클라이언트 상태 확인
# 생성한 gke 연결 후
$ gcloud container clusters get-credentials istio-test --region asia-northeast3 --project iistio
$ istioctl x precheck # 환경 확인 (정상이면 아래와 같이 나옴)
No issues found when checking the cluster. Istio is safe to install or upgrade!
$ istioctl install --set profile=demo # 테스트를 위한 demo 프로필 사용 후 설치
$ kubectl label namespace default istio-injection=enabled # 자동 사이드카 매칭
$ kubectl get namespace -L istio-injection # 사이드카 확인
# 정상 설치 확인 (아래 3개 존재 확인)
$ kubectl get svc -n istio-system
istio-egressgateway ClusterIP 10.104.3.223 <none> 80/TCP,443/TCP 102s
istio-ingressgateway LoadBalancer 10.104.9.211 34.64.230.54 15021:32493/TCP,80:31798/TCP,443:32556/TCP,31400:30436/TCP,15443:30945/TCP 102s
istiod ClusterIP 10.104.14.127 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 103s
$ kubectl get pods -n istio-system (아래 3개 존재 확인)
istio-egressgateway-56c5f9b7cc-s2xbk 1/1 Running 0 6m25s
istio-ingressgateway-678fd6f6b9-xv8js 1/1 Running 0 6m25s
istiod-664dc95b55-dfpv4 1/1 Running 0 6m25s
5. 애플리케이션 배포
aspnetcore.yaml
apiVersion: v1
kind: Service
metadata:
name: aspnetcore-service
labels:
app: aspnetcore
spec:
ports:
- port: 8080
name: http
selector:
app: aspnetcore
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: aspnetcore-v1
spec:
replicas: 1
selector:
matchLabels:
app: aspnetcore
version: v1
template:
metadata:
labels:
app: aspnetcore
version: v1
spec:
containers:
- name: aspnetcore
image: asia-northeast3-docker.pkg.dev//hello-dotnet/hello-dotnet:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
$ kubectl apply -f aspnetcore.yaml
$ kubectl get pods
6. 테스트용 게이트웨이 및 가상 서비스 배포
aspnetcore-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: aspnetcore-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
aspnetcore-virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: aspnetcore-virtualservice
spec:
hosts:
- "*"
gateways:
- aspnetcore-gateway
http:
- route:
- destination:
host: aspnetcore-service
7. 정상 동작 테스트
kubectl get svc istio-ingressgateway -n istio-system
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}/
<서비스 접속 확인)
8. 신규 버전 배포
vim aspnetcore2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: aspnetcore-v2
spec:
replicas: 1
selector:
matchLabels:
app: aspnetcore
version: v2
template:
metadata:
labels:
app: aspnetcore
version: v2
spec:
containers:
- name: aspnetcore
image: asia-northeast3-docker.pkg.dev/iistio/hello-dotnet/hello-dotnet:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
v1와 v2배포가 모두 동일한 Kubernetes 서비스( aspnetcore-service) 뒤에 노출되고 이전 실습( )에서 생성한 VirtualService가 aspnetcore-virtualservice해당 서비스를 호스트로 사용하여 새로 고침을 하였을 때 각각 다르게 나옵니다.
9. 서비스 새 버전으로 고정
- DestinationRule은 해당 대상 호스트의 명명된 버전을 의미하는 주소 지정 가능한 하위 집합도 정의하며 특정 버전의 서비스로 트래픽을 보낼 때 VirtualService 경로 사양에 사용
- 본 서버(v1) 업데이트 시에 임시 서버(v2)를 바라보게 셋팅 가능 추측
aspnetcore-destinationrule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: aspnetcore-destinationrule
spec:
host: aspnetcore-service
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
# VirtualService에서 사용할 수 있는 두 개의 하위 집합(v1 및 v2)이 생성
$ kubectl apply -f aspnetcore-destinationrule.yaml
aspnetcore-virtualservice.yaml 수정
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: aspnetcore-virtualservice
spec:
hosts:
- "*"
gateways:
- aspnetcore-gateway
http:
- route:
- destination:
host: aspnetcore-service
**subset: v2 # 이렇게 서브셋을 지정해줌**
$ kubectl apply -f aspnetcore-virtualservice.yaml
10. 버전 간 트래픽 분할
- 테스트나 과부화를 위한 트래픽 분할 가능
: 예를 들어 트래픽의 75%를 v1로 보내고 트래픽의 25%를 v2 버전의 서비스로 보낼 수 있음 - 카나리 배포로 사용
aspnetcore-virtualservice.yaml 수정
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: aspnetcore-virtualservice
spec:
hosts:
- "*"
gateways:
- aspnetcore-gateway
http:
- route:
- destination:
host: aspnetcore-service
subset: v1
weight: 75
- destination:
host: aspnetcore-service
subset: v2
weight: 25
$ kubectl apply -f aspnetcore-virtualservice-weights.yaml
11. 지연 및 에러 코드 발생 시키기
- 트래픽에 오류나 지연을 삽입하고 서비스가 이에 응답하여 어떻게 작동하는지 확인 가능
aspnetcore-virtualservice-fault-abort.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: aspnetcore-virtualservice
spec:
hosts:
- "*"
gateways:
- aspnetcore-gateway
http:
- fault: ## fault를 추가하면 에러 코드를 반환시킬 수 있다. 400 코드를 50% 반환
abort:
percentage:
value: 50
httpStatus: 400
route:
- destination:
host: aspnetcore-service
subset: v1 # 버전 1에 대해 에러 400 반환
$ kubectl apply -f aspnetcore-virtualservice-fault-abort.yaml
- 지연이 필요한 경우 아래와 같이 설정할 수 있습니다.
aspnetcore-virtualservice-fault-delay.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: aspnetcore-virtualservice
spec:
hosts:
- "*"
gateways:
- aspnetcore-gateway
http:
- fault:
delay: # 지연
fixedDelay: 5s # 5초
percentage:
value: 100 # 100프로의 확률로
route:
- destination:
host: aspnetcore-service
subset: v1 # v1에 대해
$ kubectl apply -f aspnetcore-virtualservice-fault-delay.yaml
Istio 모니터링 하기
Prometheus (로그 메트릭 수집)
# 설치
$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml
# 설치 확인
$ kubectl get svc prometheus -n istio-system
# 확인을 위한 포트 포워딩
$ kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 8080:9090
Grafana (모니터링)
# 설치
$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/grafana.yaml
# 설치 확인
kubectl get svc grafana -n istio-system
# 확인을 위한 포트 포워딩
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 8080:3000
Kiali (모니터링)
# 설치
$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.11/samples/addons/kiali.yaml
# 설치 확인
kubectl get svc grafana -n istio-system
# 확인을 위한 포트 포워딩
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=kiali -o jsonpath='{.items[0].metadata.name}') 8080:20001