Oracle Cloud Infrastructure Service Mesh忘備録

# はじめに
本記事は2022年4月に正式リリースとなったOracle Cloud Infrastructure Service Meshの概要記事となります。

# OCI Service Meshの仕組み

特定のCustom Resourceを適用するとアプリケーションコンテナのサイドカーとしてEnvoyが導入されるような仕組みになっています。サイドカーでEnvoyと聞くとIstioを思い浮かべる方が多いと思いますが、本製品はIstioの拡張というわけではなくOCI独自のServiceMeshです。

# チュートリアル

https://docs.oracle.com/en-us/iaas/Content/service-mesh-tutorials/tutorials-home.htm

# OCI Service Mesh概要図

OCIのドキュメントから引用

![OCI Service Mesh概要](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116002/b4a729c9-2b69-fa0f-dacf-8ccf8c926276.png)

https://docs.oracle.com/ja/solutions/oci-service-mesh-oke/index.html


# 各種Resource

## Mesh

OCI `Mesh` Resourceはサービスメッシュの論理境界を表します。

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/mesh.md

## VirtualService

OCI `VirtualService` ResourceはOCI `Mesh` 内の論理的な接続先を表します。
K8s `Service`に相当する概念と考えればよいです。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: VirtualService
metadata:
  name: <vs-sample-page>
  namespace: <sample-namespace>
  labels:
    version: v1
spec:
  compartmentId: ocid1.compartment.oc1..aaa...
  name: <vs-sample>
  description: <description text here>
  mesh:
    ref:
      name: <sample-mesh>
  defaultRoutingPolicy:
    type: <routing-policy> [`ROUND ROBIN`, `DENY`]
  hosts:
    - <vs-sample-page>.example.com    # ★Mesh内で利用するhost名
  mtls:
    mode: <mtls-mode> [`DISABLED`, `PERMISSIVE`, `STRICT`] # ★mTLSの設定
```

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/virtual-service.md

## VirtualDeployment

`VirtualService`の先にある論理的なグループを表します。アプリケーションの各バージョンを表すものだと考えればよいです。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: VirtualDeployment
metadata:
  name: <vs-sample-page>-version1
  namespace: <sample-namespace>
spec:
  compartmentId: ocid1.compartment.oc1..aaa...
  name: <vs-sample>-v1 
  description: <description-text>
  virtualService:
    ref:
      name: <vs-sample-page> # ★対応するVirtualService名
  accessLogging:
    isEnabled: true
  serviceDiscovery:
    type: DNS
    hostname: <vs-sample-page>-version1.example.com
  listener:
    - port: 9080
      protocol: HTTP

```

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/virtual-deployment.md


## VirtualServiceRouteTable

どの`VirtualDeployment`にルーティングを行うかの設定を記載します。
まだ各ルートに対する重みづけくらいしか機能はないようです。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: VirtualServiceRouteTable
metadata:
  name: <vs-sample-page>-rt
  namespace: <sample-namespace>
spec:
  compartmentId: ocid1.compartment.oc1..aaa...
  name: <vs-sample>-routes
  description: <description text here>
  virtualService:
    ref:
      name: <vs-sample-page>
  routeRules:
    - httpRoute:
        destinations:
          - virtualDeployment:
              ref:
                name: <vs-sample-page>-version1
            weight: 100 # ★ルートに対する重みを設定する
        isGrpc: <boolean-value> [true/false]
        path: /foo,
        pathType: PREFIX
```


## VirtualDeploymentBinding

OCI Service Meshの`VirtualDeployment`とKubernetesの`Service`を紐づけます。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: VirtualDeploymentBinding
metadata:
  name: <binding-name>
  namespace: <binding-namespace>
spec:
  podUpgradeEnabled: true
  virtualDeployment:
    ref:
      name: <vd-name> # VirtualDeployment名	
  target:
    service:
      ref:
        name: <kubernetes-service-name> # 紐づけたいK8s Service名
        namespace: <kubernetes-service-namespace> # 紐づけたいK8s ServiceがあるNamespace名
  resources: # Side-carのresource
    requests:
      memory: "64Mi"
      cpu: "250m"
    limits:
      memory: "128Mi"
      cpu: "500m"
  mountCertificateChainFromHost: true
```

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/virtual-deployment-binding.md

## AccessPolicy

