WellSpring

Istio 8주차 - 13장 : VM Support & Istio Traffic Flow 본문

ISTIO

Istio 8주차 - 13장 : VM Support & Istio Traffic Flow

daniel00324 2025. 5. 27. 18:03

 

 

목차

     

     

     

    ※ 본 게재 글은 gasida님의 'Istio' 스터디 강의 및 실습예제와 'Istio in Action' 서적 참고하여 작성하였습니다.


    ▶ 유용한 정보 모음 ( 권장 Tool 포함 )

    더보기

    [ Istio ]

    Virtual Machine Architecture : https://istio.io/v1.17/docs/ops/deployment/vm-architecture/

    Virtual Machine Installation : https://istio.io/v1.17/docs/setup/install/virtual-machine/

    Debugging Virtual Machines : https://istio.io/v1.17/docs/ops/diagnostic-tools/virtual-machines/

    An easier way to add virtual machines to Istio service mesh

     - https://istio.io/v1.17/blog/2021/simple-vms/

    Intruducing workload Entiries 

     - https://istio.io/latest/blog/2020/workload-entry/

    Understanding DNS 

     - https://istio.io/v1.17/docs/ops/configuration/traffic-management/dns/

    Expending New Frontiers - Smart DNS Proxying in Istio

     - https://istio.io/v1.17/docs/ops/configuration/traffic-management/dns-proxy/

    Istio DNS Proxy : 지연개선, DNS 부하 감소 

     - https://www.anyflow.net/sw-engineer/istio-dns-proxying

     

    [CNCF] Istio and DNS

     - https://www.youtube.com/watch?v=f6w6MoPz_u8

    Matt Turner - Life of Packet through Istio III 

     - https://www.youtube.com/watch?v=qsTK4o189_I

     

    [ Tools ]

    . kpexec : https://github.com/ssup2/kpexec

    . termshark : https://github.com/gcla/termshark


    This chapter covers Incorporating virtual machine workloads into the mesh

    • 레거시 워크로드를 이스티오 서비스 메시에 통합하기 Incorporating legacy workloads into Istio’s service mesh
    • 가상머신에 istio-agent 설치 및 설정하기 Installing and configuring the istio-agent in VMs
    • 가상머신에 ID 프로비저닝하기 Provisioning identity for VMs
    • 클러스터 서비스와 가상머신 서비스를 서로 노출하기 Exposing cluster services to VMs, and vice versa
    • 로컬 DNS 프록시를 사용해 클러스터 서비스의 FQDN 해석하기 Using the local DNS proxy to resolve FQDNs of cluster services

    ▶ 들어가며

    더보기
    https://istio.io/v1.17/blog/2021/simple-vms/
    • 지금까지는 이스티오 서비스 메시를 컨테이너 및 쿠버네티스 관점에서 다뤘다.
    • 그러나 실제 워크로드는 자주 가상머신이나 물리 머신에서 실행된다.
    • 컨테이너와 쿠버네티스는 종종 기술 스택을 현대화하려는 노력의 일환으로 사용하며, 이번 장은 이 두 세계를 애플리케이션 네트워크 계층에서 이스티오로 연결하는 방법을 보여준다.
    • 왜 단순히 레거시 워크로드를 현대화해서 쿠버네티스 클러스터에서 실행하는 것이 아니라 가상머신을 메시로 통합하는 것인지 궁금할 수 있다.
    • 우리도 가능하면 그 접근법을 추천하지만, 몇몇 경우에는 그런 접근법이 불가능하거나 최소한 비용을 고려했을 때 불가능에 가까울 수 있다.
    • 엔터프라이즈는 규제 준수 때문에 워크로드를 쿠버네티스 클러스터를 설정하고 운영할 전문 지식이 부족한 온프레미스에서 실행해야 할 수 있다.
    • 애플리케이션을 컨테이너화하는 것은 그리 간단하지 않다. 어떤 애플리케이션은 다시 설계해야 할 수 있다. 어떤 애플리케이션에는 업데이트해야 하지만 다른 의존성과 충돌하는 의존성이 있을 수 있다. 즉, 의존성 지옥이다.
    • 어떤 것들은 실행 중인 가상머신에 고유한 의존성이 있다. Some have some unique dependencies on the VM they run on.

    • 이번 장에서는 사이드카 프록시를 설치하고 설정함으로써 어떤 워크로드든 메시의 일부로 삼을 수 있는 방법을 보여준다.
    • 이 접급법은 레거시 워크로드가 있으며, 이 레거시 워크로드를 복원력 있고 안전하고 고가용성적인 방식으로 메시로 통합하길 원하는 엔터프라이즈에게 흥미로운 기능을 제공한다.

    [ 실습 환경 구성 ]

    책 실습 구성 stio-eastwestgateway 사용 시, Service(LoadBalancer)가 External-IP가 외부 공인 IP 필요한 복잡환경으로, 동일 네트워크로 변경 구성

     

    ☞ 구성 : VPC 1개, EC2 인스턴스 1대 (Ubuntu 22.04 LTS, t3.xlarge - vCPU 4 , Mem 16) , forum-vm 1대는 t3.small

    • CloudFormation 스택 실행 시 파라미터를 기입하면, 해당 정보가 반영되어 배포됩니다.
    • CloudFormation 에 EC2의 UserData 부분(Script 실행)으로 실습 환경에 필요한 기본 설정들이 자동으로 진행됩니다.

    ▶ istio-8w.yaml

    더보기
    AWSTemplateFormatVersion: '2010-09-09'
    
    Metadata:
      AWS::CloudFormation::Interface:
        ParameterGroups:
          - Label:
              default: "<<<<< Deploy EC2 >>>>>"
            Parameters:
              - KeyName
              - SgIngressSshCidr
              - MyInstanceType
              - LatestAmiId
    
          - Label:
              default: "<<<<< Region AZ >>>>>"
            Parameters:
              - TargetRegion
              - AvailabilityZone1
              - AvailabilityZone2
    
          - Label:
              default: "<<<<< VPC Subnet >>>>>"
            Parameters:
              - VpcBlock
              - PublicSubnet1Block
              - PublicSubnet2Block
    
    Parameters:
      KeyName:
        Description: Name of an existing EC2 KeyPair to enable SSH access to the instances.
        Type: AWS::EC2::KeyPair::KeyName
        ConstraintDescription: must be the name of an existing EC2 KeyPair.
      SgIngressSshCidr:
        Description: The IP address range that can be used to communicate to the EC2 instances.
        Type: String
        MinLength: '9'
        MaxLength: '18'
        Default: 0.0.0.0/0
        AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
        ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
      MyInstanceType:
        Description: Enter EC2 Type(Spec) Ex) t2.micro.
        Type: String
        Default: t3.xlarge
      LatestAmiId:
        Description: (DO NOT CHANGE)
        Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
        Default: '/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id'
        AllowedValues:
          - /aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id
    
      TargetRegion:
        Type: String
        Default: ap-northeast-2
      AvailabilityZone1:
        Type: String
        Default: ap-northeast-2a
      AvailabilityZone2:
        Type: String
        Default: ap-northeast-2c
    
      VpcBlock:
        Type: String
        Default: 192.168.0.0/16
      PublicSubnet1Block:
        Type: String
        Default: 192.168.10.0/24
      PublicSubnet2Block:
        Type: String
        Default: 192.168.20.0/24
    
    Resources:
    # VPC
      IstioVPC:
        Type: AWS::EC2::VPC
        Properties:
          CidrBlock: !Ref VpcBlock
          EnableDnsSupport: true
          EnableDnsHostnames: true
          Tags:
            - Key: Name
              Value: Istio-VPC
    
    # PublicSubnets
      PublicSubnet1:
        Type: AWS::EC2::Subnet
        Properties:
          AvailabilityZone: !Ref AvailabilityZone1
          CidrBlock: !Ref PublicSubnet1Block
          VpcId: !Ref IstioVPC
          MapPublicIpOnLaunch: true
          Tags:
            - Key: Name
              Value: Istio-PublicSubnet1
      PublicSubnet2:
        Type: AWS::EC2::Subnet
        Properties:
          AvailabilityZone: !Ref AvailabilityZone2
          CidrBlock: !Ref PublicSubnet2Block
          VpcId: !Ref IstioVPC
          MapPublicIpOnLaunch: true
          Tags:
            - Key: Name
              Value: Istio-PublicSubnet2
    
      InternetGateway:
        Type: AWS::EC2::InternetGateway
      VPCGatewayAttachment:
        Type: AWS::EC2::VPCGatewayAttachment
        Properties:
          InternetGatewayId: !Ref InternetGateway
          VpcId: !Ref IstioVPC
    
      PublicSubnetRouteTable:
        Type: AWS::EC2::RouteTable
        Properties:
          VpcId: !Ref IstioVPC
          Tags:
            - Key: Name
              Value: Istio-PublicSubnetRouteTable
      PublicSubnetRoute:
        Type: AWS::EC2::Route
        Properties:
          RouteTableId: !Ref PublicSubnetRouteTable
          DestinationCidrBlock: 0.0.0.0/0
          GatewayId: !Ref InternetGateway
      PublicSubnet1RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
          SubnetId: !Ref PublicSubnet1
          RouteTableId: !Ref PublicSubnetRouteTable
      PublicSubnet2RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
          SubnetId: !Ref PublicSubnet2
          RouteTableId: !Ref PublicSubnetRouteTable
    
    # EC2 Hosts
      EC2SG:
        Type: AWS::EC2::SecurityGroup
        Properties:
          GroupDescription: Kans EC2 Security Group
          VpcId: !Ref IstioVPC
          Tags:
            - Key: Name
              Value: Istio-SG
          SecurityGroupIngress:
          - IpProtocol: '-1'
            CidrIp: !Ref SgIngressSshCidr
          - IpProtocol: '-1'
            CidrIp: !Ref VpcBlock
          - IpProtocol: '-1'
            CidrIp: 10.10.200.0/24
          - IpProtocol: '-1'
            CidrIp: 172.16.0.0/16
          - IpProtocol: tcp
            FromPort: 80
            ToPort: 80
            CidrIp: 0.0.0.0/0
          - IpProtocol: tcp
            FromPort: 8080
            ToPort: 8080
            CidrIp: 0.0.0.0/0
          - IpProtocol: tcp
            FromPort: 30000
            ToPort: 30000
            CidrIp: 0.0.0.0/0
    
      EC21:
        Type: AWS::EC2::Instance
        Properties:
          InstanceType: !Ref MyInstanceType
          ImageId: !Ref LatestAmiId
          KeyName: !Ref KeyName
          Tags:
            - Key: Name
              Value: k3s-s
          NetworkInterfaces:
            - DeviceIndex: 0
              SubnetId: !Ref PublicSubnet1
              GroupSet:
              - !Ref EC2SG
              AssociatePublicIpAddress: true
              PrivateIpAddress: 192.168.10.10
          BlockDeviceMappings:
            - DeviceName: /dev/sda1
              Ebs:
                VolumeType: gp3
                VolumeSize: 30
                DeleteOnTermination: true
          UserData:
            Fn::Base64:
              !Sub |
                #!/bin/bash
                hostnamectl --static set-hostname k3s-s
    
                # Config convenience
                echo 'alias vi=vim' >> /etc/profile
                echo "sudo su -" >> /home/ubuntu/.bashrc
                ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
    
                # Disable ufw & apparmor 
                systemctl stop ufw && systemctl disable ufw
                systemctl stop apparmor && systemctl disable apparmor
    
                # Install packages
                apt update && apt-get install bridge-utils net-tools conntrack ngrep jq tree unzip kubecolor -y
    
                # local dns - hosts file
                echo "192.168.10.10 k3s-s" >> /etc/hosts
    
                # Install k3s-server
                curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.28.15+k3s1 INSTALL_K3S_EXEC=" --disable=traefik"  sh -s - server --token istiotoken --cluster-cidr "172.16.0.0/16" --service-cidr "10.10.200.0/24" --write-kubeconfig-mode 644 
    
                # Change kubeconfig
                echo 'export KUBECONFIG=/etc/rancher/k3s/k3s.yaml' >> /etc/profile
    
                # Install Helm
                curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
    
                # Alias kubectl to k
                echo 'alias kc=kubecolor' >> /etc/profile
                echo 'alias k=kubectl' >> /etc/profile
                echo 'complete -o default -F __start_kubectl k' >> /etc/profile
    
                # kubectl Source the completion
                source <(kubectl completion bash)
                echo 'source <(kubectl completion bash)' >> /etc/profile
                
                # Install Kubectx & Kubens
                git clone https://github.com/ahmetb/kubectx /opt/kubectx
                ln -s /opt/kubectx/kubens /usr/local/bin/kubens
                ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx
    
                # Install Kubeps & Setting PS1
                git clone https://github.com/jonmosco/kube-ps1.git /root/kube-ps1
                cat <<"EOT" >> ~/.bash_profile
                source /root/kube-ps1/kube-ps1.sh
                KUBE_PS1_SYMBOL_ENABLE=true
                function get_cluster_short() {
                  echo "$1" | cut -d . -f1
                }
                KUBE_PS1_CLUSTER_FUNCTION=get_cluster_short
                KUBE_PS1_SUFFIX=') '
                PS1='$(kube_ps1)'$PS1
                EOT
    
    
      EC24:
        Type: AWS::EC2::Instance
        Properties:
          InstanceType: t3.small
          ImageId: !Ref LatestAmiId
          KeyName: !Ref KeyName
          Tags:
            - Key: Name
              Value: forum-vm
          NetworkInterfaces:
            - DeviceIndex: 0
              SubnetId: !Ref PublicSubnet1
              GroupSet:
              - !Ref EC2SG
              AssociatePublicIpAddress: true
              PrivateIpAddress: 192.168.10.200
          BlockDeviceMappings:
            - DeviceName: /dev/sda1
              Ebs:
                VolumeType: gp3
                VolumeSize: 30
                DeleteOnTermination: true
          UserData:
            Fn::Base64:
              !Sub |
                #!/bin/bash
                hostnamectl --static set-hostname forum-vm
    
                # Config convenience
                echo 'alias vi=vim' >> /etc/profile
                echo "sudo su -" >> /home/ubuntu/.bashrc
                ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
    
                # Disable ufw & apparmor 
                systemctl stop ufw && systemctl disable ufw
                systemctl stop apparmor && systemctl disable apparmor
    
                # Install packages
                apt update && apt-get install net-tools ngrep jq tree unzip apache2 -y
    
                # local dns - hosts file
                echo "192.168.10.200  forum-vm" >> /etc/hosts
    
    
    Outputs:
      Serverhost:
        Value: !GetAtt EC21.PublicIp

    ▶ CloudFormation 스택 배포 ← 실행하는 PC에 aws cli 설치되어 있고, aws configure 자격증명 설정 상태

    더보기
    # YAML 파일 다운로드
    curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/istio-8w.yaml
    
    # CloudFormation 스택 배포
    # aws cloudformation deploy --template-file kans-7w.yaml --stack-name mylab --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region ap-northeast-2
    예시) aws cloudformation deploy --template-file istio-8w.yaml --stack-name mylab --parameter-overrides KeyName=kp-kyukim SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2
    
    ## Tip. 인스턴스 타입 변경 : MyInstanceType=t3.xlarge (vCPU 4, Mem 16)
    예시) aws cloudformation deploy --template-file istio-8w.yaml --stack-name mylab --parameter-overrides MyInstanceType=t3.xlarge KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2
    
    # CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
    aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2
    
    # [모니터링] CloudFormation 스택 상태 : 생성 완료 확인
    while true; do 
      date
      AWS_PAGER="" aws cloudformation list-stacks \
        --stack-status-filter CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED DELETE_IN_PROGRESS DELETE_FAILED \
        --query "StackSummaries[*].{StackName:StackName, StackStatus:StackStatus}" \
        --output table
      sleep 1
    done
    
    # 배포된 aws ec2 유동 공인 IP 확인
    aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
    k3s-s   43.202.60.44    running
    testpc  15.165.15.104   running
    
    # EC2 SSH 접속 : 바로 접속하지 말고, 3~5분 정도 후에 접속 할 것
    ssh -i ~/.ssh/kp-gasida.pem ubuntu@$(aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2)
    ...
    (⎈|default:N/A) root@k3s-s:~# <- kubeps 가 나오지 않을 경우 ssh logout 후 다시 ssh 접속 할 것!

     

    [ 실행 결과 한 눈에 보기 ]

    ** /etc/hosts 등록 ( 3.35.156.185    forum-vm  , 54.180.231.239  k3s-s )

     

     

    • EC2 생성 수량 부족 실패 시 : 사용자 계정의 해당 리전에 EC2 최대 갯수 제한 일 경우, Service Quotas (EC2) 증설 요청으로 해결 - 링크 EC2 요청
    • Limit Type(EC2 Instances) ⇒ 서울 리전, All Standard (A, C, D, H, I, M, R, T, Z) Instances, New limit value(40 정도)

    k3s-s , forum-vm 각각 접속 후 확인

    더보기

    1. [자신의 PC] 배포된 aws ec2 유동 공인 IP 확인

    aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
    forum-vm        54.180.250.130  running
    k3s-s   43.203.195.107  running

     

    2.  k3s-s 접속 후 확인 : ssh -i <> ubuntu@3.38.151.222

    kc get node -owide
    NAME     STATUS   ROLES                  AGE     VERSION         INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
    k3s-s    Ready    control-plane,master   2m12s   v1.28.15+k3s1   192.168.10.10    <none>        Ubuntu 22.04.5 LTS   6.8.0-1029-aws   containerd://1.7.22-k3s1.28
    
    hostnamectl 
    ...
     Hardware Vendor: Amazon EC2
      Hardware Model: t3.xlarge
    
    
    # (옵션) krew 설치
    wget -O /root/krew-linux_amd64.tar.gz https://github.com/kubernetes-sigs/krew/releases/download/v0.4.4/krew-linux_amd64.tar.gz
    tar zxvf /root/krew-linux_amd64.tar.gz
    /root/krew-linux_amd64 install krew
    export PATH="$PATH:/root/.krew/bin"
    echo 'export PATH="$PATH:/root/.krew/bin:/root/go/bin"' >> /etc/profile
    kubectl krew install get-all neat view-secret rolesum pexec
    
    
    # (옵션) termshark 설치
    apt install termshark -y # 대화형창에서 yes 입력 => DEBIAN_FRONTEND=noninteractive 
    tshark -D
    termshark -v

     

    3. forum-vm 접속 후 확인 : ssh -i <> ubuntu@54.180.243.135

    ip -br -c addr
    ip -c a
    
    hostnamectl 
    ...
     Hardware Vendor: Amazon EC2
      Hardware Model: t3.small
      
    # (옵션) termshark 설치
    apt install termshark -y # 대화형창에서 yes 입력
    tshark -D
    termshark -v

    [ 실행 결과 한 눈에 보기 ]

    krew Plug-in install
    Termshark 설치 및 결과 확인

    13.1 이스티오의 가상머신 지원

    ▶ 들어가며 : Istio’s VM support

    더보기
    • 가상머신을 메시에 통합하는 것은 이스티오 초기부터 지원됐지만, 제어 평면 외부에서 많은 해결책과 자동화가 필요했습니다.
    • 이스티오의 가상머신 지원은 1.9.0에서 핵심 기능 일부가 구현되고 API가 적절한 접근법으로 결정되면서 베타 beta 로 승격됐다.
    • 이때의 핵심 기능들이란 다음과 같다.
      • 가상머신에서의 사이드카 프록시 설치 및 설정. istioctl 로 간소화됐다.
      • 가상머신의 고가용성. 이스티오의 두 가지 새 리소스인 WorkloadGroup, WorkloadEntry 를 도입하면서 달성됐다.
      • 가상머신에서 메시 내 서비스의 DNS 해석. 이스티오의 사이드카와 함께 설정되는 로컬 DNS 프록시를 사용해서 가능해졌다.
    • 이번 장에서는 다룰 정보가 많으므로 이런 새 기능들을 고수준에서 다루는 것부터 시작한다.
    • 그런 다음, 가상머신을 메시에 통합해 구체적인 예제로 작동시킬 것이다.

     

    13.1.1 가상머신에서의 사이드카 프록시 설치 및 설정 단순화하기

      - Simplifying sidecar proxy installation and configuration in a VM

     

    ▶ 들어가며

    더보기
    • 가상머신이 메시의 일부가 되려면 다음을 해야 한다.
      • 네트워크 트래픽을 관리할 사이드카 프록시 설치 Install the sidecar proxy to manage network traffic
      • 프록시가 istiod에 연결해 메시 설정을 받도록 설정 Configure the proxy to connect to istiod and receive the mesh configuration
      • istiod에 인증하는 데 사용할 ID 토큰을 가상머신에 제공 Provide the VM with an identity token, used to authenticate to istiod

     

    그림 13.1은 워크로드가 메시의 일부가 되는 데 필요한 전제 조건을 보여준다.

     

    • 쿠버네티스에서 실행되는 워크로드에도 같은 작업이 필요하다.
      • 웹훅 webhook 이나 istioctl 을 사용해 사이드카를 자동으로 설치하고 설정한다. Install and configure the sidecar automatically with the webhook or using istioctl.
      • ID 토큰을 소유한다. 쿠버네티스가 파드에 자동으로 주입한다. Possess an identity token—Kubernetes injects it automatically into the Pod.
    • 이런 편의성은 쿠버네티스 외부의 워크로드로 확장되지 않는다. These conveniences do not extend to workloads external to Kubernetes.
    • 그러므로 가상머신 소유자는 프록시를 설치하고 설정해야 하며, 워크로드 ID용 부트스트랩 토큰을 제공해야 한다. 그러나 나서야 워크로드가 메시의 일부가 될 수 있다. Thus VM owners must install and configure the proxy and provision a bootstrap token for workload identity and only then can a workload become a part of the mesh.

    • Single-network architecture
    https://academy.tetrate.io/courses/take/istio-fundamentals/

     

    • In a single-network scenario, the Kubernetes cluster and VM workloads share the same L3 network space. The VMs can reach Istiod (the control plane) and other Pods directly by IP. You may still choose to route the control-plane traffic through a gateway (such as the istio-ingressgateway), but it's not strictly required if direct connectivity is available.
    • When using auto-registration, the VM will contact Istiod (or the gateway) on startup and automatically create a WorkloadEntry resource in the control plane, using a WorkloadGroup template you define in advance.

    • Multi-network architecture
    • In a multi-network scenario, VM workloads reside in a different network than the Kubernetes cluster, so Pods cannot directly communicate with the VMs’ IP addresses. An Istio east-west gateway (or an ingress/egress gateway configured for cross-network traffic) bridges the networks.
    • All traffic—including control-plane communication and data-plane traffic—flows through the gateway between the two networks. The VM must be configured with the gateway’s address so it can securely connect to Istiod and establish mTLS tunnels for application traffic.

    ☞ 멀티 네트워크 환경에서는 모든 Traffic 이 east-west gateway 를 통해서 전달되고, 통제된다!!

     

    가상머신의 프로비저닝 ID 자세히 살펴보기 A CLOSER LOOK AT PROVISIONING IDENTITY FOR VMS

    더보기
    • 이스티오는 가상머신에 ID를 제공하는 신뢰의 원천으로 쿠버네티스를 사용한다.
    • 이는 쿠버네티스에서 토큰을 만들고 머신에 전달하면서 동작한다.
    • 이 토큰은 머신에 설치된 istio-agent가 가져가 istiod에 인증하는 데 사용한다.

    그림 13.2와 13.3은 클러스터 워크로드와 가상머신 워크로드에서 ID가 제공되는 방식의 차이를 보여준다.

    클러스터의 워크로드는 (1) 서비스 어카운트 토큰을 파드에 주입받으며 (2) 그 토큰을 사용해 인증하고 SVID를 가져온다.
    가상머신은 외부이기 때문에 수작업이 필요하다. (1) 서비스 어카운트를 만들고, (2) 그 토큰을 가상머신에 전달하며, (3) 그 토큰을 사용해 인증하고 SVID를 받는다.

     

    • 쿠버네티스가 토큰을 자동으로 파드에 주입한다는 점만 빼면 접근법은 비슷하다.
    • 반면 가상머신에서는 서비스 메시 운영자가 이 작업을 수행해야 하는데, 수작업으로 토큰을 안전하게 가상머신으로 전달해야 한다.
    • istio-agent는 이 토큰을 사용해 istiod에 인증하고, 그 결과 istiod가 SVID 형태로 그 ID를 발급한다.
    • 이 솔루션의 단점은 서비스 메시 운영자가 Kubernetes에서 토큰을 자동으로 생성하고 이를 VM으로 안전하게 전송해야 한다는 점입니다.
      The drawback of this solution is that it requires service mesh operators to automate creating the tokens in Kubernetes and securely transferring them to VMs.
    • 이것은 많은 노력이 필요하지 않을 수도 있지만, 대부분의 조직이 다중 클라우드 전략을 따르는 경우 빠르게 많은 노력을 더하게 됩니다.
      This may not require a lot of effort, but if the organization follows a multi-cloud strategy, as most do, then it quickly adds up to a lot of effort.


    (참고) 플랫폼이 할당한 ID Platform-assigned identity

    • 이스티오 커뮤니티에서는 서로 다른 클라우드 프로바이더의 머신에 워크로드 ID를 자동으로 제공하는 해결책을 개발 중이다.
    • 이 방법은 가상머신의 플랫폼이 부여한 ID를 신뢰의 근원으로 사용하며, istio-agent가 이를 갖고 istiod에 인증하는 데 사용한다.
    • 당연히 이스티오는 토큰 검증을 설정하는 API를 클라우드 프로바이더에 노출할 것이다. 전체 과정은 아래 시각화 확인.
    워크로드를 인증하는 데 플랫폼이 부여한 ID를 사용하는 방법
    • 이 방법은 아직 개발되지 않았지만 ID 공급자 설계 문서를 참조 - Docs
    • 다음 예제에서는 머신 ID를 프로비저닝하기 위한 신뢰의 원천으로 쿠버네티스를 사용한다. In our example that follows, we use Kubernetes as the source of trust to provision the identity of the machine.
    • 간결하게 하기 위해 토큰은 수작업으로 가상머신에 전달할 것이다. To keep the chapter snappy, we’ll manually transfer the token to the VM.

     


    13.1.2 가상머신 고가용성 Virtual machine high availability

    ▶ 들어가며

    더보기
    • 가상머신에서 고가용성을 달성하고자 이스티오는 쿠버네티스가 컨테이너화된 워크로드에서 취하는 접근법을 매우 흡사하게 모방한다.
    • 기본적으로 쿠버네티스는 다음 리소스로 고가용성을 달성한다.
      • 디플로이먼트 Deployment : 고수준 리소스로, 복제본이 어떻게 만들어져야 하는지에 대한 설정을 담고 있다.
      • 파드 Pod : 위 설정으로 만든 복제본이다. 이렇게 하면 파드에 고유한 부분이 없다는 것이 보장되므로 파드가 정상이 아닐 때마다 폐기하고 갈아치울 수 있다(혹은 불필요 할 때 줄일 수 있다). 그렇게 서비스 가용성을 유지 가능하다.

    • 이스티오가 가상머신에 도입하는 리소스는 쿠버네티스의 디플로이먼트 및 파드 개념과 흡사핟.
      • WorkloadGroup 리소스는 쿠버네티스의 디플로이먼트와 유사하다.
        • 관리하는 워크로드를 설정하는 방법에 대한 템플릿을 정의하기 때문이다. it defines the template for how the workloads it manages are configured.
        • 이 리소스는 공통 속성을 지정하는데, 여기서는 애플리케이션이 노출하는 포트, 그룹의 인스턴스에 부여하는 레이블, 메시에서 워크로드의 ID를 나타내는 서비스 어카운트, 애플리케이션 상태 프로브 Probe 방법 등이 있다.
      • WorkloadEntry 리소소는 쿠버네티스의 파드와 유사하다.
        • WorkloadEntry는 최종 사용자 트래픽을 처리하는 개별 가상머신을 나타낸다. It represents a single VM that serves end-user traffic.
        • WorkloadEntry는 WorkloadGroup에서 정의한 공통 속성 외에 인스턴스의 상태와 주소 등과 같은 고유한 속성도 갖고 있다.
    • WorkloadEntry는 수동으로 생성할 수 있다. 그러나 권장하는 방식은 새로 뜬 워크로드가 메시에 자동으로 참가하는 워크로드 자동 등록을 이용하는 것이다. A WorkloadEntry can be created manually; however, the recommended approach is to use workload auto-registration, where newly provisioned workloads join the mesh automatically.

    워크로드 자동 등록 이해하기 UNDERSTANDING WORKLOAD AUTO-REGISTRATION

    더보기
    • 워크로드를 자동 등록하는 동안, 워크로드는 제공받은 설정을 사용해 컨트롤 플레인에 연결하고 ID 토큰으로 자신이 WorkloadGroup의 일원임을 인증한다.
      During workload auto-registration, a workload connects to the control plane (using the configuration supplied to it) and authenticates itself as a member of a WorkloadGroup using the identity token.
    • 이 작업이 성공하면 컨트롤 플레인은 메시에서 가상머신을 나타내는 WorkloadEntry를 생성한다 (그림 13.4 참조).
      When this is done successfully, the control plane creates a WorkloadEntry to represent the VM in the mesh.
    워크로드 자동등록 과정
    • 메시 내의 가상머신WorkloadEntry로 표현하는 것은 여러 이유로 중요하다.
      The representation of the VM in the mesh using a WorkloadEntry is important for many reasons.
    • 특히 쿠버네티스 서비스나 이스티오 ServiceEntry 리소스가 레이블 셀렉터로 워크로드를 선택해 트래픽을 라우팅할 백엔드로 사용할 수 있다.
      In particular, it can be selected by Kubernetes services or Istio ServiceEntry resources using label selectors and used as the backend to route traffic to.
    • 실제 주소가 아니라 쿠버네티스 서비스(즉, 클러스터 내의 FQDN)로 워크로드를 선택하면, 클라이언트 측에 대한 별다른 지식이나 영향 없이도 정상적이지 않은 워크로드를 폐기하거나 늘어난 수요에 맞추기 위해 새 워크로드를 쉽게 띄울 수 있다.
      Selecting workloads using Kubernetes services (that is, their fully qualified domain name [FQDN] in the cluster) and not their actual addresses makes it possible to dispose of workloads when they are not healthy or easily spin up new ones to meet increased demand without any knowledge or impact on the client side.

    • 그림 13.5는 어떻게 서비스를 사용해 WorkloadEntry와 파드를 겨냥할 수 있는지 보여준다.
      Figure 13.5 illustrates how services can be used to target workload entries and Pods.
    • 예를 들어, 가상머신에서 실행하는 레거시 워크로드를 쿠버네티스에서 실행하는 현대화 워크로드(마이그레이션) 이전할 때 위험을 줄이려는 경우가 여기에 해당할 수 있다.
      You might want to do that to, for instance, reduce the risk when migrating from legacy workloads running in VMs to modernized workloads running in a Kubernetes cluster.
    • 워크로드를 병렬로 실행한 다음, 서비스 메시의 트래픽 전환 기능을 사용해(5장에서 설명) 모든 트래픽을 가상머신에서 파드로 점차 옮긴다.
    • 이 과정에서 오류가 늘어나면 트래픽을 가상머신으로 되돌릴 수 있는 선택지도 갖고 있는 것이다.
      This is done by running workloads in parallel and then using the traffic-shifting capabilities of the service mesh (as described in chapter 5) to gradually move all traffic from VMs to Pods, with the option of shifting traffic back to the VMs if there is an increase in errors.
    Deployment와 Pod에 대비한 WorkloadGroup 과 WorkloadEntry의 관계

     

     

    이스티오가 수행하는 헬스 체크 이해하기 UNDERSTANDING THE HEALTH CHECKS PERFORMED BY ISTIO

    더보기
    • 워크로드가 서비스 메시의 일부가 되고 나면, 트래픽을 받을 준비가 돼야 하며 헬스 체크로 검사받는다.
      After becoming part of the service mesh, a workload needs to be ready to receive traffic and is probed by health checks.
    • 서비스의 고가용성을 유지하려면 두 가지 헬스 체크가 필요하다 (쿠버네티스가 헬스 체크하는 방식과 비슷하다).
      To maintain high availability of a service, we need two types of health checks (which are similar to how Kubernetes does health checking):
      • readiness 프로브는 워크로드가 시작된 후 트래픽을 수신할 준비가 됐는지 확인한다.
        Readiness probes check whether a workload is ready to receive traffic once it starts.
      • liveness 프로브는 애플리케이션이 실행 중일 때 정상인지 확인한다. 정상이 아니면 재시작해야 한다. Liveness probes check whether the application is healthy once it’s running; if not, it should be restarted.

    • liveness 프로브는 서비스 메시의 관심사가 아니다!
      Liveness probes are not a service mesh concern!
    • 워크로드가 살아 있는지 확인하는 것은 실행 중인 플랫폼의 기능이다.
      Ensuring the liveness of a workload is a platform feature where workloads are run.
    • 예를 들어, 플랫폼인 쿠버네티스가 Deployment 설정에서 정의한 프로브로 liveness 를 검사한다.
      For example, Kubernetes, which is also a platform, performs liveness checks using the probes defined in the Deployment configuration.
    • 마찬가지로 워크로드를 클라우드의 가상머신에서 실행할 때는 클라우드의 기능을 사용해 liveness 프로브를 구현하고, 프로브가 실패하면 새 인스턴스를 띄우는 등 복구하기 위한 수정 조치를 취해야 한다.
      Similarly, when running workloads on VMs in the cloud, we need to use the features of the cloud to implement liveness probes and take corrective actions to heal the VM if the probe fails, such as provisioning a new instance.
    • 다음은 가장 인기 있는 세 클라우드 프로바이더의 liveness 검사 및 자동 복구에 대한 문서다.
      To get you started, here are the docs for liveness checks and auto-healing for the three most popular cloud providers:
      • Azure implements automatic instance repairs for VM scale sets - Docs
      • Amazon Web Services implements health checks for auto-scale group instances - Docs

    ☞ Google Cloud Platform implements health checking and auto-healing for managed instance groups - Docs

     

    이스티오가 가상머신에서 readiness 프로브를 구현하는 방법 HOW ISTIO PERFORMS READINESS PROBES IN VMS

    더보기
    • 애플리케이션이 트래픽을 받을 준비가 됐는지는 WorkloadGroup 정의에 명세된 바에 따라 istio-agent 가 주기적으로 검사한다.
      The application’s readiness to receive traffic is probed periodically by the istio-agent, according to the specification in the WorkloadGroup definition.
    • 에이전트는 애플리케이션의 상태를 istiod에 보고하는데, 상태가 정상에서 비정상으로, 혹은 비정상에서 정상으로 바뀔 때 등이다 (그림 13.6)
      The agent reports the application’s health status to istiod, such as when the status switches from healthy to unhealthy or vice versa.
    사이드카 프록시는 istiod를 애플리케이션 상태 정보로 업데이트한다.

     

    • 컨트롤 플레인은 상태를 사용해 그 워크로드로 라우팅할지 여부를 결정한다.
      The control plane uses the health status to determine whether traffic should be routed to a workload.
    • 예를 들어 애플리케이션이 정상이면 데이터 플레인에 애플리케이션을 호스팅하는 가상머신의 엔드포인트를 설정한다.
      For example, when the application is healthy, the data plane is configured with the endpoint of the VM that hosts the application.
    • 그리고 그 반대도 마찬가지도. 애플리케이션이 비정상일 때 데이터플레인에서 엔드포인트를 제거한다.
      And the opposite is also true: the endpoint is removed from the data plane when the application is unhealthy.
    • 서비스 메시 운영자는 WorkloadGroup에 애플리케이션 readiness 검사를 설정하고, 클라우드 프로바이더가 권장하는 방법에 따라 인프라 계층에 liveness 검사를 만들어야 한다.
      As a service mesh operator, you have to configure the readiness checks of the application in the WorkloadGroup and create liveness checks in the infrastructure layer by following your cloud provider’s recommended practices.
    • liveness 와 readiness 프로브에는 다른 설정을 사용하는 것을 추천한다. We recommend using different configurations for liveness and readiness probes:
      • istio-agent 가 수행하는 readiness 프로브는 공격적이어야 하며 트래픽이 오류를 반환하는 인스턴스로 라우팅되는 것을 방지해야 한다. Readiness probes performed by the istio-agent should be aggressive and prevent traffic from being routed to an instance that is returning errors.
      • 클라우드 프로바이더가 수행하는 liveness 프로브는 좀 더 보수적이어야 하며 가상머신이 복구할 시간을 줘야 한다. Liveness probes performed by the cloud provider should be more conservative and allow the VM time to recover.
    • 인스턴스를 너무 경솔하게 죽이지 않도록 하자. 인스턴스를 죽이면 유예 기간 grace period 없이 진행 중인 요청을 종료해 최종 사용자에게 실패를 보여주기 때문이다. Aim to avoid killing instances too hastily, which would terminate inflight requests without a grace period, causing end-user visible failures.
    • 경험상 좋은 방법은 liveness 프로브보다 readiness 프로브가 항상 먼저 실패하는 것이다.

     


    13.1.3 메시 내 서비스의 DNS 해석 DNS resolution of in-mesh services

    더보기
    • 가상머신은 쿠버네티스 클러스터 외부에 있으므로 쿠버네티스 내부 DNS 서버에 접근할 수 없다.
      Because VMs are external to the Kubernetes cluster, they lack access to its internal DNS server.

     

    https://istio.io/latest/blog/2020/dns-proxy/
    • 그 결과 가상머신은 클러스터 서비스의 호스트네임을 해석할 수 없다.
      As a result, VMs cannot resolve the hostnames for cluster services.
    • 이를 해결하는 것이 가상머신을 서비스 메시에 통합하기 위한 마지막 단계다.
      Providing a solution to this is the last milestone to integrate VMs into the service mesh.
    • 먼저 왜 DNS 해석이 필요한지 궁금할 수 있다.
      You may wonder why we need DNS resolution in the first place.
    • 애플리케이션과 함께 배포되는 서비스 프록시는 트래픽을 모든 워크로드로 라우팅하는 설정을 갖고 있지 않은가?
      Doesn’t the service proxy, deployed along with the application, possess the configuration to route traffic to all workloads?
    • 그렇다. 프록시는 트래픽을 어떻게 라우팅할지에 관한 설정을 갖고 있다.
      You’re correct: the proxy has the configuration for how to route traffic!
    • 그러나 문제는 트래픽을 애플리케이션에서 꺼내서 프록시로 가져오는 데 있다.
      However, the issue lies in getting the traffic out of the application and to the proxy.
    • 이를 위한 전체 조건호스트네임이 해석되는 것이다.
      A precondition for that to happen is for the hostname to be resolved.
    • 그렇지 않으면, 트래픽은 절대 애플리케이션을 떠나지 않으므로 엔보이 프록시로 리다이렉트될 수 없다.
      If it isn’t, the traffic never leaves the application and cannot be redirected to the Envoy proxy.
    • 이 문제는 그림 13.7에 시각화돼 있다.
    DNS 해석이 실패하므로 아웃바운드 트래픽은 절대 엔보이 프록시에 도달하지 않는다
    • 앞서, 클러스터 호스트네임은 보통 모든 쿠버네티스 서비스를 설정해둔 프라이빗 private DNS 서버를 사용해 해석했다.
      Previously, cluster hostnames were commonly resolved using a private DNS server configured with all Kubernetes services.

     

    • 가상머신은 DNS 쿼리를 보내는 네임서버로 이 프라이빗 DNS 서버를 사용하도록 설정돼 있다. (A 레코드 동적 추가/변경/삭제 구현 필요) The VMs were configured to use this as a nameserver to which they sent DNS queries.
    • 쿠버네티스 내 워크로드의 동적인 성질 때문에 프라이빗 DNS 서버를 설정하는 과정은, 이런 변경 사항을 수신하고 DNS 서버를 동기화 상태로 유지하는 쿠버네티스 컨트롤러를 사용해 자동화돼야 했다. Due to the dynamic nature of workloads in Kubernetes, the process of configuring the private DNS server had to be automated using a Kubernetes controller that listens for these changes and keeps the DNS server synchronized.
    • exteranl-dns가 정확히 그 작업을 수행하는 오픈소스 솔루션이다. https://github.com/kubernetes-sigs/external-dns external-dns is an open source solution that does exactly that.
    DNS 쿼리는 해석을 위해 DNS 프록시로 리다이렉트되는데, DNS 프록시에는 istiod가 클러스터 내 서비스를 설정해둔다.

     

    https://istio.io/latest/blog/2020/dns-proxy/

     

    • DNS 프록시는 엔보이 프록시와 함께 이스티오 사이드카로 동작하며 애플리케이션의 DNS 쿼리를 처리하는데, 이 DNS 쿼리는 이스티오에서 일반적으로 트래픽을 포착하는 방법인 Iptable 규칙을 사용해 DNS 프록시로 리다이렉트된다.
      The DNS proxy runs in Istio’s sidecar alongside the Envoy proxy and handles DNS queries from the application, which are redirected to the DNS proxy using Iptable rules—the usual Istio traffic-capture approach.
    • istio-cni 를 사용할 때는 이 과정이 살짝 다르다. This differs slightly when using istio-cni.
    • DNS 프록시를 지속적으로 업데이트하고자 이스티오는 NDS Name Discovery Serivce 라는 새 API를 도입했다. To keep the DNS proxy continuously updated, Istio introduced a new API called the Name Discovery Service (NDS).
    • NDS를 사용하면, 메시에 쿠버네티스 서비스나 이스티오 ServiceEntry가 추가될 때마다 컨트롤 플레인이 데이터 플레인에 새 DNS 항목을 동기화한다.
      With the NDS, the control plane synchronizes the data plane with new DNS entries whenever a Kubernetes service or Istio ServiceEntry is added to the mesh.
    • 그러나 DNS 프록시는 가상머신에 국한되지 않는다. DNS 프록시를 사용하면 링크 처럼 여러 추가 기능을 사용 할 수 있다 - Blog
    https://www.anyflow.net/sw-engineer/istio-dns-proxying

     

    지금까지 고수준 개념과 그 개념의 목표를 살펴봤다. 다음으로는 가상머신을 서비스 메시에 통합하면서 실제로 실행해보자.


    13.2 인프라 준비하기 Setting up the infrastructure

    더보기

    구성 환경 : cool-store 애플리케이션 호스팅

    • webapp 과 catalog 서비스는 쿠버네티스 클러스터에 배포한다.
    • forum 서비스는 가상머신에 배포한다.
    • 클러스터와 가상머신이 다른 네트워크에 있다는 것은 주목할 만하다
      • 가상머신에서 클러스터 서비스로 향햐는 트래픽을 리버스 프록시할 east-west 게이트웨이가 필요하기 때문이다.

     

     

    13.2.1 서비스 메시 준비하기 Setting up the service mesh : istio, app (실습~)

    더보기
    # (옵션) 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=30007 --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 확인
    echo -e "http://$(curl -s ipinfo.io/ip):30007/#scale=1.5"
    echo -e "http://$(curl -s ipinfo.io/ip):30007/#scale=1.3"
    
    # 소스코드 clone
    git clone https://github.com/AcornPublishing/istio-in-action
    tree istio-in-action/book-source-code-master -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 -
    cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
    istioctl version --remote=false
    
    # 클러스터와 가상머신이 다른 네트워크에 있으므로, 이스티오를 설치한 네임스페이스에 네트워크 정보 레이블을 지정해야 한다.
    kubectl create namespace istio-system
    kubectl label namespace istio-system topology.istio.io/network=west-network
    
    # demo 프로파일 컨트롤 플레인 배포
    cat istio-in-action/book-source-code-master/ch13/controlplane/cluster-in-west-network.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: istio-controlplane
      namespace: istio-system
    spec:
      profile: demo
      components:
        egressGateways:
        - name: istio-egressgateway
          enabled: false
      values:
        global:
          meshID: usmesh
          multiCluster:
            clusterName: west-cluster
          network: west-network
    
    istioctl install -f istio-in-action/book-source-code-master/ch13/controlplane/cluster-in-west-network.yaml --set values.global.proxy.privileged=true -y
    
    
    # 보조 도구 설치
    kubectl apply -f istio-$ISTIOV/samples/addons
    
    
    # 설치 확인 : istiod, istio-ingressgateway, crd 등
    kubectl get istiooperators -n istio-system -o yaml
    kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
    kubectl get cm -n istio-system istio -o yaml
    kubectl get crd | grep istio.io | sort
    
    # 실습을 위한 네임스페이스 설정
    kubectl create ns istioinaction
    kubectl label namespace istioinaction istio-injection=enabled
    kubectl get ns --show-labels
    
    # istio-ingressgateway 서비스 : NodePort 변경 및 nodeport 지정 변경 , externalTrafficPolicy 설정 (ClientIP 수집)
    kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
    kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 8443, "nodePort": 30005}]}}'
    kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
    kc describe svc -n istio-system istio-ingressgateway
    
    # NodePort 변경 및 nodeport 30001~30003으로 변경 : prometheus(30001), grafana(30002), kiali(30003), tracing(30004)
    kubectl patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
    kubectl patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
    kubectl patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'
    kubectl patch svc -n istio-system tracing -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 16686, "nodePort": 30004}]}}'
    
    # Prometheus 접속 : envoy, istio 메트릭 확인
    echo -e "http://$(curl -s ipinfo.io/ip):30001"
    
    # Grafana 접속
    echo -e "http://$(curl -s ipinfo.io/ip):30002"
    
    # Kiali 접속 : NodePort
    echo -e "http://$(curl -s ipinfo.io/ip):30003"
    
    # tracing 접속 : 예거 트레이싱 대시보드
    echo -e "http://$(curl -s ipinfo.io/ip):30004"

     

     

     

    • cool-store 서비스/gw/vs 배포 및 http 요청 확인
    더보기
    # cool-store 서비스/gw/vs 배포
    kubectl -n istioinaction apply -f istio-in-action/book-source-code-master/ch12/webapp-deployment-svc.yaml
    kubectl -n istioinaction apply -f istio-in-action/book-source-code-master/ch12/webapp-gw-vs.yaml
    kubectl -n istioinaction apply -f istio-in-action/book-source-code-master/ch12/catalog.yaml
    
    # 확인
    kc get deploy,svc -n istioinaction
    kc get gw,vs -n istioinaction
    • http 요청 확인
    # k3s-s
    curl -s -H "Host: webapp.istioinaction.io" http://192.168.10.10:30000/api/catalog/ | jq
    curl -s -H "Host: webapp.istioinaction.io" http://192.168.10.10:30000/api/catalog/items/1 | jq
    
    # [forum-vm] k8s cool-store 요청 시도 확인
    APP_IP=43.203.195.107 # k8s-s 의 공인 IP
    curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/catalog/items/1 | jq
    while true; do curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/catalog/ ; echo; date; sleep 1; done
    
    # [자신의 PC] k8s cool-store 요청 시도 확인
    바로 위 [testpc]와 동일 요청
    
    # [k8s-s] forum-vm web 요청 시도 확인
    curl 192.168.10.200
    curl 192.168.10.200 -I
    
    VM_IP=15.165.15.104 # testpc 의 공인 IP
    curl $VM_IP
    curl $VM_IP -I

     

    [ 실행 결과 한 눈에 보기 ]

    1) wepapp.istioinaction.io  호출 테스트

     

    2) k3s-s ==> forum-vm  웹서비스 및 ext.IP 호출 테스트

    13.2.2 가상머신 프로비저닝 Provisioning the VM : Ubuntu, 공인 IP, SSH 접근, 애플리케이션 포트 8080 노출


    13.3 가상머신까지 메시 확인

    컨트롤 플레인 업데이트 Mesh expansion to VMs (실습~)

    더보기
    • 가상머신 통합 기능베타 단계이며 기본적으로 활성화돼 있지 않다. 그러므로 IstioOperator 정의를 사용해 이스티오 설치를 업데이트해야 한다 - Docs
      The features to integrate a VM are in the beta phase1 and not enabled by default. Hence we need to update the Istio installation using the following IstioOperator definition, which enables the following features:
    • 이 IstioOperator 정의는 워크로드 자동 등록, 헬스 체크, DNS 쿼리를 캡처해 DNS 프록시로 리다이렉트하는 기능을 활성화한다.
      workload auto registration, health checks, capturing DNS queries, and redirecting those queries to the DNS proxy.
    • 이 기능들은 가상머신을 메시로 통합하는 데 필요하다.
      These features, as covered earlier in this chapter, are required to integrate a VM into the mesh:

     

    # 컨트롤 플레인 업데이트 Mesh expansion to VMs
    cat istio-in-action/book-source-code-master/ch13/controlplane/cluster-in-west-network-with-vm-features.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: istio-controlplane
      namespace: istio-system
    spec:
      profile: demo
      components:
        egressGateways:
        - name: istio-egressgateway
          enabled: false
      meshConfig:
        defaultConfig:
          proxyMetadata:
            ISTIO_META_DNS_CAPTURE: "true" # DNS 쿼리가 캡처돼 DNS 프록시로 리다이렉트된다
      values:
        pilot:
          env:
            PILOT_ENABLE_WORKLOAD_ENTRY_AUTOREGISTRATION: true # 워크로드를 컨트롤 플레인에 자동 등록할 수 있다
            PILOT_ENABLE_WORKLOAD_ENTRY_HEALTHCHECKS: true # 가상머신 워크로드의 상태를 검사한다
        global:
          meshID: usmesh
          multiCluster:
            clusterName: west-cluster
          network: west-network
    
    istioctl install -f istio-in-action/book-source-code-master/ch13/controlplane/cluster-in-west-network-with-vm-features.yaml --set values.global.proxy.privileged=true -y
    kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec": {"type": "NodePort"}}'

     

    • 업데이트된 컨트롤 플레인은 DNS 해석을 위해 서비스 프록시가 DNS 쿼리를 포착해서 사이드카에 있는 로컬 DNS 프록시리다이텍트하도록 설정한다.
      The updated control plane configures the service proxies to capture DNS queries and redirect them to the local DNS proxy in the sidecar for resolution.
    • 게다가 워크로드자동으로 등록할 수 있고 헬스 체크를 수행해 istiod에 보고할 수 있다.
      Furthermore, workloads can auto-register and perform and report health status to istiod.
    • 이 기능들을 사용하려면 한 가지 조건이 더 있다. 가상머신은 istiod에 연결해 설정과 ID를 받아올 수 있어야 한다.
      There is one further condition for us to use those features: the VM must be able to connect to istiod and receive its configuration and identity.

     

    13.3.1 istiod와 클러스터 서비스들은 가상머신에 노출하기* Exposing istiod and cluster services to the VM

    더보기
    • 가상머신이 메시의 일부분이 되려면 istiod에 통신을 하고 클러스터 서비스들과 커넥션을 시작할 수 있어야 한다.
      To become part of the mesh, the VM must be able to talk to istiod and initiate connections to the cluster services.
    • 가상머신과 클러스터가 같은 네트워크에 있을 때는 기본적으로 동작한다.
      This works out of the box when the VM and the cluster are in the same network.
    • 그렇지만 우리의 경우에는 별개의 네트워크에 있으므로 트래픽을 이스티오의 컨트롤 플레인이나 워크로드로 프록시해줄 east-west 게이트웨이가 필요하다.
      but in our case, they are in separate networks and require an east-west gateway to proxy the traffic to the Istio control plane or workloads.

    Step1. east-west 게이트웨이 설치해보자 - Docs

    #
    cat istio-in-action/book-source-code-master/ch13/gateways/cluster-east-west-gw.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: istio-eastwestgateway
      namespace: istio-system
    spec:
      profile: empty
      components:
        ingressGateways:
        - name: istio-eastwestgateway
          label:
            istio: eastwestgateway
            app: istio-eastwestgateway
            topology.istio.io/network: west-network
          enabled: true
          k8s:
            env:
            - name: ISTIO_META_ROUTER_MODE
              value: "sni-dnat"
            # The network to which traffic is routed
            - name: ISTIO_META_REQUESTED_NETWORK_VIEW
              value: west-network
            service:
              ports:
              - name: status-port
                port: 15021
                targetPort: 15021
              - name: mtls
                port: 15443
                targetPort: 15443
              - name: tcp-istiod
                port: 15012
                targetPort: 15012
              - name: tcp-webhook
                port: 15017
                targetPort: 15017  
      values:
        global:
          meshID: usmesh
          multiCluster:
            clusterName: west-cluster
          network: west-network
    
    #
    istioctl install -f istio-in-action/book-source-code-master/ch13/gateways/cluster-east-west-gw.yaml -y
    
    #
    kubectl get pod -n istio-system -l chart=gateways
    NAME                                     READY   STATUS    RESTARTS   AGE
    istio-eastwestgateway-86f6cb4699-nbhnp   1/1     Running   0          9m47s
    istio-ingressgateway-7b7ccd6454-xmqgw    1/1     Running   0          22m
    
    kubectl get svc -n istio-system -l istio.io/rev=default
    NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                                                                      AGE
    istio-eastwestgateway   LoadBalancer   10.10.200.252   192.168.10.10   15021:32278/TCP,15443:31099/TCP,15012:31437/TCP,15017:32573/TCP              178m
    istio-ingressgateway    NodePort       10.10.200.125   <none>          15021:31538/TCP,80:30000/TCP,443:30005/TCP,31400:31525/TCP,15443:30143/TCP   4h1m
    istiod                  ClusterIP      10.10.200.111   <none>          15010/TCP,15012/TCP,443/TCP,15014/TCP                                        4h1m
    
    kubectl get svc -n istio-system istio-eastwestgateway -o json | jq
    ...
          {
            "name": "status-port",
            "nodePort": 32278,
            "port": 15021,
            "protocol": "TCP",
            "targetPort": 15021
          },
          {
            "name": "mtls",
            "nodePort": 31099,
            "port": 15443,
            "protocol": "TCP",
            "targetPort": 15443
          },
          {
            "name": "tcp-istiod",
            "nodePort": 31437,
            "port": 15012,
            "protocol": "TCP",
            "targetPort": 15012
          },
          {
            "name": "tcp-webhook",
            "nodePort": 32573,
            "port": 15017,
            "protocol": "TCP",
            "targetPort": 15017
          }
    ...
    
    kubectl get svc -n istio-system istiod -o json | jq
    ...
          {
            "name": "https-dns",
            "port": 15012,
            "protocol": "TCP",
            "targetPort": 15012
          },
          {
            "name": "https-webhook",
            "port": 443,
            "protocol": "TCP",
            "targetPort": 15017
          },
    ...

     

     


    • 게이트웨이를 설치하면 가상머신이 클러스터 서비스와 istiod에 접근하는 데 필요한 포트를 노출할 수 있다. With the gateway installed, we can expose the needed ports for the VM to access cluster services and istiod.
    • 그림 13.11은 가상머신이 istiod와 클러스터 서비스들에 연결할 수 있도록 노출된 포트를 보여준다.
      Figure 13.11 shows the exposed ports that enable the VM to connect to istiod and the cluster services.
    • 먼저 가상머신에서 메시 내 서비스로 향하는 요청을 리버스 프록시해주는 다중 클러스터 상호 TLS 포트(15443)을 노출해보자.
      Let’s initially expose the multi-cluster mTLS port (15443) that reverse-proxies requests from the VM to the in-mesh services
    istiod와 클러스터 서비스들은 가상머신에 노출하는 포트들

     

    Step2. 다중클러스터 mTLS포트(15443)을 노출하자!! 

    #
    cat istio-in-action/book-source-code-master/ch13/expose-services.yaml 
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: cross-network-gateway
      namespace: istio-system
    spec:
      selector:
        istio: eastwestgateway
      servers:
        - port:
            number: 15443
            name: tls
            protocol: TLS
          tls:
            mode: AUTO_PASSTHROUGH
          hosts:
            - "*.local"
    
    kubectl apply -f istio-in-action/book-source-code-master/ch13/expose-services.yaml 
    kubectl get gw,vs -A
    NAMESPACE       NAME                                                AGE
    istio-system    gateway.networking.istio.io/cross-network-gateway   2m23s
    istioinaction   gateway.networking.istio.io/coolstore-gateway       82m
    
    NAMESPACE       NAME                                                       GATEWAYS                HOSTS                         AGE
    istioinaction   virtualservice.networking.istio.io/webapp-virtualservice   ["coolstore-gateway"]   ["webapp.istioinaction.io"]   82m

     


    Step3. 다음으로는 트래픽을 허용하고 istiod로 라우팅하도록 Gateway 리소스VirtualService 리소스를 적용해 istiod 포트를 노출한다.

    #
    cat istio-in-action/book-source-code-master/ch13/expose-istiod.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: istiod-gateway
    spec:
      selector:
        istio: eastwestgateway
      servers:
        - port:
            name: tls-istiod
            number: 15012
            protocol: tls
          tls:
            mode: PASSTHROUGH        
          hosts:
            - "*"
        - port:
            name: tls-istiodwebhook
            number: 15017
            protocol: tls
          tls:
            mode: PASSTHROUGH          
          hosts:
            - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: istiod-vs
    spec:
      hosts:
      - "*"
      gateways:
      - istiod-gateway
      tls:
      - match:
        - port: 15012
          sniHosts:
          - "*"
        route:
        - destination:
            host: istiod.istio-system.svc.cluster.local
            port:
              number: 15012
      - match:
        - port: 15017
          sniHosts:
          - "*"
        route:
        - destination:
            host: istiod.istio-system.svc.cluster.local
            port:
              number: 443
    
    # 
    kubectl apply -f istio-in-action/book-source-code-master/ch13/expose-istiod.yaml -n istio-system
    
    
    # 13.3.2 실습 전 아래와 같이 gw,vs 리소스가 생성되어있는지 확인하자!
    kc get gw,vs -A
    NAMESPACE       NAME                                                AGE
    istio-system    gateway.networking.istio.io/istiod-gateway          9s
    istio-system    gateway.networking.istio.io/cross-network-gateway   4m40s
    istioinaction   gateway.networking.istio.io/coolstore-gateway       84m
    
    NAMESPACE       NAME                                                       GATEWAYS                HOSTS                         AGE
    istio-system    virtualservice.networking.istio.io/istiod-vs               ["istiod-gateway"]      ["*"]                         9s
    istioinaction   virtualservice.networking.istio.io/webapp-virtualservice   ["coolstore-gateway"]   ["webapp.istioinaction.io"]   84m

    • 인프라를 만들고, 컨트롤 플레인을 업데이트하고, 프록시가 컨트롤 플레인에 통신할 수 있도록 준비하면서 가상머신을 서비스 메시에 통합하기 위해 먼 길을 걸어왔다.
    • 이제 가상머신이 속해 있는 워크로드 그룹을 나타내는 WorkloadGroup 을 만드는 것만 남았다.

    13.3.2 WorkloadGroup 으로 워크로드 그룹 나타내기* Representing a group of workloads with a WorkloadGroup

    더보기
    • WorkloadGroup은 구성원인 가상머신들의 공통 속성을 정의하는데, 여기서는 노출할 포트, 애플리케이션이 트래픽을 받을 준비가 됐는지 테스트할 방법 같은 애플리케이션 전용 정보 등이 있다.
    • 예를 들어 forum 워크로드의 공통 속성은 다음 WorkloadGroup에서 정의한다.
    #
    cat istio-in-action/book-source-code-master/ch13/workloadgroup.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: WorkloadGroup
    metadata:
      name: forum
      namespace: forum-services
    spec:
      metadata:
        annotations: {}
        labels:
          app: forum # 서비스는 레이블을 사용해 이 그룹의 워크로드를 대상으로 삼을 수 있다
      template:
        serviceAccount: forum-sa # 워크로드가 이 워크로드 그룹에 등록하려면 forum-sa 인증 토큰을 보유하고 있어야 한다
        network: vm-network # 이스티오가 동일한 네트워크에 있는 워크로드 사이의 직접 접근을 설정할 수 있도록 한다
      probe: # 이 워크로드 그룹의 인스턴스에서 실행되는 istio-agent는 HTTP GET 요청을 8080 포트의 /api/healthz 경로로 보내 앱의 준비 상태를 확인한다
        periodSeconds: 5
        initialDelaySeconds: 1
        httpGet:
          port: 8080
          path: /api/healthz
    • 가상머신을 서비스 메시에 통합하기 위한 관련 속성 일부는 다음과 같다.
      • lables
        • 쿠버네티스 서비스들이 이 워크로드 그룹으로 등록된 워크로드 엔트리를 선택할 수 있게 해준다. Enables Kubernetes services to select the workload entries that register to this WorkloadGroup
      • network
        • 컨트롤 플레인이 이 속성을 사용해 트래픽을 가상머신으로 라우팅하도록 서비스 프록시를 설정한다. Using this property, the control plane configures service proxies to route traffic to the VM
        • 같은 네트워크에 있으면 IP 주소를 사용한다. 다른 네트워크라면 그 네트워크에 배포된 east-west 게이트웨이를 사용한다. if it’s the same network, use the IP address; otherwise, use the east-west gateway deployed in that network.
      • serviceAccount
        • 워크로드의 ID를 나타낸다. 워크로드가 이 그룹의 멤버로 등록하려면, 이 서비스 어카운트 ID용 클레임을 제시해야 한다. Represents the identity of the workloads. For a workload to register as a member of this group, it must represent a claim for the service account identity.

    Step1. 네임스페이스와 서비스 어카운트를 만들고 WorkloadGroup 설정을 클러스터에 적용해보자.  

    #
    cat istio-in-action/book-source-code-master/ch13/workloadgroup.yaml
    kubectl create namespace forum-services
    kubectl create serviceaccount forum-sa -n forum-services
    kubectl apply -f istio-in-action/book-source-code-master/ch13/workloadgroup.yaml
    
    #
    kubectl get-all -n forum-services
    kubectl get workloadgroup -n forum-services
    NAME    AGE
    forum   2m2s



    • WorkloadGroup 을 적용하고 나서 무슨 일이 일어날까?
    • 이제 클러스터는 WorkloadGroup에 명세된 forum-sa 서비스 어카운트의 유효한 토큰을 제시할 수 있는 워크로드를 자동으로 등록하도록 설정된다.

    Step2. 가상머신의 사이드카용 설정 생성하기 GENERATING THE CONFIGURATION FOR THE VM’S SIDECAR  

     

    • WorkloadGroup 은 워크로드 자동 등록을 가능하게 하는 것 외에, 이 그룹에 있는 가상머신을 위한 공통 설정을 생성하는 데도 사용할 수 있다.
    • istioctl 을 사용하면 가상머신 설정을 만드는 것이 매우 간단하다.
    • istioctl 은 WorkloadGroup 안의 정보를 사용하고, WorkloadGroup 인스턴스용 설정을 생성하는 데 필요한 추가 정보는 쿠버네티스 클러스터에 쿼리한다.
    • 예를 들어 다음 명령어는 forum 워크로드를 호스팅하는 머신용 설정을 생성한다.
    # Generates all the required configuration files for workload instance on a VM or non-Kubernetes environment from a WorkloadGroup artifact.
    istioctl x workload entry configure -h
    istioctl x workload entry configure \
    --name forum \ # forum-services 네임스페이스에 있는 forum WorkloadGroup 을 읽고 워크로드 설정을 생성한다
    --namespace forum-services \ # 상동
    --clusterID "west-cluster" \ # 반드시 이스티오 설치 시 지정한 클러스터 이름으로 설정해야 한다
    --externalIP $VM_IP \ # 워크로드가 클러스터와 동일한 네트워크에 있지 않은 경우 workloadIP 파라미터가 필요하다. 디폴트 설정에 의하면, 정의하지 않은 경우 네트워크에서 할당한 사설 IP를 사용한다.
    --autoregister \ # 워크로드를 자동으로 등록하도록 설정한다.
    -o /tmp/my-workload-files/ # 설정 파일을 저장할 디렉터리 위치를 명령 실행 위치에 대한 상대 경로로 지정한다.
    
    #
    istioctl x workload entry configure -f istio-in-action/book-source-code-master/ch13/workloadgroup.yaml -o /tmp/my-workload-files/ --clusterID "west-cluster" --autoregister
    cat /tmp/my-workload-files/hosts
    192.168.10.10 istiod.istio-system.svc
    
    chown ubuntu:ubuntu -R /tmp/my-workload-files/
    tree /tmp/my-workload-files/
    ├── cluster.env
    ├── hosts
    ├── istio-token
    ├── mesh.yaml
    └── root-cert.pem
    • 정말 쉽다! 생성된 설정을 살펴보면 다양한 구성 요소가 동작 중임을 확인할 수 있다. 이 모든 것을 완벽히 이해할 필요는 없다.
    • 그렇지만 이해하고 있다면, 마주칠 문제를 해결하는 데 도움이 될 것이다. 그런 이유로 부록 E에서 이 설정을 자세히 설명한다.
    • 고수준에서 알아야 할 중요한 사실은 파일에 다음이 포함돼 있다는 점이다.
      • east-west 게이트웨이 IP 주소. 여기를 통해 istiod가 노출된다.
        The east-west gateway IP address through which istiod is exposed.
      • 루트 인증서. istiod가 제시한 인증서의 진위를 검증하는 데 사용한다.
        The root certificate to validate the authenticity of the certificate presented by istiod.
        • 인증서 검증은 서비스 프록시와 istiod 사이의 보안 커넥션을 시작하기 전에 수행해야 하는 선행 작업이다. It’s a precursor to initiating a secure connection between the service proxy and istiod.
      • 서비스 어카운트 토큰. istiod에게 forum WorkloadGroup의 구성원임을 인증하는 데 사용한다.
        The service account token to authenticate as a member of the forum WorkloadGroup, to istiod.
      • 서비스 메시. 네트워크, 공통 속성에 대한 설정. WorkloadGroup에 정의된 대로다.
        Configuration about the service mesh, the network, and the common properties, as defined in the WorkloadGroup.

    ☞ 이 설정이 있으면 서비스 프록시는 컨트롤 플레인에 보안 커넥션을 시작하고, 자신의 SVID를 가져오고, xDS로 엔보이 설정을 수신해 메시의 구성원이 될 수 있다. In the presence of this configuration, the service proxy can start a secure connection to the control plane, get its SVID, and receive its Envoy configuration via xDS to become a member of the mesh.


     Step3. 생성된 파일을 가상머신을 전송하기 TRANSFERRING THE GENERATED FILES TO THE VM

    • 설정 파일에는 민감 정보(구체적으로는 서비스 어카운트 토큰)가 포함돼 있으므로 가상머신으로 안전하게 전송해야 한다.
    • 시연을 위해 공수가 제일 적은 방법을 사용해 파일을 SSH를 통해 복사할 것이다.
    • 이 방법은 안전하지만, 운영 환경에서는 당연히 이 과정이 자동화돼 수작업이 필요 없어야 한다.
    # 임시로, 자신의 로컬 PC에 위 파일들 복사 : 바로 vm_ip 에 복사해도 되지만, 현재 실습 환경 편리성으로 경유 복사.
    APP_IP=43.203.195.107   ## k3s-s IP
    mkdir my-workload-files
    scp -i ~/.ssh/kp-gasida.pem ubuntu@$APP_IP:/tmp/my-workload-files/\* ./my-workload-files # macOS
    scp -i ~/.ssh/kp-gasida.pem ubuntu@$APP_IP:/tmp/my-workload-files/*  ./my-workload-files # linux
    
    */ ##
    ls -al
    openssl x509 -in ./my-workload-files/root-cert.pem -noout -text # istio CA 인증서
    jwt decode $(cat ./my-workload-files/istio-token) # 토큰
    ...
    Token claims
    ------------
    {
      "aud": [
        "istio-ca"
      ],
      "exp": 1748083668,
      "iat": 1748080068,
      "iss": "https://kubernetes.default.svc.cluster.local",
      "kubernetes.io": {
        "namespace": "forum-services",
        "serviceaccount": {
          "name": "forum-sa",
          "uid": "64ab40b3-3bad-49f1-a1c9-0464d72c18c1"
        }
      },
      "nbf": 1748080068,
      "sub": "system:serviceaccount:forum-services:forum-sa"
    }
    
    cat ./my-workload-files/mesh.yaml
    defaultConfig:
      discoveryAddress: istiod.istio-system.svc:15012
      meshId: usmesh
      proxyMetadata:
        CANONICAL_REVISION: latest
        CANONICAL_SERVICE: forum
        ISTIO_META_AUTO_REGISTER_GROUP: forum
        ISTIO_META_CLUSTER_ID: west-cluster
        ISTIO_META_DNS_CAPTURE: "true"
        ISTIO_META_MESH_ID: usmesh
        ISTIO_META_NETWORK: vm-network
        ISTIO_META_WORKLOAD_NAME: forum
        ISTIO_METAJSON_LABELS: '{"app":"forum","service.istio.io/canonical-name":"forum","service.istio.io/canonical-revision":"latest"}'
        POD_NAMESPACE: forum-services
        SERVICE_ACCOUNT: forum-sa
        TRUST_DOMAIN: cluster.local
      readinessProbe:
        httpGet:
          path: /api/healthz
          port: 8080
        initialDelaySeconds: 1
        periodSeconds: 5
      tracing:
        zipkin:
          address: zipkin.istio-system:9411
    
    
    # 로컬 PC의 파일들을 forum-vm로 복사
    FORUM=54.180.250.130
    scp -i ~/.ssh/kp-kyukim.pem ./my-workload-files/cluster.env ubuntu@$FORUM:/tmp/
    scp -i ~/.ssh/kp-kyukim.pem ./my-workload-files/istio-token ubuntu@$FORUM:/tmp/
    scp -i ~/.ssh/kp-kyukim.pem ./my-workload-files/mesh.yaml ubuntu@$FORUM:/tmp/
    scp -i ~/.ssh/kp-kyukim.pem ./my-workload-files/root-cert.pem ubuntu@$FORUM:/tmp/
    
    
    # forum-vm 에서 파일 확인
    ls -l /tmp
    -rwxr--r-- 1 ubuntu ubuntu  714 May 24 19:08 cluster.env
    -rwxr--r-- 1 ubuntu ubuntu  844 May 24 19:08 istio-token
    -rwxr--r-- 1 ubuntu ubuntu  792 May 24 19:08 mesh.yaml
    -rwxr--r-- 1 ubuntu ubuntu 1094 May 24 19:08 root-cert.pem
    ...

     

    vm-forum 에 k3s-s 에서 생성한 istio-token 을 복사하였다!!

     

    ☞ 이제 파일이 가상머신으로 복사됐으므로, 사이드카가 서비스 메시에 참가하도록 설치하고 설정할 준비가 됐다!!

    13.3.3 가상머신에 istio-agent 설치 및 설정하기* Installing and configuring the istio-agent in the VM

    더보기

    Step1. forum-vm 가상머신에 istio-agent 를 다운로드하고 설치하자

    #
    cat /etc/resolv.conf
    nameserver 127.0.0.53
    ...
    
    ss -tnlp
    State      Recv-Q     Send-Q         Local Address:Port         Peer Address:Port    Process
    LISTEN     0          4096           127.0.0.53%lo:53                0.0.0.0:*        users:(("systemd-resolve",pid=357,fd=14))
    
    ss -unlp
    State     Recv-Q    Send-Q           Local Address:Port         Peer Address:Port    Process
    UNCONN    0         0                127.0.0.53%lo:53                0.0.0.0:*        users:(("systemd-resolve",pid=357,fd=13))
    
    resolvectl status
    ...
    resolv.conf mode: stub # stub 모드로 설정, 127.0.0.53(local stub resolver)을 가리키며, systemd-resolved가 이 요청을 처리함
    
    Link 2 (ens5)
        Current Scopes: DNS
             Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
    Current DNS Server: 192.168.0.2
    ...
    
    #
    iptables -t nat -L -n -v
    iptables -t filter -L -n -v
    iptables -t mangle -L -n -v
    iptables -t raw -L -n -v
    
    
    # 데비안 패키지 형식으로 다운로드 후 설치
    curl -LO https://storage.googleapis.com/istio-release/releases/1.17.8/deb/istio-sidecar.deb
    file istio-sidecar.deb
    dpkg -i istio-sidecar.deb
    which pilot-agent
    pilot-agent version
    which envoy
    envoy --version
    
    tree /etc/istio
    /etc/istio
    ├── config
    │   └── mesh
    ├── envoy
    │   ├── cluster.env
    │   ├── envoy_bootstrap_tmpl.json
    │   └── sidecar.env
    ├── extensions
    │   ├── metadata-exchange-filter.compiled.wasm
    │   ├── metadata-exchange-filter.wasm
    │   ├── stats-filter.compiled.wasm
    │   └── stats-filter.wasm
    └── proxy
    
    tree /var/lib/istio/
    /var/lib/istio/
    ├── config
    │   └── mesh
    ├── envoy
    │   ├── envoy_bootstrap_tmpl.json
    │   └── sidecar.env
    ├── extensions
    │   ├── metadata-exchange-filter.compiled.wasm
    │   ├── metadata-exchange-filter.wasm
    │   ├── stats-filter.compiled.wasm
    │   └── stats-filter.wasm
    └── proxy
    
    # istio-agent 는 특정 위치에서 설정 파일을 읽으므로, 복사해둔 파일을 옮겨보자
    mkdir -p /etc/certs
    mkdir -p /var/run/secrets/tokens
    
    cp /tmp/root-cert.pem /etc/certs/root-cert.pem
    cp /tmp/istio-token /var/run/secrets/tokens/istio-token
    cp /tmp/cluster.env /var/lib/istio/envoy/cluster.env
    cp /tmp/mesh.yaml /etc/istio/config/mesh
    
    
    # istiod.istio-system.svc 요청을 istiod 인스턴스로 프록시하는 east-weat 게이트웨이 IP 주소로 정적으로 해석하도록 한다.
    cat /etc/hosts
    echo "192.168.10.10 istiod.istio-system.svc" | sudo sh -c 'cat >> /etc/hosts'
    cat /etc/hosts
    
    # istio-agent가 호스트네임 해석을 방해하지 않도록 hosts 파일에 forum-vm 머신의 호스트네임을 하드코딩하자 : 설정되어 있음
    echo "$(hostname --all-ip-addresses | cut -d ' ' -f 1) $(hostname)" | sudo sh -c 'cat >> /etc/hosts'
    cat /etc/hosts

     

     

     

    • DNS 프록시가 클러스터 내 호스트네임을 해석해야 하는 것 아닌가? Shouldn’t the DNS proxy resolve the in-cluster hostnames?
      • 그렇다. 하지만 이 시점에서 사이드카가 아직 컨트롤 플레인에 연결되지 않았다면 파일럿이 알고 있는 DNS 항목이 없을 것이다.
      • 또한 /etc/hosts 에 east-west 게이트웨이 호스트네임을 정적으로 정의하는 것이 독자의 환경에 적합하지 않다면, east-west 게이트웨이를 가리키는 네트워크 로드 밸런서를 설치할 수 있다.
      • 네트워크 로드 밸런서를 설정하고 노출하는 방법은 자신의 클라우드 혹은 온프레미스 환경에 따라 참조하길 바란다.

    Step2.  에이전트를 시작하기 전 마지막 단계로 에이전트가 읽고 쓸 디렉터리에 소유자 권한을 부여하는 것이다.

    #
    cat /etc/passwd | tail -n 3
    ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
    lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
    istio-proxy:x:998:999::/var/lib/istio:/bin/sh
    
    tree /etc/istio
    chown -R istio-proxy /var/lib/istio /etc/certs /etc/istio/proxy /etc/istio/config /var/run/secrets /etc/certs/root-cert.pem
    
    #
    systemctl status istio
    systemctl start istio
    systemctl enable istio
    systemctl status istio
    ...
         CGroup: /system.slice/istio.service
                 ├─32047 sudo -E -u istio-proxy -s /bin/bash -c "ulimit -n 1024; INSTANCE_IP=15.165.15.104 POD_NAME=testpc POD_NAMESPACE=forum-services >
                 ├─32140 /usr/local/bin/pilot-agent proxy
                 └─32148 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drain-strategy immediate --local-address-ip-version >
    
    May 24 20:10:05 testpc istio-start.sh[32128]: -A ISTIO_OUTPUT -o lo -p tcp -m tcp ! --dport 53 -m owner ! --gid-owner 998 -j RETURN
    May 24 20:10:05 testpc istio-start.sh[32128]: -A ISTIO_OUTPUT -m owner --gid-owner 998 -j RETURN
    May 24 20:10:05 testpc istio-start.sh[32128]: -A ISTIO_OUTPUT -d 127.0.0.53/3cat 2 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 15053
    May 24 20:10:05 testpc istio-start.sh[32128]: -A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
    May 24 20:10:05 testpc istio-start.sh[32128]: -A ISTIO_OUTPUT -j ISTIO_REDIRECT
    May 24 20:10:05 testpc istio-start.sh[32128]: -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
    May 24 20:10:05 testpc istio-start.sh[32128]: COMMIT
    May 24 20:10:05 testpc istio-start.sh[32128]: # Completed on Sat May 24 20:10:05 2025
    May 24 20:10:05 testpc sudo[32047]:     root : PWD=/ ; USER=istio-proxy ; COMMAND=/bin/bash -c '\\/bin\\/bash -c ulimit\\ -n\\ 1024\\;\\ INSTANCE_IP>
    May 24 20:10:05 testpc sudo[32047]: pam_unix(sudo:session): session opened for user istio-proxy(uid=998) by (uid=0)
    ...
    ## 혹은
    journalctl -u istio -f
    ...
    
    which istio-start.sh
    cat /usr/local/bin/istio-start.sh
    
    
    #
    tree /etc/certs/
    ├── cert-chain.pem
    ├── key.pem
    └── root-cert.pem
    
    #
    ps aux |grep istio
    
    #
    iptables -t nat -L -n -v
    iptables -t filter -L -n -v
    iptables -t mangle -L -n -v
    iptables -t raw -L -n -v

     


    Step3. 에이전트 로그 확인하기 CHECKING THE AGENT LOGS  

    • 이스티오의 에이전트 로그는 다음 두 위치에 기록된다.
      • standard output 표준 출력 채널은 /var/log/istio/istio.log 파일에 쓰여진다
      • standard error 표준 오류 채널은 /var/log/istio/istio.err 파일에 쓰여진다
    • 표준 출력 로그를 확인하면 이스티오 컨트롤 플레인으로의 연결이 성공했는지 알 수 있다
    #
    cat /var/log/istio/istio.log | grep xdsproxy
    2025-05-25T01:09:42.094214Z	info	xdsproxy	Initializing with upstream address "istiod.istio-system.svc:15012" and cluster "west-cluster"
    2025-05-25T01:09:42.227661Z	info	xdsproxy	connected to upstream XDS server: istiod.istio-system.svc:15012
    
    # 만약 로그 파일이 생성되지 않았다면? 서비스 시작이 실패한 경우에 그럴 수 있다. 아래 처럼 systemd 로그를 확인하자
    journalctl -u istio -f

    Step4. 워크로드가 메시에 등록됐는지 확인하기 VERIFYING THAT THE WORKLOAD REGISTERED TO THE MESH

     

    • 워크로드 자동 등록이 활성화돼 있으면, 머신의 istio-agent 가 istiod 에 연결되자마자 WorkloadEntry 가 생성된다.
    #
    kubectl get workloadentries -n forum-services
    NAME                              AGE    ADDRESS
    forum-192.168.10.200-vm-network   110m   192.168.10.200
    
    kc get workloadentries -n forum-services -o yaml
    ...
      status:
        conditions:
        - lastProbeTime: "2025-05-25T02:35:47.436392452Z"
          lastTransitionTime: "2025-05-25T02:35:47.436392780Z"
          message: 'Get "http://192.168.10.200:8080/api/healthz": dial tcp 127.0.0.6:0->192.168.10.200:8080:
            connect: connection refused'
          status: "False"
          type: Healthy
    ...
    
    istioctl proxy-status
    NAME                                                    CLUSTER          CDS        LDS        EDS        RDS          ECDS         ISTIOD                     VERSION
    forum-vm.forum-services                                 west-cluster     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-d6549b9fc-rpg7l     1.17.0
    webapp-684c568c59-9wtbt.istioinaction                   west-cluster     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-d6549b9fc-rpg7l     1.17.8
    ...
    • 예상대로 가상머신의 WorkloadEntry 가 등록됐음을 확인할 수 있다. 또한 커넥션을 맺을 수 있는 주소도 표시된다.
    • 이것들은 이 항목이 나타내는 가상머신만의 고유한 속성이다.
    • 다음으로는 트래픽이 어떻게 클러스터 내 서비스로 라우팅되는지(그리고 그 반대도)를 살펴보자.

    13.3.4 클러스터 서비스로 트래픽 라우팅하기 Routing traffic to cluster services

    더보기

    Step1. 트래픽이 클러스터 서비스로 라우팅되는지 확인하기 위해 가상머신에서 webapp 워크로드로 curl 요청을 보내보자

    # 신규 터미널 : 패킷 모니터링 https://github.com/gcla/termshark/blob/master/docs/UserGuide.md
    tcpdump -i any -w - udp port 53 | termshark
    ## CTRL+C 로 취소 후 수집된 패킷이 termshark 에서 확인 가능
    
    # testpc : 도메인 해석은 잘 됨
    dig +short webapp.istioinaction
    10.10.200.48
    
    curl -s webapp.istioinaction/api/catalog/items/1 | jq
    watch curl -s webapp.istioinaction/api/catalog/items/1
    
    # 신규 터미널 : 15443 연결하는 envoy 프로세스(데이터 플래인) 확인!
    watch -d ss -tnp 
    watch -d 'ss -tnp | grep envoy'
    State     Recv-Q  Send-Q   Local Address:Port     Peer Address:Port  Process                                                   
    ESTAB 0      0      192.168.10.200:41238 192.168.10.10:15443 users:(("envoy",pid=3203,fd=40))
    ESTAB 0      0      192.168.10.200:41242 192.168.10.10:15443 users:(("envoy",pid=3203,fd=41))
    ...
    
    # 신규 터미널 : 
    watch -d iptables -t nat -L -n -v
    watch -d iptables -t raw -L -n -v
    
    
    # k3s-s
    kubectl get svc,ep -n istioinaction webapp
    NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    service/webapp   ClusterIP   10.10.200.48   <none>        80/TCP    148m
    
    NAME               ENDPOINTS         AGE
    endpoints/webapp   172.16.0.8:8080   148m

     

    [ service 호출에 대해 중간에 질의 해석을 가로채서 진행함을 볼 수 있다!! ]

     

     

    dataplane service flow 와 해당 구간의 데이터 처리 확인 (mTLS)

     


    • 가상머신에서 요청한 트래픽이 클러스터 서비스에 도달하는 과정
    1. 트래픽이 애플리케이션을 떠나려면 먼저 그 호스트네임을 해석해야 한다. 즉, DNS 쿼리가 DNS 프록시로 리다이렉트돼야 한다.
    2. 이름이 IP 주소로 해석되면 애플리케이션은 아웃바운드 요청을 시작할 수 있다. 이 요청은 Iptables 규칙이 엔보이 프록시로 리다이렉트한다.
    3. 엔보이 프록시는 트래픽을 east-west 게이트웨이로 라우팅한다.
    4. east-west 게이트웨이는 요청을 webapp 으로 프록시하고, webapp은 catalog 서비스에 아이템을 쿼리한다.
    • 이 과정을 고수준에서 살펴보면 ‘DNS 프록시는 어떻게 설정되는가?’와 ‘애플리케이션은 DNS 프록시와 어떻게 상호작용하는가?’ 같은 질문에 답할 수 있으며, 트래픽을 가상머신 워크로드에서 클러스터 서비스로 라우팅하는 전체 과정과 어떻게 연관되는지 이해할 수 있다.
    • 서비스 메시 사용자로서는 이만하면 충분하지만, 궁금하다면 13.4절에서 자세한 정보를 찾아볼 수 있다.

    (옵션) 자신의 PC에서 webapp 반복 접속 후 확인  

    while true; do curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/catalog/ ; echo; date; sleep 1; done

     

     

    13.3.5 트래픽을 WorkloadEntry로 라우팅하기 Routing traffic to the WorkloadEntry

    더보기
    • 앞 절에서는 머신에서 클러스터 내부/메시 내부 서비스로의 라우팅을 확인해봤다. 이제 그 반대로 라우팅하는 것을 확인해보자.
    • 즉, 클러스터 안에서 가상머신 워크로드로 라우팅할 것이다.
    • 가상머신에서 실행 중인 서비스로 도달하려면 어떻게 요청을 보내야 할까? WorkloadEntry에서 본 IP 주소를 써야 할까? 당연히 아니다.
    • 쿠버네티스에서 파드의 IP 주소를 사용하지 않는 것처럼, 플랫폼을 유연하게 유지하고 인스턴스를 교체할 수 있게 하기 위함이다.

     

    • 앞서 간단히 언급했듯이 쿠버네티스 서비스를 만들어야 한다.
    • 쿠버네티스 서비스는 인스턴스를 레이블로 고르며, 이스티오가 모든 서비스를 올바른 IP 주소로 동적으로 설정할 수 있다.
    • 예를 들어 forum WorkloadEntry를 고르려면 다음과 같은 쿠버네티스 서비스를 사용한다.

    Step1. 특정 서비스 WorkloadEntry를 선택하도록 Kubernetes Service를 만들자!!

    #
    cat istio-in-action/book-source-code-master/services/forum/kubernetes/forum-svc.yaml
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: forum
      name: forum
    spec:
      ports:
      - name: http
        port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: forum
    
    kubectl apply -f istio-in-action/book-source-code-master/services/forum/kubernetes/forum-svc.yaml -n forum-services
    
    kubectl get svc,ep -n forum-services
    NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    service/forum   ClusterIP   10.10.200.72   <none>        80/TCP    20s
    
    NAME              ENDPOINTS   AGE
    endpoints/forum   <none>      20s
    
    #
    istioctl proxy-config route deploy/webapp.istioinaction
    istioctl proxy-config route deploy/webapp.istioinaction --name 80 -o json
    ...
          "name": "forum.forum-services.svc.cluster.local:80",
          "domains": [
              "forum.forum-services.svc.cluster.local",
              "forum.forum-services",
              "forum.forum-services.svc",
              "10.10.200.72"
          ],
          "routes": [
              {
                  "name": "default",
                  "match": {
                      "prefix": "/"
                  },
                  "route": {
                      "cluster": "outbound|80||forum.forum-services.svc.cluster.local",
    ...
    
    #
    istioctl proxy-config cluster deploy/webapp.istioinaction
    istioctl proxy-config cluster deploy/webapp.istioinaction --fqdn forum.forum-services.svc.cluster.local -o json
    istioctl proxy-config cluster deploy/webapp.istioinaction --fqdn forum.forum-services.svc.cluster.local
    SERVICE FQDN                               PORT     SUBSET     DIRECTION     TYPE     DESTINATION RULE
    forum.forum-services.svc.cluster.local     80       -          outbound      EDS   
    
    # 아직 없다!
    istioctl proxy-config endpoint deploy/webapp.istioinaction
    istioctl proxy-config endpoint deploy/webapp.istioinaction | grep forum
    
    #
    istioctl proxy-config listener deploy/istio-eastwestgateway.istio-system
    istioctl proxy-config route deploy/istio-eastwestgateway.istio-system
    istioctl proxy-config cluster deploy/istio-eastwestgateway.istio-system
    istioctl proxy-config endpoint deploy/istio-eastwestgateway.istio-system
    istioctl proxy-config endpoint deploy/istio-eastwestgateway.istio-system | grep forum

     

     

    forum-services 네임스페이스에 서비스 관련 된 POD가 없어서 조회가 안되는 듯 ...

     


    Step2. forum-vm 의 envoy config 확인 - Docs  

    # [testpc] 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 -
    cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
    
    #
    curl -s localhost:15000/config_dump | istioctl proxy-config listener --file -
    curl -s localhost:15000/config_dump | istioctl proxy-config route --file -
    curl -s localhost:15000/config_dump | istioctl proxy-config clusters --file -
    curl -s localhost:15000/config_dump | istioctl proxy-config endpoint --file -
    curl -s localhost:15000/config_dump | istioctl proxy-config secret --file -
    RESOURCE NAME     TYPE           STATUS     VALID CERT     SERIAL NUMBER                               NOT AFTER                NOT BEFORE
    default           Cert Chain     ACTIVE     true           310309461583688467984066399721764000962     2025-05-26T01:09:42Z     2025-05-25T01:07:42Z
    ROOTCA            CA             ACTIVE     true           46141372426695670978289547947687101983      2035-05-23T01:04:09Z     2025-05-25T01:04:09Z

     


    • 서비스가 만들어지면 WorkloadEntry 엔드포인트가 선택되고, 이를 사용해 istiod가 데이터 플레인을 설정한다.

    Step3. forum 서비스 요청 시도를 해보자

    #
    istioctl proxy-config cluster deploy/webapp.istioinaction --fqdn forum.forum-services.svc.cluster.local
    istioctl proxy-config endpoint deploy/webapp.istioinaction | grep forum
    
    # 로그 모니터링
    kubectl logs -n istioinaction deploy/webapp -c istio-proxy -f
    [2025-05-25T04:53:18.841Z] "GET /api/users HTTP/1.1" 503 UH no_healthy_upstream - "-" 0 19 0 - "" "beegoServer" "63377970-9d0f-4591-a4d4-039b4321863d" "forum.forum-services:80" "-" outbound|80||forum.forum-services.svc.cluster.local - 10.10.200.72:80 :0 - default
    [2025-05-25T04:53:18.839Z] "GET /api/users HTTP/1.1" 500 - via_upstream - "-" 0 27 2 2 "" "curl/8.7.1" "63377970-9d0f-4591-a4d4-039b4321863d" "webapp.istioinaction.io" "172.16.0.8:8080" inbound|8080|| 127.0.0.6:36439 172.16.0.8:8080 :0 outbound_.80_._.webapp.istioinaction.svc.cluster.local default
    
    # 자신의 PC
    curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/catalog/
    while true; do curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/catalog/ ; echo; date; sleep 1; done
    
    curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/users
    curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/users -I
    HTTP/1.1 500 Internal Server Error

     

     

    • UH 응답 플래그는 ‘정상 업스트림 없음’으로, 클러스터에 트래픽을 라우팅할 수 있는 정상 엔드포인트가 없을 경우에만 나타난다.
    • webapp 에는 forum 서비스의 엔드포인프가 없다는 뜻이다.

    Step4. forum 워크로드 상태 확인하기 VERIFYING THE HEALTH OF THE FORUM WORKLOAD

    • WorkloadEntry 의 상태, 좀 더 정확히는 트래픽을 수신할 준비 상태 readiness 를 확인해보자
    #
    kc get workloadentries -n forum-services -o yaml
    ...
      status:
        conditions:
        - lastProbeTime: "2025-05-25T04:34:59.371581082Z"
          lastTransitionTime: "2025-05-25T04:34:59.371581355Z"
          message: 'Get "http://192.168.10.200:8080/api/healthz": dial tcp 127.0.0.6:0->192.168.10.200:8080:
            connect: connection refused' 
          status: "False" # 헬스체크가 실패하여, 워크로드가 비정상 상태임
          type: Healthy
    ...
    
    # testpc : 아직 8080 서비스가 실행되지 않았다!
    ss -tnlp | grep 8080

    Step5. 가상머신에서 forum 애플리케이션 시작하기 STARTING THE FORUM APPLICATION IN THE VM  

     

    • forum 바이러니를 다운로드하고, 권한을 주고, 8080 포트에서 트래픽을 수신하도록 실행하자.
    # testpc
    wget -O forum https://git.io/J3QrT
    file forum
    chmod +x forum
    ./forum
    
    # testpc
    curl http://localhost:8080/api/healthz -v
    
    ss -tnlp | grep 8080
    LISTEN 0      4096               *:8080             *:*    users:(("forum",pid=15081,fd=3))
    
    # k8s-s
    istioctl proxy-config cluster deploy/webapp.istioinaction --fqdn forum.forum-services.svc.cluster.local
    istioctl proxy-config endpoint deploy/webapp.istioinaction --cluster 'outbound|80||forum.forum-services.svc.cluster.local' -o json
    istioctl proxy-config endpoint deploy/webapp.istioinaction --cluster 'outbound|80||forum.forum-services.svc.cluster.local'
    ENDPOINT                STATUS      OUTLIER CHECK     CLUSTER
    192.168.10.200:8080     HEALTHY     OK                outbound|80||forum.forum-services.svc.cluster.local
    
    #
    kc get workloadentries -n forum-services -o yaml
    ...
      status:
        conditions:
        - lastProbeTime: "2025-05-25T05:02:23.116408430Z"
          lastTransitionTime: "2025-05-25T05:02:23.116409282Z"
          status: "True"
          type: Healthy
    ...

     

     

    다시 요청해 보자!!

    # 자신의 PC
    curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/users
    while true; do curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/users ; echo; date; sleep 1; done
    
    # 로그 모니터링
    kubectl logs -n istioinaction deploy/webapp -c istio-proxy -f
    [2025-05-25T05:05:51.328Z] "GET /api/users HTTP/1.1" 200 - via_upstream - "-" 0 5645 28 27 "218.153.65.54" "beegoServer" "888f982d-f7f3-4232-ac0b-826cf65ef294" "forum.forum-services:80" "192.168.10.200:8080" outbound|80||forum.forum-services.svc.cluster.local 172.16.0.8:38170 10.10.200.72:80 218.153.65.54:0 - default
    [2025-05-25T05:05:51.326Z] "GET /api/users HTTP/1.1" 200 - via_upstream - "-" 0 3679 30 30 "218.153.65.54" "curl/8.7.1" "888f982d-f7f3-4232-ac0b-826cf65ef294" "webapp.istioinaction.io" "172.16.0.8:8080" inbound|8080|| 127.0.0.6:36439 172.16.0.8:8080 218.153.65.54:0 outbound_.80_._.webapp.istioinaction.svc.cluster.local default

     

     

    • 이렇게 클러스터 서비스에서 WorkloadEntry 로의 트래픽 흐름을 검증했다.
    • 또한 이스티오가 어떻게 트래픽을 받을 준비가 되지 않은 워크로드로 트래픽을 보내지 않는지도 보여줬다.
    • 단순히 데이터 플레인에 그 엔드포인트를 설정하지 않는 것이다.
    • 이 예제에서는 그 이점이 잘 드러나지 않았을 수도 있지만, 운영 환경 클러스터에서는 이런 방식이 클라이언트가 오류를 반환하는 인스턴스로 트래픽을 보내는 것을 방지하고 그 대신에 정상 인스턴스만 라우팅하게 된다.

    13.3.6 컨트롤 플레인이 가상머신 설정: 상호 인증 강제  VMs are configured by the control plane: Enforcing mutual authentication

    더보기
    • 가상머신이 메시에 통합돼 사이드카 프록시가 네트워크 트래픽을 관리하므로, 이스티오의 풍부한 기능을 가상머신에 적용할 수 있다.
    • 이를 시연하기 위해, 트래픽 상호 인증을 강제하는 PeerAuthentication 을 만들어 보안을 강화해보자
    • 지금은 가상머신의 8080 포트를 노출해뒀기 때문에 연결할 수 있은 사람은 누구나 요청을 처리할 수 있다. 누구나, 심지어 권한이 없는 사용자도!
    • 메시에 통합되지 않은 로컬 컴퓨터에서 가상머신으로 요청을 보내 이를 확인해볼 수 있다.
    # 자신의 PC에서 요청
    curl -is $FORUM:8080/api/users | grep HTTP
    HTTP/1.1 200 OK
    • 요청이 처리됐다. 예상한 바이지만, 앞으로는 금지할 것이다.
    • 그러기 위해 메시에 상호 인증 트래픽만 처리하는 메시 범위 정책을 설정할 것이고, 그 결과로 서비스를 무단 접근으로부터 보호할 것이다.
    #
    cat istio-in-action/book-source-code-master/ch13/strict-peer-auth.yaml
    apiVersion: security.istio.io/v1beta1
    kind: PeerAuthentication
    metadata:
      name: default
      namespace: istio-system
    spec:
      mtls:
        mode: STRICT
    
    kubectl apply -f istio-in-action/book-source-code-master/ch13/strict-peer-auth.yaml
    kubectl get peerauthentication -A
    • 정책이 데이터 플레인에 배포될 때까지 잠시 기다리자. 그런 다음, 상호 인증되지 않은 트래픽이 금지됐는지 확인한다.
    # 자신의 PC에서 요청
    curl -is $FORUM:8080/api/users -v
    
    # istio-ingressgateway 경유 요청 
    while true; do curl -s -H "Host: webapp.istioinaction.io" http://$APP_IP:30000/api/users ; echo; date; sleep 1; done

     

    • 출력을 보면 webapp의 요청이 처리됐는데, 이는 가상머신이 컨트롤 플레인이 적용한 설정을 준수함을 보여준다.
    • PeerAuthentication 정책은 하나의 예시일 뿐이다. 비슷하게 모든 이스티오 API를 사용해 가상머신의 프록시를 설정할 수 있다.

    13.4 DNS 프록시 이해하기 Demystifying the DNS proxy

    ☞ DNS 프록시는 이스티오 사이드카의 새 구성 요소로, 이 절의 목표는 DNS 프록시가 클러스터 내 서비스의 호스트네임을 해석하는 방법을 이해시키는 것이다.

     

    13.4.1 DNS 프록시가 클러스터 호스트네임을 해석하는 방법 How the DNS proxy resolves cluster hostnames (실습~)

    [ webapp.istioinaction 호스트네임이 해석되는 구체적인 과정 ]

    더보기
    클러스터 서비스 호스트네임 해석의 흐름
    1. 클라이언트는 webapp.istioinaction 을 해석하기 위해 DNS 쿼리를 만든다
    2. 운영체제가 DNS 해석을 처리한다. 운영체제는 먼저 hosts 파일에 정의된 항목 중에 호스트네임과 일치하는 것이 있는지 확인한다.
      • 일치하는 항목이 없으면 요청을 기본 DNS 해석기 resolver 로 전달한다.
    3. 우분투기본 DNS 해석기는 systemd-resolverd(로컬 애플리케이션에 호스트네임 해석을 제공하는 시스템 서비스)이며, 루프백 주소 127.0.0.53에서 53 포트를 리스닝한다.
      • 그러나 요청은 절대로 거기에 도달하지 않는데, 요청을 DNS 프록시로 리다이렉트하도록 istio-agent 가 Iptables 규칙을 설정하기 때문이다.
    4. DNS 프록시에는 서비스 메시 내에서 알려진 서비스를 해석하기 위한 항목들이 포함돼 있다.
      • 호스트네임이 일치하면 해석되며, webapp.istioinaction이 그런 경우다.
      • 컨트롤 플레인이 NDS로 설정하기 때문이다.
    5. 그렇지 않고 클러스터 서비스가 아니면 DNS 프록시가 물러나 resolv.conf 파일에 명시된 네임서버로 넘기며, 호스트네임은 여기서 해석되거나 해석하는 데 실패한다.

    [ 단계별 검증 ]

     

    Step1. systemd-resolverd(127.0.0.53 에서 수신 중인)로 향하는 DNS 퀴리를 Iptables 규칙이 로컬호스트의 포트 15053에서 UDP 및 TCP 패킷을 수신 중인 DNS 프록시로 리다이렉트하는 것부터 확인해보자.

    # [forum-vm]
    # Iptables 규칙 확인 : proxyConfig.proxyMetadata ISTIO_META_DNS_CAPTURE="true" 설정 시 아래 규칙 추가됨
    iptables-save | grep 'to-ports 15053'
    -A OUTPUT -d 127.0.0.53/32 -p udp -m udp --dport 53 -j REDIRECT --to-ports 15053
    -A ISTIO_OUTPUT -d 127.0.0.53/32 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 15053

     

    Step2. DNS 퀴리 트래픽이 DNS 프록시 포트로 리다이렉트되는 것을 볼 수 있다. 포트 정보 확인하자.  

    # tcp, udp 를 127.0.0.1 에 port 15053 에서 이스티오 에이전트(pilot-agent)가 DNS 프록시 처리 확인
    netstat -ltunp | egrep 'PID|15053'
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 127.0.0.1:15053         0.0.0.0:*               LISTEN      3195/pilot-agent
    udp        0      0 127.0.0.1:15053         0.0.0.0:*                           3195/pilot-agent
    
    # 해당 주소로 DNS 쿼리해보자
    dig +short @localhost -p 15053 webapp.istioinaction
    10.10.200.48
    
    dig +short @localhost -p 15053 catalog.istioinaction
    dig +short @localhost -p 15053 forum.forum-services
    
    
    # (옵션)
    dig +short @localhost -p 15053 www.daum.net
    daum-4vdtymgd.kgslb.com.
    121.53.105.193
    
    
    # (옵션) coredns 쿼리 로그 확인
    KUBE_EDITOR="nano" kubectl edit cm -n kube-system coredns
    apiVersion: v1
    data:
      Corefile: |
        .:53 {
            log
            errors
            health
    ...
    
    # 설정 반영되는데 다소 시간 소요
    kubectl logs -n kube-system -l k8s-app=kube-dns -f

     

    • 예상대로 15053 포트에서 수신 중인 pilot-agent 가 FQDN 을 해석한다. 우리 예제는 요청을 해석하기 위해 DNS 서버를 직접 지정했는데, 그럴 필요가 없다.
    • 애플리케이션이 호스트네임을 해석할 때는 Iptable 규칙에 따라 요청이 자동으로 이 포트로 리다이렉트된다.
    • 다음으로는 컨트롤 플레인이 DNS 프록시에 어떤 항목을 설정했는지 알아보자.

     

     

     

     

    13.4.2 DNS 프록시가 인식하는 호스트네임은 무엇인가? Which hostnames is the DNS proxy aware of?

    더보기
    • DNS 프록시가 인식하는 항목을 모두 찾으려면 istiod의 디버그 엔드포인트를 사용해야 한다.
    • 디버그 엔드포인트를 사용하면 모든 워크로드의 사이드카에 대한 NDS 설정을 쿼리할 수 있다.
    • 우리가 관심 있는 워크로드 이름인 forum-vm 부터 선택해보자.
    #
    istioctl proxy-status | awk '{print $1}'
    catalog-77fdb4997c-f8qj4.istioinaction
    istio-eastwestgateway-86f6cb4699-4xfsn.istio-system
    istio-ingressgateway-7b7ccd6454-pv8zp.istio-system
    forum-vm.forum-services
    webapp-684c568c59-vrj97.istioinaction
    
    # NDS 설정을 가져올 때 proxyID 파라미터에 이름을 사용한다.
    kubectl -n istio-system exec deploy/istiod -- curl -Ls "localhost:8080/debug/ndsz?proxyID=forum-vm.forum-services" | jq
    {
      "resource": {
        "@type": "type.googleapis.com/istio.networking.nds.v1.NameTable",
        "table": {
          "catalog.istioinaction.svc.cluster.local": {
            "ips": [
              "10.10.200.138"
            ],
            "registry": "Kubernetes",
            "shortname": "catalog",
            "namespace": "istioinaction"
          },
          "forum.forum-services.svc.cluster.local": {
            "ips": [
              "10.10.200.72"
            ],
            "registry": "Kubernetes",
            "shortname": "forum",
            "namespace": "forum-services"
          },
          "webapp.istioinaction.svc.cluster.local": {
            "ips": [
              "10.10.200.48"
            ],
            "registry": "Kubernetes",
            "shortname": "webapp",
            "namespace": "istioinaction"
          },
    ...

     

    • 요약된 출력은 webapp 서비스를 보여주는데, webapp.istioinaction.svc.cluster.local 라는 이름에 매핑된 IP 주소 목록을 포함하고 있다.
    • 출력을 살펴보면 webapp.istioinaction 같은 짧은 변형 variation 없다는 것을 확인할 수 있다. 그럼 어떻게 해석이 작동했는가?
    • 아주 간단한다. istio-agent 가 NDS 설정을 받을 때, 다음과 같이 쿠버네티스 클러스터에서 설정될 모든 변형을 만들어낸다.
      • webapp.istioinaction
      • webapp.istioinaction.svc
      • webapp.istioinaction.svc.cluster
    • 그리고 모두 동일한 IP 목록 주소, 즉, 앞 선 목록에서 봤던 10.10.200.48로 해석된다.
    #
    istioctl proxy-config route deploy/webapp.istioinaction --name 80 -o json
    ...
                    "name": "webapp.istioinaction.svc.cluster.local:80",
                    "domains": [
                        "webapp.istioinaction.svc.cluster.local",
                        "webapp",
                        "webapp.istioinaction.svc",
                        "webapp.istioinaction",
                        "10.10.200.48"
    ...

     

    • 핵심은 다음과 같다.
      • DNS 프록시는 istiod가 알고 있는 서비스들로 설정된다.
      • istio-agent는 호스트네임의 더 짧은 변형들을 생성한다 (쿠버네티스 내의 경험과 일치시키기 위함이다)
      • 이런 DNS 프록시 내의 레코드는 클러스터 내 서비스 호스트네임을 해석하는 데 사용된다.
      • 클러스터가 아닌 호스트네임(퍼블릭 도메인 같은)쿼리는 머신에서 처음 설정한 네임서버로 넘어간다.

     

    13.5 에이전트 동작 커스터마이징하기 Customizing the agent’s behavior

    더보기
    • 에이전트는 로그 내용, 로그 형식, 에이전트가 인증서를 발급받기 위해 요청할 인증서 수명 설정 같은 동작 등 다양한 설정 선택지가 있다.
    • 예를 들어 두 가지 수정을 하길 원한다고 해보자.
      • DNS 프록시의 로깅 수준을 debug로 올린다.
      • 인증서 수명을 12시간으로 줄인다.
    • 사이드카용 설정 파일인 /var/lib/istio/envoy/sidecar.env 를 업데이트하면 된다.
    #
    cat /var/lib/istio/envoy/sidecar.env
    grep "^[^#]" /var/lib/istio/envoy/sidecar.env # 주석 처리
    
    #
    echo 'ISTIO_AGENT_FLAGS="--log_output_level=dns:debug"' >> /var/lib/istio/envoy/sidecar.env
    echo 'SECRET_TTL="12h0m0s"' >> /var/lib/istio/envoy/sidecar.env
    grep "^[^#]" /var/lib/istio/envoy/sidecar.env # 주석 처리
    ISTIO_AGENT_FLAGS="--log_output_level=dns:debug"
    SECRET_TTL="12h0m0s"
    
    # 변경 사항 적용
    systemctl restart istio
    
    
    # www.daum.net 도메인은 질의 처리를 하지 못해서, 로컬에 resolver DNS 서버를 통해 질의 로그 확인.
    tail -f /var/log/istio/istio.log
    2025-05-25T07:23:03.660035Z	debug	dns	response for hostname "www.daum.net." not found in dns proxy, querying upstream
    2025-05-25T07:23:03.662845Z	debug	dns	upstream response for hostname "www.daum.net." : ;; opcode: QUERY, status: NOERROR, id: 30399
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version 0; flags: ; udp: 65494
    
    ;; QUESTION SECTION:
    ;www.daum.net.	IN	 A
    
    ;; ANSWER SECTION:
    www.daum.net.	77	IN	CNAME	daum-4vdtymgd.kgslb.com.
    daum-4vdtymgd.kgslb.com.	5	IN	A	121.53.105.193
    
    #
    dig +short @localhost -p 15053 www.daum.net

     

    • DNS 프록시에 대한 디버그 로그를 볼 수 있다.
    • 인증서가 로테이션되면 /etc/certs/cert-chain.pem 파일에 저장된 새 인증서의 만료 시간을 검사할 수도 있다.
    • 모든 설정 옵션 목록은 이스티오의 pilot-agent 문서를 참조하자 - Docs

    13.6 메시에서 WorkloadEntry 제거하기 Removing a WorkloadEntry from the mesh & 13장 내용 정리

    더보기
    • 가상머신이 메시에 자동 등록되던 것처럼, 삭제되면 정리된다. 시도해보자.
      • AWS 가상머신용 EC2 를 삭제하자 → 시간이 조금 지난 후, WorkloadEntry 가 정리됐는지 확인하자.
    #
    watch kubectl get workloadentries -A
    kubectl get workloadentries -A
    No resources found

     

    클라우드 네이티브 워크로드의 일시성을 지원하려면 워크로드 항목을 자동으로 정리(삭제)하는 것이 자동 등록만큼 중요하다.


    기능
    쿠버네티스 구현
    가상머신 구현
    프록시 설치
    istioctl로 직접 주입하거나 웹훅으로 자동 주입
    직접 다운로드해 설치
    프록시 설정
    사이드카 주입 중 완료
    istioctl을 사용해 WorkloadGroup에서 설정을 생성하고 프록시가 있는 가상머신으로 전송
    워크로드 ID 부트스트랩
    서비스 어카운트 토큰이 쿠버네티스 메커니즘에 의해 주입
    서비스 어카운트 토큰을 가상머신으로 수작업으로 전송
    헬스 체크
    쿠버네티스가 Readiness / Liveness 프로브 수행
    WorkloadGroup에 Rediness 프로브 설정
    등록
    쿠버네티스가 처리
    WorkloadGroup의 구성원으로 가상머신 자동 등록
    DNS 해석
    클러스터 내 FQDN을 해석하는 데 DNS 서버 사용, DNS 프록시를 사용할지는 선택 가능
    istiod가 DNS 프록시를 설정해 FQDN을 해석

     

    • 여기서 한 가지 유의 사항을 강조하고 싶다.
    • 간단히 말하면, 우리는 프록시를 수작업으로 설치하고 구성했으며, 이 방식은 워크로드를 메시에 통합하는 방법을 구석구석 모두 보여주는 데 도움이 됐다.
    • 그러나 실제 프로젝트에서는 이 과정을 자동화해야 한다. 가상머신을 메시에 수작업으로 추가하면 메시가 아주 취약해진다.
    • 따라서 그럴 경우, 서비스를 복구하기 위해 새벽 3시에 가상머신을 수작업으로 재구성하고 메시에 등록할 것을 요구받는 불상사가 일어날 수 있다.
    • 자동화라는 단어가 벅차게 들릴 수 있다.
    • 그러나 실제로 오늘날의 프로젝트들은 좋은 관행들을 따라 가상머신을 구축 및 배포하는 자동화를 갖추고 있어 보통 패커 packer.io , 앤서블 ansible.com , 테라폼 terraform.io 같은 도구를 사용한다.
    • 그러나 기존 자동화가 있으면 일거리가 줄어드므로, 애플리케이션에 이스티오의 사이드카를 설치하고 설정과 토큰을 제공하도록 스크립트를 업데이트하기만 하면 된다.
    • 그러면 마침내 가상머신이 메시에 통합된다.

     

     

    [ Summary ]

    더보기
    • 가상머신은 이스티오 v1.9에서 베타로 승격됐다. 앞으로는 더 많은 개선이 기대되며, 향후 몇 달 동안 흥미로운 개발 영역이 될 것이다.
      • 동시에 이미 성숙한 상태이므로, 여기서 다룬 내용은 바뀌지 않을 것으로 예상한다.
    • WorkloadGroup 및 WorkloadEntry 를 사용하면 가상머신을 메시에 자동 등록할 수 있다.
    • 자동 등록은 가상머신에서 워크로드의 고가용성을 달성하는 데 중요한다. Auto-registration is important to achieve high availability of workloads in VMs.
    • istioctl은 가상머신을 istiod에 연결하는 데 필요한 가상머신 설정을 생성할 수 있다. istioctl can generate VM configuration for it to connect to istiod.
    • east-west 게이트웨이는 가상머신이 연결할 수 있도록 istiod를 노출한다. East-west gateways expose istiod so that VMs can connect to it.
    • DNS 프록시는 클러스터 내부의 호스트네임을 해석하면 istiod가 NDS API로 설정한다.
    • 가상머신 사이드카는 다른 워크로드와 마찬가지로 이스티오 설정을 준수한다.

    [ 실습 후 자원 삭제 : AWS CloudFormation Stack 삭제 ]  ** 콘솔 > CloudFormation > Stacks > 생성된 대상 삭제!!


     

    Istio Traffic Flow

     kind(controlplane 1대) + istio-ingressgateway(NodePort)로 실습 가이드 + Istio 통신 흐름

    더보기

    1. kind k8s 배포

    #
    cat <<EOF> kind-1node.yaml 
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
      extraPortMappings:
      - containerPort: 30000
        hostPort: 30000
      - containerPort: 30001
        hostPort: 30001
      - containerPort: 30002
        hostPort: 30002
      - containerPort: 30003
        hostPort: 30003
    networking:
      podSubnet: 10.10.0.0/16
      serviceSubnet: 10.200.1.0/24 
    EOF
    kind create cluster --config kind-1node.yaml --name myk8s --image kindest/node:v1.30.4
    
    # 설치 확인
    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'
    docker exec -it myk8s-control-plane sh -c 'DEBIAN_FRONTEND=noninteractive apt install termshark -y'
    docker exec -it myk8s-control-plane tshark -D
    docker exec -it myk8s-control-plane termshark -v
    
    
    # (옵션) 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

     2. istioctl 설치 - install , profile


    # myk8s-control-plane 진입 후 설치 진행
    docker exec -it myk8s-control-plane bash
    -----------------------------------
    # istioctl 설치
    export ISTIOV=1.23.2
    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 profile list
    istioctl install --set profile=default -y
    
    # 설치 확인 : istiod, istio-ingressgateway, crd 등
    kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
    kubectl get crd | grep istio.io | sort
    
    # istio-ingressgateway 서비스 NodePort 변경 및 nodeport 30000로 지정 변경
    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
    
    # 빠져나오기
    exit
    -----------------------------------

     

    3. default 네임스페이스에 istio-proxy sidecar 주입 설정 - Docs

    # mutating Webhook admisstion controller 사용
    kubectl label namespace default istio-injection=enabled
    kubectl get ns -L istio-injection

     

     4. Istio 접속 테스트를 위한 변수 지정

    •  자신의 mac
    # /etc/hosts 파일 수정
    MYDOMAIN=<각자 자신의 www 도메인> # 단, 사용하고 있지 않는 공인 도메인을 사용 할 것
    export MYDOMAIN=www.gasida.dev # 예시 도메인
    echo "127.0.0.1 $MYDOMAIN" | sudo tee -a /etc/hosts
    
    # istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
    curl -v -s $MYDOMAIN:30000
    curl -v -s 127.0.0.1:30000

     

    • [신규 터미널] testpc 컨테이너
    # myk8s-control-plane 컨테이너 IP 확인
    docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myk8s-control-plane
    172.18.0.2
    
    
    # testpc 진입 후 설치 진행
    docker exec -it testpc zsh
    -----------------------------------
    #
    echo -e "172.18.0.2 www.gasida.dev" | tee -a /etc/hosts
    
    #
    curl -v -s www.gasida.dev:30000
    
    # 이후에도 접속 테스트를 위해서 해당 터미널은 유지

     

    5. Istio 를 통한 Nginx 파드 접속 테스트

    • Nginx 디플로이먼트와 서비스 배포
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: kans-nginx
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: deploy-websrv
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: deploy-websrv
      template:
        metadata:
          labels:
            app: deploy-websrv
        spec:
          serviceAccountName: kans-nginx
          terminationGracePeriodSeconds: 0
          containers:
          - name: deploy-websrv
            image: nginx:alpine
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: svc-clusterip
    spec:
      ports:
        - name: svc-webport
          port: 80
          targetPort: 80
      selector:
        app: deploy-websrv
      type: ClusterIP
    EOF
    • Istio Gateway/VirtualService 설정 - Host 기반 트래픽 라우팅 설정 - Gateway
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: test-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: nginx-service
    spec:
      hosts:
      - "$MYDOMAIN"  # 도메인 접속이 잘 되지 않을 경우 "*" 로 변경하고 IP로 접속 할 것
      gateways:
      - test-gateway
      http:
      - route:
        - destination:
            host: svc-clusterip
            port:
              number: 80
    EOF

     

    • 리소스 생성 확인
    #
    kubectl get deploy,pod,svc,ep,sa
    kubectl describe pod -l app=deploy-websrv
    kubectl get gw,vs
    
    # 로그 확인
    kubectl logs -l app=deploy-websrv -c istio-init --tail=-1
    kubectl logs -l app=deploy-websrv -c istio-proxy --tail=-1
    kubectl logs -l app=deploy-websrv -c deploy-websrv --tail=-1
    
    #
    docker exec -it myk8s-control-plane istioctl proxy-status # 단축어 ps
    NAME                                                   CLUSTER        CDS              LDS              EDS              RDS              ECDS        ISTIOD                      VERSION
    deploy-websrv-778ffd6947-7s9fk.default                 Kubernetes     SYNCED (14m)     SYNCED (14m)     SYNCED (14m)     SYNCED (14m)     IGNORED     istiod-868cc8b7d7-l95c2     1.23.2
    istio-ingressgateway-64f9774bdc-b4rzj.istio-system     Kubernetes     SYNCED (22m)     SYNCED (22m)     SYNCED (22m)     SYNCED (22m)     IGNORED     istiod-868cc8b7d7-l95c2     1.23.2
    
    # proxy-config 단축어 pc
    docker exec -it myk8s-control-plane istioctl proxy-config all deploy-websrv-778ffd6947-7s9fk
    docker exec -it myk8s-control-plane istioctl proxy-config all istio-ingressgateway-64f9774bdc-b4rzj.istio-system
    
    docker exec -it myk8s-control-plane istioctl proxy-config listener deploy-websrv-778ffd6947-7s9fk
    docker exec -it myk8s-control-plane istioctl proxy-config route deploy-websrv-778ffd6947-7s9fk
    docker exec -it myk8s-control-plane istioctl proxy-config cluster deploy-websrv-778ffd6947-7s9fk
    docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy-websrv-778ffd6947-7s9fk
    docker exec -it myk8s-control-plane istioctl proxy-config log deploy-websrv-778ffd6947-7s9fk
    
    # envoy 가 사용하고 있는 인증서 정보 확인
    docker exec -it myk8s-control-plane istioctl proxy-config secret deploy-websrv-778ffd6947-7s9fk
    RESOURCE NAME     TYPE           STATUS     VALID CERT     SERIAL NUMBER                        NOT AFTER                NOT BEFORE
    default           Cert Chain     ACTIVE     true           fde80f16813a7838713e9f6107679ab3     2024-10-20T07:33:16Z     2024-10-19T07:31:16Z
    ROOTCA            CA             ACTIVE     true           5148b1373dbec92eb58b536d562d4976     2034-10-17T07:31:57Z     2024-10-19T07:31:57Z

     

    • Istio 를 통한 Nginx 파드 접속 테스트
    # (참고) 출력 로그 정보 확인
    kubectl logs -n istio-system -l app=istio-ingressgateway -f
    kubectl logs -l app=deploy-websrv -c istio-proxy -f
    kubectl logs -l app=deploy-websrv -c deploy-websrv -f
    
    # testpc 컨테이너에서 접속 테스트
    curl -v -s <각자 자신의 www 도메인>:30000
    curl -v -s www.gasida.dev:30000
    curl -v -s <controlplane 컨테이너IP>:30000
    curl -v -s 172.18.0.2:30000
    
    # 자신의 mac 에서 접속 테스트
    curl -v -s <각자 자신의 www 도메인>:30000
    curl -v -s www.gasida.dev:30000
    curl -v -s 127.0.0.1:30000
    open http://127.0.0.1:30000

     

    (참고) 특정 파드 istio-proxy Envoy 로그 레벨 변경 : /logging 엔드포인트에 요청으로 조정 가능 - Blog , Docs

    # 특정 파드에 istio-proxy 에 Envoy 로그 레벨 확인
    kubectl exec -it deploy/deploy-websrv -c istio-proxy -- curl -X POST http://localhost:15000/logging
    active loggers:
      ...
      http: warning
      http2: warning
    ...
    
    # 로그 레벨 : trace > debug > info > warning/warn > error > critical > off
    
    # 특정 컴포넌트 로그만 레벨 변경 : http 만 info 변경 >> testpc에서 curl 접속 후 로그 정보 확인
    kubectl exec -it deploy/deploy-websrv -c istio-proxy -- curl -X POST http://localhost:15000/logging?http=info
    
    # 특정 컴포넌트 로그만 레벨 변경 : http 만 debug 변경 >> testpc에서 curl 접속 후 로그 정보 확인
    kubectl exec -it deploy/deploy-websrv -c istio-proxy -- curl -X POST http://localhost:15000/logging?http=debug

     

    (참고) istio-proxy 파드에 envoy 컨테이너 admin 페이지 접속

    # istio-proxy 파드에 envoy 컨테이너 admin 접속 포트 포워딩 설정
    kubectl port-forward deployment/deploy-websrv 15000:15000 &
    
    # envoy 컨테이너 admin 페이지 접속
    open http://localhost:15000

     

    certs 에 spiff 에 service account 확인

    (참고) Istiod 상세 분석을 위해, ControlZ 웹 접속 후 제공 정보 확인 : istiod 디플로이먼트에 포트 포워딩 접속 - Docs

     

    # istiod 디플로이먼트에 포트 포워딩 설정
    kubectl port-forward deploy/istiod -n istio-system 9876:9876 &
    
    # istiod ControlZ 페이지 접속
    open http://localhost:9876

     

    • 실습 리소스 삭제
    kubectl delete gw test-gateway
    kubectl delete vs nginx-service
    kubectl delete deploy deploy-websrv
    kubectl delete svc svc-clusterip
    kubectl delete sa kans-nginx

     


    6. Bookinfo & Addon 설치

    • Bookinfo + Istio GW/VS 설정 & Addon 설치 - Link
    # myk8s-control-plane 진입 후 설치 진행
    docker exec -it myk8s-control-plane bash
    -----------------------------------
    # Bookinfo 애플리케이션 배포
    export ISTIOV=1.23.2
    cat /istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml
    kubectl apply -f /istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml
    
    # 확인 : 서비스 어카운트(sa)는 spiffe 에 svid 에 사용됨
    kubectl get all,sa
    
    # product 웹 접속 확인
    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>"
    
    # productpage 파드 로그
    kubectl logs -l app=productpage -c istio-proxy --tail=-1
    kubectl logs -l app=productpage -c productpage -f
    
    # Istio Gateway/VirtualService 설정
    cat istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml
    kubectl apply -f /istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml
    
    # Istio Gateway/VirtualService 설정 확인
    kubectl get gw,vs
    istioctl proxy-status
    
    # productpage 파드의 istio-proxy 로그 확인 Access log 가 출력 - Default access log format : 링크
    kubectl logs -l app=productpage -c istio-proxy -f
    
    
    # Addon 설치
    ## Install Kiali and the other addons and wait for them to be deployed. : Kiali dashboard, along with Prometheus, Grafana, and Jaeger.
    tree /istio-$ISTIOV/samples/addons/
    kubectl apply -f /istio-$ISTIOV/samples/addons # 디렉터리에 있는 모든 yaml 자원을 생성
    kubectl rollout status deployment/kiali -n istio-system
    
    # 확인
    kubectl get all,sa,cm -n istio-system
    kubectl get svc,ep -n istio-system
    
    # NodePort 변경 및 nodeport 30001~30003으로 변경 : prometheus(30001), grafana(30002), kiali(30003)
    kubectl patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
    kubectl patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
    kubectl patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'
    
    # 빠져나오기
    exit
    -----------------------------------

     

    • Prometheus , Grafana , Kiali 접속
    # Prometheus 접속
    open http://127.0.0.1:30001
    
    # Grafana 접속
    open http://127.0.0.1:30002
    
    # Kiali 접속 : NodePort
    open http://127.0.0.1:30003
    
    # Kiali 접속 : Port forward
    kubectl port-forward deployment/kiali -n istio-system 20001:20001 &
    open http://127.0.0.1:20001

     

    7. Istio 를 통한 productpage 접속(반복) 테스트 & 웹 브라우저 접속 테스트

    • testppc 컨테이너
    # testpc 컨테이너에서 접속 테스트
    curl -v -s <각자 자신의 www 도메인>:30000
    curl -v -s www.gasida.dev:30000/
    curl -v -s www.gasida.dev:30000/productpage
    curl -v -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>"
    
    # 반복 접속 테스트
    for i in {1..10};  do curl -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>" ; done
    for i in {1..100};  do curl -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>" ; done
    for i in {1..1000};  do curl -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>" ; done
    
    while true; do curl -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
    while true; do curl -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.5; done
    while true; do curl -s www.gasida.dev:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done

     

    • mac OS
    # 자신의 mac 에서 접속 테스트
    curl -v -s <각자 자신의 www 도메인>:30000
    curl -v -s www.gasida.dev:30000/productpage
    curl -v -s 127.0.0.1:30000/productpage
    
    open http://www.gasida.dev:30000/productpage
    open http://127.0.0.1:30000/productpage
    
    
    # (위 접속이 잘 안될 경우) productpage 파드로 직접 port-forward 로 접속
    kubectl port-forward deployment/productpage-v1 9080:9080 &
    open http://127.0.0.1:9080
    open http://127.0.0.1:9080/productpage
    kubectl port-forward deployment/productpage-v1 9080:9080 후 open http://127.0.0.1:9080 접속 시

     

    • Kiali (키알리) 보기 설정
      • Namespacedefault 로 선택 후 Graph (Traffic, Versioned app graph) 에서 Display 옵션 중 ‘Traffic Distribution’ 과 ‘Traffic Animation’ 활성화! , Security 체크 해보자 (Last 1m, Evety 10s)

     

    8. 나머지 Istio 기능 실습 진행! → 아래 노션에 기능들은 직접 실습 해주시면 됩니다.

     

    9. Bookinfo 삭제 : addon은 남겨둠!

    # myk8s-control-plane 진입 후 설치 진행
    docker exec -it myk8s-control-plane bash
    -----------------------------------
    # Bookinfo 삭제
    export ISTIOV=1.23.2
    cd /istio-$ISTIOV/samples/bookinfo/platform/kube
    ./cleanup.sh
    namespace ? [default] 엔터 입력
    
    exit
    -----------------------------------

     

     

     

    Istio 트래픽 흐름 상세 분석

    https://jimmysong.io/en/blog/sidecar-injection-iptables-and-traffic-routing/#understand-outbound-handler

    더보기

    1. 실습을 위한 환경 설정 및 배포 : nginx-app 로 향하는 통신의 경우 peer 간 mtls 끄기 - 링크

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-pod
      labels:
        app: nginx-app
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: nginx-container
        image: nginx
        ports:
        - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: svc-nginx
    spec:
      ports:
        - name: svc-nginx
          port: 80
          targetPort: 80
      selector:
        app: nginx-app
      type: ClusterIP
    ---
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: test-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: nginx-service
    spec:
      hosts:
      - "$MYDOMAIN"
      gateways:
      - test-gateway
      http:
      - route:
        - destination:
            host: svc-nginx
            port:
              number: 80
    ---
    apiVersion: security.istio.io/v1
    kind: PeerAuthentication
    metadata:
      name: "example-workload-policy"
    spec:
      selector:
         matchLabels:
           app: nginx-app
      portLevelMtls:
        80:
          mode: DISABLE
    EOF
    • testpc 반복 접속 
    while true; do curl -s www.gasida.dev:30000 | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done

     

    •  확인
    #
    kubectl get gw,vs,pod,svc,PeerAuthentication
    
    # application(nginx) 로그 확인 : XFF 정보를 통해 클라이언트 IP 확인 가능
    kubectl logs -l app=nginx-app -c nginx-container -f

     

    • kiali 확인 : http 평문 통신

    2. Istio 트래픽 흐름 상세 분석 case1 : testpc → nginx 파드 요청 트래픽 

     

    Flow 예시

     

     a. testpc ↔ Tcp8080[IstioIngressGW] ↔ Tcp80[istio-proxy/nginx] 구간 확인

    # istio-ingressgateway 파드의 IP 확인
    kubectl get pod -n istio-system -l app=istio-ingressgateway -o jsonpath='{.items[*].status.podIP}'
    10.10.0.9
    
    IGWIP=<출력된 IP>
    IGWIP=10.10.0.9
    
    # istio-ingressgateway 파드가 연결된 veth 정보 확인
    docker exec -it myk8s-control-plane ip -c route | grep $IGWIP
    10.10.0.9 dev veth1b80f0bd scope host
    
    IGWVETH=<출력된 veth>
    IGWVETH=veth1b80f0bd
    
    
    # testpc <<=>> Tcp8080[IstioIngressGW] -> Tcp80[nginx] : testpc 와 IstioIngress 파드간 트래픽 덤프
    docker exec -it myk8s-control-plane tcpdump -i $IGWVETH -nnq tcp port 8080
    docker exec -it myk8s-control-plane sh -c "ngrep -tW byline -d $IGWVETH '' 'tcp port 8080'"
    
    
    # testpc <<=>> Tcp8080[IstioIngressGW] -<<=>> Tcp80[istio-proxy/nginx] : IstioIngress 와 nginx 파드간 트래픽 덤프
    docker exec -it myk8s-control-plane tcpdump -i $IGWVETH -nnq tcp port 80
    docker exec -it myk8s-control-plane sh -c "ngrep -tW byline -d $IGWVETH '' 'tcp port 80'"
    ..
    T 2024/10/18 09:37:32.649437 10.10.0.9:46038 -> 10.10.0.26:80 [AP] #7
    GET / HTTP/1.1.
    host: www.gasida.dev:30000.
    user-agent: curl/8.7.1.
    accept: */*.
    x-forwarded-for: 172.18.0.3. <<= IstioIngress 파드가 XFF에 클라이언트IP를 담아서 nginx 파드로 전달
    x-forwarded-proto: http.
    x-envoy-internal: true.
    ...

     

     b. nginx 파드 내에서 iptables 정보 확인

    # myk8s-control-plane 진입 후 설치 진행
    docker exec -it myk8s-control-plane bash
    ------------------------------------------------------------
    # myk8s-control-plane 에 network 네임스페이스 확인
    lsns -t net
    
    # nginx-pod 파드의 nginx-container 컨테이너 ID 추출
    crictl ps --name nginx-container
    crictl ps --name nginx-container -q
    CID1=$(crictl ps --name nginx-container -q)
    echo $CID1
    
    # nginx-pod 파드의 nginx-container 컨테이너의 PID 추출
    crictl inspect $CID1| jq
    crictl inspect $CID1| jq '.info.pid'
    CID1PID=$(crictl inspect $CID1| jq '.info.pid')
    echo $CID1PID
    
    # nginx-pod 파드의 네트워크 네임스페이스로 진입
    nsenter -t $CID1PID -n /bin/bash
    --------------------------------------
    # IP 정보 확인
    ip -c -4 addr show dev lo
    ip -c -4 addr show dev eth0
    11: eth0@if36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc noqueue state UP group default  link-netnsid 0
        inet 10.10.0.26/24 brd 10.10.0.255 scope global eth0
    ...
    
    # ss (socket statistics)로 시스템 소켓 상태 확인 : 15006 은 envoy 프로세스가 Listen 하고 있다
    ss -tpnl '( dport = :15006 or sport = :15006 )'
    
    # 현재 연결된 tcp 소켓 정보 확인
    ss -tpnt '( dport = :15006 or sport = :15006 or sport = :80 or dport = :80 )'
    
    # conntrack 정보 확인 후 초기화 
    conntrack -L 
    
    # iptables NAT 정보 확인
    iptables -t nat --zero 
    
    # 트래픽 인입 시 TCP 경우 모든 트래픽을 15006 으로 리다이렉트한다, 일부 포트는 제외(15008, 15090, 15020, 15021)
    iptables -t nat -L -n -v
    Chain PREROUTING (policy ACCEPT 9 packets, 540 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        9   540 ISTIO_INBOUND  tcp  --  any    any     anywhere             anywhere            
    ...     
    
    Chain ISTIO_INBOUND (1 references)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15008
        0     0 RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15090
        9   540 RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15021
        0     0 RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15020
        0     0 ISTIO_IN_REDIRECT  tcp  --  any    any     anywhere             anywhere            
    
    Chain ISTIO_IN_REDIRECT (3 references)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 REDIRECT   tcp  --  any    any     anywhere             anywhere             redir ports 15006
    
    
    # watch 로 모니터링 : testpc 에서0 접속 후 pkts/bytes 증가 부분 확인
    conntrack -F && iptables -t nat --zero
    watch -d "iptables -v --numeric --table nat --list PREROUTING ; echo ; iptables -v --numeric --table nat --list ISTIO_INBOUND ; echo ; iptables -v --numeric --table nat --list ISTIO_IN_REDIRECT"
    conntrack -L
    ss -tpnt '( dport = :15006 or sport = :15006 or sport = :80 or dport = :80 )'
    
    # nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태를 유지 : 아래에서 계속 사용 됨

     

     c. istioctl proxy-config 로 envoy 정보 확인

    # proxy-config listener 정보 확인
    docker exec -it myk8s-control-plane istioctl proxy-config listener nginx-pod
    docker exec -it myk8s-control-plane istioctl proxy-config listener nginx-pod --address 0.0.0.0 --port 15006
    ADDRESSES PORT  MATCH                                                   DESTINATION
    ...
    0.0.0.0   15006 Trans: raw_buffer; App: http/1.1,h2c; Addr: *:80        Cluster: inbound|80||
    0.0.0.0   15006 Trans: raw_buffer; Addr: *:80                           Cluster: inbound|80||
    
    
    # proxy-config route 정보 확인
    docker exec -it myk8s-control-plane istioctl proxy-config route nginx-pod
    docker exec -it myk8s-control-plane istioctl proxy-config route nginx-pod --name 80
    NAME     VHOST NAME                                                 DOMAINS                                             MATCH     VIRTUAL SERVICE
    80       svc-nginx.default.svc.cluster.local:80                     svc-nginx, svc-nginx.default + 1 more...            /*        
    ...
    
    docker exec -it myk8s-control-plane istioctl proxy-config route nginx-pod --name 80 -o json | jq
    ...
         {
            "name": "svc-nginx.default.svc.cluster.local:80",
            "domains": [
              "svc-nginx.default.svc.cluster.local",
              "svc-nginx",
              "svc-nginx.default.svc",
              "svc-nginx.default",
              "10.200.1.228"
            ],
            "routes": [
              {
                "name": "default",
                "match": {
                  "prefix": "/"
                },
                "route": {
                  "cluster": "outbound|80||svc-nginx.default.svc.cluster.local",
                  "timeout": "0s",
                  "retryPolicy": {
                    "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                    "numRetries": 2,
    ...
    
    
    # proxy-config cluster 정보 확인
    docker exec -it myk8s-control-plane istioctl proxy-config cluster nginx-pod
    docker exec -it myk8s-control-plane istioctl proxy-config cluster nginx-pod --fqdn svc-nginx.default.svc.cluster.local
    SERVICE FQDN                            PORT     SUBSET     DIRECTION     TYPE     DESTINATION RULE
    svc-nginx.default.svc.cluster.local     80       -          outbound      EDS 
    
    docker exec -it myk8s-control-plane istioctl proxy-config cluster nginx-pod --fqdn svc-nginx.default.svc.cluster.local -o json | jq
    
    
    # proxy-config endpoint 정보 확인
    docker exec -it myk8s-control-plane istioctl proxy-config endpoint nginx-pod
    docker exec -it myk8s-control-plane istioctl proxy-config endpoint nginx-pod --port 80
    docker exec -it myk8s-control-plane istioctl proxy-config endpoint nginx-pod --cluster "outbound|80||svc-nginx.default.svc.cluster.local" -o json
    [
        {
            "name": "outbound|80||svc-nginx.default.svc.cluster.local",
            "addedViaApi": true,
            "hostStatuses": [
                {
                    "address": {
                        "socketAddress": {
                            "address": "10.10.0.26",
                            "portValue": 80
    ...

     

    d. (참고) nginx-pod 파드에 envoy 컨테이너 admin 페이지 접속 , istio-proxy 컨테이너 로그 확인

    # istio-proxy 파드에 envoy 컨테이너 admin 접속 포트 포워딩 설정
    kubectl port-forward nginx-pod 15000:15000 &
    
    # envoy 컨테이너 admin 페이지 접속
    open http://localhost:15000
    
    # 로그 확인
    kubectl logs nginx-pod -c istio-proxy -f
    
    # nginx-pod에 istio-proxy 에 로그 레벨 변경 : http 만 debug/info 변경 >> testpc에서 curl 접속 후 로그 정보 확인
    kubectl exec -it nginx-pod -c istio-proxy -- curl -X POST http://localhost:15000/logging?http=debug
    
    # 로그 확인
    kubectl logs nginx-pod -c istio-proxy -f
    
    # nginx-pod에 istio-proxy 에 로그 레벨 원복
    kubectl exec -it nginx-pod -c istio-proxy -- curl -X POST http://localhost:15000/logging?http=warning

     

    e. istio-proxy 컨테이너의 envoy(프로세스)를 통과하여 빠져 나가는 트래픽 확인

    • nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태에서 아래 입력
    # envoy가 가로챈 후 lo로 SNAT 후 빠져나갈 때 iptables OUTPUT -> ISTIO_OUTPUT -> POSTROUTIN 체인 지나감
    iptables -t nat -L -n -v
    Chain OUTPUT (policy ACCEPT 6 packets, 1519 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        6  1519 ISTIO_OUTPUT  6    --  *      *       0.0.0.0/0            0.0.0.0/0   
        
    Chain ISTIO_OUTPUT (1 references)
     pkts bytes target     prot opt in     out     source               destination         
        1   291 RETURN     0    --  *      lo      127.0.0.6            0.0.0.0/0           
        0     0 ISTIO_IN_REDIRECT  6    --  *      lo      0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 owner UID match 1337
        0     0 RETURN     0    --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner UID match 1337
        5  1228 RETURN     0    --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
        0     0 ISTIO_IN_REDIRECT  6    --  *      lo      0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 owner GID match 1337
        0     0 RETURN     0    --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner GID match 1337
        0     0 RETURN     0    --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
        0     0 RETURN     0    --  *      *       0.0.0.0/0            127.0.0.1           
        0     0 ISTIO_REDIRECT  0    --  *      *       0.0.0.0/0            0.0.0.0/0   
    
    Chain POSTROUTING (policy ACCEPT 6 packets, 1519 bytes)
     pkts bytes target     prot opt in     out     source               destination     
    
    
    # watch 로 모니터링 : testpc 에서 접속 후 pkts/bytes 증가 부분 확인
    conntrack -F && iptables -t nat --zero
    watch -d "iptables -v --numeric --table nat --list OUTPUT ; echo ; iptables -v --numeric --table nat --list ISTIO_OUTPUT ; echo ; iptables -v --numeric --table nat --list POSTROUTING"
    conntrack -L
    
    
    # lsof 확인
    lsof -i TCP:80,15006 -n
    ...
    envoy   26955     1337   39u  IPv4 1298844      0t0  TCP 127.0.0.6:58477->10.10.0.26:http (ESTABLISHED)
    ...
    
    # lo 인터페이스 로 tcpdump 할 경우 출발지 IP가 127.0.0.6으로 SNAT 되어서 빠져나감을 확인
    tcpdump -nnqi lo not net 127.0.0.1
    15:00:02.955442 IP 127.0.0.6.35151 > 10.10.0.26.80: tcp 239
    15:00:02.955569 IP 10.10.0.26.80 > 127.0.0.6.35151: tcp 238
    ...
    
    # lo 인터페이스도 RX/TX가 증가함을 확인
    watch -d ifconfig lo
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10<host>
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 127341  bytes 404699497 (385.9 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 127341  bytes 404699497 (385.9 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    # ngrep 로 http 헤더 정보 확인 : 해당 요청(패킷)이 nginx 컨테이너로 전달 됨
    ngrep -tW byline -d lo -v 'host 127.0.0.1'  # 127.0.0.1 IP는 제외
    T 2024/10/18 15:07:42.035857 127.0.0.6:58477 -> 10.10.0.26:80 [AP] #16
    GET / HTTP/1.1.
    host: www.gasida.dev:30000.
    user-agent: curl/8.7.1.
    accept: */*.
    x-forwarded-for: 172.18.0.3.
    x-forwarded-proto: http.
    x-request-id: 76357e24-71a3-487b-94e1-ddf79b3c717d.
    x-envoy-attempt-count: 1.
    x-envoy-internal: true.
    
    # (참고) 기본적으로 127.0.0.0/8 대역 통신은 lo local 통신 라우팅 처리함
    ip route show table local
    local 10.10.0.26 dev eth0 proto kernel scope host src 10.10.0.26 
    broadcast 10.10.0.255 dev eth0 proto kernel scope link src 10.10.0.26 
    local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 
    local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1

     

     f. 최종적으로 nginx 컨테이너에 클라이언트의 요청 트래픽이 도착한다.

    # nginx 웹 데몬에 도착하여 액세스 로그 기록되고, 이후 200ok 리턴되며, XFF 헤더에서 클라이언트의 IP를 확인
    kubectl logs nginx-pod -c nginx-container -f
    127.0.0.6 - - [18/Oct/2024:15:26:24 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1" "172.18.0.3"

     

    3. Istio 트래픽 흐름 상세 분석 case1 : testpc ← nginx 파드 (2번 요청에 대한) 응답 트래픽 

    Flow 예시

     

    • nginx (웹 서버)컨테이너에서 리턴 트래픽(응답, 200 OK)를 클라이언트에 전달합니다.
    • IPTables CT(Connection Table)에 정보를 참고해서 역변환 등이 적용되어 전달됩니다.
    • 위(요청)에서 알아본 3번 과정 직전과 위 8번 과정의 NAT 트래픽 정보
      • nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태에서 아래 입력
    # conntrack 정보 확인
    conntrack -L --dst-nat
    tcp      6 431999 ESTABLISHED src=10.10.0.9 dst=10.10.0.26 sport=46038 dport=80 src=10.10.0.26 dst=10.10.0.9 sport=15006 dport=46038 [ASSURED] mark=0 use=1

     

    4. Istio 트래픽 흐름 상세 분석 case2 : ‘nginx 파드 → 외부 인터넷’에서 다운로드 시

    • 파드에서 업데이트 나 패치 다운로드 처럼 외부 웹서버인터넷 연결 과정에서의 트래픽의 흐름
    Flow 예시

     

    a. 'nginx 컨테이너' 에서 외부 웹서버 요청

    # 아래 처럼 'nginx 컨테이너' 에서 외부 웹서버 요청
    kubectl exec -it nginx-pod -c nginx-container -- curl -s http://wttr.in/seoul
    kubectl exec -it nginx-pod -c nginx-container -- curl -s http://ipinfo.io/city
    kubectl exec -it nginx-pod -c nginx-container -- curl -k https://www.google.com | grep -o "<title>.*</title>";echo
    
    # 반복 요청 : https는 암호화되니, http 접속을 사용 할 것
    while true; do kubectl exec -it nginx-pod -c nginx-container -- curl -s http://ipinfo.io/city ; date "+%Y-%m-%d %H:%M:%S" ; echo "--------------" ; sleep 5; done
    while true; do kubectl exec -it nginx-pod -c nginx-container -- curl -k https://www.google.com | grep -o "<title>.*</title>"; date "+%Y-%m-%d %H:%M:%S" ; echo "--------------" ; sleep 3; done

     

    • nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태에서 아래 입력
    # conntrack 정보 확인
    conntrack -L --dst-nat
    tcp      6 99 TIME_WAIT src=10.10.0.26 dst=142.250.207.4 sport=37812 dport=443 src=127.0.0.1 dst=10.10.0.26 sport=15001 dport=37812 [ASSURED] mark=0 use=1
    src=10.10.0.26 dst=142.250.207.4 sport=37812 dport=443 # 최초 요청 트래픽 정보
    src=127.0.0.1 dst=10.10.0.26 sport=15001 dport=37812   # 리턴 트래픽에서 IP/Port 정보를 보면, 출발지 포트가 15001 으로, 'istio-proxy' 경유를 했음을 알 수 있다

     

     b. nginx → iptables → envoy 구간

    • nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태에서 아래 입력
    # nginx 파드에서 외부로 TCP 트래픽 요청(인입) 시, ISTIO_OUTPUT 에서 맨 마지막 줄에 매칭되고 이후 ISTIO_REDIRECT 에서 redir ports 15001 되어 'Envoy'로 인입됩니다.
    ## ISTIO_OUTPUT 은 envoy 를 빠져나와서 다시 한번 더 Rule 매칭 확인을 한다. envoy IN/OUT 구분을 위해서, UID 1337 조건을 확인함.
    iptables -t nat -L -n -v
    Chain OUTPUT (policy ACCEPT 687 packets, 52287 bytes)
     pkts bytes target     prot opt in     out     source               destination         
      261 16819 ISTIO_OUTPUT  6    --  *      *       0.0.0.0/0            0.0.0.0/0  
    
    Chain ISTIO_OUTPUT (1 references)
     pkts bytes target     prot opt in     out     source               destination         
        2   351 RETURN     0    --  *      lo      127.0.0.6            0.0.0.0/0           
        0     0 ISTIO_IN_REDIRECT  6    --  *      lo      0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 owner UID match 1337
        0     0 RETURN     0    --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner UID match 1337
      147  9748 RETURN     0    --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
        0     0 ISTIO_IN_REDIRECT  6    --  *      lo      0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 owner GID match 1337
        0     0 RETURN     0    --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner GID match 1337
        0     0 RETURN     0    --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
        0     0 RETURN     0    --  *      *       0.0.0.0/0            127.0.0.1           
      112  6720 ISTIO_REDIRECT  0    --  *      *       0.0.0.0/0            0.0.0.0/0    
    
    Chain ISTIO_REDIRECT (1 references)
     pkts bytes target     prot opt in     out     source               destination         
      112  6720 REDIRECT   6    --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001
    
    
    # watch 로 모니터링 : testpc 에서 접속 후 pkts/bytes 증가 부분 확인
    ## 'owner UID match 1337' pkts/bytes 증가는 envoy 를 빠져나오서 매칭되어 증가됨
    conntrack -F && iptables -t nat --zero
    watch -d "iptables -v --numeric --table nat --list OUTPUT ; echo ; iptables -v --numeric --table nat --list ISTIO_OUTPUT ; echo ; iptables -v --numeric --table nat --list ISTIO_REDIRECT"
    conntrack -L

     

    • nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태에서 아래 입력 
    # lo 인터페이스 로 tcpdump로 확인
    ## 외부(인터넷) 목적지 IP/Port 를 127.0.0.1:15001로 Redirect 된 것을 확인
    ## 그 아래는 리턴 트래픽을 lo 에서 nginx 로 전달
    tcpdump -nnqi lo
    01:53:33.969167 IP 10.10.0.26.60212 > 127.0.0.1.15001: tcp 0
    01:53:34.004123 IP 172.217.175.36.443 > 10.10.0.26.60212: tcp 6426
    
    # lo 인터페이스도 RX/TX가 증가함을 확인
    watch -d ifconfig lo
    
    
    # ngrep 로 http 헤더 정보 확인
    ngrep -tW byline -d lo
    T 2024/10/19 02:06:19.323748 10.10.0.26:49648 -> 127.0.0.1:15001 [AP] #53
    GET /city HTTP/1.1.
    Host: ipinfo.io.
    User-Agent: curl/7.88.1.
    Accept: */*.

     

     c. istioctl proxy-config 로 envoy 정보 확인 : 생략..

     

    d. Envoy는 대리인(Proxy) 역할로 목적지 IP/Port 정보를 nginx 가 원래 요청한 정보로 변경하여 외부 웹서버에 연결

    • nginx-pod 파드의 네트워크 네임스페이스로 진입되어 있는 터미널 상태에서 아래 입력
    #
    tcpdump -nnqi eth0 tcp port 80
    02:22:09.470964 IP 10.10.0.26.46252 > 34.117.59.81.80: tcp 699
    02:22:09.633974 IP 34.117.59.81.80 > 10.10.0.26.46252: tcp 378
    ...
    
    #
    lsof -i TCP:80,15001 -n
    envoy   26955     1337   42u  IPv4 2071968      0t0  TCP 10.10.0.26:45406->34.117.59.81:http (ESTABLISHED)
    envoy   26955     1337   44u  IPv4 2071145      0t0  TCP 10.10.0.26:46252->34.117.59.81:http (ESTABLISHED)
    ...
    
    # ISTIO_OUTPUT 은 envoy 를 빠져나와서 다시 한번 더 Rule 매칭 확인을 한다. envoy IN/OUT 구분을 위해서, UID 1337 조건을 확인함.
    ## envoy 는 ㅕㅕ
    ## 즉 맨 하단에 ISTIO_REDIRECT 매칭되기 전에 그 위에 'owner UID match 1337' 매팅이 되어서 RETURN 을 통해 외부로 라우팅 된다.
    ## ISTIO_OUTPUT 을 envoy 로 보내고, 돌아오는 flow 를 구분하기 위해서 User ID(1337) 매칭을 확인 함.
    iptables -t nat -L -n -v
    Chain OUTPUT (policy ACCEPT 687 packets, 52287 bytes)
     pkts bytes target     prot opt in     out     source               destination         
      261 16819 ISTIO_OUTPUT  6    --  *      *       0.0.0.0/0            0.0.0.0/0  
    
    Chain ISTIO_OUTPUT (1 references)
     pkts bytes target     prot opt in     out     source               destination
        0     0 RETURN     0    --  *      lo      127.0.0.6            0.0.0.0/0
        0     0 ISTIO_IN_REDIRECT  6    --  *      lo      0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 owner UID match 1337
        0     0 RETURN     0    --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner UID match 1337
        7  2730 RETURN     0    --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
        0     0 ISTIO_IN_REDIRECT  6    --  *      lo      0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 owner GID match 1337
        0     0 RETURN     0    --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner GID match 1337
        0     0 RETURN     0    --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
        0     0 RETURN     0    --  *      *       0.0.0.0/0            127.0.0.1
        6   360 ISTIO_REDIRECT  0    --  *      *       0.0.0.0/0            0.0.0.0/0
    
    # watch 로 모니터링 : testpc 에서 접속 후 pkts/bytes 증가 부분 확인
    ## 'owner UID match 1337' pkts/bytes 증가는 envoy 를 빠져나오서 매칭되어 증가됨
    conntrack -F && iptables -t nat --zero
    watch -d "iptables -v --numeric --table nat --list OUTPUT ; echo ; iptables -v --numeric --table nat --list ISTIO_OUTPUT"
    conntrack -L
    • istio 애플리케이션 요구 사항 중 일부 - Docs
      • Application UIDs: Ensure your pods do not run applications as a user with the user ID (UID) value of 1337 because 1337 is reserved for the sidecar proxy.

    e. 이후 노드를 통해서 외부에 요청이 전달됨

     

    End!!


    5. Istio 트래픽 흐름 상세 분석 case2 : ‘nginx 파드 ← 외부 인터넷’ 요청에 대한 응답 리턴 시

    • 웹 서버에서 리턴 트래픽이 파드에 돌아오는 과정은 case1 에서 알아본 흐름과 유사합니다.
    • 다만, 파드 내로 인입 시 목적지 포트가 다르므로 이므로, ‘Nginx 컨테이너’ 로 바로 가지 않고, 'Istio-proxy 컨테이너' 로 먼저 가게 됩니다.

    [ 주요 참고 자료 ]

     KoB[트러블 빵야] Istio 를 디버깅 해보자! - Connection Refused 편 : holdApplicationUntilProxyStarts: true

    ☞ Understanding the Sidecar injection, Traffic Intercepting & Routing Process in Istio | Jimmy Song- Link

     


    6.1 클라이언트(요청) → 파드(인입)

    트래픽 흐름

    • 외부 클라이언트 PC에서 k8s 클러스터 내부의 웹 서버 파드로 인입 시 트래픽 흐름입니다.
    • 기존 패킷 내용 중 변경 전(굵음)과 변경 후(빨간 색)으로 표현하였습니다.

     

    파드 내 IPTables 적용 흐름 : 아래 (1) ~ (8) 까지의 과정을 먼저 설명합니다.

    출처 : https://jimmysong.io/en/blog/sidecar-injection-iptables-and-traffic-routing/#understand-outbound-handler

     

    추천링크 : Life of a Packet in ISTIO Part 1 - 링크

    더보기

    1. (통신시작) 트래픽 인입 → 목적지 파드

    2. (통신시작) 파드 → 외부 

    • 내부 파드1 → 내부 파드2 접속 시 : Outbound 그림 중간에 ISTIO_IN_REDIRECT → ISTIO_REDIRECT 로 오타!

     


    6.1.1 Client PC → Istio IngressGateway 파드 구간

     외부 클라이언트 PC(192.168.10.254) 에서 웹 서버 파드로 접속 시도

    더보기
    • 외부에서 Istio IngressGateway 파드로 인입 과정 부분은 생략하였습니다.
    # 아래 처럼 정상적으로 웹 서버 접속 정보 출력 확인
    curl -s -v $MYDOMAIN:$IGWHTTP
    curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
    while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
    while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done
    
    curl -s --user-agent "IPHONE" $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
    while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"; date "+%Y-%m-%d %H:%M:%S" ; echo "--------------" ; sleep 1; done
    
    # 로그 확인
    kubetail -l app=nginx-app -f
    istio-INBOUND-1.pcap
    0.01MB

     


    6.1.2 Istio IngressGateway 파드 → 노드 인입

     Istio IngressGateway(envoy) 파드를 경유하여 웹 서버 파드가 있는 노드로 인입

    더보기
    • Istio IngressGateway(envoy) 파드는 클라이언트 PCIP를 HTTP XFF(X-Forwarded-for) 헤더에 담아서 전달합니다.
    • Istio IngressGateway(envoy) 파드 x-envoy-Y 헤더를 추가해서 전달합니다.

    6.1.3 [파드 내부] IPTables 적용 → Istio-proxy 컨테이너 인입*

    ▶ 'PAUSE 컨테이너'가 파드 네트워크 네임스페이스를 생성하여 제공하며, 'Init 컨테이너'는 Istio-proxy가 트래픽을 가로챌 수 있게 파드 내에 iptables rules 설정을 완료합니다.

    더보기
    # 아래 처럼 'istio-init 컨테이너' 의 로그에 iptables rules 설정을 확인할 수 있습니다.
    # 참고로, NAT Tables 만 설정되고, 그외(filter, mangle, raw 등)은 설정하지 않습니다.
    (istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-init
    * nat
    -N ISTIO_INBOUND
    -N ISTIO_REDIRECT
    -N ISTIO_IN_REDIRECT
    -N ISTIO_OUTPUT
    -A ISTIO_INBOUND -p tcp --dport 15008 -j RETURN
    -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
    -A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
    -A PREROUTING -p tcp -j ISTIO_INBOUND
    -A ISTIO_INBOUND -p tcp --dport 22 -j RETURN
    -A ISTIO_INBOUND -p tcp --dport 15090 -j RETURN
    -A ISTIO_INBOUND -p tcp --dport 15021 -j RETURN
    -A ISTIO_INBOUND -p tcp --dport 15020 -j RETURN
    -A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
    -A OUTPUT -p tcp -j ISTIO_OUTPUT
    -A ISTIO_OUTPUT -o lo -s 127.0.0.6/32 -j RETURN
    -A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
    -A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
    -A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
    -A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
    -A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
    -A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
    -A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
    -A ISTIO_OUTPUT -j ISTIO_REDIRECT
    COMMIT

    파드 내 IPTables Chains/Rules 적용 (NAT 테이블) → 'Istio-proxy 컨테이너'로 인입됩니다.

    더보기
    • PREROUTING → ISTIO_INBOUND → ISTIO_IN_REDIRECT (redirect ports 15006)
    nginx 파드가 배치된 노드에서 아래 실행
    # 아래 확인은 istio-proxy 대신 pause 에서 iptables 확인 해보자...
    
    # 변수 지정 : C1(Istio-proxy, Envoy , 단축키 지정
    lsns -t net
    ps -ef |grep istio
    1337      347173  347155  0 18:52 ?        00:00:01 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drain-strategy immediate --local-address-ip-version v4 --file-flush-interval-msec 1000 --disable-hot-restart --allow-unknown-static-fields -l warning --component-log-level misc:error --concurrency 2
    C1PID=347173
    alias c1="nsenter -t $C1PID -n"
    
    crictl ps
    CONTAINER           IMAGE               CREATED             STATE               NAME                     ATTEMPT             POD ID              POD
    b6a2265bd4e09       25eeeeca367cf       6 minutes ago       Running             istio-proxy              0                   adfe596135f4e       nginx-pod
    adbc8a95a979f       7f553e8bbc897       6 minutes ago       Running             nginx-container          0                   adfe596135f4e       nginx-pod
    fee76dda9c16d       f9095e2f0444d       About an hour ago   Running             grafana                  0                   79122dcc70e1c       grafana-7f76bc9cdb-jqs29
    ef150da585889       a342234ebb356       5 hours ago         Running             discovery                0                   549480847b6d1       istiod-7f8b586864-mv944
    31fecdd35c503       5d221316a3c61       6 hours ago         Running             local-path-provisioner   0                   c1fe2cf4bd962       local-path-provisioner-6795b5f9d8-64b8j
    
    crictl exec -it b6a2265bd4e09 ip -c a
    alias c1="crictl exec -it b6a2265bd4e09"
    
    sudo crictl exec -it b6a2265bd4e09 ip -c a
    
    # Istio-proxy 컨테이너의 iptables 확인
    c1 iptables -t nat --zero # 패킷 카운트 초기화
    
    # 트래픽 인입 시 TCP 경우 모든 트래픽을 15006 으로 리다이렉트한다, 일부 포트는 제외(22, 15008, 15020, 15021, 15090)
    c1 iptables -t nat -L -n -v
    Chain PREROUTING (policy ACCEPT 44 packets, 2640 bytes)
     pkts bytes target     prot opt in     out     source               destination
       45  2700 ISTIO_INBOUND  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Chain ISTIO_INBOUND (1 references)
     pkts bytes target             prot opt in     out     source               destination
    ...
        1    60 ISTIO_IN_REDIRECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Chain ISTIO_IN_REDIRECT (3 references)
     pkts bytes target     prot opt in     out     source               destination
        1    60 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15006
    
    # 모니터링 >> 아래 ss 소켓 강제 Reset 참고
    c1 iptables -t nat --zero
    c1 iptables -t nat -S | grep 15006
    c1 iptables -v --numeric --table nat --list ISTIO_IN_REDIRECT
    watch -d "nsenter -t $C1PID -n iptables -v --numeric --table nat --list PREROUTING ; echo ; nsenter -t $C1PID -n iptables -v --numeric --table nat --list ISTIO_INBOUND; echo ; nsenter -t $C1PID -n iptables -v --numeric --table nat --list ISTIO_IN_REDIRECT"
    watch -d "nsenter -t $C1PID -n iptables -t nat -L -n -v"

     

     

    ▶  'Istio-proxy 컨테이너'15006 Listener 확인

    더보기
    # ss (socket statistics)로 시스템 소켓 상태 확인 : 15006 은 envoy 프로세스가 Listen 하고 있다
    root@k8s-w2:~# c1 ss -tpnl '( dport = :15006 or sport = :15006 )'
    State      Recv-Q      Send-Q           Local Address:Port            Peer Address:Port     Process
    LISTEN     0           4096                   0.0.0.0:15006                0.0.0.0:*         users:(("envoy",pid=3928,fd=37))
    LISTEN     0           4096                   0.0.0.0:15006                0.0.0.0:*         users:(("envoy",pid=3928,fd=36))
    
    # 확인 예시
    c1 ss -tpnt '( dport = :15006 or sport = :15006 or sport = :80 or dport = :80 )'
    watch -d "nsenter -t $C1PID -n  ss -tpnt '( dport = :15006 or sport = :15006 or sport = :80 or dport = :80 )'"
    
    # 연결된 소켓 강제 Reset
    # c0 ss -K dst 172.16.228.66 dport = 44526
    c1 ss -K dst 172.16.228.66
    c1 ss -K dst 172.16.46.13

     

    (참고) istioctl proxy-config listener 과 cluster 정보 확인

    더보기
    # istio-proxy(envoy) 로 nginx-pod 정보 확인
    istioctl proxy-config listener nginx-pod
    istioctl proxy-config listener nginx-pod --address 0.0.0.0 --port 15006
    0.0.0.0 15006 Trans: raw_buffer; App: HTTP; Addr: *:80                                 Cluster: inbound|80||
    ...
    istioctl proxy-config listener nginx-pod --address 0.0.0.0 --port 15006 -o json
    [
        {
            "name": "virtualInbound",
            "address": {
                "socketAddress": {
                    "address": "0.0.0.0",
                    "portValue": 15006
    ...
    
    #
    istioctl proxy-config cluster nginx-pod
    istioctl proxy-config cluster nginx-pod --direction inbound -o json
    ...
    				"upstreamBindConfig": {
                "sourceAddress": {
                    "address": "127.0.0.6",
                    "portValue": 0
                }
            },
            "metadata": {
                "filterMetadata": {
                    "istio": {
                        "services": [
                            {
                                "host": "svc-nginx.default.svc.cluster.local",
                                "name": "svc-nginx",
                                "namespace": "default"

    ▶ (참고) nginx 파드 내에서 istio-proxy 컨테이너와 nginx 컨테이너 정보 확인 → 스터디에서는 Skip

    더보기
    마스터 노드에서 아래 실행
    # 노드에서 -c 옵션으로 istio-proxy 컨테이너와 nginx-container 컨테이너간 구별되어 정보가 확인된다
    kubectl exec nginx-pod -c istio-proxy -- ls -l /proc/1/ns
    lrwxrwxrwx 1 istio-proxy istio-proxy 0 Dec 14 14:52 mnt -> mnt:[4026532435]
    lrwxrwxrwx 1 istio-proxy istio-proxy 0 Dec 14 14:52 net -> net:[4026532367]
    lrwxrwxrwx 1 istio-proxy istio-proxy 0 Dec 14 14:52 pid -> pid:[4026532437]
    
    kubectl exec nginx-pod -c nginx-container -- ls -l /proc/1/ns
    lrwxrwxrwx 1 root root 0 Dec 14 14:52 mnt -> mnt:[4026532432]
    lrwxrwxrwx 1 root root 0 Dec 14 14:52 net -> net:[4026532367]
    lrwxrwxrwx 1 root root 0 Dec 14 14:52 pid -> pid:[4026532434]
    
    lsns -t net
    
    
    # 단축키(alias) 지정
    alias c1="kubectl exec -it nginx-pod -c istio-proxy --"
    alias c2="kubectl exec -it nginx-pod -c nginx-container --"
    
    # nginx 컨테이너에 툴 설치
    c2 apt update
    c2 apt install -y iproute2 procps tree tcpdump ngrep
    
    # PID 비교
    c1 ps afxuwww
    c2 ps afxuwww
    
    # MNT 비교
    c1 ls -al /etc/nginx
    c2 ls -al /etc/nginx
    
    # NET 비교
    c1 ip -c addr
    c2 ip -c addr

    ▶ (참고) debug 파드 활용 : tcpdump, ngrep 등

    더보기
    # debug 컨테이너
    kubectl debug nginx-pod -it --image=nicolaka/netshoot -c netdebug
    -----
    ip -c addr
    curl localhost
    ss
    ss -l
    ss -4tpl
    ss -4tp
    ss -xpl
    ss -xp
    tcpdump -i any -nnq
    ngrep -d any -tW byline
    exit
    -----

    6.1.4 [파드 내부] Istio-proxy 컨테이너 → IPTables 적용

    ▶ 'Istio-proxy 컨테이너' 는 대리인(Proxy) 역할로, 출발지 IP127.0.0.6 으로 변경하여 'Nginx 컨테이너'와 연결을 한다

    더보기
    • 'Istio-proxy 컨테이너'의 로그 확인
    # 로그 내용 중 출발지 정보(127.0.0.6:50763)를 변경하고 전달하는 것을 알 수 있다
    (istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-proxy -f
    [2021-12-15T18:05:56.334Z] "GET / HTTP/1.1" 200 - via_upstream - "-" 0 615 0 0 "192.168.10.254" "curl/7.68.0" "0844349b-d290-994b-93b2-da36bf929c62" "www.gasida.dev:30384" "172.16.46.11:80" inbound|80|| 127.0.0.6:50763 172.16.46.11:80 192.168.10.254:0 - default
    • 파드 내에서 패킷 덤프 후 확인 : 출발지 IP가 127.0.0.6 으로 변경되었다! 
    # 패킷 덤프 (예시) 
    c1 tcpdump -nni any  not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q
    c1 tcpdump -nni any  not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q -w /tmp/istio-nginx.pcap
    c1 tcpdump -nni lo   not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q
    c1 tcpdump -nni eth0 not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q
    
    c2 tcpdump -nni any  not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q
    c2 tcpdump -nni any  not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q -w /tmp/istio-nginx.pcap
    c2 tcpdump -nni lo   not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q
    c2 tcpdump -nni eth0 not net 10.0.2.15 and not udp and not tcp port 15012 and not tcp port 15020 -q
    
    #
    kubectl exec nginx-pod -c istio-proxy -- bash
    ------------------
    tcpdump -i any -nnq
    ------------------
    
    # debug 컨테이너
    tcpdump -i any -nnq
    07:09:19.911008 eth0  In  IP 10.0.2.15.35822 > 172.16.184.18.15021: tcp 0
    07:09:19.911029 eth0  Out IP 172.16.184.18.15021 > 10.0.2.15.35822: tcp 0
    07:09:19.911048 eth0  In  IP 10.0.2.15.35822 > 172.16.184.18.15021: tcp 0
    07:09:19.911286 eth0  In  IP 10.0.2.15.35822 > 172.16.184.18.15021: tcp 119
    07:09:19.911293 eth0  Out IP 172.16.184.18.15021 > 10.0.2.15.35822: tcp 0
    07:09:19.911587 lo    In  IP 127.0.0.1.60644 > 127.0.0.1.15020: tcp 216
    07:09:19.911756 lo    In  IP 127.0.0.1.15020 > 127.0.0.1.60644: tcp 75
    07:09:19.911770 lo    In  IP 127.0.0.1.60644 > 127.0.0.1.15020: tcp 0
    07:09:19.911950 eth0  Out IP 172.16.184.18.15021 > 10.0.2.15.35822: tcp 143
    07:09:19.911966 eth0  In  IP 10.0.2.15.35822 > 172.16.184.18.15021: tcp 0

     

    • 파드 내 lsof (list open files) 확인
    # 아래 처럼 126.0.0.6 -> 172.16.46.11(nginx)로 TCP 세션이 연결된것을 알 수 있다
    c1 lsof -i TCP:80,15006 -n
    COMMAND  PID            USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    envoy   3928            1337   40u  IPv4 901362      0t0  TCP 127.0.0.6:41109->172.16.46.11:http (ESTABLISHED)
    nginx   3864 systemd-resolve    9u  IPv4 901363      0t0  TCP 172.16.46.11:http->127.0.0.6:41109 (ESTABLISHED)
    envoy   3928            1337   38u  IPv4 901360      0t0  TCP 172.16.46.11:15006->172.16.228.76:40486 (ESTABLISHED)
    
    # 확인 예시
    c1 lsof -i TCP:80,15006 -n
    c1 lsof -i TCP:80,15001,15006 -n
    watch -d "nsenter -t $C0PID -n lsof -i TCP:80,15006 -n"
    watch -d "nsenter -t $C0PID -n lsof -i TCP:80,15001,15006 -n"
    
    # 연결된 TCP 강제 Reset
    # c0 ss -K dst 172.16.228.66 dport = 44526
    c1 ss -K dst 172.16.228.95
    c1 ss -K dst 172.16.46.14

     

     

    ▶  (참고) 'Istio-proxy 컨테이너' → 'Nginx 컨테이너' 와 통신 시에는 로컬 통신

    더보기
    • 두 컨테이너는 동일한 NET NS 를 사용하므로, 별도 통신을 위해서 'istio-proxy' 는 lo 통신이 가능한 127.0.0.6 주소로 변경 후 로컬 통신을 수행한다
    # 기본적으로 127.0.0.0/8 대역 통신은 lo local 통신 라우팅 처리다!
    c1 ip route show table local
    broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
    local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
    local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
    
    # lo 인터페이스도 통신에 사용된다 : 실제 아래 RX/TX packets 이 증가한다!
    c1 ifconfig lo
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 28141  bytes 19036394 (19.0 MB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 28141  bytes 19036394 (19.0 MB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

     


    6.1.5 [파드 내부] IPTables 적용 → Nginx 컨테이너 인입

    파드 내에 IPTables 는 전역(?)으로 적용되므로, 'Istio-proxy' 의 인/아웃 시 트래픽 구별이 중요하다.

    더보기
    • 'Istio-proxy' 를 빠져나올때는 출발지 IP가 127.0.0.6 이므로 ISTIO_OUTPUT 에 적용되어 리턴되어 POSTROUTING 를 통해 nginx 로 도착한다
    • IPTables 확인 : istio-proxy → OUTPUT → ISTIO_OUTOUT(맨 상단 Rule 매칭으로 RETURN) -> POSTROUTING -> NGINX 컨테이너
    # 출발IP가 127.0.0.6 이고, 빠져나오는 인터페이스가(-o lo)에 매칭되어 리턴됨
    c1 iptables -v --numeric --table nat --list ISTIO_OUTPUT
    Chain ISTIO_OUTPUT (1 references)
     pkts bytes target     prot opt in     out     source               destination
        2   120 RETURN     all  --  *      lo      127.0.0.6            0.0.0.0/0
    
    # POSTROUTING 은 특별한 rule 이 없으니 통과!
    Chain POSTROUTING (policy ACCEPT 144 packets, 12545 bytes)
     pkts bytes target     prot opt in     out     source               destination
    
    # 모니터링 예시
    c1 iptables -t nat --zero
    c1 iptables -v --numeric --table nat --list ISTIO_OUTPUT
    watch -d "nsenter -t $C1PID -n iptables -v --numeric --table nat --list OUTPUT; echo ; nsenter -t $C1PID -n iptables -v --numeric --table nat --list ISTIO_OUTPUT; echo ; nsenter -t $C1PID -n iptables -v --numeric --table nat --list POSTROUTING"
    watch -d "nsenter -t $C1PID -n iptables -t nat -L -n -v"

     

     

     

    최종적으로 nginx 컨테이너에 클라이언트의 요청 트래픽이 도착한다.

    더보기
    • nginx 컨테이너의 웹 액세스 로그에서 확인 : XFF 헤더에서 클라이언트의 출발지 IP를 확인!
    # nginx 웹 데몬에 도착하여 액세스 로그 기록되고, 이후 200ok 리턴되며, XFF 헤더에서 클라이언트의 IP를 확인 할 수 있다
    (istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -f
    127.0.0.6 - - [15/Dec/2021:18:37:38 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.68.0" "192.168.10.254"
    127.0.0.6 - - [15/Dec/2021:18:40:52 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.68.0" "192.168.10.254"
    ...

     

     


    6.2 파드(리턴 트래픽) → 클라이언트

    트래픽 흐름

    • nginx (웹 서버)컨테이너에서 리턴 트래픽(응답, 200 OK)를 클라이언트에 전달합니다.
    • IPTables CT(Connection Table)에 정보를 참고해서 역변환 등이 적용되어 전달됩니다.

    8번 과정의 패킷

    • 200 OK 응답이며, 'Istio-proxy' 에 의해서 x-envoy-upstream-Y 헤더가 추가되어 있습니다.
    더보기
    istio-INBOUND-2.pcap
    0.01MB

     

    (참고) 1.1 에서 알아본 3번 과정 직전과 위 8번 과정의 NAT 트래픽 정보

    c1 conntrack -L --dst-nat
    tcp      6 430172 ESTABLISHED src=172.16.228.76 dst=172.16.46.11 sport=40882 dport=80 src=172.16.46.11 dst=172.16.228.76 sport=15006 dport=40882 [ASSURED] mark=0 use=1
     src=172.16.228.76 dst=172.16.46.11 sport=40882 dport=80     # 3번 과정 직전(IPTables 적용 전)의 IP/Port 정보
     src=172.16.46.11 dst=172.16.228.76 sport=15006 dport=40882  # 8번 과정 의 IP/Port 정보, 특히 출발지 포트가 15006 으로, 'istio-proxy' 경유를 했음을 알 수 있다

    6.3 파드(요청) → 외부 웹서버

    트래픽 흐름

    더보기
    • 파드에서 업데이트 나 패치 다운로드 처럼 외부 웹서버 나 인터넷 연결 과정에서의 트래픽의 흐름입니다.

     

    파드 내 IPTables 적용 흐름 : 아래 (9) ~ (15) 까지의 과정을 먼저 설명합니다.

    더보기
    출처 : https://jimmysong.io/en/blog/sidecar-injection-iptables-and-traffic-routing/

    6.3.1 [파드 내부] Client PC → Istio IngressGateway 파드 구간

     

    ▶ 'nginx 컨테이너' 에서 외부 웹서버 요청을 합니다.

    더보기
    # 아래 처럼 'nginx 컨테이너' 에서 외부 웹서버 요청
    kubectl exec -it nginx-pod -c nginx-container -- curl -s 192.168.10.254
    kubectl exec -it nginx-pod -c nginx-container -- curl -s http://wttr.in/seoul
    kubectl exec -it nginx-pod -c nginx-container -- curl -s wttr.in/seoul?format=3
    kubectl exec -it nginx-pod -c nginx-container -- curl -s 'wttr.in/{London,Busan}'
    kubectl exec -it nginx-pod -c nginx-container -- curl -s http://ipinfo.io/city
    kubectl exec -it nginx-pod -c nginx-container -- curl -k https://www.google.com | grep -o "<title>.*</title>";echo
    while true; do kubectl exec -it nginx-pod -c nginx-container -- curl -s http://ipinfo.io/city; date "+%Y-%m-%d %H:%M:%S" ; echo "--------------" ; sleep 3; done

     

    (참고) 파드 내에서 NAT 트래픽 정보 

    root@k8s-w2:~# c1 conntrack -L --dst-nat
    tcp      6 0 TIME_WAIT src=172.16.46.11 dst=34.117.59.81 sport=59010 dport=80 src=127.0.0.1 dst=172.16.46.11 sport=15001 dport=59010 [ASSURED] mark=0 use=1
    conntrack v1.4.5 (conntrack-tools): 1 flow entries have been shown.
     src=172.16.46.11 dst=34.117.59.81 sport=59010 dport=80     # 최초 요청 트래픽 정보
     src=127.0.0.1    dst=172.16.46.11 sport=15001 dport=59010  # 리턴 트래픽에서 IP/Port 정보를 보면, 출발지 포트가 15001 으로, 'istio-proxy' 경유를 했음을 알 수 있다

     


    6.3.2 [파드 내부] IPTables → Istio-proxy 컨테이너 인입

     

    파드 내 IPTables Chains/Rules 적용 (NAT 테이블) → 'Istio-proxy 컨테이너'로 인입됩니다.

    더보기
    • OUTPUT → ISTIO_OUTPUT → ISTIO_REDIRECT (redir ports 15001)
    # iptables 확인
    c1 iptables -t nat --zero
    c1 iptables -v --numeric --table nat --list ISTIO_REDIRECT
    watch -d "nsenter -t $C1PID -n iptables -v --numeric --table nat --list OUTPUT; echo ; nsenter -t $C1PID -n iptables -v --numeric --table nat --list ISTIO_OUTPUT; echo ; nsenter -t $C1PID -n iptables -v --numeric --table nat --list ISTIO_REDIRECT"
    watch -d "nsenter -t $C1PID -n iptables -t nat -L -n -v"
    
    # nginx 파드에서 TCP 트래픽 요청으로 인입 시, ISTIO_REDIRECT 에서 redir ports 15001 되어 'Istio-proxy 컨테이너'로 인입됩니다.
    c1 iptables -t nat -L -n -v
    Chain OUTPUT (policy ACCEPT 5 packets, 455 bytes)
     pkts bytes target        prot opt in     out     source               destination
        0     0 ISTIO_OUTPUT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Chain ISTIO_OUTPUT (1 references)
     pkts bytes target          prot opt in     out     source               destination
     ...
        0     0 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Chain ISTIO_REDIRECT (1 references)
     pkts bytes target     prot opt in     out     source               destination
        0     0 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001

    6.3.3 [파드 내부] Istio-proxy 컨테이너 → 노드의 호스트 네임스페이스

     

    ▶ 'Istio-proxy 컨테이너' 는 대리인(Proxy) 역할로, 출발지 포트변경(+2) 후 외부 웹서버에 연결을 한다

    더보기
    • 'Istio-proxy 컨테이너'의 로그 확인
    (istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-proxy -f
    [2021-12-15T21:13:34.787Z] "GET /loc HTTP/1.1" 200 - via_upstream - "-" 0 17 187 187 "-" "curl/7.74.0" "d86b9c0b-9519-9c96-9b06-17938fa6ed3b" "ipinfo.io" "34.117.59.81:80" PassthroughCluster 172.16.46.11:36198 34.117.59.81:80 172.16.46.11:36196 - allow_any

     

    • 파드 내에서 패킷 덤프 후 확인 : 출발지 포드를 변경(+2) 및 x-envoy 헤더를 추가
    • lsof 확인 : envoy 에서 외부로 연결되는 정보이며, User ID(UID)가 1337 이다.
    root@k8s-w2:~# c1 lsof -i TCP:80,15006 -n
    COMMAND  PID            USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
    envoy   3928            1337   40u  IPv4 1405154      0t0  TCP 172.16.46.11:38428->34.117.59.81:http (ESTABLISHED)

     

    ▶ 파드를 빠져나가기 전, 다시 한번 더 IPTables 적용 된다 ⇒ 이때, 이전 트래픽과 매칭되는 Rule 이 다른 것은 UID 1337 때문입니다. - Docs

     

    더보기
    • OUTPUT → ISTIO_OUTPUT

     

    # iptables 확인
    c1 iptables -t nat --zero # 패킷 카운트 초기화
    
    # 아래 처럼 Istio-proxy(15001)에서 빠져나온 부분은 UID 1337 매칭되어서 RETURN 되어 파드를 빠져나오게 됩니다!
    c1 iptables -t nat -L -n -v
    Chain ISTIO_OUTPUT (1 references)
     pkts bytes target             prot opt in     out     source               destination
        0     0 RETURN             all  --  *      lo      127.0.0.6            0.0.0.0/0
        0     0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            owner UID match 1337
        0     0 RETURN             all  --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner UID match 1337
        2   120 RETURN             all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
        0     0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            owner GID match 1337
        0     0 RETURN             all  --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner GID match 1337
        0     0 RETURN             all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
        0     0 RETURN             all  --  *      *       0.0.0.0/0            127.0.0.1
        2   120 ISTIO_REDIRECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0
    • istio 애플리케이션 요구 사항 중 일부 - Docs
      • Application UIDs: Ensure your pods do not run applications as a user with the user ID (UID) value of 1337 because 1337 is reserved for the sidecar proxy.

    6.3.4 노드 → 외부

    노드에 SNAT(masquerading) 설정이 되어 있을 경우, 출발지 IP 를 노드의 NIC IP로 변환하여 외부 웹서버에 요청을 전달합니다.

     


    6.4 외부 웹서버(리턴 트래픽) → 파드

    웹 서버에서 리턴 트래픽이 파드에 돌아오는 과정은 **1.**2 에서 알아본 흐름과 유사합니다.

    다만, 파드 내로 인입 시 목적지 포트(+2) 이므로, ‘Nginx 컨테이너’ 로 바로 가지 않고, 'Istio-proxy 컨테이너' 로 먼저 가게 됩니다.


    6.5 실습 종료 후 리소스 삭제

    실습 환경 삭제 : 모든 실습 완료 후에는 꼭 삭제 확인 해주시기 바랍니다.

    더보기
    # CloudFormation 스택 삭제
    aws cloudformation delete-stack --stack-name mylab
    
    # [모니터링] CloudFormation 스택 상태 : 삭제 확인
    while true; do 
      date
      AWS_PAGER="" aws cloudformation list-stacks \
        --stack-status-filter CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED DELETE_IN_PROGRESS DELETE_FAILED \
        --query "StackSummaries[*].{StackName:StackName, StackStatus:StackStatus}" \
        --output table
      sleep 1
    done

     

    • /etc/hosts 에 추가한 내용 삭제

    [ 참고 링크 모음 ]

    더보기

    [추천] Kubernetes CoreDNS - Link

    [추천] istio DNS Proxy,지연개선, DNS부하감소 - Link

    Istio and DNS - Costin Manolache, Google - Link

    추천링크 : Life of a Packet in ISTIO Part 1 - 링크

     Ambient mode 도입기 - Link