WellSpring

7주차 - Service Mesh : Istio-Mode (Sidecar, Ambient) 본문

KANS3 - k8s Advanced Networking Study

7주차 - Service Mesh : Istio-Mode (Sidecar, Ambient)

daniel00324 2024. 10. 15. 12:44
더보기

※ 본 게재 글은 gasida님의 KANS(Kubernetes Advanced Networking Study) 강의내용과 실습예제 및 kubernetes, Ingress, Istio 공식 가이드 문서, "쿠버네티스입문" 서적 등을 참고하여 작성하였습니다. 


0. 실습환경 구성

☞ 구성 요약 : VPC 1개(퍼블릭 서브넷 2개), EC2 인스턴스 3대 (Ubuntu 22.04 LTS, t3.xlarge - vCPU 4 , Mem 16) , testpc 1대는 t3.small

  . CloudFormation 스택 실행 시 파라미터를 기입하면, 해당 정보가 반영되어 배포됩니다.

  . CloudFormation 에 EC2의 UserData 부분(Script 실행)으로 실습 환경에 필요한 기본 설정들이 자동으로 진행됩니다.

 

▶ Cloud Formation 배포

   : 실행하는 PC에 aws cli 설치되어 있고, aws configure 자격증명 설정 상태여야 함  - Ref. Link : Blog 

더보기
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-7w.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 kans-7w.yaml --stack-name mylab --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

## Tip. 인스턴스 타입 변경 : MyInstanceType=t3.xlarge (vCPU 4, Mem 16)
예시) aws cloudformation deploy --template-file kans-7w.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	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	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 접속 할 것!

 

[ 실행 결과 - 한 눈에 보기 ]

k3s-s , testpc 각각 접속 후 확인

  - 구성 요약 : 실습 환경은 K3S v1.30.4 , 노드 OS(Ubuntu 22.04.5) , CNI(Flannel) , IPTABLES proxy mode , Istio v1.23.2(Envoy v1.32.2)

  • [자신의 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
k3s-s	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	running
  • k3s-s 접속 후 확인 : ssh -i <자신의 pem key> 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   8m57s   v1.30.5+k3s1   192.168.10.10    <none>        Ubuntu 22.04.5 LTS   6.8.0-1015-aws   containerd://1.7.21-k3s2
k3s-w1   Ready    <none>                 8m46s   v1.30.5+k3s1   192.168.10.101   <none>        Ubuntu 22.04.5 LTS   6.8.0-1015-aws   containerd://1.7.21-k3s2
k3s-w2   Ready    <none>                 8m45s   v1.30.5+k3s1   192.168.10.102   <none>        Ubuntu 22.04.5 LTS   6.8.0-1015-aws   containerd://1.7.21-k3s2

hostnamectl 
...
 Hardware Vendor: Amazon EC2
  Hardware Model: t3.xlarge

 [ 실행 결과 - 한 눈에 보기 ]

  • testpc 각각 접속 후 확인 : ssh -i < 자신의 pem key > ubuntu@54.180.243.135
더보기
ip -br -c addr
lo               UNKNOWN        127.0.0.1/8 ::1/128 
ens5             UP             192.168.10.200/24 metric 100 fe80::3:e9ff:fefa:85d9/64 

hostnamectl 
...
 Hardware Vendor: Amazon EC2
  Hardware Model: t3.small

 [ 실행 결과 - 한 눈에 보기 ]

 

 


1. Istio 란?

 - 서비스 메시 는 코드 변경 없이 애플리케이션에 제로 트러스트 보안, 관찰 가능성, 고급 트래픽 관리와

   같은 기능을 제공 하는 인프라 계층입니다. 

 - 2016년 Google, IBM, Lyft가 설립한 Istio는 Kubernetes 및 Prometheus와 같은 프로젝트와 함께

   Cloud Native Computing Foundation에서 졸업한 프로젝트임

 - mTLS 암호화, 정책 관리 및 액세스 제어를 포함한 보안 및 거버넌스 제어를 지원하고 , 카나리아 배포,

   A/B 테스트,  부하 분산, 장애 복구와 같은 네트워크 기능을 제공하며 , 부지 전체의 트래픽을 

   관찰할 수 있도록 합니다 .

[ 출처 : https://istio.io/latest/about/service-mesh/ ]

 

1-1. 등장배경

 - 마이크로서비스 아키텍처 환경의 시스템이 등장함에 따라 서비스 연동구조가 복잡해 지면서

   전체 모니터링의 어려움 생겨나고, 운영 시 시스템 장애나 문제 발생 시, 원인과 병목 구간을 찾기가

   어려움 에 따라 솔루션을 찾게됨

 

1-2. 특징

1) 기본적으로 보안 적용 ( Secure by default )

  - Istio는 워크로드 ID, 상호 TLS 및 강력한 정책 제어를 기반으로 하는 시장을 선도하는 제로 트러스트 솔루션을 제공

 

[ More ... ]

더보기
  • Istio는  데이터, 엔드포인트, 커뮤니케이션 및 플랫폼에 대한 내부 및 외부 위협을 완화해 준다.
[ Istio가 제공하는 보안 기능들 ]

 

  1. 기본 보안: 애플리케이션 코드 및 인프라를 변경할 필요 없음
  2. 심층 방어: 기존 보안 시스템과 통합하여 다중 계층의 방어 제공
  3. 제로 트러스트 네트워크: 신뢰할 수 없는 네트워크에 보안 솔루션 구축

Istio proxy : Golang 으로 작성되었고 envoy 래핑한 Proxy, istiod와 통신하고 서비스 트래픽을 통제, 옵저버빌리티를 위한 메트릭 제공

 

Istio Proxy는 Control Plane에서 API Server의 configuration을 관리하고, Data Plane에서 PEP를 구성한다.

 

* PEP 란?

 - Police Enforce Point 로 Traffic 처리를 함에 있어서 정책적으로 강화된 연결점을 제공해 준다.

 - 웹 서비스에서 노출된 리소스를 실제로 보호(액세스 제어 측면에서)하는 메커니즘  

 

 

♣ Pilot : configuration 관리
 Citadel : mTLS, Security 통신 처리
 Galley : Ingress -> POD 엔드포인트 바로 통신 가능한 것은 galley가 바로 파드정보 확인가능하기 때문

2) 증가된 관찰성 제공 (Increase Observability)

 - Istio는 서비스 메시 내에서 원격 측정을 생성하여 서비스 동작에 대한 관찰을 가능하게 해줌

 - Grafana, Prometheus 등 연계 Tool을 통해 가시성을 극대화함

 

[ More ... ]

더보기
  • Istio는 전반적인 서비스 메시 관찰성을 제공하기 위해 다음 유형의 원격 측정을 생성합니다.

 

1) Metric : Istio는 모니터링의 4가지 "golden Signals"( latency, traffic, errors, and saturation )를 기반으로 일련의 서비스 메트릭을 생성 해 준다.

2) Distributed Tracds :  Istio는 각 서비스에 대한 분산 추적 범위를 생성하여 운영자에게 메시 내의 호출 흐름과

서비스 종속성에 대한 자세한 이해를 제공

 

3) Access Logs : 트래픽이 메시 내의 서비스로 유입되면 Istio는 소스 및 대상 메타데이터를 포함하여 각 요청의 전체 기록을 생성할 수 있습니다. 이 정보를 통해 운영자는 개별 워크로드 인스턴스 수준까지 서비스 동작을 감사할 수 있습니다.

 

3) 트래픽 관리기능 제공 ( Manage Traffic )

  - 트래픽 라우팅과 서비스 수준 구성을 간소화하여 서비스 간 흐름을 쉽게 제어하게 해줌

  - A/B 테스트, 카나리아 배포, 백분율 기반 트래픽 분할을 통한 단계적 롤아웃과 같은 작업을 설정할 수 있게 도와줌

 

[ More ... ]

더보기
  • Istio의 트래픽 라우팅 규칙을 사용하면 서비스 간의 트래픽 흐름과 API 호출을 쉽게 제어할 수 있다.

 

☞ 서비스와 연관하여 설치된 Envoy Proxy data-plane 에서 처리되는 Traffic을 서비스 변경없이 자동으로 파악하고  제어할 수 있도록 도와준다.

 

- 대부분의 마이크로서비스 기반 애플리케이션은 각 서비스 워크로드의 여러 인스턴스를 사용하여 서비스 트래픽을 처리하는데, 이를 로드 밸런싱 풀이라고도 합니다. 기본적으로 Envoy 프록시최소 요청 모델( least requests model )을 사용하여 각 서비스의 로드 밸런싱 풀에 트래픽을 분산합니다. 여기서 각 요청은 풀에서 무작위로 선택된 두 호스트에서 활성 요청이 적은 호스트로 라우팅됩니다. 이런 방식으로 가장 부하가 많은 호스트는 다른 호스트보다 더 부하가 없을 때까지 요청을 수신하지 않습니다.

 

 

1-3. Istio 의 장점

1) 다양한 배포 모드를 제공

