티스토리 뷰

□ Service Mesh 란?

 

서비스 메시는 기존의 모놀리식 워크로드를 현대화하고 서비스 간의 통신을 제어하고 관리할 수 있도록 하는 데 특화된 마이크로서비스를 위한 인프라 계층입니다. 기존의 서비스 아키텍처의 호출이 직접 호출 방식이었다면, 서비스 메시에서의 호출은 자체 인프라 계층의 Proxy를 통해 이뤄지게 됩니다. 서비스 메시를 구성하는 개별 proxy는 서비스 내부가 아니라 각 서비스와 함께 실행되므로 'sidecar'라고도 합니다. 각 서비스에서 분리된 이러한 sidecar proxy들이 모여서 Mesh Network를 형성합니다.

 

□ Service Mesh 왜 필요한가?

 

컨테이너 오케스트레이터 지금 많이 쓰고 있는 Kubernetes가 이미 존재합니다. 하지만 또 다른 인프라스트럭처 계층이 필요한 이유는 일반적으로 마이크로서비스든가 컨테이너 메인 스트림을 통해 컨테이너 오케스트레이터는 클러스터에 필요한 많은 것들을 제공합니다. 주로 인프라 수준의 스케줄링, 헬스 체크에 중점을 두지만 충족시키지 못하는 요구 사항은 마이크로서비스가 구현하도록 남겨둡니다. 서비스메시는 컨테이너 오케스트레이터 위에 별도의 계층으로 배포해 서비스 간 통신을 안전하고 빠르며 안정적으로 만드는 전용 인프라 계층입니다. 

일반적으로 컨테이너 오케스트레이터에 에지 프록시로 사용되는 API 게이트웨이는 서비스메시와 유사한 요구를 해결합니다. API 게이트웨이는 컨테이너 인프라의 안정성, 가용성, 확장성을 위해 컨테이너 오케스트레이터를 사용하면서 L4에서 L7관리로 서비스를 제공합니다. API 게이트웨이는 기존 시스템에서부터 클라우드 호스팅되는 마이크로서비스 API 게이트웨이에 이르기까지 많은 것을 복잡하게 하는 방식으로 서비스 메시와 상호작용합니다. 그리하여 API 게이트웨이는 외부의 트래픽을 받아들이고 내부적으로 배포하게 설계되었고 서비스 트래픽 안팎으로 노스-사우스 트래픽을 전송하는데 중점을 둡니다. API 게이트웨이는 중앙 프록시를 통해 트래픽이 이동해야 하며 네트워크 홉을 추가하기 때문에 서비스 메시 내 트래픽 관리에 적합하지 않습니다. 따라서, 상호 보완적인 특성을 고려할 때 API 게이트웨이와 서비스 메시를 조합해 배치하는 경우가 많은데 API 게이트웨이의 주된 목적은 다른 API 관리 기능과 함께 분석, 비지니스 데이터, 부가 제공자 서비스 및 버전 관리 구현을 처리하는게 주된 목적입니다. 분명 서비스 메시와 API 게이트웨이 사이에는 겹치는 부분과 갭이 존재하여 상당히 고려되어야 하는 문제라고 생각합니다. (현재의 혹은 머지않아 미래에는 서비스 메시의 기능은 다양해질 것으로 예상)

istio up running 인용(번역이 쫌 이상하게 되어있네요,,)

 

□ Service Mesh로 얻는 이점

- 개발자들이 서비스 간의 안정적인 연동에 집중하는 대신 비즈니스 가치를 추구하는 일에 좀 더 집중할 수 있습니다.

- Jaeger를 통한 요청의 분산 추적은 서비스와 함께 가시적인 인프라 계층을 제공하므로 문제를 손쉽게 인식하고 진단할 수 있습니다.

- 서비스 메시는 장애가 발생한 서비스로부터 요청을 재 라우팅 할 수 있기 때문에 다운 타임 발생 시 어플리케이션 복구 능력이 향상됩니다.

- 성능 매트릭을 통해 런타임 환경에서 커뮤니케이션을 최적화하는 방법을 제안할 수 있습니다.

 

□ istio란

MicroService Architecture의 분산 네트워크 환경 즉, Kubernetes에서 각 app들의 네트워크 연결을 쉽게 설정할 수 있도록 지원하는 기술이며, 서비스에 대한 연결, 보안, 제어 및 모니터링을 할 수 있습니다. 또한, 동적 서비스 발견, 로드 밸런싱, TLS 처리, HTTP/2 및 gRPC 프록싱, 서킷 브레이커, 헬스 체크, 백분율 기반 트래픽 분할을 통한 단계적 출시, 결함 주입 및 풍부한 메트릭 등의 Envoy 기능을 활용합니다.

 

