Work/개발 노트

[Istio 스터디] 1주차 - Istio 소개, 첫걸음

★용호★ 2025. 4. 12. 13:02

서비스 메시 소개

  • 클라우드가 확산되면서 애플리케이션 설계에 있어서도 고려할 사항들이 변화하고 있음
    • 컨테이너화 된 애플리케이션들은 언제든 삭제되고 재생성될 수 있음
    • 네트워크는 신뢰할 수 없으므로 더 크고 더 분산된 시스템을 구축할 때는 네트워크에 대해 재시도, 타임아웃, 서킷 브레이커와 같은 네트워크 복원력이나 관찰가능성, 애플리케이션 계층은 보안 등을 신경써야함
  • 네트워킹, 보안, 메트릭 수집은 애플리케이션 구현에 있어서 필수이지만 차별화 요소는 아님
    • 중요한 자원인 개발자들이 네트워크 단의 설계와 구현에 많은 시간을 투자하는 것보다는 더 가치있는 본연의 업무를 수행할 수 있도록 해야함
  • 서비스 메시는 이런 공통 관심사를 애플리케이션 대신 프로세스 외부에서 투명한 방식으로 구현하기 위함
    • 네트워킹, 보안, 메트릭 수집과 같은 것들을 프로그래밍 언어와 프레임워크에 구애받지 않는 방식으로 구현하고 정책을 적용하는 것
  • Istio는 서비스 메시의 오픈소스 구현체
    • 애플리케이션 코드를 수정하지 않고도 보안, 정책 관리, 관찰 가능성과 같은 어려운 문제를 해결할 수 있고 신뢰성있고 안전한 클라우드 네이티브 시스템을 구축할 수 있도록 함
  • 애플리케이션 네트워킹을 위해 아래와 같은 구현들이 필요한데 각각의 애플리케이션들이 이런 것들을 모두 구현하기에는 반복적이고 어려움
    • 클라이언트 측 로드밸런싱 : 클라이언트에게 엔드포인트 목록을 제공하고 어떤 엔드포인트를 호출할지를 클라이언트가 결정
    • 서비스 디스커버리 : 특정 논리적 서비스의 주기적으로 갱신되는 정상 엔드포인트 목록을 찾는 매커니즘
    • 서킷 브레이커 : 오동작하는 것으로 보이는 서비스에 일정 시간 부하를 차단
    • 격벽 (Bulkheading) : 서비스 호출 시 클라이언트 리소스 사용량을 명시적 임계값으로 제한 (커넥션, 스레드, 세션 등)
    • 타임아웃 : 서비스 호출 시 요청, 소켓, 활성 liveness 등에 시간 제한을 적용
    • 재시도 : 실패한 요청을 재시도
    • 재시도 예산(Retry budgets) : 재시도에 제한을 적용. (예. 10초 동안 호출의 50%까지만 재시도 가능)
    • 데드라인 : 요청에 응답 유효 기간 지정. 데드라인을 벗어나면 요청 처리를 무시

https://kimdoky.github.io/devops/2025/04/10/study-istio-week1/

  • 서비스메시 vs API Gateway
    • API GW를 사용하는 경우 모든 통신이 API GW를 거쳐서 통신하기 때문에 서비스간 통신에서 네트워크 홉이 증가하고 MSA 구조에서 트래픽 량이 증가하게 되면 API GW가 받는 부하가 커지기 때문에 스케일링에 대한 고려가 필요함. 서비스 간 direct로 통신하는 것에 대한 통제가 불가능함
    • istio는 모든 서비스에 Proxy가 붙어 있기 때문에 중앙에서 트래픽을 관리하는 것이 불필요해짐
  • istio는 무조건 좋을까?
    • 프록시에 익숙하지 않은 경우 이 영역의 동작이 블랙박스가 되어 애플리케이션 동작을 디버깅하기 어렵게 만들 수 있음
      • Envoy가 디버깅하기 쉽도록 설계가 되었지만 Envoy를 사용해보지 않은 사람에게는 복잡하게 보일 수 있음
    • Istio를 적용하면 또하나의 인프라 레이어가 생기는 것으로 볼 수 있기 때문에 설정에 따라 테넌시 및 격리 모델로 인한 서비스 영향이 있을 수 있음
    • 복잡성이 올라가기 때문에 누가 어떻게 담당할지에 대한 R&R에 대한 문제가 발생할 수 있음. 조직 내 거버넌스 계획이 필요
    • 서비스 메시가 가져다주는 이점이 크지만 그에 따른 트레이드 오프가 발생함

