eksworkshop.comのIstioハンズオン

eksworkshop.comのIstioハンズオンをやってみる

eksworkshop.comのIstioハンズオンをやってみたメモ。

環境

コンポーネント バージョン 備考
eksctl 0.14.0
Kubernetes バージョン 1.14
プラットフォームのバージョン eks.9
istioctl 1.4.5

クラスターを作成する。

eksctl create cluster --name=istio --nodes=3 --managed --ssh-access --ssh-public-key=sotosugi

istioctlはHomebrewで入っていたものを使う。

$ istioctl version  --remote=false
1.4.5

サンプルアプリケーションのマニフェストが必要なので、作業ディレクトリにIstioをダウンロードする。

ISTIO_VERSION="1.4.5"
curl -L https://istio.io/downloadIstio | sh -

Istioのインストール

Istioのインストール方法は以下3つの方法がある。

istioctlが現在の推奨。

istioctlではプロファイルを指定することができるが、使用できるプロファイルはprofile listで確認できる。

$ istioctl profile list
Istio configuration profiles:
    default
    demo
    minimal
    remote
    sds

profile dumpでプロファイルの詳細が確認できる。

$ istioctl profile dump demo
autoInjection:
  components:
    injector:
      enabled: true
      k8s:
        replicaCount: 1
        strategy:
          rollingUpdate:
            maxSurge: 100%
            maxUnavailable: 25%
  enabled: true
cni:
  enabled: false
configManagement:
  components:
    galley:
      enabled: true

(省略)

インストールには、manifest applyで直接適用するか、manifest generateで一旦マニフェストを生成してから適用する。

細かく設定をカスタマイズしたい場合は、以下のようなYAMLを作ってdefaultプロファイルを上書きできる。

apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
spec:
  telemetry:
    enabled: false
istioctl manifest apply -f telemetry_off.yaml

なお、Operatorの場合にはこのkind: IstioControlPlaneのリソースを作成すればOperatorがIstioをインストールしてくれるようだ。

以下のコマンドでdemoプロファイルでIstioをインストールする。

istioctl manifest apply --set profile=demo
$ istioctl manifest apply --set profile=demo
- Applying manifest for component Base...
✔ Finished applying manifest for component Base.
- Applying manifest for component Tracing...
- Applying manifest for component Citadel...
- Applying manifest for component IngressGateway...
- Applying manifest for component Galley...
- Applying manifest for component Kiali...
- Applying manifest for component EgressGateway...
- Applying manifest for component Prometheus...
- Applying manifest for component Policy...
- Applying manifest for component Pilot...
- Applying manifest for component Injector...
- Applying manifest for component Telemetry...
- Applying manifest for component Grafana...
✔ Finished applying manifest for component Citadel.
✔ Finished applying manifest for component Prometheus.
✔ Finished applying manifest for component Kiali.
✔ Finished applying manifest for component Tracing.
✔ Finished applying manifest for component Galley.
✔ Finished applying manifest for component Injector.
✔ Finished applying manifest for component IngressGateway.
✔ Finished applying manifest for component Pilot.
✔ Finished applying manifest for component Policy.
✔ Finished applying manifest for component EgressGateway.
✔ Finished applying manifest for component Grafana.
✔ Finished applying manifest for component Telemetry.


✔ Installation complete

Serviceを確認する。

$ kubectl -n istio-system get svc
NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP                                                                   PORT(S)                                                                                                                      AGE
grafana                  ClusterIP      10.100.88.107    <none>                                                                        3000/TCP                                                                                                                     60s
istio-citadel            ClusterIP      10.100.132.156   <none>                                                                        8060/TCP,15014/TCP                                                                                                           63s
istio-egressgateway      ClusterIP      10.100.64.33     <none>                                                                        80/TCP,443/TCP,15443/TCP                                                                                                     61s
istio-galley             ClusterIP      10.100.88.94     <none>                                                                        443/TCP,15014/TCP,9901/TCP,15019/TCP                                                                                         62s
istio-ingressgateway     LoadBalancer   10.100.198.18    a2fd22ea85d6511ea915f0ec6e811fa2-179736594.ap-northeast-1.elb.amazonaws.com   15020:32122/TCP,80:30530/TCP,443:31399/TCP,15029:31432/TCP,15030:30310/TCP,15031:30979/TCP,15032:32370/TCP,15443:30848/TCP   61s
istio-pilot              ClusterIP      10.100.126.231   <none>                                                                        15010/TCP,15011/TCP,8080/TCP,15014/TCP                                                                                       61s
istio-policy             ClusterIP      10.100.72.152    <none>                                                                        9091/TCP,15004/TCP,15014/TCP                                                                                                 61s
istio-sidecar-injector   ClusterIP      10.100.124.141   <none>                                                                        443/TCP                                                                                                                      62s
istio-telemetry          ClusterIP      10.100.110.67    <none>                                                                        9091/TCP,15004/TCP,15014/TCP,42422/TCP                                                                                       59s
jaeger-agent             ClusterIP      None             <none>                                                                        5775/UDP,6831/UDP,6832/UDP                                                                                                   63s
jaeger-collector         ClusterIP      10.100.78.120    <none>                                                                        14267/TCP,14268/TCP,14250/TCP                                                                                                63s
jaeger-query             ClusterIP      10.100.210.72    <none>                                                                        16686/TCP                                                                                                                    63s
kiali                    ClusterIP      10.100.151.38    <none>                                                                        20001/TCP                                                                                                                    63s
prometheus               ClusterIP      10.100.188.165   <none>                                                                        9090/TCP                                                                                                                     63s
tracing                  ClusterIP      10.100.65.161    <none>                                                                        80/TCP                                                                                                                       63s
zipkin                   ClusterIP      10.100.86.195    <none>                                                                        9411/TCP

