Post

Istio 1์ฃผ์ฐจ ์ •๋ฆฌ

๐Ÿณ kind : k8s(1.23.17) ๋ฐฐํฌ

1. ๊นƒ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ํด๋ก 

1
2
3
4
5
6
7
8
9
10
11
git clone https://github.com/AcornPublishing/istio-in-action
cd istio-in-action/book-source-code-master

# ๊ฒฐ๊ณผ
Cloning into 'istio-in-action'...
remote: Enumerating objects: 448, done.
remote: Counting objects: 100% (448/448), done.
remote: Compressing objects: 100% (341/341), done.
remote: Total 448 (delta 76), reused 448 (delta 76), pack-reused 0 (from 0)
Receiving objects: 100% (448/448), 17.29 MiB | 7.19 MiB/s, done.
Resolving deltas: 100% (76/76), done.

2. ํ˜„์žฌ ์ž‘์—… ๊ฒฝ๋กœ ํ™•์ธ

1
pwd

โœ…ย ์ถœ๋ ฅ

1
/home/devshin/workspace/istio/istio-in-action/book-source-code-master

3. ํด๋Ÿฌ์Šคํ„ฐ ์ƒ์„ฑ

  • pod ๋ฐ service ๋„คํŠธ์›Œํฌ ๋Œ€์—ญ ์ง€์ •
  • ์ถ”๊ฐ€ ํฌํŠธ ๋งคํ•‘๊ณผ ํ˜ธ์ŠคํŠธ ๊ฒฝ๋กœ ๋งˆ์šดํŠธ ์„ค์ •
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
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: /home/devshin/workspace/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

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
Creating cluster "myk8s" ...
 โœ“ Ensuring node image (kindest/node:v1.23.17) ๐Ÿ–ผ 
 โœ“ Preparing nodes ๐Ÿ“ฆ  
 โœ“ Writing configuration ๐Ÿ“œ 
 โœ“ Starting control-plane ๐Ÿ•น๏ธ 
 โœ“ Installing CNI ๐Ÿ”Œ 
 โœ“ Installing StorageClass ๐Ÿ’พ 
Set kubectl context to "kind-myk8s"
You can now use your cluster with:

kubectl cluster-info --context kind-myk8s

Thanks for using kind! ๐Ÿ˜Š

4. ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ ํ™•์ธ

1
docker ps

โœ…ย ์ถœ๋ ฅ

1
2
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                             NAMES
54d6019751b2   kindest/node:v1.23.17   "/usr/local/bin/entrโ€ฆ"   52 seconds ago   Up 51 seconds   0.0.0.0:30000-30005->30000-30005/tcp, 127.0.0.1:46707->6443/tcp   myk8s-control-plane

5. ๋…ธ๋“œ์— ๊ธฐ๋ณธ ํˆด ์„ค์น˜

1
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'

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
Get:4 http://deb.debian.org/debian bookworm/main amd64 Packages [8792 kB]
Get:5 http://deb.debian.org/debian bookworm-updates/main amd64 Packages [512 B]
Get:6 http://deb.debian.org/debian-security bookworm-security/main amd64 Packages [252 kB]
Fetched 9300 kB in 2s (4552 kB/s)                        
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
41 packages can be upgraded. Run 'apt list --upgradable' to see them.
....
...
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vimdiff (vimdiff) in auto mode
Setting up bind9-libs:amd64 (1:9.18.33-1~deb12u2) ...
Setting up openssh-client (1:9.2p1-2+deb12u5) ...
Setting up libxext6:amd64 (2:1.3.4-1+b1) ...
Setting up dbus-daemon (1.14.10-1~deb12u1) ...
Setting up libnet1:amd64 (1.1.6+dfsg-3.2) ...
Setting up libpcap0.8:amd64 (1.10.3-1) ...
Setting up dbus (1.14.10-1~deb12u1) ...
invoke-rc.d: policy-rc.d denied execution of start.
/usr/sbin/policy-rc.d returned 101, not running 'start dbus.service'
Setting up libgdbm-compat4:amd64 (1.23-3) ...
Setting up xauth (1:1.1.2-1) ...
Setting up bind9-host (1:9.18.33-1~deb12u2) ...
Setting up libperl5.36:amd64 (5.36.0-7+deb12u1) ...
Setting up tcpdump (4.99.3-1) ...
Setting up ngrep (1.47+ds1-5+b1) ...
Setting up perl (5.36.0-7+deb12u1) ...
Setting up bind9-dnsutils (1:9.18.33-1~deb12u2) ...
Setting up dnsutils (1:9.18.33-1~deb12u2) ...
Setting up liberror-perl (0.17029-2) ...
Setting up git (1:2.39.5-0+deb12u2) ...
Processing triggers for libc-bin (2.36-9+deb12u4) ...

6. ํŽธ์˜์„ฑ ํˆด ์„ค์น˜ - kube-ops-view

(1) Helm์„ ์‚ฌ์šฉํ•ด kube-ops-view ์„ค์น˜, ์„œ๋น„์Šค ํƒ€์ž…์€ NodePort, ํฌํŠธ ๋ฒˆํ˜ธ๋Š” 30005๋กœ ์„ค์ •