`Mesh` Resource内の通信許可/拒否のルールを記載します。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: AccessPolicy
metadata:
  name: <sample-access-policy>
  namespace: <sample-namespace>
spec:
  compartmentId: ocid1.compartment.oc1..aaa...
  name: sample-ap
  description: This Access Policy
  mesh:
    ref:
      name: <sample-mesh> # ★ポリシを適用するMesh Resource名
  rules:
    - action: ALLOW # ★拒否/許可のルールを記載する
      source:
        virtualService:
          ref:
            name: <sample-virtual-service>
      destination:
          allVirtualServices: {}
```

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/access-policy.md

## IngressGatewayDeployment

クラスタ外部から`Mesh`内への通信を処理します。
`type: LoadBalancer`なK8s `Service`やK8s `Deployment`Resourceを生成します。Nginx Ingress Controllerのような、K8s `Ingress` Resourceの実装部分と考えればよいです。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: IngressGatewayDeployment
metadata:
  name: <sample-ingress-gateway>-deployment
  namespace: <sample-namespace>
spec:
  ingressGateway:
    ref:
      name: <sample-ingress-gateway>
  deployment:
    autoscaling: # ★外部からの通信を処理するPodの個数設定
      minPods: 1
      maxPods: 1
    mountCertificateChainFromHost: true
  ports:
    - protocol: TCP
      port: 8080
      serviceport: 80
  service:
    type: LoadBalancer # ★OCI LBaaSと連携し、外部公開される
  secrets:
    - secretName: secret-tls-secret
```

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/ingress-gateway-deployment.md

K8s `Deployment`やK8s `Service`は、OCI Service Operatorが上記YAMLをもとに作成します。作成部分の実装はこちら。

https://github.com/oracle/oci-service-operator/blob/main/pkg/servicemanager/servicemesh/ingressgatewaydeployment/ingressgatewaydeployment_servicemanager.go

## IngressGatewayRouteTable

クラスタ外部から`Mesh`内に到達した通信のルーティングルールを作成します。
`VirtualServiceRouteTable`と同じく、`RouteRule`型のパラメータでルールを設定します。

```yaml
apiVersion: servicemesh.oci.oracle.com/v1beta1
kind: IngressGatewayRouteTable
metadata:
  name: <sample-ingress-gateway>-route-table    # Name of Ingress Gateway Route Table
  namespace: <sample-namespace>
spec:
  compartmentId: ocid1.compartment.oc1..aaa...
  name: <sample-ig-rt>       # Ingress Gateway Route Table name inside the mesh
  description: This Ingress Gateway Route Table
  ingressGateway:
    ref:
      name: <sample-ingress-gateway>
  routeRules:
    - httpRoute:
        ingressGatewayHost:
          name: samplehost
        path: /foo
        pathType: PREFIX
        isGrpc: false
        destinations:
          - virtualService:
              ref:
                name: <vs-sample-page> # ★ルーティング先のVirtualServiceを指定
```

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/ingress-gateway-route-table.md

## IngressGateway

クラスタ外部から`Mesh`内への通信に関わる設定を行います。
K8s `Ingress`に相当するものと考えればよいです。

https://github.com/oracle/oci-service-operator/blob/main/docs/service-mesh/ingress-gateway.md

# 所感

## 各種機能は今後に期待

調べた範囲では大まかに

- トラフィックの重みづけ
- トラフィックの許可/拒否ルールの設定
- mTLS
- Telemetry（PrometheusやGrafanaと連携）

の機能のみが提供されています。リトライやタイムアウト、Fault Injectionなどの機能はまだ実装されていません。まだまだ発展途上という段階で、IstioのようなServiceMeshと比較すると機能不足な感じは否めないです。

Kubernetesクラスタのみならず、VMなどのプラットフォームにまたがったメッシュの構築なども今後のロードマップに含まれているようなので、今後の拡張に期待します。

## OCI Serviceとの連携

証明書の発行（OCI Certificates）との連携など、いくつかの機能ではOCI Managed Serviceとの連携がされていますがダッシュボード機能などはまだまだといったところ。

## 余談

余談ですが、OCI `VirtualDeployment`に`spec.serviceDiscovery.hostname`があるのが不思議な感じがしました。Githubに下記のような記載があるので、そのまま`VirtualServiceVersion`とかでも良かったのではと思っています。（個人の感想です）

> A virtual deployment is a version of a virtual service in the mesh.