@amsy810's Blog

~Kubernetes / Cloud Native / Docker / etc~

【Kubernetes】GKEのBackendConfigとNetwork Endpoint Groups(NEGs)

この記事は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は、GCPCDNです。 設定項目としてはキャッシュポリシーに関わるものがあります。

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つのモードがありますが、いずれの場合にも一定の負荷・レイテンシの微増・分散のばらつきが生じます。

f:id:masaya_aoyama:20181206035829p:plain

一方でNEGsを利用することで、直接Pod宛てに負荷分散を行うことができるため、これらの問題を低減することが可能です。

f:id:masaya_aoyama:20181206035824p:plain

AWSの場合には、aws-vpc-cni-k8sとalb-ingress-controllerを使うと同様のことが実現できるそうです。(未検証)

Using container-native load balancing  |  Kubernetes Engine  |  Google Cloud

また、Ingressの実装の違いについては下記を参考にしてみてください。

speakerdeck.com

(あ、こんなところにKubernetes 本...)

www.amazon.co.jp