2) 강력한 기능의 Envoy Proxy 제공

  - Simple, Powerful function

  - 최초의 외부 community 로, Google Cloud에서 사용하는 Load Balancer ( Rich Reference examples 보유 )

  - Istio팀이 개발한 WebAssembly를 사용하여 Global expendability를 보유함

3) 안정적인 Binary 릴리즈를 제공

 

[ More ... ]

더보기

1. Why not use "eBPF"?

eBPF는 리눅스 커널단에서 동작하는 머신이며, 간단한 L3 트래픽 라우팅이나 애플리케이션 관찰과

   같은 불안정한 커널 동작을 피하기 위해 제한된 컴퓨팅 봉투에서 완료되도록 보장된 기능을 위해 설계

   되었습니다. Envoy에서 발견되는 것과 같은 장기 실행 또는 복잡한 기능을 위해 설계되지 않았습니다.

   이것이 바로 OS가 User Space를 가지고 있는 이유가 됩니다. 

   Envoy만큼 복잡한 프로그램을 실행하도록 확장될 수 있다고 이론화했지만, 이는 과학 프로젝트이며

   실제 세계에서 실용성이 없을 가능성이 높습니다.

 

2. Why not use a per-node Proxy?

☞ Envoy는 본직적으로 Multi-tenant 가 아닙니다.

    그 결과, 공유 인스턴스에서 여러 제약 없는 테넌트의 L7 트래픽에 대한 복잡한 처리 규칙을 혼합하면

    보안 및 안정성에 큰 문제가 발생합니다. Kubernetes는 기본적으로 모든 네임스페이스에서 모든 노드로

    포드를 예약할 수 있으므로 노드는 적절한 테넌시 경계가 아닙니다.

    예산 책정 및 비용 귀속도 주요 문제인데, L7 처리 비용이 L4보다 훨씬 더 많이 들기 때문입니다.

앰비언트 모드에서는 ztunnel 프록시를 Linux 커널과 마찬가지로 L4 처리로 엄격하게 제한합니다 .

    이렇게 하면 취약성 표면 영역이 상당히 줄어들고 공유 구성 요소를 안전하게 작동할 수 있습니다.

     그런 다음 트래픽은 네임스페이스별로 작동하는 Envoy 프록시로 전달되므로 Envoy 프록시는

     결코 멀티 테넌트가 되지 않습니다.

 

 

3. Why "CNI" is not able to be a substitue object of Istio? 

☞ CNI가 제공하는 Mesh-Addon 은 비표준으로 제한적 환경에서만 동작한다.

    오늘날 일부 CNI 플러그인은 자체 CNI 구현 위에 있는 애드온으로 서비스 메시와 유사한 기능을 제공하기

    시작했습니다. 예를 들어, 노드 또는 포드 간 트래픽에 대한 자체 암호화 체계를 구현하거나, 워크로드 ID를 

    구현하거나, 트래픽을 L7 프록시로 리디렉션하여 일정 수준의 전송 수준 정책을 지원할 수 있습니다. 

    그러나, 이러한 서비스 메시 애드온은 비표준이므로 이를 제공하는 CNI 위에서만 작동할 수 있습니다. 

 

  반면, Istio는 일관적이고, 높은 보안성, 효율성, 표준을 준수하는 서비스 메시 구현을 제공하는 서비스 메시로

     설계되었으며, 강력한 L7 정책 세트 와 플랫폼에 독립적인 워크로드 ID를 제공하고 , 업계에서 검증된 mTLS 

     프로토콜을 사용하여 어떤 환경, 어떤 CNI를 사용하든, 심지어 서로 다른 CNI를 사용하는 클러스터에서도 

     사용 가능합니다.

 


2. Envoy

2-1. Envoy 란?

-   Envoy는 대규모 현대 서비스 지향 아키텍처를 위해 설계된 L7 프록시 및 통신 버스를 지칭 합니다.

-   Envoy는 하기의 2가지 base 개념을 바탕으로 생성됩니다.

   1) 모든 네트웍은 투명(transparancy) 해야 한다.

   2) 네트워크 및 어플리케이션에 문제가 생겼을 때, 문제의 근원을 쉽게 파악할 수 있어야 한다.

 

L4/7 Proxy , Istio 의 Sidecar proxy 로 사용* - 링크 주요 용어

더보기

[ Envoy 의 Traffic 처리 개념도 ]

 

 

♣ 주요 용어 설명

 

호스트 : 네트워크 통신이 가능한 엔터티(모바일 폰, 서버 등의 애플리케이션). 이 문서에서 호스트는 논리적 네트워크 애플리케이션입니다. 물리적 하드웨어는 각각이 독립적으로 주소 지정될 수 있는 한 여러 호스트를 실행할 수 있습니다.

다운스트림 : 다운스트림 호스트는 Envoy에 연결하여 요청을 보내고 응답을 받습니다.

업스트림 : 업스트림 호스트는 Envoy로부터 연결과 요청을 받고 응답을 반환합니다.

리스너 : 리스너는 다운스트림 클라이언트가 연결할 수 있는 명명된 네트워크 위치(예: 포트, 유닉스 도메인 소켓 등)입니다. Envoy는 다운스트림 호스트가 연결하는 하나 이상의 리스너를 노출합니다.

클러스터 : 클러스터는 Envoy가 연결하는 논리적으로 유사한 업스트림 호스트의 그룹입니다. Envoy는 서비스 검색을 통해 클러스터의 멤버를 검색합니다 . 선택적으로 활성 상태 검사를 통해 클러스터 멤버의 상태를 확인합니다 . Envoy가 요청을 라우팅하는 클러스터 멤버는 로드 밸런싱 정책 에 의해 결정됩니다 .

메시 : 일관된 네트워크 토폴로지를 제공하기 위해 조정하는 호스트 그룹입니다. 이 문서에서 "Envoy 메시"는 다양한 서비스와 애플리케이션 플랫폼으로 구성된 분산 시스템을 위한 메시지 전달 기판을 형성하는 Envoy 프록시 그룹입니다.

런타임 구성 : Envoy와 함께 배포된 대역 외 실시간 구성 시스템. Envoy를 다시 시작하거나 기본 구성을 변경하지 않고도 작동에 영향을 미치는 구성 설정을 변경할 수 있습니다.

Istio 구성요소와 envoy

    : 컨트롤 플레인(istiod) - ADS 를 이용한 Configuration 동기화 - 데이터 플레인(istio-proxy → envoy)

 

