WellSpring

Istio 1주차 - Istio 소개, 첫걸음 본문

ISTIO

Istio 1주차 - Istio 소개, 첫걸음

daniel00324 2025. 4. 7. 22:12

목차

     

    ※ 본 게재 글은 gasida님의 'Istio' 강의내용과 실습예제 AWS, Istio 공식 사이트,  'Istio In Action' 서적을 참고하여 작성하였습니다. 


    1. 들어가며

    1-1. 서비스 메시 소개하기

    서비스 메시는 애플리케이션의 서비스 간 모든 통신을 처리하는 소프트웨어 계층으로, 컨테이너화된 마이크로서비스로 구성된다. 현대 사회의 다양한 고객 Needs를 만족시키기 위해 어플리케이션은 날로 복잡도가 높아지고 있어 점점 모니터링 하기가 어려워 지고 있다. 이런 상황에서 서비스 메시는 서비스 간 연결을 관리하기 위해 모니터링, 로깅, 추적, 트래픽 제어와 같은 새로운 기능을 제공하고 있어 마이크로서비스가 요구하는 '서비스 수준 관찰성' 제공과 더불어  '서비스 수준 제어'를 가능케 해 준다.

     

    1-2. 서비스 메시의 구성요소 - Link

    더보기
    출처 : https://aws.amazon.com/ko/what-is/service-mesh/

     

    a. Data Plane

     - Applicatoin layer Proxy 사용하여 Application을 대신하여 네트워킹 트래픽을 관리해 줌

      : 모든 SideCar Proxy 포함하며, 해당 요소는 다음과 같은 역할을 한다.

    1. 사이드카가 요청을 가로챕니다.
    2. 요청을 별도의 네트워크 연결로 캡슐화합니다.
    3. 소스 프록시와 대상 프록시 간에 안전하고 암호화된 채널을 설정합니다.

     

    b. Control Plane

     - 서비스 메시의 중앙 관리 및 구성 계층 역할

     - 조직의 네트워크와 마이크로서비스 간의 중간 게이트웨이 역할을 하는  Proxy 를 관리함

     

    [ control Plane의 기능 ]

    • 메시 내의 모든 서비스를 추적하는 서비스 레지스트리
    • 신규 서비스 자동 검색 기능 및 비활성 서비스 제거 기능
    • 지표, 로그, 분산 추적 정보와 같은 텔레메트리 데이터의 수집 및 집계

     

    1-3. 서비스 메시의 특징

    특정 프로그래밍 언어나 프레임워크에 의존하지 않고, 중요한 애플리케이션-네트워킹 기능을 애플리케이션 외부에서 구축 할 수 있다.

     

    [ 장점 ]

    더보기

    서비스 검색

    서비스 메시는 자동화된 서비스 검색을 제공하여 서비스 엔드포인트 관리의 운영 부하를 줄입니다. 서비스 레지스트리를 사용하여 메시 내의 모든 서비스를 동적으로 검색하고 추적합니다. 서비스는 위치나 기반 인프라에 관계없이 서로를 원활하게 찾고 통신할 수 있습니다. 필요에 따라 새 서비스를 배포하여 빠르게 확장할 수 있습니다.

     

    로드 밸런싱

    서비스 메시는 라운드 로빈, 최소 연결 또는 가중치 로드 밸런싱과 같은 다양한 알고리즘을 사용하여 요청을 여러 서비스 인스턴스에 지능적으로 분산합니다. 로드 밸런싱은 리소스 활용도를 높이고 고가용성 및 확장성을 보장합니다. 성능을 최적화하고 네트워크 통신 병목 현상을 방지할 수 있습니다.

     

    트래픽 관리

    서비스 메시는 요청 라우팅 및 트래픽 동작을 세밀하게 제어할 수 있는 고급 트래픽 관리 기능을 제공합니다. 여기 몇 가지 예가 있습니다.

     

    트래픽 분할

    들어오는 트래픽을 서로 다른 서비스 버전 또는 구성 간에 분할할 수 있습니다. 메시는 일부 트래픽을 업데이트된 버전에 전달하므로 변경 사항을 제어하고 점진적으로 적용할 수 있습니다. 이를 통해 원활한 전환이 가능하며, 변경으로 인한 영향을 최소화할 수 있습니다.

     

    미러링 요청

    기본 요청 흐름에 영향을 주지 않으면서 분석을 위해 테스트 또는 모니터링 서비스에 트래픽을 복제할 수 있습니다. 요청을 미러링하면 서비스가 프로덕션 트래픽에 영향을 미치지 않으면서 특정 요청을 처리하는 방법을 파악할 수 있습니다.

     

    카나리 배포

    대부분의 사용자가 기존의 안정적인 버전을 계속 사용하면서 일부 사용자 또는 트래픽을 새 서비스 버전에 전달할 수 있습니다. 노출이 제한되므로 실제 환경에서 새 버전의 동작과 성능을 실험해 볼 수 있습니다.

     

    보안

    서비스 메시는 상호 TLS(mTLS) 암호화, 인증 및 권한 부여와 같은 보안 통신 기능을 제공합니다. 상호 TLS를 사용하면 서비스 간 통신에서 ID를 검증할 수 있습니다. 트래픽을 암호화하여 데이터 기밀성과 무결성을 보장하는 데 도움이 됩니다. 또한 권한 부여 정책을 적용하여 특정 엔드포인트에 액세스하거나 특정 작업을 수행하는 서비스를 제어할 수 있습니다.

     

    모니터링

    서비스 메시는 포괄적인 모니터링 및 관찰성 기능을 제공하여 서비스의 상태, 성능 및 행동에 대한 인사이트를 도출할 수 있습니다. 모니터링은 문제 해결 및 성능 최적화도 지원합니다. 사용할 수 있는 모니터링 기능의 예는 다음과 같습니다.

    • 지연 시간, 오류율, 리소스 사용률과 같은 지표를 수집하여 전체 시스템 성능을 분석합니다.
    • 분산 추적을 수행하여 여러 서비스 전반에서 요청의 전체 경로와 시간을 확인할 수 있습니다.
    • 감사, 디버깅 및 규정 준수를 위해 로그에 서비스 이벤트를 캡처합니다.

    1-4. 서비스 메시란?

    더보기
    • 서비스 메시란 애플리케이션 대신 프로세스 외부에서 투명하게 네트워크 트래픽을 처리하는 분산형 애플리케이션 인프라를 말한다.
    • 아래 그림은 서비스 프록시가 데이터 플레인을 형성하는 방식을 보여준다. 데이터 플레인은 모든 트래픽을 처리하고 관찰하는 곳이다.

     

    • 데이터 플레인은 메시를 거쳐가는 트래픽을 설정하고 보호하고 제어하는 책임을 맡는다.
    • 데이터 플레인의 동작은 컨트롤 플레인이 설정한다.
    • 컨트롤 플레인은 메시의 두뇌로, 운영자가 네트워크 동작을 조작할 수 있도록 API를 노출한다.
    • 데이터 플레인과 컨트롤 플레인이 모여 모든 클라우드 네트워크 아키텍처에 필요한 다음과 같은 중요 기능을 제공한다.
      • 서비스 복원력
      • 관찰 가능성 신호
      • 트래픽 제어 기능
      • 보안
      • 정책 강제 Policy enforcement

    기능

    • 서비스 메시는 재시도, 타임아웃, 서킷 브레이커 같은 기능을 구현해 서비스 통신이 장애에 복원력을 갖추게 만들 책임을 맡는다.
    • 또한 서비스 디스커버리, 적응형 및 영역 인식 zone-aware 로드 밸런싱, 헬스 체크 같은 기능을 처리함으로써 변화하는 인프라 토폴로지를 처리할 수도 있다.
    • 모든 트래픽이 메시를 통과하므로 운영자는 트래픽을 명시적으로 제어하고 지시할 수 있다.
    • 트래픽이 메시를 통과하므로 요청 급증, 지연 시간, 처리량, 장애 등과 같은 메트릭을 추적함으로써 네트워크 동작에 대한 상세한 신호를 포착할 수 있다.
    • 텔레메트리 telemetry 를 활용해 시스템에서 어떤 일이 일어나고 있는지 그려낼 수 있다.
    • 마지막으로, 서비스 메시가 애플리케이션 간 네트워크 통신의 양쪽 끝을 제어하므로 상호 인증을 사용한 전송 계층 암호화 같은 강력한 보안을 적용할 수 있다.
    • 구체적으로는 TLS 프로토콜을 사용할 수 있다.

    정리

    • 서비스 메시는 이 모든 기능을 애플리케이션 코드 변경이나 의존성 추가를 거의(혹은 전혀) 하지 않고도 서비스 운영자에게 제공한다.
    • 일부 기능에서는 애플리케이션 코드와 약간의 협업이 필요하지만, 크고 복잡한 라이브러리 의존성을 피할 수 있다.
    • 서비스 메시를 사용하면 애플리케이션을 구축하는 데 어떤 애플리케이션 프레임워크나 프로그래밍 언어를 사용했든지 상관없이 이런한 기능들이 일관되고 정확하게 구현되므로, 서비스 팀이 변화를 구현해 전달할 때 빠르고 안전하며 자신감 있게 움직일 수 있게 된다.

      

    1-5. Istio 서비스 메시 소개

    더보기

    ▷ 이스티오 istio 는 그리스어로 ‘돛’을 의미하며, k8s 항해 용어들과 잘 어울림

     

    ▶ Istio = 서비스 메시의 구현체?!

    • 이스티오를 사용하면 대부분의 경우 애플리케이션 코드를 수정하지 않고도 보안, 정책 관리, 관찰 가능성과 같은 어려운 문제를 해결할 수 있고, 신뢰성 있고 안전한 클라우드 네이티브 시스템을 구축할 수 있다.
    • 이스티오의 데이터 플레인 엔보이 프록시를 기반으로 한 서비스 프록시로 구성되며, 서비스 프록시는 애플리케이션 옆에 자리 잡고 있다.
    • 서비스 프록시는 애플리케이션 간의 중개자 역할을 하며, 컨트롤 플레인이 전달한 설정에 따라 네트워킹 동작에 영향을 준다.
    • 이스티오는 MSA 또는 서비스 지향 아키텍처 SOA 를 염두에 뒸지만, 그 아키텍처들에만 국한되지는 않는다.
    • 현실에서는 대부분의 조직이 기존 애플리케이션과 플랫폼에 많은 투자를 하고 있다.
    • 이들은 기존 애플리케이션을 중심으로 서비스 아키텍처를 구축할 가능성이 높으면, 이 부분이야말로 이스티오가 진가를 발휘하는 지점이다.
    • 이스티오를 사용하면 기존 시스템을 바꾸지 않고도 애플리케이션 네트워킹 관심사를 구현할 수 있다.
    • 어떤 서비스 기반 아키텍처에서도 중요한 요구 사항은 보안이다. 이스티오는 기본적으로 보안이 활성화돼 있다.
    • 이스티오가 애플리케이션 네트워킹 경로의 양 끝단을 제어하는 덕분에 기본적으로 트래픽을 투명하게 암호화 할 수 있다.
    • 이스티오는 서비스가 mTLS를 바로 사용할 수 있도록 키 및 인증서 발급, 설치, 로테이션을 관리할 수 있다.
    • 이스티오는 워크로드에 ID를 부여하고 이를 인증서에 포함시킬 수 있다. 또한 ID를 사용해 강력한 접근 제어 정책을 구현할 수 있다.
    • 마지막으로, 이스티오를 사용하면 할당량, 속도 제한, 조직 정책을 구현할 수 있다.
    • 이스티오의 정책 강제 policy enforcement 를 사용하면, 어떤 서비스가 서로 상호작용할 수 있고 어떤 서비스가 상호작용할수 없는지에 대해 아주 세밀한 규칙을 만들 수 있다.

     

    1. 트래픽은 이스티오 인그레스 게이트웨이를 통해 메시 외부의 클라이언트에서 클러스터로 들어온다.
    2. 트래픽이 쇼핑 카트 서비스로 이동한다. 트래픽은 먼저 해당 서비스 프록시를 통과한다.
      • 서비스 프록시는 서비스에 타임아웃, 메트릭 수집, 보안 강제 등을 적용할 수 있다.
    3. 요청이 다양한 서비스를 거치므로, 이스티오의 서비스 프록시는 다양한 단계에서 요청을 가로채고 라우팅 결정을 내릴 수 있다.
    4. 이스티오의 컨트롤 플레인 istiod 는 라우팅, 보안, 텔레메트릭 수집, 복원력을 처리하는 이스티오 프록시를 설정하는 데 사용한다.
    5. 요청 메트릭은 주기적으로 다양한 수집 서비스로 전송된다. 분산 트레이싱 스팬은 트레이싱 저장소로 전송돼 시스템을 거치는 요청의 경로 및 지연 시간을 추후에 추적하는 용도로 사용할 수 있다.

    [ 서비스 메시와 API Gateway 비교 ]

    • 이스티오와 서비스 메시 기술은 API 게이트웨이와도 몇 가지 유사점과 차이점을 공유한다.
    • API 게이트웨이 인프라는 API 관리 제품군에서 조직의 공개 API에 외부에서 접근할 수 있는 엔드포인트를 제공하는 데 사용한다.
    • API 게이트웨이의 역할은 크게 두 가지다.
    • 첫 번째는 공개 API에 보안, 속도 제한, 할당량 관리, 메트릭 수집 기능을 제공하는 것이고,
    • 두 번째는 API 계획 명세, 사용자 등록, 요금 청구와 기타 운영 문제를 포함하는 전반적 API 관리 솔루션에 공개 API를 연결하는 것이다.
    • API 게이트웨이 아키텍처는 매우 다양하지만, 대부분 아키텍처의 경계에서 공개 API를 노출하는 데 사용됐다.
    • 또한 보안, 정책, 메트릭 수집을 중앙화하기 위해 내부 API에도 사용돼 왔다.
    • 그렇지만 API 게이트웨이는 트래픽이 흐르는 중앙집중 시스템을 만들기 때문에 ESB와 메시징 버스에서 설명했듯 병목 현상의 원인이 될 수 있다.

    아래 그림은 내부 API에 API 게이트웨이를 사용할 때 서비스 간에 모든 내부 트래픽이 어떻게 API 게이트웨이를 거쳐가는지 보여준다.

     

    • 그래프의 모든 서비스에서 홉 hop 이 두 번을 거치게 된다. 한번은 게이트웨이로 향하고, 한 번은 실제 서비스로 향하는 것이다.
    • 이는 네트워크 오버헤드와 지연 시간 뿐 아니라 보안에도 영향을 미친다.
    • 이런 다중 홉 아키텍처에서는 애플리케이션 관여 없이 API 게이트웨이가 단독으로 전송 매커니즘을 보호할 수 없다.
    • 그리고 API 게이트웨이는 보통 서킷 브레이커나 격벽 같은 복원력 기능을 구현하지 않는다.
    • 서비스 메시에서 프록시는 서비스와 함께 배치되므로 추가 홉을 거치지 않는다.
    • 또한 서비스 메시는 탈중앙적이므로, 각 에플리케이션은 자신의 프록시를 자신의 워크로드에 맞게 설정할 수 있고 시끄러운 이웃 noisy neithbor 시나리오에 영향을 받지 않는다.
    • 각 프록시는 짝 애플리케이션 인스턴스와 함께 있으므로, 애플리케이션이 알아차리거나 적극적으로 참여할 필요 없이 전송 매커니즘을 처음부터 끝까지 end-to-end 보호할 수 있다.

     

    아래 그림은 서비스 프록시가 API 게이트웨이 기능을 구현하고 강제하는 장소가 되는 모습을 보여준다.

     

     

    ☞ 이스티오 같은 서비스 메시 기술이 계속 성숙하게 되면, API 관리가 서비스 메시 위에 구축되고 전문 API 게이트웨이 프록시가 필요하지 않게 될 것이다.


    [ 서비스 메시가 분산 아키텍쳐에 적합한 경우 ]

    • 구현에 사용할 기술은 당면한 문제와 필요한 기능을 고려해 선택해야 한다.
    • 이스티오 같은 서비스 메시 기술은 강력한 인프라 기능이여 분산 아키텍처의 많은 영역에 영향을 미친다.
    • 그렇지만 모든 문제에 적합한 것은 아니므로 모든 문제에 해결책으로 고려해서는 안된다.
    • 아래 그림은 클라우드 아키텍처에서 애플리케이션 네트워킹 관심사를 이상적으로 분리하는 방법을 보여준다.
    • 아키텍처의 하위 계층에는 배포 자동화 인프라가 있다.
    • 이 인프라는 코드를 플랫폼에 배포하는 역할을 담당한다. 이스티오는 어떤 배포 자동화 도구를 사용해야 하는지를 규정하거나 침해하지 않는다.
    • 상위 계층에는 애플리케이션 비즈니스 로직(코드)이 있다. 이 코드에는 비즈니스 도메인은 물론 어떤 서비스를 어떤 순서로 호출할지, 서비스 상호작용 응답을 어떻게 처리할지, 프로세스 실패 시 어떻게 처리할지 등이 포함된다.
    • 이스티오는 어떤 비즈니스 로직도 구현하거나 대체하지 않는다. 또한 서비스 오케스트레이션, 비즈니스 페이로드 변환, 페이로드 강화, 분할 집계, 규칙 계산 등을 수행하지 않는다. 이런 기능은 애플리케이션 내부 라이브러리와 프레임워크에 맡기는 것이 가장 좋다.
    • 이스티오는 배포 플랫폼과 애플리케이션 코드 사이의 연결 조직 역할을 한다.
    • 복잡한 네트워킹 코드를 애플리케이션 외부로 꺼낼 수 있게 하는 것이다.

    [ 서비스 메시를 사용할 때의 단점 ]

    1. 첫 번째로, 서비스 메시를 사용하면 요청 경로에 미들웨어, 특히 프록시가 추가된다.
      • 이 프록시가 많은 이점을 주기도 하지만, 프록시에 익숙하지 않은 이들에게는 블랙박스가 돼 애플리케이션의 동작을 디버깅하기 어렵게 만들 수 있다.
      • 엔보이 프록시는 아주 디버깅하기 쉽도록, 네트워크상에서 발생하고 있는 일을 많이 노출하게 특별히 설계됐다.
      • 그렇지만 엔보이를 운영하는 데 익숙하지 않은 사람들에게는 아주 복잡해 보일 수 있고, 기존 디버깅 방식을 방해할 수 있다.
    2. 두 번째로, 테넌시 측면이다.
      • 메시는 메시 내에서 실행되는 서비스 만큼 가치가 있다. 즉, 메시 내에 서비스가 많을수록 그 서비스들을 운영하는 데 메시의 가치가 높아진다.
      • 그러나 물리적 메시 배포의 테넌트 및 격리 모델에 적절한 정책, 자동화, 그리고 사전 고려 없이는 메시를 잘못 구성하면 많은 서비스에 영향을 미칠 수 있는 상황에 처할 수 있습니다. → 학습 필요. 잘 알고 설정 필요
    3. 마지막으로, 서비스 메시는 요청 경로에 위치하기 때문에 서비스 및 애플리케이션 아키텍처의 매우 중요한 요소가 된다.
      • 서비스 메시는 보안, 관찰 가능성 및 라우팅 제어 자세를 개선할 수 있는 많은 기회를 제공할 수 있습니다.
      • 단점은 메쉬가 또 다른 레이어와 또 다른 복잡성의 기회를 제공한다는 점입니다.
      • 운영상 이슈(R&R) : 서비스 메시를 어떻게 설정하고 운영해야 하는지, 기존 조직의 절차와 거버넌스에는 어떻게 통합해야 하는지, 또한 팀 간에는 어떻게 통합해야 하는지 이해하기가 어려울 수 있다.

     


    2. 이스티오 첫 걸음

    [ 실습 환경 ]

    • 책 실습 환경 : docker desktop, k8s 1.21.1, istio 1.13 (istio-proxy init 실패… ’22.2.11 출시) - Link
    • 스터디 실습 환경 : docker (kind - k8s 1.23.17 ‘23.2.28 - Link) , istio 1.17.8(’23.10.11) - Link

     kind(k8s) 소개 및 설치와 기본 사용

    더보기
    • kind 소개 : ‘도커 IN 도커 docker in docker’로 쿠버네티스 클러스터 환경을 구성 - Link
    참조 : https://kind.sigs.k8s.io/

     

    kind 설치 : Windows (WSL2) 사용자

    더보기

    ☞  WSL 2 설치 + Ubuntu 배포판 설치 - Docs , 설명서

     

    Step1. Powershell 관리자 권한으로 실행

    # DISM(배포 이미지 서비스 및 관리) 명령어로 Microsoft-Windows-Subsystem-Linux 기능을 활성화
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    
    # DISM 명령어로 VirtualMachinePlatform 기능을 활성화
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    
    # wsl 설치
    wsl --install
    
    # 기본값 WSL 2 버전 설정
    wsl --set-default-version 2
    
    # wsl 업데이트
    wsl --update

     

    Step2. 윈도우 OS 재부팅

     

    Step3. Powershell 관리자 권한으로 실행

    # 설치 가능한 배포판 확인
    wsl --list --online
    
    # Ubuntu 배포판 설치
    wsl --install Ubuntu-24.04
    ...
    Enter new UNIX username: <각자 Ubuntu 사용 계정>
    New password: <해당 계정 암호>
    Retype new password: <해당 계정 암호>
    passwd: password updated successfully
    Installation successful!
    To run a command as administrator (user "root"), use "sudo <command>".
    ---------------------------------------
    # 기본 정보 확인
    hostnamectl
    whoami
    id
    pwd
    
    # apt 업데이트
    sudo apt update 
    sudo apt install jq htop curl wget ca-certificates net-tools -y
    ifconfig eth0
    ping -c 1 8.8.8.8
    
    # 빠져나오기
    $ exit
    ---------------------------------------
    
    # 설치된 배포판 확인
    wsl -l -v
    
    # Ubuntu 재진입
    wsl

     

    ▶ WSL2 (Ubuntu) 에 Docker 설치 - Docs

    더보기
    # WSL2 에 Docker 설치 : 아래 스크립트 실행 후 20초 대기하면 스크립트 실행 됨
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh ./get-docker.sh
    ...
    
    # 설치 확인
    docker info
    docker ps
    sudo systemctl status docker
    cat /etc/group | grep docker

    ▶ 옵션 설정

    더보기
    • (옵션) Windows Terminal 설치 및 꾸미기(개발 환경 편리하게)
    • (옵션) VSCODE 설치 - Download , WSL-VSCODE

     

    ☞ WSL 배포에서 프로젝트를 열려면 배포의 명령줄을 열고 다음을 입력합니다. code .

    code .
    Installing VS Code Server for Linux x64 (f1a4fb101478ce6ec82fe9627c43efbf9e98c813)
    Downloading:   100%
    Unpacking: 100%
    Unpacked 1773 files and folders to /home/gasida/.vscode-server/bin/f1a4fb101478ce6ec82fe9627c43efbf9e98c813.
    Looking for compatibility check script at /home/gasida/.vscode-server/bin/f1a4fb101478ce6ec82fe9627c43efbf9e98c813/bin/helpers/check-requirements.sh
    Running compatibility check script
    Compatibility check successful (0)

      

     

    WSL2 에 kind 및 관리 툴 설치

    더보기
    # 기본 사용자 디렉터리 이동
    cd $PWD
    pwd
    
    #
    sudo systemctl stop apparmor && sudo systemctl disable apparmor
    
    # 
    sudo apt update && sudo apt-get install bridge-utils net-tools jq tree unzip kubectx kubecolor -y
    
    # Install Kind
    curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-amd64
    chmod +x ./kind
    sudo mv ./kind /usr/local/bin/kind
    kind --version
    
    # Install kubectl
    curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
    chmod +x kubectl
    sudo mv ./kubectl /usr/bin
    sudo kubectl version --client=true
    
    # Install Helm
    curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
    helm version
    
    # Source the completion
    source <(kubectl completion bash)
    echo 'source <(kubectl completion bash)' >> ~/.bashrc
    
    # Alias kubectl to k
    echo 'alias k=kubectl' >> ~/.bashrc
    echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
    
    # Install Kubeps & Setting PS1
    git clone https://github.com/jonmosco/kube-ps1.git
    echo -e "source $PWD/kube-ps1/kube-ps1.sh" >> ~/.bashrc
    cat <<"EOT" >> ~/.bashrc
    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
    
    # .bashrc 적용을 위해서 logout 후 터미널 다시 접속 하자
    exit

    kind 기본 사용 - 클러스터 배포 및 확인

    더보기
    # 클러스터 배포 전 확인
    docker ps
    
    # Create a cluster with kind
    kind create cluster
    
    # 클러스터 배포 확인
    kind get clusters
    kind get nodes
    kubectl cluster-info
    
    # 노드 정보 확인
    kubectl get node -o wide
    
    # 파드 정보 확인
    kubectl get pod -A
    kubectl get componentstatuses
    
    # 컨트롤플레인 (컨테이너) 노드 1대가 실행
    docker ps
    docker images
    
    # kube config 파일 확인
    cat ~/.kube/config
    혹은
    cat $KUBECONFIG # KUBECONFIG 변수 지정 사용 시
    
    # nginx 파드 배포 및 확인 : 컨트롤플레인 노드인데 파드가 배포 될까요?
    kubectl run nginx --image=nginx:alpine
    kubectl get pod -owide
    
    # 노드에 Taints 정보 확인
    kubectl describe node | grep Taints
    Taints:             <none>
    
    # 클러스터 삭제
    kind delete cluster
    
    # kube config 삭제 확인
    cat ~/.kube/config
    혹은
    cat $KUBECONFIG # KUBECONFIG 변수 지정 사용 시

    ▶ krew 설치 - https://krew.sigs.k8s.io/docs/user-guide/setup/install/

     

    kind 로 k8s 배포 : Windows (WSL2) 사용자

    더보기

    Step1. 기본 정보 확인

    # 클러스터 배포 전 확인
    docker ps
    mkdir ~/aews-labs
    cd ~/aews-labs
    
    # Create a cluster with kind : 1.29.14 , 1.30.10 , 1.31.6 , 1.32.2
    kind create cluster --name myk8s --image kindest/node:v1.32.2 --config - <<EOF
    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
      kubeadmConfigPatches:
      - |
        kind: ClusterConfiguration
        controllerManager:
          extraArgs:
            bind-address: "0.0.0.0"
        etcd:
          local:
            extraArgs:
              listen-metrics-urls: "http://0.0.0.0:2381"
        scheduler:
          extraArgs:
            bind-address: "0.0.0.0"
      - |
        kind: KubeProxyConfiguration
        metricsBindAddress: "0.0.0.0"
    EOF
    
    # 확인
    kind get nodes --name myk8s
    kubens default
    
    # kind 는 별도 도커 네트워크 생성 후 사용 : 기본값 172.18.0.0/16
    docker network ls
    docker inspect kind | jq
    
    # k8s api 주소 확인 : 어떻게 로컬에서 접속이 되는 걸까?
    kubectl cluster-info
    
    # 노드 정보 확인 : CRI 는 containerd 사용
    kubectl get node -o wide
    
    # 파드 정보 확인 : CNI 는 kindnet 사용
    kubectl get pod -A -o wide
    
    # 네임스페이스 확인 >> 도커 컨테이너에서 배운 네임스페이스와 다릅니다!
    kubectl get namespaces
    
    # 컨트롤플레인노드(컨테이너) 확인 : 도커 컨테이너 이름은 myk8s-control-plane
    docker ps
    docker images
    docker exec -it myk8s-control-plane ss -tnlp
    
    # 디버그용 내용 출력에 ~/.kube/config 권한 인증 로드
    kubectl get pod -v6
    
    # kube config 파일 확인 : "server: https://127.0.0.1:YYYYY" 127.0.0.1:Port로 접속 가능을 확인!
    cat ~/.kube/config
    ls -l ~/.kube/config

     

    Step2. Kube-Ops-View

    # kube-ops-view
    # helm show values geek-cookbook/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=30000 --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 확인 (1.5 , 2 배율) : 아래 접속 주소를 자신의 웹 브라우저에서 접속할 것!
    echo "http://127.0.0.1:30000/#scale=1.5"
    echo "http://127.0.0.1:30000/#scale=2"

     

    [ 참고 - 클러스터 삭제 ]

    # 클러스터 삭제
    kind delete cluster --name myk8s
    docker ps
    cat ~/.kube/config

     

    [옵션] prometheus-stack 설치 by helm - Link

    더보기
    # 모니터링
    watch kubectl get pod,pvc,svc,ingress -n monitoring
    
    # repo 추가
    helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
    helm repo update
    
    # 파라미터 파일 생성
    cat <<EOT > monitor-values.yaml
    prometheus:
      service:
        type: NodePort
        nodePort: 30001
        
      prometheusSpec:
        scrapeInterval: "15s"
        evaluationInterval: "15s"
        podMonitorSelectorNilUsesHelmValues: false
        serviceMonitorSelectorNilUsesHelmValues: false
        retention: 5d
        retentionSize: "10GiB"
    
    grafana:
      defaultDashboardsTimezone: Asia/Seoul
      adminPassword: prom-operator
      service:
        type: NodePort
        nodePort: 30002
    
    defaultRules:
      create: false
    prometheus-windows-exporter:
      prometheus:
        monitor:
          enabled: false
    alertmanager:
      enabled: false
    EOT
    cat monitor-values.yaml
    
    # 배포
    helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 69.3.1 \
    -f monitor-values.yaml --create-namespace --namespace monitoring
    
    # 각각 웹 접속 실행
    ## Windows(WSL2) 사용자는 아래 주소를 자신의 웹 브라우저에서 기입 후 직접 접속, 이후에도 동일.
    open http://127.0.0.1:30001 # macOS
    open http://127.0.0.1:30002 # macOS
    
    # 확인
    ## alertmanager-0 : 사전에 정의한 정책 기반(예: 노드 다운, 파드 Pending 등)으로 시스템 경고 메시지를 생성 후 경보 채널(슬랙 등)로 전송
    ## grafana : 프로메테우스는 메트릭 정보를 저장하는 용도로 사용하며, 그라파나로 시각화 처리
    ## prometheus-0 : 모니터링 대상이 되는 파드는 ‘exporter’라는 별도의 사이드카 형식의 파드에서 모니터링 메트릭을 노출, pull 방식으로 가져와 내부의 시계열 데이터베이스에 저장
    ## node-exporter : 노드익스포터는 물리 노드에 대한 자원 사용량(네트워크, 스토리지 등 전체) 정보를 메트릭 형태로 변경하여 노출
    ## operator : 시스템 경고 메시지 정책(prometheus rule), 애플리케이션 모니터링 대상 추가 등의 작업을 편리하게 할수 있게 CRD 지원
    ## kube-state-metrics : 쿠버네티스의 클러스터의 상태(kube-state)를 메트릭으로 변환하는 파드
    helm list -n monitoring
    kubectl get pod,svc,ingress,pvc -n monitoring
    kubectl get-all -n monitoring
    kubectl get prometheus,servicemonitors -n monitoring
    kubectl get crd | grep monitoring
    
    # 삭제
    helm uninstall -n monitoring kube-prometheus-stack

    (옵션) Bookinfo 애플리케이션 배포 및 반복 접속

    더보기
    # Bookinfo 애플리케이션 배포
    kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml
    
    # 확인
    kubectl get all,sa
    
    # ratings 파드에서 product 웹 접속(Service:ClusterIP) 확인
    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 서비스 NodePort 30003 설정
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: productpage
      labels:
        app: productpage
        service: productpage
    spec:
      type: NodePort
      ports:
      - name: http
        nodePort: 30003
        port: 9080
      selector:
        app: productpage
    EOF
    
    # productpage 서비스 NodePort 30003 접속
    ## Windows(WSL2) 사용자는 아래 주소를 자신의 웹 브라우저에서 기입 후 직접 접속, 이후에도 동일.
    echo "http://127.0.0.1:30003/productpage"
    open http://127.0.0.1:30003/productpage
    
    # 로그
    kubectl stern -l app=productpage
    혹은
    kubectl log -l app=productpage -f
    
    # NodePort 를 통한 반복 접속
    while true; do curl -s http://127.0.0.1:30003/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
    for i in {1..100};  do curl -s http://127.0.0.1:30003/productpage | grep -o "<title>.*</title>" ; done
    
    
    # (참고) bookinfo 삭제
    kubectl delete -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml

    kind : k8s(1.23.17) 배포

    더보기
    #
    git clone https://github.com/AcornPublishing/istio-in-action
    cd istio-in-action/book-source-code-master
    pwd # 각자 자신의 pwd 경로
    code .
    
    # 
    kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
      extraPortMappings:
      - containerPort: 30000 # Sample Application (istio-ingrssgateway)
        hostPort: 30000
      - containerPort: 30001 # Prometheus
        hostPort: 30001
      - containerPort: 30002 # Grafana
        hostPort: 30002
      - containerPort: 30003 # Kiali
        hostPort: 30003
      - containerPort: 30004 # Tracing
        hostPort: 30004
      - containerPort: 30005 # kube-ops-view
        hostPort: 30005
      extraMounts:
      - hostPath: /mnt/d/Learnings/03_AEWS/istio-in-action/book-source-code-master # 각자 자신의 pwd 경로로 설정
        containerPath: /istiobook
    networking:
      podSubnet: 10.10.0.0/16
      serviceSubnet: 10.200.1.0/24
    EOF
    
    # 설치 확인
    docker ps
    
    # 노드에 기본 툴 설치
    docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

    (옵션) 편의성 툴 설치

    더보기
    # (옵션) kube-ops-view
    helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
    helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30005 --set env.TZ="Asia/Seoul" --namespace kube-system
    kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view
    
    ## kube-ops-view 접속 URL 확인
    open "http://localhost:30005/#scale=1.5"
    open "http://localhost:30005/#scale=1.3"
    
    # (옵션) metrics-server
    helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
    helm install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
    kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server

    [ 실습하며 배우기 ]

    2.2 Getting to know the Istio control plane

    istio 1.17.8 설치 - Docs , Install , profile

    더보기
    # myk8s-control-plane 진입 후 설치 진행
    docker exec -it myk8s-control-plane bash
    -----------------------------------
    # 코드 파일들 마운트 확인
    tree /istiobook/ -L 1
    
    # istioctl 설치
    export ISTIOV=1.17.8
    echo 'export ISTIOV=1.17.8' >> /root/.bashrc
    
    curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
    tree istio-$ISTIOV -L 2 # sample yaml 포함
    cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
    istioctl version --remote=false
    
    # default 프로파일 컨트롤 플레인 배포
    istioctl x precheck # 설치 전 k8s 조건 충족 검사
    istioctl profile list
    istioctl install --set profile=default -y
    ✔ Istio core installed
    ✔ Istiod installed
    ✔ Ingress gateways installed
    ✔ Installation complete
    
    # 설치 확인 : istiod, istio-ingressgateway, crd 등
    kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
    ...
    NAME                                    READY   STATUS              RESTARTS   AGE
    istio-ingressgateway-58888b4f9b-gv7r9   1/1     Running             0          2m43s
    istiod-78c465d86b-tsd8l                 1/1     Running             0          3m
    ...
    
    kubectl get crd | grep istio.io | sort
    istioctl verify-install # 설치 확인
    
    # 보조 도구 설치
    kubectl apply -f istio-$ISTIOV/samples/addons
    
    #
    kubectl get pod -n istio-system
    NAME                                    READY   STATUS    RESTARTS   AGE
    grafana-67f5ccd9d7-cgkn4                1/1     Running   0          86s
    istio-ingressgateway-58888b4f9b-7t5zj   1/1     Running   0          116s
    istiod-78c465d86b-pvqv6                 1/1     Running   0          2m14s
    jaeger-78cb4f7d4b-d8b88                 1/1     Running   0          86s
    kiali-c946fb5bc-4njln                   1/1     Running   0          86s
    prometheus-7cc96d969f-6ft4s             2/2     Running   0          86s
    
    # 빠져나오기
    exit
    -----------------------------------
    
    #
    kubectl get cm -n istio-system istio -o yaml
    kubectl get cm -n istio-system istio -o yaml | kubectl neat

     

     


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

    2.3 Deploying your first application in the service mesh

    ▶ 서비스 메시에 첫 애플리케이션 배포

    더보기

     

    Step1. Webhook Mutating 을 활용하여 서비스 배포

    #
    kubectl create ns istioinaction
    
    # 방법1 : yaml에 sidecar 설정을 추가
    cat services/catalog/kubernetes/catalog.yaml
    docker exec -it myk8s-control-plane istioctl kube-inject -f /istiobook/services/catalog/kubernetes/catalog.yaml
    ...
      - args:
            - proxy
            - sidecar
            - --domain
            - $(POD_NAMESPACE).svc.cluster.local
            - --proxyLogLevel=warning
            - --proxyComponentLogLevel=misc:error
            - --log_output_level=default:info
            - --concurrency
            - "2"
            env:
            - name: JWT_POLICY
              value: third-party-jwt
            - name: PILOT_CERT_PROVIDER
              value: istiod
            - name: CA_ADDR
              value: istiod.istio-system.svc:15012
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
      ...
            image: docker.io/istio/proxyv2:1.13.0
            name: istio-proxy
    
    
    # 방법2 : namespace에 레이블을 추가하면 istiod (오퍼레이터)가 해당 namepsace의 pod spec에 자동으로 sidecar 설정을 주입
    kubectl label namespace istioinaction istio-injection=enabled
    kubectl get ns --show-labels
    
    # 
    kubectl get mutatingwebhookconfiguration
    NAME                         WEBHOOKS   AGE
    istio-revision-tag-default   4          9m24s # 특정 revision의 사이드카 주입 설정 관리
    istio-sidecar-injector       4          9m45s # Istio는 각 애플리케이션 Pod에 Envoy 사이드카 프록시를 자동으로 주입
                                                  ## 네임스페이스나 Pod에 istio-injection=enabled 라벨이 있어야 작동 
    
    kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml
    
    #
    kubectl get cm -n istio-system istio-sidecar-injector -o yaml | kubectl neat

     

     

    #
    cat services/catalog/kubernetes/catalog.yaml
    kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
    
    cat services/webapp/kubernetes/webapp.yaml 
    kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
    
    #
    kubectl get pod -n istioinaction
    NAME                     READY   STATUS    RESTARTS   AGE
    catalog-6cf4b97d-jx8xw   2/2     Running   0          29s
    webapp-7685bcb84-zlxmv   2/2     Running   0          29s
    
    # 접속 테스트용 netshoot 파드 생성
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: netshoot
    spec:
      containers:
      - name: netshoot
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]
      terminationGracePeriodSeconds: 0
    EOF
    
    # catalog 접속 확인
    kubectl exec -it netshoot -- curl -s http://catalog.istioinaction/items/1 | jq
    {
      "id": 1,
      "color": "amber",
      "department": "Eyewear",
      "name": "Elinor Glasses",
      "price": "282.00"
    }
    
    # webapp 접속 확인
    kubectl exec -it netshoot -- curl -s http://webapp.istioinaction/api/catalog/items/1 | jq
    {
      "id": 1,
      "color": "amber",
      "department": "Eyewear",
      "name": "Elinor Glasses",
      "price": "282.00"
    }
    # 아래 방법 대신 임시 사용
    kubectl port-forward -n istioinaction deploy/webapp 8080:8080
    확인 후 CTRL+C 로 종료
    
    #
    open http://localhost:8080

     

    2.4 Exploring the power of Istio with resilience, observability, and traffic control

    ▶ 복원력, 관찰가능성, 트래픽 제어

    더보기

    ☞ xDS 란?

     - eXtensible Discovery Service의 약자로, Istio의 동적 구성을 관리하는 핵심 기술입니다. Istio Envoy proxy에 동적으로 설정되는 데이터로, 노출할 포트, 라우팅 규칙, 업스트림 서비스 등이 포함됩니다.

     

    ☞ xDS의 주요기능

    • Istio Envoy proxy에 동적으로 구성 정보를 푸시할 수 있습니다.
    • Envoy 프록시가 동적으로 구성을 업데이트할 수 있습니다. 
    • 서비스 메시에서의 트래픽 관리를 최적화할 수 있습니다. 
    • 업스트림 클러스터의 멤버들을 관리할 수 있습니다. 

    ☞ xDS 종류

    - LDS (Listener Discovery Service), RDS (Route Discovery Service), CDS (Cluster Discovery Service), EDS (Endpoint Discovery Service). 

     

    ☞ xDS 동작순서(방식)

    1. Control Plane이 xDS API를 통해 Envoy에 구성 정보를 푸시하거나 Envoy가 주기적으로 요청하여 설정을 동기화 함
    2. Envoy-proxy (사이드카 및 게이트웨이)는 파드(컨테이너)가 뜨는 시점에 istiod를 구독하기 위해 커넥션을 맺음
    3. 구독이 완료되어야 istiod에서 server-side PUSH 가 가능함

    # istioctl proxy-status : 단축어 ps
    docker exec -it myk8s-control-plane istioctl proxy-status
    docker exec -it myk8s-control-plane istioctl ps
    
    #
    cat ch2/ingress-gateway.yaml
    cat <<EOF | kubectl -n istioinaction apply -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: outfitters-gateway
      namespace: istioinaction
    spec:
      selector:
        istio: ingressgateway # use istio default controller
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: webapp-virtualservice
      namespace: istioinaction
    spec:
      hosts:
      - "*"
      gateways:
      - outfitters-gateway
      http:
      - route:
        - destination:
            host: webapp
            port:
              number: 80
    EOF
    
    #
    kubectl get gw,vs -n istioinaction
    NAME                                             AGE
    gateway.networking.istio.io/outfitters-gateway   126m
    
    NAME                                                       GATEWAYS                 HOSTS   AGE
    virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]   126m
    
    
    # istioctl proxy-status : 단축어 ps
    docker exec -it myk8s-control-plane istioctl proxy-status
    NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
    catalog-6cf4b97d-nccfj.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
    istio-ingressgateway-996bc6bb6-mz544.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
    webapp-7685bcb84-c55ck.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-bj7h7     1.17.8
    
    ISTIOIGW=istio-ingressgateway-996bc6bb6-647tx.istio-system
    WEBAPP=webapp-7685bcb84-nfntj.istioinaction
    
    # istioctl proxy-config : 단축어 pc
    docker exec -it myk8s-control-plane istioctl proxy-config all $ISTIOIGW
    docker exec -it myk8s-control-plane istioctl proxy-config all $WEBAPP
    
    docker exec -it myk8s-control-plane istioctl proxy-config listener $ISTIOIGW
    docker exec -it myk8s-control-plane istioctl proxy-config route $ISTIOIGW
    docker exec -it myk8s-control-plane istioctl proxy-config cluster $ISTIOIGW
    docker exec -it myk8s-control-plane istioctl proxy-config endpoint $ISTIOIGW
    docker exec -it myk8s-control-plane istioctl proxy-config log $ISTIOIGW
    
    docker exec -it myk8s-control-plane istioctl proxy-config listener $WEBAPP
    docker exec -it myk8s-control-plane istioctl proxy-config route $WEBAPP
    docker exec -it myk8s-control-plane istioctl proxy-config cluster $WEBAPP
    docker exec -it myk8s-control-plane istioctl proxy-config endpoint $WEBAPP
    docker exec -it myk8s-control-plane istioctl proxy-config log $WEBAPP
    
    # envoy 가 사용하고 있는 인증서 정보 확인
    docker exec -it myk8s-control-plane istioctl proxy-config secret $ISTIOIGW
    docker exec -it myk8s-control-plane istioctl proxy-config secret $WEBAPP
    
    
    #
    docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system
    NAME          DOMAINS     MATCH                  VIRTUAL SERVICE
    http.8080     *           /*                     webapp-virtualservice.istioinaction
                  *           /stats/prometheus*
                  *           /healthz/ready*
    
    
    # istio-ingressgateway 서비스 NodePort 변경 및 nodeport 30000로 지정 변경
    kubectl get svc,ep -n istio-system istio-ingressgateway
    kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
    kubectl get svc -n istio-system istio-ingressgateway
    
    # istio-ingressgateway 서비스 externalTrafficPolicy 설정 : ClientIP 수집 확인
    kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
    kubectl describe svc -n istio-system istio-ingressgateway
    
    #
    kubectl stern -l app=webapp -n istioinaction
    kubectl stern -l app=catalog -n istioinaction
    
    #
    curl -s http://127.0.0.1:30000/api/catalog | jq
    curl -s http://127.0.0.1:30000/api/catalog/items/1 | jq
    curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1
    
    # webapp 반복 호출
    while true; do curl -s http://127.0.0.1:30000/api/catalog/items/1 ; sleep 1; echo; done
    while true; do curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1 ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
    while true; do curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1 ; date "+%Y-%m-%d %H:%M:%S" ; sleep 0.5; echo; done

     

    [ 실행 결과 한 눈에 보기 ]

    2.4.1 Istio observability

    ▶ Istio 관찰가능성

    더보기

     

    Step1. 각 Observability Tool을 Node Port 방식으로 띄우기

    # 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 메트릭 확인
    open http://127.0.0.1:30001
    
    # Grafana 접속
    open http://127.0.0.1:30002
    
    # Kiali 접속 1 : NodePort
    open http://127.0.0.1:30003
    
    # (옵션) Kiali 접속 2 : Port forward
    kubectl port-forward deployment/kiali -n istio-system 20001:20001 &
    open http://127.0.0.1:20001
    
    # tracing 접속 : 예거 트레이싱 대시보드
    open http://127.0.0.1:30004

     

    Step2. 그파라나 확인 : 대시보드 - Istio Service Dashboard ⇒ 상단 Service (webapp.. 선택) ← 트래픽 반복 접속 해둔 상태

     

    Step3. 오픈트레이싱을 통한 분산 트레이싱 : 예거 트레이싱 대시보드 확인

     

     

    Step4. Kiali 확인

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

     

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

    2.4.2 Istio for resiliency

    ▶ Catalog에 의도적으로 500에러를 재현하고 retry로 복원력 높이기

    더보기
    • 만약 ‘간헐적/일시적 네트워크 오류’가 발생하여 webapp 은 catalog 요청이 실패하는 경우가 발생 시, 애플리케이션 코드 수정 없이 복원력을 높여보자!

     Step1. bin/chaos.sh {에러코드} {빈도} - chaos.sh 500 50 (500에러를 50% 빈도로 재현)

    #
    docker exec -it myk8s-control-plane bash
    ----------------------------------------
    # istioinaction 로 네임스페이스 변경
    cat /etc/kubernetes/admin.conf
    kubectl config set-context $(kubectl config current-context) --namespace=istioinaction
    cat /etc/kubernetes/admin.conf
    
    cd /istiobook/bin/ 
    ./chaos.sh 500 100 # 모니터링 : kiali, grafana, tracing
    
    ./chaos.sh 500 50 # 모니터링 : kiali, grafana, tracing
    
    
    ##kubectl config set-context $(kubectl config current-context) --namespace=default
    ##cat /etc/kubernetes/admin.conf
    ----------------------------------------

     

    ☞ Kiali 대시보드 - red (Error) / blue (total req.) 


    Step2. 에러 발생 시 reslience 하게 retry 하도록 애플리케이션 코드 수정 없이 해보기!

     

    ☞ Resiliency 하게 해보자 ⇒ proxy(envoy)에 endpoint(catalog) 5xx 에러 시 retry 적용

    # catalog 3번까지 요청 재시도 할 수 있고, 각 시도에는 2초의 제한 시간이 있음.
    cat <<EOF | kubectl -n istioinaction apply -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: catalog
    spec:
      hosts:
      - catalog
      http:
      - route:
        - destination:
            host: catalog
        retries:
          attempts: 3
          retryOn: 5xx
          perTryTimeout: 2s
    EOF
    
    kubectl get vs -n istioinaction
    NAME                    GATEWAYS                 HOSTS         AGE
    catalog                                          ["catalog"]   12s
    webapp-virtualservice   ["outfitters-gateway"]   ["*"]         3h38m

     

    ☞ 결과적으로 client 에 응답 성공율이 높아졌다!

     

    그라파나 (Istio Mesh Dashboard) : retry 적용 후 Success Rate은 증가하고 5xx 에러는 감소하는 것을 확인할 수 있습니다.

     

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

     

     

    2.4.3 Istio for Traffic Routing

    ▶ 새 기능 추가 시나리오 대응

    더보기

     

    ☞ 특정 사용자 집단만 새 배포로 라우팅하도록, 릴리즈에 단계적 접근 : catalog v2 에 imageUrl 새 속성 추가

    # catalog v2 배포
    cat <<EOF | kubectl -n istioinaction apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: catalog
        version: v2
      name: catalog-v2
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: catalog
          version: v2
      template:
        metadata:
          labels:
            app: catalog
            version: v2
        spec:
          containers:
          - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: SHOW_IMAGE
              value: "true"
            image: istioinaction/catalog:latest
            imagePullPolicy: IfNotPresent
            name: catalog
            ports:
            - containerPort: 3000
              name: http
              protocol: TCP
            securityContext:
              privileged: false
    EOF
    
    # (옵션) 500 에러 발생 꺼두기
    docker exec -it myk8s-control-plane bash
    ----------------------------------------
    cd /istiobook/bin/
    ./chaos.sh 500 delete
    exit
    ----------------------------------------
    
    #
    kubectl get deploy,pod,svc,ep -n istioinaction
    kubectl get gw,vs -n istioinaction
    
    # 반복 접속 종료해두기

    v1만 접속 설정

    #
    cat <<EOF | kubectl -n istioinaction apply -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: catalog
    spec:
      host: catalog
      subsets:
      - name: version-v1
        labels:
          version: v1
      - name: version-v2
        labels:
          version: v2
    EOF
    
    #
    kubectl get gw,vs,dr -n istioinaction
    
    # 반복 접속 : v1,v2 분산 접속 확인
    while true; do curl -s http://127.0.0.1:30000/api/catalog | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
    
    
    # v1 라우팅 VS 수정(업데이트)
    cat <<EOF | kubectl -n istioinaction apply -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: catalog
    spec:
      hosts:
      - catalog
      http:
      - route:
        - destination:
            host: catalog
            subset: version-v1
    EOF
    
    # 반복 접속 : v1 접속 확인
    while true; do curl -s http://127.0.0.1:30000/api/catalog | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done

     


    특정 헤더는 v2, 그외에는 v1 접속 설정

    # 라우팅 VS 수정(업데이트)
    cat <<EOF | kubectl -n istioinaction apply -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: catalog
    spec:
      hosts:
      - catalog
      http:
      - match:
        - headers:
            x-dark-launch:
              exact: "v2"
        route:
        - destination:
            host: catalog
            subset: version-v2
      - route:
        - destination:
            host: catalog
            subset: version-v1
    EOF
    
    #
    kubectl get gw,vs,dr -n istioinaction
    
    # 반복 접속 : v1 접속 확인
    while true; do curl -s http://127.0.0.1:30000/api/catalog | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
    
    # 반복 접속 : v2 접속 확인
    while true; do curl -s http://127.0.0.1:30000/api/catalog -H "x-dark-launch: v2" | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done

     

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

     

     

     

    ▶ 실습 완료 후, 자원 삭제

    kubectl delete deploy,svc,gw,vs,dr --all -n istioinaction && kind delete cluster --name myk8s

     


    [ 옵션 : 최신버전 실습 추가 ]

    • 실습 환경 : docker (kind - k8s 1.32.2) , istio 1.25.1

    kind : k8s(1.23.17) 배포

    더보기
    # 
    kind create cluster --name myk8s --image kindest/node:v1.32.2 --config - <<EOF
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
      extraPortMappings:
      - containerPort: 30000 # Sample Application
        hostPort: 30000
      - containerPort: 30001 # Prometheus
        hostPort: 30001
      - containerPort: 30002 # Grafana
        hostPort: 30002
      - containerPort: 30003 # Kiali
        hostPort: 30003
      - containerPort: 30004 # Tracing
        hostPort: 30004
      - containerPort: 30005 # kube-ops-view
        hostPort: 30005
    networking:
      podSubnet: 10.10.0.0/16
      serviceSubnet: 10.200.1.0/24
    EOF
    
    # 설치 확인
    docker ps
    
    # 노드에 기본 툴 설치
    docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

     

    [ 옵션 - 편의성 툴 설치 ]

    # (옵션) kube-ops-view
    helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
    helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30005 --set env.TZ="Asia/Seoul" --namespace kube-system
    kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view
    
    ## kube-ops-view 접속 URL 확인
    open "http://localhost:30005/#scale=1.5"
    open "http://localhost:30005/#scale=1.3"
    
    # (옵션) metrics-server
    helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
    helm install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
    kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server

     

     

    istio 1.25.1 설치 - GettingStarted , install , profile , brew , Github

    더보기

    A. mac 사용자

    brew install istioctl
    istioctl version --remote=false
    
    #
    export ISTIOV=1.25.1
    curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
    
    # 샘플 코드 확인
    cd istio-$ISTIOV
    tree
    code .
    
    # default 프로파일 배포
    cat <<EOF | istioctl install -y -f - 
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      profile: demo
      components:
        ingressGateways:
        - name: istio-ingressgateway
          enabled: true
        egressGateways:
        - name: istio-egressgateway
          enabled: false
    EOF

     

    B. Linux os WSL2 (Ubuntu) 사용자

    # istioctl 설치
    export ISTIOV=1.25.1
    echo 'export ISTIOV=1.25.1' >> /root/.bashrc
    
    curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
    tree istio-$ISTIOV -L 2 # sample yaml 포함
    cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
    istioctl version --remote=false
    
    
    # default 프로파일 배포
    cd istio-$ISTIOV
    cat <<EOF | istioctl install -y -f - 
    # IOP configuration used to install the demo profile without gateways.
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      profile: demo
      components:
        ingressGateways:
        - name: istio-ingressgateway
          enabled: true
        egressGateways:
        - name: istio-egressgateway
          enabled: false
    EOF

      

    C. 공통 - addon 설치

    # 설치 확인 : 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
    
    
    # default 네임스페이스에 istio-proxy sidecar 주입 설정 - Docs
    kubectl label namespace default istio-injection=enabled
    kubectl get ns --show-labels
    
    
    # addon 설치
    kubectl apply -f samples/addons
    kubectl rollout status deployment/kiali -n istio-system
    
    #
    kubectl get pod,svc -n istio-system
    
    # 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 메트릭 확인
    open http://127.0.0.1:30001
    
    # Grafana 접속
    open http://127.0.0.1:30002
    
    # Kiali 접속 1 : NodePort
    open http://127.0.0.1:30003
    
    # (옵션) Kiali 접속 2 : Port forward
    kubectl port-forward deployment/kiali -n istio-system 20001:20001 &
    open http://127.0.0.1:20001
    
    # tracing 접속 : 예거 트레이싱 대시보드
    open http://127.0.0.1:30004

     

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

     

     

     

    Bookinfo sample application 배포 - Docs

    더보기
    참조 : https://istio.io/latest/docs/examples/bookinfo/

     

    #
    kubectl apply -f 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

     

     

     

    Open the application to outside traffic

    더보기
    # Istio Gateway/VirtualService 설정
    cat samples/bookinfo/networking/bookinfo-gateway.yaml
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: bookinfo-gateway
    spec:
      # The selector matches the ingress gateway pod labels.
      # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
      selector:
        istio: ingressgateway # use istio default controller
      servers:
      - port:
          number: 8080
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: bookinfo
    spec:
      hosts:
      - "*"
      gateways:
      - bookinfo-gateway
      http:
      - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
        route:
        - destination:
            host: productpage
            port:
              number: 9080
              
    kubectl apply -f 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
    kubectl stern -l app=productpage
    
    # productpage 웹 접속 : 새로고침
    open http://127.0.0.1:30000/productpage
    curl -v -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>"
    
    # 반복 접속
    for i in {1..10};  do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; done
    for i in {1..100}; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; done
    
    while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
    while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.5; done
    while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done

     

     

    ☞ (참고) istio-ingressgateway 에 istio-proxy 에도 로깅 변경 해보자.

    kubectl exec -it deploy/istio-ingressgateway -n istio-system -- curl -X POST http://localhost:15000/logging
    kubectl exec -it deploy/istio-ingressgateway -n istio-system -- curl -X POST http://localhost:15000/logging?http=debug
    kubectl exec -it deploy/istio-ingressgateway -n istio-system -- curl -X POST http://localhost:15000/logging?http=info

     

    ☞ (참고) istio-ingressgateway 에 istio-proxy 에도 로깅 변경 해보자.

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

     

    ▶ 실습 완료 후 자원 삭제

    kind delete cluster --name myk8s

    [ 마무리 ]

    간단한 예제 환경이지만 kubeopsView 부터 Kiali, Prometheus, Jeger 까지 막강한 모니터링/분석 툴을 같이 보면서 Istio 단의 기능 조작만으로도 복잡한 코드 수정 없이 Incident 성 이벤트를 빠르게 대응할 수 있다는 것이 놀라웠다.

    현업 환경에서 많이 사용하고 있어 업무 활용을 위해  Istio의 configuration과 기타 기능에 대해서도 차근 차근 공부해야 겠다는 생각이 든다.


    [ 참고 링크 모음 ]

    더보기

    kind 소개 : ‘도커 IN 도커 docker in docker’로 쿠버네티스 클러스터 환경을 구성 - Link

    Envoy 에 관하여 : 추천 Blog 

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

    WSL 설치 : 참조1, 참조2, 참조3