Istio 소개

  • Istio는 서비스 메시(Service Mesh) 기술을 구현한 오픈소스 플랫폼
    • 마이크로서비스 아키텍처에서 서비스 간 통신과 관련된 복잡성을 줄여주는 도구
    • 애플리케이션 코드를 변경할 필요 없이 서비스 간 트래픽 흐름을 관리하고, 보안 정책을 적용하며, 원격 분석 데이터를 수집함
  • 클라우드 기반 애플리케이션을 구성하는 다양한 마이크로서비스 간 통신 방법을 효과적으로 관리할 수 있음

https://istio.io/latest/docs/ops/deployment/architecture/

  • 데이터플레인
    • Envoy 프록시를 사이드카 패턴으로 각 서비스에 배포
    • Envoy 프록시가 마이크로서비스 간의 모든 네트워크 통신을 조정하고 제어
      • 모든 인바운드 및 아웃바운드 트래픽을 가로채서 처리
      • 트래픽 라우팅, 로드 밸런싱, 보안 정책 적용 등을 담당
      • 모든 메시 트래픽에 대한 원격 분석을 수집하고 보고합니다
  • 컨트롤플레인
    • 트래픽을 라우팅하도록 프록시를 구성하고 관리
    • istiod라는 프로세스를 통해 Envoy에 대한 설정 관리
    • istiod 구성 요소
      • 파일럿(Pilot): 모든 Envoy 사이드카에서 프록시 라우팅 규칙을 관리하며, 서비스 디스커버리와 로드 밸런싱 설정 제공
      • 갤리(Galley): Istio와 쿠버네티스(TLS 연결 및 파일럿에 필요한 설정)를 연결해 주는 역할
        • 서비스 메시 구성 데이터를 검증하고 변환
      • 시타델(Citadel): 보안 기능을 담당하며, TLS 인증서 발급 및 관리를 통해 서비스 간 통신의 암호화 수행

 

 

Envoy Proxy 소개

https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request

  • C++로 개발한 고성능 프록시 서버
  • HTTP/1.1, HTTP/2, gRPC 등 지원
  • L3/L4 네트워크 프록시 및 L7 기능 제공
  • 구성 요소
    • Cluster : envoy 가 트래픽을 포워드할 수 있는 논리적인 서비스 (엔드포인트 세트), 실제 요청이 처리되는 IP 또는 엔드포인트의 묶음을 의미
    • Endpoint : IP 주소, 네트워크 노드로 클러스터로 그룹핑됨, 실제 접근이 가능한 엔드포인트를 의미. 엔드포인트가 모여서 하나의 Cluster 가 됨
    • Listener : 무엇을 받을지 그리고 어떻게 처리할지 IP/Port 를 바인딩하고, 요청 처리 측면에서 다운스트림을 조정하는 역할
    • Route : Listener 로 들어온 요청을 어디로 라우팅할 것인지를 정의. 라우팅 대상은 일반적으로 Cluster 라는 것에 대해 이뤄지게 됨
    • Filter : Listener 로부터 서비스에 트래픽을 전달하기까지 요청 처리 파이프라인
    • UpStream : envoy 요청을 포워딩해서 연결하는 백엔드 네트워크 노드 - 사이드카일때 application app, 아닐때 원격 백엔드
    • DownStream : Envoy에 연결하는 엔티티, 사이드카가 아닌 모델에서는 원격 클라이언트
  • Flow : downstream으로부터 들어온 트래픽을 리스너가 수신해서 HTTP router filter로 불필요한 트래픽을 차단하고 엔드포인트에 해당하는 클러스터가 받아 로직 수행

실습 환경 구성

CloudFormation으로 vscode server를 AWS에 구축하기