Type: LoadBalancerのServiceがあり、これによってCLBが作られていることが確認できる。

aws elb describe-load-balancers

Podを確認する。

$ kubectl -n istio-system get pods
NAME                                      READY   STATUS    RESTARTS   AGE
grafana-5f798469fd-79ls6                  1/1     Running   0          5m41s
istio-citadel-58bb67f9b8-zvjqb            1/1     Running   0          5m43s
istio-egressgateway-6fd57475b5-wm9rp      1/1     Running   0          5m43s
istio-galley-7d4b9874c8-x9pk4             1/1     Running   0          5m42s
istio-ingressgateway-7d65bf7fdf-bpvjv     1/1     Running   0          5m43s
istio-pilot-65f8557545-5z5mm              1/1     Running   0          5m43s
istio-policy-6c6449c56f-t8h8r             1/1     Running   2          5m43s
istio-sidecar-injector-774969d686-w7z26   1/1     Running   0          5m42s
istio-telemetry-585cc965f7-jnd7z          1/1     Running   2          5m42s
istio-tracing-cd67ddf8-cfqwt              1/1     Running   0          5m43s
kiali-7964898d8c-rxmdv                    1/1     Running   0          5m42s
prometheus-586d4445c7-2ltkq               1/1     Running   0          5m43s

サンプルアプリケーションのデプロイ

Namespacesを作成し、このNamespacesでAuto Injectionを有効にする。

kubectl create namespace bookinfo
kubectl label namespace bookinfo istio-injection=enabled

ラベルを確認する。

$ kubectl get ns bookinfo --show-labels
NAME       STATUS   AGE   LABELS
bookinfo   Active   51s   istio-injection=enabled

アプリケーションをデプロイする。

kubectl -n bookinfo apply \
  -f istio-${ISTIO_VERSION}/samples/bookinfo/platform/kube/bookinfo.yaml

確認する。

$ kubectl -n bookinfo get pod,svc
NAME                                 READY   STATUS    RESTARTS   AGE
pod/details-v1-c5b5f496d-zq57c       2/2     Running   0          34s
pod/productpage-v1-c7765c886-kbk4q   2/2     Running   0          33s
pod/ratings-v1-f745cf57b-zvxmb       2/2     Running   0          33s
pod/reviews-v1-75b979578c-4v756      2/2     Running   0          33s
pod/reviews-v2-597bf96c8f-hcqp6      2/2     Running   0          33s
pod/reviews-v3-54c6c64795-zbr7l      2/2     Running   0          33s

NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/details       ClusterIP   10.100.75.161    <none>        9080/TCP   34s
service/productpage   ClusterIP   10.100.192.148   <none>        9080/TCP   33s
service/ratings       ClusterIP   10.100.148.131   <none>        9080/TCP   34s
service/reviews       ClusterIP   10.100.144.233   <none>        9080/TCP   33s

EnvoyがインジェクションされたPodの設定を見てみる。

