はじめに
- Google Container Engine のネットワーク関連の How To についてあとで参照できるように逆引き形式でまとめる
検証環境
- Google Container Engine
- Google Cloud SDK 172.0.1
- Kubernetes 1.7.6
GKE ネットワーク概要
- GKE クラスタは作成時に配備する
VPC ネットワーク
を選択する - VPC ネットワークは GCP コンソールや gcloud コマンドで作成できる
- VPC ネットワークはリージョンごとにサブネットワークを持つ
- VPC ネットワークは設定値としてファイアーウォール設定やルーティング設定を持つ
- ファイアーウォール設定はデフォルトで全ての内向き通信を拒否し全ての外向き通信を許可する
- 詳細は公式ドキュメントで
同一 Pod 内のコンテナ同士で通信する
- コンテナ設定の
containerPort
で設定しているポートであればhostname
コマンドで取得できるホスト宛に設定したポート番号でアクセスできる - 以下の設定の Pod なら
busybox
コンテナからwget http://$(hostname)
でnginx
コンテナに通信できる
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
hostname: nginx
containers:
- image: busybox
name: busybox
command:
- sleep
- "3600"
- image: nginx
name: nginx
ports:
- containerPort: 80
同一クラスタ内のコンテナ同士で通信する
- 同一クラスタ内であれば Pod の IP と公開しているコンテナのポートで直接アクセスできる
- クラスタ内の IP は可変なので静的な接続先が必要であれば NodePort サービスを使って内部 DNS で名前解決のできるドメイン名を使って通信できる
- 詳細は https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/ とか Headless Service とかで検索
Service の作成
- selecter 要素で指定したラベルのついた Pod に対して
[POD_NAME].[SERVICE_NAME].[NAMESPACE].logging.svc.cluster.local
でアクセスできる
apiVersion: v1
kind: Service
metadata:
name: [SERVICE_NAME]
namespace: [NAMESPACE]
spec:
ports:
- port: [SERVICE_PORT]
# [podname].broker.logging.svc.cluster.local
clusterIP: None
selector:
[KEY]: [VALUE]
設定例
- Pod
busybox1
の FQDN はbusybox-1.default-subdomain.my-namespace.svc.cluster.local
になる
apiVersion: v1
kind: Service
metadata:
name: default-subdomain
spec:
selector:
name: busybox
clusterIP: None
ports:
- name: foo # Actually, no port is needed.
port: 1234
targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1
subdomain: default-subdomain
containers:
- image: busybox
command:
- sleep
- "3600"
name: busybox
同一プロジェクトの別クラスタのコンテナ同士で通信する
- 異なるクラスタのコンテナ同士で通信をしたい場合は VPC ネットワークを作成し、それぞれのクラスタの作成時に同じネットワークに割り当てる
VPC ネットワークの作成
- GCP コンソールの「VPC ネットワーク > VPC ネットワーク」に移動
- 「VPC ネットワークを作成」で作成
- 名前と説明は任意で
- サブネット作成モードは「自動」なら全リージョン分サブネットを自動で作る、リソースを節約したい場合は「カスタム」で任意のリージョンにだけサブネットを作った方がいい
- カスタムの場合は名前とリージョンは任意
- IP アドレス範囲は多分「10.0.0.0/8」以下のクラス A のプライベート IP アドレスで適当に割り当てれば良さそう
ネットワーク作成コマンド
- コンソールの作成フォームから実行コマンドを参照することができる
- my-project プロジェクトで my-network ネットワークに my-sub-networm サブネットワークを asia-northeast1 リージョンで 10.0.0.0/24 の範囲で作成した場合
gcloud compute --project=my-project networks create my-network --mode=custom
gcloud compute --project=my-project networks subnets create my-sub-network --network=my-network --region=asia-northeast1 --range=10.0.0.0/24
コンテナの作成
- GCP コンソールから「Container Engine > コンテナクラスタ」で「クラスタを作成」で作成
- 同一ネットワークでサブネットワークを作成したリージョンで複数コンテナを作成する
疎通確認
- 複数のコンテナそれぞれで適当に Pod を作成
-
kubectl describe pods
で Pod の IP アドレスを確認 - 一方のコンテナで他方のコンテナに ping をする
kubectl exec -it [POD_NAME] -- ping [OTHER_POD_ID]
別コンテナの静的なエンドポイントを取得する
- Pod の IP での通信だと接続先が動的に変わるので扱いづらい
- コンテナが違うと内部 DNS による名前解決もできない
- そのため別コンテナで静的なエンドポイントを提供するために Internal Load Balancing を使う
Internal Load Balancing の作成
- Internal Load Balancing は内部向けのロードバランサで外部に公開する IP アドレスは持たない
- 同一ネットワークにあればデフォルトでルーティングしてくれるので別クラスタ同士でも固定された IP アドレスに接続しやすくなる
- 設定は以下の通り
-
type: LoadBalancer
で記載のアノテーションが指定されていれば Internal Load Balancing 扱いになる - [IP-ADDRESS] にはサブネットワークに指定した範囲の IP が割り当てられる
- とりあえずコメントにしておき割り当てられたら値を入れる
-
apiVersion: v1
kind: Service
metadata:
name: [SERVICE-NAME]
annotations:
cloud.google.com/load-balancer-type: "internal"
labels:
app: echo
spec:
type: LoadBalancer
loadBalancerIP: [IP-ADDRESS]
ports:
- port: 9000
protocol: TCP
selector:
[KEY]: [VALUE]
Internal Load Balancing の動作確認
- ステータスは普通に
kubectl describe service
で確認 - ping は通らないので公開したポートに telnet するとか実際にサービスを利用して確認する
別プロジェクトのコンテナ同士で通信する
クラスタ外部に静的 IP アドレスで HTTP サービスを公開する
- NodePort サービスと IP アドレスを作成し Ingress と関連づけて公開する
Service の作成
- NodePort タイプのサービスでクラスタ内にサービスを公開する
apiVersion: v1
kind: Service
metadata:
name: [SERVICE_NAME]
spec:
selector:
app: [APP_NAME]
ports:
- port: [APP_PORT]
type: NodePort
静的 IP アドレスを作成する
# IP アドレスの作成
gcloud compute addresses create [IP_ADDRESS_NAME] --global
# IP アドレスの確認
gcloud compute addresses describe [IP_ADDRESS_NAME] --global
Ingress の作成
- 作成した Service を公開する Ingress を作成する
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: [INGRESS_NAME]
annotations:
kubernetes.io/ingress.global-static-ip-name: [IP_ADDRESS_NAME]
spec:
backend:
serviceName: [SERVICE_NAME]
servicePort: [APP_PORT]
クラスタ外部に静的 IP アドレスで任意のサービスを公開する
- LoadBalancer サービスを作成し IP アドレスを静的に変更してサービス設定に IP アドレスを追加する
Service を作成する
- 確認した IP アドレスを設定する
apiVersion: v1
kind: Service
metadata:
name: [SERVICE_NAME]
spec:
type: LoadBalancer
ports:
- port: [APP_PORT]
selector:
app: [APP_NAME]
IP アドレスを確認する
- 作成したサービスに割り当てられている動的 IP アドレスを確認する
kubectl describe service [SERVICE_NAME]
- 出力の以下の行が IP アドレス
LoadBalancer Ingress: [IP_ADDRESS]
動的 IP アドレスを静的に変更する
- https://console.cloud.google.com/networking/addresses/list から対象の IP アドレスを探して、タイプを「静的」に変更する
Serivce 設定に IP アドレスを追加する
- spce の要素に以下を追加
loadBalancerIP: "[IP_ADDRESS]"