Resources:
  VscodeServerVPC757FAB28:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/Resource
  VscodeServerVPCpublicSubnet1SubnetA1A0B3AA:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2a
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: aws-cdk:subnet-name
          Value: public
        - Key: aws-cdk:subnet-type
          Value: Public
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/publicSubnet1
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet1/Subnet
  VscodeServerVPCpublicSubnet1RouteTable629F63A5:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/publicSubnet1
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet1/RouteTable
  VscodeServerVPCpublicSubnet1RouteTableAssociation8CC5347E:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VscodeServerVPCpublicSubnet1RouteTable629F63A5
      SubnetId:
        Ref: VscodeServerVPCpublicSubnet1SubnetA1A0B3AA
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet1/RouteTableAssociation
  VscodeServerVPCpublicSubnet1DefaultRoute6AE6FDA2:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: VscodeServerVPCIGW13663343
      RouteTableId:
        Ref: VscodeServerVPCpublicSubnet1RouteTable629F63A5
    DependsOn:
      - VscodeServerVPCVPCGW8B7CC360
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet1/DefaultRoute
  VscodeServerVPCpublicSubnet1EIP590279C8:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/publicSubnet1
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet1/EIP
  VscodeServerVPCpublicSubnet1NATGateway1F5F5652:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId:
        Fn::GetAtt:
          - VscodeServerVPCpublicSubnet1EIP590279C8
          - AllocationId
      SubnetId:
        Ref: VscodeServerVPCpublicSubnet1SubnetA1A0B3AA
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/publicSubnet1
    DependsOn:
      - VscodeServerVPCpublicSubnet1DefaultRoute6AE6FDA2
      - VscodeServerVPCpublicSubnet1RouteTableAssociation8CC5347E
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet1/NATGateway
  VscodeServerVPCpublicSubnet2Subnet84DD90E3:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2b
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: aws-cdk:subnet-name
          Value: public
        - Key: aws-cdk:subnet-type
          Value: Public
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/publicSubnet2
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet2/Subnet
  VscodeServerVPCpublicSubnet2RouteTable740E19CB:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/publicSubnet2
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet2/RouteTable
  VscodeServerVPCpublicSubnet2RouteTableAssociation18FBBED4:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VscodeServerVPCpublicSubnet2RouteTable740E19CB
      SubnetId:
        Ref: VscodeServerVPCpublicSubnet2Subnet84DD90E3
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet2/RouteTableAssociation
  VscodeServerVPCpublicSubnet2DefaultRouteE31A60EC:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: VscodeServerVPCIGW13663343
      RouteTableId:
        Ref: VscodeServerVPCpublicSubnet2RouteTable740E19CB
    DependsOn:
      - VscodeServerVPCVPCGW8B7CC360
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/publicSubnet2/DefaultRoute
  VscodeServerVPCprivateSubnet1SubnetB33C64E0:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2a
      CidrBlock: 10.0.2.0/24
      MapPublicIpOnLaunch: false
      Tags:
        - Key: aws-cdk:subnet-name
          Value: private
        - Key: aws-cdk:subnet-type
          Value: Private
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/privateSubnet1
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet1/Subnet
  VscodeServerVPCprivateSubnet1RouteTableDE4B9197:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/privateSubnet1
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet1/RouteTable
  VscodeServerVPCprivateSubnet1RouteTableAssociationEA535B83:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VscodeServerVPCprivateSubnet1RouteTableDE4B9197
      SubnetId:
        Ref: VscodeServerVPCprivateSubnet1SubnetB33C64E0
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet1/RouteTableAssociation
  VscodeServerVPCprivateSubnet1DefaultRoute4A41E27A:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: VscodeServerVPCpublicSubnet1NATGateway1F5F5652
      RouteTableId:
        Ref: VscodeServerVPCprivateSubnet1RouteTableDE4B9197
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet1/DefaultRoute
  VscodeServerVPCprivateSubnet2Subnet3578E158:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-2b
      CidrBlock: 10.0.3.0/24
      MapPublicIpOnLaunch: false
      Tags:
        - Key: aws-cdk:subnet-name
          Value: private
        - Key: aws-cdk:subnet-type
          Value: Private
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/privateSubnet2
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet2/Subnet
  VscodeServerVPCprivateSubnet2RouteTable13687399:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC/privateSubnet2
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet2/RouteTable
  VscodeServerVPCprivateSubnet2RouteTableAssociationB55E97C6:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VscodeServerVPCprivateSubnet2RouteTable13687399
      SubnetId:
        Ref: VscodeServerVPCprivateSubnet2Subnet3578E158
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet2/RouteTableAssociation
  VscodeServerVPCprivateSubnet2DefaultRoute3FB89628:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: VscodeServerVPCpublicSubnet1NATGateway1F5F5652
      RouteTableId:
        Ref: VscodeServerVPCprivateSubnet2RouteTable13687399
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/privateSubnet2/DefaultRoute
  VscodeServerVPCIGW13663343:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: VscodeServerStack/VscodeServerVPC
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/IGW
  VscodeServerVPCVPCGW8B7CC360:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId:
        Ref: VscodeServerVPCIGW13663343
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/VPCGW
  VscodeServerVPCRestrictDefaultSecurityGroupCustomResource699DD8BC:
    Type: Custom::VpcRestrictDefaultSG
    Properties:
      ServiceToken:
        Fn::GetAtt:
          - CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E
          - Arn
      DefaultSecurityGroupId:
        Fn::GetAtt:
          - VscodeServerVPC757FAB28
          - DefaultSecurityGroup
      Account: "482687297408"
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerVPC/RestrictDefaultSecurityGroupCustomResource/Default
  CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
      ManagedPolicyArns:
        - Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: Inline
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ec2:AuthorizeSecurityGroupIngress
                  - ec2:AuthorizeSecurityGroupEgress
                  - ec2:RevokeSecurityGroupIngress
                  - ec2:RevokeSecurityGroupEgress
                Resource:
                  - Fn::Join:
                      - ""
                      - - arn:aws:ec2:ap-northeast-2:482687297408:security-group/
                        - Fn::GetAtt:
                            - VscodeServerVPC757FAB28
                            - DefaultSecurityGroup
    Metadata:
      aws:cdk:path: VscodeServerStack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Role
  CustomVpcRestrictDefaultSGCustomResourceProviderHandlerDC833E5E:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket: cdk-hnb659fds-assets-482687297408-ap-northeast-2
        S3Key: 7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200.zip
      Timeout: 900
      MemorySize: 128
      Handler: __entrypoint__.handler
      Role:
        Fn::GetAtt:
          - CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0
          - Arn
      Runtime: nodejs20.x
      Description: Lambda function for removing all inbound/outbound rules from the VPC default security group
    DependsOn:
      - CustomVpcRestrictDefaultSGCustomResourceProviderRole26592FE0
    Metadata:
      aws:cdk:path: VscodeServerStack/Custom::VpcRestrictDefaultSGCustomResourceProvider/Handler
      aws:asset:path: asset.7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200
      aws:asset:property: Code
  VscodeServerSG6CB386E7:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow traffic to VS Code Server
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          Description: Allow all outbound traffic by default
          IpProtocol: "-1"
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          Description: Allow VS Code Server traffic
          FromPort: 8000
          IpProtocol: tcp
          ToPort: 8000
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerSG/Resource
  VscodeServerSGfromVscodeServerStackAlbSGACC5D0CA8000C6700CB5:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      Description: Allow traffic from ALB to VS Code Server
      FromPort: 8000
      GroupId:
        Fn::GetAtt:
          - VscodeServerSG6CB386E7
          - GroupId
      IpProtocol: tcp
      SourceSecurityGroupId:
        Fn::GetAtt:
          - AlbSGE6D0E5D1
          - GroupId
      ToPort: 8000
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerSG/from VscodeServerStackAlbSGACC5D0CA:8000
  AlbSGE6D0E5D1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP traffic to ALB
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          Description: Allow all outbound traffic by default
          IpProtocol: "-1"
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          Description: Allow HTTP traffic
          FromPort: 80
          IpProtocol: tcp
          ToPort: 80
        - CidrIp: 0.0.0.0/0
          Description: Allow HTTPS traffic
          FromPort: 443
          IpProtocol: tcp
          ToPort: 443
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/AlbSG/Resource
  VscodeServerRole26698AC1:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
        Version: "2012-10-17"
      ManagedPolicyArns:
        - Fn::Join:
            - ""
            - - "arn:"
              - Ref: AWS::Partition
              - :iam::aws:policy/AmazonSSMManagedInstanceCore
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerRole/Resource
  VscodeServerLaunchTemplateProfile9F18C67E:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - Ref: VscodeServerRole26698AC1
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerLaunchTemplate/Profile
  VscodeServerLaunchTemplate2CD546F9:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        IamInstanceProfile:
          Arn:
            Fn::GetAtt:
              - VscodeServerLaunchTemplateProfile9F18C67E
              - Arn
        ImageId:
          Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
        InstanceType: t3.medium
        SecurityGroupIds:
          - Fn::GetAtt:
              - VscodeServerSG6CB386E7
              - GroupId
        TagSpecifications:
          - ResourceType: instance
            Tags:
              - Key: Name
                Value: VscodeServerStack/VscodeServerLaunchTemplate
          - ResourceType: volume
            Tags:
              - Key: Name
                Value: VscodeServerStack/VscodeServerLaunchTemplate
        UserData:
          Fn::Base64: |-
            #!/bin/bash
            yum update -y
            yum install -y curl wget unzip git
            yum install -y nodejs npm
            curl -fsSL https://code-server.dev/install.sh | sh
            mkdir -p ~/.config/code-server
            echo "bind-addr: 0.0.0.0:8000" > ~/.config/code-server/config.yaml
            echo "auth: password" >> ~/.config/code-server/config.yaml
            echo "password: $(openssl rand -base64 12)" >> ~/.config/code-server/config.yaml
            echo "cert: false" >> ~/.config/code-server/config.yaml
            cat > /etc/systemd/system/code-server.service << EOF
            [Unit]
            Description=VS Code Server
            After=network.target

            [Service]
            Type=simple
            User=root
            ExecStart=/usr/bin/code-server
            Restart=always

            [Install]
            WantedBy=multi-user.target
            EOF
            systemctl enable code-server
            systemctl start code-server
      TagSpecifications:
        - ResourceType: launch-template
          Tags:
            - Key: Name
              Value: VscodeServerStack/VscodeServerLaunchTemplate
    DependsOn:
      - VscodeServerRole26698AC1
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerLaunchTemplate/Resource
  VscodeServerASG9D8D3BF1:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      LaunchTemplate:
        LaunchTemplateId:
          Ref: VscodeServerLaunchTemplate2CD546F9
        Version:
          Fn::GetAtt:
            - VscodeServerLaunchTemplate2CD546F9
            - LatestVersionNumber
      MaxSize: "1"
      MinSize: "1"
      TargetGroupARNs:
        - Ref: VscodeServerTargetGroup0ADA727F
      VPCZoneIdentifier:
        - Ref: VscodeServerVPCprivateSubnet1SubnetB33C64E0
        - Ref: VscodeServerVPCprivateSubnet2Subnet3578E158
    UpdatePolicy:
      AutoScalingScheduledAction:
        IgnoreUnmodifiedGroupSizeProperties: true
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerASG/ASG
  VscodeServerALBBD8337B1:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      LoadBalancerAttributes:
        - Key: deletion_protection.enabled
          Value: "false"
      Scheme: internet-facing
      SecurityGroups:
        - Fn::GetAtt:
            - AlbSGE6D0E5D1
            - GroupId
      Subnets:
        - Ref: VscodeServerVPCpublicSubnet1SubnetA1A0B3AA
        - Ref: VscodeServerVPCpublicSubnet2Subnet84DD90E3
      Type: application
    DependsOn:
      - VscodeServerVPCpublicSubnet1DefaultRoute6AE6FDA2
      - VscodeServerVPCpublicSubnet1RouteTableAssociation8CC5347E
      - VscodeServerVPCpublicSubnet2DefaultRouteE31A60EC
      - VscodeServerVPCpublicSubnet2RouteTableAssociation18FBBED4
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerALB/Resource
  VscodeServerALBHttpListener68E8857C:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn:
            Ref: VscodeServerTargetGroup0ADA727F
          Type: forward
      LoadBalancerArn:
        Ref: VscodeServerALBBD8337B1
      Port: 80
      Protocol: HTTP
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerALB/HttpListener/Resource
  VscodeServerTargetGroup0ADA727F:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: /healthz
      HealthCheckTimeoutSeconds: 5
      Matcher:
        HttpCode: 200-499
      Port: 8000
      Protocol: HTTP
      TargetGroupAttributes:
        - Key: stickiness.enabled
          Value: "false"
      TargetType: instance
      VpcId:
        Ref: VscodeServerVPC757FAB28
    Metadata:
      aws:cdk:path: VscodeServerStack/VscodeServerTargetGroup/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Analytics: v2:deflate64:H4sIAAAAAAAA/31SwW7CMAz9lt1DtlU7bMeCJlQJbRUgrpMbTAmkSZU4IFT13+dSoGyadvJ7z6/Js5tEPr++yacHOIaRWu9HRheyWRCovWDpq0GVyGZVKzHZ2FU+EXksjFaLWFikThvQ3EXCJRQGB33Q0hCc0kDa2Zu5A+9Z3pUPoCkQHuEkcq8PDIeDM0voGV8NfZILS4mzbiu0JBaootd0mnoX63OGf4XMlh5DEDOIVm2XWNUG+kw/lVZoqGQzd/1g15rZQGAV5t5ttGEXRHJBgdG2lE3KZNGT2+2/tVaggUBaGQfrAgyfxq0D7zuta17yeVkz7o3PPfTnbPf83qcDob14rviuvwRf8gqvWe5o24o5Bhe94rliIFcNlMf9u8VTH/Qa/RgCCv63SPxmSo7ffZODhwqpD/MZqY7UCuvWKHfh8ZAk8vmFX9wuaD3y0ZKuUM77+g3MyLXujgIAAA==
    Metadata:
      aws:cdk:path: VscodeServerStack/CDKMetadata/Default
