Istio

jsbak·2023년 6월 16일
0

참고

목록 보기
9/13

서비스 메시와 Istio

  • 서비스 메시란?
    • 클러스터와 함께 배포하는 추가 소프트웨어 계층
    • k8s 에서 모든 포드의 아래에 있는 소프트웨어 레이어로 생각 가능
    • 개념적으로 보자면 설정을 통해 클러스터로 이동하는 모든 네트워크 트래픽이 서비스 메시를 통해 라우팅 되도록 설정
  • istio

    • 응용프로그램 자원을 침범하지 않는다. (컨테이너에 대한 변경을 최소한으로 수행.)
    • 데이터 플레인
      • pod 안에서 실행되는 모든 프록시를 의미
    • 컨트롤 플레인
      • istio 시스템에서 실행되는 모든 포드 (istiod), 실제로 이스티오 기능을 구현하는 포드
    • Kiali 포드와 포드의 연결 방식을 시각화 해주는 UI(User Interface)
    • 서비스 메시이자 k8s 클럭스터에 적용할 수 있는 레이어
    • 포드 사이의 트래픽을 모니터링 및 관리
    • 잘 실행되지 않는 샘플 시스템이 왜 잘 실행되지 않는지 이스티오를 이용해 문제를 진단하고, 무엇이 이뤄지는지 파악하는 방법, 해법등을 알아본다.
    • 이스티오는 포드와 서비스, 일반 쿠버네티스의 집합체이기 때문에 쿠버네티스 클러스터가 있다면 이스티오 실행 가능
  • istio 와 probe

이스티오를 위한 쿠버네티스 설치

# 도커
$ sudo yum -y install git wget curl
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
$ systemctl enable --now docker

# 미니쿠버 v1.25.0 설치
	# 미니쿠버 를 위한 conntarck 설치
$ yum install -y conntrack
$ wget https://storage.googleapis.com/minikube/releases/v1.25.0/minikube-linux-amd64
$ sudo install minikube-linux-amd64 /usr/local/bin/minikube
$ minikube version

# 미니쿠버 시작 
$ minikube start --driver=none
$ sudo mv /root/.kube /root/.minikube $HOME
$ sudo chown -R $USER $HOME/.kube $HOME/.minikube
$ minikube status

# kubectl 설치 v1.25.0
$ curl -LO https://dl.k8s.io/release/v1.25.0/bin/linux/amd64/kubectl
$ sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
$ source <(kubectl completion bash)
	# 시스템이 껏다 켜지더라도 자동완경 가능하게 설정
$ echo "source <(kubectl completion bash)" >> ~/.bashrc
$ exit

$ kubectl version --client
$ kubectl get all

미니쿠버와 이스티오 데모

이스티모 데모

  • 워크 스페이스 생성
$ mkdir warmup-exercise && cd $_
  • 1-istio-init.yaml
$ vi 1-istio-init.yaml
	내용 복사 -> https://github.com/DickChesterwood/istio-fleetman/blob/master/_course_files/x86_amd64/warmup-exercise/1-istio-init.yaml
$ kubectl apply -f 1-istio-init.yaml

  • 2-istio-minikube.yaml
$ vi 2-istio-minikube.yaml
	내용 복사 => https://github.com/DickChesterwood/istio-fleetman/blob/master/_course_files/x86_amd64/warmup-exercise/2-istio-minikube.yaml
$ kubectl apply -f 2-istio-minikube.yaml
$ kubectl get po -n istio-system

  • 3-kiali-secret.yaml
$ vi 3-kiali-secret.yaml
	내용 복사 =>	https://github.com/DickChesterwood/istio-fleetman/blob/master/_course_files/x86_amd64/warmup-exercise/3-kiali-secret.yaml
$ kubectl apply -f 3-kiali-secret.yaml
  • 4-application-full-stack.yaml
$ kubectl describe ns default
$ kubectl get ns default -o yaml

$ vi 4-application-full-stack.yaml
$ kubectl apply -f 4-application-full-stack.yaml
	내용 복사 => https://github.com/DickChesterwood/istio-fleetman/tree/master/_course_files/x86_amd64/warmup-exercise
$ kubectl get po
$ kubectl get svc
 --> nodeport로 접속시 사이트에서 차량목록에 추가되어야하는데 문제가 있나 추가되지 않음.