[ 출처 : https://blog.naver.com/alice_k106/222000680202 ]

 

 

Envoy는 구성을 동적으로 관리하기 위한 강력한 API를 제공하는 것이 중요합니다.

더보기

◎ Service Mesh 솔루션이나, Gateway API 구현체들을 Enovy를 내부적으로 사용하고 있으며,

     Envoy가 제공하는 동적 구성을 위한 API (xDS Sync API)를 이용하여 다양한 네트워크 정책을 구성하게 됩니다.

 

 

[ Envoy 가 동작하는 Layer 들 ]

 

LDS - Listener Discovery Service

RDS - Route Discovery Service

CDS - Cluseter Discovery Service

EDS - Endpoint Discovery Service

 

 

 

 

 

 

[ 출처 : https://blog.naver.com/yu3papa/223614975957 ]

  

 . Control-Plane 에 있는 Pilot 과 Envoy-Proxy Agent 사이 통신을 통해 구성요소에 대해 동적으로 업데이트 한다.

  


2-2. Envoy 실습

▶ testpc EC2에 Envoy 설치하기

더보기
# 설치
wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
sudo apt-get update && sudo apt-get install envoy -y

# 확인
envoy --version

# 도움말
envoy --help

 

[ 실행 결과 - 한 눈에 보기 ]

▶ envoy-demo.yaml 다운로드 및 설치 후, 구성내용 확인하기

더보기

♣ envoy-demo.yaml   ( ※  Cluster 는 endpoint 들을 포함한다!! )

static_resources:

  listeners:
  - name: listener_0
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          http_filters:
          - name: envoy.filters.http.router
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite_literal: www.envoyproxy.io
                  cluster: service_envoyproxy_io

  clusters:
  - name: service_envoyproxy_io
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    connect_timeout: 5s
    load_assignment:
      cluster_name: service_envoyproxy_io
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.envoyproxy.io
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        sni: www.envoyproxy.io
# (터미널1) 데모 config 적용하여 실행
curl -O https://www.envoyproxy.io/docs/envoy/latest/_downloads/92dcb9714fb6bc288d042029b34c0de4/envoy-demo.yaml
envoy -c envoy-demo.yaml


# (터미널2) 정보 확인
ss -tnlp
State    Recv-Q  Send-Q    Local Address:Port   Peer Address:Port    Process
LISTEN   0       4096      0.0.0.0:10000        0.0.0.0:*            users:(("envoy",pid=8007,fd=18),("envoy",pid=8007,fd=16))

# 접속 테스트
curl -s http://127.0.0.1:10000 | grep -o "<title>.*</title>"

# 외부 접속 정보 출력
echo -e "http://$(curl -s ipinfo.io/ip):10000"
http://54.180.243.135:10000

--------------------
# 자신의 PC 웹브라우저에서 외부 접속 정보 접속 확인!

# k3s-s 에서 접속 테스트
curl -s http://192.168.10.200:10000 | grep -o "<title>.*</title>" 
--------------------

# 연결 정보 확인
ss -tnp

# (터미널1) envoy 실행 취소(CTRL+C) 후 (관리자페이지) 설정 덮어쓰기 - 링크
cat <<EOT> envoy-override.yaml
admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9902
EOT
envoy -c envoy-demo.yaml --config-yaml "$(cat envoy-override.yaml)"

# envoy 관리페이지 외부 접속 정보 출력
echo -e "http://$(curl -s ipinfo.io/ip):9902"
http://54.180.243.135:9902

--------------------
# 자신의 PC 웹브라우저에서 관리 페이지 외부 접속 정보 접속 확인!

 

[ 실습 결과 - 한 눈에 보기 ]

[ 도전과제 1. Envoy 공식문서에 Quick start 전체 내용을 실습 및 정리해보자 ]

 

더보기

1 ~ 2. Envoy Validation & Logging

3. Envoy Networking

 - 기본적으로 IPv4 와 IPv6를 같이 사용가능하다.

 - 만약, 서비스 특성 상 IPv4 만 사용하고자 한다면, 옵션 설정으로 IPv6를 disable 할 수 있다.

  clusters:
  - name: service_envoyproxy_io
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    load_assignment:
      cluster_name: service_envoyproxy_io
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:

 

 

4. Debugging Envoy

- Default : info

- Supplied Level : trace, debug, info, warning/warn, error, critical, off

 

 5. Configuration Static

- Static configuration 을 사용하기 위해서는 listeners 와 clusters를  static_resources 에서 선언해야 한다.

 

6. Configuration: Dynamic from filesystem

You can start Envoy with dynamic configuration by using files that implement the xDS protocol.

When the files are changed on the filesystem, Envoy will automatically update its configuration.

※  Envoy only updates when the configuration file is replaced by a file move, and not when

     the file is edited in place. It is implemented this way to ensure configuration consistency.

 ( 파일 정합성을 맞추기 위해, 수정 시는 제외하고, 파일이 교체 될 경우만 자동으로 반영된다. )

 

node:
  cluster: test-cluster
  id: test-id

dynamic_resources:
  cds_config:
    path: /var/lib/envoy/cds.yaml

 

  • node to uniquely identify the proxy node.
  • dynamic_resources to tell Envoy where to find its dynamic configuration.

제공된 예제에서 xDS는 다음과 같이 매핑된다.

노드는 cluster 와 id   키, 값으로 정의되며, unique 한 값으로 지정되어야 한다.

  id: test-id

dynamic_resources:
  cds_config:
    path: /var/lib/envoy/cds.yaml
  lds_config:
    path: /var/lib/envoy/lds.yaml

Dynamic_resource는 해당 설정파일이 어디에 정의 되어 있는지 확인할 수 있다.

 

7. Configuration: Dynamic from control plane

 - control plane 의 설정이 병행되어야 하므로, 약간 더 복잡해 진다.

 - Envoy는 여러 API와 호환이 된다. (예를 들면, Gloo 와 istio 가 있다.)

 - configuration의 변화에 동적으로 대응하기 위해서 dynamic_resources 이하 필요한 구성을 지정할 수 있다.

  id: test-id

dynamic_resources:
  ads_config:
    api_type: GRPC
    grpc_services:
    - envoy_grpc:
        cluster_name: xds_cluster
  cds_config:
    ads: {}
  lds_config:
    ads: {}

static_resources:
  clusters:
  - type: STRICT_DNS
    typed_extension_protocol_options:
  • node to uniquely identify the proxy node.
  • dynamic_resources to tell Envoy which configurations should be updated dynamically
  • static_resources to specify where Envoy should retrieve its configuration from.
node:
  cluster: test-cluster
  id: test-id

dynamic_resources:
  ads_config:
    api_type: GRPC
    grpc_services:
    - envoy_grpc:
        cluster_name: xds_cluster
  cds_config:
    ads: {}
  lds_config:
    ads: {}

static_resources:
  clusters:
  - type: STRICT_DNS
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    name: xds_cluster
    load_assignment:
      cluster_name: xds_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: my-control-plane
                port_value: 18000

admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 19000

 

   


3. istio 설치 ( sidecar mode )

공식 문서 링크를 통해 istio 에 대해 상세히 확인할 수 있다.

- Ref. link : https://istio.io/latest/docs/

 

Istio Sidecar mode 설치 : v1.23.2 - 버전 설치 , without GwApi - Docs

https://istio.io/latest/docs/setup/install/operator/

참고 : The Istio operator is deprecated. 

더보기

Operator-based Installations of Istio will continue to run indefinitely, but cannot be upgraded past 1.23.x. Please see the announcement to learn how to upgrade to a supported installation method. https://istio.io/latest/blog/2024/in-cluster-operator-deprecation-announcement/

 

Istio has deprecated its In-Cluster Operator

What you need to know if you are running the Operator controller in your cluster.

istio.io

 

 

https://istio.io/latest/docs/setup/additional-setup/config-profiles/

 

▶ 새로운 sail operator 설치 방법 소개 : https://istio.io/latest/blog/2024/introducing-sail-operator/

더보기
# istioctl 설치
export ISTIOV=1.23.2
echo "export ISTIOV=1.23.2" >> /etc/profile
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV TARGET_ARCH=x86_64 sh -
tree istio-$ISTIOV -L 2 # sample yaml 포함
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# (default 프로파일) 컨트롤 플레인 배포 - 링크 Customizing
# The istioctl command supports the full IstioOperator API via command-line options for individual settings or for passing a yaml file containing an IstioOperator custom resource (CR).
istioctl profile list
istioctl profile dump default
istioctl profile dump --config-path components.ingressGateways
istioctl profile dump --config-path values.gateways.istio-ingressgateway
istioctl profile dump demo

istioctl profile dump demo > demo-profile.yaml
vi demo-profile.yaml # 복잡성을 줄이게 실습 시나리오 환경 맞춤
--------------------
    egressGateways:
    - enabled: false
--------------------    

istioctl install -f demo-profile.yaml
✔ Istio core installed ⛵️                                                                                                          
✔ Istiod installed 🧠                                                                                                              
✔ Ingress gateways installed 🛬                                                                                                    
✔ Installation complete                                                                                                            

# 설치 확인 : istiod, istio-ingressgateway
kubectl get all,svc,ep,sa,cm,secret -n istio-system
kubectl get crd  | grep istio.io | sort

# istio-ingressgateway 의 envoy 버전 확인
kubectl exec -it deploy/istio-ingressgateway -n istio-system -c istio-proxy -- envoy --version
envoy  version: 6c72b2179f5a58988b920a55b0be8346de3f7b35/1.31.2-dev/Clean/RELEASE/BoringSSL

# istio-ingressgateway 서비스 NodePort로 변경
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"type":"NodePort"}}'

# istio-ingressgateway 서비스 확인
kubectl get svc,ep -n istio-system istio-ingressgateway

## istio-ingressgateway 서비스 포트 정보 확인
kubectl get svc -n istio-system istio-ingressgateway -o jsonpath={.spec.ports[*]} | jq

## istio-ingressgateway 디플로이먼트 파드의 포트 정보 확인 
kubectl get deploy/istio-ingressgateway -n istio-system -o jsonpath={.spec.template.spec.containers[0].ports[*]} | jq
kubectl get deploy/istio-ingressgateway -n istio-system -o jsonpath={.spec.template.spec.containers[0].readinessProbe} | jq

# istiod 디플로이먼트 정보 확인
kubectl exec -it deployment.apps/istiod -n istio-system -- ss -tnlp
kubectl exec -it deployment.apps/istiod -n istio-system -- ss -tnp
kubectl exec -it deployment.apps/istiod -n istio-system -- ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
istio-p+       1       0  0 05:27 ?        00:00:07 /usr/local/bin/pilot-discovery discovery --monitoringAddr=:15014 --log_output_l

# istio-ingressgateway 디플로이먼트 정보 확인
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -tnlp
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -tnp
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ps -ef
istio-p+       1       0  0 05:27 ?        00:00:01 /usr/local/bin/pilot-agent proxy router --domain istio-system.svc.cluster.local
istio-p+      15       1  0 05:27 ?        00:00:11 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drai

kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- cat /etc/istio/proxy/envoy-rev.json
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -xnlp
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -xnp

# istio-ingressgateway 서비스 externalTrafficPolicy 설정 : 점검
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'

 

[ 실행 결과 - 한 눈에 보기 ]

 

 

 

 

  

 

  • Auto Injection with namespace label : 해당 네임스페이스에 생성되는 모든 파드들은 istio 사이드카가 자동으로 injection 됨
더보기
# mutating Webhook admisstion controller 사용
kubectl label namespace default istio-injection=enabled
kubectl get ns -L istio-injection
NAME              STATUS   AGE     ISTIO-INJECTION
default           Active   58m     enabled
...

 