Parameters:
  SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64
  BootstrapVersion:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /cdk-bootstrap/hnb659fds/version
    Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Outputs:
  LoadBalancerDNS:
    Description: The DNS name of the load balancer
    Value:
      Fn::GetAtt:
        - VscodeServerALBBD8337B1
        - DNSName

 

필요한 프로그램 설치

# docker 설치
sudo yum update
sudo yum install docker -y

# kubectl 설치
curl -LO https://dl.k8s.io/release/v1.32.0/bin/linux/amd64/kubectl
chmod +x ./kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

# kind 설치
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

# helm 설치
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

kind로 k8s 설치

git clone https://github.com/AcornPublishing/istio-in-action
cd istio-in-action/book-source-code-master
pwd # 각자 자신의 pwd 경로

kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000 # Sample Application (istio-ingrssgateway)
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # kube-ops-view
    hostPort: 30005
  extraMounts:
  - hostPath: /root/istio-in-action/book-source-code-master
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24
EOF

# 설치 확인
docker ps

# 노드에 기본 툴 설치
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

# (옵션) kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30005 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view

## kube-ops-view 접속 URL 확인
open "http://localhost:30005/#scale=1.5"
open "http://localhost:30005/#scale=1.3"

# (옵션) metrics-server
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server
​

istio 설치