1
2
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

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
"geek-cookbook" already exists with the same configuration, skipping
NAME: kube-ops-view
LAST DEPLOYED: Sat Apr 12 23:12:43 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace kube-system -o jsonpath="{.spec.ports[0].nodePort}" services kube-ops-view)
  export NODE_IP=$(kubectl get nodes --namespace kube-system -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

(2) ๋ฆฌ์†Œ์Šค ์ƒํƒœ ํ™•์ธ

1
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/kube-ops-view   1/1     1            1           31s

NAME                                 READY   STATUS    RESTARTS   AGE
pod/kube-ops-view-79df45849b-6tlrg   1/1     Running   0          31s

NAME                    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
service/kube-ops-view   NodePort   10.200.1.11   <none>        8080:30005/TCP   31s

NAME                      ENDPOINTS        AGE
endpoints/kube-ops-view   10.10.0.5:8080   31s

(3) ์›น ์ ‘์†: http://localhost:30005/#scale=1.5

7. ๋ฉ”ํŠธ๋ฆญ ์„œ๋ฒ„ ์„ค์น˜

(1) Helm์„ ์‚ฌ์šฉํ•ด ๋ฉ”ํŠธ๋ฆญ ์„œ๋ฒ„ ์„ค์น˜

1
2
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

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"metrics-server" has been added to your repositories
NAME: metrics-server
LAST DEPLOYED: Sat Apr 12 23:15:52 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
***********************************************************************
* Metrics Server                                                      *
***********************************************************************
  Chart version: 3.12.2
  App version:   0.7.2
  Image tag:     registry.k8s.io/metrics-server/metrics-server:v0.7.2
***********************************************************************

(2) ๋ฆฌ์†Œ์Šค ์ƒํƒœ ํ™•์ธ

1
kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
NAME                                  READY   STATUS    RESTARTS   AGE
pod/metrics-server-65bb6f47b6-x6kvk   1/1     Running   0          34s

NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/metrics-server   ClusterIP   10.200.1.106   <none>        443/TCP   34s

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/metrics-server   1/1     1            1           34s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/metrics-server-65bb6f47b6   1         1         1       34s

๐Ÿ”ง istio(1.17.8) ์„ค์น˜

1. myk8s-control-plane ์ง„์ž…

1
2
3
docker exec -it myk8s-control-plane bash

root@myk8s-control-plane:/# 

2. ์ฝ”๋“œ ํŒŒ์ผ๋“ค ๋งˆ์šดํŠธ ํ™•์ธ

1
root@myk8s-control-plane:/# tree /istiobook/ -L 1

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/istiobook/
|-- README.md
|-- appendices
|-- bin
|-- ch10
|-- ch11
|-- ch12
|-- ch13
|-- ch14
|-- ch2
|-- ch3
|-- ch4
|-- ch5
|-- ch6
|-- ch7
|-- ch8
|-- ch9
`-- services

17 directories, 1 file

3. istioctl ์„ค์น˜

1
2
3
root@myk8s-control-plane:/# export ISTIOV=1.17.8
echo 'export ISTIOV=1.17.8' >> /root/.bashrc
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Downloading istio-1.17.8 from https://github.com/istio/istio/releases/download/1.17.8/istio-1.17.8-linux-amd64.tar.gz ...

Istio 1.17.8 download complete!

The Istio release archive has been downloaded to the istio-1.17.8 directory.

To configure the istioctl client tool for your workstation,
add the /istio-1.17.8/bin directory to your environment path variable with:
	export PATH="$PATH:/istio-1.17.8/bin"

Begin the Istio pre-installation check by running:
	istioctl x precheck 

Try Istio in ambient mode
	https://istio.io/latest/docs/ambient/getting-started/
Try Istio in sidecar mode
	https://istio.io/latest/docs/setup/getting-started/
Install guides for ambient mode
	https://istio.io/latest/docs/ambient/install/
Install guides for sidecar mode
	https://istio.io/latest/docs/setup/install/

Need more information? Visit https://istio.io/latest/docs/ 

4. ๋‹ค์šด๋กœ๋“œ ํŒŒ์ผ ๊ตฌ์กฐ ํ™•์ธ

1
root@myk8s-control-plane:/# tree istio-$ISTIOV -L 2

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
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

5. istioctl ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ณต์‚ฌ ๋ฐ ๋ฒ„์ „ ํ™•์ธ

1
2
root@myk8s-control-plane:/# cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
root@myk8s-control-plane:/# istioctl version --remote=false

โœ…ย ์ถœ๋ ฅ

1
1.17.8

6. Istio ํ”„๋กœํŒŒ์ผ ํ™•์ธ ๋ฐ ๊ธฐ๋ณธ ์„ค์น˜

(1) ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ Istio ํ”„๋กœํŒŒ์ผ ๋ชฉ๋ก ํ™•์ธ

1
root@myk8s-control-plane:/# istioctl profile list

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
Istio configuration profiles:
    ambient
    default
    demo
    empty
    external
    minimal
    openshift
    preview
    remote

(2) ๊ธฐ๋ณธ ํ”„๋กœํŒŒ์ผ(default)๋กœ ์„ค์น˜

1
root@myk8s-control-plane:/# istioctl install --set profile=default -y

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
โœ” 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

7. ์„ค์น˜ ์ƒํƒœ ๋ฐ ๊ตฌ์„ฑ ํ™•์ธ

(1) istiooperators ์ƒํƒœ ํ™•์ธ

1
root@myk8s-control-plane:/# kubectl get istiooperators -n istio-system

โœ…ย ์ถœ๋ ฅ

1
2
NAME              REVISION   STATUS   AGE
installed-state                       35

(2) istiooperators ์„ธ๋ถ€ ๊ตฌ์„ฑ ํ™•์ธ

1
root@myk8s-control-plane:/# kubectl get istiooperators -n istio-system -o yaml

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
apiVersion: v1
items:
- apiVersion: install.istio.io/v1alpha1
  kind: IstioOperator
  metadata:
    annotations:
      install.istio.io/ignoreReconcile: "true"
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"install.istio.io/v1alpha1","kind":"IstioOperator","metadata":{"annotations":{"install.istio.io/ignoreReconcile":"true"},"creationTimestamp":null,"name":"installed-state","namespace":"istio-system"},"spec":{"components":{"base":{"enabled":true},"cni":{"enabled":false},"egressGateways":[{"enabled":false,"name":"istio-egressgateway"}],"ingressGateways":[{"enabled":true,"name":"istio-ingressgateway"}],"istiodRemote":{"enabled":false},"pilot":{"enabled":true}},"hub":"docker.io/istio","meshConfig":{"defaultConfig":{"proxyMetadata":{}},"enablePrometheusMerge":true},"profile":"default","tag":"1.17.8","values":{"base":{"enableCRDTemplates":false,"validationURL":""},"defaultRevision":"","gateways":{"istio-egressgateway":{"autoscaleEnabled":true,"env":{},"name":"istio-egressgateway","secretVolumes":[{"mountPath":"/etc/istio/egressgateway-certs","name":"egressgateway-certs","secretName":"istio-egressgateway-certs"},{"mountPath":"/etc/istio/egressgateway-ca-certs","name":"egressgateway-ca-certs","secretName":"istio-egressgateway-ca-certs"}],"type":"ClusterIP"},"istio-ingressgateway":{"autoscaleEnabled":true,"env":{},"name":"istio-ingressgateway","secretVolumes":[{"mountPath":"/etc/istio/ingressgateway-certs","name":"ingressgateway-certs","secretName":"istio-ingressgateway-certs"},{"mountPath":"/etc/istio/ingressgateway-ca-certs","name":"ingressgateway-ca-certs","secretName":"istio-ingressgateway-ca-certs"}],"type":"LoadBalancer"}},"global":{"configValidation":true,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"imagePullPolicy":"","imagePullSecrets":[],"istioNamespace":"istio-system","istiod":{"enableAnalysis":false},"jwtPolicy":"third-party-jwt","logAsJson":false,"logging":{"level":"default:info"},"meshNetworks":{},"mountMtlsCerts":false,"multiCluster":{"clusterName":"","enabled":false},"network":"","omitSidecarInjectorConfigMap":false,"oneNamespace":false,"operatorManageWebhooks":false,"pilotCertProvider":"istiod","priorityClassName":"","proxy":{"autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"misc:error","enableCoreDump":false,"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","logLevel":"warning","privileged":false,"readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2","resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"sds":{"token":{"aud":"istio-ca"}},"sts":{"servicePort":0},"tracer":{"datadog":{},"lightstep":{},"stackdriver":{},"zipkin":{}},"useMCP":false},"istiodRemote":{"injectionURL":""},"pilot":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"configMap":true,"cpu":{"targetAverageUtilization":80},"deploymentLabels":null,"enableProtocolSniffingForInbound":true,"enableProtocolSniffingForOutbound":true,"env":{},"image":"pilot","keepaliveMaxServerConnectionAge":"30m","nodeSelector":{},"podLabels":{},"replicaCount":1,"traceSampling":1},"telemetry":{"enabled":true,"v2":{"enabled":true,"metadataExchange":{"wasmEnabled":false},"prometheus":{"enabled":true,"wasmEnabled":false},"stackdriver":{"configOverride":{},"enabled":false,"logging":false,"monitoring":false,"topology":false}}}}}}
    creationTimestamp: "2025-04-12T14:35:15Z"
    generation: 1
    name: installed-state
    namespace: istio-system
    resourceVersion: "2681"
    uid: 7baf9f8e-bd3f-477e-ac38-31466c740879
  spec:
    components:
      base:
        enabled: true
      cni:
        enabled: false
      egressGateways:
      - enabled: false
        name: istio-egressgateway
      ingressGateways:
      - enabled: true
        name: istio-ingressgateway
      istiodRemote:
        enabled: false
      pilot:
        enabled: true
    hub: docker.io/istio
    meshConfig:
      defaultConfig:
        proxyMetadata: {}
      enablePrometheusMerge: true
    profile: default
    tag: 1.17.8
    values:
      base:
        enableCRDTemplates: false
        validationURL: ""
      defaultRevision: ""
      gateways:
        istio-egressgateway:
          autoscaleEnabled: true
          env: {}
          name: istio-egressgateway
          secretVolumes:
          - mountPath: /etc/istio/egressgateway-certs
            name: egressgateway-certs
            secretName: istio-egressgateway-certs
          - mountPath: /etc/istio/egressgateway-ca-certs
            name: egressgateway-ca-certs
            secretName: istio-egressgateway-ca-certs
          type: ClusterIP
        istio-ingressgateway:
          autoscaleEnabled: true
          env: {}
          name: istio-ingressgateway
          secretVolumes:
          - mountPath: /etc/istio/ingressgateway-certs
            name: ingressgateway-certs
            secretName: istio-ingressgateway-certs
          - mountPath: /etc/istio/ingressgateway-ca-certs
            name: ingressgateway-ca-certs
            secretName: istio-ingressgateway-ca-certs
          type: LoadBalancer
      global:
        configValidation: true
        defaultNodeSelector: {}
        defaultPodDisruptionBudget:
          enabled: true
        defaultResources:
          requests:
            cpu: 10m
        imagePullPolicy: ""
        imagePullSecrets: []
        istioNamespace: istio-system
        istiod:
          enableAnalysis: false
        jwtPolicy: third-party-jwt
        logAsJson: false
        logging:
          level: default:info
        meshNetworks: {}
        mountMtlsCerts: false
        multiCluster:
          clusterName: ""
          enabled: false
        network: ""
        omitSidecarInjectorConfigMap: false
        oneNamespace: false
        operatorManageWebhooks: false
        pilotCertProvider: istiod
        priorityClassName: ""
        proxy:
          autoInject: enabled
          clusterDomain: cluster.local
          componentLogLevel: misc:error
          enableCoreDump: false
          excludeIPRanges: ""
          excludeInboundPorts: ""
          excludeOutboundPorts: ""
          image: proxyv2
          includeIPRanges: '*'
          logLevel: warning
          privileged: false
          readinessFailureThreshold: 30
          readinessInitialDelaySeconds: 1
          readinessPeriodSeconds: 2
          resources:
            limits:
              cpu: 2000m
              memory: 1024Mi
            requests:
              cpu: 100m
              memory: 128Mi
          statusPort: 15020
          tracer: zipkin
        proxy_init:
          image: proxyv2
          resources:
            limits:
              cpu: 2000m
              memory: 1024Mi
            requests:
              cpu: 10m
              memory: 10Mi
        sds:
          token:
            aud: istio-ca
        sts:
          servicePort: 0
        tracer:
          datadog: {}
          lightstep: {}
          stackdriver: {}
          zipkin: {}
        useMCP: false
      istiodRemote:
        injectionURL: ""
      pilot:
        autoscaleEnabled: true
        autoscaleMax: 5
        autoscaleMin: 1
        configMap: true
        cpu:
          targetAverageUtilization: 80
        deploymentLabels: null
        enableProtocolSniffingForInbound: true
        enableProtocolSniffingForOutbound: true
        env: {}
        image: pilot
        keepaliveMaxServerConnectionAge: 30m
        nodeSelector: {}
        podLabels: {}
        replicaCount: 1
        traceSampling: 1
      telemetry:
        enabled: true
        v2:
          enabled: true
          metadataExchange:
            wasmEnabled: false
          prometheus:
            enabled: true
            wasmEnabled: false
          stackdriver:
            configOverride: {}
            enabled: false
            logging: false
            monitoring: false
            topology: false
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

(3) istio ๊ด€๋ จ ๋ฆฌ์†Œ์Šค ํ™•์ธ

1
root@myk8s-control-plane:/# kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
NAME                                       READY   STATUS    RESTARTS   AGE
pod/istio-ingressgateway-996bc6bb6-b24ff   1/1     Running   0          2m4s
pod/istiod-7df6ffc78d-25zjr                1/1     Running   0          2m20s

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                      AGE
service/istio-ingressgateway   LoadBalancer   10.200.1.191   <pending>     15021:30191/TCP,80:31021/TCP,443:31846/TCP   2m4s
service/istiod                 ClusterIP      10.200.1.144   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP        2m20s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/istio-ingressgateway   1/1     1            1           2m4s
deployment.apps/istiod                 1/1     1            1           2m20s

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/istio-ingressgateway-996bc6bb6   1         1         1       2m4s
replicaset.apps/istiod-7df6ffc78d                1         1         1       2m20s

NAME                                                       REFERENCE                         TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/istio-ingressgateway   Deployment/istio-ingressgateway   6%/80%    1         5         1          2m4s
horizontalpodautoscaler.autoscaling/istiod                 Deployment/istiod                 0%/80%    1         5         1          2m20s

NAME                             ENDPOINTS                                                     AGE
endpoints/istio-ingressgateway   10.10.0.8:15021,10.10.0.8:8080,10.10.0.8:8443                 2m4s
endpoints/istiod                 10.10.0.7:15012,10.10.0.7:15010,10.10.0.7:15017 + 1 more...   2m20s

NAME                                                  SECRETS   AGE
serviceaccount/default                                1         2m22s
serviceaccount/istio-ingressgateway-service-account   1         2m4s
serviceaccount/istio-reader-service-account           1         2m21s
serviceaccount/istiod                                 1         2m21s
serviceaccount/istiod-service-account                 1         2m21s

NAME                                            DATA   AGE
configmap/istio                                 2      2m20s
configmap/istio-ca-root-cert                    1      2m7s
configmap/istio-gateway-deployment-leader       0      2m7s
configmap/istio-gateway-status-leader           0      2m7s
configmap/istio-leader                          0      2m7s
configmap/istio-namespace-controller-election   0      2m7s
configmap/istio-sidecar-injector                2      2m20s
configmap/kube-root-ca.crt                      1      2m22s

NAME                                                      TYPE                                  DATA   AGE
secret/default-token-mt6d9                                kubernetes.io/service-account-token   3      2m22s
secret/istio-ca-secret                                    istio.io/ca-root                      5      2m7s
secret/istio-ingressgateway-service-account-token-vrgzz   kubernetes.io/service-account-token   3      2m4s
secret/istio-reader-service-account-token-57zcm           kubernetes.io/service-account-token   3      2m21s
secret/istiod-service-account-token-5gkrg                 kubernetes.io/service-account-token   3      2m21s
secret/istiod-token-9vsfv                                 kubernetes.io/service-account-token   3      2m21s

NAME                                              MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
poddisruptionbudget.policy/istio-ingressgateway   1               N/A               0                     2m4s
poddisruptionbudget.policy/istiod                 1               N/A               0                     2m20s
1
root@myk8s-control-plane:/# kubectl get crd | grep istio.io | sort

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
authorizationpolicies.security.istio.io    2025-04-12T14:34:47Z
destinationrules.networking.istio.io       2025-04-12T14:34:47Z
envoyfilters.networking.istio.io           2025-04-12T14:34:48Z
gateways.networking.istio.io               2025-04-12T14:34:48Z
istiooperators.install.istio.io            2025-04-12T14:34:48Z
peerauthentications.security.istio.io      2025-04-12T14:34:48Z
proxyconfigs.networking.istio.io           2025-04-12T14:34:48Z
requestauthentications.security.istio.io   2025-04-12T14:34:48Z
serviceentries.networking.istio.io         2025-04-12T14:34:48Z
sidecars.networking.istio.io               2025-04-12T14:34:48Z
telemetries.telemetry.istio.io             2025-04-12T14:34:48Z
virtualservices.networking.istio.io        2025-04-12T14:34:48Z
wasmplugins.extensions.istio.io            2025-04-12T14:34:48Z
workloadentries.networking.istio.io        2025-04-12T14:34:48Z
workloadgroups.networking.istio.io         2025-04-12T14:34:48Z

8. ๋ณด์กฐ ๋„๊ตฌ(addons) ์„ค์น˜

(1) istio ์ƒ˜ํ”Œ ์• ๋“œ์˜จ ๋ฆฌ์†Œ์Šค ์ ์šฉ

1
root@myk8s-control-plane:/# kubectl apply -f istio-$ISTIOV/samples/addons

โœ…ย ์ถœ๋ ฅ

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
serviceaccount/grafana created
configmap/grafana created
service/grafana created
deployment.apps/grafana created
configmap/istio-grafana-dashboards created
configmap/istio-services-grafana-dashboards created
deployment.apps/jaeger created
service/tracing created
service/zipkin created
service/jaeger-collector created
serviceaccount/kiali created
configmap/kiali created
clusterrole.rbac.authorization.k8s.io/kiali-viewer created
clusterrole.rbac.authorization.k8s.io/kiali created
clusterrolebinding.rbac.authorization.k8s.io/kiali created
role.rbac.authorization.k8s.io/kiali-controlplane created
rolebinding.rbac.authorization.k8s.io/kiali-controlplane created
service/kiali created
deployment.apps/kiali created
serviceaccount/prometheus created
configmap/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
service/prometheus created
deployment.apps/prometheus created

(2) ์„ค์น˜ ํ›„ istio-system ๋„ค์ž„์ŠคํŽ˜์ด์Šค(Pod) ์ƒํƒœ ํ™•์ธ

1
root@myk8s-control-plane:/# kubectl get pod -n istio-system

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
NAME                                   READY   STATUS    RESTARTS   AGE
grafana-b854c6c8-j2g5j                 1/1     Running   0          47s
istio-ingressgateway-996bc6bb6-b24ff   1/1     Running   0          5m54s
istiod-7df6ffc78d-25zjr                1/1     Running   0          6m10s
jaeger-5556cd8fcf-8l5ht                1/1     Running   0          47s
kiali-648847c8c4-krnzf                 0/1     Running   0          47s
prometheus-7b8b9dd44c-8hc8g            2/2     Running   0          47s

9. ConfigMap ํ™•์ธ

1
2
root@myk8s-control-plane:/# exit
kubectl get cm -n istio-system istio -o yaml | kubectl neat

โœ…ย ์ถœ๋ ฅ

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
apiVersion: v1
data:
  mesh: |-
    defaultConfig:
      discoveryAddress: istiod.istio-system.svc:15012
      proxyMetadata: {}
      tracing:
        zipkin:
          address: zipkin.istio-system:9411
    enablePrometheusMerge: true
    rootNamespace: istio-system
    trustDomain: cluster.local
  meshNetworks: 'networks: {}'
kind: ConfigMap
metadata:
  labels:
    install.operator.istio.io/owning-resource: unknown
    install.operator.istio.io/owning-resource-namespace: istio-system
    istio.io/rev: default
    operator.istio.io/component: Pilot
    operator.istio.io/managed: Reconcile
    operator.istio.io/version: 1.17.8
    release: istio
  name: istio
  namespace: istio-system

โœจ ์„œ๋น„์Šค ๋ฉ”์‹œ์— ์ฒซ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ

1. ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ƒ์„ฑ

1
2
3
4
kubectl create ns istioinaction

# ๊ฒฐ๊ณผ
namespace/istioinaction created

2. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํ™•์ธ

1
cat services/catalog/kubernetes/catalog.yaml

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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

3. istio ์‚ฌ์ด๋“œ์นด ์ž๋™ ์ฃผ์ž… ์‹คํ–‰

1
docker exec -it myk8s-control-plane istioctl kube-inject -f /istiobook/services/catalog/kubernetes/catalog.yaml

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
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:
  creationTimestamp: null
  labels:
    app: catalog
    version: v1
  name: catalog
spec:
  replicas: 1
  selector:
    matchLabels:
      app: catalog
      version: v1
  strategy: {}
  template:
    metadata:
      annotations:
        kubectl.kubernetes.io/default-container: catalog
        kubectl.kubernetes.io/default-logs-container: catalog
        prometheus.io/path: /stats/prometheus
        prometheus.io/port: "15020"
        prometheus.io/scrape: "true"
        sidecar.istio.io/status: '{"initContainers":["istio-init"],"containers":["istio-proxy"],"volumes":["workload-socket","credential-socket","workload-certs","istio-envoy","istio-data","istio-podinfo","istio-token","istiod-ca-cert"],"imagePullSecrets":null,"revision":"default"}'
      creationTimestamp: null
      labels:
        app: catalog
        security.istio.io/tlsMode: istio
        service.istio.io/canonical-name: catalog
        service.istio.io/canonical-revision: v1
        version: v1
    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
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: INSTANCE_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
        - name: HOST_IP
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: PROXY_CONFIG
          value: |
            {}
        - name: ISTIO_META_POD_PORTS
          value: |-
            [
                {"name":"http","containerPort":3000,"protocol":"TCP"}
            ]
        - name: ISTIO_META_APP_CONTAINERS
          value: catalog
        - name: ISTIO_META_CLUSTER_ID
          value: Kubernetes
        - name: ISTIO_META_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: ISTIO_META_INTERCEPTION_MODE
          value: REDIRECT
        - name: ISTIO_META_MESH_ID
          value: cluster.local
        - name: TRUST_DOMAIN
          value: cluster.local
        image: docker.io/istio/proxyv2:1.17.8
        name: istio-proxy
        ports:
        - containerPort: 15090
          name: http-envoy-prom
          protocol: TCP
        readinessProbe:
          failureThreshold: 30
          httpGet:
            path: /healthz/ready
            port: 15021
          initialDelaySeconds: 1
          periodSeconds: 2
          timeoutSeconds: 3
        resources:
          limits:
            cpu: "2"
            memory: 1Gi
          requests:
            cpu: 100m
            memory: 128Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
          privileged: false
          readOnlyRootFilesystem: true
          runAsGroup: 1337
          runAsNonRoot: true
          runAsUser: 1337
        volumeMounts:
        - mountPath: /var/run/secrets/workload-spiffe-uds
          name: workload-socket
        - mountPath: /var/run/secrets/credential-uds
          name: credential-socket
        - mountPath: /var/run/secrets/workload-spiffe-credentials
          name: workload-certs
        - mountPath: /var/run/secrets/istio
          name: istiod-ca-cert
        - mountPath: /var/lib/istio/data
          name: istio-data
        - mountPath: /etc/istio/proxy
          name: istio-envoy
        - mountPath: /var/run/secrets/tokens
          name: istio-token
        - mountPath: /etc/istio/pod
          name: istio-podinfo
      initContainers:
      - args:
        - istio-iptables
        - -p
        - "15001"
        - -z
        - "15006"
        - -u
        - "1337"
        - -m
        - REDIRECT
        - -i
        - '*'
        - -x
        - ""
        - -b
        - '*'
        - -d
        - 15090,15021,15020
        - --log_output_level=default:info
        image: docker.io/istio/proxyv2:1.17.8
        name: istio-init
        resources:
          limits:
            cpu: "2"
            memory: 1Gi
          requests:
            cpu: 100m
            memory: 128Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_ADMIN
            - NET_RAW
            drop:
            - ALL
          privileged: false
          readOnlyRootFilesystem: false
          runAsGroup: 0
          runAsNonRoot: false
          runAsUser: 0
      serviceAccountName: catalog
      volumes:
      - name: workload-socket
      - name: credential-socket
      - name: workload-certs
      - emptyDir:
          medium: Memory
        name: istio-envoy
      - emptyDir: {}
        name: istio-data
      - downwardAPI:
          items:
          - fieldRef:
              fieldPath: metadata.labels
            path: labels
          - fieldRef:
              fieldPath: metadata.annotations
            path: annotations
        name: istio-podinfo
      - name: istio-token
        projected:
          sources:
          - serviceAccountToken:
              audience: istio-ca
              expirationSeconds: 43200
              path: istio-token
      - configMap:
          name: istio-ca-root-cert
        name: istiod-ca-cert
status: {}
---

4. mutatingwebhookconfiguration ์กฐํšŒ

1
kubectl get mutatingwebhookconfiguration

โœ…ย ์ถœ๋ ฅ

1
2
3
4
NAME                         WEBHOOKS   AGE
istio-revision-tag-default   4          13m  # ํŠน์ • revision์˜ ์‚ฌ์ด๋“œ์นด ์ฃผ์ž… ์„ค์ • ๊ด€๋ฆฌ
istio-sidecar-injector       4          14m  # Istio๋Š” ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ Pod์— Envoy ์‚ฌ์ด๋“œ์นด ํ”„๋ก์‹œ๋ฅผ ์ž๋™์œผ๋กœ ์ฃผ์ž…
                                             # ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋‚˜ Pod์— istio-injection=enabled ๋ผ๋ฒจ์ด ์žˆ์–ด์•ผ ์ž‘๋™

5. ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ ˆ์ด๋ธ” ์ง€์ •

1
2
kubectl label namespace istioinaction istio-injection=enabled
kubectl get ns --show-labels

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
namespace/istioinaction labeled
NAME                 STATUS   AGE     LABELS
default              Active   42m     kubernetes.io/metadata.name=default
istio-system         Active   16m     kubernetes.io/metadata.name=istio-system
istioinaction        Active   6m55s   istio-injection=enabled,kubernetes.io/metadata.name=istioinaction
kube-node-lease      Active   42m     kubernetes.io/metadata.name=kube-node-lease
kube-public          Active   42m     kubernetes.io/metadata.name=kube-public
kube-system          Active   42m     kubernetes.io/metadata.name=kube-system
local-path-storage   Active   42m     kubernetes.io/metadata.name=local-path-storage
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ Pod์— ์‚ฌ์ด๋“œ์นด ์ž๋™ ์ฃผ์ž…์„ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋„ค์ž„์ŠคํŽ˜์ด์Šค istioinaction์— ๋ผ๋ฒจ ์ถ”๊ฐ€
  • istio-injection=enabled

6. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ

1
2
3
4
5
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

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
serviceaccount/catalog created
service/catalog created
deployment.apps/catalog created
apiVersion: v1
kind: ServiceAccount
metadata:
  name: webapp
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: webapp
  name: webapp
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: webapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webapp
  name: webapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      serviceAccountName: webapp
      containers:
      - env:
        - name: KUBERNETES_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: CATALOG_SERVICE_HOST
          value: catalog.istioinaction
        - name: CATALOG_SERVICE_PORT
          value: "80"
        - name: FORUM_SERVICE_HOST
          value: forum.istioinaction
        - name: FORUM_SERVICE_PORT
          value: "80"
        image: istioinaction/webapp:latest
        imagePullPolicy: IfNotPresent
        name: webapp
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        securityContext:
          privileged: false
          
serviceaccount/webapp created
service/webapp created
deployment.apps/webapp created

7. ๋ฐฐํฌ ๋ฆฌ์†Œ์Šค ํ™•์ธ

(1) pod ํ™•์ธ

1
kubectl get pod -n istioinaction

โœ…ย ์ถœ๋ ฅ

1
2
3
NAME                     READY   STATUS    RESTARTS   AGE
catalog-6cf4b97d-kw68k   2/2     Running   0          46s
webapp-7685bcb84-dlnwg   2/2     Running   0          46s

(2) catalog ๋””ํ”Œ๋กœ์ด๋จผํŠธ pod spec ํ™•์ธ

1
kubectl get deploy -n istioinaction catalog -o jsonpath="{.spec.template.spec}" | jq

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
{
  "containers": [
    {
      "env": [
        {
          "name": "KUBERNETES_NAMESPACE",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "metadata.namespace"
            }
          }
        }
      ],
      "image": "istioinaction/catalog:latest",
      "imagePullPolicy": "IfNotPresent",
      "name": "catalog",
      "ports": [
        {
          "containerPort": 3000,
          "name": "http",
          "protocol": "TCP"
        }
      ],
      "resources": {},
      "securityContext": {
        "privileged": false
      },
      "terminationMessagePath": "/dev/termination-log",
      "terminationMessagePolicy": "File"
    }
  ],
  "dnsPolicy": "ClusterFirst",
  "restartPolicy": "Always",
  "schedulerName": "default-scheduler",
  "securityContext": {},
  "serviceAccount": "catalog",
  "serviceAccountName": "catalog",
  "terminationGracePeriodSeconds": 30
}

(3) ์‹ค์ œ pod ์ŠคํŽ™ ํ™•์ธ

1
kubectl get pod -n istioinaction -l app=catalog -o jsonpath="{.items[0].spec}" | jq

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
{
  "containers": [
    {
      "env": [
        {
          "name": "KUBERNETES_NAMESPACE",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "metadata.namespace"
            }
          }
        }
      ],
      "image": "istioinaction/catalog:latest",
      "imagePullPolicy": "IfNotPresent",
      "name": "catalog",
      "ports": [
        {
          "containerPort": 3000,
          "name": "http",
          "protocol": "TCP"
        }
      ],
      "resources": {},
      "securityContext": {
        "privileged": false
      },
      "terminationMessagePath": "/dev/termination-log",
      "terminationMessagePolicy": "File",
      "volumeMounts": [
        {
          "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
          "name": "kube-api-access-rm86r",
          "readOnly": true
        }
      ]
    },
    {
      "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": {
              "apiVersion": "v1",
              "fieldPath": "metadata.name"
            }
          }
        },
        {
          "name": "POD_NAMESPACE",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "metadata.namespace"
            }
          }
        },
        {
          "name": "INSTANCE_IP",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "status.podIP"
            }
          }
        },
        {
          "name": "SERVICE_ACCOUNT",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "spec.serviceAccountName"
            }
          }
        },
        {
          "name": "HOST_IP",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "status.hostIP"
            }
          }
        },
        {
          "name": "PROXY_CONFIG",
          "value": "{}\n"
        },
        {
          "name": "ISTIO_META_POD_PORTS",
          "value": "[\n    {\"name\":\"http\",\"containerPort\":3000,\"protocol\":\"TCP\"}\n]"
        },
        {
          "name": "ISTIO_META_APP_CONTAINERS",
          "value": "catalog"
        },
        {
          "name": "ISTIO_META_CLUSTER_ID",
          "value": "Kubernetes"
        },
        {
          "name": "ISTIO_META_NODE_NAME",
          "valueFrom": {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "spec.nodeName"
            }
          }
        },
        {
          "name": "ISTIO_META_INTERCEPTION_MODE",
          "value": "REDIRECT"
        },
        {
          "name": "ISTIO_META_WORKLOAD_NAME",
          "value": "catalog"
        },
        {
          "name": "ISTIO_META_OWNER",
          "value": "kubernetes://apis/apps/v1/namespaces/istioinaction/deployments/catalog"
        },
        {
          "name": "ISTIO_META_MESH_ID",
          "value": "cluster.local"
        },
        {
          "name": "TRUST_DOMAIN",
          "value": "cluster.local"
        }
      ],
      "image": "docker.io/istio/proxyv2:1.17.8",
      "imagePullPolicy": "IfNotPresent",
      "name": "istio-proxy",
      "ports": [
        {
          "containerPort": 15090,
          "name": "http-envoy-prom",
          "protocol": "TCP"
        }
      ],
      "readinessProbe": {
        "failureThreshold": 30,
        "httpGet": {
          "path": "/healthz/ready",
          "port": 15021,
          "scheme": "HTTP"
        },
        "initialDelaySeconds": 1,
        "periodSeconds": 2,
        "successThreshold": 1,
        "timeoutSeconds": 3
      },
      "resources": {
        "limits": {
          "cpu": "2",
          "memory": "1Gi"
        },
        "requests": {
          "cpu": "100m",
          "memory": "128Mi"
        }
      },
      "securityContext": {
        "allowPrivilegeEscalation": false,
        "capabilities": {
          "drop": [
            "ALL"
          ]
        },
        "privileged": false,
        "readOnlyRootFilesystem": true,
        "runAsGroup": 1337,
        "runAsNonRoot": true,
        "runAsUser": 1337
      },
      "terminationMessagePath": "/dev/termination-log",
      "terminationMessagePolicy": "File",
      "volumeMounts": [
        {
          "mountPath": "/var/run/secrets/workload-spiffe-uds",
          "name": "workload-socket"
        },
        {
          "mountPath": "/var/run/secrets/credential-uds",
          "name": "credential-socket"
        },
        {
          "mountPath": "/var/run/secrets/workload-spiffe-credentials",
          "name": "workload-certs"
        },
        {
          "mountPath": "/var/run/secrets/istio",
          "name": "istiod-ca-cert"
        },
        {
          "mountPath": "/var/lib/istio/data",
          "name": "istio-data"
        },
        {
          "mountPath": "/etc/istio/proxy",
          "name": "istio-envoy"
        },
        {
          "mountPath": "/var/run/secrets/tokens",
          "name": "istio-token"
        },
        {
          "mountPath": "/etc/istio/pod",
          "name": "istio-podinfo"
        },
        {
          "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
          "name": "kube-api-access-rm86r",
          "readOnly": true
        }
      ]
    }
  ],
  "dnsPolicy": "ClusterFirst",
  "enableServiceLinks": true,
  "initContainers": [
    {
      "args": [
        "istio-iptables",
        "-p",
        "15001",
        "-z",
        "15006",
        "-u",
        "1337",
        "-m",
        "REDIRECT",
        "-i",
        "*",
        "-x",
        "",
        "-b",
        "*",
        "-d",
        "15090,15021,15020",
        "--log_output_level=default:info"
      ],
      "image": "docker.io/istio/proxyv2:1.17.8",
      "imagePullPolicy": "IfNotPresent",
      "name": "istio-init",
      "resources": {
        "limits": {
          "cpu": "2",
          "memory": "1Gi"
        },
        "requests": {
          "cpu": "100m",
          "memory": "128Mi"
        }
      },
      "securityContext": {
        "allowPrivilegeEscalation": false,
        "capabilities": {
          "add": [
            "NET_ADMIN",
            "NET_RAW"
          ],
          "drop": [
            "ALL"
          ]
        },
        "privileged": false,
        "readOnlyRootFilesystem": false,
        "runAsGroup": 0,
        "runAsNonRoot": false,
        "runAsUser": 0
      },
      "terminationMessagePath": "/dev/termination-log",
      "terminationMessagePolicy": "File",
      "volumeMounts": [
        {
          "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
          "name": "kube-api-access-rm86r",
          "readOnly": true
        }
      ]
    }
  ],
  "nodeName": "myk8s-control-plane",
  "preemptionPolicy": "PreemptLowerPriority",
  "priority": 0,
  "restartPolicy": "Always",
  "schedulerName": "default-scheduler",
  "securityContext": {},
  "serviceAccount": "catalog",
  "serviceAccountName": "catalog",
  "terminationGracePeriodSeconds": 30,
  "tolerations": [
    {
      "effect": "NoExecute",
      "key": "node.kubernetes.io/not-ready",
      "operator": "Exists",
      "tolerationSeconds": 300
    },
    {
      "effect": "NoExecute",
      "key": "node.kubernetes.io/unreachable",
      "operator": "Exists",
      "tolerationSeconds": 300
    }
  ],
  "volumes": [
    {
      "emptyDir": {},
      "name": "workload-socket"
    },
    {
      "emptyDir": {},
      "name": "credential-socket"
    },
    {
      "emptyDir": {},
      "name": "workload-certs"
    },
    {
      "emptyDir": {
        "medium": "Memory"
      },
      "name": "istio-envoy"
    },
    {
      "emptyDir": {},
      "name": "istio-data"
    },
    {
      "downwardAPI": {
        "defaultMode": 420,
        "items": [
          {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "metadata.labels"
            },
            "path": "labels"
          },
          {
            "fieldRef": {
              "apiVersion": "v1",
              "fieldPath": "metadata.annotations"
            },
            "path": "annotations"
          }
        ]
      },
      "name": "istio-podinfo"
    },
    {
      "name": "istio-token",
      "projected": {
        "defaultMode": 420,
        "sources": [
          {
            "serviceAccountToken": {
              "audience": "istio-ca",
              "expirationSeconds": 43200,
              "path": "istio-token"
            }
          }
        ]
      }
    },
    {
      "configMap": {
        "defaultMode": 420,
        "name": "istio-ca-root-cert"
      },
      "name": "istiod-ca-cert"
    },
    {
      "name": "kube-api-access-rm86r",
      "projected": {
        "defaultMode": 420,
        "sources": [
          {
            "serviceAccountToken": {
              "expirationSeconds": 3607,
              "path": "token"
            }
          },
          {
            "configMap": {
              "items": [
                {
                  "key": "ca.crt",
                  "path": "ca.crt"
                }
              ],
              "name": "kube-root-ca.crt"
            }
          },
          {
            "downwardAPI": {
              "items": [
                {
                  "fieldRef": {
                    "apiVersion": "v1",
                    "fieldPath": "metadata.namespace"
                  },
                  "path": "namespace"
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

8. ์ ‘์† ํ…Œ์ŠคํŠธ์šฉ netshoot ํŒŒ๋“œ ์ƒ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

# ๊ฒฐ๊ณผ
pod/netshoot created

9. ์„œ๋น„์Šค ๋ฐ ์—”๋“œํฌ์ธํŠธ ์ƒํƒœ ํ™•์ธ

1
k get svc,ep -n istioinaction

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/catalog   ClusterIP   10.200.1.197   <none>        80/TCP    7m45s
service/webapp    ClusterIP   10.200.1.44    <none>        80/TCP    7m45s

NAME                ENDPOINTS         AGE
endpoints/catalog   10.10.0.13:3000   7m45s
endpoints/webapp    10.10.0.14:8080   7m45s

10. ์„œ๋น„์Šค ์ ‘์† ํ…Œ์ŠคํŠธ

(1) catalog ์ ‘์† ํ…Œ์ŠคํŠธ

1
kubectl exec -it netshoot -- curl -s http://catalog.istioinaction/items/1 | jq

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

(2) webapp ์ ‘์† ํ…Œ์ŠคํŠธ

1
kubectl exec -it netshoot -- curl -s http://webapp.istioinaction/api/catalog/items/1 | jq

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

(3) ์ž„์‹œ ์ ‘์† ๋ฐฉ๋ฒ• - ํฌํŠธํฌ์›Œ๋”ฉ

1
kubectl port-forward -n istioinaction deploy/webapp 8080:8080


๐Ÿ“Š ๋ณต์›๋ ฅ, ๊ด€์ฐฐ๊ฐ€๋Šฅ์„ฑ, ํŠธ๋ž˜ํ”ฝ ์ œ์–ด

1. proxy ์ƒํƒœ ํ™•์ธ

1
docker exec -it myk8s-control-plane istioctl proxy-status

โœ…ย ์ถœ๋ ฅ

1
2
3
4
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS          ECDS         ISTIOD                      VERSION
catalog-6cf4b97d-kw68k.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-7df6ffc78d-25zjr     1.17.8
istio-ingressgateway-996bc6bb6-b24ff.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     NOT SENT     NOT SENT     istiod-7df6ffc78d-25zjr     1.17.8
webapp-7685bcb84-dlnwg.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-7df6ffc78d-25zjr     1.17.8

2. Gateway ๋ฐ VirtualService ์ƒ์„ฑ

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
32
33
34
35
36
37
38
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

# ๊ฒฐ๊ณผ
gateway.networking.istio.io/outfitters-gateway created
virtualservice.networking.istio.io/webapp-virtualservice created

3. ๋ฆฌ์†Œ์Šค ์กฐํšŒ

(1) Gateway ๋ฐ VirtualService ์กฐํšŒ

1
kubectl get gw,vs -n istioinaction

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
NAME                                             AGE
gateway.networking.istio.io/outfitters-gateway   36s

NAME                                                       GATEWAYS                 HOSTS   AGE
virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]   36s

(2) VirtualService API ๋ฆฌ์†Œ์Šค ํ™•์ธ

1
k api-resources |grep vs

โœ…ย ์ถœ๋ ฅ

1
virtualservices                   vs           networking.istio.io/v1beta1            true         VirtualService

(3) Gateway API ๋ฆฌ์†Œ์Šค ํ™•์ธ

1
k api-resources |grep gw

โœ…ย ์ถœ๋ ฅ

1
2
3
mutatingwebhookconfigurations                  admissionregistration.k8s.io/v1        false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io/v1        false        ValidatingWebhookConfiguration
gateways                          gw           networking.istio.io/v1beta1            true         Gateway

4. Proxy ์ƒํƒœ ํ™•์ธ

(1) istio ์‚ฌ์ด๋“œ์นด ํ”„๋ก์‹œ ๋™๊ธฐํ™” ์ƒํƒœ ํ™•์ธ

1
docker exec -it myk8s-control-plane istioctl proxy-status

โœ…ย ์ถœ๋ ฅ

1
2
3
4
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
catalog-6cf4b97d-kw68k.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-25zjr     1.17.8
istio-ingressgateway-996bc6bb6-b24ff.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-25zjr     1.17.8
webapp-7685bcb84-dlnwg.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-25zjr     1.17.8

(2) ํ”„๋ก์‹œ ์ด๋ฆ„์„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ์ง€์ •

1
2
ISTIOIGW=istio-ingressgateway-996bc6bb6-b24ff.istio-system
WEBAPP=webapp-7685bcb84-dlnwg.istioinaction

2. ๋ผ์šฐํŠธ ๋ฐ ๋ฆฌ์Šค๋„ˆ ๊ตฌ์„ฑ ํ™•์ธ

(1) ๋ผ์šฐํŠธ ์ •๋ณด ํ™•์ธ

1
docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system

โœ…ย ์ถœ๋ ฅ

1
2
3
4
NAME          DOMAINS     MATCH                  VIRTUAL SERVICE
http.8080     *           /*                     webapp-virtualservice.istioinaction
              *           /stats/prometheus*     
              *           /healthz/ready*

(2) ๋ฆฌ์Šค๋„ˆ ์„ค์ • ์ •๋ณด ํ™•์ธ

1
docker exec -it myk8s-control-plane istioctl proxy-config listener $ISTIOIGW

โœ…ย ์ถœ๋ ฅ

1
2
3
4
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*

3. ๋ฐฑ์—”๋“œ ์—”๋“œํฌ์ธํŠธ ๋ฐ ์ธ์ฆ์„œ ์ •๋ณด ํ™•์ธ

(1) ์—”๋“œํฌ์ธํŠธ ์ƒํƒœ ํ™•์ธ

1
docker exec -it myk8s-control-plane istioctl proxy-config endpoint $ISTIOIGW

โœ…ย ์ถœ๋ ฅ

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
32
ENDPOINT                                                STATUS      OUTLIER CHECK     CLUSTER
10.10.0.10:9411                                         HEALTHY     OK                outbound|9411||jaeger-collector.istio-system.svc.cluster.local
10.10.0.10:9411                                         HEALTHY     OK                outbound|9411||zipkin.istio-system.svc.cluster.local
10.10.0.10:14250                                        HEALTHY     OK                outbound|14250||jaeger-collector.istio-system.svc.cluster.local
10.10.0.10:14268                                        HEALTHY     OK                outbound|14268||jaeger-collector.istio-system.svc.cluster.local
10.10.0.10:16685                                        HEALTHY     OK                outbound|16685||tracing.istio-system.svc.cluster.local
10.10.0.10:16686                                        HEALTHY     OK                outbound|80||tracing.istio-system.svc.cluster.local
10.10.0.11:9090                                         HEALTHY     OK                outbound|9090||kiali.istio-system.svc.cluster.local
10.10.0.11:20001                                        HEALTHY     OK                outbound|20001||kiali.istio-system.svc.cluster.local
10.10.0.12:9090                                         HEALTHY     OK                outbound|9090||prometheus.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:3000                                          HEALTHY     OK                outbound|3000||grafana.istio-system.svc.cluster.local
10.200.1.155:9411                                       HEALTHY     OK                zipkin
127.0.0.1:15000                                         HEALTHY     OK                prometheus_stats
127.0.0.1:15020                                         HEALTHY     OK                agent
172.18.0.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

(2) Envoy ์ธ์ฆ์„œ ์ •๋ณด ํ™•์ธ

1
docker exec -it myk8s-control-plane istioctl proxy-config secret $ISTIOIGW

โœ…ย ์ถœ๋ ฅ

1
2
3
RESOURCE NAME     TYPE           STATUS     VALID CERT     SERIAL NUMBER                               NOT AFTER                NOT BEFORE
default           Cert Chain     ACTIVE     true           196175599541375521141632695734158995035     2025-04-13T14:35:14Z     2025-04-12T14:33:14Z
ROOTCA            CA             ACTIVE     true           83445744217971306758784358156191133935      2035-04-10T14:35:02Z     2025-04-12T14:35:02Z

4. NodePort ๋ฐ ์™ธ๋ถ€ ํŠธ๋ž˜ํ”ฝ ์ •์ฑ… ๋ณ€๊ฒฝ

(1) istio-ingressgateway ์„œ๋น„์Šค NodePort ๋ณ€๊ฒฝ

1
2
3
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

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                      AGE
service/istio-ingressgateway   LoadBalancer   10.200.1.191   <pending>     15021:30191/TCP,80:31021/TCP,443:31846/TCP   61m

NAME                             ENDPOINTS                                       AGE
endpoints/istio-ingressgateway   10.10.0.8:15021,10.10.0.8:8080,10.10.0.8:8443   61m
service/istio-ingressgateway patched
NAME                   TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                                      AGE
istio-ingressgateway   NodePort   10.200.1.191   <none>        15021:30191/TCP,80:30000/TCP,443:31846/TCP   61m
  • LoadBalancer ํƒ€์ž… ์„œ๋น„์Šค๋ฅผ NodePort ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝ ๋ฐ ํฌํŠธ 30000 ์ง€์ •

(2) ์™ธ๋ถ€ ํŠธ๋ž˜ํ”ฝ ์ •์ฑ… ๋ณ€๊ฒฝ

1
2
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl describe svc -n istio-system istio-ingressgateway

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
service/istio-ingressgateway patched

Name:                     istio-ingressgateway
Namespace:                istio-system
Labels:                   app=istio-ingressgateway
                          install.operator.istio.io/owning-resource=unknown
                          install.operator.istio.io/owning-resource-namespace=istio-system
                          istio=ingressgateway
                          istio.io/rev=default
                          operator.istio.io/component=IngressGateways
                          operator.istio.io/managed=Reconcile
                          operator.istio.io/version=1.17.8
                          release=istio
Annotations:              <none>
Selector:                 app=istio-ingressgateway,istio=ingressgateway
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.200.1.191
IPs:                      10.200.1.191
Port:                     status-port  15021/TCP
TargetPort:               15021/TCP
NodePort:                 status-port  30191/TCP
Endpoints:                10.10.0.8:15021
Port:                     http2  80/TCP
TargetPort:               8080/TCP
NodePort:                 http2  30000/TCP
Endpoints:                10.10.0.8:8080
Port:                     https  443/TCP
TargetPort:               8443/TCP
NodePort:                 https  31846/TCP
Endpoints:                10.10.0.8:8443
Session Affinity:         None
External Traffic Policy:  Local
Internal Traffic Policy:  Cluster
Events:
  Type    Reason  Age   From                Message
  ----    ------  ----  ----                -------
  Normal  Type    77s   service-controller  LoadBalancer -> NodePort
  • ์™ธ๋ถ€ ์š”์ฒญ ์‹œ ํด๋ผ์ด์–ธํŠธ IP ์ˆ˜์ง‘์„ ์œ„ํ•ด externalTrafficPolicy๋ฅผ โ€œLocalโ€๋กœ ์„ค์ •

5. ์ตœ์ข… ์„œ๋น„์Šค ์ ‘๊ทผ ํ…Œ์ŠคํŠธ

(1) ์ „์ฒด catalog ์กฐํšŒ

1
curl -s http://127.0.0.1:30000/api/catalog | jq

โœ…ย ์ถœ๋ ฅ

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
[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]

(2) ํŠน์ • ์•„์ดํ…œ ์กฐํšŒ

1
curl -s http://127.0.0.1:30000/api/catalog/items/1 | jq

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

(3) HTTP ์‘๋‹ต ์ฝ”๋“œ ํ™•์ธ

1
curl -s http://127.0.0.1:30000/api/catalog -I | head -n 1

โœ…ย ์ถœ๋ ฅ

1
HTTP/1.1 200 OK

6. ๋ฐ˜๋ณต ํ˜ธ์ถœ ํ…Œ์ŠคํŠธ

1
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

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HTTP/1.1 200 OK
2025-04-13 00:42:39

HTTP/1.1 200 OK
2025-04-13 00:42:39

HTTP/1.1 200 OK
2025-04-13 00:42:40

HTTP/1.1 200 OK
2025-04-13 00:42:40

HTTP/1.1 200 OK
2025-04-13 00:42:41

HTTP/1.1 200 OK
2025-04-13 00:42:41

...

๐Ÿ” istio observability

1. observability๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ๋ณ€๊ฒฝ

1
2
3
4
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}]}}'

โœ…ย ์ถœ๋ ฅ

1
2
3
4
service/prometheus patched
service/grafana patched
service/kiali patched
service/tracing patched

2. ๋Œ€์‹œ๋ณด๋“œ ์ ‘์†

(1) Prometheus ์ ‘์†: http://127.0.0.1:30001

envoy, istio ๋ฉ”ํŠธ๋ฆญ ํ™•์ธ

(2) Grafana ์ ‘์†: http://127.0.0.1:30002

(3) Kiali ์ ‘์† 1 : http://127.0.0.1:30003 - NodePort

(4) Kiali ์ ‘์† 2 : http://127.0.0.1:30003 - Port forward

1
kubectl port-forward deployment/kiali -n istio-system 20001:20001 &

โœ…ย ์ถœ๋ ฅ

1
2
3
4
[1] 340443

โœฆ โฏ Forwarding from 127.0.0.1:20001 -> 20001
Forwarding from [::1]:20001 -> 20001

(5) ์˜ˆ๊ฑฐ ํŠธ๋ ˆ์ด์‹ฑ ๋Œ€์‹œ๋ณด๋“œ ์ ‘์†: http://127.0.0.1:30004

3. ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ ์ •๋ณด ํ™•์ธ

  • ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœํŒ€์€ ๋ณ„๋„์˜ ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Œ
  • ๋Œ€์ƒ ํƒ€๊ฒŸ(webapp, catalog ๋“ฑ)์˜ envoy ๋ฐ istio ๊ด€๋ จ ๋งคํŠธ๋ฆญ์€ ๋ณ„๋„ ์„ค์ • ์—†์ด ์ˆ˜์ง‘๋˜๊ณ  ์žˆ์Œ

  • Namespace: istioincation / Graph: Traffic, Versioned app graph
  • Display: Traffic Distribution, Traffic Animation, Service nods, Security ํ™œ์„ฑํ™” (Last 1m, Evety 10s)

4. ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ

(1) 0.1์ดˆ ๊ฐ„๊ฒฉ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ

1
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.1; echo; done

5. Kiali ํ™•์ธ

(1) Graph - ๊ฐ„๊ฒฉ์ด ์ด˜์ด˜ํ•ด์ง

(2) Workloads โ†’ Overview

(3) Workloads โ†’ Logs

(4) Workloads โ†’ Traces

(5) Workloads โ†’ Envoy

6. ์˜ˆ๊ฑฐ ํ™•์ธ


๐Ÿ”„ Catalog: 500 ์—๋Ÿฌ ์žฌํ˜„ ๋ฐ Retry ์ ์šฉ ๋ณต์›๋ ฅ ๊ฐ•ํ™”

1. ํ™˜๊ฒฝ ์„ค์ • ๋ณ€๊ฒฝ ๋ฐ ์ž‘์—… ์ค€๋น„

(1) istio ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด myk8s-control-plane ์ปจํ…Œ์ด๋„ˆ ์ ‘์†

1
2
3
docker exec -it myk8s-control-plane bash

root@myk8s-control-plane:/# 

(2) istioinaction๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ณ€๊ฒฝ

1
2
3
root@myk8s-control-plane:/# cat /etc/kubernetes/admin.conf
kubectl config set-context $(kubectl config current-context) --namespace=istioinaction
cat /etc/kubernetes/admin.conf

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJMU1EUXhNakUwTURnMU1sb1hEVE0xTURReE1ERTBNRGcxTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTHJwCnpqOGVSR3kvUDNqM2lWdkhMNFJjWWVaQ2hIQkR0TThXTUIvN2toeHdSdTFteFBQWmRSZ0pZOUluT3VzT20yaUQKQ25XOGsySkhwQng0SDBNZDhMT3NFU0R4c040MlA1WVNVOGZZRGlkMlBBYzBLcHlpR0hYSW5JbjBqdUk1WHpxUApCSVZEelBsTmVhdEkzUjRxa3lya29XQTBBRllzZzM5MDVIbWlTdXU2MGROSTduQjhneEYrT0ZpdGd5T0doZzlnCjRmVSttV0U3UUxNZXhieEFWTlQxMUM1Z29OV2RoY2Q1SUE4M3hPUFlERVJzNy9lUHRHWjkxRWk3RXNBdjhhWW8KQTgxZU9ILzlYczVaQUFZSzNnNzVJSE0zUVpXNGN4Tms3cDhUc0hNcy9aY1Z2WWZIdlZ6TEQwRXdlYktsQURTQgpqay9xWXlzblpHMnVsZ3BxamFVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZEcDFaVUtsendaNmRtMGJaRk85cm4xK3hwWVRNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQmxsNXBUUnFhSzlzVENFVXc0RApnUCtENXA3Vm50dUdhWCs4djJlREg5dUovaUZOcTdKVnI1cjZteTVzYmE3WGV5Um5talpHN3hlaGRrYVcweW5mClZVdmJuYWlkaXJXV0xOeUNsaHY5UDVBNHR1UzFaSk1zM0sya3doaDdnQUtoZnZFNU9nRTQxYkFIbWVweEhNS3AKMUtFb3Zpa0lSUHdRNUc2elB1L1MyZ1ZjTWVRVnJoUmZnVFRyOWt3YXVLcURYSmRwSjJ1TENjMEN2U01SVDFGTAoyZ2NKUlA2ekIvZFM2dDdyYitzelFoRHkyYmJVcWlXanBzeTh6UEJMZkV1RjI1MjlNVGprQmZBNjZGR05xUFMzCjdoOUwwYU9BQ0Y3d1VyOFdYWHhOUWttTk94T0J2UUY1aEV0VXIwZ0ZoRkZxQ25vcEVGeGlFSWNZUEJVUmNuWlEKS3dnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://myk8s-control-plane:6443
  name: myk8s
contexts:
- context:
    cluster: myk8s
    user: kubernetes-admin
  name: kubernetes-admin@myk8s
current-context: kubernetes-admin@myk8s
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJZWMzTk5OWW5vcTR3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBME1USXhOREE0TlRKYUZ3MHlOakEwTVRJeE5EQTROVFJhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTJLY294Z01kc1JBZzRibUsKdVRDcTR3L0VaQmlEMCtJRW8xdlM0ZG9mTUlRSXg4d2Q2SHAyZTViZGtYK0tqb2o5SjE3SHIySmxSc2xGMWFxZgpWdjBjcUprWXVmaFNXcTFOM2RGc012VFBOazN2L3RGU3RDYWl4THJTa2taemw3aENvbERsc0hsWnE0Slk1amZMCmh3cDRXVC9wUlh5VXhPeXprcGZkQnRBSkRwUWV1ZlBtVFJVTmpiQ0tSbEpFSnpFZXhzYnM1UU94eHowR1JqU3UKT0lvd0JWcEw1RzFIVGFpa3hkUll6b29QNmlTeDNHRFQwaDI2QU1tcFZJc20vK2xwYUhSWFZybER4RWlLandaOQpjMEowYyszU252QnQxd0E1RCtVc053akdqTFZHMHA0MkVCaWY0cWl6T0YySndCd3lzR3daWFFKMFRUdm9mMzlZCnBFMzQ1UUlEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JRNmRXVkNwYzhHZW5adEcyUlR2YTU5ZnNhVwpFekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBR3lYbFdmNVNaVEZhelBDVkI3WDhEWm1mbFZkcUc5YitxQ2NKClZIb1BGWUF0bGRUODhyc0sxcjNnUjUybTRWT1YvSjlZM3lObTlOOC90K3QrY2Y4VDFMU0cvQlMzeENzODNxN3gKdUlkUWx2YUtDYUhqWmZUL1NFeVRmTzk5NjE1OFdaZDNrMlB6TjJ4aW0zNWlReXV4K0xqRzZnSm5ucGpaNytEMApjeDNSWmI1Ly9Ta1JKem9IeGZoeE5RaDUwR0MwQm40cG95aTFkTVFpMHFCR0pnK0ZXRmxZcG9YV2gzNWE0Vk5PCkxTZGY4bzBoUEhjNmhYcEpRK0RuWENyRE5nQ0MrNTZrUkhlZTRHWFVHc1BXU01veEU5RVl0WjFhQ29SdTVWYUsKeklrWnlGWEV5eE1XeERGNlRsR0d4TkpoSHJkUzVud2tpZTlESk9qWTJSWVFUd0lsNEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMktjb3hnTWRzUkFnNGJtS3VUQ3E0dy9FWkJpRDArSUVvMXZTNGRvZk1JUUl4OHdkCjZIcDJlNWJka1grS2pvajlKMTdIcjJKbFJzbEYxYXFmVnYwY3FKa1l1ZmhTV3ExTjNkRnNNdlRQTmszdi90RlMKdENhaXhMclNra1p6bDdoQ29sRGxzSGxacTRKWTVqZkxod3A0V1QvcFJYeVV4T3l6a3BmZEJ0QUpEcFFldWZQbQpUUlVOamJDS1JsSkVKekVleHNiczVRT3h4ejBHUmpTdU9Jb3dCVnBMNUcxSFRhaWt4ZFJZem9vUDZpU3gzR0RUCjBoMjZBTW1wVklzbS8rbHBhSFJYVnJsRHhFaUtqd1o5YzBKMGMrM1NudkJ0MXdBNUQrVXNOd2pHakxWRzBwNDIKRUJpZjRxaXpPRjJKd0J3eXNHd1pYUUowVFR2b2YzOVlwRTM0NVFJREFRQUJBb0lCQUZJRGpXclArU2h6QzQrSApkbDArY0NJK2NNRFhpdWZsc28zSWo5OFJmQ2NZaEY1bUJaaGc2NE5EakNLdEhsMXd2Q3h3TTdWUDBUam5ybmtBCit3cXFESFJDYUZyV0J3N3VkZ0NYYTVjcWwxcGVUSkN3MnRiNW5UcE40cktlMnRrL1ZuSXRuNVdiaW5kamc1VzYKMzJBQ2RhYUxqQm5TM0ZwanBHTEUvRlc4NFFEVUhOeVdNdkh2MEhzL0MzSFhubFc2UWhlam5DdlBabnVEUGlIUgpsSFNVeFhKa005Vm9XaVVMYUNZTk1MQ2Joc2RVL20vdnVaVHdhcVhYcjlMUk0yWURPdmJibGRhaEFZOVpCNGhHCkttbHBKUDE3S2U4S1VLejhBT0RXcXNFeVcwL2ZmL1ZxczdCTHM3Y21zUnBNdWptV0xXZks3VzNOZDAzeks4bnMKc25pVkU2MENnWUVBK29OSkJXMUFwVURWNmxENktNRHJJNHVsQUFnQ2hHVmc5a1JGOFRIVUFvb212WUR3Z3JjQQpwQitNa3VDNXh4elVlSm40YkszZjYwTXBUSnp5SkhpUjAydGQ5SktEeXo3RzMwbmJ6djdRKy9nOHgzM2UrU2J4CkhMYnhqd042TjNUa2hHbmVZck4zRWVJYWlJWUk4TVZQc1Nna1RlS0hNZXFuNFhvTXdzVEFkRDhDZ1lFQTNXWUMKZXRjYzMwNkZMWURGaVZVekxBZWlZRVp2d3Q5RWE2dE1jTjhkck9BOG1uOGowdjFRQ3ZRTXlIV0xtOG1jZTNTWQowdWVXVzVjVkJTTFNDalFsS3hXbW9zMk1qS3VvMUlyYVdrSHRRdmFXV3N4K0VJSm14KzVDY2FCWTRxeFl3MjU5CmRzL3VBY0FFWXhiUktVRWd2UjBWdndiQnZ3V2hycFBhVTdJWHVkc0NnWUF1YkgvdXVvVmRXbnVKOWNHMkpiSXQKbnlaUHNDeFBQcjVPUk82MU9PZXlKTW56R2w3M3lsUWJGaUdsNG5GckhjT2VLZUpvdVh3aWpBcXVRUE42b01GZApiYXMydEtRcDJSTmZzNzlCUitXUW5Ec2ZPUXRHSHRwVjJPMUE5SU1FbmV2dlFmTk5WVGErb0trTUhkS3dVOUJsCjR5dC9KM2lvWG5VSUN1Y3NmT3V4WHdLQmdCSVRyU29vZkRRRGJqNUw0RlVaUHNkZWpEUitLOHZtZk9pcG9PRXEKWm5yaUNEQzVKc3lvWUN1MHg0SnFqbzZXeEk4VDh4SnRWRXFBS0hnMTRwNXdxWVErRFZBSHBtMHA2dXdIdGxKZQpSYWdOQ0RPN3RLTldjbHZxcVVRcnluWWZpbFBTcHEzWHhtQWdOSHQrdG04KzRSUnYxb0cxWklaYlNGcy91VGpTCk5ydTNBb0dCQUp3WFp3VEd2UzFESmRFWDQxb04yVGhkR0d1RHFSeE1UeGNwZHRnQkh5cmFuUk5JK0hYNEdnRzMKb3I3bGFOVmh5WDJ3b25KRWpWemUyMlZlU2lRUktFRkxOdUkxWktaTFJrN21HeU4wS2d0VStKWTFZK3IwM25FNwpVWHBkSFRsVHhzTHRJcjVMZ3orQitVMHdMY1o2RS9BdkNPWlRkemt5Vnd0RURCanp4c2VECi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
Context "kubernetes-admin@myk8s" modified.
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJMU1EUXhNakUwTURnMU1sb1hEVE0xTURReE1ERTBNRGcxTWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTHJwCnpqOGVSR3kvUDNqM2lWdkhMNFJjWWVaQ2hIQkR0TThXTUIvN2toeHdSdTFteFBQWmRSZ0pZOUluT3VzT20yaUQKQ25XOGsySkhwQng0SDBNZDhMT3NFU0R4c040MlA1WVNVOGZZRGlkMlBBYzBLcHlpR0hYSW5JbjBqdUk1WHpxUApCSVZEelBsTmVhdEkzUjRxa3lya29XQTBBRllzZzM5MDVIbWlTdXU2MGROSTduQjhneEYrT0ZpdGd5T0doZzlnCjRmVSttV0U3UUxNZXhieEFWTlQxMUM1Z29OV2RoY2Q1SUE4M3hPUFlERVJzNy9lUHRHWjkxRWk3RXNBdjhhWW8KQTgxZU9ILzlYczVaQUFZSzNnNzVJSE0zUVpXNGN4Tms3cDhUc0hNcy9aY1Z2WWZIdlZ6TEQwRXdlYktsQURTQgpqay9xWXlzblpHMnVsZ3BxamFVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZEcDFaVUtsendaNmRtMGJaRk85cm4xK3hwWVRNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQmxsNXBUUnFhSzlzVENFVXc0RApnUCtENXA3Vm50dUdhWCs4djJlREg5dUovaUZOcTdKVnI1cjZteTVzYmE3WGV5Um5talpHN3hlaGRrYVcweW5mClZVdmJuYWlkaXJXV0xOeUNsaHY5UDVBNHR1UzFaSk1zM0sya3doaDdnQUtoZnZFNU9nRTQxYkFIbWVweEhNS3AKMUtFb3Zpa0lSUHdRNUc2elB1L1MyZ1ZjTWVRVnJoUmZnVFRyOWt3YXVLcURYSmRwSjJ1TENjMEN2U01SVDFGTAoyZ2NKUlA2ekIvZFM2dDdyYitzelFoRHkyYmJVcWlXanBzeTh6UEJMZkV1RjI1MjlNVGprQmZBNjZGR05xUFMzCjdoOUwwYU9BQ0Y3d1VyOFdYWHhOUWttTk94T0J2UUY1aEV0VXIwZ0ZoRkZxQ25vcEVGeGlFSWNZUEJVUmNuWlEKS3dnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://myk8s-control-plane:6443
  name: myk8s
contexts:
- context:
    cluster: myk8s
    namespace: istioinaction
    user: kubernetes-admin
  name: kubernetes-admin@myk8s
current-context: kubernetes-admin@myk8s
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJZWMzTk5OWW5vcTR3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBME1USXhOREE0TlRKYUZ3MHlOakEwTVRJeE5EQTROVFJhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTJLY294Z01kc1JBZzRibUsKdVRDcTR3L0VaQmlEMCtJRW8xdlM0ZG9mTUlRSXg4d2Q2SHAyZTViZGtYK0tqb2o5SjE3SHIySmxSc2xGMWFxZgpWdjBjcUprWXVmaFNXcTFOM2RGc012VFBOazN2L3RGU3RDYWl4THJTa2taemw3aENvbERsc0hsWnE0Slk1amZMCmh3cDRXVC9wUlh5VXhPeXprcGZkQnRBSkRwUWV1ZlBtVFJVTmpiQ0tSbEpFSnpFZXhzYnM1UU94eHowR1JqU3UKT0lvd0JWcEw1RzFIVGFpa3hkUll6b29QNmlTeDNHRFQwaDI2QU1tcFZJc20vK2xwYUhSWFZybER4RWlLandaOQpjMEowYyszU252QnQxd0E1RCtVc053akdqTFZHMHA0MkVCaWY0cWl6T0YySndCd3lzR3daWFFKMFRUdm9mMzlZCnBFMzQ1UUlEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JRNmRXVkNwYzhHZW5adEcyUlR2YTU5ZnNhVwpFekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBR3lYbFdmNVNaVEZhelBDVkI3WDhEWm1mbFZkcUc5YitxQ2NKClZIb1BGWUF0bGRUODhyc0sxcjNnUjUybTRWT1YvSjlZM3lObTlOOC90K3QrY2Y4VDFMU0cvQlMzeENzODNxN3gKdUlkUWx2YUtDYUhqWmZUL1NFeVRmTzk5NjE1OFdaZDNrMlB6TjJ4aW0zNWlReXV4K0xqRzZnSm5ucGpaNytEMApjeDNSWmI1Ly9Ta1JKem9IeGZoeE5RaDUwR0MwQm40cG95aTFkTVFpMHFCR0pnK0ZXRmxZcG9YV2gzNWE0Vk5PCkxTZGY4bzBoUEhjNmhYcEpRK0RuWENyRE5nQ0MrNTZrUkhlZTRHWFVHc1BXU01veEU5RVl0WjFhQ29SdTVWYUsKeklrWnlGWEV5eE1XeERGNlRsR0d4TkpoSHJkUzVud2tpZTlESk9qWTJSWVFUd0lsNEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMktjb3hnTWRzUkFnNGJtS3VUQ3E0dy9FWkJpRDArSUVvMXZTNGRvZk1JUUl4OHdkCjZIcDJlNWJka1grS2pvajlKMTdIcjJKbFJzbEYxYXFmVnYwY3FKa1l1ZmhTV3ExTjNkRnNNdlRQTmszdi90RlMKdENhaXhMclNra1p6bDdoQ29sRGxzSGxacTRKWTVqZkxod3A0V1QvcFJYeVV4T3l6a3BmZEJ0QUpEcFFldWZQbQpUUlVOamJDS1JsSkVKekVleHNiczVRT3h4ejBHUmpTdU9Jb3dCVnBMNUcxSFRhaWt4ZFJZem9vUDZpU3gzR0RUCjBoMjZBTW1wVklzbS8rbHBhSFJYVnJsRHhFaUtqd1o5YzBKMGMrM1NudkJ0MXdBNUQrVXNOd2pHakxWRzBwNDIKRUJpZjRxaXpPRjJKd0J3eXNHd1pYUUowVFR2b2YzOVlwRTM0NVFJREFRQUJBb0lCQUZJRGpXclArU2h6QzQrSApkbDArY0NJK2NNRFhpdWZsc28zSWo5OFJmQ2NZaEY1bUJaaGc2NE5EakNLdEhsMXd2Q3h3TTdWUDBUam5ybmtBCit3cXFESFJDYUZyV0J3N3VkZ0NYYTVjcWwxcGVUSkN3MnRiNW5UcE40cktlMnRrL1ZuSXRuNVdiaW5kamc1VzYKMzJBQ2RhYUxqQm5TM0ZwanBHTEUvRlc4NFFEVUhOeVdNdkh2MEhzL0MzSFhubFc2UWhlam5DdlBabnVEUGlIUgpsSFNVeFhKa005Vm9XaVVMYUNZTk1MQ2Joc2RVL20vdnVaVHdhcVhYcjlMUk0yWURPdmJibGRhaEFZOVpCNGhHCkttbHBKUDE3S2U4S1VLejhBT0RXcXNFeVcwL2ZmL1ZxczdCTHM3Y21zUnBNdWptV0xXZks3VzNOZDAzeks4bnMKc25pVkU2MENnWUVBK29OSkJXMUFwVURWNmxENktNRHJJNHVsQUFnQ2hHVmc5a1JGOFRIVUFvb212WUR3Z3JjQQpwQitNa3VDNXh4elVlSm40YkszZjYwTXBUSnp5SkhpUjAydGQ5SktEeXo3RzMwbmJ6djdRKy9nOHgzM2UrU2J4CkhMYnhqd042TjNUa2hHbmVZck4zRWVJYWlJWUk4TVZQc1Nna1RlS0hNZXFuNFhvTXdzVEFkRDhDZ1lFQTNXWUMKZXRjYzMwNkZMWURGaVZVekxBZWlZRVp2d3Q5RWE2dE1jTjhkck9BOG1uOGowdjFRQ3ZRTXlIV0xtOG1jZTNTWQowdWVXVzVjVkJTTFNDalFsS3hXbW9zMk1qS3VvMUlyYVdrSHRRdmFXV3N4K0VJSm14KzVDY2FCWTRxeFl3MjU5CmRzL3VBY0FFWXhiUktVRWd2UjBWdndiQnZ3V2hycFBhVTdJWHVkc0NnWUF1YkgvdXVvVmRXbnVKOWNHMkpiSXQKbnlaUHNDeFBQcjVPUk82MU9PZXlKTW56R2w3M3lsUWJGaUdsNG5GckhjT2VLZUpvdVh3aWpBcXVRUE42b01GZApiYXMydEtRcDJSTmZzNzlCUitXUW5Ec2ZPUXRHSHRwVjJPMUE5SU1FbmV2dlFmTk5WVGErb0trTUhkS3dVOUJsCjR5dC9KM2lvWG5VSUN1Y3NmT3V4WHdLQmdCSVRyU29vZkRRRGJqNUw0RlVaUHNkZWpEUitLOHZtZk9pcG9PRXEKWm5yaUNEQzVKc3lvWUN1MHg0SnFqbzZXeEk4VDh4SnRWRXFBS0hnMTRwNXdxWVErRFZBSHBtMHA2dXdIdGxKZQpSYWdOQ0RPN3RLTldjbHZxcVVRcnluWWZpbFBTcHEzWHhtQWdOSHQrdG04KzRSUnYxb0cxWklaYlNGcy91VGpTCk5ydTNBb0dCQUp3WFp3VEd2UzFESmRFWDQxb04yVGhkR0d1RHFSeE1UeGNwZHRnQkh5cmFuUk5JK0hYNEdnRzMKb3I3bGFOVmh5WDJ3b25KRWpWemUyMlZlU2lRUktFRkxOdUkxWktaTFJrN21HeU4wS2d0VStKWTFZK3IwM25FNwpVWHBkSFRsVHhzTHRJcjVMZ3orQitVMHdMY1o2RS9BdkNPWlRkemt5Vnd0RURCanp4c2VECi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==

2. 500 ์—๋Ÿฌ ์žฌํ˜„์„ ์œ„ํ•œ Chaos ํ…Œ์ŠคํŠธ ์‹คํ–‰

(1) 500 ์—๋Ÿฌ๋ฅผ 100% ์žฌํ˜„

1
2
3
4
5
6
7
root@myk8s-control-plane:/# cd /istiobook/bin/ 
root@myk8s-control-plane:/istiobook/bin# chmod +x chaos.sh
root@myk8s-control-plane:/istiobook/bin# ./chaos.sh 500 100

# ๊ฒฐ๊ณผ
catalog-6cf4b97d-kw68k
blowups=[object Object]

500 ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์‘๋‹ต์ด HTTP 500 Internal Server Error๋กœ ๋ฐ˜๋ณต ์ถœ๋ ฅ๋จ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
HTTP/1.1 500 Internal Server Error
2025-04-13 01:26:29

HTTP/1.1 500 Internal Server Error
2025-04-13 01:26:29

HTTP/1.1 500 Internal Server Error
2025-04-13 01:26:29

HTTP/1.1 500 Internal Server Error
2025-04-13 01:26:29

HTTP/1.1 500 Internal Server Error
2025-04-13 01:26:30

...

(2) 500 ์—๋Ÿฌ ์žฌํ˜„ ๋น„์œจ์„ 50%๋กœ ์กฐ์ •

1
2
3
root@myk8s-control-plane:/istiobook/bin# ./chaos.sh 500 50 
catalog-6cf4b97d-kw68k
blowups=[object Object]

HTTP 500๊ณผ 200 OK๊ฐ€ ํ˜ผํ•ฉ๋˜์–ด ๋‚˜ํƒ€๋‚จ

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
32
33
HTTP/1.1 500 Internal Server Error
2025-04-13 01:29:22

HTTP/1.1 200 OK
2025-04-13 01:29:23

HTTP/1.1 500 Internal Server Error
2025-04-13 01:29:23

HTTP/1.1 500 Internal Server Error
2025-04-13 01:29:23

HTTP/1.1 500 Internal Server Error
2025-04-13 01:29:23

HTTP/1.1 200 OK
2025-04-13 01:29:23

HTTP/1.1 200 OK
2025-04-13 01:29:23

HTTP/1.1 500 Internal Server Error
2025-04-13 01:29:23

HTTP/1.1 500 Internal Server Error
2025-04-13 01:29:23

HTTP/1.1 200 OK
2025-04-13 01:29:23

HTTP/1.1 200 OK
2025-04-13 01:29:24
...

Tags: error=true๋กœ ์„ค์ •

3. VirtualService Retry ์„ค์ • ์ ์šฉ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด, proxy(envoy)๋ฅผ ํ†ตํ•ด endpoint(catalog)์— 5xx ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์ž๋™ retry๋ฅผ ์ ์šฉํ•˜์—ฌ ๋ณต์›๋ ฅ์„ ๋†’์ž„

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@myk8s-control-plane:/istiobook/bin# 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
virtualservice.networking.istio.io/catalog created
  • catalog ์„œ๋น„์Šค์— ๋Œ€ํ•ด ์ตœ๋Œ€ 3๋ฒˆ๊นŒ์ง€ ์š”์ฒญ ์žฌ์‹œ๋„
  • ๊ฐ ์š”์ฒญ ์žฌ์‹œ๋„ ์‹œ 2์ดˆ์˜ ์ œํ•œ ์‹œ๊ฐ„ ์ ์šฉ

์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜ํ™˜๋˜๋Š” ์„ฑ๊ณต๋ฅ ์ด ์•ฝ 92%๊นŒ์ง€ ์ƒ์Šนํ•˜๋ฉฐ 5xx ์—๋Ÿฌ์œจ์ด ๊ฐ์†Œํ•จ

์„ฑ๊ณต๋ฅ ์€ ์˜ฌ๋ผ๊ฐ€๊ณ , ์—๋Ÿฌ์œจ์€ ๊ฐ์†Œ


๐Ÿ†• ์ƒˆ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ์‹œ๋‚˜๋ฆฌ์˜ค ๋Œ€์‘

1. catalog v2 ๋ฐฐํฌ

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
32
33
34
35
36
37
38
39
40
41
42
43
root@myk8s-control-plane:/istiobook/bin# exit

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

# ๊ฒฐ๊ณผ
deployment.apps/catalog-v2 created

2. 500 ์—๋Ÿฌ ์žฌํ˜„ ์„ค์ • ์ œ๊ฑฐ

1
2
3
4
5
6
7
8
9
10
docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# cd /istiobook/bin/
root@myk8s-control-plane:/istiobook/bin# ./chaos.sh 500 delete

# ๊ฒฐ๊ณผ
catalog-6cf4b97d-kw68k catalog-v2-6df885b555-bfg8k
Deleting 500 rule from catalog-6cf4b97d-kw68k
blowups=[object Object]Deleting 500 rule from catalog-v2-6df885b555-bfg8k

root@myk8s-control-plane:/istiobook/bin# exit

3. v1๋งŒ ์ ‘์† ์„ค์ • (DestinationRule ์ ์šฉ)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

# ๊ฒฐ๊ณผ
destinationrule.networking.istio.io/catalog created

4. ๋ฆฌ์†Œ์Šค ์ƒํƒœ ์กฐํšŒ

1
kubectl get gw,vs,dr -n istioinaction

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
NAME                                             AGE
gateway.networking.istio.io/outfitters-gateway   96m

NAME                                                       GATEWAYS                 HOSTS         AGE
virtualservice.networking.istio.io/catalog                                          ["catalog"]   13m
virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]         96m

NAME                                          HOST      AGE
destinationrule.networking.istio.io/catalog   catalog   37s

5. ๋ถ„์‚ฐ ์ ‘์† ๋ฐ ๋ถ€ํ•˜๋ถ„์‚ฐ ํ™•์ธ

ํŠธ๋ž˜ํ”ฝ์ด v2๋กœ ์ ‘๊ทผํ•  ๊ฒฝ์šฐ, ์‘๋‹ต JSON์— imageUrl ์†์„ฑ์ด ์ถ”๊ฐ€๋˜์–ด ๋ฐ˜ํ™˜

1
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

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  }
]
2025-04-13 01:49:04

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  }
]
2025-04-13 01:49:05

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
....

6. v1 ๋ผ์šฐํŒ… ๊ฐ•์ œ ์ ์šฉ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

# ๊ฒฐ๊ณผ
virtualservice.networking.istio.io/catalog configured

7. ๋ถ„์‚ฐ ์ ‘์† ๋ฐ ๋ถ€ํ•˜๋ถ„์‚ฐ ํ™•์ธ

์‘๋‹ต JSON์—์„œ imageUrl ์†์„ฑ์ด ์—†์ด v1 ๋ฒ„์ „ ์‘๋‹ต์ด ์ถœ๋ ฅ๋จ

1
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

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
2025-04-13 01:51:47

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
2025-04-13 01:51:48

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
2025-04-13 01:51:49

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
2025-04-13 01:51:50

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
...

7. ํ—ค๋” ๊ธฐ๋ฐ˜ v2 ๋ผ์šฐํŒ… ์ ์šฉ

ํŠน์ • ํ—ค๋”(x-dark-launch: v2)๋ฅผ ํฌํ•จํ•˜๋ฉด catalog v2๋กœ, ๊ทธ ์™ธ์—๋Š” v1์œผ๋กœ ๋ผ์šฐํŒ…ํ•˜๋„๋ก VirtualService ์—…๋ฐ์ดํŠธ

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
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

# ๊ฒฐ๊ณผ
virtualservice.networking.istio.io/catalog configured

8. ๋ฐ˜๋ณต ์ ‘์† : v1 ์ ‘์† ํ™•์ธ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
2025-04-13 01:56:11

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
2025-04-13 01:56:12

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00"
  }
]
2025-04-13 01:56:13
...

9. ๋ฐ˜๋ณต ์ ‘์† : v2 ์ ‘์† ํ™•์ธ

1
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

โœ…ย ์ถœ๋ ฅ

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  }
]
2025-04-13 01:56:33

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  }
]
2025-04-13 01:56:34

[
  {
    "id": 1,
    "color": "amber",
    "department": "Eyewear",
    "name": "Elinor Glasses",
    "price": "282.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 2,
    "color": "cyan",
    "department": "Clothing",
    "name": "Atlas Shirt",
    "price": "127.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 3,
    "color": "teal",
    "department": "Clothing",
    "name": "Small Metal Shoes",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  },
  {
    "id": 4,
    "color": "red",
    "department": "Watches",
    "name": "Red Dragon Watch",
    "price": "232.00",
    "imageUrl": "http://lorempixel.com/640/480"
  }
]
2025-04-13 01:56:36
...


๐Ÿ—‘๏ธ ์‹ค์Šต ์™„๋ฃŒ ํ›„ ์‚ญ์ œ

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

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
deployment.apps "catalog" deleted
deployment.apps "catalog-v2" deleted
deployment.apps "webapp" deleted
service "catalog" deleted
service "webapp" deleted
gateway.networking.istio.io "outfitters-gateway" deleted
virtualservice.networking.istio.io "catalog" deleted
virtualservice.networking.istio.io "webapp-virtualservice" deleted
destinationrule.networking.istio.io "catalog" deleted
Deleting cluster "myk8s" ...
error: lost connection to pod
[1]  + 340443 exit 1     kubectl port-forward deployment/kiali -n istio-system 20001:20001
Deleted nodes: ["myk8s-control-plane"]
This post is licensed under CC BY 4.0 by the author.