前回 の続きです。
Istio でのサービス間通信 まあ、ただサービス間で通信するだけなら Istio は不要なわけだけれども、まずはここから。
httpbin をサービスとして deploy httpbin.org のコンテナは Request Header をそのまま返してくれたりして便利なのでこれをサービスとして deploy します。
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
apiVersion : apps/v1
kind : Deployment
metadata :
name : httpbin-deployment
labels :
app : httpbin
spec :
replicas : 2
selector :
matchLabels :
app : httpbin
template :
metadata :
labels :
app : httpbin
spec :
containers :
- name : httpbin
image : kennethreitz/httpbin:latest
imagePullPolicy : IfNotPresent
ports :
- containerPort : 80
readinessProbe :
httpGet :
path : /status/200
port : 80
initialDelaySeconds : 10
periodSeconds : 5
livenessProbe :
httpGet :
path : /status/200
port : 80
initialDelaySeconds : 15
periodSeconds : 5
---
apiVersion : v1
kind : Service
metadata :
name : httpbin-service
spec :
selector :
app : httpbin
ports :
- name : http
protocol : TCP
port : 80
targetPort : 80
不要なんだけど、全部同じ名前にしちゃうとどれとどれが連動しているのかわかりにくくなるので -service とか -deployment とかを名前に入れています。これを httpbin.yaml として保存します。
これに Istio の sidecar を inject するのが istioctl kube-inject です。次のように実行すれば inject 済みの manifest が出力されます。
1
istioctl kube-inject -f httpbin.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
apiVersion : apps/v1
kind : Deployment
metadata :
creationTimestamp : null
labels :
app : httpbin
name : httpbin-deployment
spec :
replicas : 2
selector :
matchLabels :
app : httpbin
strategy : {}
template :
metadata :
annotations :
sidecar.istio.io/interceptionMode : REDIRECT
sidecar.istio.io/status : '{"version":"1cdb312e0b39910b7401fa37c42113f6436e281598036cb126f9692adebf1545","initContainers":["istio-init"],"containers":["istio-proxy"],"volumes":["istio-envoy","podinfo","istiod-ca-cert"],"imagePullSecrets":null}'
traffic.sidecar.istio.io/excludeInboundPorts : "15020"
traffic.sidecar.istio.io/includeInboundPorts : "80"
traffic.sidecar.istio.io/includeOutboundIPRanges : '*'
creationTimestamp : null
labels :
app : httpbin
security.istio.io/tlsMode : istio
spec :
containers :
- image : kennethreitz/httpbin:latest
imagePullPolicy : IfNotPresent
livenessProbe :
httpGet :
path : /status/200
port : 80
initialDelaySeconds : 15
periodSeconds : 5
name : httpbin
ports :
- containerPort : 80
readinessProbe :
httpGet :
path : /status/200
port : 80
initialDelaySeconds : 10
periodSeconds : 5
resources : {}
- args :
- proxy
- sidecar
- --domain
- $(POD_NAMESPACE).svc.cluster.local
- --configPath
- /etc/istio/proxy
- --binaryPath
- /usr/local/bin/envoy
- --serviceCluster
- httpbin.$(POD_NAMESPACE)
- --drainDuration
- 45s
- --parentShutdownDuration
- 1m0s
- --discoveryAddress
- istiod.istio-system.svc:15012
- --zipkinAddress
- zipkin.istio-system:9411
- --proxyLogLevel=warning
- --proxyComponentLogLevel=misc:error
- --connectTimeout
- 10s
- --proxyAdminPort
- "15000"
- --concurrency
- "2"
- --controlPlaneAuthPolicy
- NONE
- --dnsRefreshRate
- 300s
- --statusPort
- "15020"
- --trust-domain=cluster.local
- --controlPlaneBootstrap=false
env :
- name : JWT_POLICY
value : first-party-jwt
- name : PILOT_CERT_PROVIDER
value : istiod
- name : CA_ADDR
value : istio-pilot.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 : ISTIO_META_POD_PORTS
value : |-
[
{"containerPort":80}
]
- name : ISTIO_META_CLUSTER_ID
value : Kubernetes
- name : ISTIO_META_POD_NAME
valueFrom :
fieldRef :
fieldPath : metadata.name
- name : ISTIO_META_CONFIG_NAMESPACE
valueFrom :
fieldRef :
fieldPath : metadata.namespace
- name : ISTIO_META_INTERCEPTION_MODE
value : REDIRECT
- name : ISTIO_META_WORKLOAD_NAME
value : httpbin-deployment
- name : ISTIO_META_OWNER
value : kubernetes://apis/apps/v1/namespaces/default/deployments/httpbin-deployment
- name : ISTIO_META_MESH_ID
value : cluster.local
image : docker.io/istio/proxyv2:1.5.0
imagePullPolicy : IfNotPresent
name : istio-proxy
ports :
- containerPort : 15090
name : http-envoy-prom
protocol : TCP
readinessProbe :
failureThreshold : 30
httpGet :
path : /healthz/ready
port : 15020
initialDelaySeconds : 1
periodSeconds : 2
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/istio
name : istiod-ca-cert
- mountPath : /etc/istio/proxy
name : istio-envoy
- mountPath : /etc/istio/pod
name : podinfo
initContainers :
- command :
- istio-iptables
- -p
- "15001"
- -z
- "15006"
- -u
- "1337"
- -m
- REDIRECT
- -i
- '*'
- -x
- ""
- -b
- '*'
- -d
- 15090 , 15020
image : docker.io/istio/proxyv2:1.5.0
imagePullPolicy : IfNotPresent
name : istio-init
resources :
limits :
cpu : 100m
memory : 50Mi
requests :
cpu : 10m
memory : 10Mi
securityContext :
allowPrivilegeEscalation : false
capabilities :
add :
- NET_ADMIN
- NET_RAW
drop :
- ALL
privileged : false
readOnlyRootFilesystem : false
runAsGroup : 0
runAsNonRoot : false
runAsUser : 0
securityContext :
fsGroup : 1337
volumes :
- emptyDir :
medium : Memory
name : istio-envoy
- downwardAPI :
items :
- fieldRef :
fieldPath : metadata.labels
path : labels
- fieldRef :
fieldPath : metadata.annotations
path : annotations
name : podinfo
- configMap :
name : istio-ca-root-cert
name : istiod-ca-cert
status : {}
---
apiVersion : v1
kind : Service
metadata :
name : httpbin-service
spec :
selector :
app : httpbin
ports :
- name : http
protocol : TCP
port : 80
targetPort : 80
よって、これを pipe で kubectl apply に食わせることで deploy できます。kubectl apply -f <(istioctl kube-inject -f ...) でも良いし、もちろんファイルに一旦書き出しても大丈夫。
1
istioctl kube-inject -f httpbin.yaml | kubectl apply -f -
default namespace に deploy しました。
$ istioctl kube-inject -f httpbin.yaml | kubectl apply -f -
deployment.apps/httpbin-deployment created
service/httpbin-service created
$ kubectl get pods,deployments,services
NAME READY STATUS RESTARTS AGE
pod/httpbin-deployment-9bfd96975-px5lv 2/2 Running 0 88s
pod/httpbin-deployment-9bfd96975-v6mgg 2/2 Running 0 88s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/httpbin-deployment 2/2 2 2 88s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/httpbin-service ClusterIP 10.109.118.31 80/TCP 88s
service/kubernetes ClusterIP 10.96.0.1 443/TCP 4h24m 自動で inject されるようにする 毎回 Deployment を作る度に kube-inject をするのは面倒なので自動化することができる。自動 inject 対象としたい namespace に対して istio-injection=enabled という label をつけるだけで良い。
1
kubectl label namespace default istio-injection= enabled
$ kubectl get ns default -o yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: "2020-03-07T06:44:22Z"
labels:
istio-injection: enabled
name: default
resourceVersion: "12273"
selfLink: /api/v1/namespaces/default
uid: 1c02a69b-5ab5-433a-90be-6c6e3b785867
spec:
finalizers:
- kubernetes
status:
phase: Active先ほど deploy した httpbin に対してクラスタ内からアクセスするための ubuntu コンテナを Deployment として deploy します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion : apps/v1
kind : Deployment
metadata :
name : ubuntu-deployment
labels :
app : ubuntu
spec :
replicas : 1
selector :
matchLabels :
app : ubuntu
template :
metadata :
labels :
app : ubuntu
spec :
containers :
- name : ubuntu
image : ubuntu:latest
imagePullPolicy : IfNotPresent
command :
- sleep
- infinity
この manifest を ubuntu.yaml として保存し、今度は istioctl kube-inject を使わずにそのまま kubectl apply します。それでも自動で inject されるはずです。
$ kubectl apply -f ubuntu.yaml
deployment.apps/ubuntu-deployment createdDeployment の spec には ubuntu コンテナしか書いてなかったのにコンテナの数が2になっています。
$ kubectl get pods -l app=ubuntu
NAME READY STATUS RESTARTS AGE
ubuntu-deployment-cc86cc647-vsvbh 2/2 Running 0 21sistio-proxy というコンテナが追加されています。長いので名前だけ表示。
$ kubectl get pods -l app=ubuntu -o json | jq '.items[].spec.containers[].name'
"ubuntu"
"istio-proxy"curl でアクセスしてみる ubuntu Pod から httpbin Service にアクセスしてみます。
$ kubectl exec -it ubuntu-deployment-cc86cc647-vsvbh -c ubuntu -- bash
root@ubuntu-deployment-cc86cc647-vsvbh:/#curl が入っていないのでインストールする。
root@ubuntu-deployment-cc86cc647-vsvbh# apt-get update && apt-get install -y curlhttpbin-service にアクセスしてみる。
root@ubuntu-deployment-cc86cc647-vsvbh:/# curl -sv http://httpbin-service/headers
* Trying 10.109.118.31...
* TCP_NODELAY set
* Connected to httpbin-service (10.109.118.31) port 80 (#0)
> GET /headers HTTP/1.1
> Host: httpbin-service
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< server: envoy
< date: Sat, 07 Mar 2020 11:33:28 GMT
< content-type: application/json
< content-length: 521
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 26
<
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin-service",
"User-Agent": "curl/7.58.0",
"X-B3-Parentspanid": "361390f32cd55bdc",
"X-B3-Sampled": "0",
"X-B3-Spanid": "f95fbc3875ab93e5",
"X-B3-Traceid": "3a3e0cd03f1ded4e361390f32cd55bdc",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/default;Hash=b87885c2542d1279071454ae1ce34cea21b7a265095bb23297ff44542009a304;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
}
}
* Connection #0 to host httpbin-service left intactできました。Response Header に server: envoy や x-envoy-upstream-service-time: 26 が入っています。また、X- プレフィックスのついた curl では送っていないヘッダーが httpbin 側に届いているようです。Envoy が間に入っているようです。X-Forwarded-Client-Cent も送られているのでクライアント証明書も送られたっぽいですね。これは Istio 1.5 からデフォルトになったのだろうか。1.4.6 の時は追加の設定が必要だったのだが。
$ kubectl get -n istio-system cm istio -o yaml | grep -v '{' | grep enableAutoMtls:
enableAutoMtls: truetrue になってる。前回の記事 に戻って default プロファイルの値を確認してみよう。
$ istioctl manifest generate --set profile=default | grep enableAutoMtls
enableAutoMtls: falseあれ?どこで変わったんだ? 🤔 後で確認してみよう。
1
2
3
4
# If true, automatically configure client side mTLS settings to match the corresponding service's
# server side mTLS authentication policy, when destination rule for that service does not specify
# TLS settings.
enableAutoMtls : true
っていう値。
Envoy のログを確認してみる 前回の istio のインストール時に Envoy のログを有効にしておいたので istio-proxy の出力を確認してみます。
まずは送信元の ubuntu 側。 grep を pipe に繋げると buffering されて全然 jq まで渡ってこないので --line-buffered をつけています。
1
kubectl logs -l app = ubuntu -c istio-proxy -f --tail 0 | grep --line-buffered '^{' | 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
{
"authority" : "httpbin-service" ,
"bytes_received" : "0" ,
"bytes_sent" : "521" ,
"downstream_local_address" : "10.109.118.31:80" ,
"downstream_remote_address" : "172.17.0.9:52178" ,
"duration" : "2" ,
"istio_policy_status" : "-" ,
"method" : "GET" ,
"path" : "/headers" ,
"protocol" : "HTTP/1.1" ,
"request_id" : "a93e2afa-cc27-4bb7-897c-5282c754d382" ,
"requested_server_name" : "-" ,
"response_code" : "200" ,
"response_flags" : "-" ,
"route_name" : "default" ,
"start_time" : "2020-03-07T12:00:58.425Z" ,
"upstream_cluster" : "outbound|80||httpbin-service.default.svc.cluster.local" ,
"upstream_host" : "172.17.0.8:80" ,
"upstream_local_address" : "172.17.0.9:43422" ,
"upstream_service_time" : "2" ,
"upstream_transport_failure_reason" : "-" ,
"user_agent" : "curl/7.58.0" ,
"x_forwarded_for" : "-"
}
172.17.0.9 は ubuntu Pod の IP アドレス。10.109.118.31 は httpbin-service Serivce の IP アドレス。172.17.0.8 は httpbin Pod の IP アドレス。
istio-proxy が 172.17.0.9:43422 –> 172.17.0.8:80 でリクエストを投げて、10.109.118.31:80 から 172.17.0.9:52178 に返したことにしてるってことなのか??
次に httpbin 側のログ
1
2
3
4
kubectl logs -l app = httpbin -c istio-proxy -f --tail 0 \
| grep --line-buffered '^{' \
| grep --line-buffered -v kube-probe \
| 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
{
"authority" : "httpbin-service" ,
"bytes_received" : "0" ,
"bytes_sent" : "521" ,
"downstream_local_address" : "172.17.0.8:80" ,
"downstream_remote_address" : "172.17.0.9:43422" ,
"duration" : "1" ,
"istio_policy_status" : "-" ,
"method" : "GET" ,
"path" : "/headers" ,
"protocol" : "HTTP/1.1" ,
"request_id" : "a93e2afa-cc27-4bb7-897c-5282c754d382" ,
"requested_server_name" : "outbound_.80_._.httpbin-service.default.svc.cluster.local" ,
"response_code" : "200" ,
"response_flags" : "-" ,
"route_name" : "default" ,
"start_time" : "2020-03-07T12:00:58.425Z" ,
"upstream_cluster" : "inbound|80|http|httpbin-service.default.svc.cluster.local" ,
"upstream_host" : "127.0.0.1:80" ,
"upstream_local_address" : "127.0.0.1:55232" ,
"upstream_service_time" : "1" ,
"upstream_transport_failure_reason" : "-" ,
"user_agent" : "curl/7.58.0" ,
"x_forwarded_for" : "-"
}
172.17.0.9:43422 (ubuntu:istio-proxy) –> 172.17.0.8:80 (httpbin:istio-proxy) 127.0.0.1:55232 –> 127.0.0.1:80 (httpbin:httpbin)
各 Pod と Serivce の IP アドレスは次の通り。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpbin-deployment-9bfd96975-px5lv 2/2 Running 0 60m 172.17.0.8 m01 httpbin-deployment-9bfd96975-v6mgg 2/2 Running 0 60m 172.17.0.7 m01 ubuntu-deployment-cc86cc647-vsvbh 2/2 Running 0 45m 172.17.0.9 m01 $ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpbin-service ClusterIP 10.109.118.31 80/TCP 60m
kubernetes ClusterIP 10.96.0.1 443/TCP 5h22m 続く
Istio 導入への道シリーズ