# myk8s-control-plane 진입 후 설치 진행
docker exec -it myk8s-control-plane bash
-----------------------------------
# 코드 파일들 마운트 확인
tree /istiobook/ -L 1

# istioctl 설치
export ISTIOV=1.17.8
echo 'export ISTIOV=1.17.8' >> /root/.bashrc

curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
tree istio-$ISTIOV -L 2 # sample yaml 포함
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# default 프로파일 컨트롤 플레인 배포
istioctl x precheck # 설치 전 k8s 조건 충족 검사
istioctl profile list
istioctl install --set profile=default -y
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete

# 설치 확인 : istiod, istio-ingressgateway, crd 등
kubectl get istiooperators -n istio-system
NAME              REVISION   STATUS   AGE
installed-state                       4m49s

kubectl get istiooperators -n istio-system -o yaml
...
  spec:
    components:
      base:
        enabled: true
      cni:
        enabled: false
      egressGateways:
      - enabled: false
        name: istio-egressgateway
      ingressGateways:
      - enabled: true
        name: istio-ingressgateway
      istiodRemote:
        enabled: false
      pilot:
        enabled: true
    hub: docker.io/istio
    meshConfig:
      defaultConfig:
        proxyMetadata: {}
      enablePrometheusMerge: true
    profile: default
    ...
      pilot:
        autoscaleEnabled: true
        autoscaleMax: 5
        autoscaleMin: 1
        configMap: true
        cpu:
          targetAverageUtilization: 80
        deploymentLabels: null
        enableProtocolSniffingForInbound: true
        enableProtocolSniffingForOutbound: true
        env: {}
        image: pilot
        keepaliveMaxServerConnectionAge: 30m
        nodeSelector: {}
        podLabels: {}
        replicaCount: 1
        traceSampling: 1
      telemetry:
        enabled: true
        v2:
          enabled: true
          metadataExchange:
            wasmEnabled: false
          prometheus:
            enabled: true
            wasmEnabled: false
          stackdriver:
            configOverride: {}
            enabled: false
            logging: false
            monitoring: false
            topology: false


kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
...
NAME                                    READY   STATUS              RESTARTS   AGE
istio-ingressgateway-58888b4f9b-gv7r9   1/1     Running             0          2m43s
istiod-78c465d86b-tsd8l                 1/1     Running             0          3m
...

kubectl get crd | grep istio.io | sort
istioctl verify-install # 설치 확인

# 보조 도구 설치
kubectl apply -f istio-$ISTIOV/samples/addons

#
kubectl get pod -n istio-system
NAME                                    READY   STATUS    RESTARTS   AGE
grafana-67f5ccd9d7-cgkn4                1/1     Running   0          86s
istio-ingressgateway-58888b4f9b-7t5zj   1/1     Running   0          116s
istiod-78c465d86b-pvqv6                 1/1     Running   0          2m14s
jaeger-78cb4f7d4b-d8b88                 1/1     Running   0          86s
kiali-c946fb5bc-4njln                   1/1     Running   0          86s
prometheus-7cc96d969f-6ft4s             2/2     Running   0          86s

# 빠져나오기
exit
-----------------------------------

#
kubectl get cm -n istio-system istio -o yaml
kubectl get cm -n istio-system istio -o yaml | kubectl neat

  • profile을 default로 지정했기 때문에 위 테이블과 같이 istio-ingressgateway와 istiod를 설치함
  • 참고로 istio 최신 버전에서는 profile 기능을 사용하지 않지만 현재 사용하고 있는 istio 버전은 오래된 버전이라 실습 내용에는 profile을 사용하고 있음

istio가 정상적으로 설치된 경우 아래와 같이 리소스가 구성됨

  • istio 구성에 CRD를 사용하며 configmap에 구성된 설정에 따라 사용 도구 및 동작 방식이 정의됨 (예를들어 지표 수집에 zipkin 사용)
    • CRD(Custom Resource Definition)란? 쿠버네티스 API를 확장하여 사용자 정의 리소스를 만들고 관리할 수 있게 해주는 기능. 기본적으로 제공되는 Pod, Deployment, Service 등의 리소스 외에 사용자가 직접 새로운 리소스 유형을 정의할 수 있음

  • 스크립트를 통해 보조 도구를 설치하면 위 그림과 같이 grafana, kiali, jaeger, prometheus 등 사용할 도구들이 추가됨

