ry's Tech blog

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

入門 OpenServiceMesh

OpenServiceMeshとは

マイクロソフト製で、Kubernetes対応のサービスメッシュ(Service Mesh)を実現するOSSです。

特徴としては、Service Mesh Interface(SMI)対応とEnvoyを採用しているという点でしょうか。

では実際にどんな感じなのか見ていきたいと思います!

Install

インストールはとても簡単にできます。 今回は、以下の2パターンご紹介いたします。

どちらもすぐインストールできますが、後にmesh上に乗せる際、osm cliが必要になるので、 osm cliにて実施することをお勧めします。

※Namespaceにopenservicemesh.io/monitored-by=<mesh-name>というLabelを入れることで対応可能。

osm cli

まず、以下からosm cliをダウンロードして、使える状態にしてください。

github.com

あとは、以下を実行するのみです。

# osm install
OSM installed successfully in namespace [osm-system] with mesh name [osm]

ここで表示されているmesh nameがLabelに仕込む値になります。(今回はosm)

以下のようにPodが起動されていることを確認してください。

# kubectl get all -n osm-system
NAME                                  READY   STATUS    RESTARTS   AGE
pod/osm-controller-6d9878c747-gfwzr   1/1     Running   0          23s
pod/osm-grafana-dc99fdd69-7vqzk       1/1     Running   0          23s
pod/osm-prometheus-c7cb9764f-s9k8x    1/1     Running   0          23s
pod/zipkin-f98fd66f9-lfgfl            1/1     Running   0          23s


NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
service/osm-controller   ClusterIP   10.100.200.186   <none>        15128/TCP,443/TCP   23s
service/osm-grafana      ClusterIP   10.100.200.116   <none>        3000/TCP            23s
service/osm-prometheus   ClusterIP   10.100.200.64    <none>        7070/TCP            23s
service/zipkin           ClusterIP   10.100.200.165   <none>        9411/TCP            23s


NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/osm-controller   1/1     1            1           23s
deployment.apps/osm-grafana      1/1     1            1           23s
deployment.apps/osm-prometheus   1/1     1            1           23s
deployment.apps/zipkin           1/1     1            1           23s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/osm-controller-6d9878c747   1         1         1       23s
replicaset.apps/osm-grafana-dc99fdd69       1         1         1       23s
replicaset.apps/osm-prometheus-c7cb9764f    1         1         1       23s
replicaset.apps/zipkin-f98fd66f9            1         1         1       23s

Helm

まず、git cloneしましょう。

# git clone https://github.com/openservicemesh/osm.git

その後、directoryを移動し、Namespaceを作成した後、helm installを実施します。

# cd osm/chart

# kubectl create ns osm-system
namespace/osm created

# helm install osm --values osm/values.yaml -n osm-system osm
NAME: osm
LAST DEPLOYED: Fri Aug  7 18:32:38 2020
NAMESPACE: osm-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Congratulations! The OSM control plane has been installed in your Kubernetes cluster!

使ってみよう!

traffic制御

osm cliでインストールした方は、まずhelm installの所を参考にgit cloneをしてください。

まず、Namespaceを作成していきます。

# for i in bookstore bookbuyer bookthief bookwarehouse; do kubectl create ns $i; done
namespace/bookstore created
namespace/bookbuyer created
namespace/bookthief created
namespace/bookwarehouse created

そのあと、proxy-injectionをするためのLabelを埋め込みます。

# for i in bookstore bookbuyer bookthief bookwarehouse; do osm namespace add $i; done
Namespace [bookstore] succesfully added to mesh [osm]
Namespace [bookbuyer] succesfully added to mesh [osm]
Namespace [bookthief] succesfully added to mesh [osm]
Namespace [bookwarehouse] succesfully added to mesh [osm]

osmのtop directoryに行き、以下を実行します。

# kubectl create -f docs/example/manifests/apps/

この時、Namespaceは既に存在するというErrorが出ますが気にせず進みます。

# kubectl get all -n bookbuyer
NAME                            READY   STATUS    RESTARTS   AGE
pod/bookbuyer-68d57c5bc-9b9dq   2/2     Running   0          58s


NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/bookbuyer   ClusterIP   10.100.200.26   <none>        9999/TCP   62s


NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/bookbuyer   1/1     1            1           62s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/bookbuyer-68d57c5bc   1         1         1       62s
# kubectl get all -n bookthief
NAME                            READY   STATUS    RESTARTS   AGE
pod/bookthief-bcb85bccb-crtpm   2/2     Running   0          79s


NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/bookthief   ClusterIP   10.100.200.20   <none>        9999/TCP   89s


NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/bookthief   1/1     1            1           89s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/bookthief-bcb85bccb   1         1         1       89s
# kubectl get all -n bookstore
NAME                                READY   STATUS    RESTARTS   AGE
pod/bookstore-v1-6c77fb8798-p9dhg   2/2     Running   0          112s


NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/bookstore      ClusterIP   10.100.200.185   <none>        80/TCP    118s
service/bookstore-v1   ClusterIP   10.100.200.184   <none>        80/TCP    118s


NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/bookstore-v1   1/1     1            1           118s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/bookstore-v1-6c77fb8798   1         1         1       118s
# kubectl get all -n bookwarehouse
NAME                                 READY   STATUS    RESTARTS   AGE
pod/bookwarehouse-6b98bd8597-lrmfm   2/2     Running   0          2m16s


NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/bookwarehouse   ClusterIP   10.100.200.69   <none>        80/TCP    2m20s


NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/bookwarehouse   1/1     1            1           2m20s

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/bookwarehouse-6b98bd8597   1         1         1       2m20s

アプリケーションとしては以下のようなアクセスが実行されます。

f:id:ryo_xjsbx:20200808002436p:plain

bookstoreというNamespaceには以下のリソースが入っています。

# kubectl get trafficsplit -n bookstore
NAME              SERVICE
bookstore-split   bookstore.bookstore


apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
  name: bookstore-split
  namespace: bookstore
spec:
  service: bookstore.bookstore # <root-service>.<namespace>
  backends:
  - service: bookstore-v1
    weight: 100

IstioでいうVertual Serviceですね!

では実際にGUIにアクセスしていきます。

f:id:ryo_xjsbx:20200808002717p:plain

まだ、疎通ができておらず、カウンターが動いていません。

理由として、この時点ではアクセス制御ポリシーが適用されていないため、アプリケーションは相互にアクセスできないためです。

以下のアクセス制御ポリシーを定義します。

# kubectl create -f docs/example/manifests/access/

以下のmanifestが実行されています。

kind: TrafficTarget
apiVersion: access.smi-spec.io/v1alpha2
metadata:
  name: bookstore-v1
  namespace: bookstore
spec:
  destination:
    kind: ServiceAccount
    name: bookstore-v1
    namespace: bookstore
  rules:
  - kind: HTTPRouteGroup
    name: bookstore-service-routes
    matches:
    - buy-a-book
    - books-bought
  sources:
  - kind: ServiceAccount
    name: bookbuyer
    namespace: bookbuyer
  #- kind: ServiceAccount
    #name: bookthief
    #namespace: bookthief
---
apiVersion: specs.smi-spec.io/v1alpha3
kind: HTTPRouteGroup
metadata:
  name: bookstore-service-routes
  namespace: bookstore
spec:
  matches:
  - name: books-bought
    pathRegex: /books-bought
    methods:
    - GET
    headers:
    - host: "bookstore.bookstore"
    - "user-agent": ".*-http-client/*.*"
    - "client-app": "bookbuyer"
  - name: buy-a-book
    pathRegex: ".*a-book.*new"
    methods:
    - GET
    headers:
    - host: "bookstore.bookstore"

Sourceに指定されたService Accountを持つPodから destinationに指定されたService Accountを持つPodへのアクセスを ruleに沿って流すという流れですね。

これを適用することで、カウンターが動くようになります。

f:id:ryo_xjsbx:20200808003528p:plain

ただ、お気づきの方もいらっしゃったかと思いますが、 TrafficTargetにて、bookthiefコメントアウトしているため、bookthiefではカウンターがまだ動きません。

コメントアウトを外し、再度applyしていただくと、Thiefのカウンターも動くようになります。

trafficの切り替え

bookstoreのv2をデプロイしていきます。

# kubectl apply -f docs/example/manifests/bookstore-v2/
service/bookstore-v2 created
serviceaccount/bookstore-v2 created
deployment.apps/bookstore-v2 created
traffictarget.access.smi-spec.io/bookstore-v2 created

v1とv2を切り替えるために、以下を適用していきます。

apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
  name: bookstore-split
  namespace: bookstore
spec:
  service: bookstore.bookstore # <root-service>.<namespace>
  backends:
  - service: bookstore-v1
    weight: 0
  - service: bookstore-v2
    weight: 100

weightを0:100でv2に流れるようにしています。

では適用していきます。

# kubectl apply -f docs/example/manifests/split-v2/

すると、v1のカウンターが止まり、v2が動き出すのがわかります。

f:id:ryo_xjsbx:20200808005005p:plain