일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Ingress
- traffic cloning
- peerauthentication
- loadbalancer
- kiali
- aws gateway api controller
- Kind
- authorizationpolicy
- docker
- aws eks
- argocd
- prometheus
- leastconnection
- service mesh
- WSL
- traffic mirroring
- CNI
- requestauthentication
- K8S
- vagrant
- istio in action
- Kubernetes
- service entry
- Observability
- CICD
- Istio
- vpc cni
- envoy
- Jenkins
- grafana
- Today
- Total
WellSpring
Istio 1주차 - Istio 소개, 첫걸음 본문
목차
※ 본 게재 글은 gasida님의 'Istio' 강의내용과 실습예제 및 AWS, Istio 공식 사이트, 'Istio In Action' 서적을 참고하여 작성하였습니다.
1. 들어가며
1-1. 서비스 메시 소개하기
☞ 서비스 메시는 애플리케이션의 서비스 간 모든 통신을 처리하는 소프트웨어 계층으로, 컨테이너화된 마이크로서비스로 구성된다. 현대 사회의 다양한 고객 Needs를 만족시키기 위해 어플리케이션은 날로 복잡도가 높아지고 있어 점점 모니터링 하기가 어려워 지고 있다. 이런 상황에서 서비스 메시는 서비스 간 연결을 관리하기 위해 모니터링, 로깅, 추적, 트래픽 제어와 같은 새로운 기능을 제공하고 있어 마이크로서비스가 요구하는 '서비스 수준 관찰성' 제공과 더불어 '서비스 수준 제어'를 가능케 해 준다.
1-2. 서비스 메시의 구성요소 - Link

a. Data Plane
- Applicatoin layer Proxy 사용하여 Application을 대신하여 네트워킹 트래픽을 관리해 줌
: 모든 SideCar Proxy 포함하며, 해당 요소는 다음과 같은 역할을 한다.
- 사이드카가 요청을 가로챕니다.
- 요청을 별도의 네트워크 연결로 캡슐화합니다.
- 소스 프록시와 대상 프록시 간에 안전하고 암호화된 채널을 설정합니다.
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 를 사용하면, 어떤 서비스가 서로 상호작용할 수 있고 어떤 서비스가 상호작용할수 없는지에 대해 아주 세밀한 규칙을 만들 수 있다.

