このドキュメントでは、Google Distributed Cloud のユーザー、ハイブリッド、またはスタンドアロン クラスタで Kubernetes Ingress オブジェクトを作成する方法について説明します。1 つの Ingress は 1 つ以上の Service オブジェクトに関連付けられます。それぞれの Service オブジェクトは、Pod のセットに関連付けられます。
Deployment を作成する
Deployment のマニフェストを次に示します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
selector:
matchLabels:
greeting: hello
replicas: 3
template:
metadata:
labels:
greeting: hello
spec:
containers:
- name: hello-world
image: "gcr.io/google-samples/hello-app:2.0"
env:
- name: "PORT"
value: "50000"
- name: hello-kubernetes
image: "gcr.io/google-samples/node-hello:1.0"
env:
- name: "PORT"
value: "8080"
この演習を進めるにあたって、この Deployment のマニフェストについて次のことを理解しておくことが重要です。
Deployment に属する各 Pod には
greeting: hello
ラベルが付いています。各 Pod には 2 つのコンテナがあります。
env
フィールドは、hello-app
コンテナは TCP ポート 50000 でリッスンし、node-hello
コンテナは TCP ポート 8080 でリッスンするように指定します。hello-app
の場合、ソースコードを見るとPORT
環境変数の効果がわかります。
このマニフェストを hello-deployment.yaml
という名前のファイルにコピーして Deployment を作成します。
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml
CLUSTER_KUBECONFIG
は、クラスタの kubeconfig ファイルの名前に置き換えます。
Service を使用して Deployment を公開する
クライアントが Deployment の Pod にリクエストを安定して送信するには、Service を作成します。
Deployment をクラスタ内のクライアントに公開する Service のマニフェストは次のとおりです。
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
type: ClusterIP
selector:
greeting: hello
ports:
- name: world-port
protocol: TCP
port: 60000
targetPort: 50000
- name: kubernetes-port
protocol: TCP
port: 60001
targetPort: 8080
マニフェストを hello-service.yaml
という名前のファイルにコピーして、Service を作成します。
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-service.yaml
CLUSTER_KUBECONFIG
は、クラスタの kubeconfig ファイルの名前に置き換えます。
Service を表示します。
kubectl --kubeconfig CLUSTER_KUBECONFIG get service hello-service --output yaml
出力には、Service に対して指定された clusterIP
の値が表示されます。例:
apiVersion: v1
kind: Service
metadata:
annotations:
...
spec:
clusterIP: 10.96.14.249
clusterIPs:
- 10.96.14.249
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
selector:
greeting: hello
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
上述の出力では、ports
フィールドは ServicePort
オブジェクトの配列であり、1 つは world-port
、もう 1 つは kubernetes-port
という名前です。Service フィールドの詳細については、Kubernetes ドキュメントの ServiceSpec をご覧ください。
クライアントが Service を呼び出す方法は次のとおりです。
world-port
の使用: クラスタノードのいずれかで実行されているクライアントが、port
のclusterIP
にリクエストを送信します。この例では、10.96.14.249:60000 です。リクエストは、targetPort
上のメンバー Pod に転送されます。この例では、POD_IP_ADDRESS:50000
です。kubernetes-port
の使用: クラスタノードのいずれかで実行されているクライアントが、port
のclusterIP
にリクエストを送信します。この例では、10.96.14.249:60001 です。リクエストは、targetPort
上のメンバー Pod に転送されます。この例では、POD_IP_ADDRESS:8080
です。
Ingress コンポーネント
Ingress に関連する一部のクラスタ コンポーネントは次のとおりです。
istio-ingress
Deployment。これは上り(内向き)プロキシです。上り(内向き)プロキシは、Ingress オブジェクトで指定されたルールに従ってトラフィックを内部 Service に転送します。istio-ingress
Service。この Service は、istio-ingress
Deployment を公開します。istiod
Deployment。これは上り(内向き)コントローラです。上り(内向き)コントローラは、Ingress オブジェクトの作成を監視し、それに応じて Ingress プロキシを構成します。
これらのクラスタ内 Istio コンポーネントはすべて、gke-system
Namespace にインストールされます。この Namespace は、Istio / Cloud Service Mesh の完全なインストールと競合しません。
Ingress を作成する
Ingress のマニフェストを次に示します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- http:
paths:
- path: /greet-the-world
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60000
- path: /greet-kubernetes
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60001
このマニフェストを my-ingress.yaml
という名前のファイルにコピーし、次のようにして Ingress を作成します。
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress.yaml
ユーザー クラスタを作成する場合は、クラスタ構成ファイルで loadbalancer.ingressVIP
の値を指定します。この IP アドレスは、クラスタ ロードバランサ上に構成されます。Ingress を作成すると、Ingress には、その外部 IP アドレスと同じ VIP が付与されます。
クライアントがユーザー クラスタの上り(内向き)VIP にリクエストを送信すると、そのリクエストはロードバランサに転送されます。ロードバランサは、istio-ingress
Service を使用してユーザー クラスタで実行される Ingress プロキシにリクエストを転送します。Ingress プロキシは、リクエスト URL のパスに応じて、異なるバックエンドにリクエストを転送するように構成されています。
/greet-the-world
パス
Ingress マニフェストで、パス /greet-the-world
が serviceName: hello-service
と servicePort: 60000
に関連付けられていることを示すルールを確認できます。hello-service
Service の world-port
セクションの port
値が 60000 であることを思い出してください。
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
Ingress サービスが、リクエストを clusterIP
:50000 に転送します。その後、リクエストは、hello-service
Service のメンバー Pod のいずれかに送信されます。送信された Pod 内のポート 50000 でリッスンするコンテナに、Hello World!
メッセージが表示されます。
/greet-kubernetes
パス
Ingress マニフェストで、パス /greet-kubernetes
が serviceName: hello-service
と servicePort: 60001
に関連付けられていることを示すルールを確認できます。hello-service
Service の kubernetes-port
セクションの port
値が 60001 であることを思い出してください。
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
Ingress サービスはリクエストを clusterIP
: 8080 に転送します。その後、リクエストは、hello-service
Service のメンバー Pod のいずれかに送信されます。送信された Pod 内のポート 8080 でリッスンするコンテナに、Hello Kubernetes!
メッセージが表示されます。
Ingress をテストする
/greet-the-world
パスを使用して Ingress をテストします。
curl CLUSTER_INGRESS_VIP/greet-the-world
CLUSTER_INGRESS_VIP
は、Ingress の外部 IP アドレスに置き換えます。
出力には、Hello, world!
メッセージが表示されます。
Hello, world!
Version: 2.0.0
Hostname: ...
/greet-kubernetes
パスを使用して Ingress をテストします。
curl CLUSTER_INGRESS_VIP/greet-kubernetes
出力には、Hello, Kubernetes!
メッセージが表示されます。
Hello Kubernetes!
バンドルされた Ingress を無効にする
Google Distributed Cloud にバンドルされた Ingress 機能は上り(内向き)機能のみをサポートしています。Istio または Cloud Service Mesh と統合することも選択できます。これらのプロダクトには、相互 TLS(mTLS)、サービス間の認証を管理する機能、ワークロードのオブザーバビリティなど、完全に機能するサービス メッシュの追加の利点があります。Istio または Cloud Service Mesh と統合する場合は、バンドルされた Ingress 機能を無効にすることをおすすめします。
バンドルされた Ingress を有効または無効にするには、クラスタ構成ファイルの spec.clusterNetwork.bundledIngress
フィールドを使用します。このフィールドは、バージョン 1.13.0 以降のクラスタでのみ使用できます。bundledIngress
フィールドはデフォルトで true
になり、生成されたクラスタ構成ファイルには存在しません。このフィールドは可変で、バージョン 1.13.0 以降のクラスタを作成または更新するときに変更できます。このフィールドは、クラスタをバージョン 1.13.0 以降にアップグレードするときにも指定できます。
次のクラスタ構成ファイルのサンプルは、バンドルされた Ingress 機能を無効にするようにクラスタを構成する方法を示しています。
apiVersion: v1
kind: Namespace
metadata:
name: cluster-hybrid-basic
---
apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
name: hybrid-basic
namespace: cluster-hybrid-basic
spec:
type: hybrid
profile: default
anthosBareMetalVersion: 1.13.0
gkeConnect:
projectID: project-fleet
controlPlane:
nodePoolSpec:
nodes:
- address: 10.200.0.2
clusterNetwork:
bundledIngress: false
pods:
cidrBlocks:
- 192.168.0.0/16
services:
cidrBlocks:
- 10.96.0.0/20
...
Ingress 用に HTTPS を設定する
クライアントからの HTTPS リクエストを受け入れるには、Ingress プロキシは証明書を持っていなければなりません。これにより、適切な送信先であることをクライアントに示すことができます。このプロキシには、HTTPS handshake を実行するための秘密鍵も必要です。
以下の例では、次のエンティティを使用します。
Ingress プロキシ: HTTPS handshake に加わり、パケットを
hello-service
Service のメンバー Pod に転送します。hello-service
Service のドメイン: Example Org の altostrat.com
手順は次のとおりです。
ルート証明書と秘密鍵を作成します。この例では、Root CA Example Org の
root.ca.example.com
のルート認証局を使用します。openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj \ '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key \ -out root-ca.crt
証明書署名リクエストを作成します。
openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \ "/CN=altostrat.com/O=Example Org"
Ingress プロキシのサービス証明書を作成します。
openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 \ -in server.csr -out server.crt
これで、次の証明書と鍵が作成されました。
root-ca.crt
: ルート CA の証明書root-ca.key
: ルート CA の秘密鍵server.crt
: Ingress プロキシの証明書を提供server.key
: Ingress プロキシの秘密鍵
サービス提供側の証明書と鍵を保持する Kubernetes Secret を作成します。
kubectl create secret tls example-server-creds --key=server.key --cert=server.crt \ --namespace gke-system
生成された Secret の名前は
example-server-creds
です。
Deployment と Service を作成する
このガイドの HTTP 部分で Deployment と Service を作成した場合は、そのままにしておきます。作成していない場合は、HTTP 用の手順に沿って作成します。
Ingress を作成する
HTTP の部分で Ingress をすでに作成している場合は、その Ingress を削除して続行します。
Ingress を削除します。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
以前に作成した Service のトラフィックを処理するには、tls
セクションを持つ新しい Ingress を作成します。これにより、クライアントと上り(内向き)プロキシ間の HTTPS が有効になります。
Ingress のマニフェストを次に示します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-2
spec:
tls:
- hosts:
- altostrat.com
secretName: example-server-creds
rules:
- host: altostrat.com
http:
paths:
- path: /greet-the-world
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60000
- path: /greet-kubernetes
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60001
このマニフェストを my-ingress-2.yaml
という名前のファイルに保存して、Ingress を作成します。
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
テストして確認します。
/greet-the-world
パスをテストします。curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP\ https://altostrat.com/greet-the-world \ --cacert root-ca.crt
出力:
Hello, world! Version: 2.0.0 Hostname: hello-deployment-5ff7f68854-wqzp7
/greet-kubernetes
パスをテストします。curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \ https://altostrat.com/greet-kubernetes --cacert root-ca.crt
出力:
Hello Kubernetes!
LoadBalancer Service を作成する
LoadBalancer
タイプの Service は、クラスタ外部にワークロードを公開する別の方法です。LoadBalancer
タイプの Service を作成する手順と例については、アプリケーションのデプロイの LoadBalancer
タイプの Service の作成をご覧ください。
クリーンアップ
Ingress を削除します。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
INGRESS_NAME
は、Ingress の名前(my-ingress
や my-ingress-2
など)に置き換えます。
Service を削除します。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
Deployment を削除します。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
LoadBalancer Service を削除します。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports