Skip to content

Instantly share code, notes, and snippets.

@pottava
Last active August 26, 2020 09:37
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pottava/8c24967e9022609ca03394de56ad385f to your computer and use it in GitHub Desktop.
Save pottava/8c24967e9022609ca03394de56ad385f to your computer and use it in GitHub Desktop.
本番環境のための GKE 構築 Tips

プロジェクト・ネットワーク・クラスタの構成

プロジェクト

  • GCP のすべてのリソースは プロジェクト の下に作成される
  • プロジェクトごとに請求や IAM の管理が可能
  • 本番やステージングといった複数環境のリソースを分離するためにもプロジェクトで分けよう

ネットワークとサブネットワーク

  • ネットワークはサブネットワーク・外部 IP アドレス・ファイアウォールルール・ルートなどをもつ

  • GCP ではパフォーマンスやシンプルさを追求し、リージョンを跨げるネットワークになっている

  • ファイアウォールはネットワークに対して設定できる

  • ファイアウォールはデフォルトで GKE ノードへの流入トラフィックは禁止している

  • サブネットワークは GKE クラスタへの IN/OUT トラフィックを隔離して制御する柔軟さを提供

  • プロジェクト作成時にデフォルトサブネットワークは作られるが、IP 管理上は別途作ることを推奨

  • サブネットワークはゾーンはまたげるが、リージョンはまたげない

  • サブネットワーク間の通信は、ファイアウォールルール上それが許可されている必要がある

  • プロジェクトデフォルトのサブネットワーク(Auto-mode)はデフォルトでそれが許可されている

  • 自作のサブネットワークの場合は新規ルールでサブネット間の通信許可をする必要がある

  • GKE クラスタやノード作成時に tag をつけておくとルート作成時に有用

IAM

プロジェクトレベルの制御

  • IAM ロールはユーザ、グループまたはサービスアカウントに対して関連づけることができる
  • 開発用プロジェクトと本番用プロジェクトがあるとして、それぞれに適切な IAM を設定する
  • 開発プロジェクトでは、開発者向けに container.developer ロールを
  • 本番プロジェクトでは、運用者向けに container.admin、セキュリティチームに container.viewer + security.admin、ネットワークチームに network.admin、CI/CD 自動化用サービスアカウントに container.developer ロールを渡すといった具合
  • 開発プロジェクトは複数の開発チームが使うことになるが、それは IAM ではなく k8s の Namespaces を使うことで競合が防げる
  • Namespaces を使えば利用できる CPU やメモリ、ストレージの上限も設定可能

RBAC 認証

  • k8s v1.6 以降であれば、各クラスタにおいて、各ユーザのより綿密な権限管理も可能
  • RBAC を使えば、ユーザごとに API レベルでクラスタに対し行えることを制御できる
  • GKE なら kubectl は gcloud からアクティブなクレデンシャルを受け取る仕組みなので
  • クラスタ管理者は、RoleBindings として GCP のユーザやサービスアカウントに適切な RBAC のロールが渡せる
  • これによりプロジェクトレベルだけでなく、クラスタレベル、または Namespace レベルでの綿密な権限管理が可能

コンテナイメージへのアクセス制御と共有

  • Google Container Registry(GCR)のイメージは、実際には GCS に格納されている
  • イメージを公開するには、バケットとオブジェクトを公開すれば OK
  • プロジェクトを横断してアクセスさせるには、サービスアカウントに storage.viewer ロールを付与すれば OK
  • ただしプロジェクトにデフォルトで作成されるサービスアカウントはプロジェクト全体の編集権限を持っているので注意

ネットワークの設定

k8s はクラスタ内の pod だけでなく、クラスタ外のサービスも含めたロードバランスや サービスディスカばりを サービス を使って抽象化しています。

同一クラスタ内での通信

  • k8s ではラベルを使い、特定の pod をまとめた サービス が定義できる
  • このサービスはクラスタ内では一意の DNS で表現され、探すことができる
  • クラスタ内で有効な DNS、kube-dns はサービス名を一連の healthy な IP に解決してくれる
  • デフォルトでは、サービスごとに固定で割り当てられた仮想 IP を返す
  • その仮想 IP にトラッフィックを向けると、kube-proxy に動的管理されたローカルノードの iptables に従い、適切な pod に送信される
  • 仮想 IP ではなく A レコードとして有効な pod の IP リストがほしければ、そのようにサービスを起動することもできる
  • ただしその場合、クライアントの DNS リゾルバがキャッシュしてしまうかもしれないし、ローテーションは非効率かもしれない

GCP 内から GKE クラスタへの接続

  • GCP のプライペート IP アドレス帯からのアクセスなら、Internal なロードバランサを使うべき
  • https://cloud.google.com/compute/docs/load-balancing/internal/
  • クラスタ外からのアクセスを受け入れるためには NodePort を指定することになるが
  • そうすると、クラスタ内全ノードの該当ポートが解放される
  • アクセス制御を確実なものにしたければ、ファイアウォールルールを追加で設定することもできる
  • GKE クラスタのノードは同一のインスタンスグループに所属しているので、それをロードバランサのバックエンドに指定できる
  • ロードバランサからはセッションアフィニティに基づいて該当ノードへトラフィックが割り振られるが
  • kube-proxy が適切にローカルの iptables を管理しているため、必要ならノード間でさらに適切な通信が起こる

クラスタ内から外部サービスへの接続

  • 方法は 3 つある
  • k8s v1.6 以降であれば、特定ドメインへの DNS クエリを外部 DNS サーバにフォワードできる
  • または外部サービスの DNS レコードをクラスタ内のサービス名に CNAME でマップすることもできる
  • またはセレクタなしで、エンドポイントを直指定したサービスを定義することもできる。ただしメンテコストは高い。
  • クラスタ内のサービスディスカバリと同じメカニズムで統一できるのは大きなメリットである

インターネットからのアクセス受け入れ

  • インターネットからのトラフィックを受け入れるには、k8s としては 2 つの方法がある
  • k8s のサービスを外部の TCP/UDP を受け入れる LoadBalancer タイプで作成するのが簡単
  • 結果生成される GCP の Network Load Balancer はリージョン縛りがあることに注意
  • または k8s で Ingress リソースを作り、サービスを NodePort タイプで生成し、Global HTTP(S) Load Balancer を使う
  • Global HTTP(S) Load Balancer なら一つの Anycast IP アドレスで複数リージョンをまたいだロードバランスが可能

ファイアウォール

  • すべての GKE ノードは GCE のインスタンスとして起動する
  • よってファイアウォールの仕組みもそれに倣った形をとることになる
  • デフォルトでは、ノードプールはそれ自身を特定する一意のタグが付与される
  • クラスタやノードプールの作成時に --tags でカスタムタグを持つこともできる
  • ファイアウォールのルールにはタグが利用できるので、それらを使えばクラスタへのアクセスが容易に制御できる
  • ロードバランサへのアクセスをオンプレの前面においた VPN からのみに制限したり

オンプレへの接続

  • いくつか Cloud Interconnect にも選択肢がある
  • ワークロードや要件に応じて組み合わせるといったこともできる
    1. インターネット経由: 膨大なデータでもレイテンシが重要でもなければ
    1. Direct Peering: L3 接続。専有帯域、低レイテンシ、GCP アクセスなどが必要なワークロードに
    1. Carrier Interconnect: AS 番号を持たない事業者向け、サービスプロバイダが提供する Direct Peering
    1. Cloud VPN: IPsec が必要な場合。自身のプライベートネットワークを GCE に拡張したい時。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment