Istio入門

2019-01-15

Istio についてまとめる。

概要

非常に大規模なハイブリッド・マルチクラウドにおいて、DevOpsチームのオペレータはマイクロサービスを展開・管理する。
Istio は サービスメッシュ によりオペレータにかかる負荷を軽減し、マイクロサービス間接続・保護・制御・監視をサポートする統一された方法を提供する。

参考

  • Control Plane / istiod として 1 バイナリにまとめられている
    • Mixer : Envoy を通して各サービスのデータを収集し、その情報を元にアクセスコントロールやサービスメッシュに渡る制御を行う。
    • Pilot : サービスディスカバリと高度なトラフィックマネジメント(A/Bテスト、カナリアデプロイなど)を提供する。
    • Galley : Control Planeを代表してユーザー認証されたIstio APIを提供する。
    • Citadel: サービス間とエンドユーザー認証を行う。
  • Data Plane
    • Proxy : Envoy を使って レイヤー4/7 のイン・アウト両方のサービスメッシュを提供し、 Pod に Sidecarとしてインジェクションされる。

サービスメッシュ

サービスメッシュはマイクロサービス間のネットワークとそれらに相互作業し、複雑さの理解と管理をサポートする。
その機能には、サービスディスカバリ・負荷分散・障害回復・メトリクス・監視が含まれ、さらに、A/Bテスト・カナリアリリース・レート制御・アクセス制御・エンドツーエンド認証など複雑な運用機能も有する。
Istio はマイクロサービスにサイドカープロキシを構成することで、すべてのネットワーク通信をインターセプトすることによりこの機能を提供する。

  • HTTP、gRPC、WebSocket、およびTCPトラフィックの自動負荷分散
  • 豊富なルーティングルール、再試行、フェイルオーバー、およびフォールトインジェクションによるトラフィック動作のきめ細かい制御
  • アクセス制御、レート制限、およびクォータをサポートするプラグ可能なポリシーレイヤーと構成 API
  • クラスターの入力と出力を含む、クラスター内のすべてのトラフィックの自動メトリック、ログ、およびトレース
  • 強力なIDベースの認証と承認により、クラスター内のサービス間通信を保護

Istio のコア機能

  • トラフィック管理
    • サーキットブレーカー・タイムアウト・リトライなどのサービスレベルの属性設定の簡素化
    • A/Bテスト・カナリアリリース・パーセンテージベースのトラフィック分割を使用した段階的なリリースなどの多様なリリース方法の提供
  • セキュリティ
    • マイクロサービス間通信の認証・認可・暗号化の管理
    • アプリケーションに変更無く、さまざまなプロトコル・ランタイムにわたって一貫したポリシー適用
  • 可観測性
    • トラフィックのトレース・監視およびログ機能による問題の迅速かつ効果的な検出
    • カスタムダッシュボードによるサービスのパフォーマンスを可視化

ローカル環境構築

Homebrew で構築できるものは以下。

$ brew install awscli
$ brew install terraform
$ brew install kubernetes-cli
$ brew install kubernetes-helm
$ brew install helmfile
$ helm plugin install https://github.com/databus23/helm-diff --version master

Istio のコマンドライン資材の設定は以下。

$ cd
$ curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.3.1 sh -
$ cd istio-1.3.1
$ export PATH=$PWD/bin:$PATH
$ istioctl verify-install

k8s 環境構築

k8s クラスタは構築されている前提。

Tiller 構築

$ kubectl apply -f ~/istio-1.3.1/install/kubernetes/helm/helm-service-account.yaml # tiller の Service Account 作成
$ helm init --history-max 200 --service-account tiller                             # tiller の作成
$ kubectl get all --all-namespaces -o wide | grep tiller | wc -l                   # tiller の構築を確認
       4

istio-init

$ helm install ~/istio-1.3.1/install/kubernetes/helm/istio-init --name istio-init --namespace istio-system
$ kubectl get crds | grep 'istio.io' | wc -l
      23
$ helm ls --all                              # 確認2
NAME      	REVISION	UPDATED                 	STATUS  	CHART           	APP VERSION	NAMESPACE
istio-init	1       	Thu Oct  3 21:02:53 2019	DEPLOYED	istio-init-1.3.1	1.3.1      	istio-system

