Kong Meshは、サービスメッシュの管理を簡素化するためのプラットフォームで、マイクロサービス間の通信を安全かつ効率的に管理します。セキュリティ、可観測性、トラフィック制御といった機能を提供し、サイドカーアーキテクチャを利用して、各サービス間の通信をプロキシします。KubernetesやVMに対応し、異なる環境間でも統一したネットワーク管理を実現します。これにより、開発者はアプリケーションに集中でき、運用の複雑さを軽減できます。

この記事は、Kong Meshのデプロイ方法と、ポリシーの使い方をメモします。

K8s 環境の準備

標準のk8s環境であればどれでも大丈夫ですが、今回自分はk3sを使います。

1
2
export INSTALL_K3S_EXEC="--tls-san <ip address> --write-kubeconfig ~/.kube/config --write-kubeconfig-mode 644"
curl -sfL https://get.k3s.io | sh -

shの前に INSTALL_K3S_CHANNEL=v1.24.4+k3s1みたいのを入れればインストールするバージョンを指定できますが、省略する場合は最新のバージョンになります。

1
2
3
kubectl get node
NAME          STATUS   ROLES                  AGE     VERSION
wenhan-demo   Ready    control-plane,master   5m56s   v1.30.4+k3s1

Kong Meshのデプロイメント

今回はまずシンプルなSingle Zone構成をデプロイします。

Kumactl

kumactlは、Kong MeshやKumaの管理用CLIツールで、サービスメッシュの設定やリソースの操作を簡単に行えます。CLIコマンドで、メッシュのデプロイ、ポリシー設定、監視が可能です。 以下の手順でkumactlを展開し、PATHにも追加します。 こちらも同じく、VERSIONを省略したら最新のバージョンがインストールされます。

1
2
3
4
curl -L https://docs.konghq.com/mesh/installer.sh | VERSION=2.8.2 sh -

cd kong-mesh-2.8.2/bin
export PATH=$(pwd):$PATH

Kong Mesh Control Plane

以下のコマンドでKong Mesh Control Planeをk8s上にデプロイします。 ここで初めてkumactlを使います。インストールに必要なCRDなどが生成してくれます。 --license-pathには、Kong Gatewayと同じライセンスファイルのパスをセットします。

1
2
kumactl install control-plane \
    --license-path=/home/ubuntu/license | kubectl apply -f -

デプロイが終わると、kong-mesh-control-plane-xxxxxのPodがRunning状態になり、defaultmeshesがデプロイされています。

1
2
3
4
5
6
7
kubectl get pods -n kong-mesh-system
NAME                                       READY   STATUS    RESTARTS   AGE
kong-mesh-control-plane-5d5cb5f55c-h59wb   1/1     Running   0          24s

kubectl get meshes
NAME      AGE
default   2m20s

Kong Mesh Control planeをアクセスするには、CLIとGUIの方法があります。 まずはkong-mesh-control-planeサービスを公開します。方法はなんでもありですが、今回はまずシンプルにNodePortでexposeします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
kubectl expose deployment kong-mesh-control-plane \
    -n kong-mesh-system \
    --type=NodePort \
    --name=kongmesh-cp \
    --port 5681

service/kongmesh-cp exposed

kubectl patch service kongmesh-cp \
    --namespace=kong-mesh-system  \
    --type='json' \
    --patch='[{"op": "replace", "path": "/spec/ports/0/nodePort", "value":30001}]'

service/kongmesh-cp patched

serviceへのアクセス

上記で公開したサービスにアクセスすると、以下のような内容が出力されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
  curl -sX GET http://<IP address>:30001 | jq
  {
    "hostname": "kong-mesh-control-plane-5d5cb5f55c-h59wb",
    "tagline": "Kong Mesh",
    "product": "Kong Mesh",
    "version": "2.8.2",
    "instanceId": "kong-mesh-control-plane-5d5cb5f55c-h59wb-2875",
    "clusterId": "ed1a75f5-caf5-4749-943b-0ad7c6c7a49d",
    "gui": "/gui",
    "basedOnKuma": "2.8.2"
  }

GUIでのアクセス

公開したサービスの後ろに、/guiを追加すると、GUI画面が表示されています。 image.png

kumactlからのアクセス

kumactlコマンドからでもKong Mesh Control Planeを確認することもできます。 まずは、kumactlコマンドに上記のControl Planeの情報を追加します。

1
2
3
4
5
kumactl config control-planes add \
    --name=kongmesh-cp \
    --address=http://18.178.66.113:30001 --overwrite
added Control Plane "kongmesh-cp"
switched active Control Plane to "kongmesh-cp"

kumactl get meshesから、現在のMeshの設定状況を確認できる。

1
2
3
kumactl get meshes
NAME      mTLS   METRICS   LOGGING   TRACING   LOCALITY   ZONEEGRESS   AGE
default   off    off       off       off       off        off          9h

Kong MeshにAppを追加

リソースのmetadata.labelskuma.io/sidecar-injection: enabledを付与すれば、Kong Meshにそのリソースに含まれているものが追加されます。以下の例では、Namespaceにラベルを付与したので、このNamespace内の全てのPodにsidecar(DP)を追加し、Kong Meshで管理することになります。

Appのデプロイ

以下のdemo用のYAMLファイルを保存します。Front Endのサービスはページ表示、Redisのサービスはカウンターを保存する簡単なアプリです。

image.png

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
apiVersion: v1
kind: Namespace
metadata:
  name: kuma-demo
  labels:
    kuma.io/sidecar-injection: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: kuma-demo
spec:
  selector:
    matchLabels:
      app: redis
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: "redis"
          ports:
            - name: tcp
              containerPort: 6379
          lifecycle:
            postStart:
              exec:
                command: ["/usr/local/bin/redis-cli", "set", "zone", "local"]
---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: kuma-demo
spec:
  selector:
    app: redis
  ports:
  - protocol: TCP
    port: 6379
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  namespace: kuma-demo
spec:
  selector:
    matchLabels:
      app: demo-app
  replicas: 1
  template:
    metadata:
      labels:
        app: demo-app
        version: v1
    spec:
      containers:
        - name: demo-app
          image: "thefosk/kuma-demo"
          env:
            - name: REDIS_HOST
              value: "redis.kuma-demo.svc.cluster.local"
            - name: REDIS_PORT
              value: "6379"
            - name: APP_VERSION
              value: "1.0"
            - name: APP_COLOR
              value: "#efefef"
          ports:
            - name: http
              containerPort: 5000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app-v2
  namespace: kuma-demo
spec:
  selector:
    matchLabels:
      app: demo-app
  replicas: 1
  template:
    metadata:
      labels:
        app: demo-app
        version: v2
    spec:
      containers:
        - name: demo-app
          image: "thefosk/kuma-demo"
          env:
            - name: REDIS_HOST
              value: "redis.kuma-demo.svc.cluster.local"
            - name: REDIS_PORT
              value: "6379"
            - name: APP_VERSION
              value: "2.0"
            - name: APP_COLOR
              value: "#5da36f"
          ports:
            - name: http
              containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: demo-app
  namespace: kuma-demo
  annotations:
    5000.service.kuma.io/protocol: http
    ingress.kubernetes.io/service-upstream: "true"
spec:
  selector:
    app: demo-app
  ports:
  - protocol: TCP
    port: 5000

保存したYAMLファイルを使ってデモ用リソースを追加します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kubectl apply -f counterapp.yaml
namespace/kuma-demo created
deployment.apps/redis created
service/redis created
deployment.apps/demo-app created
deployment.apps/demo-app-v2 created
service/demo-app created

kubectl get pod -n kuma-demo
NAME                          READY   STATUS    RESTARTS   AGE
demo-app-5db8dc7c7c-5lxv4     2/2     Running   0          31s
demo-app-v2-977f89977-szv4p   2/2     Running   0          31s
redis-b95455698-hk7sm         2/2     Running   0          31s

各Podにcontainerが二つあることから、Sidecarが追加されたことはわかります。

GUIのData Plane Proxiesを開いたら確認できます。

iShot_2024-09-02_10.00.19.png

kumactlコマンドからでも、現在管理中のSidecar(dataplane)を確認することができます。

