ry's Tech blog

Cloud Native技術などについて書いていきます。

サービスメッシュ Linkerd

Linkerdとは

image.png

Linkerdはオープンソースのサービスメッシュで、Cloud Native Computing Foundationのメンバープロジェクトです。 現在では、Incubating projectとなっています。

Architecture

image.png

Linkerdはコントロールプレーンとデータプレーンで構成されます。

コントロールプレーンは、専用のnamespaceで実行されるサービスのセットです。 これらのサービスは、テレメトリデータの集計、ユーザー向けAPIの提供、データプレーンプロキシへの制御データの提供など、さまざまなことを実現します。

データプレーンは、各サービスインスタンスにて実行されている透過的なプロキシです。 コントロールプレーンにテレメトリを送信し、コントロールプレーンから制御信号を受信します。

  • destination

    • データプレーンの各プロキシは、このコンポーネントを使用してリクエストの送信先を検索します。

    • destinationdeploymentは、ルートごとのメトリック、再試行、およびタイムアウトに使用されるサービスプロファイル情報を取得するためにも使用されます。

  • tap

    • CLIダッシュボードからリクエストを受け取り、リクエストとレスポンスをリアルタイムで監視します。
  • identity

    • このコンポーネントは、プロキシからCSRを受け入れ、正しいIDで署名された証明書を返す認証局です。
    • これらの証明書は、開始時にプロキシによって取得され、プロキシの準備が整う前に発行する必要があります。その後、Linkerdプロキシ間の接続でmTLSを実装するために使用されます。
  • proxy-injector

    • インジェクターは、ポッドが作成されるたびにwebhookリクエストを受け取るアドミッションコントローラーです。
    • このインジェクターは、linkerd.io/inject: enabledというannotationを探し、存在すればproxyを入れます。
  • sp-validator

    • バリデーターは、保存前に新しいサービスプロファイルを検証するアドミッションコントローラーです。

Step 1: Install the CLI

# curl -sL https://run.linkerd.io/install | sh
Downloading linkerd2-cli-stable-2.6.0-linux...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   622    0   622    0     0    221      0 --:--:--  0:00:02 --:--:--   221
100 36.6M  100 36.6M    0     0   476k      0  0:01:18  0:01:18 --:--:--  567k
Download complete!

Validating checksum...
Checksum valid.

Linkerd stable-2.6.0 was successfully installed 🎉


Add the linkerd CLI to your path with:

  export PATH=$PATH:/root/.linkerd2/bin

Now run:

  linkerd check --pre                     # validate that Linkerd can be installed
  linkerd install | kubectl apply -f -    # install the control plane into the 'linkerd' namespace
  linkerd check                           # validate everything worked!
  linkerd dashboard                       # launch the dashboard

Looking for more? Visit https://linkerd.io/2/next-steps

では、使えるようにしていきます。

# vi .bash_profile
以下を追加
export PATH=$PATH:$HOME/.linkerd2/bin

# source .bash_profile

Step 2: Validate your Kubernetes cluster

次のコマンドで、kubernetesがLinkerdを動かすうえで適した環境が作れているかの検証を行います。

# linkerd check --pre
kubernetes-api
--------------
√ can initialize the client
√ can query the Kubernetes API

kubernetes-version
------------------
√ is running the minimum Kubernetes API version
√ is running the minimum kubectl version

pre-kubernetes-setup
--------------------
√ control plane namespace does not already exist
√ can create Namespaces
√ can create ClusterRoles
√ can create ClusterRoleBindings
√ can create CustomResourceDefinitions
√ can create PodSecurityPolicies
√ can create ServiceAccounts
√ can create Services
√ can create Deployments
√ can create CronJobs
√ can create ConfigMaps
√ no clock skew detected

pre-kubernetes-capability
-------------------------
√ has NET_ADMIN capability
√ has NET_RAW capability

pre-linkerd-global-resources
----------------------------
√ no ClusterRoles exist
√ no ClusterRoleBindings exist
√ no CustomResourceDefinitions exist
√ no MutatingWebhookConfigurations exist
√ no ValidatingWebhookConfigurations exist
√ no PodSecurityPolicies exist

linkerd-version
---------------
√ can determine the latest version
√ cli is up-to-date

Status check results are √

Step 3: Install Linkerd onto the cluster

それでは、Linkerdをデプロイしていきます。