▶ Istio 접속 테스트를 위한 환경변수 설정 * 

 

더보기
  • k3s-s 노드에서 수행
k3s-s)
# istio ingress gw NodePort(HTTP 접속용) 변수 지정 : 아래 ports[0] 은 어떤 용도의 포트일까요?
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
echo $IGWHTTP
IGWHTTP=<각자 자신의 NodePort>

## istio-ingressgateway 파드가 배치된 노드의 유동 공인 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	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	running

# /etc/hosts 파일 수정
MYDOMAIN=<각자 자신의 www 도메인> # 단, 사용하고 있지 않는 공인 도메인을 사용 할 것
MYDOMAIN=www.gasida.dev
echo "<istio-ingressgateway 파드가 있는 워커 노드> $MYDOMAIN" >> /etc/hosts

MYDOMAIN=<각자 자신의 www 도메인>
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

 [ 실행 결과 - 한 눈에 보기 ]

  • TestPC에서 수행
# 아래 변수는 각자 자신의 값을 직접 입력 할 것
IGWHTTP=<각자 출력된 NodePort>
IGWHTTP=32759
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

 

  • 자신의 local PC에서 수행
# 아래 변수는 각자 자신의 값을 직접 입력 할 것 : ISTIONODEIP는 3개의 노드 중 아무거나 입력
IGWHTTP=<각자 출력된 NodePort>
IGWHTTP=32759
ISTIONODEIP=<k3s-s 의 유동 공인 IP>
ISTIONODEIP=3.38.208.153

MYDOMAIN=www.gasida.dev
echo "$ISTIONODEIP $MYDOMAIN" | sudo tee -a /etc/hosts

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

 

[ 실행 결과 - 한 눈에 보기 ] 

[ 도전과제 - 추후 작성 예정 ]

더보기

도전과제2. Istio 진입점에 해당하는 IngressGateway 를 GatewayAPI로 구성 - Docs , Istio-GwApi

https://istio.io/latest/blog/2024/gateway-mesh-ga/

https://kubernetes.io/blog/2024/05/09/gateway-api-v1-1/

⇒ 향후 IngressGateway 는 어떻게 경쟁과 발전할 것인지, 그리고 표준의 주도권은 누가 가져갈 것 인지 한번 생각해보자.

 

도전과제3. Istio EgressGateway 를 구성해보자

https://istio.io/latest/docs/tasks/traffic-management/egress/

https://istio.io/latest/blog/2023/egress-sni/

 

 


4. Istio 통한 외부 노출

▶ Nginx 디플로이먼트와 서비스 배포

더보기
# 로그 모니터링
kubectl get pod -n istio-system -l app=istiod
kubetail -n istio-system -l app=istiod -f

kubectl get pod -n istio-system -l app=istio-ingressgateway
kubetail -n istio-system -l app=istio-ingressgateway -f

 

cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-websrv
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deploy-websrv
  template:
    metadata:
      labels:
        app: deploy-websrv
    spec:
      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
# 사이드카 컨테이너 배포 확인
kubectl get pod,svc,ep -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
deploy-websrv-7d7cf8586c-rhhv8   2/2     Running   0          29s   172.16.2.6   k3s-w2   <none>           <none>
...

kc describe pod

 

[ 실행 결과 - 한 눈에 보기 ]

[ Tip & Tips : istio 설치부터 injection 거부설정까지 - shortcut ]

더보기

 

  

☞ 자원 Clear : kubectl delete deploy,svc --all

▶ Istio Gateway/VirtualService 설정 - Host 기반 트래픽 라우팅 설정 - Gateway

더보기

 

  • 클라이언트 PC → (Service:NodePort) Istio ingressgateway 파드 → (Gateway, VirtualService, Service 는 Bypass) → Endpoint(파드 : 사이드카 - Application 컨테이너)
  • Gateway : 지정한 인그레스 게이트웨이로부터 트래픽이 인입, 프로토콜 및 포트, HOSTS, Proxy 등 설정 가능
https://istio.io/latest/docs/setup/additional-setup/gateway/
  • VirtualService : 인입 처리할 hosts 설정, L7 PATH 별 라우팅, 목적지에 대한 정책 설정 가능 (envoy route config)
  • (참고) Introducing Istio v1 APIs - Blog
cat <<EOF | kubectl create -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"
  gateways:
  - test-gateway
  http:
  - route:
    - destination:
        host: svc-clusterip
        port:
          number: 80
EOF

 

# Istio Gateway(=gw)/VirtualService(=vs) 설정 정보를 확인
kc explain gateways.networking.istio.io
kc explain virtualservices.networking.istio.io
kubectl api-resources  | grep istio

# virtual service 는 다른 네임스페이스의 서비스(ex. svc-nn.<ns>)도 참조할 수 있다
kubectl get gw,vs
NAME                                       AGE
gateway.networking.istio.io/test-gateway   21s

NAME                                               GATEWAYS           HOSTS                AGE
virtualservice.networking.istio.io/nginx-service   ["test-gateway"]   ["www.gasida.dev"]   4m9s

# Retrieves last sent and last acknowledged xDS sync from Istiod to each Envoy in the mesh
# istioctl proxy-status command was improved to include the time since last change, and more relevant status values.
istioctl proxy-status # 단축어 ps
istioctl ps

 

[ 실행 결과 - 한 눈에 보기 ]

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

더보기
  • 외부(자신의PC, testpc)에서 접속 테스트
# istio ingress gw 를 통한 접속 테스트
curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
curl -v -s $MYDOMAIN:$IGWHTTP
curl -v -s <유동공인이IP>:$IGWHTTP
  • 출력 로그 정보 확인
kubetail -n istio-system -l app=istio-ingressgateway -f
kubetail -l app=deploy-websrv

 

Istio proxy 로그 출력 중
  • istioctl 정보 확인
#
istioctl proxy-status
NAME                                                   CLUSTER        CDS                LDS                EDS                RDS                ECDS        ISTIOD                      VERSION
deploy-websrv-7d7cf8586c-l22cs.default                 Kubernetes     SYNCED (22m)       SYNCED (22m)       SYNCED (22m)       SYNCED (22m)       IGNORED     istiod-7f8b586864-mv944     1.23.2
istio-ingressgateway-5f9f654d46-c4g7s.istio-system     Kubernetes     SYNCED (5m19s)     SYNCED (5m19s)     SYNCED (5m19s)     SYNCED (5m19s)     IGNORED     istiod-7f8b586864-mv944     1.23.2

# Envoy config dump : all, cluster, endpoint, listener 등
istioctl proxy-config --help 
istioctl proxy-config all deploy-websrv-7d7cf8586c-l22cs
istioctl proxy-config all deploy-websrv-7d7cf8586c-l22cs -o json | jq
istioctl proxy-config route deploy-websrv-7d7cf8586c-l22cs -o json | jq
  • pilot : istio-proxy 내 uds 로 envoy 와 grpc 통신, istiod 받아온 dynamic config 를 envoy 에 전달
# istio-proxy 사용자 정보 확인 : uid(1337):gid(1337) 확인 -> iptables rule 에서 사용됨
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- tail -n 3 /etc/passwd
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
tcpdump:x:100:102::/nonexistent:/usr/sbin/nologin
istio-proxy:x:1337:1337::/home/istio-proxy:/bin/sh

# envoy 설정 정보 확인 : dynamic_resources , static_resources - listeners  : 출력되는 IP가 누구인지 확인 해보자
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- cat /etc/istio/proxy/envoy-rev.json
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- ss -nlp
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- ss -np
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- netstat -np
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 172.16.1.10:15021       172.16.1.1:49548        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:15006       172.16.2.4:37814        ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:43138        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:39158         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:42948        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51370       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 172.16.1.10:15021       172.16.1.1:39522        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51360       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 127.0.0.1:39172         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39158         ESTABLISHED 1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39172         ESTABLISHED 1/pilot-agent       

Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  3      [ ]         STREAM     CONNECTED     151002   1/pilot-agent        var/run/secrets/workload-spiffe-uds/socket
unix  3      [ ]         STREAM     CONNECTED     152729   -                    
unix  3      [ ]         STREAM     CONNECTED     152723   -                    
unix  3      [ ]         STREAM     CONNECTED     152727   -                    
unix  3      [ ]         STREAM     CONNECTED     150129   12/envoy             
unix  3      [ ]         STREAM     CONNECTED     152726   -                    
unix  3      [ ]         STREAM     CONNECTED     152724   -                    
unix  3      [ ]         STREAM     CONNECTED     152722   -                    
unix  3      [ ]         STREAM     CONNECTED     150979   12/envoy             
unix  3      [ ]         STREAM     CONNECTED     152728   -                    
unix  3      [ ]         STREAM     CONNECTED     152725   -                    
unix  3      [ ]         STREAM     CONNECTED     150120   1/pilot-agent        etc/istio/proxy/XDS