1
2
3
4
5
kumactl inspect dataplanes
MESH      NAME                                    TAGS                                                                                                                                                                                                                                                                             STATUS   LAST CONNECTED AGO   LAST UPDATED AGO   TOTAL UPDATES   TOTAL ERRORS   CERT REGENERATED AGO   CERT EXPIRATION   CERT REGENERATIONS   CERT BACKEND   SUPPORTED CERT BACKENDS   KUMA-DP VERSION   ENVOY VERSION   DEPENDENCIES VERSIONS   NOTES
default   demo-app-5db8dc7c7c-5lxv4.kuma-demo     app=demo-app k8s.kuma.io/namespace=kuma-demo k8s.kuma.io/service-name=demo-app k8s.kuma.io/service-port=5000 kubernetes.io/hostname=wenhan-demo kuma.io/protocol=http kuma.io/service=demo-app_kuma-demo_svc_5000 kuma.io/zone=default pod-template-hash=5db8dc7c7c version=v1   Online   1m                   51s                9               0              never                  -                 0                    -                                        2.8.2             1.30.4          -
default   demo-app-v2-977f89977-szv4p.kuma-demo   app=demo-app k8s.kuma.io/namespace=kuma-demo k8s.kuma.io/service-name=demo-app k8s.kuma.io/service-port=5000 kubernetes.io/hostname=wenhan-demo kuma.io/protocol=http kuma.io/service=demo-app_kuma-demo_svc_5000 kuma.io/zone=default pod-template-hash=977f89977 version=v2    Online   1m                   51s                9               0              never                  -                 0                    -                                        2.8.2             1.30.4          -
default   redis-b95455698-hk7sm.kuma-demo         app=redis k8s.kuma.io/namespace=kuma-demo k8s.kuma.io/service-name=redis k8s.kuma.io/service-port=6379 kubernetes.io/hostname=wenhan-demo kuma.io/protocol=tcp kuma.io/service=redis_kuma-demo_svc_6379 kuma.io/zone=default pod-template-hash=b95455698                         Online   1m                   50s                9               0              never                  -                 0                    -                                        2.8.2             1.30.4          -

Appの公開

このアプリにアクセスしてみましょう。やり方は複数ありますが、ここではGateway + Ingressの方法で公開します。

Install gateway

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created

echo "
---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
 name: kong
 annotations:
   konghq.com/gatewayclass-unmanaged: 'true'

spec:
 controllerName: konghq.com/kic-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
 name: kong
spec:
 gatewayClassName: kong
 listeners:
 - name: proxy
   port: 80
   protocol: HTTP
" | kubectl apply -f -
gatewayclass.gateway.networking.k8s.io/kong created
gateway.gateway.networking.k8s.io/kong created

Install Kong KIC and Ingress

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
kubectl create ns kong
kubectl label ns kong kuma.io/sidecar-injection='enabled'
helm install kong kong/ingress -n kong
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/ubuntu/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/ubuntu/.kube/config
NAME: kong
LAST DEPLOYED: Mon Sep  2 10:02:13 2024
NAMESPACE: kong
STATUS: deployed
REVISION: 1
TEST SUITE: None

cat <<EOF | kubectl apply -f - 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: counterapp
  namespace: kuma-demo
  annotations:
    kubernetes.io/ingress.class: kong
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app
            port:
              number: 5000
EOF

これでKong-gateway-proxyを使って、デプロイしたAPPにアクセスすることができます。

1
2
3
4
5
6
kubectl get svc -n kong
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
kong-controller-validation-webhook   ClusterIP      10.43.225.243   <none>        443/TCP                         3m10s
kong-gateway-admin                   ClusterIP      None            <none>        8444/TCP                        3m10s
kong-gateway-manager                 NodePort       10.43.69.48     <none>        8002:32047/TCP,8445:31615/TCP   3m10s
kong-gateway-proxy                   LoadBalancer   10.43.97.252    <pending>     80:32333/TCP,443:31081/TCP      3m10s

32333 portにアクセスすれば、デモAPPにアクセスすることができます。 適当にIncrementをクリックしたら、全てが正常に動作しているはずです。

iShot_2024-09-02_10.49.44.png

Kong Meshのポリシーを活用

ここからはKong Meshの本領を発揮するところです。Kong Meshのポリシーは、サービスメッシュ環境でセキュリティやアクセス管理、トラフィック制御を実現するためのルール設定をサポートするものです。これらのポリシーには、主に以下の要素が含まれます。

  1. セキュリティポリシー: 通信の暗号化(mTLS)や認証・認可を通じて、マイクロサービス間のセキュリティを強化します。トラフィックが安全に通信されることを保証します
  2. トラフィックポリシー: サービス間の通信ルールを定義します。リトライやタイムアウト設定、トラフィックシェーピング、ロードバランシングなどを管理することが可能です
  3. 認可ポリシー: RBAC(Role-Based Access Control)に基づき、どのサービスやユーザーがどのリソースにアクセスできるかを制御します
  4. 監査ポリシー: システム全体のアクティビティを記録し、監査ログを生成します。これにより、異常やセキュリティインシデントの早期検知が可能です

Kong Meshのポリシーは、これらの機能を通じて、分散システム全体のセキュリティ、パフォーマンス、信頼性を向上させることを目的としています。 https://docs.konghq.com/mesh/latest/policies/introduction/