용어

  • IBM - Istio란?

  • 이스티오에 플래그를 설정하여 특정한 네임스페이스에 대해 모든 포드에 프록시 컨테이너를 자동으로 주입

  • 사이드카 : 포드안에서 추가적인 도움을 주는 헬퍼 컨테이너

  • 인젝터 : 컨트롤 플레인 컴포넌트 중 하나로 기본적으로 포드를 스케줄링 할 때 항상 모니터링하고, 인젝터가 이것을 탐지하고

  • kiali : 어떤 마이크로서비스가 이스티오 서비스 메시의 일부인지 알려주고 어떻게 연결/작동하는지 알려준다.

  • 마이크로 서비스의 컨테이너는 다른 포드를 호출하는 것이 아니라 클러스터 외부의 URL을 호출하고 이는 프록시(; 서비스 메시) 로 인도되며 우리가 우리가 yaml 수정을 프록시에 제공 및 통제

  • Kubernetes는 컨테이너 오케스트레이션 툴입니다. Kubernetes의 핵심 단위 중 하나가 노드입니다. 노드는 파일 시스템 또는 기타 컴포넌트와 함께 하나 이상의 컨테이너로 구성되어 있습니다. 마이크로서비스 아키텍처는 12개의 노드를 보유할 수 있는데, 노드마다 각기 다른 마이크로 서비스를 대표합니다. Kubernetes는 노드의 가용성과 리소스 이용을 관리하며, 팟(Pod) 오토스케일러를 통해 수요 증가에 따라 팟(Pod)을 추가합니다. Istio는 추가 컨테이너를 팟(Pod)에 삽입하는 방식으로 보안, 관리, 모니터링 기능을 추가합니다.

  • 이스티오는 서비스 메시의 일종으로 프록시를 이용하여 서비스 메시를 구현하고 서비스 특정한 컨테이너가 우리 클러스터에 있는 또 다른 컨테이너를 호출 이 프록시 컴포넌트를 통해 라우팅된다는 점, 쿠버네티스에서 사이드카 컨테이너로서 구현됩니다.

    • 이스티오는 코드와 쿠버네티스 포드가 변경되지 않는 비침습적인 서비스 메시를 추구
    • 허나 분산 추적을 작동하려면 코드를 수정해야한다.
      • 예거(Jaeger)에서 분산 추척을 수행하기 위해서 x-request-id 라는 헤더를 추가해야한다.
  • envoy: 클러스터 기반 응용 프로그램을 위한 프록시, 프록시를 공급하고 이 프록시가 쿠버네티스 플랫폼에서 사이드카 컨테이너가 된다.

  • 프록시 세트이스티오의 데이터 플레인이라고 일컽는다.

  • 이스티오는 envoy 구성을 간단하게 해준다.

kiali

  • kiali 에서 Graph - Service graph 는 지정한 기간중에 서비스들 간의 이동한 트래픽을 기초로 서비스들이 어떻게 연결되어 있는지 볼 수 있다.
    • 또한 그래프의 그림은 정적이 아니라 동적으로 연결된 상태를 반영한다.
    • 그래프 에서 각 요소들을 클릭하면 상세히 볼수 있다.
  • 서비스 상세보기에서 가중치 라우팅이나 매칭 라우팅, 트래픽 중지 등을 설정해볼 수 있다.
    • 설정을 하면 뭔가 변화하고 그 내역이 새로 생긴다.
    • kubectl edit 또는 쿠버네티스의 yaml 을 변경하지 않고도 UI를 통해 우리의 구성을 변경가능
    • 사용의 2가지 - 비상상황이 있을 경우, 직접 수정해야할 때, minikube로 임시로 실행해 볼때





  • kiali - Services 세부정보 - Actions - Create Matching Routing 을 통해서 설정할 수 도 있다.

분산 추적이란?

  • 긴 체인에서 호출되는 서로 협력하는 다수의 컴포넌트들의 특정한 요청을 다루는 것
  • 이스티오는 분산 추적 프레임워크를 기반 인프라 안에 내장하고 있다.
  • 요청에 대한 세부 정보들을 Trace(확인)해볼수 있다.

분산 추적과 원격 측정

  • kiali 에서 서비스의 세부정보로 간 다음 Inbound Metrics 정보를 확인 가능하다. 그래프를 통해서 요청량이나 요청 지속시간, 요청 사이즈등을 확인 가능, 또한 Outbound Metrics에 대한 데이터도 얻을 수 있다.
  • 그라파나는 오픈소스 그래프 작성 프레임워크로 차트, 그래프와 같은 것을 대시보드 형태로 제시하고 많은 응용 프로그램과 통합 가능하다.
    • Ex_) k8s 의 클러스터를 모니터링하고 싶을때, 노드의 상태를 모니터링 하고 싶을 때 이용하며, 프로메테우스는 이 지표를 스크랩핑 하는 역할을 수행 (물리적 노드의 CPU 사용량 등을 프로메테우스가 종합하고 그라파나와 연결하여 차트를 얻게 된다.)
    • 이스티오와 프로메테우스는 서로 다른 모니터링 툴, 물리적인 하드웨어(prometheus)/포드간 네트워크 트래픽의 세부정보(istio) 들을 grafana에서 독립적인 차트를 생성하여 대시보드로 제공

