서비스 메시는 애플리케이션을 대신해 프로세스 외부에서 투명하게 네트워크 트래픽을 처리하는 분산형 애플리케이션 인프라입니다.
데이터 플레인과 컨트롤 플레인으로 구성되며, 특정 프로그래밍 언어나 프레임워크에 의존하지 않고 중요한 애플리케이션 네트워킹 기능을 구현합니다.
클라우드 환경의 도전 과제
기존 해결책의 한계
[라이브러리 접근 방식의 문제점]
[중앙화된 인프라(ESB, API 게이트웨이)의 한계]
데이터 플레인
컨트롤 플레인
이스티오는 구글, IBM, 리프트가 개발한 오픈소스 서비스 메시 구현체로, 다음과 같은 구성요소를 가집니다.
서비스 복원력 패턴 구현
트래픽 제어
관찰 가능성
보안
장점
단점
ESB(Enterprise Service Bus)와 차이점
API 게이트웨이와 차이점
서비스 메시는 클라우드 환경에서 마이크로서비스 간 통신 문제를 해결하기 위한 강력한 패턴이며 애플리케이션 코드를 변경하지 않고도 복원력, 관찰 가능성, 보안, 트래픽 제어를 구현할 수 있어 개발자가 비즈니스 로직에 집중할 수 있게 해줍니다.
그러나 가장 중요한 점은 추가적인 복잡성을 도입하므로 도입 시 신중한 계획과 평가가 필요합니다.
실습을 위해 먼저 선행되어야 할 점은 Local PC 에 Docker Engine 이 설치되어 있어야합니다. Docker Desktop 대신 OrbStack 을 사용하였습니다.
또한, Minikube 대신 Kind : Docker-in-Docker 를 사용하여 k8s 클러스터를 프로비저닝 하는 환경으로 진행하겠습니다.
# Install Kind
brew install kind
kind --version
# Install kubectl
brew install kubernetes-cli
kubectl version --client=true
## kubectl -> k 단축키 설정
echo "alias =kubecolor" >> ~/.zshrc
# Install Helm
brew install helm
helm version
# 툴 설치
brew install krew
brew install kube-ps1
brew install kubectx
# kubectl 출력 시 하이라이트 처리
brew install kubecolor
echo "alias kubectl=kubecolor" >> ~/.zshrc
echo "compdef kubecolor=kubectl" >> ~/.zshrc
# krew 플러그인 설치
kubectl krew install neat stern
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: /Users/leeeuijoo/Downloads/playground/istio/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
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-bd6b6df9f-mrtvh 1/1 Running 0 3m54s
coredns-bd6b6df9f-sp6x6 1/1 Running 0 3m54s
etcd-myk8s-control-plane 1/1 Running 0 4m7s
kindnet-zzmv6 1/1 Running 0 3m54s
kube-apiserver-myk8s-control-plane 1/1 Running 0 4m7s
kube-controller-manager-myk8s-control-plane 1/1 Running 0 4m7s
kube-ops-view-79df45849b-nmpfj 1/1 Running 0 20s
kube-proxy-wnrhv 1/1 Running 0 3m54s
kube-scheduler-myk8s-control-plane 1/1 Running 0 4m7s
## 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
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-bd6b6df9f-mrtvh 1/1 Running 0 6m56s
coredns-bd6b6df9f-sp6x6 1/1 Running 0 6m56s
etcd-myk8s-control-plane 1/1 Running 0 7m9s
kindnet-zzmv6 1/1 Running 0 6m56s
kube-apiserver-myk8s-control-plane 1/1 Running 0 7m9s
kube-controller-manager-myk8s-control-plane 1/1 Running 0 7m9s
kube-ops-view-79df45849b-nmpfj 1/1 Running 0 3m22s
kube-proxy-wnrhv 1/1 Running 0 6m56s
kube-scheduler-myk8s-control-plane 1/1 Running 0 7m9s
metrics-server-65bb6f47b6-2xl5v 1/1 Running 0 68s
# myk8s-control-plane 진입 후 설치 진행
docker exec -it myk8s-control-plane bash
-----------------------------------
# 코드 파일들 마운트 확인
tree /istiobook/ -L 1
하기 이미지를 보시면 이전에 host mount path 를 컨테이너(Control Plane 서버) 디렉토리를 공유하고 있는 것을 보실 수 있습니다.
root@myk8s-control-plane:/istiobook# tree /istiobook/ -L 1
/istiobook/
|-- README.md
|-- appendices
|-- bin
|-- ch10
|-- ch11
|-- ch12
|-- ch13
|-- ch14
|-- ch2
|-- ch3
|-- ch4
|-- ch5
|-- ch6
|-- ch7
|-- ch8
|-- ch9
`-- services
17 directories, 1 file
[istio Install]
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
tree istio-$ISTIOV -L 2 # sample yaml 포함
root@myk8s-control-plane:/istiobook# tree istio-$ISTIOV -L 2
istio-1.17.8
|-- LICENSE
|-- README.md
|-- bin
| `-- istioctl
|-- manifest.yaml
|-- manifests
| |-- charts
| |-- examples
| `-- profiles
|-- samples
| |-- README.md
| |-- addons
| |-- bookinfo
| |-- certs
| |-- cicd
| |-- custom-bootstrap
| |-- extauthz
| |-- external
| |-- grpc-echo
| |-- health-check
| |-- helloworld
| |-- httpbin
| |-- jwt-server
| |-- kind-lb
| |-- multicluster
| |-- open-telemetry
| |-- operator
| |-- ratelimit
| |-- security
| |-- sleep
| |-- tcp-echo
| |-- wasm_modules
| `-- websockets
`-- tools
|-- _istioctl
|-- certs
`-- istioctl.bash
31 directories, 7 files
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false
root@myk8s-control-plane:/istiobook# cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
root@myk8s-control-plane:/istiobook# istioctl version --remote=false
1.17.8
istioctl x precheck # 설치 전 k8s 조건 충족 검사
istioctl profile list
istioctl install --set profile=default -y
root@myk8s-control-plane:/istiobook# istioctl x precheck
✔ No issues found when checking the cluster. Istio is safe to install or upgrade!
To get started, check out https://istio.io/latest/docs/setup/getting-started/
root@myk8s-control-plane:/istiobook# istioctl profile list
Istio configuration profiles:
ambient
default
demo
empty
external
minimal
openshift
preview
remote
root@myk8s-control-plane:/istiobook# istioctl install --set profile=default -y
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete Making this installation the default for injection and validation.
Thank you for installing Istio 1.17. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/hMHGiwZHPU7UQRWe9
kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
kubectl get crd | grep istio.io | sort
istioctl verify-install # 설치 확인
kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
NAME READY STATUS RESTARTS AGE
pod/istio-ingressgateway-996bc6bb6-dbkqg 1/1 Running 0 54s
pod/istiod-7df6ffc78d-nlvdc 1/1 Running 0 66s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-ingressgateway LoadBalancer 10.200.1.50 <pending> 15021:30191/TCP,80:30932/TCP,443:31839/TCP 54s
service/istiod ClusterIP 10.200.1.109 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 66s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/istio-ingressgateway 1/1 1 1 54s
deployment.apps/istiod 1/1 1 1 66s
NAME DESIRED CURRENT READY AGE
replicaset.apps/istio-ingressgateway-996bc6bb6 1 1 1 54s
replicaset.apps/istiod-7df6ffc78d 1 1 1 66s
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/istio-ingressgateway Deployment/istio-ingressgateway 9%/80% 1 5 1 54s
horizontalpodautoscaler.autoscaling/istiod Deployment/istiod 0%/80% 1 5 1 66s
NAME ENDPOINTS AGE
endpoints/istio-ingressgateway 10.10.0.8:15021,10.10.0.8:8080,10.10.0.8:8443 54s
endpoints/istiod 10.10.0.7:15012,10.10.0.7:15010,10.10.0.7:15017 + 1 more... 66s
NAME SECRETS AGE
serviceaccount/default 1 67s
serviceaccount/istio-ingressgateway-service-account 1 54s
serviceaccount/istio-reader-service-account 1 67s
serviceaccount/istiod 1 66s
serviceaccount/istiod-service-account 1 67s
NAME DATA AGE
configmap/istio 2 66s
configmap/istio-ca-root-cert 1 56s
configmap/istio-gateway-deployment-leader 0 57s
configmap/istio-gateway-status-leader 0 57s
configmap/istio-leader 0 57s
configmap/istio-namespace-controller-election 0 56s
configmap/istio-sidecar-injector 2 66s
configmap/kube-root-ca.crt 1 67s
NAME TYPE DATA AGE
secret/default-token-wxbjg kubernetes.io/service-account-token 3 67s
secret/istio-ca-secret istio.io/ca-root 5 57s
secret/istio-ingressgateway-service-account-token-6wmpb kubernetes.io/service-account-token 3 54s
secret/istio-reader-service-account-token-bkz4q kubernetes.io/service-account-token 3 67s
secret/istiod-service-account-token-5xjpd kubernetes.io/service-account-token 3 67s
secret/istiod-token-mcrhw kubernetes.io/service-account-token 3 66s
NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
poddisruptionbudget.policy/istio-ingressgateway 1 N/A 0 54s
poddisruptionbudget.policy/istiod 1 N/A 0 66s
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
현재는 Ingress Gateway 만 배포되어 있는 상태
아직 Egress GW 는 배포하지 않았습니다.
구성요소를 보게 되면 isiod 는 istio proxy 를 관리하고 있으며 xds API (Discovery API) 를 통해 proxy 안에 있는 Envoy 의 동적인 설정들을 주입시킵니다.
istiod 가 mtls 를 위한 인증서를 내려주는 로직입니다.
애플리케이션은 간단합니다.웹엡이라는 서비스는 카탈로그에 등록되어 있는 목록 정보들을 읽어나가는 애플리케이션 입니다.
서비스 매쉬를 주입하는 방법은 두가지 가 있는데 후자를 선택하여 진행합니다.
#
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
현재는 catalog service yaml 파일을 보게 되면 istio 관련 세팅이 없는 것을 볼 수 있습니다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: catalog
---
apiVersion: v1
kind: Service
metadata:
labels:
app: catalog
name: catalog
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 3000
selector:
app: catalog
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: catalog
version: v1
name: catalog
spec:
replicas: 1
selector:
matchLabels:
app: catalog
version: v1
template:
metadata:
labels:
app: catalog
version: v1
spec:
serviceAccountName: catalog
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: istioinaction/catalog:latest
imagePullPolicy: IfNotPresent
name: catalog
ports:
- containerPort: 3000
name: http
protocol: TCP
securityContext:
privileged: false
하지만, istio 인젝션을 추가 하게 되면 아래와 같습니다. 추가로 yaml 파일도 출력됩니다.
네트워크를 꺾기 위해 iptable 을 조작하는 것을 보실 수 있으며 또한, sidecar 컨테이너도 생성 되는 것을 보실 수 있습니다.
spec:
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: istioinaction/catalog:latest
imagePullPolicy: IfNotPresent
name: catalog
ports:
- containerPort: 3000
name: http
protocol: TCP
resources: {}
securityContext:
privileged: false
- 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
하지만 매번 이렇게 yaml 파일을 넣을 순 없으니 mutation Webhook(kube API 가 인증 인가 이후에 admission 컨트롤 단계를 진행할 때) 을 사용합니다. 이것이 바로 인젝션 자동 주입 입니다.
#
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
istioincation 네임스페이스에 라벨일 달린 것을 보실 수 있습니다.
이제, 실제 애플리케이션을 배포해보겠습니다.
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
NAME READY STATUS RESTARTS AGE
catalog-6cf4b97d-k6kw8 2/2 Running 0 4m59s
webapp-7685bcb84-gzwl6 2/2 Running 0 4m54s
배포된 것을 보실 수 있으며, 첫번째로 확인해 볼 내용은 Pod 에 컨테이너가 하나인데 2/2 를 확인할 수 있습니다.
하여, kubectl describe 로 해당 Pod 를 살펴봅니다.
Containers:
catalog:
Container ID: containerd://3ec216599ed739bd63dc43e502ba980cda670d791e8e2c412e74d9150ce5536f
Image: istioinaction/catalog:latest
Image ID: docker.io/istioinaction/catalog@sha256:304226b8b076ec363f72c0cd13d60ae1a913680a9f2e61e33254d1de5b34f8fb
Port: 3000/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 10 Apr 2025 10:41:45 +0900
Ready: True
Restart Count: 0
Environment:
KUBERNETES_NAMESPACE: istioinaction (v1:metadata.namespace)
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wzjxs (ro)
istio-proxy:
Container ID: containerd://a711e7bb1777eda8d7553345ef1602078cc170344a9015f9331bdfa02536824e
Image: docker.io/istio/proxyv2:1.17.8
Image ID: docker.io/istio/proxyv2@sha256:d33fd90e25c59f4f7378d1b9dd0eebbb756e03520ab09cf303a43b51b5cb01b8
Port: 15090/TCP
Host Port: 0/TCP
Args:
proxy
sidecar
--domain
$(POD_NAMESPACE).svc.cluster.local
--proxyLogLevel=warning
--proxyComponentLogLevel=misc:error
--log_output_level=default:info
--concurrency
2
State: Running
Started: Thu, 10 Apr 2025 10:41:45 +0900
Ready: True
Restart Count: 0
Limits:
cpu: 2
memory: 1Gi
Requests:
cpu: 100m
memory: 128Mi
즉, Admission Webhook 이 istio-proxy 를 자동으로 주입한 것입니다.
네트워크 트러블 슈팅 도구를 배포 - 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
kubectl get svc,ep -n istioinaction
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/catalog ClusterIP 10.200.1.112 <none> 80/TCP 9m48s
service/webapp ClusterIP 10.200.1.9 <none> 80/TCP 9m43s
NAME ENDPOINTS AGE
endpoints/catalog 10.10.0.13:3000 9m48s
endpoints/webapp 10.10.0.14:8080 9m43s
catalog 라는 서비스에 Cluster IP 에 매핑되는 도메인 주소로 접근하기 위해 netshoot Pod 에 접속하여 테스트
# catalog 접속 확인
kubectl exec -it netshoot -- curl -s http://catalog.istioinaction/items/1 | jq
# webapp 접속 확인
kubectl exec -it netshoot -- curl -s http://webapp.istioinaction/api/catalog/items/1 | jq
# 아래 방법 대신 임시 사용
kubectl port-forward -n istioinaction deploy/webapp 8080:8080
확인 후 CTRL+C 로 종료
#
open http://localhost:8080
두번째 명령어는 webapp 을 경유해서 catalog 서비스내 목록을 리턴 받는 명령어입니다.
현재 istioctl 명령어는 host 내에 설치가 되어 있지 않기 때문에 컨테이너 내에서 명령을 실행하는 점 참고를 부탁드립니다.
Istio 로 상태 정보 확인
# istioctl proxy-status : 단축어 ps
docker exec -it myk8s-control-plane istioctl proxy-status
docker exec -it myk8s-control-plane istioctl ps
docker exec -it myk8s-control-plane istioctl proxy-status ✔ 12:55:56
NAME CLUSTER CDS LDS EDS RDS ECDS ISTIOD VERSION
catalog-6cf4b97d-k6kw8.istioinaction Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-7df6ffc78d-nlvdc 1.17.8
istio-ingressgateway-996bc6bb6-dbkqg.istio-system Kubernetes SYNCED SYNCED SYNCED NOT SENT NOT SENT istiod-7df6ffc78d-nlvdc 1.17.8
webapp-7685bcb84-gzwl6.istioinaction Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-7df6ffc78d-nlvdc 1.17.8
docker exec -it myk8s-control-plane istioctl ps ✔ 13:06:17
NAME CLUSTER CDS LDS EDS RDS ECDS ISTIOD VERSION
catalog-6cf4b97d-k6kw8.istioinaction Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-7df6ffc78d-nlvdc 1.17.8
istio-ingressgateway-996bc6bb6-dbkqg.istio-system Kubernetes SYNCED SYNCED SYNCED NOT SENT NOT SENT istiod-7df6ffc78d-nlvdc 1.17.8
webapp-7685bcb84-gzwl6.istioinaction Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-7df6ffc78d-nlvdc 1.17.8
이제 istio Ingress GW 를 사용하여 webapp 을 Istio 망으로 외부에서 접근하는 내용을 다뤄보겠습니다.
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
여기서 중요한 점은 spec.selector, VirtualService 부분입니다.
[확인]
kubectl get gw,vs -n istioinaction ✔ kind-myk8s ⎈ 15:12:18
NAME AGE
gateway.networking.istio.io/outfitters-gateway 35s
NAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/webapp-virtualservice ["outfitters-gateway"] ["*"] 35s
추가적으로 아래는 evoy 로 동기화 되는 내용인데, envoy 에 대한 정보를 상세하게 보려면 아래의 명령어를 사용하시면 됩니다.
ISTIOIGW=istio-ingressgateway-996bc6bb6-dbkqg.istio-system
WEBAPP=webapp-7685bcb84-gzwl6.istioinaction
# 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
[route 확인]
docker exec -it myk8s-control-plane istioctl proxy-config route $ISTIOIGW ✔ 15:18:15
NAME DOMAINS MATCH VIRTUAL SERVICE
http.8080 * /* webapp-virtualservice.istioinaction
* /stats/prometheus*
* /healthz/ready*
[리스너 확인]
docker exec -it myk8s-control-plane istioctl proxy-config listener $ISTIOIGW ✔ 15:18:31
ADDRESS PORT MATCH DESTINATION
0.0.0.0 8080 ALL Route: http.8080
0.0.0.0 15021 ALL Inline Route: /healthz/ready*
0.0.0.0 15090 ALL Inline Route: /stats/prometheus*
[클러스터 확인]
docker exec -it myk8s-control-plane istioctl proxy-config cluster $ISTIOIGW ✔ 15:21:03
SERVICE FQDN PORT SUBSET DIRECTION TYPE DESTINATION RULE
BlackHoleCluster - - - STATIC
agent - - - STATIC
catalog.istioinaction.svc.cluster.local 80 - outbound EDS
grafana.istio-system.svc.cluster.local 3000 - outbound EDS
istio-ingressgateway.istio-system.svc.cluster.local 80 - outbound EDS
istio-ingressgateway.istio-system.svc.cluster.local 443 - outbound EDS
istio-ingressgateway.istio-system.svc.cluster.local 15021 - outbound EDS
istiod.istio-system.svc.cluster.local 443 - outbound EDS
istiod.istio-system.svc.cluster.local 15010 - outbound EDS
istiod.istio-system.svc.cluster.local 15012 - outbound EDS
istiod.istio-system.svc.cluster.local 15014 - outbound EDS
jaeger-collector.istio-system.svc.cluster.local 9411 - outbound EDS
jaeger-collector.istio-system.svc.cluster.local 14250 - outbound EDS
jaeger-collector.istio-system.svc.cluster.local 14268 - outbound EDS
kiali.istio-system.svc.cluster.local 9090 - outbound EDS
kiali.istio-system.svc.cluster.local 20001 - outbound EDS
kube-dns.kube-system.svc.cluster.local 53 - outbound EDS
kube-dns.kube-system.svc.cluster.local 9153 - outbound EDS
kube-ops-view.kube-system.svc.cluster.local 8080 - outbound EDS
kubernetes.default.svc.cluster.local 443 - outbound EDS
metrics-server.kube-system.svc.cluster.local 443 - outbound EDS
prometheus.istio-system.svc.cluster.local 9090 - outbound EDS
prometheus_stats - - - STATIC
sds-grpc - - - STATIC
tracing.istio-system.svc.cluster.local 80 - outbound EDS
tracing.istio-system.svc.cluster.local 16685 - outbound EDS
webapp.istioinaction.svc.cluster.local 80 - outbound EDS
xds-grpc - - - STATIC
zipkin - - - STRICT_DNS
zipkin.istio-system.svc.cluster.local 9411 - outbound EDS
[엔드포인트 확인]
docker exec -it myk8s-control-plane istioctl proxy-config endpoint $ISTIOIGW ✔ 15:21:56
ENDPOINT STATUS OUTLIER CHECK CLUSTER
10.10.0.10:9090 HEALTHY OK outbound|9090||prometheus.istio-system.svc.cluster.local
10.10.0.11:3000 HEALTHY OK outbound|3000||grafana.istio-system.svc.cluster.local
10.10.0.12:9090 HEALTHY OK outbound|9090||kiali.istio-system.svc.cluster.local
10.10.0.12:20001 HEALTHY OK outbound|20001||kiali.istio-system.svc.cluster.local
10.10.0.13:3000 HEALTHY OK outbound|80||catalog.istioinaction.svc.cluster.local
10.10.0.14:8080 HEALTHY OK outbound|80||webapp.istioinaction.svc.cluster.local
10.10.0.3:53 HEALTHY OK outbound|53||kube-dns.kube-system.svc.cluster.local
10.10.0.3:9153 HEALTHY OK outbound|9153||kube-dns.kube-system.svc.cluster.local
10.10.0.4:53 HEALTHY OK outbound|53||kube-dns.kube-system.svc.cluster.local
10.10.0.4:9153 HEALTHY OK outbound|9153||kube-dns.kube-system.svc.cluster.local
10.10.0.5:8080 HEALTHY OK outbound|8080||kube-ops-view.kube-system.svc.cluster.local
10.10.0.6:10250 HEALTHY OK outbound|443||metrics-server.kube-system.svc.cluster.local
10.10.0.7:15010 HEALTHY OK outbound|15010||istiod.istio-system.svc.cluster.local
10.10.0.7:15012 HEALTHY OK outbound|15012||istiod.istio-system.svc.cluster.local
10.10.0.7:15014 HEALTHY OK outbound|15014||istiod.istio-system.svc.cluster.local
10.10.0.7:15017 HEALTHY OK outbound|443||istiod.istio-system.svc.cluster.local
10.10.0.8:8080 HEALTHY OK outbound|80||istio-ingressgateway.istio-system.svc.cluster.local
10.10.0.8:8443 HEALTHY OK outbound|443||istio-ingressgateway.istio-system.svc.cluster.local
10.10.0.8:15021 HEALTHY OK outbound|15021||istio-ingressgateway.istio-system.svc.cluster.local
10.10.0.9:9411 HEALTHY OK outbound|9411||jaeger-collector.istio-system.svc.cluster.local
10.10.0.9:9411 HEALTHY OK outbound|9411||zipkin.istio-system.svc.cluster.local
10.10.0.9:14250 HEALTHY OK outbound|14250||jaeger-collector.istio-system.svc.cluster.local
10.10.0.9:14268 HEALTHY OK outbound|14268||jaeger-collector.istio-system.svc.cluster.local
10.10.0.9:16685 HEALTHY OK outbound|16685||tracing.istio-system.svc.cluster.local
10.10.0.9:16686 HEALTHY OK outbound|80||tracing.istio-system.svc.cluster.local
10.200.1.191:9411 HEALTHY OK zipkin
127.0.0.1:15000 HEALTHY OK prometheus_stats
127.0.0.1:15020 HEALTHY OK agent
192.168.97.2:6443 HEALTHY OK outbound|443||kubernetes.default.svc.cluster.local
unix://./etc/istio/proxy/XDS HEALTHY OK xds-grpc
unix://./var/run/secrets/workload-spiffe-uds/socket HEALTHY OK sds-grpc
[envoy가 사용하는 인증서 확인]
docker exec -it myk8s-control-plane istioctl proxy-config secret $ISTIOIGW ✔ 15:23:30
RESOURCE NAME TYPE STATUS VALID CERT SERIAL NUMBER NOT AFTER NOT BEFORE
default Cert Chain ACTIVE true 302875308037867659574676603792259781271 2025-04-11T01:11:33Z 2025-04-10T01:09:33Z
ROOTCA CA ACTIVE true 115355687722131461630430825423341905706 2035-04-08T01:11:22Z 2025-04-10T01:11:22Z
docker exec -it myk8s-control-plane istioctl proxy-config secret $WEBAPP ✔ 15:23:34
RESOURCE NAME TYPE STATUS VALID CERT SERIAL NUMBER NOT AFTER NOT BEFORE
default Cert Chain ACTIVE true 225597692875984161266694924911353550614 2025-04-11T01:41:53Z 2025-04-10T01:39:53Z
ROOTCA CA ACTIVE true 115355687722131461630430825423341905706 2035-04-08T01:11:22Z 2025-04-10T01:11:22Z
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
실제 애플리케이션에 접속
마스터 Node 의 30000 번 Port 로 접근 > istio ingressGW 가 수신 > GW + VirtualSerice 의 논리 세팅에 의해 > istio Service Mesh 내 web app 으로 라우팅이 진행됨
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
Obervability 세팅
# 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
따로 애플리케이션 내 telemetry 를 구성할 필요가 없습니다.
# Prometheus 접속 : envoy, istio 메트릭 확인
open http://127.0.0.1:30001
Grafana
# Grafana 접속
open http://127.0.0.1:30002
여러 대쉬보드가 존재
Kiali
# Kiali 접속 1 : NodePort
open http://127.0.0.1:30003
Kiali UI > Graph > NameSpace : istioinaction 으로 설정 이후 하기 이미지와 같이 설정합니다.
[워크로드 탭 > webapp]
또한, Log 도 찾아보실 수 있습니다.
추가로 Traces 를 지원하며 해당 Trace 를 찍고, 해당 Trace Number 를 사용하여 Jaeger 도구를 사용해 분석하실 수 있습니다.
가장 중요한 점은 Envoy 설정을 Kiali 내에서 보실 수 있다는 점도 포인트 입니다.
envoy config 를 보시게 되면 '왜 Trouble Shooting' 이 어려운가' 를 아실 수 있습니다...ㅎ
Jaeger
# tracing 접속 : 예거 트레이싱 대시보드
open http://127.0.0.1:30004
istio ingree gateway 를 Tracing 해보겠습니다.
한개의 요청(개별 Trace ID)에 대해서 Span 을 살펴보게 되면, 아래와 같습니다.
catalog에 의도적으로 500에러를 재현하고 retry로 복원력 높이기
만약 ‘간헐적/일시적 네트워크 오류’가 발생하여 webapp 은 catalog 요청 실패이 실패하는 경우가 발생 시, 애플리케이션 코드 수정 없이 복원력을 높여보겠습니다.
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
Kiali Dashboard 확인
Grafana Dashboard 확인
jaeger Dashboard 확인
코드 수정 없이 에러 발생 시 reslience 하게 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
root@myk8s-control-plane:/istiobook/bin# kubectl get vs -n istioinaction
NAME GATEWAYS HOSTS AGE
catalog ["catalog"] 34s
webapp-virtualservice ["outfitters-gateway"] ["*"] 3h22m
Kiali Dashboard 확인
Grafana DashBoard 확인
새 기능 추가 시나리오 대응
배포를 다양하게 진행하는데 굉장히 복잡한 배포를 진행할때 굉장히 유연하게 중앙에서 통제가 가능합니다.
개발자가 신규 버전의 catalog V2 를 개발을 하였으며 검증 절차를 거치기 위해 QA 팀이 검증을 진행한다고 가정 - 검증이 완료 되어 이상이 없다고 판단 되면 트래픽을 V2 로 보내는 시나리오 입니다.
특정 사용자 집단만 새 배포로 라우팅하도록, 릴리즈에 단계적 접근 : 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
- name: SHOW_IMAGE value: "true"
카탈로그의 새로운 이미지가 아니라 초기 이미지를 빌드할 때 환경 변수가 true 로 변경 되면 V2 로 배포가 되게끔 되어 있습니다.배포 진행 후에 500Error 발생 스크립트를 중지시켜 놓고 Kiali 를 모니터링 해봅니다.
이제 트래픽을 전환 해보겠습니다.
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 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
추가 시나리오 : x-dark-launch 헤더를 달고 오는 요청은 v2 로 라우팅 하는 시나리오
# 라우팅 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 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
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
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
[애플리케이션 노출]
# 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
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-proxy 파드에 envoy 컨테이너 admin 접속 포트 포워딩 설정
kubectl port-forward deployment/deploy-websrv 15000:15000 &
# envoy 컨테이너 admin 페이지 접속
open http://localhost:15000
kind delete cluster --name myk8s