Envoy 주입 및 설정

  • Pod에 Envoy를 sidecar로 실행하기 위해 주입하는 방법은 두가지가 있음
    • 실행 중인 Pod에 강제 주입
    • Pod가 실행할 때 자동으로 Envoy가 같이 실행 (편리함)
kubectl create namespace istioinaction
kubectl label namespace istioinaction istio-injection=enabled
kubectl get ns --show-labels

# 
kubectl get mutatingwebhookconfiguration
NAME                         WEBHOOKS   AGE
istio-revision-tag-default   4          9m24s # 특정 revision의 사이드카 주입 설정 관리
istio-sidecar-injector       4          9m45s # Istio는 각 애플리케이션 Pod에 Envoy 사이드카 프록시를 자동으로 주입
                                              ## 네임스페이스나 Pod에 istio-injection=enabled 라벨이 있어야 작동 

kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml

# sample 애플리케이션 추가
cat services/catalog/kubernetes/catalog.yaml
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction

cat services/webapp/kubernetes/webapp.yaml 
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction

# 접속 테스트용 netshoot 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: netshoot
spec:
  containers:
  - name: netshoot
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

# catalog 접속 확인
kubectl exec -it netshoot -- curl -s http://catalog.istioinaction/items/1 | jq
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

# webapp 접속 확인 : webapp 서비스는 다른 서비스에서 데이터를 집계해 브라우저에 시각적으로 표시한다. 
## 즉 webapp은 다른 백엔드 서비스의 파사드 facade 역할을 한다.
kubectl exec -it netshoot -- curl -s http://webapp.istioinaction/api/catalog/items/1 | jq
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

# 샘플 애플리케이션 접속
kubectl port-forward -n istioinaction deploy/webapp 8080:8080

  • 웹 페이지에 접속해보면 Webapp이 catalog 서비스로부터 정보를 가져와서 테이블로 표시해주고 있음
  • Forum 서비스는 아직 실행 전이라서 정보를 가져오지 못함
# istioctl proxy-status : 단축어 ps
docker exec -it myk8s-control-plane istioctl proxy-status
docker exec -it myk8s-control-plane istioctl ps

  • Envoy 프록시 상태를 살펴보면 xDS의 동기화 상태를 확인할 수 있음
    • xDS(eXtensible Discovery Services)란? Istio의 동적 구성(dynamic configuration) 관리의 핵심 요소로, Envoy 프록시에 동적으로 설정 정보를 제공하는 API 및 서비스들의 집합

istio 네트워크 흐름

Gateway와 VirtualService

cat ch2/ingress-gateway.yaml
cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: outfitters-gateway
  namespace: istioinaction
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: webapp-virtualservice
  namespace: istioinaction
spec:
  hosts:
  - "*"
  gateways:
  - outfitters-gateway
  http:
  - route:
    - destination:
        host: webapp
        port:
          number: 80
EOF

#
kubectl get gw,vs -n istioinaction
NAME                                             AGE
gateway.networking.istio.io/outfitters-gateway   126m

NAME                                                       GATEWAYS                 HOSTS   AGE
virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]   126m


# istio-ingressgateway 서비스 NodePort 변경 및 nodeport 30000로 지정 변경
kubectl get svc,ep -n istio-system istio-ingressgateway
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
kubectl get svc -n istio-system istio-ingressgateway

# istio-ingressgateway 서비스 externalTrafficPolicy 설정 : ClientIP 수집 확인
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl describe svc -n istio-system istio-ingressgateway

curl -s http://127.0.0.1:30000/api/catalog | jq
curl -s http://127.0.0.1:30000/api/catalog/items/1 | jq
curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1

# webapp 반복 호출
while true; do curl -s http://127.0.0.1:30000/api/catalog/items/1 ; sleep 1; echo; done
while true; do curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1 ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
while true; do curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1 ; date "+%Y-%m-%d %H:%M:%S" ; sleep 0.5; echo; done

  • Istio에서 Gateway와 VirtualService는 트래픽 관리의 핵심 구성 요소로, 각자 고유한 역할을 수행하면서 함께 작동하여 효과적인 트래픽 제어를 제공함
    • Gateway : 서비스 메시의 경계에서 작동하는 트래픽 입출구 관리 리소스
      • 메시에 대한 인바운드/아웃바운드 트래픽을 관리하며, 어떤 트래픽이 메시에 들어오거나 나갈지를 지정
      • 애플리케이션과 함께 실행되는 사이드카 Envoy 프록시가 아닌, 메시의 엣지에서 실행되는 독립적인 Envoy 프록시에 적용
    • VirtualService : 실제 트래픽 라우팅 규칙을 정의하는 리소스
      • Envoy 프록시에게 어떤 목적지로 어떻게 트래픽을 전달할지 알려주는 역할
      • Istio 서비스 메시 내에서 서비스로 요청을 라우팅하는 방법 구성
      • HTTP URI, 헤더, 포트 등 다양한 조건에 따른 라우팅 규칙 설정
      • 트래픽 비중(weight) 조절. 카나리 배포, A/B 테스팅에 활용