원격 측정의 요구사항

  • 원격 측정을 위한 요구사항
    • 모니터링 하려는 모든 포드에 프록시(엔보이 사이드카) 가 있어야한다.
    • 컨트롤 플레인을 설정하고 실행시켜야한다.
    • 원격 측정을 위해서는 어떤 특별한 istio 구성도 필요하지 않다.

카나리아 배포

  • kiali는 k8s 에서 labels(key: value) 을 통해 식별하고 이를 그림으로 표현하게 된다.
    • labels에 version 을 넣게 되면 버전 별로 정보를 확인해 볼 수도 있다.
    • 예를 들어 Actions - Create Weighted Routing 에서 10% : 90% 으로 설정했다면 거의 10번중 1번은 카나리아가 나오게된다. (정확하게 10번 중 1번이 카나리아라곤 보장할 수는 없다.)


virtual service & destination rule

  • virtualservice 는 서비스 메시에 사용자 지정 라우팅 규칙을 구성할 수 있도록 도와준다.
  • destination rule 는 특정한 서비스를 위한 로드 밸랜서의 구성을 의미한다.
  • 조회하기
$ kubectl get virtualservice
$ kubectl get vs

$ kubectl get destinationrule
$ kubectl get dr
  • 정의된 YAML 파일 확인하기

    • -o yaml 옵션으로 출력하기

      
      $ kubectl get <resource> -o yaml
      	# 예시) kubectl get vs -o yaml
    • kiali 에서 조회하기 - View YAML 클릭

  • 클러스터를 재시작 할때 버추얼 서비스를 다시 생성하고 싶다면 해당 YAML의 내용을 복사하여 소스 컨트롤을 수행할수 있으며 kubectl apply -f 로 적용하면 된다.

    • 일부 내용을 정리해야한다. selfLink, uuid, resourceVersion, generation, creationTimestamp, labels, managedFields 등 또한 ~ 값을 제공하지 않겠다 라는 부분도 제거
    
    kind: VirtualService
    apiVersion: networking.istio.io/v1alpha3
    metadata:
      #name: fleetman-staff-service 
      # 그냥 버추얼 서비스의 이름, 정하고 싶은대로 정하고 kubectl get vs 하면 나오는 그것
      name: a-set-of-routing-rules-we-can-call-this-anything  # "just" a name for this virtualservice
      namespace: default
    spec:
      hosts:
        #- fleetman-staff-service.default.svc.cluster.local
        # "FQDN - 전체 주소 도메인 네임" 를 지정해야한다.
        # 쿠버네티스의 Service DNS 이름
        - fleetman-staff-service.default.svc.cluster.local  # The Service DNS (ie the regular K8S Service) name that we're applying routing rules to.
      http:
        - route:
            - destination:
                 # The Target DNS name, 클러스터 내부에서 요청으로 전달하고 싶은 대상 서비스의 DNS 이름
                host: fleetman-staff-service.default.svc.cluster.local
                subset: safe-group # DestinationRule 에 정의된 subset 의 이름
              weight: 90
            - destination:
                host: fleetman-staff-service.default.svc.cluster.local
                subset: risky-group # The name defined in the DestinationRule
              weight: 10
    ---
    kind: DestinationRule	# Defining which pods should be part of each subset
    apiVersion: networking.istio.io/v1alpha3
    metadata:
      #name: fleetman-staff-service
      name: grouping-rules-for-our-photograph-canary-release # This can be anything you like.
      namespace: default
    spec:
      # host - Service DNS 네임
      host: fleetman-staff-service.default.svc.cluster.local	
      subsets:
         # labels(셀렉터) 의 정의를 통해 라벨에 해당하는 pod를 찾아서 매칭 
        - labels:	# SELECTOR.
            version: safe	# find pods with label "safe"
          name: safe-group	# 해당 subset의 이름을 "safe-group" 이라고 정의
        - labels:
            version: risky
          name: risky-group
    
  • 이스티오는 프록시 구성 권한을 우리에게 주고 프록시 구성 권한에 사용자 지정 라우팅 규칙을 설정하면 (envoy)프록시에 버추얼 서비스들이 배포 되고 이를 통해서 (envoy) 프록시의 트래픽 관리 기능을 이용할 수 있게되며 이를 통해서 카라니아 배포도 할 수 있는 것

    • 쿠버네티스의 서비스는 개별 포드의 IP 주소를 부여하는 방법
    • 쿠버네티스 서비스와 버추얼 서비스는 연관성이 없다.
    • 버추얼 서비스는 pilot에 의해 관리되며 프록시를 역동적으로 재구성한다.
    • 아키텍처의 모든 마이크로서비스가 버추얼 서비스를 구성할 필요는 없다.
  • kiali 는 버추얼 서비스와 데스티네이션 룰을 검증하고 이를 보여준다.

