- 2020年1月時点での事例のため情報が古い箇所がありますが随時更新していきます。
マイクロサービスアーキテクチャとは
モノリシックシックアーキテクチャ(一枚岩、巨大なコードベース)のように一つのコードが複数の環境に影響を及ばさないように適切なサイズにアプリケーションを分割すること。
メリット
- 適切なサイズのコードベースで開発できる
- チームを適切なサイズに保つことができる
- 特定のコードベースに所属しない(フレームワーク)
デメリット
- パフォーマンスの低下
マイクロサービスの課題
依存関係の解決
適切にロードバランシングする必要がある
通信の可観測性
あるサービスで起きた障害がどの程度の影響を及ぼすのか考える必要がある
サービス間通信が正常に行われているか、サービス間の通信がどの程度行われたかを観測する必要がある
認証・認可
複数を協調してサービスを実装する際に特定のサービスが接続するサービスを制限したり特定の API を呼び出す権限を制限したりすることが必要になるケースがあるので各マイクロサービス間も外部サービスの連携と同じく、暗号鍵や権限管理などを正しく行う必要がある
障害の分離
マイクロサービス間の通信はプロセスによる通信よりも失敗する可能性が高くなるためにリトライ回数やタイムアウトの設定、リトライ上限を正しく設定する必要がある
サービスメッシュとは
マイクロサービスアーキテクチャによって生じる課題に対応するためのデザインパターン
各マイクロサービスのサイドカーとしてサービスプロキシをデプロイする
サイドカーとしてデプロイする理由は各開発言語に左右されないこととアプリケーション側でリトライ処理やサーキットブレーカーのコードを記述する必要やメンテナンスコストがないため
サービス間の全ての通信はデータプレーンであるサービスプロキシを経由しておこなう
できること
- リトライ、 タイムアウトなどの通信の障害への対策
- 分散トレーシングによるネットワークレベルの情報収集、サービス監視、ログ収集
できないこと
- ネットワーク以外の対応
- サービスのロールバック
データプレーン
実際に通信の制御を行うコンポーネント
サービスメッシュでは Envoy などのサービスプロキシに相当
コントロールプレーン
データプレーンで用いる設定を出力しデータプレーンを制御するコンポーネント
データプレーンが定期的、リアルタイムでコントロールプレーンに問い合わせを行い変更があれば設定を変更する
複数のデータプレーンの設定を一度に更新することができる
Istio
サービスメッシュのデファクトスタンダードなコントロールプレーン
主な機能
- ネットワークトラフィックの管理
- セキュリティ
- 監視とロギング
- OpenTracing
アーキテクチャ
コントロールプレーン
- Pilot
- Mixer
- Galley
- Citadel
Pilot
- トラフィックの送信先のサービスディスカバリ
- トラフィックに関する機能
- Blue/Green, Canary
- タイムアウト、リトライの制御
- istio-proxy に設定情報を提供
Mixer
- データプレーンにあるメトリクスやログを収集し Stackdriver, Prometheus に送信
- サービスが別のサービスに対して通信する際のアクセスコントロール(認証、認可、レート制限)
- トラフィック後に Envoy から送られてきたテレメトリを受信
Citadel
- 認証局
- セキュリティ
- rbac 設定
- kubernetes のアクセス制御と連携
Galley
- istio に対する管理操作を受け付けを行いバリデーション
Polocy
Sidecar Injector
- Deployment に istio-proxy を追加
データプレーン
トラフィックの管理 Envoy を拡張したサービスプロキシ istio-proxy
GKE における istio 関連の Workload
$ kubectl get deploy -n istio-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE
grafana 1 1 1 1
istio-citadel 1 1 1 1
istio-galley 1 1 1 1
istio-pilot 1 1 1 1
istio-policy 1 1 1 1
istio-sidecar-injector 1 1 1 1
istio-telemetry 1 1 1 1
kiali 1 1 1 1
prometheus 1 1 1 1
Envoy
サービスプロキシ、Istio などに採用される代表的なデータプレーン
data plane api によってコントロールプレーンから設定を読み込む grpc でやりとりする xds api
- 様々なプロトコルのサポート
- http/2
- gRPC
- 高度なロードバランシング
- パッシブヘルスチェック
- リクエストのリトライ、タイムアウト、レートリミット
- サーキットブレーカー
- 可観測性
- リクエストの流量や回数
- タイムアウトやリトライ、サーキットブレーカが発動した回数
- 動的な設定の変更
- オンラインで設定の更新
静的な Envoy の設定
static_resources:
listeners:
- name: listener_0
address:
socket_address:
- address: 0.0.0.0
- port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
route_config:
name: route
virtual_hosts:
- name: backend
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: service1
clusters:
- name: service1
load_assignment:
cluster_name: service1
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
- address: sevice1.example.com
- port_value: 80
コントロールプレーンを使用した Envoy の設定
EDS
clusters:
- name: service1
type: EDS
eds_cluster_config:
eds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: xds_cluster
- name: xds_cluster
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
- address: 127.0.0.1
- port_value: 20000
xDS API
Envoy がコントロールプレーンから設定を取得するための API
API スキーマに Protobuf, エンドポイントに gRPC(bidi) or REST
envoy の設定を動的に取得するためのサービス
- Endpoint Discovery Service (EDS)
- Cluster Discovery Service (CDS)
- Route Discovery Service (RDS)
- Listener Discovery Service (LDS)
- Health Discovery Service (HDS)
- Aggregated Discovery Service (ADS)
- Secret Discovery Service (SDS)
GKE に導入(コマンドラインベース)
構成例
# Gateways Configuration, refer to the charts/gateways/values.yaml
# for detailed configuration
#
gateways:
enabled: false
# sidecar-injector webhook configuration, refer to the
# charts/sidecarInjectorWebhook/values.yaml for detailed configuration
#
sidecarInjectorWebhook:
enabled: true
# galley configuration, refer to charts/galley/values.yaml
# for detailed configuration
#
galley:
enabled: true
# mixer configuration
#
# @see charts/mixer/values.yaml for all values
mixer:
policy:
# if policy is enabled the global.disablePolicyChecks has affect.
enabled: true
telemetry:
enabled: true
#
# pilot configuration
#
# @see charts/pilot/values.yaml
pilot:
enabled: true
# security configuration
#
security:
enabled: true
# nodeagent configuration
#
nodeagent:
enabled: false
# addon grafana configuration
#
grafana:
enabled: true
security:
enabled: true
# addon prometheus configuration
#
prometheus:
enabled: true
# addon jaeger tracing configuration
#
tracing:
enabled: false
# addon kiali tracing configuration
#
kiali:
enabled: true
# addon certmanager configuration
#
certmanager:
enabled: false
手順
$ curl -L https://git.io/getLatestIstio | sh -
$ cd istio-LATEST-VERSION
$ kubectl create namespace istio-system
$ helm template install/kubernetes/helm/istio-init --name istio-init --namespace istio-system | kubectl apply -f -
$ PASSWORD=$(head -c 12 /dev/urandom | shasum| cut -d' ' -f1)
$ kubectl -n istio-system create secret generic grafana --from-literal=username=admin --from-literal=passphrase="$PASSWORD"
パスワードの確認
$ kubectl get secret -n istio-system grafana -o jsonpath="{.data.passphrase}" | base64 --decode ; echo
$ helm template --namespace istio-system install/kubernetes/helm/istio > istio.yaml
$ KIALI_USERNAME=$(read '?Kiali Username: ' uval && echo -n $uval | base64)
$ KIALI_PASSPHRASE=$(read -s "?Kiali Passphrase: " pval && echo -n $pval | base64)
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: kiali
namespace: $NAMESPACE
labels:
app: kiali
type: Opaque
data:
username: $KIALI_USERNAME
passphrase: $KIALI_PASSPHRASE
EOF
$ kubectl patch svc kiali -n istio-system -p '{"spec": {"type": "LoadBalancer"}}'
$ kubectl patch svc grafana -n istio-system -p '{"spec": {"type": "LoadBalancer"}}'
Istio によるトラフィック制御
- VirtualService
- ServiceEntry
- DestinationRule
- Sidecar
VirtualService
リトライやタイムアウトの設定
ServiceEntry
クラスタ外部にある API に対してリクエストする際の設定
DestinationRule
トラフィックが Pod に届くまでの振る舞いを設定
サーキットブレーカー, ロードバランシング, コネクションプーリング
Sidecar
特定の Envoy に対する設定
Sidecar Injection の有効化
Pod 起動時に自動的に Sidecar を注入
有効化
$ kubectl label namespace {YOUR_NAMESPACE} istio-injection=enabled
無効化
$ kubectl label namespace {YOUR_NAMESPACE} istio-injection-
設定の確認
$ kubectl get namespaces -L istio-injection
マニフェスト例
Retry, Timeout
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- service-a
http:
- route:
- destination:
host: service-a
retries:
attempts: 5
perTryTimeout: 2s
retryOn: 5xx
timeout: 120s
Fault Injection
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- service-a
http:
- route:
- destination:
host: service-a
fault:
delay:
percent: 50
fixedDelay: 5s
Circuit Breaker
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: circuit-breaker
spec:
host: service-c
subsets:
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http2MaxRequests: 1024
maxRequestsPerConnection: 10
outlierDetection:
consecutiveErrors: 7
interval: 5m
baseEjectionTime: 3m
maxEjectionPercent: 100
Destination Rule | 役割 |
---|---|
spec.trafficPolicy.connectionPool.tcp | TCPのコネクションプール |
maxConnections | HTTP/TCPの最大コネクション数 |
connectTimeout | TCPのタイムアウト |
tcpKeepalive | ソケットにkeepaliveを適用するか |
spec.trafficPolicy.connectionPool.http | HTTPのコネクションプール |
http1MaxRequests | 保留するリクエスト最大数 |
http2MaxRequests | バックエンドへの要求最大数 |
maxRequestsPerConnection | バックエンドに対するコネクションごとのリクエストの最大数 |
maxRetries | リトライの最大数 |
spec.trafficPolicy.outlinerDetection | 異常値の閾値とその時の挙動を定義 |
consecutiveErrors | 継続した障害だと判定される閾値 |
Interval | 解析を行う間隔 |
baseEjectionTime | consecutiveErrorsの上限を越したときに、ホストが即時エラーを返す最小期間 |