Istio Service Mesh
By Bys on April 25, 2024
Istio
1. Istio service mesh
Istio Architecture
Istio는 컨트롤 플레인과 데이터 플레인으로 나뉜다.
- 컨트롤 플레인은 트래픽 라우팅을 위해 프록시를 관리하고 구성하는 역할을 담당한다.
- 데이터 플레인은 사이드카로 배포된 일련의 지능형 프록시(Envoy)로 구성되며 이러한 프록시는 마이크로서비스 간의 모든 네트워크 통신을 중개하고 제어한다. 또한 모든 메시 트래픽에 대해 텔레메트리 정보를 수집하고 보고한다.
Istio Component
- Envoy
Istio는Envoy
프록시를 이용합니다. Envoy는 서비스 메시의 모든 서비스에 대한 모든 Inbound/Outbound 트래픽에 대해 중개하는 고성능 Proxy 입니다. Envoy 프록시는 데이터 플레인 트래픽과 상호작용하는 유일한 Istio 컴포넌트이다.
Envoy 프록시는 사이드카 패턴으로 배포되며 논리적으로 Envoy의 아래의 다양한 build-in 기능으로 서비스를 논리적으로 보강한다.- Dynamic service discovery
- Load balancing
- TLS termination
- HTTP/2 and gRPC proxies
- Circuit breakers
- Health checks
- Staged rollouts with %-based traffic split
- Fault injection
- Rich metrics
Envoy 프록시에서 사용할 수 있는 Istio 기능 및 작업은 다음과 같습니다.
- 트래픽 제어 기능: HTTP, gRPC, WebSocket, TCP 트래픽 에 대해서 다양한 라우팅 규칙을 통해 세분화된 트래픽 제어 시행
- 네트워크 복원력 기능: Setup retries, Fail-over, Circuit breakers, Fault injection
- 보안 및 인증 기능: 보안 정책, 접근 제어, 속도 제한을 시행
-
Istiod
Istiod provides service discovery, configuration and certificate management.Istiod
는 트래픽 동작을 제어하는 high level 라우팅 규칙을 Envoy 전용 구성으로 변환하여 런타임에 사이드카에 전파한다.Pilot
플랫폼별 서비스 검색 메커니즘을 추상화하여 Envoy API를 준수하는 모든 사이드카가 사용할 수 있는 표준형식으로 합성한다.
Istiod 보안은 build-in identity 및 자격 증명 관리를 통해 강력한 서비스 간 및 최종 사용자 인증을 지원합니다. Istio를 사용하여 서비스 메시에서 암호화되지 않은 트래픽을 업그레이드할 수 있습니다. 운영자는 Istio를 사용하여 상대적으로 불안정한 계층 3 또는 계층 4 네트워크 식별자 대신 서비스 ID를 기반으로 정책을 시행할 수 있습니다. 또한 Istio의 인가 기능을 사용하여 서비스에 액세스할 수 있는 사용자를 제어할 수 있습니다. Istiod는 인증 기관(CA) 역할을 할 수 있으며 데이터 플레인에서 안전한 mTLS 통신을 허용하는 인증서를 생성합니다.
2. Install Istio
Istio를 설치하는 방법에는 여러가지 방법이 있고 istioctl과 helm을 통한 설치방법을 소개하지만 여기서는 Helm을 이용하기로 한다. Helm의 values파일을 변경하여 필요한 값을 Customize하여 사용하기 위해서다.
2.1. Install with istioctl
Install Download
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.19.3
cp bin/istioctl /usr/local/bin
Install
istioctl install --set profile=demo -y
istioctl uninstall --set profile=demo -y
Injection Configuration
kubectl label namespace default istio-injection=enabled
Deploy the sample application
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
2.2. Install with helm
base-values.yaml
istiod-values.yaml
gateway-values.yaml
gateway-values.yaml
ingress-gateway를 위해
- Service(NLB)의 설정파일 실제 Listener로 설정될 포트는 서비스 포트이며 타겟 포트로 설정될 포트는 Gateway 서버포트와 일치해야 한다.
- 헬스체크에 대해서는 고민이 필요하다. 15021 포트로 헬스체크를 하면 istio-ingressgateway 파드 자체에 대한 헬스체크는 가능하나 backend 서비스에 자체에 대한 헬스체크는 불가능하다. 만약 traffic-port로 변경할 경우 healthcheck-path 값을 통해 backend 중 하나에는 트래픽을 보낼 수 있지만 여러 서비스로는 보낼 수 없다. 그래서 traffic-port를 tcp로 변경하고 traffic-port로 설정하면 각 서비스에 대한 헬스체크가 가능하다(path는 제외하였지만).
service:
# Type of service. Set to "None" to disable the service entirely
type: LoadBalancer
ports:
# - name: status-port
# port: 15021
# protocol: TCP
# targetPort: 15021
# - name: https
# port: 443
# protocol: TCP
# targetPort: 10012
# 실제 트래픽 전달을 위해 사용 하는 포트 (awssdk)
- name: https
port: 443
protocol: TCP
targetPort: 80
# 실제 트래픽 전달을 위해 사용 하는 포트 (bookinfo)
- name: http
port: 8080
protocol: TCP
targetPort: 8080
annotations:
service.beta.kubernetes.io/aws-load-balancer-name: k8s-istiosys-ingressgateway
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-subnets: subnet-02e6d788fad8afdcf, subnet-020255d69e8c814da #az1-extelb, az3-extelb
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-attributes: load_balancing.cross_zone.enabled=true
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:ap-northeast-2:558846430793:certificate/250015a4-4753-4a97-b536-88a6e6aaaf73
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
# SET 1
service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: http
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "15021" # traffic-port "15021"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: /healthz/ready
# SET 2
service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: tcp
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: traffic-port # traffic-port "15021"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "2"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "3"
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "20"
service.beta.kubernetes.io/aws-load-balancer-security-groups: sg-0f94ae1a6d9ba9d69
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: auto-delete=no
loadBalancerIP: ""
loadBalancerSourceRanges: []
externalTrafficPolicy: ""
externalIPs: []
ipFamilyPolicy: ""
ipFamilies: []
설정한 파일을 가지고 총 3개의 Helm 차트를 설치한다.
- istio-base
- CRD, WebhookConfiguration 등이 설치된다.
- istiod
- istio-ingressgateway
helm repo add istio https://istio-release.storage.googleapis.com/charts
helm repo update
kubectl create namespace istio-system
helm upgrade -i istio-base istio/base -n istio-system -f /Users/bys/workspace/kubernetes/istio/bys-dev-eks-main/helm/base-values.yaml
helm upgrade -i istiod istio/istiod -n istio-system -f /Users/bys/workspace/kubernetes/istio/bys-dev-eks-main/helm/istiod-values.yaml
helm upgrade -i istio-ingressgateway istio/gateway -n istio-system -f /Users/bys/workspace/kubernetes/istio/bys-dev-eks-main/helm/gateway-values.yaml
2.2. Istio object
- Gateway
Gateway는 송/수신 HTTP/TCP 연결을 받는 서비스 메시의 edge에서 동작하는 로드밸런서를 설명한다. 즉, 노출해야하는 port, protocol, 로드밸런서에 대한 SNI 구성을 설정한다. 아래의 Gateway 명세는 로드밸런서의 L4-L6 속성을 설명한다.
(Gateway의 포트 설정은 istio-ingressgateway로 배포된 proxy 서버의 타겟포트와 일치해야하는데, 그 타겟포트로 도 했을 때의 Gateway 맵핑으로 이해하면 이후 라우팅 동작은 Gateway와 연결된 VirtualService에서 정의한다고 이해하면 된다)
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway
namespace: some-config-namespace
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- uk.bookinfo.com
- eu.bookinfo.com
tls:
httpsRedirect: true # sends 301 redirect for http requests
- port:
number: 443
name: https-443
protocol: HTTPS
hosts:
- uk.bookinfo.com
- eu.bookinfo.com
tls:
mode: SIMPLE # enables HTTPS on this port
serverCertificate: /etc/certs/servercert.pem
privateKey: /etc/certs/privatekey.pem
- port:
number: 9443
name: https-9443
protocol: HTTPS
hosts:
- "bookinfo-namespace/*.bookinfo.com"
tls:
mode: SIMPLE # enables HTTPS on this port
credentialName: bookinfo-secret # fetches certs from Kubernetes secret
- port:
number: 9080
name: http-wildcard
protocol: HTTP
hosts:
- "*"
- port:
number: 2379 # to expose internal service via external port 2379
name: mongo
protocol: MONGO
hosts:
- "*"
- VirtualService
트래픽 라우팅에 영향을 미치는 설정이다. VirtualService는 host를 통해 목적지 주소를 지정하며 트래픽 라우팅 집합을 정의한다. route.destination.subset은 DestinationRule에 선언된 서비스 subset의 이름을 참조하여 식별되어야 합니다.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
rewrite:
uri: "/newcatalog"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
- name: "reviews-v1-route"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-destination
spec:
host: reviews.prod.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
이 외에도 기타 여러 설정 등을 통해 추가적인 Traffic 제어가 가능하다.
2.3. Kiali dashbaord
Istio 메시의 시각화를 위해 사용할 수 있다. 추후 Sample을 배포하고 흐름을 볼 수 있도록 미리 설치를 진행한다.
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/addons/kiali.yaml
istioctl dashboard kiali
2.4 Deploy Sample Application
kubectl label namespace default istio-injection=enabled
## Deploy sample Deployments, Services
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
## Deploy sample Gateway, VirtualService
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
정상적으로 배포가 되었는지 확인하기 위한 작업
export INGRESS_NAME=istio-ingressgateway
export INGRESS_NS=istio-system
kubectl get svc "$INGRESS_NAME" -n "$INGRESS_NS"
export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
curl http://$GATEWAY_URL/productpage
# watch -n 1 curl -o /dev/null -s -w %{http_code} $GATEWAY_URL/productpage
2.5 Deploy Application(개인용)
기존의 존재하던 Application에 Gateway, VirtualService 추가 구성.
awssdk-gateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: awssdk-gateway
namespace: aws
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
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "istio-awssdk.bys.digital"
awssdk-virtual-service
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: awssdk-virtual-service
namespace: aws
spec:
hosts:
- "*"
gateways:
- awssdk-gateway
http:
- match:
- uri:
prefix: /storage
route:
- destination:
host: awssdk-storage-dev-svc.aws.svc.cluster.local
port:
number: 10011
- match:
- uri:
prefix: /iam
route:
- destination:
host: awssdk-iam-dev-svc.aws.svc.cluster.local
port:
number: 10012
curl -v https://istio-awssdk.bys.digital/storage/v2/s3/buckets
curl -v https://istio-awssdk.bys.digital/iam/v2/sts/id
10. Troubleshooting
1. Kiali 구성 시, 기존 Prometheus 연결
Kiali dashboard를 사용하기 위해서는 prometheus 구성이 필수이지만 기존 prometheus가 설치된 경우 istio-system에 존재하지 않기 때문에 주소를 등록해주어야 한다.
kiali ConfigMap의 external_services에 custom 설치된 prometheus URL을 추가하여 설정한다.
# kubectl edit cm kiali -n istio-system
......
external_services:
custom_dashboards:
enabled: true
istio:
root_namespace: istio-system
tracing:
enabled: false
prometheus:
url: http://prometheus-server.prometheus.svc.cluster.local/
2. Envoy Access Logging
Gateway, VirtualService 등을 구성하고 503 오류가 발생하여 istio-ingressgateway에서 발생한 오류인지 혹은 각 서비스 Envoy 프록시에서 발생한 오류인지를 확인하려고 kubectl logs 커맨드를 사용하였으나 Access 로그가 보이지 않았다.
Envoy access log를 활성화 하기 위해서는 아래의 Telemetry를 배포한다.
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
accessLogging:
- providers:
- name: envoy
- References
[1] Istio Architecture
[2] Kiali troubleshooting
istio
servicemesh
]