로드 밸런싱

Consistent Hashing

  • trafficPolicy.loadBalancer.consistentHash.httpHeaderName 에서 헤더의 이름을 지정한다. 헤더 연쇄부분은 해당하는 애플리케이션을 직접 수정해줘야 한다. 그렇지 않으면 분산 추적이 정상적으로 동작하지 않으며 우리가 원하는 것 처럼 연쇄 되어있는 서비스로 연결되지 않는다.
  • httpHeaderName 이외에도 다른 설정(sourceIp) 검증 등을 이용하여 해싱 처리를 할 수도 있다.
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
  name: a-set-of-routing-rules-we-can-call-this-anything  # "just" a name for this virtualservice
  namespace: default
spec:
  hosts:
    - fleetman-staff-service.default.svc.cluster.local  # The Service DNS (ie the regular K8S Service) name that we're applying routing rules to.
  http:
    - route:
        - destination:
            host: fleetman-staff-service.default.svc.cluster.local # The Target DNS name
            subset: all-staff-service-pods  # The name defined in the DestinationRule
          # weight: 100 not needed if there's only one.
---
kind: DestinationRule       # Defining which pods should be part of each subset
apiVersion: networking.istio.io/v1alpha3
metadata:
  name: grouping-rules-for-our-photograph-canary-release # This can be anything you like.
  namespace: default
spec:
  host: fleetman-staff-service # Service
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: "x-myval"
  subsets:
    - labels:   # SELECTOR.
        app: staff-service # find pods with label "safe"
      name: all-staff-service-pods
  • 만약 요청사항으로 특정 사용자가 항상 같은 포드 인스턴스로 전달되도록 하는 것이 있다면, 이 일관된 해싱을 사용하면 되고 이것이 쉬운 작업이나이런 요청은 꽤 드물고, 높은 수준의 요구사항이다.
    • 꼭 성능 향상을 위해서 사용
      • 예를 들어 클라이언트가 요청을 보내고 이것이 포드로 들어간다고 하면 이 포드가 유저를 위해 계산량이 많은 일을 할 때 무언가를 생성하고 성능을 위해서 이 결과를 클라이언트 별로 캐싱하는 경우

인그레스 게이트 웨이


apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: ingress-gateway-configuration
spec:
  # The selector matches the ingress gateway pod labels.
  # 용어가 거시기 한데, 여기서 "selector" 는 k8s 의 labels 과 같은 역할
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  # 즉 위 내용은 Helm 으로 구성하게 되면 labels의 istio: ingress 라는 key-value로 만들어진다는 의미
  selector: 
    istio: ingressgateway  # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com" # Domain name of the external website
---
kind: VirtualService
apiVersion: networking.istio.io/v1alpha3
metadata:
  name: fleetman-webapp
  namespace: default
spec:
	# The Service DNS (ie the regular K8S Service) name that we're applying routing rules to.  	
    # 트래픽이 전송되는 대상 호스트입니다. 와일드카드 접두사가 있는 DNS 이름 또는 IP 주소일 수 있습니다.
  hosts:      # which incoming host are we applying the proxy rules to???
    - "*"
  gateways:	# 위에서 정의한 ingress gateway 이름
    - ingress-gateway-configuration
  http:
  	...
  • 인그레스 게이트웨이는 이스티오 시스템에서 들어온다.
    • 인그레스 게이트웨이를 사용하려면 K8S 의 pod 가 NodePort 등으로 외부에 직접 연결되어 있다면 외부와 직접 연결되지 못하게 ClusterIP 서비스 구성으로 변경

