前書き
首題の通り、マイクロサービスを実現する上で欠かせないサービスメッシュをLinkerdで実現し、各マイクロサービスの分散トレースをZipkinで実現します。
説明もそこそこに、とにかく早く構築してみたい方は、「構築手順」の章から進めてください。
Linkerdについて
Linkerdとは、buoyant社が開発したサービスメッシュOSSツールで、「本番環境として世界で最も使われているサービスメッシュ」と言われています。(ソース)
buoyant社はLinkerdとは別に、kubernetes専用のサービスメッシュConduitを発表しました。
ConduitはLinkerdの後継ではなく、Linkerdの開発とサポートは継続されるものの、いずれはConduitがメインとなると言われています。(ソース同上)
サービスメッシュの構成方法は主に、per nodeとper pod(サイドカー)方式があります。
Linkerdは両方対応可能ですが、今回はper nodeで実装します。
per nodeの場合、多数のpodを配置してもコンポーネントが増加することはないため、一般的にはper podよりもリソースを抑えることが出来ると言われています(が、per nodeのLinkerd自体のリソース使用量は小さくなく(ソース同上)、ultra-low-resourceな環境では別の選択肢を考える必要があります。)
上図では、pod4にあるサービスからpod8にあるサービスへリクエストを送る様子を描いています。
pod4はnode 1のLinkerdにリクエストを送ります。node1のLinkerdはdtabルールに従って、node2のLinkerdにリクエストを送りnode2のLinkerdはpod8のサービスに送ります。
※node1のLinkerdとnode2のLinkerdを繋ぐnamerdについて
manerdはdtabs(Delegation tables)によるルーティング情報を中央管理し、Linkerdからルーティング情報が参照されます。
上図のようにnodeまたぎでLinkerdのサービスメッシュを実現するためには、namerdが必要です。
Zipkinについて
zipkinは分散トレーシングツールで、マイクロサービス間のレイテンシーを収集/可視化することができます。(Zipkin公式ホームページ)
Zipkinは以下のアーキテクチャーで動作します。
Zipkinをkubernetesのpodとして動作させるために、serviceとしてcollectorとUIの2つが必要であることがわかります。
構築手順
GCP(GKE)の設定
GCP(GKE)のクラスターが作成されている前提で、以下コマンドを実行し、認証/kubectlとdockerの向き先を設定します。
##ログイン
$ gcloud auth login
##プロジェクト一覧
$ gcloud projects list
##プロジェクト変更
$ gcloud config set project soty-naky-0113
## クラスター一覧
$ gcloud container clusters list
## クラスター設定
$ gcloud container clusters get-credentials NAME --zone ZONE
## kubectlの構成の確認
$ kubectl config current-context
## dockerの構成
$ gcloud auth configure-docker
Zipkinの導入
以下のファイルを用意します。
・zipkin-replicationcontroller.yaml :podのyaml
・zipkin-collecter-service.yaml :Zipkinのcollecterのservice.yaml
・zipkin-ui-service.yaml :UIのservice.yaml
・zipkin-ingress.yaml :ZipkinのUIへ(httpsで)アクセスするためのingress.yaml
・各種tlsファイル :ingressへhttpsプロトコルで接続するために作成する自己証明のファイル群
・zipkin-secret.yaml :Ingressの自己証明書のsecret.yaml
それぞれのyamlファイルの中身は以下の通りです。
apiVersion: v1
kind: ReplicationController
metadata:
name: zipkin
spec:
replicas: 1
selector:
app: zipkin
template:
metadata:
name: zipkin
labels:
app: zipkin
spec:
containers:
- name: zipkin
image: openzipkin/zipkin:1.20
env:
- name: SCRIBE_ENABLED
value: "true"
ports:
- name: scribe
containerPort: 9410
- name: http
containerPort: 9411
apiVersion: v1
kind: Service
metadata:
labels:
name: zipkin-collector
name: zipkin-collector
spec:
type: ClusterIP
selector:
app: zipkin
ports:
- name: scribe
port: 9410
targetPort: 9410
apiVersion: v1
kind: Service
metadata:
name: zipkin-ui
labels:
name: zipkin
spec:
type: NodePort
selector:
app: zipkin
ports:
- name: https
port: 443
targetPort: 9411
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: zipkin-ingress
namespace: default
annotations:
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- secretName: zipkin-tls
backend:
serviceName: zipkin-ui
servicePort: 443
apiVersion: v1
data:
tls.crt: LS0tLS1...... #生成した.crtをbase64でエンコードした値を入力
tls.key: LS0tLS1...... #生成した.keyをbase64でエンコードした値を入力
kind: Secret
metadata:
name: zipkin-tls
namespace: default
type: Opaque
上記tls.crt:
とtls.key:
については、以下の手順で作成します。
・自己証明ファイル群を作成します。どの方法でも構いませんが、私はこちらのwebサイトを参考に、自己証明ファイル群を作成しました。
・作成した.crt
ファイルと.key
ファイル(以下例ではそれぞれserver.crtとserver.key)をbase64でエンコードします。以下コマンドを実行して、その標準出力をそれぞれtls.crt:
とtls.key:
の値として貼り付けます。
## server.crtとserver.keyファイルを、それぞれbase64エンコードするコマンド
$ cat server.crt | base64
$ cat server.key | base64
ここまで作成したファイル群をGKEに適用します。
まず以下コマンドを実行して、先にSecretを作成します。
$ kubectl create -f zipkin-secret.yaml
secret "zipkin-tls" created
pod(replicationcontroller)を作成します。
$ kubectl create -f zipkin-replicationcontroller.yaml
serviceを作成します。
$ kubectl create -f zipkin-ui-service.yaml zipkin-collecter-service.yaml
ingressを作成します。
$ kubectl create -f zipkin-ingress.yaml
アクセスポイントを確認します。以下コマンドでingressに割り振られているIPアドレスを確認します。(IPアドレスの割り振りには時間がかかる場合があります)
$ kubectl get ingress zipkin-ingress
NAME HOSTS ADDRESS PORTS AGE
zipkin-ingress * 35.xxx.xxx.xxx 80, 443 10m
割り振られたアドレス(35.xxx.xxx.xxx)にhttpsでアクセスします。
(Ingressのannotations:
の設定でkubernetes.io/ingress.allow-http: "false"
としているため、httpプロトコルではアクセスできないことも併せて確認します)
以上でZipkinの導入は完了です。
Linkerdの導入
Linkerdを導入するにあたり、以下のファイルを用意します。
・linkerd-daemonset.yaml :linkerdをdaemonsetとしてデプロイするyaml
・linkerd-configmap.yaml :linkerdの設定ファイルとなるconfig.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
labels:
app: l5d
name: l5d
spec:
template:
metadata:
labels:
app: l5d
spec:
volumes:
- name: l5d-config
configMap:
name: "l5d-config"
containers:
- name: l5d
image: mycluster.icp:8500/default/linkerd:1.3.6
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
args:
- /io.buoyant/linkerd/config/config.yaml
ports:
- name: outgoing
containerPort: 4140
hostPort: 4140
- name: incoming
containerPort: 4141
- name: admin
containerPort: 9990
volumeMounts:
- name: "l5d-config"
mountPath: "/io.buoyant/linkerd/config"
readOnly: true
- name: kubectl
image: mycluster.icp:8500/default/kubectl:v1.8.5
args:
- "proxy"
- "-p"
- "8001"
apiVersion: v1
kind: ConfigMap
metadata:
name: l5d-config
data:
config.yaml: |-
admin:
ip: 0.0.0.0
port: 9990
namers:
- kind: io.l5d.k8s
host: localhost
port: 8001
telemetry:
- kind: io.l5d.prometheus
- kind: io.l5d.zipkin
host: zipkin-collector.default.svc.cluster.local
port: 9410
sampleRate: 1.0
- kind: io.l5d.recentRequests
sampleRate: 0.25
usage:
orgId: linkerd-examples-daemonset-zipkin
routers:
- protocol: http
label: outgoing
dtab: |
/srv => /#/io.l5d.k8s/default/http;
/host => /srv;
/svc => /host;
/host/world => /srv/world-v1;
interpreter:
kind: default
transformers:
- kind: io.l5d.k8s.daemonset
namespace: default
port: incoming
service: l5d
servers:
- port: 4140
ip: 0.0.0.0
service:
responseClassifier:
kind: io.l5d.http.retryableRead5XX
- protocol: http
label: incoming
dtab: |
/srv => /#/io.l5d.k8s/default/http;
/host => /srv;
/svc => /host;
/host/world => /srv/world-v1;
interpreter:
kind: default
transformers:
- kind: io.l5d.k8s.localnode
servers:
- port: 4141
ip: 0.0.0.0
Linkerdが取得したサービスメッシュのデータは、config.yaml内で定義した以下の箇所でzipkinに渡しています。
telemetry:
- kind: io.l5d.prometheus
- kind: io.l5d.zipkin
host: zipkin-collector.default.svc.cluster.local
port: 9410
sampleRate: 1.0
configmapを作成します。
$ kubectl create -f linkerd-configmap.yaml
Linkerdをdaemonsetとしてデプロイします。
$ kubectl create -f linkerd-daemonset.yaml
デプロイしたpodが正常に稼働していることを確認します。
$ kubectl get po -o wide -l app=l5d
NAME READY STATUS RESTARTS AGE IP NODE
l5d-22rkl 2/2 Running 0 5m 10.8.2.8 gke-cluster-1-default-pool-c4146799-hc7z
l5d-tcfhc 2/2 Running 0 5m 10.8.1.8 gke-cluster-1-default-pool-c4146799-69xf
l5d-xmv7z 2/2 Running 0 5m 10.8.0.9 gke-cluster-1-default-pool-c4146799-tps1
以上でLinkerdの導入は完了です。
サンプルアプリケーションの導入
あとはアプリケーションをデプロイし、動作させることでZipkinのインターフェースから分散トレースを可視化することができます。
※6/8までに詳しい手順をアップデート予定です