Istio の構築(デモ版)

$ helm install ~/istio-1.3.1/install/kubernetes/helm/istio --name istio --namespace istio-system \
      --values ~/istio-1.3.1/install/kubernetes/helm/istio/values-istio-demo.yaml # Istio 構築
$ helm install ~/istio-1.3.1/install/kubernetes/helm/istio --name istio --namespace istio-system # Istio 構築
$ kubectl label namespace default istio-injection=enabled                         # サイドカーを自動でつける設定
$ kubectl get namespace -L istio-injection                                        # 確認
$ kubectl apply -f <your-application>.yaml                                        # アプリのデプロイ

上記では default namespace に istio-injection=enabled ラベルを付与して自動でサイドカー( envoy )インジェクションするように設定している。
サイドカーインジェクションを有効にしたいネームスペースには istio-injection=enabled ラベルを付与すべし。
なお、自動でサイドカーインジェクションされるための条件は ここ

以降、helm で構築された Istio 以外の主要コンポーネントについて確認していく。
なお、管理画面へのアクセスは port-forward を利用する。
セキュリティが気になる人は kauthproxy のようなものを利用してもいいかもしれない。

Prometheus

$ kubectl -n istio-system get pod -l app=prometheus                          # Pod 名を確認
NAME                          READY   STATUS    RESTARTS   AGE
prometheus-776fdf7479-zhqbc   1/1     Running   0          7m15s
$ kubectl -n istio-system get svc -l app=prometheus                          # ポートを確認
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
prometheus   ClusterIP   172.20.55.63   <none>        9090/TCP   12m
$ kubectl -n istio-system port-forward prometheus-776fdf7479-zhqbc 9090:9090 # port forward
$ curl http://localhost:9090                                                 # ブラウザでアクセス

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

Grafana

$ kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000 # port forward
$ curl http://localhost:3000/dashboard/db/istio-mesh-dashboard

Kiali

まずはユーザ/パスワードを作成して secret を適用する。
createDemoSecret: true に設定した場合、 ID/Pass は admin/admin )

$ KIALI_USERNAME=$(read -p 'Kiali Username: ' uval && echo -n $uval | base64)
Kiali Username: # ユーザ名を入力する
$ KIALI_PASSPHRASE=$(read -p 'Kiali Passphrase: ' pval && echo -n $pval | base64)
Kiali Passphrase: # パスワードを入力する
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: kiali
  namespace: istio-system
  labels:
    app: kiali
type: Opaque
data:
  username: $KIALI_USERNAME
  passphrase: $KIALI_PASSPHRASE
EOF

以下でアクセスして、上記で作成したユーザ/パスワードを利用する。

$ kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=kiali -o jsonpath='{.items[0].metadata.name}') 20001:20001 # port forward
$ curl http://localhost:20001/kiali/console

Istio Ingress Gateway

従来、Kubernetes は外部からクラスタに入るトラフィックを処理するために Ingress Controller 使用していた。Istioを使用する場合、これはもはや当てはまない。
Istio は、使い慣れた Ingress リソースを新しい Gateway および VirtualServices リソースに置き換えた。
これらは連携して動作し、トラフィックをメッシュにルーティングする。
メッシュ内では、サービスはクラスタローカルサービス名で相互にアクセスできるため、ゲートウェイは必要ない。
以下のように動作する。

  1. クライアントは特定のポートにリクエストを発行する
  2. LoadBalancer がクラスタ内の woker node へトラフィックをフォワードする
  • ここでの LoadBalancer は状況( IP が必要 or Nor )によって NodePort でもよい
    • 例えば AWS の Autoscaling Group だと IP は意識しなくていいので NodePort でよい
  • Istio IngressGateway へトラフィックを流すためだけの役割で、手動もしくは自動で設定する
  1. Istio IngressGateway の Service/Deployment(Pod) が LoadBalancer からのリクエストを受ける
  • Istio IngressGateway は type を LoadBalancer/NodePort/ClusterIP から選択できるため、 NodePort として前段の LoadBalancer を省略することもできる
  1. Istio IngressGateway の Pod が Gateway および VirtualService の設定に応じてリクエストを処理する
  • Gateway では、ポート、プロトコル、および証明書の設定を行う
  • VirtualService は、 アプリケーションの Service へリクエストをルーティングするための設定を行う