□ istio 구조

모든 컴포넌트가 istiod 라는 하나의 프로세스로 합쳐지고 Control plane에 Mixer가 없어지고 Pilot이 Mixer의 기능까지도 함께 수행되는것으로 바뀌었습니다. Control plane은 트래픽 동작을 제어하는 높은 수준의 라우팅 규칙을 Envoy Proxy전용 구성으로 변환하고 런타임에 사이드카로 전파합니다.

 

  • Control plane

Pilot, Citadel, Galley, istio-auth로 구성되어 런타임에 정책을 시행 할뿐만 아니라 트래픽을 라우팅하기 위해 프록시를 관리 및 구성합니다.

 

  • Pilot

Data plane에 대한 서비스 실행 상태와 위치를 추적하고 표시해 기반 플랫폼(ex, 쿠버네티스)과 동기화 상태를 유지합니다. 또한 envoy에 대한 설정 관리를 하는 역할을 합니다. 더불어 Traffic Management(Service Discovery [Envoy Endpoint를 알아내는 작업], Traffic Retry, Circuit Breaker, Timeout) 기능을 제공합니다.

 

  • Citadel

보안에 관련된 기능을 담당하는 모듈입니다. 인증 기능 관리(TLS Certification 등)

 

  • Galley

Istio configuration을 체크합니다. Kubernetes Yaml 파일을 istio가 이해할 수 있는 형태로 변환합니다.

 

  • Data plane

Data plane 구성요소는 istio의 Proxy를 담당하는 Envoy가 있습니다. Envoy를 통해 서비스에 대한 모든 인바운드 아웃바운드 트래픽을 중재합니다. 이를 통해서 모니터링 시스템(kiail, jaeger, prometheus)으로 전송해 전체 메시의 행동에 대한 정보를 제공할 수 있습니다.

□ istio를 왜 사용해야할까? (이건 참고만해주세요,,)

위의내용은 document 및 이미 구글링을 해보면 많이 나와있습니다. 저도 사실 istio를 적용해야한다고 생각하고 여러 자료들을 봤지만 사실, 이해도 잘 안되었고 좋다는건 알겠는데 이걸 쓰면서 어떤 이점이 있는지 머리속에 떠오르지 않던 찰나에 인프라를 운영하며 겪은 이슈(CORS)로 인해 회사 플랫폼의 서비스들의 구성을 상세히 파악하고, istio를 적용하면 정말 편할것 같다는 생각이 들었습니다.(이 포스팅이 올라가는 시점, 지금 계속 적용중인데 단점도 보이긴합니다,,) 음 간단히 설명하자면 현재 수많은 micro service들이 있지만, 그중에서도 static하게 개발된 front(react) 서비스들은 A pod를 바라보고 있으며 spring mvc 패턴으로 개발한 서비스들은 A pod를 바라보고 있지 않고, 특별한 서비스들은 자체적으로 dockerize를 할때 자체적으로 proxy service 를 같이 묶어서 올려 외부에서 요청이 들어오면 A pod를 바라보는게 아니라 자체적인 proxy service를 통하게 됩니다. 또한,, 클라이언트가 front에 요청을 하게되면 B pod를 거쳐서 backend pod에 도달하게 되는 등 딱봐도 트래픽제어 및 장애대응이 쉽지 않는 인프라 구성이라고 느꼈습니다.(개인적인 생각) 그리고 최근에 겪은 대망의 CORS 에러를 겪었습니다.(아직 해결중,,) 인프라쪽에서 해당 포스팅 이슈로인해(do-hansung.tistory.com/65) TLS를 적용하고나서부터 CORS 에러가 간혈적으로 일어났습니다. 

 

istio를 적용하면 지금 적용되어있는 gateway 및 proxy를 대체할 수 있다고 생각했고 또한 그로인해 장애대응 및 트래픽제어가 정말 효율적으로 관리할수 있다고 생각했습니다.        

 

□ istio 1.8.2

 

1.8.2 version으로 설치하기 위해 아래처럼 작성합니다.

curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.8.2 TARGET_ARCH=x86_64 sh -

□ istioctl

cd istio-1.8.2

export PATH=$PWD/bin:$PATH

istioctl

□ istio install

[admin@bastion ~/istio/istio-1.8.2]$ istioctl install --set profile=demo -y
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/v1.8/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete

아래처럼 error가 발생하면 리소스 부족

[admin@bastion ~/istio/istio-1.8.2]$ istioctl install --set profile=demo -y
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/v1.8/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
✔ Istio core installed
✔ Istiod installed
✘ Egress gateways encountered an error: failed to wait for resource: resources not ready after 5m0s: rpc error: code = Unavailable desc = transport is closing