ここでは、以下の二つのポリシーを適用して、Zero Trust networkを構築する方法を説明します。 https://docs.konghq.com/mesh/latest/policies/meshpassthrough/ https://docs.konghq.com/mesh/latest/policies/meshtrafficpermission/

Zero-trust Networkの構築

mTLSの有効化

デフォルトでは、mTLSが無効になっています。

1
2
3
kumactl get meshes
NAME      mTLS   METRICS   LOGGING   TRACING   LOCALITY   ZONEEGRESS   AGE
default   off    off       off       off       off        off          9h

Kong Mesh内部にbuilt-inのCAがあるため、以下で簡単に有効することができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# config mesh to enable mtls
cat <<EOF | kubectl apply -f - 
apiVersion: kuma.io/v1alpha1
kind: Mesh
metadata:
  name: default
spec:
  mtls:
    enabledBackend: ca-1
    backends:
    - name: ca-1
      type: builtin
EOF

kumactl get meshes
NAME      mTLS           METRICS   LOGGING   TRACING   LOCALITY   ZONEEGRESS   AGE
default   builtin/ca-1   off       off       off       off        off          9h

mTLSを有効化すれば、これで全てのトラフィックに、meshtrafficpermissionが必要になっています。現在はまだ作っていないため、APPへのアクセスが失敗になるはずです。

Kong Meshのバージョンによって失敗にならないケースもありますが、それはデフォルトにallow-allmeshtrafficpermissionが存在しているからです。

マイクロサービス間のアクセスを許可

例えば、以下のようにallow-allのPermissionを作ったら、Mesh内の全てのトラフィックが正常のままになっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
cat <<EOF | kubectl apply -f -
apiVersion: kuma.io/v1alpha1
kind: MeshTrafficPermission
metadata:
  name: allow-all
  namespace: kong-mesh-system
  labels:
    kuma.io/mesh: default
spec:
  targetRef:
    kind: Mesh
  from:
  - targetRef:
      kind: Mesh
    default:
      action: Allow
EOF

もう少しコントロールしたいので、許可をマイクロベースレベルで設定してみます。 まずはFront EndのKong GatewayのサービスからAPPへの許可を設定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
cat <<EOF | kubectl apply -f -
apiVersion: kuma.io/v1alpha1
kind: MeshTrafficPermission
metadata:
  name: kong2frontend
  namespace: kong-mesh-system
  labels:
    kuma.io/mesh: default
spec:
  targetRef:
    kind: MeshService
    name: demo-app_kuma-demo_svc_5000
  from:
  - targetRef:
      kind: MeshSubset
      tags:
        kuma.io/service: kong-gateway-admin_kong_svc_8444
    default:
      action: Allow
EOF
meshtrafficpermission.kuma.io/kong2frontend created

次に、APPからRedisへの許可を設定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF | kubectl apply -f -
apiVersion: kuma.io/v1alpha1
kind: MeshTrafficPermission
metadata:
  name: frontend2backend
  namespace: kong-mesh-system
  labels:
    kuma.io/mesh: default
spec:
  targetRef:
    kind: MeshService
    name: redis_kuma-demo_svc_6379
  from:
  - targetRef:
      kind: MeshSubset
      tags:
        kuma.io/service: demo-app_kuma-demo_svc_5000
    default:
      action: Allow
EOF

ここまでで、マイクロサービスレベルのアクセス許可を設定し、アプリケーションの動きが正常になるはずです。

まとめ

Kong Meshは、サービスメッシュの管理を簡素化するプラットフォームで、マイクロサービス間の通信を安全かつ効率的に管理します。この記事では、Kong Meshのデプロイ方法とポリシーの使い方を説明しています。

  1. K8s環境の準備: k3sを使用してKubernetes環境をセットアップします。

  2. Kong Meshのデプロイ:

    • kumactlを使用してKong Mesh Control Planeをデプロイします。
    • NodePortを使用してControl Planeを公開し、CLIやGUIでアクセスします。
  3. アプリケーションのデプロイ:

    • kuma.io/sidecar-injection: enabledラベルを使用して、Namespace内のPodにサイドカーを追加します。
    • Redisとデモアプリをデプロイし、Kong Meshで管理します。
  4. アプリケーションの公開:

    • GatewayとIngressを使用してアプリケーションを公開します。
  5. Kong Meshのポリシー活用:

    • mTLSを有効化し、Zero Trust Networkを構築します。
    • MeshTrafficPermissionを設定して、マイクロサービス間のアクセスを制御します。

このプロセスにより、Kong Meshを使用してセキュアで効率的なサービスメッシュを構築し、ポリシーを活用してトラフィックを管理する方法を学びます。