# linkerd install | kubectl apply -f -
namespace/linkerd created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-identity created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-identity created
serviceaccount/linkerd-identity created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-controller created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-controller created
serviceaccount/linkerd-controller created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-destination created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-destination created
serviceaccount/linkerd-destination created
role.rbac.authorization.k8s.io/linkerd-heartbeat created
rolebinding.rbac.authorization.k8s.io/linkerd-heartbeat created
serviceaccount/linkerd-heartbeat created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-web-admin created
serviceaccount/linkerd-web created
customresourcedefinition.apiextensions.k8s.io/serviceprofiles.linkerd.io created
customresourcedefinition.apiextensions.k8s.io/trafficsplits.split.smi-spec.io created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-prometheus created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-prometheus created
serviceaccount/linkerd-prometheus created
serviceaccount/linkerd-grafana created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-proxy-injector created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-proxy-injector created
serviceaccount/linkerd-proxy-injector created
secret/linkerd-proxy-injector-tls created
mutatingwebhookconfiguration.admissionregistration.k8s.io/linkerd-proxy-injector-webhook-config created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-sp-validator created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-sp-validator created
serviceaccount/linkerd-sp-validator created
secret/linkerd-sp-validator-tls created
validatingwebhookconfiguration.admissionregistration.k8s.io/linkerd-sp-validator-webhook-config created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-tap created
clusterrole.rbac.authorization.k8s.io/linkerd-linkerd-tap-admin created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-tap created
clusterrolebinding.rbac.authorization.k8s.io/linkerd-linkerd-tap-auth-delegator created
serviceaccount/linkerd-tap created
rolebinding.rbac.authorization.k8s.io/linkerd-linkerd-tap-auth-reader created
secret/linkerd-tap-tls created
apiservice.apiregistration.k8s.io/v1alpha1.tap.linkerd.io created
podsecuritypolicy.policy/linkerd-linkerd-control-plane created
role.rbac.authorization.k8s.io/linkerd-psp created
rolebinding.rbac.authorization.k8s.io/linkerd-psp created
configmap/linkerd-config created
secret/linkerd-identity-issuer created
service/linkerd-identity created
deployment.apps/linkerd-identity created
service/linkerd-controller-api created
service/linkerd-destination created
deployment.apps/linkerd-controller created
service/linkerd-dst created
deployment.apps/linkerd-destination created
cronjob.batch/linkerd-heartbeat created
service/linkerd-web created
deployment.apps/linkerd-web created
configmap/linkerd-prometheus-config created
service/linkerd-prometheus created
deployment.apps/linkerd-prometheus created
configmap/linkerd-grafana-config created
service/linkerd-grafana created
deployment.apps/linkerd-grafana created
deployment.apps/linkerd-proxy-injector created
service/linkerd-proxy-injector created
service/linkerd-sp-validator created
deployment.apps/linkerd-sp-validator created
service/linkerd-tap created
deployment.apps/linkerd-tap created

以下のコマンドで、正常にデプロイされたかを確認します。 出力は長かったので、省略します。

# linkerd check

deploymentの状態を見てみます。

# kubectl -n linkerd get deploy
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
linkerd-controller       1/1     1            1           114s
linkerd-destination      1/1     1            1           114s
linkerd-grafana          1/1     1            1           114s
linkerd-identity         1/1     1            1           114s
linkerd-prometheus       1/1     1            1           114s
linkerd-proxy-injector   1/1     1            1           113s
linkerd-sp-validator     1/1     1            1           113s
linkerd-tap              1/1     1            1           113s
linkerd-web              1/1     1            1           114s

Step 4: Explore Linkerd

それでは、以下のコマンドでDashboardにアクセスできるようにします。

# nohup linkerd dashboard --address 127.0.0.1 -p 8000 &
Linkerd dashboard available at:
http://127.0.0.1:8000
Grafana dashboard available at:
http://127.0.0.1:8000/grafana
Opening Linkerd dashboard in the default browser
Failed to open Linkerd dashboard automatically
Visit http://127.0.0.1:8000 in your browser to view the dashboard

image.png

Step 5: Install the demo app

では、Linkerdの動きを見るために、デモのアプリケーションを動かしていきます。

# curl -sL https://run.linkerd.io/emojivoto.yml  | kubectl apply -f -
namespace/emojivoto created
serviceaccount/emoji created
serviceaccount/voting created
serviceaccount/web created
service/emoji-svc created
service/voting-svc created
service/web-svc created
deployment.apps/emoji created
deployment.apps/vote-bot created
deployment.apps/voting created
deployment.apps/web created