#
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
istio-p+       1       0  0 07:11 ?        00:00:00 /usr/local/bin/pilot-agent proxy sidecar --domain default.svc.cluster.local --p
istio-p+      12       1  0 07:11 ?        00:00:02 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drai
istio-p+      91       0  0 07:21 pts/0    00:00:00 ps -ef

# 출력되는 IP가 누구인지 확인 해보자
kubectl get pod,svc -A -owide
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:15004         0.0.0.0:*               LISTEN      1/pilot-agent       
tcp        0      0 127.0.0.1:15000         0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 172.16.1.10:15006       172.16.2.4:37814        ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:42632        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:39158         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:55752        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51370       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 172.16.1.10:15021       172.16.1.1:50394        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51360       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 172.16.1.10:15021       172.16.1.1:49496        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:39172         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::15020                :::*                    LISTEN      1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39158         ESTABLISHED 1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39172         ESTABLISHED 1/pilot-agent  


# istiod 정보 같이 확인 : 출력되는 IP가 누구인지 확인 해보자
kubectl get pod,svc -A -owide
kubectl exec -it deploy/istiod -n istio-system -- ps -ef
kubectl exec -it deploy/istiod -n istio-system -- netstat -antp
kubectl exec -it deploy/istiod -n istio-system -- ss -nlp
kubectl exec -it deploy/istiod -n istio-system -- ss -np

 

 [ 실행 결과 - 한 눈에 보기 ]

 

더보기
[ Istio Proxy 사용 포트리스트 ]

 

[ Istiod - control plane 사용 포트리스트 ]

 

istio-proxy 사이드카 컨테이너의 Pilot agent 프로세스와 Envoy 프로세스의 사용 포트 정보

 

출처 : https://www.anyflow.net/sw-engineer/istio-internals-by-port

 

(심화) Debug 모드 : Pod debugging

더보기
#
kubectl get pod
kc describe pod

# 방안1 : 파드의 복제본을 이용
kubectl debug $(kubectl get pod -l app=deploy-websrv -oname) -it --image=nicolaka/netshoot -c netdebug --share-processes --copy-to=websrv-debug --profile='sysadmin'
-----
ip -c addr
curl localhost

ps axf
PID   USER     TIME  COMMAND
    1 65535     0:00 /pause
   26 root      0:00 nginx: master process nginx -g daemon off;
   57 101       0:00 nginx: worker process
   58 101       0:00 nginx: worker process
   59 root      0:01 zsh
   89 1337      0:00 /usr/local/bin/pilot-agent proxy sidecar --domain default.svc.cluster.local --proxyLogLevel=warning --proxyC
  137 1337      0:00 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev0.json --restart-epoch 0 --drain-time-s 45 --drain-strategy
  188 root      0:00 ps axf

ss
ss -l
ss -4tpl
ss -4tp
ss -xpl
ss -xp

netstat -n

exit
-----
kubectl delete pod websrv-debug


# 방안2 : 동작 중인 파드 내 컨테이너 삽입
kubectl debug $(kubectl get pod -l app=deploy-websrv -oname) -it --image=nicolaka/netshoot -c netdebug --profile='netadmin'
-----
ip -c addr
curl localhost
ps axf
ss
ss -l
ss -4tpl
ss -4tp
ss -xpl
ss -xp

tcpdump -i. ..
네트워크 툴...

exit
-----

 

[ 실행 결과 - 한 눈에 보기 ]

 

 

▶ (심화 옵션) IPC & UDS 관련 정보 링크 - UDS 소개2 IPC방법들

 

▶ Istio - Envoy xDS (x Discovery Service, Dynamic API Configuration) - 링크

더보기
  • 동적으로 각 영역의 설정을 로드하는 방법
  • Management 서비스(Istiod)와 통신하면서 configuration 을 갱신 : Istod - [Istop-proxy ↔ envoy]
  • gRPC, REST 방식 모두 지원
  • CDS(Clusters) , LDS(Listeners) , EDS(Endpoints), RDS(Routes) → Discovery Service ⇒ ADS (Aggregation Discovery Service) ↔ Istiod
# proxy 상태 확인
istioctl proxy-status
NAME                                                   CLUSTER        CDS               LDS               EDS              RDS               ECDS        ISTIOD                      VERSION
deploy-websrv-7d7cf8586c-tvzk6.default                 Kubernetes     SYNCED (55s)      SYNCED (55s)      SYNCED (55s)     SYNCED (55s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
istio-ingressgateway-5f9f654d46-c4g7s.istio-system     Kubernetes     SYNCED (4m1s)     SYNCED (4m1s)     SYNCED (55s)     SYNCED (4m1s)     IGNORED     istiod-7f8b586864-mv944     1.23.2
...

 

 

 

  • ADS 를 통해 다양한 타입의 리소스를 싱글 스트림에서 해결

https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol#aggregated-discovery-service

 

xDS REST and gRPC protocol — envoy 1.33.0-dev-2f9104 documentation

API flow For typical HTTP routing scenarios, the core resource types for the client’s configuration are Listener, RouteConfiguration, Cluster, and ClusterLoadAssignment. Each Listener resource may point to a RouteConfiguration resource, which may point t

www.envoyproxy.io

 

 [ 증분 xDS ]

  • Incremental xDS https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol#incremental-xds

    • 프로토콜이 리소스/리소스 이름 델타("Delta xDS") 측면에서 와이어에서 통신할 수 있도록 합니다.
      이는 xDS 리소스의 확장성이라는 목표를 지원합니다. 단일 클러스터가 수정될 때 모든 100k
      클러스터를 제공하는 대신, 관리 서버는 변경된 단일 클러스터만 제공하면 됩니다.
    • Allows the Envoy to on-demand / lazily request additional resources.
      e.g. 응답이 클러스터에 도착했을 때만 클러스터를 요청함
    Incremental xDS 세션은 항상 gRPC 양방향 스트림의 컨텍스트에 있습니다.
        이를 통해 xDS 서버는 연결된 xDS 클라이언트의 상태를 추적할 수 있습니다. 
        아직 Incremental xDS의 REST 버전은 없습니다.

      In the delta xDS wire protocol, the nonce field is required and used to pair a DeltaDiscoveryResponse to
      a 
DeltaDiscoveryRequest ACK or NACK. Optionally, a response message level system_version_info is present
      for debugging purposes only.

 

 

Istio - Istio proxy 와 Envoy 프로세스간 ‘유닉스 도메인 소켓 통신’ 확인

더보기
# 파드 확인
kubectl get pod

# istio 컨테이너 접속
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- bash
---------------------------------------------------------------
# SDS, XDS 는 소켓 타입
ls -al /etc/istio/proxy
total 28
drwxrwsrwt 2 root        istio-proxy   120 Dec 13 13:03 .
drwxr-xr-x 1 root        root         4096 Dec 13 13:03 ..
srw-rw-rw- 1 istio-proxy istio-proxy     0 Dec 13 13:03 SDS
srw-rw-rw- 1 istio-proxy istio-proxy     0 Dec 13 13:03 XDS
-rw-r--r-- 1 istio-proxy istio-proxy 17409 Dec 13 13:03 envoy-rev.json
-rw-r--r-- 1 istio-proxy istio-proxy  2967 Dec 13 13:03 grpc-bootstrap.json

# .json 파일 확인
more /etc/istio/proxy/envoy-rev.json
{
  "node": {
    "id": "sidecar~172.16.228.67~netpod-866d9d7765-tw7xd.default~default.svc.cluster.local",
    "cluster": "netpod.default",
...
"admin": {
    "access_log_path": "/dev/null",
    "profile_path": "/var/lib/istio/data/envoy.prof",
    "address": {
      "socket_address": {
        "address": "127.0.0.1",
        "port_value": 15000
      }
...
"dynamic_resources": {
    "lds_config": {
      "ads": {},
      "initial_fetch_timeout": "0s",
      "resource_api_version": "V3"
    },
    "cds_config": {
      "ads": {},
      "initial_fetch_timeout": "0s",
      "resource_api_version": "V3"
    },
    "ads_config": {
      "api_type": "GRPC",
      "set_node_on_first_message_only": true,
      "transport_api_version": "V3",
      "grpc_services": [
        {
          "envoy_grpc": {
            "cluster_name": "xds-grpc"
...
"static_resources": {
    "clusters": [
      {
        ...
        "name": "xds-grpc",
        "type" : "STATIC",
        "connect_timeout": "1s",
        "lb_policy": "ROUND_ROBIN",
        "load_assignment": {
          "cluster_name": "xds-grpc",
          "endpoints": [{
            "lb_endpoints": [{
              "endpoint": {
                "address":{
                  "pipe": {
                    "path": "./etc/istio/proxy/XDS"
                  }
...
"listeners":[
  ...
	"address": {
	           "socket_address": {
	             "protocol": "TCP",
	             "address": "0.0.0.0",
	             "port_value": 15021
	           }
	"filter_chains": [
	          {
	            "filters": [
	              {
	                "name": "envoy.filters.network.http_connection_manager",
	                "typed_config": {
	                  "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
	,
	                  "codec_type": "AUTO",
	                  "stat_prefix": "agent",
	                  "route_config": {
	                    "virtual_hosts": [
	                      {
	                        "name": "backend",
	                        "domains": [
	                          "*"
	                        ],
	                        "routes": [
	                          {
	                            "match": {
	                              "prefix": "/healthz/ready"
	                            },
	                            "route": {
	                              "cluster": "agent"
...
more /etc/istio/proxy/grpc-bootstrap.json

# display only Unix domain sockets : Listener 과 ESTAB 상태 정보 확인
ss -xpl
Netid   State    Recv-Q   Send-Q            Local Address:Port         Peer Address:Port   Process
u_str   LISTEN   0        4096        etc/istio/proxy/SDS 446191                  * 0       users:(("pilot-agent",pid=1,fd=13))
u_str   LISTEN   0        4096        etc/istio/proxy/XDS 446192                  * 0       users:(("pilot-agent",pid=1,fd=14))

ss -xp
Netid   State   Recv-Q   Send-Q           Local Address:Port         Peer Address:Port     Process
u_str   ESTAB   0        0          etc/istio/proxy/XDS 446483                  * 446482    users:(("pilot-agent",pid=1,fd=16))
u_str   ESTAB   0        0          etc/istio/proxy/SDS 446267                  * 446266    users:(("pilot-agent",pid=1,fd=18))
u_str   ESTAB   0        0                            * 446482                  * 446483    users:(("envoy",pid=16,fd=20))
u_str   ESTAB   0        0                            * 446266                  * 446267    users:(("envoy",pid=16,fd=19))

# display only TCP sockets and display only IP version 4 sockets
ss -4tpl

 

[ 실행 결과 - 한 눈에 보기 ]

 

 

▶ 자원 삭제 : kubectl delete gw,vs,deploy,svc --all


5. Book Info 실습 및 Istio 기능

5-1. Observability 

 - Istio 와 연계하여 모니터링, 추적관리의 편의성을 제공하는 여러 툴 들이 있다.

 

5-2. Kiali 소개 및 배포

[ Kiali 소개 ]

Kiali (키알리) 소개 : 주 데이터 소스(Prometheus, Jaeger)- 링크 링크2 링크3

더보기
  • Kiali is an observability console for Istio with service mesh configuration and validation capabilities.
  • Kiali provides detailed metrics and a basic Grafana integration, which can be used for advanced queries.
  • Distributed tracing is provided by integration with Jaeger.
    Jaeger 와 연동을 통해서 분산 트레이싱을 제공할 수 있다.

 

  • Monitoring port of the IstioD pod : Kiali connects directly to the IstioD pod (not the Service) to check for its health. By default, the connection is done to port 15014 which is the default monitoring port of the IstioD pod.
     ☆  파드의 헬스체크Kiali 가 직접 IstioD 파드에 TCP Port 15014 를 통해서 체크한다
  • Prometheus, Jaeger and Grafana - 링크
  • Prometheus and Jaeger are primary data sources for Kiali. This page describes how to configure Kiali to communicate with these dependencies. A minimalistic Grafana integration is also available.
    주 데이터 소스는 Prometheus and Jaeger 이며, 최소 수준의 Grafana 와 연동할 수 있다.

 


[ 참고 - kans3 설치 실습 ]

더보기
# 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

# kiali 서비스 변경
kubectl patch svc -n istio-system kiali -p '{"spec":{"type":"NodePort"}}'

# kiali 웹 접속 주소 확인  ( KIALI UI URL = http://3.38.183.127:31088 )
KIALINodePort=$(kubectl get svc -n istio-system kiali -o jsonpath={.spec.ports[0].nodePort})
echo -e "KIALI UI URL = http://$(curl -s ipinfo.io/ip):$KIALINodePort"

# Grafana 서비스 변경
kubectl patch svc -n istio-system grafana -p '{"spec":{"type":"NodePort"}}'

# Grafana 웹 접속 주소 확인 : 7개의 대시보드 ( Grafana URL = http://3.38.183.127:30114) 
GRAFANANodePort=$(kubectl get svc -n istio-system grafana -o jsonpath={.spec.ports[0].nodePort})
echo -e "Grafana URL = http://$(curl -s ipinfo.io/ip):$GRAFANANodePort"

# Prometheus 서비스 변경
kubectl patch svc -n istio-system prometheus -p '{"spec":{"type":"NodePort"}}'

# Prometheus 웹 접속 주소 확인  ( Prometheus URL = http://3.38.183.127:30088) 
PROMENodePort=$(kubectl get svc -n istio-system prometheus -o jsonpath={.spec.ports[0].nodePort})
echo -e "Prometheus URL = http://$(curl -s ipinfo.io/ip):$PROMENodePort"

 

[ 실행 결과 - 한 눈에 보기 ]

 

 

  • 프로메테우스 : Targets - 파드 별로 tcp 15020 에 /stats/prometheus

 

  • 그라파나 : 7개 대시보드
control plane
service

 

 

BookInfo Application 소개 : 4개의 마이크로서비스로 구성 : Productpage, reviews, ratings, details - 링크

 

Bookinfo Application

Deploys a sample application composed of four separate microservices used to demonstrate various Istio features.

istio.io

더보기

[ 테스트 시나리오 소개 ]

 

  • ProductPage 페이지에서 요청을 받으면, 도서 리뷰를 보여주는 Reviews 서비스와 도서 상세 정보를 보여주는 Details 서비스에 접속하고,
  • ProductPage 는 Reviews 와 Details 결과를 사용자에게 응답한다.
  • Reviews 서비스는 v1, v2, v3 세 개의 버전이 있고 v2, v3 버전의 경우 Ratings 서비스에 접소갛여 도서에 대한 5단계 평가를 가져옴.
  • Reviews 서비스의 차이는, v1은 Rating 이 없고, v2는 검은색 별로 Ratings 가 표시되며, v3는 색깔이 있는 별로 Ratings 가 표시됨.
  • (도서 참고 정보) 실수연발 (셰익스피어) Wikipedia

 

  Bookinfo 애플리케이션 배포 - 링크

더보기
# 모니터링
watch -d 'kubectl get pod -owide;echo;kubectl get svc'

# Bookinfo 애플리케이션 배포
echo $ISTIOV
cat ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -f ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml

# 확인
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>"

# 로그
kubetail -l app=productpage -f

 

[ 실행 결과 - 한 눈에 보기 ]

Istio Gateway/VirtualService 설정

더보기
  • bookinfo gateway yaml
# Istio Gateway/VirtualService 설정
cat ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml
kubectl apply -f ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml

# 확인
kubectl get gw,vs
istioctl proxy-status
NAME                                                   CLUSTER        CDS                LDS                EDS                RDS                ECDS        ISTIOD                      VERSION
details-v1-65cfcf56f9-4drsk.default                    Kubernetes     SYNCED (7m4s)      SYNCED (7m4s)      SYNCED (6m57s)     SYNCED (7m4s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
istio-ingressgateway-5f9f654d46-c4g7s.istio-system     Kubernetes     SYNCED (3m7s)      SYNCED (3m7s)      SYNCED (6m57s)     SYNCED (3m7s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
productpage-v1-d5789fdfb-5cr6m.default                 Kubernetes     SYNCED (6m59s)     SYNCED (6m59s)     SYNCED (6m57s)     SYNCED (6m59s)     IGNORED     istiod-7f8b586864-mv944     1.23.2
ratings-v1-7c9bd4b87f-9q4nv.default                    Kubernetes     SYNCED (7m3s)      SYNCED (7m3s)      SYNCED (6m57s)     SYNCED (7m3s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
reviews-v1-6584ddcf65-rqgp7.default                    Kubernetes     SYNCED (7m2s)      SYNCED (7m2s)      SYNCED (6m57s)     SYNCED (7m2s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
reviews-v2-6f85cb9b7c-h6m7p.default                    Kubernetes     SYNCED (7m2s)      SYNCED (7m2s)      SYNCED (6m57s)     SYNCED (7m2s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
reviews-v3-6f5b775685-rprpb.default                    Kubernetes     SYNCED (6m58s)     SYNCED (6m58s)     SYNCED (6m57s)     SYNCED (6m58s)     IGNORED     istiod-7f8b586864-mv944     1.23.2

# productpage 파드의 istio-proxy 로그 확인 Access log 가 출력 - Default access log format : 링크
kubetail -l app=productpage -c istio-proxy -f

 

[ 실행 결과 - 한 눈에 보기 ]

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

더보기
  • k3s control-plane 노드에서 수행
#
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
echo $IGWHTTP
32759

# 접속 확인
kubectl get svc -n istio-system istio-ingressgateway
curl -s http://localhost:$IGWHTTP/productpage
curl -s http://192.168.10.101:$IGWHTTP/productpage
curl -s http://192.168.10.102:$IGWHTTP/productpage

# 정보 확인
echo $MYDOMAIN
cat /etc/hosts

#
curl -s http://$MYDOMAIN:$IGWHTTP/productpage
  • 자신의 PC에서 접속 확인
#
echo $MYDOMAIN $IGWHTTP
cat /etc/hosts

#
curl -v -s $MYDOMAIN:$IGWHTTP/productpage
echo -e "http://$MYDOMAIN:$IGWHTTP/productpage"

#
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

 

  • testpc 에서 접속 실행*
# istio ingress gw 를 통한 접속 테스트
curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>"
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
for i in {1..100};  do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; done

   

 

Kiali 그래프 살펴보기

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

더보기

k8s-rtr 에서 트래픽 요청 간격을 조절해보자 (1초, 0.5초, 0.3초, 0.1초)

testpc 에서 아래 실행
# 반복 접속 테스트
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.5; done
for i in {1..100};  do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; done
for i in {1..1000}; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; done

 

[ 실행 결과 - 한 눈에 보기 ]

외부 client(testpc)에서 istio-ingressgateway로 web service 호출(0.5s)

 

Service 측면 확인
workload 측면에서 확인

 


 

[ 개인 정리 - Kiali Dashboard 설치 ]

kiali 설치를 위한 Promtheus & Grafana 설치  ( Ref. Link - https://istio.io/latest/docs/setup/getting-started/#dashboard )

더보기
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/grafana.yaml

 kiali 설치 및 확인

더보기
## 1. kiali 설치
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.23/samples/addons/kiali.yaml

## 2. 설치결과 확인
kubectl get pods -n istio-system

kiali 서비스를 NodePort로 수정

더보기
kubectl edit svc -n istio-system kiali
[ default type : ClusterIP -> NodePort 로 수정 ]

 

kiali 접속 포트 확인

더보기
kubectl get svc -n istio-system kiali

웹 브라우저에서 아래 주소로 접속

더보기
http://<ANY-WORKERNODE-EXTERNALIP>:<NODEPORT>/kiali
## http://3.36.117.75:31213/kiali

 

5-3. BookInfo 설치 테스트

▶ 리소스 배포 및 확인

더보기

 

## 1. bookinfo 설치
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

## 2. 리소스 확인
kubectl get pod,svc

## 3. 타이틀 확인
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>"

## 4. GW,vs 배포
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

## 5. 접속 노드포트 확인
kubectl get svc -n istio-system istio-ingressgateway

## 6. 80포트에 해당하는 노드포트 확인 
## 예시)  80:31578/TCP # 이때 31578

## 7. 노드 공인IP 확인
curl ifconfig.io

## 8. 주소접속 확인
## http://<노드의 공인 ip>:<위에서 확인한 노드포트>/productpage

 

[ 실행 결과 - 한 눈에 보기 ]

▶ Kiali 에서 확인

 

더보기

[ service 호출 Scene ]

 

[ kiali - all namespace Traffic 호출 처리 확인 ]

5-4. Request Routing 실습

더보기
## 1.버전 라우팅을 위한 Destination Rule 생성
kubectl apply -f samples/bookinfo/networking/destination-rule-all-mtls.yaml

## 2. 라우팅 경로 규칙 생성
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

## 3. bookinfo 웹 새로고침 시도 
# http://3.36.117.75:31213/productpage
## 4.kiali 에서 트래픽 흐름 확인

## 5. 사용자 ID 기반 경로 라우팅 설정
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

## 6. username : jason 으로 암호는 아무 암호를 입력하여 로그인
## 7. 새로고침을 해도 계속 검은별 리뷰만 확인됨, kiali 에서 트래픽 흐름 확인

## 8. 다른계정으로 로그인을 하고 새로고침 시도 하여 결과 확인

5-5. Circuit Breaking

더보기
## 1. httpbin sample 배포
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/httpbin/httpbin.yaml

## 2. 서킷브레이킹 설정 Destination Rule 생성
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100
EOF

## 3. 간단한 부하 테스트 클라이언트 fortio 배포 
kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml

## 4. POD 변수 등록
export FORTIO_POD=$(kubectl get pods -l app=fortio -o 'jsonpath={.items[0].metadata.name}')

## 5. POD에 접속하여, fortio를 사용하여 호출 테스트
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio curl -quiet http://httpbin:8000/get

## 6. 2개의 연결로 20개의 요청 트래픽 테스트
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get

## 7. 동시연결 3개, 30개 요청 테스트
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get

## 8. 통계 쿼리 확인 
kubectl exec "$FORTIO_POD" -c istio-proxy -- pilot-agent request GET stats | grep httpbin | grep pending

[ Tip & Tips - Traffic Management - Simple Test Scenario ]

더보기

1. Gateway  & Virtual Service

 1) Gateway : Cluster 내/외부 통신 흐름을 관리하는 역할

  - 종류 : Ingress Gateway, Egress Gateway

  - Service와 연계하여 세밀한 Traffic 제어가 가능함

 2) Virtual Service :  istio 에서 트래픽을 어디로, 어떻게 라우팅 할지 제어하는 리소스

  - 주요기능
 . 트래픽 라우팅
 . 트래픽 분배
 . retry TimeOut 설정
 . 장애주입
 . 트래픽 미러링 


☞ 자원 정리 : kubectl delete vs,deploy,svc --all


2. 다중 경로 처리

 - 경로를 세분화 하여 호출 지정경로에 따라 Traffic 처리


 

☞ 자원 Clear : kubectl delete deploy,svc,vs --all 

 


3.  Traffic 분할 및 canary 배포

 - virtual Service 배포 시, weight 를 설정하여 canary 배포를 진행할 수 있다.

 

☞ 자원 Clear : kubectl delete deploy,svc,vs --all 


4. Fault Injection

  

  


 5. Subsets

 - Destination Rule : istio에서 트래픽이 목적지 Service 에 도달할 때까지 해당 Service가 어떻게 Traffic을 처리할지 제어함

 - Virtual Service 는 Traffic을 어디로 보낼지에 촛점을 맞추고 있음

 [ Destination Rule 의 주요 설정내용 ]

 1) 서브셋 정의 : host와 trafficPolicy 설정

 2) 로드벨런싱 : traffic 을 서비스에 분배하는 방식정의

 3) 서킷 브레이커 : 장애지연 설정 등 서비스 연속성을 최대한 지킬 수 있도록 customizing 하는 설정

 . consecutive5xxErrors : 오류가 연속 발생할 때 처리 결정하는 임계치

 . interval : 오류 감지하는 시간 간격

 . baseEjectionTime : 인스턴스 제외하는 기본 시간

 . maxEjectionPercent : 제외 할 수 있는 최대 비율

 4) 연결 풀 관리 : 서비스로 연결관리를 위한 설정

 5) TLS 설정 : 서비스 간의 통신을 tls로 보호할 수 있도록 지정하는 설정 

 [ 실행 결과 ]

 

 

☞ 자원 Clear : kubectl delete deploy,vs,dr,svc --all 


6. LoadBalancing

 

  

☞ 자원 Clear : kubectl delete deploy,vs,dr,svc --all 


7. Mirroring 

 

☞ 자원 Clear : kubectl delete deploy,vs,dr,svc --all 


6. Istio 트래픽 흐름

☞ Life of a Packet : https://gasidaseo.notion.site/Istio-Life-of-a-packet-6ad9808e14594296bf854dcc203cab71

 

▼  Istio 통신 : 호스트의 tcp/ip 와 iptables 과 파드 내에 iptables 와 envoy 를 경유

  • 달리기에 비유하자면, Istio 가 없을 경우를 운동장 한바퀴라면, istio 사용 시 대략 운동장 세바퀴라고 볼 수 있습니다.
  • Istio 사용 시 장점도 있지만, 없을 경우 대비 비용(지연 추가, 프로세싱 추가, 복잡한 구조 등)이 추가됩니다.
더보기

[ istio 사용 시, Traffic 흐름 분석도 ]

출처 : https://cilium.io/blog/2021/12/01/cilium-service-mesh-beta
  • 외부 클라이언트 PC에서 K8S 파드(웹서버)로 접속 과정

 

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

더보기
k3s-s)
# istio ingress gw NodePort(HTTP 접속용) 변수 지정 : 아래 ports[0] 은 어떤 용도의 포트일까요?
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
echo $IGWHTTP
IGWHTTP=<각자 자신의 NodePort>

## istio-ingressgateway 파드가 배치된 노드의 유동 공인 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	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	running

# /etc/hosts 파일 수정
MYDOMAIN=<각자 자신의 www 도메인> # 단, 사용하고 있지 않는 공인 도메인을 사용 할 것
MYDOMAIN=www.gasida.dev
echo "<istio-ingressgateway 파드가 있는 워커 노드> $MYDOMAIN" >> /etc/hosts

MYDOMAIN=<각자 자신의 www 도메인>
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

 

  • testpc 에서
# 아래 변수는 각자 자신의 값을 직접 입력 할 것
IGWHTTP=30492
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

 

  • 자신의 PC에서 ( Windows의 경우, notepad - 관리자 권한 으로 실행 후, host 파일 수정 )
# 아래 변수는 각자 자신의 값을 직접 입력 할 것 : ISTIONODEIP는 3개의 노드 중 아무거나 입력
IGWHTTP=30492
ISTIONODEIP=3.39.223.99
MYDOMAIN=www.gasida.dev
echo "$ISTIONODEIP $MYDOMAIN" | sudo tee -a /etc/hosts

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

  실습을 위한 환경 설정 및 배포 : 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/v1alpha3
kind: Gateway
metadata:
  name: test-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-service
spec:
  hosts:
  - "$MYDOMAIN"
  gateways:
  - test-gateway
  http:
  - route:
    - destination:
        host: svc-nginx
        port:
          number: 80
EOF
# 모니터링
watch -d "kubectl get svc -n istio-system -l app=istio-ingressgateway;echo;kubectl get pod -n istio-system -o wide -l app=istio-ingressgateway;echo;kubectl get pod -owide nginx-pod"
watch -d "kubectl get pod -n istio-system -o wide -l app=istio-ingressgateway;echo;kubectl get pod -owide nginx-pod"

 

testpc 에서 아래 실행
# istio ingress 를 통한 접속
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

 

  • istio-proxy peer 간 mtls 끄기 - 링크
# 서비스 중 app: nginx-app 로 향하는 통신의 경우 peer 간 mtls 끄기(istio-ingressgw 와 목적지 워커노드의 파드에 istio-proxy 간)
cat <<EOF | kubectl create -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "example-workload-policy"
spec:
  selector:
     matchLabels:
       app: nginx-app
  portLevelMtls:
    80:
      mode: DISABLE
EOF

 

(옵션) 특정 노드에 파드 지정해서 설치 → 실습을 위해 istio-ingressgateway 파드와 nginx-pod 파드를 다른 노드에 배치를 권장

cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx-app
spec:
  terminationGracePeriodSeconds: 0
  nodeName: k3s-w1
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
EOF

 

 [ 실행 결과 - 한 눈에 보기 ]

 

 

[2개의 ‘파드-서비스’ 간 통신 흐름 분석] - 참고

더보기

☞ 외부 Client 호출 시, 내부 Application POD(container)에 도달하기 전에 kernel Netfilter 통해 인증/인가/라우팅이 이루어 지므로, traffic 처리의 payload가 부가되는 구조임

출처 : 정환열님 교육자료

 

6-1. Client 요청 -> POD 인입

Traffic 흐름

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

 

POD 내 IPtables 흐름 ***

 

▶  (추천 링크) Life of a Packet in ISTIO Part 1 - 링크

6.1.1 외부 Client(testpc) → IstioIngressgateway POD

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

더보기
# 아래 처럼 정상적으로 웹 서버 접속 정보 출력 확인
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

 

[ 실행 결과 - 한 눈에 보기 ]

 

6.1.2  Istio Ingress-gateway → Node 진입

  • Istio IngressGateway(envoy) 파드를 경유하여 웹 서버 파드가 있는 노드로 인입
더보기
  • Istio IngressGateway(envoy) 파드는 클라이언트 PC의 IP를 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 확인 (참고) 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 (참고) 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
-----

 

[ 참고 설명 - Istio mesh의 iptables Traffic 처리가 복잡한 이유?! ]

 

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

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

더보기
# 로그 내용 중 출발지 정보(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

 

# 패킷 덤프 (예시) 
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

 

(참고) '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' 의 인/아웃 시 트래픽 구별이 중요하다.
  • 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 파드(리턴 트래픽) → 클라이언트

▶ Traffic 흐름

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

더보기

☞ 8번 패킷 과정

  • 200 OK 응답이며, 'Istio-proxy' 에 의해서 x-envoy-upstream-Y 헤더가 추가되어 있습니다.

 

1.1 에서 살펴본 3번 과정 직전과 8번 과정의  NAT traffic 정보

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 파드(요청) → 외부 웹서버

▶ Traffic 흐름

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

 

  •  POD 내 IPtables Traffic 흐름 : 아래 (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

 

  • (참고) POD 내 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 Istio Ambient Mesh

☞ Istio Mesh Sidecar model 에서는 POD 당 Proxy container 를 할당하여 관리 규모가 커질 수록 복잡도가 높아지기 때문에 서비스의 구간 별 Traffic 관리의 어려움이 생길 수 있다. 이를 해결하기 위해 하나의 POD 에 Proxy layer를 구축하여 share 하는 방식으로 관리하는 것으로 복잡도를 줄 일 수 있다는 것에 착안하여 만들어진 모델이다.

 

참조  : Istio Internals: Ambient mode https://www.anyflow.net/sw-engineer/istio-ambient-mode

 

★ 세부 설명 링크 :  gasida님 Notion 링크

[ More ... ]

더보기
  • Ambient is currently in alpha status - Link
 

Feature Status

List of features and their release stages.

istio.io

 

[ Istio Sidecar Data Plane vs Ambient Mesh Data Plane 비교 ]

 

[ Sidecar (Proxy 모든 기능 담당) vs Ambient Mesh (L4 Proxy 와 L7 Proxy 기능 분리) ]

 

▶ Istio Ambient Mesh 

   : A new, open source contribution to the Istio project, that defines a new sidecar-less data plane

  • Istio and sidecars 방식 : 파드 마다 Sidecar Proxy 배치
https://istio.io/latest/blog/2022/introducing-ambient-mesh/

 

▶ Istio Ambient Mesh 방식

  • 파드들은 해당 노드에 ztunnel 파드를 공유하여 다른 파드들(동일 노드, 다른 노드)과 안전한 통신 환경을 제공
  • Ambient mesh uses a shared, per-node ztunnel to provide a zero-trust secure overlay

 Cluster node 간 통신 시, ztunnel proxy Pod 간에 hbone 을 통해 통신경로를 맺고 Traffic 을 전달해 준다.

 

▶ Layer7 통제와 정책이 필요 시, Waypoint Proxy 파드를 통하여 기능을 구현

 - When additional features are needed, ambient mesh deploys waypoint proxies, which ztunnels connect through for policy enforcement

 

L7 통제를 위해서 "Waypoint Proxy" Pod 를 통해서 기능을 제공 - 기존보다 간결해진 라우팅 정책 적용/관리

 

 

HBONE HTTP Based Overlay Network Encapsulation는 애플리케이션 통신 트래픽을 HTTP CONNECT 메서드를 통해 표준 HTTP 터널링을 사용합니다. TCP 상위에 HTTP/2를 사용하며, TLS를 통해 상호 인증과 암호를 제공합니다. HBONE tunnel 은 TCP 15008 포트를 사용합니다 - HTTP CONNECT & HTTP/2

 

 [ HBONE Protocol ]

 

▶ 통신흐름 (상세) - Link

더보기
  • 파드 트래픽을 ztunnel 로 redirection 하기 위해서, Istio CNI DaemonSet 을 활용

☞ CNI Network Plugin 을 통해 인입 Traffic을 Istio Proxy가 처리할 수 있도록 routing 처리를 해 준다.

 


[ 실습 종료 후 리소스 삭제 ]

☞ 모든 실습 종료 후, 자원을 정리합시다 !!

더보기
# 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

[ 마무리 ]

Istio mesh의 다양한 쓰임새와 rich한 기능들을 직/간접적으로 접해 볼 수 있어서 유용한 학습 시간이었던 것 같습니다.

다만, Istio mesh 의 방대한 양을 다루다 보니, 정리하기가 쉽지 않은 것 같습니다. ㅠㅠ 워낙 기능이 다양하고 많다 보니 gasida 님 강의에 따라 핵심만 따라 해 보았는데도 상당한 시간과 effort가 들어가게 되네요. 

이번 정리에 못해 본 내용들은 추후 시간 날때 짬짬이 들여다 보아야 할 것 같습니다. 


[ 도움이 되는 링크모음 ]

더보기

[ Istio 관련 ]

△ 공식 Document : https://istio.io/latest/docs/

MacBook M시리즈에 VMware Fusion과 Vagrant 이용하여 K3S 클러스터와 Istio 구성 - icebreaker70 : Blog

△ Istio 도식화 참고자료 : Blog

Life of a Packet : Notion

Understanding of Sidecar injection, Traffic intercepting & Routing Process in istio : Blog

Ambient model - ztunnel & Secure overlay : Blog 

Ambient - ztunnel Architecture : Blog

EKS Burstable 설정과 KRR을 활용한 비용 절감: Blog

 

[ K8s & 네트워크 관련 ]

△ 쿠버네티스가 쉬워지는 컨테이너 이야기 - cgroup, cpu편 : Blog

△ 쿠버네티스가 쉬워지는 컨테이너 이야기 -  Memory편 : Blog

△ 토스ㅣSLASH 24 - 미처 알지 못했던 Kernel까지 Observability 향상시키기 : YouTube

△ [CNKCD2024] Lakehouse 구축을 위한 K8S 디자인패턴 (신호승) : YouTube

네트워크 인프라에서 Kubernetes 서비스 네트워킹 지원하기 / if(kakao)2022 - Youtube

 

[ Cilium 관련 ]

△ Integrating Cilium with Gateway API, IPv6, and BGP for Advanced Networking Solutions : Link