$ kubectl get po -n bookinfo details-v1-c5b5f496d-zq57c -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/psp: eks.privileged
    sidecar.istio.io/status: '{"version":"b5faac9e6b02231b7db3b29487392a395f1c85c746bf62dc8cb660444af6e0d9","initContainers":["istio-init"],"containers":["istio-proxy"],"volumes":["istio-envoy","istio-certs"],"imagePullSecrets":null}'
  creationTimestamp: "2020-03-03T15:59:16Z"
  generateName: details-v1-c5b5f496d-
  labels:
    app: details
    pod-template-hash: c5b5f496d
    security.istio.io/tlsMode: istio
    version: v1
  name: details-v1-c5b5f496d-zq57c
  namespace: bookinfo
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: details-v1-c5b5f496d
    uid: ef685e96-5d67-11ea-ac5d-062ae758ff04
  resourceVersion: "4604"
  selfLink: /api/v1/namespaces/bookinfo/pods/details-v1-c5b5f496d-zq57c
  uid: ef6e6577-5d67-11ea-ac5d-062ae758ff04
spec:
  containers:
  - image: docker.io/istio/examples-bookinfo-details-v1:1.15.0
    imagePullPolicy: IfNotPresent
    name: details
    ports:
    - containerPort: 9080
      protocol: TCP
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: bookinfo-details-token-jx8zv
      readOnly: true
  - args:
    - proxy
    - sidecar
    - --domain
    - $(POD_NAMESPACE).svc.cluster.local
    - --configPath
    - /etc/istio/proxy
    - --binaryPath
    - /usr/local/bin/envoy
    - --serviceCluster
    - details.$(POD_NAMESPACE)
    - --drainDuration
    - 45s
    - --parentShutdownDuration
    - 1m0s
    - --discoveryAddress
    - istio-pilot.istio-system:15010
    - --zipkinAddress
    - zipkin.istio-system:9411
    - --proxyLogLevel=warning
    - --proxyComponentLogLevel=misc:error
    - --connectTimeout
    - 10s
    - --proxyAdminPort
    - "15000"
    - --concurrency
    - "2"
    - --controlPlaneAuthPolicy
    - NONE
    - --dnsRefreshRate
    - 300s
    - --statusPort
    - "15020"
    - --applicationPorts
    - "9080"
    - --trust-domain=cluster.local
    env:
    - 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: ISTIO_META_POD_PORTS
      value: |-
        [
            {"containerPort":9080,"protocol":"TCP"}
        ]
    - name: ISTIO_META_CLUSTER_ID
      value: Kubernetes
    - name: ISTIO_META_POD_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    - name: ISTIO_META_CONFIG_NAMESPACE
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.namespace
    - name: SDS_ENABLED
      value: "false"
    - name: ISTIO_META_INTERCEPTION_MODE
      value: REDIRECT
    - name: ISTIO_META_INCLUDE_INBOUND_PORTS
      value: "9080"
    - name: ISTIO_METAJSON_ANNOTATIONS
      value: |
        {"kubernetes.io/psp":"eks.privileged"}
    - name: ISTIO_METAJSON_LABELS
      value: |
        {"app":"details","pod-template-hash":"c5b5f496d","version":"v1"}
    - name: ISTIO_META_WORKLOAD_NAME
      value: details-v1
    - name: ISTIO_META_OWNER
      value: kubernetes://apis/apps/v1/namespaces/bookinfo/deployments/details-v1
    - name: ISTIO_META_MESH_ID
      value: cluster.local
    image: docker.io/istio/proxyv2:1.4.5
    imagePullPolicy: IfNotPresent
    name: istio-proxy
    ports:
    - containerPort: 15090
      name: http-envoy-prom
      protocol: TCP
    readinessProbe:
      failureThreshold: 30
      httpGet:
        path: /healthz/ready
        port: 15020
        scheme: HTTP
      initialDelaySeconds: 1
      periodSeconds: 2
      successThreshold: 1
      timeoutSeconds: 1
    resources:
      limits:
        cpu: "2"
        memory: 1Gi
      requests:
        cpu: 10m
        memory: 40Mi
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
      privileged: false
      readOnlyRootFilesystem: true
      runAsGroup: 1337
      runAsNonRoot: true
      runAsUser: 1337
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /etc/istio/proxy
      name: istio-envoy
    - mountPath: /etc/certs/
      name: istio-certs
      readOnly: true
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: bookinfo-details-token-jx8zv
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  initContainers:
  - command:
    - istio-iptables
    - -p
    - "15001"
    - -z
    - "15006"
    - -u
    - "1337"
    - -m
    - REDIRECT
    - -i
    - '*'
    - -x
    - ""
    - -b
    - '*'
    - -d
    - "15020"
    image: docker.io/istio/proxyv2:1.4.5
    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
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
  nodeName: ip-192-168-65-11.ap-northeast-1.compute.internal
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: bookinfo-details
  serviceAccountName: bookinfo-details
  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:
  - name: bookinfo-details-token-jx8zv
    secret:
      defaultMode: 420
      secretName: bookinfo-details-token-jx8zv
  - emptyDir:
      medium: Memory
    name: istio-envoy
  - name: istio-certs
    secret:
      defaultMode: 420
      optional: true
      secretName: istio.bookinfo-details