✘ Ingress gateways encountered an error: failed to wait for resource: resources not ready after 5m0s: rpc error: code = Unavailable desc = transport is closing

- Pruning removed resources                                                                                                          2021-03-29T06:20:17.280308Z	warn	installer	retrieving resources to prune type apps/v1, Kind=DaemonSet: rpc error: code = Unavailable desc = transport is closing not found
2021-03-29T06:20:27.570523Z	warn	installer	retrieving resources to prune type rbac.authorization.k8s.io/v1, Kind=RoleBinding: rpc error: code = Unavailable desc = transport is closing not found
2021-03-29T06:20:37.836681Z	warn	installer	retrieving resources to prune type admissionregistration.k8s.io/v1beta1, Kind=MutatingWebhookConfiguration: rpc error: code = Unavailable desc = transport is closing not found
Error: failed to install manifests: errors occurred during operation

 

□ Envoy 사이드카 Injection을 위한 namespace label 설정

 

어플리케이션을 배포할 때 istio가 Envoy 사이드카 Proxy를 자동으로 삽입하도록 할 수 있도록 namespace label을 추가해줍니다. namespace에 istio-injection = enabled 레이블을 설정하고 injection webhook이 활성화되면 해당 namespace에서 생성된 모든 pod에는 자동으로 사이드카가 추가됩니다.

[admin@bastion ~/istio/istio-1.8.2]$ kc label namespace istio istio-injection=enabled
namespace/istio labeled

[admin@hskim-bastion ~]$ kc get namespaces --show-labels
NAME                   STATUS   AGE     LABELS
default                Active   6d13h   istio-injection=enabled
istio                  Active   4d7h    istio-injection=enabled
kube-node-lease        Active   6d13h   <none>
kube-public            Active   6d13h   <none>
kube-storage           Active   6d9h    <none>
kube-system            Active   6d13h   <none>
kubernetes-dashboard   Active   6d7h    <none>
nginx-ingress          Active   6d9h    <none>

□ book info 프로젝트 다운로드

[admin@bastion ~/istio/istio-1.8.2/samples/bookinfo/platform/kube]$ kc apply -f bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created

□ 정상적으로 배포가 잘 되면 아래처럼 pod가 Running 상태로나오며 2/2 사이드카가 정상적으로 같이 배포된걸 확인할 수 있습니다.

[admin@bastion ~/istio/istio-1.8.2/samples/bookinfo/platform/kube]$ kubectl get pod
NAME                                               READY   STATUS    RESTARTS   AGE
details-v1-558b8b4b76-jsr2v                        2/2     Running   0          2m12s
nfs-client-nfs-client-provisioner-9ccfcc95-fsddn   1/1     Running   36         24d
productpage-v1-6987489c74-9v7dm                    2/2     Running   0          2m11s
ratings-v1-7dc98c7588-n4gqk                        2/2     Running   0          2m11s
reviews-v1-7f99cc4496-94lz5                        2/2     Running   0          2m11s
reviews-v2-7d79d5bd5d-6lkrw                        2/2     Running   0          2m11s
reviews-v3-7dbcdcbc56-288v5                        2/2     Running   0          2m11s

□ istio gateway

istio gateway를 생성해줘야 외부로 접근이 가능해집니다. gateway는 istio가 배포한 커스텀된 오브젝트이므로 마치 kubernetes에서 제공되는 ingress처럼 동작하며 gateway는 외부로부터 트래픽을 받으며 가장 앞단에 존재합니다. mesh에 대한 inbound 및 outbound trafic을 관리하여 mesh에 진입하거나 나가는 트래픽을 지정할수 있습니다. 

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "book.demo.test.com"

아래처럼 gateway를 배포해주면 해당 url로 이제 bookinfo 샘플페이지가 접근이 가능해집니다.

http://book.demo.test.com/productpage

[admin@bastion ~/istio/istio-1.8.2/samples/bookinfo/platform/kube]$ kc apply -f bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created

□ istio 아키텍처의 트래픽 흐름

실제 NaverCloud에서 K8S Cluster 앞에 LoadBalancer를 쓰고있습니다. 클라이언트가 bar.test.com이라는 도메인에 접근했을때 LoadBalancer의 Public IP 및 Private IP의 응답을 받게됩니다. LoadBalancer에는 istio Ingress Gateway Service의 포트를 맵핑해주게됩니다. Virtual Service에 라우팅 룰을 적절하게 지정하게됩니다. 예를들어 host가 hskim.test.com으로 요청이 들어오게 된다면 특정 K8S svc를 목적지로 지정합니다. 앞서 설명한 목적지로 지정하는 부분은 DestinationRule에 정의하게되며 DestinationRule에서 정의한 서비스로 라우팅을 하게 됩니다.   