인그레스 게이트웨이가 필요한 시점

  • 커스텀 트래픽 규칙을 엣지에 있는 서비스에 적용할 때
    • 웹 앱을 클러스터 외부에서 직접 접근하는 것은 접근하려는 체인의 제일 선두에 있는 서비스에 접근하는 것과 마찬가지 게이트웨이가 없다면 트래픽 관리를 위해 프록시를 활용할 수 없습니다.

prefix 기반 라우팅

header 기반 라우팅

다크 배포

  • 스테이징 환경을 구축하지 않고
  • 실제 환경에 업그레이드 버전을 끼워넣어서 테스트 하는 방식
    • 이스티오의 설정을 통해 특수한 헤더값이 있는 사람만 접속할 수 있도록 설정하면 은밀하게 다른 실제 마이크로 서비스와 연동하여 테스트 해볼 수 있다.
      • 이로써 테스트 버전을 통해 부하 테스트도 진행할 수 있다.
    • 주의점 : 헤더 기반 라우팅으로 각각의 마이크로 서비스를 테스트할 경우 헤더 전파 를 생각하기 - 💢 분산 추적 ❗
      • 체인에 있는 모든 마이크로서비스에 헤더가 전파되야한다. - 이스티오의 제일 큰 단점

Mutual TLS; 상호 TLS

  • PeerAuthentication
  • 외부 데이터 센터나 클라우드를 이용하게 된다면 클러스터 내부의 노드들 끼리 HTTP 통신을 하는 경우 외부에서 공격자가 중간자 공격을 수행하면 물리적으로 이격되어 있을 확률이 높기 때문에 네트워크 트래픽 가로채기에 취약하다 따라서 최소한의 TLS 설정이라도 하는 것이 좋다.
  • istio 의 컨트롤 플레인에서는 citadel 을 통해서 tls를 지원하고 있다.
  • 현재는 기본으로 활성화 되어 있으며, 육안으로 확인하고 싶으면 Kiali 에서 Display - Security 를 체크하면된다.
    • container 와 proxy 같의 트래픽은 http 이나 proxy 가 service로 트래픽을 보낼때는 tls 변경하게 보내게 된다. (즉, pod - pod 간 트래픽은 tls)
    • 단, 사이드카 주입이 활성화된 네임스페이스의 pod만 적용이된다. (이스티오의 관리 하에 있어야한다.)
      • 이스티오의 관리를 받지 않아도 요청은 보낼수 있다. 물론 http 요청만 가능하다. (기본값이 https가 아니라도 처리를 하는 PERMISSIVE 모드 이기 때문이다.) 하지만, 물리적으로 이격된 클러스터의 노드끼리 소통할 경우 중간자 공격이 발생할 수 있게 된다. 따라서 STRICT 모드를 고려해볼수 있다.

간단한 strict 적용 예시

  • 네임스페이스 istio-system 의 모든 워크로드에 대해 mTLS 트래픽을 허용하는 정책
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: foo
spec:
  mtls:
    mode: STRICT

참고

이스티오 설치 관련

  • 이스티오를 설치하면 나머지 addons 관련 kiali, grafana, prometheus 를 쉽게 설치할 수 있다.
  • 이스티오를 yaml로 설치하려면
$ istioctl install -f YAML_FILE.yaml --set values.global.jwtPolicy=first-party-jwt

jwt - 서드파티 토큰 구성

  • 타사 서비스 계정 토큰 구성
  • Istio는 기본적으로 타사 토큰을 사용
  • istioctl을 사용하여 설치하는 경우 지원이 자동으로 감지됩니다. 이는 수동으로도 수행할 수 있으며 --set values.global.jwtPolicy=third-party-jwt 또는 --set values.global.jwtPolicy=first-party-jwt를 전달하여 구성할 수 있습니다.
	# 퍼스트 파티 예시
$ istioctl install -f YAML_FILE.yaml --set values.global.jwtPolicy=first-party-jwt

이스티오 삭제 관련

# "삭제가 실험적이라고 하여 이렇게 됨.", 차후 변경될 수도 있음.
$ istioctl x uninstall --purge

이스티오 프로필 커스텀

  • CPU 와 메모리 및 추적 주기와 요청 설정 등을 커스텀 해볼 수 있다.

YAML 메니페스트 생성

  • istio operator yaml을 이용해서 k8s yaml 생성하기
istioctl manifest generate -f YAML_FILE.yaml > NEW_FILE.yaml

addons 관련

  • addons 관련된 서비스를 외부와 연결하기 위해서 는 NodePort/LoadBalancer 을 직접 설정해야한다.

용어

  • Pilot => Istiod 의 옛이름
profile
끄적끄적 쓰는곳

0개의 댓글