0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Gateway APIでNamespaceを跨いでロードバランシングする

Last updated at Posted at 2024-03-28

Microservices的なシステムを作ると、IngressがNamespaceを跨げないことが問題となることがある。
ExternalNameを活用するなどすれば跨げなくもないのだが、セキュリティ的に問題となることもあるらしい。
そのため別のNamespaceのServiceを参照したい、というニーズに応えるために、Gateway APIではReferencePolicyというリソースが用意され、これを使うとHTTPRouteが別のNamespaceのServiceを参照できるようになる。
image.png
(ReferenceGrantより引用)

今回はReferencePolicyの動作を確認するために、前回検証したnginxとhttbinのNamespaceを変えて以下のような構成で意図通りに通信できるかを検証する。
image.png

なお、検証は前回の環境を使い回すため、クラスタの準備やGateway API、Gateway Controllerの導入は終わっているところからスタートする。

ReferenceGrantの概要

ReferenceGrantは名前の通り参照権限を与えるためのリソースであり、Namespaceをまたいだ場合の各種リソースの権限を管理する。
仕様はこちらにあるが、実物を見た方がわかりやすいので以下サンプルを示す。

kind: ReferenceGrant
metadata:
  name: bar
  namespace: bar
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: foo
  to:
  - group: ""
    kind: Service

spec.fromで権限をリクエストする側を指定し、spec.toで参照先を指定する。
リソース名やNamespace名などもここで細かく指定することが出来、権限の付与に関して細かく設定できるようになっている。
なお、ここではHTTPRouteのためにReferenceGrantを使っているが、ストレージ(PVC)に適用した事例もあるため、ネットワークに限らず様々なリソースに応用することも出来そうだ。

参考:CNDT 2022、日立のエンジニアによるKubernetesに新機能をマージした経験を語るセッション

検証

最初に検証用のnginxを起動する。

kubectl create ns demo-back
kubectl run nginx --image nginx --port 80 -n demo-back
kubectl expose pod nginx --port 80 -n demo-back

httpbinをつなぐServiceを作成する。

kubectl create ns demo-external
kubectl create svc externalname httpbin --external-name httpbin.org -n demo-external

Gatewayリソースを作成する。

kubectl create ns demo-front
cat <<EOF | kubectl apply -n demo-front -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: kong
  listeners:
  - name: http
    port: 80
    protocol: HTTP
EOF

HTTPRouteを作成する。

PROXY_IP=$(kubectl get gateway gateway -n demo -o jsonpath={.status.addresses[].value})
export HOSTNAME="my-service.$(sed "s/\./-/g" <<< $PROXY_IP).nip.io"
cat <<EOF | kubectl apply -n demo-front -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: route
  annotations:
    konghq.com/strip-path: 'true'
spec:
  hostnames: 
  - $HOSTNAME
  parentRefs:
  - name: gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /service
    backendRefs:
    - name: nginx
      kind: Service
      namespace: demo-back
      port: 80
      weight: 50
    - name: httpbin
      kind: Service
      namespace: demo-external
      port: 80
      weight: 50
EOF

前回との違いとして、backendRefs内のService指定時にnamespaceも指定するようにした。
この状態だとまだReferenceGrantがないため、参照する権限がない。
試しにサービスのエンドポイントにアクセスしても、"no existing backendRef provided"と怒られてしまう。

$ curl my-service.192-168-64-202.nip.io/service
{"message":"no existing backendRef provided"}

ここでReferenceGrantを適用してみる。まずはnginxのServiceにのみ適用する。

cat <<EOF | kubectl apply -f - 
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: nginx-grant
  namespace: demo-back
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: demo-front
  to:
  - group: ""
    kind: Service
EOF

この状態でエンドポイントにアクセスすると、nginxへのアクセスのみ発生する。

$ curl my-service.192-168-64-202.nip.io/service
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
:(省略)

httpbin側の方も許可を与える。

cat <<EOF | kubectl apply -f - 
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: httpbin-grant
  namespace: demo-external
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: demo-front
  to:
  - group: ""
    kind: Service
EOF

こうすると、nginx, httpbinそれぞれにアクセスするようになる。

$ curl my-service.192-168-64-202.nip.io/service
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>httpbin.org</title>
:(省略)

適切に参照権限が与えられることが確認できた。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?