kiali

위의 아키텍처의 흐름을 잘 파악하고 bookinfo페이지가 해당 도메인으로 접근했을때 잘 들어가졌다면 kiali dashboard도 아래와 같이 손쉽게 설정할수있습니다.

[admin@hskim-bastion kiali]$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/kiali.yaml
customresourcedefinition.apiextensions.k8s.io/monitoringdashboards.monitoring.kiali.io unchanged
serviceaccount/kiali created
configmap/kiali created
clusterrole.rbac.authorization.k8s.io/kiali-viewer created
clusterrole.rbac.authorization.k8s.io/kiali created
clusterrolebinding.rbac.authorization.k8s.io/kiali configured
service/kiali created
deployment.apps/kiali created
monitoringdashboard.monitoring.kiali.io/envoy created
monitoringdashboard.monitoring.kiali.io/go created
monitoringdashboard.monitoring.kiali.io/kiali created
monitoringdashboard.monitoring.kiali.io/micrometer-1.0.6-jvm-pool created
monitoringdashboard.monitoring.kiali.io/micrometer-1.0.6-jvm created
monitoringdashboard.monitoring.kiali.io/micrometer-1.1-jvm created
monitoringdashboard.monitoring.kiali.io/microprofile-1.1 created
monitoringdashboard.monitoring.kiali.io/microprofile-x.y created
monitoringdashboard.monitoring.kiali.io/nodejs created
monitoringdashboard.monitoring.kiali.io/quarkus created
monitoringdashboard.monitoring.kiali.io/springboot-jvm-pool created
monitoringdashboard.monitoring.kiali.io/springboot-jvm created
monitoringdashboard.monitoring.kiali.io/springboot-tomcat created
monitoringdashboard.monitoring.kiali.io/thorntail created
monitoringdashboard.monitoring.kiali.io/tomcat created
monitoringdashboard.monitoring.kiali.io/vertx-client created
monitoringdashboard.monitoring.kiali.io/vertx-eventbus created
monitoringdashboard.monitoring.kiali.io/vertx-jvm created
monitoringdashboard.monitoring.kiali.io/vertx-pool created
monitoringdashboard.monitoring.kiali.io/vertx-server created

kiali dashboard를 도메인기반으로 접근하려면 아래처럼 gateway를 만들어줍니다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: kiali-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http-kiali
      protocol: HTTP
    hosts:
    - "kiali.hskim.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: kiali-vs
  namespace: istio-system
spec:
  hosts:
  - "kiali.hskim.test.com"
  gateways:
  - kiali-gateway
  http:
  - route:
    - destination:
        host: kiali
        port:
          number: 20001
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: kiali
  namespace: istio-system
spec:
  host: kiali
  trafficPolicy:
    tls:
      mode: DISABLE

위의 상태에서 kiali dashboard에 들어가면 graph에 아무것도 보이지 않습니다. 왜냐하면 istio metrics를 수집하고 있지 않기 때문입니다. 따라서 prometheus로 istio metrics를 수집해줍니다.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml

아래처럼 정상적으로 metrics를 수집하므로 kiali dashboard에서 확인할 수 있습니다.

 

jaeger

jaeger도 마찬가지로 kiali처럼 service를 install 시키고 gateway를 붙여 hosts 기반으로 접근할 수 있도록 구성할 수 있습니다.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/jaeger.yaml

정상적으로 install 된다면 아래처럶 서비스가 생기는걸 볼 수 있습니다.

service/tracing                ClusterIP      172.19.69.1      <none>        80/TCP                                                                       10m
service/zipkin                 ClusterIP      172.19.88.187    <none>        9411/TCP                                                                     10m

tracing svc 포트를 변경해줍니다.

kc edit -n istio-system service/tracing
spec:
  clusterIP: 172.19.69.1
  ports:
  - name: http-query
    port: 16686
    protocol: TCP
    targetPort: 16686
  selector:
    app: jaeger
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

gateway는 아래처럼 배포해줍니다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: tracing-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: tracing-zipkin
      protocol: HTTP
    hosts:
    - "jaeger.demo.test.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: tracing-vs
  namespace: istio-system
spec:
  hosts:
  - "jaeger.demo.test.com"
  gateways:
  - tracing-gateway
  http:
  - route:
    - destination:
        host: tracing
        port:
          number: 16686
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: tracing
  namespace: istio-system
spec:
  host: tracing
  trafficPolicy:
    tls:
      mode: DISABLE
댓글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30