[Study 7주차] 쿠버네티스 Service Mesh - Istio 기능 & Bookinfo 실습
- -
CoudNet@ 팀의 가시다님께서 리딩하시는 KANS Study (Kubernetes Advanced Networking Study) 7주차 스터디 내용 정리
저번 글에 이어서 서비스 메시 Istio 대해 알아보겠습니다.
이번에는 이스티오 공식 문서에 있는 데모 어플리케이션인 Book Info 를 배포한 후 이스티오의 동작을 이해해보겠습니다.
1. Book Info 어플리케이션
이스티오 실습을 위한 데모 마이크로서비스 어플리케이션입니다.
Productpage, reviews, ratings, details 의 4개의 마이크로서비스로 구성되어 있습니다.
Book info 어플리케이션의 동작방식
1. ProductPage 페이지에서 요청
2. 도서 리뷰를 보여주는 Reviews 서비스와 도서 상세 정보를 보여주는 Details 서비스에 접속
3. ProductPage 는 Reviews 와 Details 결과 응답
4. Reviews 서비스는 v1, v2, v3 세 개의 버전이 있고 v2, v3 버전의 경우 Ratings 서비스에 접속하여 도서에 대한 5단계 평가 응답
5. v1 Review 는 Rating 이 없고, v2 Review 는 검은색 별로 Ratings 표시, v3 Review는 색깔이 있는 별로 Ratings 표시
1.1. Book Info 어플리케이션 배포
실습환경은 이전 글에서 구성한 서버를 이용합니다.
이스티오가 설치된 서버에서 실행합니다.
Book info Yaml 파일은 아래와 같습니다.
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################################################################
# This file defines the services, service accounts, and deployments for the Bookinfo sample.
#
# To apply all 4 Bookinfo services, their corresponding service accounts, and deployments:
#
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
#
# Alternatively, you can deploy any resource separately:
#
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l service=reviews # reviews Service
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l account=reviews # reviews ServiceAccount
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3 # reviews-v3 Deployment
##################################################################################################
##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
service: details
spec:
ports:
- port: 9080
name: http
selector:
app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-details
labels:
account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: details-v1
labels:
app: details
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: details
version: v1
template:
metadata:
labels:
app: details
version: v1
spec:
serviceAccountName: bookinfo-details
containers:
- name: details
image: docker.io/istio/examples-bookinfo-details-v1:1.20.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: ratings
labels:
app: ratings
service: ratings
spec:
ports:
- port: 9080
name: http
selector:
app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-ratings
labels:
account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratings-v1
labels:
app: ratings
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: ratings
version: v1
template:
metadata:
labels:
app: ratings
version: v1
spec:
serviceAccountName: bookinfo-ratings
containers:
- name: ratings
image: docker.io/istio/examples-bookinfo-ratings-v1:1.20.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
service: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-reviews
labels:
account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
app: reviews
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v1
template:
metadata:
labels:
app: reviews
version: v1
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v1:1.20.1
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v2
labels:
app: reviews
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v2
template:
metadata:
labels:
app: reviews
version: v2
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v2:1.20.1
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v3
labels:
app: reviews
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v3
template:
metadata:
labels:
app: reviews
version: v3
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v3:1.20.1
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
service: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-productpage
labels:
account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
app: productpage
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9080"
prometheus.io/path: "/metrics"
labels:
app: productpage
version: v1
spec:
serviceAccountName: bookinfo-productpage
containers:
- name: productpage
image: docker.io/istio/examples-bookinfo-productpage-v1:1.20.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
---
# Book info 설치
ISTIOV=1.23.2
echo $ISTIOV
kubectl apply -f ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml
# 해당 서버에서 접속 테스트
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
1.2. Book Info 어플리케이션 접속 구성 및 확인
Istio Gateway & VirtualService 배포
- bookinfo-gateway.yaml 정보
파드에 진입하기 위한 게이트웨이 및 라우터 설정입니다.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
# The selector matches the ingress gateway pod labels.
# If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 8080
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
# Gateway & VirtualService 배포
kubectl apply -f ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml
# Gateway & VirtualService 정보 확인
kubectl get gw,vs
istioctl proxy-status
외부 접속 테스트
- k3s-s 서버에서 접속
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
# Control Plane
curl -s http://localhost:$IGWHTTP/productpage
# Node 1번
curl -s http://192.168.10.101:$IGWHTTP/productpage
# Node 2번
curl -s http://192.168.10.102:$IGWHTTP/productpage
- Local PC 에서 접속
curl -v -s $MYDOMAIN:$IGWHTTP/productpage
- testpc 에서 접속
curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>"
브라우저를 통한 접근 확인
echo -e "http://$MYDOMAIN:$IGWHTTP/productpage"
# http://www.kimalarm.com:32251/productpage
2. 이스티오 모니터링
Kiali 를 통해 이스티오를 연동하여 시각화 대시보드를 구성할 수 있습니다.
저희는 데모 환경이므로, kiali / Prometheus / Grafana / Jaeger 를 한 번에 설치했습니다.
2.1. 모니터링 도구 구성
# 샘플 애드온 디렉토리 구조 확인
tree ~/istio-$ISTIOV/samples/addons/
# 출력 화면
/root/istio-1.23.2/samples/addons/
├── README.md
├── extras
│ ├── prometheus-operator.yaml
│ ├── skywalking.yaml
│ └── zipkin.yaml
├── grafana.yaml
├── jaeger.yaml
├── kiali.yaml
├── loki.yaml
└── prometheus.yaml
# 도구 설치
kubectl apply -f ~/istio-$ISTIOV/samples/
각 도구별 노드포트 구성
편의를 위해 노드포트로 접근을 허용해줍니다.
# Kiali 서비스
kubectl patch svc -n istio-system kiali -p '{"spec":{"type":"NodePort"}}'
KIALINodePort=$(kubectl get svc -n istio-system kiali -o jsonpath={.spec.ports[0].nodePort})
echo -e "KIALI UI URL = http://$(curl -s ipinfo.io/ip):$KIALINodePort"
# Grafana 서비스
kubectl patch svc -n istio-system grafana -p '{"spec":{"type":"NodePort"}}'
GRAFANANodePort=$(kubectl get svc -n istio-system grafana -o jsonpath={.spec.ports[0].nodePort})
echo -e "Grafana URL = http://$(curl -s ipinfo.io/ip):$GRAFANANodePort"
# Prometheus 서비스
kubectl patch svc -n istio-system prometheus -p '{"spec":{"type":"NodePort"}}'
PROMENodePort=$(kubectl get svc -n istio-system prometheus -o jsonpath={.spec.ports[0].nodePort})
echo -e "Prometheus URL = http://$(curl -s ipinfo.io/ip):$PROMENodePort"
이스티오와 엔보이 메트릭이 수집되고 있는 것을 알 수 있습니다.
2.2. Kiali 대시보드 둘러보기
방금 구성한 Kiali 에서 시각화 대시보드를 확인해봅니다.
혹시 아무런 그래프가 그려지지 않으면, 우측 상단에 시간을 늘려주거나 서버에 트래픽을 흘려보내면 됩니다.
# testpc 서버에서 진행
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; don
Security 정보 확인
Security 탭을 누르면 우측 패널에 인증에 대한 정보가 나옵니다.
3. Traffic Management
서비스 메시 이스티오의 다양한 네트워크 제어 기능을 살펴보겠습니다.
3.1. Request Routing
Request Routing 은 의도한 바로 네트워크 라우팅을 설정할 수 있는 기능입니다.
# 기본 Destination Rule 적용
cd ~/istio-$ISTIOV/samples/bookinfo/networking
tree
# 기본 DestinationRule 적용
kubectl apply -f destination-rule-all.yaml
reviews v1 으로만 통신 설정
해당 VirtualService Yaml 내용입니다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- route:
- destination:
host: details
subset: v1
---
# istio vs(virtualservices) 확인
kubectl get vs
NAME GATEWAYS HOSTS AGE
bookinfo ["bookinfo-gateway"] ["*"] 44m
# 모든 마이크로서비스에 대해 v1 의 서브셋(subset) 에 전송되게 virtualservices 적용
kubectl apply -f virtual-service-all-v1.yaml
해당 설정 적용 후, reviews 서비스에 대해 v1 로만 트래픽이 흐르는 것을 알 수 있습니다.
reviews v2 으로만 통신 설정
match 의 exact 를 사용해 값이 완전히 일치되는 값만 별도의 destination 라우팅을 설정할 수 있습니다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
jason 유저에 대해서는 v2 로 이동하게 설정합니다.
kubectl apply -f virtual-service-reviews-test-v2.yaml
Book Info 웹페이지에서 jason 으로 로그인 합니다. (비밀번호는 아무거나 입력해도 로그인 가능)
jason 로그인 성공 시, reviews v2 에 해당하는 검은 별 리뷰 화면이 출력됩니다.
Kiali 대시보드에서도 v2 로 흐르는 트래픽이 캡쳐됩니다.
3.2. Fault Injection
Fault Injection 은 의도적으로 서비스를 지연 시키거나 중단하는 것입니다.
jason 유저는 7초 지연 발생, 그외 사용자는 정상 연결
jason 유저에 대해 7초의 지연 시간을 발생 시키는 설정입니다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- headers:
end-user:
exact: jason
fault:
delay:
percentage:
value: 100.0
fixedDelay: 7s
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
kubectl apply -f virtual-service-ratings-test-delay.yaml
jason 유저로 로그인을 시도해봅니다.
7초 이상 로그인이 지연되었기 때문에, 실패 응답을 반환합니다.
kiali 대시보드에서 해당 트래픽에 문제가 있는 것을 알 수 있습니다.
jason 유저는 500 에러 발생, 그외 사용자는 정상 연결
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- headers:
end-user:
exact: jason
fault:
abort:
percentage:
value: 100.0
httpStatus: 500
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
kubectl apply -f virtual-service-ratings-test-abort.yaml
jason 유저로 로그인 시도 시, reviews 서비스에 오류가 발생한 것을 확인할 수 있습니다.
4. Istio 보안
보안이 강한 회사에서는 제로 트러스트 정책을 기반으로 보안 거버넌스를 수립할 것입니다.
제로 트러스트는 아무도 신뢰할 수 없으며,
사내 내부자들 또한 악의적인 공격을 할 수 있다는 가정하에 최소한의 권한과 세밀한 통제를 지속적으로 수행하는 보안 활동을 의미합니다.
4.1. mTLS Authentication
Istio 는 기본적으로 mtls (상호 인증) 방식의 통신을 하기 때문에 보안 효율성을 높일 수 있습니다.
* TLS
- 암호화를 통한 인증, 통신 기밀성 제공
* mTLS
- 서버측도 클라이언트측에 대한 인증서 확인 및 액세스 권한 확인
Authentication 방식
* Permissive Mode
- 일반 텍스트 트래픽과 상호 TLS 트래픽을 동시에 허용
* Strict Mode
- 상호 TLS 트래픽만 허용
4.2. Authorization
서버 측 Envoy 프록시에서 인바운드 트래픽에 대한 액세스 제어가 가능합니다.
AuthorizationPolicy 리소스를 통해 권한을 부여(Allow) 하거나 거절(Deny) 할 수 있습니다.
Authorization 방식
- Implicit enablement : 인증 미적용 시 모든 요청 허용
- AuthorizationPolicy 는 허용(Allow), 거부(Deny), 사용자 지정(Custom) 등의 동작
- 정책 적용 우선 순위는 Custom - Deny - Allow 순으로 적용
5. Istio 트래픽 흐름
이렇게 다양한 기능을 제공하고 편리한데, 이스티오 도입을 주저하게 만드는 이유는 바로 트래픽 성능 저하 때문일 것입니다.
이전 글의 첫 단락에서도 다뤘지만 서비스 메시가 없는 환경에서 어플리케이션 간 통신은 파드와 파드가 Direct 통신입니다.
서비스 메시가 생기게 되면서 Proxy 가 해당 네트워크 패킷을 가로채 통신을 하게 되는데, 이 때문에 네트워크 지연이 발생합니다.
해당 아키텍처는 외부 트래픽이 파드로 들어왔을 때 트래픽의 흐름을 보여주는 그림입니다.
참고해야할 점은 저 경로를 왕복으로 지나가야 실제 엔드유저가 응답을 받을 수 있다는 것입니다.
그렇기 때문에 단순한 서비스 구조라면 Istio 가 꼭 필요한 지 한 번 생각해봐야될 것입니다.
이번에 서비스 메시를 공부하면서 이스티오의 동작 방식에 대해 많은 공부를 할 수 있었습니다.
양이 방대하여 아직 부족한 부분이 너무 많은데, 시간 날 때마다 틈틈히 공부해야될 것 같습니다.
'Kubernetes' 카테고리의 다른 글
[Study 8주차] 쿠버네티스 Cilium CNI - 서비스 통신 확인 (1) | 2024.10.26 |
---|---|
[Study 8주차] 쿠버네티스 Cilium CNI 개요 (3) | 2024.10.26 |
[Study 7주차] 쿠버네티스 Service Mesh - Envoy Proxy, Istio (1) | 2024.10.19 |
[Study 6주차] 쿠버네티스 Gateway API (3) | 2024.10.13 |
[Study 6주차] 쿠버네티스 Ingress (4) | 2024.10.13 |