status:

(省略)

Init ContainerがNET_ADMINNET_RAWのCapabilityを持っていて、iptablesを操作していそうなことがわかる。

UbuntuのPodに特権を付けて起動してみる。

cat <<EOF >ubuntu-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: ubuntu
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu
    command:
    - tail
    - -f
    - /dev/null
    securityContext:
      privileged: true
EOF
kubectl apply -f ubuntu-pod.yaml -n bookinfo

このPodに入り、iptablesをインストールしてiptablesのルールを確認する。

kubectl exec -it -n bookinfo ubuntu bash
apt-get update
apt-get install -y iptables
iptables -t nat -n -L -v
root@ubuntu:/# iptables -t nat -n -L -v
Chain PREROUTING (policy ACCEPT 333 packets, 19980 bytes)
 pkts bytes target     prot opt in     out     source               destination
  334 20040 ISTIO_INBOUND  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain INPUT (policy ACCEPT 334 packets, 20040 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 40 packets, 3126 bytes)
 pkts bytes target     prot opt in     out     source               destination
   15   900 ISTIO_OUTPUT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain POSTROUTING (policy ACCEPT 43 packets, 3306 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain ISTIO_INBOUND (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
  333 19980 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15020
    1    60 ISTIO_IN_REDIRECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain ISTIO_IN_REDIRECT (2 references)
 pkts bytes target     prot opt in     out     source               destination
    1    60 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15006

Chain ISTIO_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination
    1    60 RETURN     all  --  *      lo      127.0.0.6            0.0.0.0/0
    0     0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1
   11   660 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
    0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
    0     0 RETURN     all  --  *      *       0.0.0.0/0            127.0.0.1
    3   180 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain ISTIO_REDIRECT (1 references)
 pkts bytes target     prot opt in     out     source               destination
    3   180 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001

utuntuのPodを削除する。

kubectl delete pod ubuntu -n bookinfo

続いてVirtualServiceとGatewayをデプロイする。

kubectl -n bookinfo \
  apply -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/bookinfo-gateway.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
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: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

確認する。

$ kubectl get virtualservice,gateway -n bookinfo
NAME                                          GATEWAYS             HOSTS   AGE
virtualservice.networking.istio.io/bookinfo   [bookinfo-gateway]   [*]     44s

NAME                                           AGE
gateway.networking.istio.io/bookinfo-gateway   44s

istio-ingressgatewayというServiceのExternal IPを確認する。

GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "http://${GATEWAY_URL}/productpage"

URLにアクセスする。

f:id:sotoiwa:20200304025317p:plain

この状態では、reviewsというServiceはv1、v2、v3のPodにランダムに割り振っている。 セレクターがapp: reviewsとなっていて、v1、v2、v3のPodがこのラベルを持っているため。 つまりVirtualServiceやDestinationRuleがない状態では、普通にService経由で通信されている。

$ kubectl get po --show-labels -n bookinfo
NAME                             READY   STATUS    RESTARTS   AGE   LABELS
details-v1-c5b5f496d-zq57c       2/2     Running   0          57m   app=details,pod-template-hash=c5b5f496d,security.istio.io/tlsMode=istio,version=v1
productpage-v1-c7765c886-kbk4q   2/2     Running   0          57m   app=productpage,pod-template-hash=c7765c886,security.istio.io/tlsMode=istio,version=v1
ratings-v1-f745cf57b-zvxmb       2/2     Running   0          57m   app=ratings,pod-template-hash=f745cf57b,security.istio.io/tlsMode=istio,version=v1
reviews-v1-75b979578c-4v756      2/2     Running   0          57m   app=reviews,pod-template-hash=75b979578c,security.istio.io/tlsMode=istio,version=v1
reviews-v2-597bf96c8f-hcqp6      2/2     Running   0          57m   app=reviews,pod-template-hash=597bf96c8f,security.istio.io/tlsMode=istio,version=v2
reviews-v3-54c6c64795-zbr7l      2/2     Running   0          57m   app=reviews,pod-template-hash=54c6c64795,security.istio.io/tlsMode=istio,version=v3

トラフィックマネジメント

サブセットの定義

DestinationRuleを定義する。DestinationRuleでは、各サービスのサブセットをラベルに基づいて定義している。

kubectl -n bookinfo apply \
  -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/destination-rule-all.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: productpage
spec:
  host: productpage
  subsets:
  - name: v1
    labels:
      version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ratings
spec:
  host: ratings
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v2-mysql
    labels:
      version: v2-mysql
  - name: v2-mysql-vm
    labels:
      version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: details
spec:
  host: details
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
---

確認する。

$ kubectl get destinationrule -n bookinfo
NAME          HOST          AGE
details       details       19s
productpage   productpage   19s
ratings       ratings       19s
reviews       reviews       19s

単一バージョンへのルーティング

続いてVirtualServieを作成する。VirtualServiceが各サブセットへの振り分けのルールを記述している。ここでは全てv1にルーティングするルールを適用する。 DestinationRuleがそのリソース名からすると振り分けのルールっぽいが、DestinationRuleはサブセットの定義で、VirtualServiveが振り分けのルールなので注意が必要。

kubectl -n bookinfo \
  apply -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/virtual-service-all-v1.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
  - productpage
  http:
  - route:
    - destination:
        host: productpage
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: details
spec:
  hosts:
  - details
  http:
  - route:
    - destination:
        host: details
        subset: v1
---

確認する。

$ kubectl get virtualservice -n bookinfo
NAME          GATEWAYS             HOSTS           AGE
bookinfo      [bookinfo-gateway]   [*]             27m
details                            [details]       64s
productpage                        [productpage]   64s
ratings                            [ratings]       64s
reviews                            [reviews]       64s

HTTPヘッダーに基づいたルーティング

ヘッダーにend-user: jasonが含まれる場合はreviews:v2にルーティングするルールを適用する。

kubectl -n bookinfo \
  apply -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

jasonでログインするとv2(黒い星)が、それ以外ではv1(星なし)が表示される。

遅延のインジェクション

jasonに対して7秒の遅延をインジェクションするルールを適用する。

kubectl -n bookinfo \
  apply -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    fault:
      delay:
        percentage:
          value: 100.0
        fixedDelay: 7s
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1

productpagereviewsを呼び出すときのタイムアウトは6秒なため、jasonでアクセスすると6秒待った後、reviewsの取得がエラーとなる。

f:id:sotoiwa:20200304025507p:plain

失敗のインジェクション

jasonに対して直ちに500エラーを返すルールを適用する。

kubectl -n bookinfo \
  apply -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    fault:
      abort:
        percentage:
          value: 100.0
        httpStatus: 500
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1

jasonでアクセスするとreviewsの取得が直ちにエラーとなる。

トラフィックの重み付け

v1とv3で50%づつ振り分けるルールを適用する。

kubectl -n bookinfo \
  apply -f istio-${ISTIO_VERSION}/samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

(上記YAMLの内容)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 50
    - destination:
        host: reviews
        subset: v3
      weight: 50

v1(星なし)とv3(赤い星)が半々で表示される。

モニタリングと可視化

新しくメトリクスを定義する。

kubectl apply -f istio-${ISTIO_VERSION}/samples/bookinfo/telemetry/metrics.yaml

(上記YAMLの内容)

# Configuration for metric instances
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
  name: doublerequestcount
  namespace: istio-system
spec:
  compiledTemplate: metric
  params:
    value: "2" # count each request twice
    dimensions:
      reporter: conditional((context.reporter.kind | "inbound") == "outbound", "client", "server")
      source: source.workload.name | "unknown"
      destination: destination.workload.name | "unknown"
      message: '"twice the fun!"'
    monitored_resource_type: '"UNSPECIFIED"'
---
# Configuration for a Prometheus handler
apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
  name: doublehandler
  namespace: istio-system
spec:
  compiledAdapter: prometheus
  params:
    metrics:
    - name: double_request_count # Prometheus metric name
      instance_name: doublerequestcount.instance.istio-system # Mixer instance name (fully-qualified)
      kind: COUNTER
      label_names:
      - reporter
      - source
      - destination
      - message
---
# Rule to send metric instances to a Prometheus handler
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: doubleprom
  namespace: istio-system
spec:
  actions:
  - handler: doublehandler
    instances: [ doublerequestcount ]

PrometheusとGrafanaが稼働していることを確認する。

kubectl -n istio-system get svc prometheus grafana

Prometheusにポートフォワードする。

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 9090:9090

以下のURLにアクセスし、新しく定義したdouble_request_countというメトリクスが取得できていることを確認する。

f:id:sotoiwa:20200304025606p:plain

Grafanaにポートフォワードする。

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 8080:3000

以下のURLにアクセスし、Istioのメトリクスがいろいろ表示されることを確認する。

f:id:sotoiwa:20200304025623p:plain