- 트래픽은 이스티오 인그레스 게이트웨이를 통해 메시 외부의 클라이언트에서 클러스터로 들어온다.
- 트래픽이 쇼핑 카트 서비스로 이동한다. 트래픽은 먼저 해당 서비스 프록시를 통과한다.
- 서비스 프록시는 서비스에 타임아웃, 메트릭 수집, 보안 강제 등을 적용할 수 있다.
- 요청이 다양한 서비스를 거치므로, 이스티오의 서비스 프록시는 다양한 단계에서 요청을 가로채고 라우팅 결정을 내릴 수 있다.
- 이스티오의 컨트롤 플레인 istiod 는 라우팅, 보안, 텔레메트릭 수집, 복원력을 처리하는 이스티오 프록시를 설정하는 데 사용한다.
- 요청 메트릭은 주기적으로 다양한 수집 서비스로 전송된다. 분산 트레이싱 스팬은 트레이싱 저장소로 전송돼 시스템을 거치는 요청의 경로 및 지연 시간을 추후에 추적하는 용도로 사용할 수 있다.
[ 서비스 메시와 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 게이트웨이 프록시가 필요하지 않게 될 것이다.
[ 서비스 메시가 분산 아키텍쳐에 적합한 경우 ]
- 구현에 사용할 기술은 당면한 문제와 필요한 기능을 고려해 선택해야 한다.
- 이스티오 같은 서비스 메시 기술은 강력한 인프라 기능이여 분산 아키텍처의 많은 영역에 영향을 미친다.
- 그렇지만 모든 문제에 적합한 것은 아니므로 모든 문제에 해결책으로 고려해서는 안된다.
- 아래 그림은 클라우드 아키텍처에서 애플리케이션 네트워킹 관심사를 이상적으로 분리하는 방법을 보여준다.

- 아키텍처의 하위 계층에는 배포 자동화 인프라가 있다.
- 이 인프라는 코드를 플랫폼에 배포하는 역할을 담당한다. 이스티오는 어떤 배포 자동화 도구를 사용해야 하는지를 규정하거나 침해하지 않는다.
- 상위 계층에는 애플리케이션 비즈니스 로직(코드)이 있다. 이 코드에는 비즈니스 도메인은 물론 어떤 서비스를 어떤 순서로 호출할지, 서비스 상호작용 응답을 어떻게 처리할지, 프로세스 실패 시 어떻게 처리할지 등이 포함된다.
- 이스티오는 어떤 비즈니스 로직도 구현하거나 대체하지 않는다. 또한 서비스 오케스트레이션, 비즈니스 페이로드 변환, 페이로드 강화, 분할 집계, 규칙 계산 등을 수행하지 않는다. 이런 기능은 애플리케이션 내부 라이브러리와 프레임워크에 맡기는 것이 가장 좋다.
- 이스티오는 배포 플랫폼과 애플리케이션 코드 사이의 연결 조직 역할을 한다.
- 복잡한 네트워킹 코드를 애플리케이션 외부로 꺼낼 수 있게 하는 것이다.
[ 서비스 메시를 사용할 때의 단점 ]
- 첫 번째로, 서비스 메시를 사용하면 요청 경로에 미들웨어, 특히 프록시가 추가된다.
- 이 프록시가 많은 이점을 주기도 하지만, 프록시에 익숙하지 않은 이들에게는 블랙박스가 돼 애플리케이션의 동작을 디버깅하기 어렵게 만들 수 있다.
- 엔보이 프록시는 아주 디버깅하기 쉽도록, 네트워크상에서 발생하고 있는 일을 많이 노출하게 특별히 설계됐다.
- 그렇지만 엔보이를 운영하는 데 익숙하지 않은 사람들에게는 아주 복잡해 보일 수 있고, 기존 디버깅 방식을 방해할 수 있다.
- 두 번째로, 테넌시 측면이다.
- 메시는 메시 내에서 실행되는 서비스 만큼 가치가 있다. 즉, 메시 내에 서비스가 많을수록 그 서비스들을 운영하는 데 메시의 가치가 높아진다.
- 그러나 물리적 메시 배포의 테넌트 및 격리 모델에 적절한 정책, 자동화, 그리고 사전 고려 없이는 메시를 잘못 구성하면 많은 서비스에 영향을 미칠 수 있는 상황에 처할 수 있습니다. → 학습 필요. 잘 알고 설정 필요
- 마지막으로, 서비스 메시는 요청 경로에 위치하기 때문에 서비스 및 애플리케이션 아키텍처의 매우 중요한 요소가 된다.
- 서비스 메시는 보안, 관찰 가능성 및 라우팅 제어 자세를 개선할 수 있는 많은 기회를 제공할 수 있습니다.
- 단점은 메쉬가 또 다른 레이어와 또 다른 복잡성의 기회를 제공한다는 점입니다.
- 운영상 이슈(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 설치 : 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 동작순서(방식)
- Control Plane이 xDS API를 통해 Envoy에 구성 정보를 푸시하거나 Envoy가 주기적으로 요청하여 설정을 동기화 함
- Envoy-proxy (사이드카 및 게이트웨이)는 파드(컨테이너)가 뜨는 시점에 istiod를 구독하기 위해 커넥션을 맺음
- 구독이 완료되어야 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 확인
☞ Namespace 를 istioincation 로 선택 후 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

#
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과 기타 기능에 대해서도 차근 차근 공부해야 겠다는 생각이 든다.
[ 참고 링크 모음 ]
'ISTIO' 카테고리의 다른 글
Istio 5주차 - 마이크로서비스 통신 보안 (1) | 2025.05.04 |
---|---|
ISTIO 4주차 - Observability (0) | 2025.04.28 |
Istio-3주차 Istio Traffic 제어 및 복원력 (0) | 2025.04.19 |
Istio 2주차 - Envoy, Istio Gateway (0) | 2025.04.14 |