この記事はAdvent Calendar 1日目の記事になります。
(Japan Container Days v18.12の運営やshowKsやセッション資料の作成に追われ、遅れてしまい申し訳ありません。)
こんにちは。 @amsy810 です。
GKE では、最近ネットワークに関する便利な機能追加が多く行われており、この記事ではそれらについて紹介したいと思います。 主に下記の2つについて紹介します。
- BackendConfig Resource
- Network Endpoint Groups (NEGs)
BackendConfig Resource
BackendConfig Resource は GKE でのみ利用可能な CRD(Custom Resource Definition)で、HTTP/HTTPS Load Balancing(Ingress Resource)をする際に、下記の機能を付随して利用することが可能になります。
- Cloud Content Delivery Network (Cloud CDN)
- Cloud Armor
- Cloud Identity-Aware Proxy (Cloud IAP)
- Timeout, Connection draining timeout, Session affinity
もう少しいうと、GCE用のIngress ControllerがこのBackendConfigリソースをみて、連携を行なっているようです。Ingress ResourceのSpecは一般化されたリソースのためこのような記述をすることができず、もしできるとしてもAnnotationsで設定することになってしまうと思います。 そのため、BackendConfigとして実装する道を辿ったのだと思います。 現時点ではBackendConfigはGKE用のリソースとなっています。 実際の処理部分は下記のあたりです。
ingress-gce/pkg/backends/features at v1.4.0 · kubernetes/ingress-gce · GitHub
なお、BackendConfigのリソースは、下記のリンク先にある構造体を持っています。
ingress-gce/types.go at v1.4.0 · kubernetes/ingress-gce · GitHub
全部埋めた状態だとこんな感じですね。
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: sample-backend-config namespace: default spec: iap: enabled: true oauthclientCredentials: secretName: my_secret # Secret で clientID と clientSecret を指定する場合は不要 # clientID: my_client_id # clientSecret: my_client_secret cdn: enabled: true cachePolicy: includeHost: true includeProtocol: true includeQueryString: false QueryStringBlacklist: - "" QueryStringWhitelist: - "" securityPolicy: name: my_policy timeoutSec: 40 connectionDraining: drainingTimeoutSec: 60 sessionAffinity: affinityType: "GENERATED_COOKIE" affinityCookieTtlSec: 50
ちなみにCloud IAPとCloud CDNを両方とも1つのBackendConfigに設定することはできません。 また、作成したBackendConfigは、ServiceのAnnotationsに beta.cloud.google.com/backend-config を記述することで利用します。 Ingress ResourceのAnnotationsに設定するイメージでしたが、Serviceの方に設定するんですね。 おそらく、複数のIngress ObjectからServiceのNodePortを指定することができるため下流の方で設定をかけたかったか、Ingress ControllerはService Objectの情報を元に動作する(NEGsはServiceのNodePortに送られるのではなく、Serviceに紐付くPodのIPをDiscoveryしている)思想で作られたのかなと思っています。
apiVersion: v1 kind: Service metadata: annotations: beta.cloud.google.com/backend-config: '{"ports": {"http":"config-http", "http2" :"config-http2"}, "default": "config-default"}' name: my-service spec: type: NodePort ports: - name: http protocol: TCP port: 80 targetPort: 8080 - name: http2 protocol: TCP port: 443 targetPort: 8080 - name: http3 protocol: TCP port: 49152 targetPort: 49152
Cloud Armor
Cloud Armorは、DDOS対策・IP Addressの Allow/Deny・Geo-based Access Controlをはじめとした様々なセキュリティ機能を利用することができます。
現状では事前に gcloud beta compute security-policies rules create コマンドでポリシーを作成しておき、そのポリシーを使うことを明示的にBackendConfigリソースに指定してあげる必要があります。
例えば、事前にポリシーとルールを作成し、
$ gcloud beta compute security-policies create sample-policy $ gcloud beta compute security-policies rules create 1000 \ --security-policy sample-policy \ --description "Deny traffic from 192.0.2.0/24." \ --src-ip-ranges "192.0.2.0/24" \ --action "deny-404"
下記のようなBackendConfigを作るような形になっています。
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: sample-backend-config namespace: default spec: securityPolicy: name: sample-policy
現状ではKubernetesの世界で設定を完結できないようになっていますが、この辺りは下記のようにいずれK8sの世界で管理できるようになってくるのではないでしょうか。
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: sample-backend-config namespace: default spec: securityPolicy: - srcIPRange: 192.0.2.0/24 action: deny-404 priority: 1000
Configuring Cloud Armor | Kubernetes Engine | Google Cloud
Cloud IAP (Identity-Aware Proxy)
Cloud IAPは、GCP(GKE)上にデプロイされたアプリへのAccess Controlを行うサービスです。 事前にClient IDとClient SecretのデータをSecretに登録しておきます。
apiVersion: v1 kind: Secret metadata: name: sample-db-auth type: Opaque data: client_id: XXXXXXX client_secret: XXXXXXX
Cloud IAPの設定項目としては、Client IDとClient Secret になります。Secret経由で渡している場合には、Secret名を指定すれば問題ありません。
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: sample-backend-config namespace: default spec: iap: enabled: true oauthclientCredentials: secretName: my_secret # Secret で clientID と clientSecret を指定する場合は不要 # clientID: my_client_id # clientSecret: my_client_secret
Cloud CDN (Content Delivery Network)
Cloud CDNは、GCPのCDNです。 設定項目としてはキャッシュポリシーに関わるものがあります。
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: sample-backend-config namespace: default spec: cdn: enabled: true cachePolicy: includeHost: true includeProtocol: true includeQueryString: false QueryStringBlacklist: - "" QueryStringWhitelist: - ""
そのほかの設定
そのほかにもタイムアウトの設定や、セッションアフィニティの設定などを行うことも可能です。
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: sample-backend-config namespace: default spec: timeoutSec: 40 connectionDraining: drainingTimeoutSec: 60 sessionAffinity: affinityType: "GENERATED_COOKIE" affinityCookieTtlSec: 50
注意事項・参考資料
現在はまだ beta リリースなため、SLAが担保されていなかったり、後方互換のない変更が行われる可能性があるため注意してください。
BackendConfig custom resource | Kubernetes Engine | Google Cloud
Network Endpoint Groups (NEGs)
NEGsは、IPとPortのペアをネットワークエンドポイントとしてLoadBalancerの設定に利用するものです。 NEGsとPod Nativeなネットワーク(CalicoなどでPod Network / Internal Network に対してVM Networkから疎通性がある構成)を利用することで、LoadBalancerから直接Podまでリクエストを受けることができます。
通常はこのように、LoadBalancerからKubernetes Nodeに対してリクエストが送られると、Node上に到達した後に、再度負荷分散(2段階ロードバランシング)が行われます。 NodeからPodへのロードバランシング(kube-proxyの担当範囲)は、usermode・iptables・ipvsと3つのモードがありますが、いずれの場合にも一定の負荷・レイテンシの微増・分散のばらつきが生じます。
一方でNEGsを利用することで、直接Pod宛てに負荷分散を行うことができるため、これらの問題を低減することが可能です。
AWSの場合には、aws-vpc-cni-k8sとalb-ingress-controllerを使うと同様のことが実現できるそうです。(未検証)
Using container-native load balancing | Kubernetes Engine | Google Cloud
また、Ingressの実装の違いについては下記を参考にしてみてください。
(あ、こんなところにKubernetes 本...)