디테일한 Envoy 설정 확인

docker exec -it myk8s-control-plane istioctl proxy-status
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
catalog-6cf4b97d-nccfj.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
istio-ingressgateway-996bc6bb6-mz544.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
webapp-7685bcb84-c55ck.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8

ISTIOIGW=istio-ingressgateway-996bc6bb6-647tx.istio-system
WEBAPP=webapp-7685bcb84-nfntj.istioinaction

docker exec -it myk8s-control-plane istioctl proxy-config all $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config all $WEBAPP

docker exec -it myk8s-control-plane istioctl proxy-config listener $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config route $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config cluster $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config endpoint $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config log $ISTIOIGW

docker exec -it myk8s-control-plane istioctl proxy-config listener $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config route $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config cluster $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config endpoint $WEBAPP
docker exec -it myk8s-control-plane istioctl proxy-config log $WEBAPP

# envoy 가 사용하고 있는 인증서 정보 확인
docker exec -it myk8s-control-plane istioctl proxy-config secret $ISTIOIGW
docker exec -it myk8s-control-plane istioctl proxy-config secret $WEBAPP

istio 관찰 가능성

  • 애플리케이션에 별도의 로직을 수정하지 않더라도 서비스 메시에 대한 메트릭들을 자동으로 수집해서 추가로 설치한 Prometheus와 Grafana를 통해 손쉽게 대시보드를 구성할 수 있음

  • Kiali를 사용하면 Istio 서비스 메시의 ingressgateway부터 뒷단의 애플리케이션까지의 네트워크 흐름을 시각적으로 볼 수 있음

  • 아래 그림과 같이 Kiali에서 Jaeger를 사용할 수 있어서 애플리케이션에서 별도로 Trace를 남기지 않더라도 Trace 정보를 확인할 수 있음

  • Envoy에 대한 설정도 Kiali에서 손쉽게 볼 수 있는데 서비스 메시가 어려운 이유 중 하나가 Envoy의 설정이 굉장히 복잡하다는 것. Config의 라인수를 보면 1만 3천줄이 넘어감

장애 상황 감지 및 해결

git으로 clone 한 디렉토리 내 bin/chaos.sh 파일을 사용하여 의도적으로 500 에러 발생 시킴

docker exec -it myk8s-control-plane bash
----------------------------------------
# istioinaction 로 네임스페이스 변경
cat /etc/kubernetes/admin.conf
kubectl config set-context $(kubectl config current-context) --namespace=istioinaction
cat /etc/kubernetes/admin.conf

cd /istiobook/bin/ 
./chaos.sh 500 100 # 모니터링 : kiali, grafana, tracing

./chaos.sh 500 50 # 모니터링 : kiali, grafana, tracing
  • 먼저 Grafana 대시보드에서도 성공률이 점차 떨어지고, 500 에러가 증가하는 것을 확인

  • 이 후 Kiali에서 트래픽의 어느 구간에 문제가 있는지 시각적으로 확인

 

  • Jaeger의 Trace 정보를 통해 오류에 대한 상세 내용 확인

 

  • Client가 오류가 발생하더라도 무조건 트래픽을 보내고 있기 때문에 서버는 계속 부하를 받게됨. 애플리케이션 코드 수정 없이 오류가 발생하면 간격을 두고 retry를 하도록 수정하여 서버 부하를 완화시킬 수 있음
# catalog 3번까지 요청 재시도 할 수 있고, 각 시도에는 2초의 제한 시간이 있음.
cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  http:
  - route:
    - destination:
        host: catalog
    retries:
      attempts: 3
      retryOn: 5xx
      perTryTimeout: 2s
EOF

kubectl get vs -n istioinaction
NAME                    GATEWAYS                 HOSTS         AGE
catalog                                          ["catalog"]   12s
webapp-virtualservice   ["outfitters-gateway"]   ["*"]         3h38m
  • 이 후 상대적으로 오류가 발생하는 트래픽은 재시도 간격이 있기 때문에 상대적으로 트래픽이 적어지고, 오류율도 줄어듦