# kubectl get pods -n emojivoto
NAME                        READY   STATUS    RESTARTS   AGE
emoji-6b966565b5-nd59b      1/1     Running   0          73s
vote-bot-67d8555767-2w5pp   1/1     Running   0          73s
voting-675d89b7b8-w6hwb     1/1     Running   0          73s
web-859cf8f695-l6pw5        1/1     Running   0          73s
[root@gateway ~]# k get all -n emojivoto
NAME                            READY   STATUS    RESTARTS   AGE
pod/emoji-6b966565b5-nd59b      1/1     Running   0          79s
pod/vote-bot-67d8555767-2w5pp   1/1     Running   0          79s
pod/voting-675d89b7b8-w6hwb     1/1     Running   0          79s
pod/web-859cf8f695-l6pw5        1/1     Running   0          79s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/emoji-svc    ClusterIP      10.100.200.127   <none>        8080/TCP       79s
service/voting-svc   ClusterIP      10.100.200.200   <none>        8080/TCP       79s
service/web-svc      LoadBalancer   10.100.200.5     <pending>     80:32716/TCP   79s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/emoji      1/1     1            1           79s
deployment.apps/vote-bot   1/1     1            1           79s
deployment.apps/voting     1/1     1            1           79s
deployment.apps/web        1/1     1            1           79s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/emoji-6b966565b5      1         1         1       79s
replicaset.apps/vote-bot-67d8555767   1         1         1       79s
replicaset.apps/voting-675d89b7b8     1         1         1       79s
replicaset.apps/web-859cf8f695        1         1         1       79s

では、デモアプリにアクセスしていきましょう。

http://[worker node の IP]: [LoadBalancerのport]

image.png

以下のコマンドで、このapplicationをlinkerdから監視できるようにしていきます。

# kubectl get -n emojivoto deploy -o yaml | linkerd inject - | kubectl apply -f -

deployment "emoji" injected
deployment "vote-bot" injected
deployment "voting" injected
deployment "web" injected

deployment.extensions/emoji configured
deployment.extensions/vote-bot configured
deployment.extensions/voting configured
deployment.extensions/web configured

このコマンドは、emojivoto ネームスペースで実行されているすべてのデプロイメントを取得し、linkerd injectしてから、クラスターに再適用します。 linkerd injectはpodの中に以下のようなproxyコンテナを入れてくれます。