Istio IngressGateway の他に Istio EgressGateway (外部への HTTP(S) 通信用)、 Istio IblGateway (クラスタ内 HTTP(S)/gRPC 通信用)が利用できる。
なお、 クラスタ外部サービス( API や DB )へのアクセスは ServiceEntry を設定しなければアクセスできない。( 参考

解説

Helm から構築する Istio は、 Istio では飽き足らず、様々な機能を構築することが可能。

  • certmanager
    • TLSの証明書を自動で生成し管理するK8sのアドオン
  • galley
    • Istio のコンポーネント
  • gateways
    • Istio のコンポーネント
    • Istio IngressGateway/IblGateway/EgressGateway
  • global
    • Istio の共通設定
  • grafana
    • 可視化ツール、 Prometheus とともに
  • istio_cni
    • CNI (Container Network Interface) の設定
  • istiocoredns
    • Istio サービスの namespace で利用できるDNS の設定
    • kube-dns (CoreDNS) のサブドメインとして可動させたりできる
  • kiali
    • リクエストのトレースを行い、以下の機能を提供する
      • 健全性: アプリケーション、サービス、またはワークロードの問題を素早く特定します。
      • トポロジー: Kiali グラフを使用して、アプリケーション、サービス、またはワークロードの通信方法を可視化します。
      • メトリクス: 事前定義済みのメトリクスダッシュボードを使用すると、Go、Node.js、Quarkus、Spring Boot、Thorntail、および Vert.x のサービスメッシュおよびアプリケーションのパフォーマンスをチャートに表示できます。また、独自のカスタムダッシュボードを作成することもできます。
      • トレース: Jaeger との統合により、アプリケーションを構成するさまざまなマイクロサービスで要求のパスを追跡できます。
      • 検証: 最も一般的な Istio オブジェクト (宛先ルール、サービスエントリー、仮想サービスなど) で高度な検証を実行します。
      • 設定: ウィザードを使用するか、または Kiali コンソールの YAML エディターを直接使用して、Istio ルーティング設定を作成し、更新し、削除できるオプションの機能です。
  • mixer
    • Istio のコンポーネント
  • nodeagent
    • ノード単位のセキュリティ機能・設定を提供するエージェント
  • pilot
    • Istio のコンポーネント
  • prometheus
    • メトリクス監視ツール
  • security
    • セキュリティの設定
  • sidecarInjectorWebhook
  • tracing
    • 各 Service/Deployment でのリクエストのレイテンシを追跡する
    • Jeager

設定については ここ を参照。

ちょっと設定見てみる

.
├── README.md
├── helmfile.yaml
└── istio-values.yaml
repositories: # 利用する helm リポジトリ
  - name: elastic
    url: https://helm.elastic.co
  - name: kiwigrid
    url: https://kiwigrid.github.io
  - name: codecentric
    url: https://codecentric.github.io/helm-charts

releases: # 利用する helm chart 単位で name をつけて設定する
          # values.yaml ファイルにて設定を外出しできるので環境毎に作成できる
  # 前提として、istio-init が完了している必要がある
  # https://github.com/istio/istio/tree/master/install/kubernetes/helm/istio
  - name: istio
    namespace: istio-system
    chart: istio.io/istio
    values:
    - istio-values.yaml

以下 Istio の valies.yaml ファイルの例。

gateways:
  enabled: true
  istio-ingressgateway:
    type: NodePort

global:
  proxy:
    autoInject: disabled

grafana:
  enabled: true
  ingress:
    enabled: true
    hosts:
      - istio-grafana.sample.com
  contextPath: /
  security:
    enabled: true

kiali:
  enabled: true
  ingress:
    enabled: true
    hosts:
      - istio-kiali.sample.com
  dashboard:
    jaegerURL: https://istio-jaeger.sample.com
  createDemoSecret: true

tracing:
  enabled: true
  ingress:
    enabled: true
    hosts:
      - istio-jaeger.sample.com
  contextPath: /
  jaeger:
    persist: true
    accessMode: ReadWriteOnce

参考

おすすめ書籍

おすすめ記事