TT Lab
はじめる
学ぶ 学習パス コース

CKAD — Kubernetesアプリケーション開発者

Service、Ingress、NetworkPolicy

TT Labで続きを見る

目標

Serviceの3種類のポートを区別して指定し、named port・ヘッドレス・StatefulSetのDNS・Ingressのルーティング・NetworkPolicyの許可リストをマニフェストとして書けるようになります。

なぜ重要なのか

Serviceで出るミスは、ほぼ2つだけです。セレクターがPodのラベルと違うことと、3つのポートを混同することです。セレクターがずれると、エラーなくエンドポイントが空になり、クライアントには接続拒否だけが見えます。kubectl get endpointsが空かどうかを確認する習慣1つで、時間の大半を節約できます。

ポートは方向で覚えると混乱しません。portは入ってくる側(クライアントがServiceに接続するポート)、targetPortは出ていく側(ServiceがPodに接続するポート)、nodePortは外から入ってくる側(ノードで開くポート)です。

ヘッドレスServiceは、ロードバランシングをあきらめる選択です。仮想IPを作らず、DNSがPodのIPリストをそのまま返し、StatefulSetとペアにするとPodごとに固有の名前ができます。クライアントが特定のインスタンスを指名する必要があるワークロード(DBのプライマリ、シャード)に使います。

NetworkPolicyは、デフォルトは許可、ポリシーが付くと許可リストという2つの文に要約されます。そのため実務では、まずネームスペース全体にデフォルトの遮断を設定し、必要な通信だけを開けます。ポリシー同士は互いを上書きせず、和集合として加算される点も覚えておいてください。

ステップ

  1. ネームスペースckad-netを作成してください。Deployment frontend(レプリカ2、ラベルapp=frontend、イメージnginx:1.27、コンテナポート80に名前http)と、Service frontend(ClusterIP、port: 80、targetPort: 80、セレクターapp=frontend)を作成してください。
  2. Deployment backend(レプリカ2、ラベルapp=backend、イメージnginx:1.27、コンテナポート8080に名前api)と、Service backend(ClusterIP、port: 80、targetPort: apiを名前で指定、セレクターapp=backend)を作成してください。
  3. Service frontend-npを作成してください。タイプはNodePort、port: 80、targetPort: 80、nodePort: 30080、セレクターはapp=frontendです。
  4. ヘッドレスService cache-hs(clusterIP: None、port: 6379、セレクターapp=cache)とStatefulSet cache(レプリカ3、serviceName: cache-hs、ラベルapp=cache、イメージnginx:1.27)を作成してください。そして、インデックス0のPodの完全なDNS名を、/root/ckad-net/dns.txtに1行で書いてください。
  5. Ingress shopを作成してください。ingressClassName: nginx、ホストshop.ckad.local、パス/(pathType Prefix) → Service frontendのポート80、パス/api(pathType Prefix) → Service backendのポート80にします。
  6. NetworkPolicy backend-allow-frontendを作成してください。対象はapp=backendのPod、policyTypes: [Ingress]、許可する送信元はapp=frontendのPod、ポートはTCPの8080です。
  7. NetworkPolicy default-deny-ingressを作成してください。podSelector: {}(ネームスペース全体)、policyTypes: [Ingress]、ingressルールは空のままにします。この時点で、Service backendのセレクターが実際にPodを2つ以上選んでいるかを、kubectl get pods -n ckad-net -l app=backendで確認してください。

参考

DeploymentとClusterIP Serviceを作成する

ネームスペースckad-netを作成してください。Deployment frontend(レプリカ2、ラベルapp=frontend、イメージnginx:1.27、コンテナポート80に名前http)と、Service frontend(ClusterIP、port: 80、targetPort: 80、セレクターapp=frontend)を作成してください。

kubectl expose deploymentを使うか、Serviceを直接書きます。Serviceのセレクターが、Podのラベルとまったく同じでなければ、エンドポイントが付きません。コンテナのポートに名前を付けておくと、次のステップが楽です。

named portでtargetPortを接続する

Deployment backend(レプリカ2、ラベルapp=backend、イメージnginx:1.27、コンテナポート8080に名前api)と、Service backend(ClusterIP、port: 80、targetPort: apiを名前で指定、セレクターapp=backend)を作成してください。

コンテナのports[].nameに付けた名前を、ServiceのtargetPortに文字列として書きます。名前は15文字以下の小文字/数字/ハイフンである必要があります。

NodePortで外部に公開する

Service frontend-npを作成してください。タイプはNodePort、port: 80、targetPort: 80、nodePort: 30080、セレクターはapp=frontendです。

タイプをNodePortにして、nodePortを直接指定します。許可される範囲は30000–32767で、指定しなければ自動で割り当てられます。portとtargetPortはそのまま残ります。

ヘッドレスServiceとStatefulSetを作成する

ヘッドレスService cache-hs(clusterIP: None、port: 6379、セレクターapp=cache)とStatefulSet cache(レプリカ3、serviceName: cache-hs、ラベルapp=cache、イメージnginx:1.27)を作成してください。そして、インデックス0のPodの完全なDNS名を、/root/ckad-net/dns.txtに1行で書いてください。

ヘッドレスはclusterIP: Noneです。StatefulSetのserviceNameにそのService名を書いて初めて、PodごとのDNS名ができます。名前の規則は、Pod名・Service名・ネームスペースの順にドットでつなぎます。

Ingressでホストとパスのルーティングを設定する

Ingress shopを作成してください。ingressClassName: nginx、ホストshop.ckad.local、パス/(pathType Prefix) → Service frontendのポート80、パス/api(pathType Prefix) → Service backendのポート80にします。

networking.k8s.io/v1で、バックエンドはservice.nameとservice.port.numberで指定します。各パスにはpathTypeが必須です。ルールはrules[].hostとrules[].http.paths[]の構造です。

NetworkPolicyでフロントエンドだけを許可する

NetworkPolicy backend-allow-frontendを作成してください。対象はapp=backendのPod、policyTypes: [Ingress]、許可する送信元はapp=frontendのPod、ポートはTCPの8080です。

podSelectorはポリシーが適用される対象を、ingress[].from[].podSelectorは許可する送信元を指します。2つを取り違えやすいので注意してください。ポートも一緒に絞ります。

デフォルト遮断ポリシーとセレクターを点検する(総合)

NetworkPolicy default-deny-ingressを作成してください。podSelector: {}(ネームスペース全体)、policyTypes: [Ingress]、ingressルールは空のままにします。この時点で、Service backendのセレクターが実際にPodを2つ以上選んでいるかを、kubectl get pods -n ckad-net -l app=backendで確認してください。

空のpodSelector: {}は、ネームスペースのすべてのPodを意味します。ここにingressルールを1つも置かないと、デフォルトの遮断になります。そして、Serviceのセレクターが実際のPodを選んでいるかを、kubectl get pods -lで直接確認します。