linkerd-proxy:
    Container ID:   docker://f93e85b155827ffe8fdd06e2c689784ca103ba81eb5d259c82f37edb0f4c08e7
    Image:          gcr.io/linkerd-io/proxy:stable-2.6.0
    Image ID:       docker-pullable://gcr.io/linkerd-io/proxy@sha256:633b8b3434f4229b219274c7d452335e3f93300a30d01d465dd80102a7df3a50
    Ports:          4143/TCP, 4191/TCP
    Host Ports:     0/TCP, 0/TCP
    State:          Running
      Started:      Sat, 07 Dec 2019 18:20:39 +0900
    Ready:          True
    Restart Count:  0
    Liveness:       http-get http://:4191/metrics delay=10s timeout=1s period=10s #success=1 #failure=3
    Readiness:      http-get http://:4191/ready delay=2s timeout=1s period=10s #success=1 #failure=3
    Environment:
      LINKERD2_PROXY_LOG:                           warn,linkerd2_proxy=info
      LINKERD2_PROXY_DESTINATION_SVC_ADDR:          linkerd-dst.linkerd.svc.cluster.local:8086
      LINKERD2_PROXY_CONTROL_LISTEN_ADDR:           0.0.0.0:4190
      LINKERD2_PROXY_ADMIN_LISTEN_ADDR:             0.0.0.0:4191
      LINKERD2_PROXY_OUTBOUND_LISTEN_ADDR:          127.0.0.1:4140
      LINKERD2_PROXY_INBOUND_LISTEN_ADDR:           0.0.0.0:4143
      LINKERD2_PROXY_DESTINATION_GET_SUFFIXES:      svc.cluster.local.
      LINKERD2_PROXY_DESTINATION_PROFILE_SUFFIXES:  svc.cluster.local.
      LINKERD2_PROXY_INBOUND_ACCEPT_KEEPALIVE:      10000ms
      LINKERD2_PROXY_OUTBOUND_CONNECT_KEEPALIVE:    10000ms
      _pod_ns:                                      emojivoto (v1:metadata.namespace)
      LINKERD2_PROXY_DESTINATION_CONTEXT:           ns:$(_pod_ns)
      LINKERD2_PROXY_IDENTITY_DIR:                  /var/run/linkerd/identity/end-entity
      LINKERD2_PROXY_IDENTITY_TRUST_ANCHORS:        -----BEGIN CERTIFICATE-----
                                                    MIIBhDCCASmgAwIBAgIBATAKBggqhkjOPQQDAjApMScwJQYDVQQDEx5pZGVudGl0
                                                    eS5saW5rZXJkLmNsdXN0ZXIubG9jYWwwHhcNMTkxMjA2MDUxMTA3WhcNMjAxMjA1
                                                    MDUxMTI3WjApMScwJQYDVQQDEx5pZGVudGl0eS5saW5rZXJkLmNsdXN0ZXIubG9j
                                                    YWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQHTUOU5YfGgDl87w3QU+e/Nag5
                                                    H3KVLk24Fp0uPSNB407gJ655kI+/W4M3f766aufGZR4UE6p6bo2TwcBxMGIHo0Iw
                                                    QDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
                                                    MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAIfCEwHV0iBh3HBY
                                                    JNchSjex3/EweFbzUBYX733GSrocAiEA4Kpl7iTGuSUARydgfXnMknVDNi1AHhv7
                                                    iUciHX8oFVw=
                                                    -----END CERTIFICATE-----

      LINKERD2_PROXY_IDENTITY_TOKEN_FILE:           /var/run/secrets/kubernetes.io/serviceaccount/token
      LINKERD2_PROXY_IDENTITY_SVC_ADDR:             linkerd-identity.linkerd.svc.cluster.local:8080
      _pod_sa:                                       (v1:spec.serviceAccountName)
      _l5d_ns:                                      linkerd
      _l5d_trustdomain:                             cluster.local
      LINKERD2_PROXY_IDENTITY_LOCAL_NAME:           $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
      LINKERD2_PROXY_IDENTITY_SVC_NAME:             linkerd-identity.$(_l5d_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
      LINKERD2_PROXY_DESTINATION_SVC_NAME:          linkerd-destination.$(_l5d_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
      LINKERD2_PROXY_TAP_SVC_NAME:                  linkerd-tap.$(_l5d_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
    Mounts:
      /var/run/linkerd/identity/end-entity from linkerd-identity-end-entity (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from emoji-token-whvv2 (ro)

これをすることで、DashboardNamespacepaneでは通信の成功率や、mesh数を見ることができるようになります。

image.png

image.png

しっかり、データプレーンで機能しているのかを確認する場合は以下のコマンドを打ちます。

# linkerd -n emojivoto check --proxy
kubernetes-api
--------------
√ can initialize the client
√ can query the Kubernetes API

kubernetes-version
------------------
√ is running the minimum Kubernetes API version
√ is running the minimum kubectl version

linkerd-config
--------------
√ control plane Namespace exists
√ control plane ClusterRoles exist
√ control plane ClusterRoleBindings exist
√ control plane ServiceAccounts exist
√ control plane CustomResourceDefinitions exist
√ control plane MutatingWebhookConfigurations exist
√ control plane ValidatingWebhookConfigurations exist
√ control plane PodSecurityPolicies exist

linkerd-existence
-----------------
√ 'linkerd-config' config map exists
√ heartbeat ServiceAccount exist
√ control plane replica sets are ready
√ no unschedulable pods
√ controller pod is running
√ can initialize the client
√ can query the control plane API

linkerd-api
-----------
√ control plane pods are ready
√ control plane self-check
√ [kubernetes] control plane can talk to Kubernetes
√ [prometheus] control plane can talk to Prometheus
√ no invalid service profiles


linkerd-version
---------------
√ can determine the latest version
√ cli is up-to-date

linkerd-data-plane
------------------
√ data plane namespace exists
√ data plane proxies are ready
√ data plane proxy metrics are present in Prometheus
√ data plane is up-to-date
√ data plane and cli versions match

Status check results are √

Step 6: Watch it run

GUI上に行きます。

Namespacepaneから、emojivotoを選択してみます。

image.png

各サービスの結びつきや、詳細情報を見ることができます。

Deploymentにある各componentを押すことで、個々の詳細な関係も見ることができます。

image.png

終わりに

とてもとっつきやすいservice meshツールなのではないかなと触っていて感じました。

この記事がLinkerdの最初のとっかかりの助けになればと思います。

読んでいただき、ありがとうございました。