- はじめに
- Gateway APIって?
- 一先ずApplication Gateway for ContainersでGateway APIで、mTLS接続をば
- namespace跨りのルーティングしてみる
- さいごに
- ACS事業部のご紹介
はじめに
こんにちは!ACS事業部の谷合です。
先日Application Gateway for Containersプレビュー版の使用感の記事を、弊社吉川より(おそらく日本最速で)投稿しました。
techblog.ap-com.co.jp
実は、Application Gateway for ContainersではIngressの他にもGateway APIがサポートされています。
今回は(おそらく日本最速で)Application Gateway for ContainersでGateway APIを使う方法をご紹介します。
Application Gateway for Containers単体でIngressとGateway APIが使えるのはとっても便利ですよね。
Gateway APIって?
Application Gateway for Containersで個人的に素晴らしいなと思う点に、IngressとGateway APIのサポートあります。
Gateway APIはIngressの後継の位置付けて実装されており、以下の思想で実装されています。
- Role-oriented - Gateway is composed of API resources which model organizational roles that use and configure Kubernetes service networking.
- Portable - This isn't an improvement but rather something that should stay the same. Just as Ingress is a universal specification with numerous implementations, Gateway API is designed to be a portable specification supported by many implementations.
- Expressive - Gateway API resources support core functionality for things like header-based matching, traffic weighting, and other capabilities that were only possible in Ingress through custom annotations.
- Extensible - Gateway API allows for custom resources to be linked at various layers of the API. This makes granular customization possible at the appropriate places within the API structure.
今回はRole-orientedに着目してみます。
今までは、Ingressはnamespaceに閉じられており、異なるnamespaceにルーティングすることは正攻法では困難でした。
Gateway APIではこれを単体で解決することでマルチテナントを実現しています。
一先ずApplication Gateway for ContainersでGateway APIで、mTLS接続をば
以下のドキュメントを参考に検証を進めます。 learn.microsoft.com
早速実装してみましょう。
本手順は前回記事のBring Your Own (BYO)でのApplication Gateway for Containersデプロイを前提としています。
そのため、前回指定したResource GroupやResource Name、Frontend Nameを使用します。
まず、サンプルアプリをデプロイします。
この時、test-infra namespaceにアプリ、サービス、ConfigMap、Secret(証明書)がデプロイされます。
$ kubectl apply -f https://trafficcontrollerdocs.blob.core.windows.net/examples/https-scenario/end-to-end-ssl-with-backend-mtls/deployment.yaml
namespace/test-infra created
service/mtls-app created
deployment.apps/mtls-app created
configmap/mtls-app-nginx-cm created
secret/backend.com created
secret/frontend.com created
secret/gateway-client-cert created
secret/ca.bundle created
デプロイ確認してみましょう。
$ kubectl -n test-infra get all,secret,configmap NAME READY STATUS RESTARTS AGE pod/mtls-app-5dd5c75d4f-bwp4w 1/1 Running 0 20s pod/mtls-app-5dd5c75d4f-cpgd8 1/1 Running 0 20s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/mtls-app LoadBalancer 10.0.210.6 4.156.162.222 443:30911/TCP 22s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/mtls-app 2/2 2 2 21s NAME DESIRED CURRENT READY AGE replicaset.apps/mtls-app-5dd5c75d4f 2 2 2 21s NAME TYPE DATA AGE secret/backend.com kubernetes.io/tls 2 21s secret/ca.bundle Opaque 1 19s secret/frontend.com kubernetes.io/tls 2 21s secret/gateway-client-cert kubernetes.io/tls 2 20s NAME DATA AGE configmap/kube-root-ca.crt 1 25s configmap/mtls-app-nginx-cm 1 23s
以降でGateway APIをデプロイしていきます。
まずは以下環境変数を設定してください。
$ RESOURCE_GROUP=rg-sample $ RESOURCE_NAME='alb-sample' $ RESOURCE_ID=$(az network alb show --resource-group $RESOURCE_GROUP --name $RESOURCE_NAME --query id -o tsv) $ FRONTEND_NAME='frontend-sample'
次にGatewayリソースをデプロイします。
Gatewayリソースとは文字通り、Gatewayであり、外からの接続要求のFrontendとしての役割を持ちます。
$ kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: gateway-01 namespace: test-infra annotations: alb.networking.azure.io/alb-id: $RESOURCE_ID spec: gatewayClassName: azure-alb-external listeners: - name: https-listener port: 443 protocol: HTTPS allowedRoutes: namespaces: from: Same tls: mode: Terminate certificateRefs: - kind : Secret group: "" name: frontend.com addresses: - type: alb.networking.azure.io/alb-frontend value: $FRONTEND_NAME EOF
kubectl get -oyamlコマンドを実行することで以下のような出力が確認できるはずです。
$ kubectl get gateway gateway-01 -n test-infra -o yaml : status: addresses: - type: IPAddress value: 4f264daf5a4666fb2142e1240a164e86.fz46.alb.azure.com conditions: - lastTransitionTime: "2023-07-27T08:05:21Z" message: Valid Gateway observedGeneration: 2 reason: Accepted status: "True" type: Accepted - lastTransitionTime: "2023-07-27T08:05:21Z" message: Application Gateway for Containers resource has been successfully updated. observedGeneration: 2 reason: Programmed status: "True" type: Programmed listeners: - attachedRoutes: 1 conditions: - lastTransitionTime: "2023-07-27T08:05:21Z" message: "" observedGeneration: 2 reason: ResolvedRefs status: "True" type: ResolvedRefs - lastTransitionTime: "2023-07-27T08:05:21Z" message: Listener is Accepted observedGeneration: 2 reason: Accepted status: "True" type: Accepted - lastTransitionTime: "2023-07-27T08:05:21Z" message: Application Gateway for Containers resource has been successfully updated. observedGeneration: 2 reason: Programmed status: "True" type: Programmed name: https-listener supportedKinds: - group: gateway.networking.k8s.io kind: HTTPRoute
次に、HTTPRouteリソースをデプロイします。
HTTPRouteリソースは、Gatewayリソースに紐づき、接続要求をルーティングします。
同じくGatewayリソースに紐づくListenerからリクエストをバックエンドに流します。
$ kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: https-route namespace: test-infra spec: parentRefs: - name: gateway-01 rules: - backendRefs: - name: mtls-app port: 443 EOF
Gatewayリソースと同じくkubectl get -oyamlコマンドを実行することで以下のような出力があるはずです。
※数分かかる場合があります。
$ kubectl get httproute https-route -n test-infra -o yaml : status: parents: - conditions: - lastTransitionTime: "2023-07-27T08:05:21Z" message: "" observedGeneration: 1 reason: ResolvedRefs status: "True" type: ResolvedRefs - lastTransitionTime: "2023-07-27T08:05:21Z" message: Route is Accepted observedGeneration: 1 reason: Accepted status: "True" type: Accepted - lastTransitionTime: "2023-07-27T08:05:21Z" message: Application Gateway for Containers resource has been successfully updated. observedGeneration: 1 reason: Programmed status: "True" type: Programmed controllerName: alb.networking.azure.io/alb-controller parentRef: group: gateway.networking.k8s.io kind: Gateway name: gateway-01
最後にBackendTLSPolicyリソースを作成します。
BackendTLSPolicyリソースは、HTTPRoute で参照されるバックエンド サービスのクライアント証明書と CA 証明書を持つバックエンド TLS ポリシーの作成を行います。
$ kubectl apply -f - <<EOF apiVersion: alb.networking.azure.io/v1 kind: BackendTLSPolicy metadata: name: mtls-app-tls-policy namespace: test-infra spec: targetRef: group: "" kind: Service name: mtls-app namespace: test-infra default: sni: backend.com ports: - port: 443 clientCertificateRef: name: gateway-client-cert group: "" kind: Secret verify: caCertificateRef: name: ca.bundle group: "" kind: Secret subjectAltName: backend.com EOF
kubectl get -oyamlコマンドを実行してみましょう。
$ kubectl get backendtlspolicy -n test-infra mtls-app-tls-policy -o yaml : status: conditions: - lastTransitionTime: "2023-07-27T08:14:30Z" message: Valid BackendTLSPolicy observedGeneration: 1 reason: Accepted status: "True" type: Accepted
これまでの作業で以下のような状況になっているはずです。
$ kubectl -n test-infra get pod,gateway,httproute,backendtlspolicy,secret NAME READY STATUS RESTARTS AGE pod/mtls-app-5dd5c75d4f-bwp4w 1/1 Running 0 87m pod/mtls-app-5dd5c75d4f-cpgd8 1/1 Running 0 87m NAME CLASS ADDRESS PROGRAMMED AGE gateway.gateway.networking.k8s.io/gateway-01 azure-alb-external 4f264daf5a4666fb2142e1240a164e86.fz46.alb.azure.com True 73m NAME HOSTNAMES AGE httproute.gateway.networking.k8s.io/https-route 41m NAME READY AGE backendtlspolicy.alb.networking.azure.io/mtls-app-tls-policy 38m NAME TYPE DATA AGE secret/backend.com kubernetes.io/tls 2 21s secret/ca.bundle Opaque 1 19s secret/frontend.com kubernetes.io/tls 2 21s secret/gateway-client-cert kubernetes.io/tls 2 20s
これで準備が整いましたので、接続してみましょう。
問題なく接続できましたね!!
$ fqdn=$(kubectl get gateway gateway-01 -n test-infra -o jsonpath='{.status.addresses[0].value}') $ curl --insecure https://$fqdn/ Hello World!
namespace跨りのルーティングしてみる
namespace跨りのルーティングについては、以下の公式ドキュメントを参考に動かします。 gateway-api.f5se.io
ここからの手順は上記でデプロイしたリソースに変更を加えることで検証を行います。
まずは、GatewayリソースでmTLSを行う際に使用するfrontend用の証明書Secretのnamespaceを変更します。
$ k -n test-infra get secrets frontend.com -oyaml # 別namespaceに変更 $ cat << EOT | k apply -f - apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDR・・・ElGSUNBVEUtLS0tLQo= tls.key: LS0tLS1CRUdJTiBF・・・UFJJVkFURSBLRVktLS0tLQo= kind: Secret metadata: annotations: : creationTimestamp: "2023-07-27T07:25:58Z" name: frontend.com # test-infra → azure-alb-system namespace: azure-alb-system resourceVersion: "8807" uid: 2e8175e7-f92f-46cb-860a-6ec8061ddf55 type: kubernetes.io/tls EOT $ kubectl -n test-infra delete secrets frontend.com
次に、Gatewayリソースをデプロイします。
この時以下の変更を行います。
- .matadata.namespaceをSecretと同じnamespaceにする
- .spec.listener[ ].allowedRoutes.namespacesをSelectorに変更し、HTTPRouteと同じnamespaceのラベルを指定する。
- .spec.listener[ ].tls.certificateRefs[ ].namespaceをSecretと同じnamespaceにする
$ kubectl get ns test-infra --show-labels NAME STATUS AGE LABELS test-infra Active 123m kubernetes.io/metadata.name=test-infra kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: gateway-01 namespace: azure-alb-system annotations: alb.networking.azure.io/alb-id: $RESOURCE_ID spec: gatewayClassName: azure-alb-external listeners: - name: https-listener port: 443 protocol: HTTPS allowedRoutes: namespaces: from: Selector selector: matchLabels: kubernetes.io/metadata.name: test-infra tls: mode: Terminate certificateRefs: - kind : Secret group: "" name: frontend.com namespace: azure-alb-system addresses: - type: alb.networking.azure.io/alb-frontend value: $FRONTEND_NAME EOF
次にHTTPRouteリソースの構成変更を行います。
以下の箇所を変更して、applyします。
* .spec.parentRefs[ ].namespaceをGatewayリソースと同じにする
$ kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: https-route namespace: test-infra spec: parentRefs: - name: gateway-01 namespace: azure-alb-system rules: - backendRefs: - name: mtls-app port: 443 EOF
これまでの作業で以下のような状況になっているはずです。
$ kubectl -n azure-alb-system get pod,gateway,secret NAME READY STATUS RESTARTS AGE pod/alb-controller-59455854-tkd8w 1/1 Running 0 143m pod/alb-controller-bootstrap-5f8c757676-rs2vk 1/1 Running 0 143m NAME CLASS ADDRESS PROGRAMMED AGE gateway.gateway.networking.k8s.io/gateway-01 azure-alb-external 4f264daf5a4666fb2142e1240a164e86.fz46.alb.azure.com True 10m NAME TYPE DATA AGE secret/frontend.com kubernetes.io/tls 2 10m $ kubectl -n test-infra get pod,httproute,backendtlspolicy,secret NAME READY STATUS RESTARTS AGE pod/mtls-app-5dd5c75d4f-bwp4w 1/1 Running 0 133m pod/mtls-app-5dd5c75d4f-cpgd8 1/1 Running 0 133m NAME HOSTNAMES AGE httproute.gateway.networking.k8s.io/https-route 87m NAME READY AGE backendtlspolicy.alb.networking.azure.io/mtls-app-tls-policy 84m NAME TYPE DATA AGE secret/backend.com kubernetes.io/tls 2 133m secret/ca.bundle Opaque 1 133m secret/gateway-client-cert kubernetes.io/tls 2 133m
これで準備完了です。
接続してみましょう。
$ curl --insecure https://$fqdn/ Hello World!
さいごに
Application Gateway for Containers、いいですよねえ。
Microsoftさん、なんて最高なものをリリースしてくれたんでしょう。
これはGAになれば、L7通信のデファクトスタンダードになる予感がします。
GAを楽しみに待ちましょう!!
ACS事業部のご紹介
私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。
www.ap-com.co.jp
また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。
www.ap-com.co.jp