【Kubernetes超入門#05】ClusterIP、NodePort

Kubernetes超入門05 tech

こんにちは、Mashです。

本記事は、近年大注目されているコンテナオーケストレーション技術である Kubernetes について、図解と実機確認例を交えて解説するシリーズとなります。

今回は第5回。

前回までで、Pod/ReplicaSet/Deploymentと、コンテナの展開戦略について学びましたので今回からはK8s環境のネットワーク関連リソースをご紹介します。

今回のゴール
  • PodのIPアドレスを抽象化するリソース「ClusterIP」を理解する
  • Podをクラスタ外に公開するリソース「NodePort」を理解する

※本シリーズはLinuxコマンドやネットワーク、Dockerの基礎知識がある方を前提としています。

それではいきましょう!

環境

私の検証環境はこのようになっています。

  • 検証環境はUbuntu Server 20.04 LTSのサーバ1台構成(MasterとNodeを兼任)
  • 検証マシンへSSH接続済み
  • kubectlコマンドでK8sクラスタを操作
  • ノードがインターネットに接続していること
  • Kubernetesバージョンは1.19.4

イメージはこのような状態↓です。

Deploymentを展開し、NginxのPod(コンテナ)が3つ起動できており、curlコマンドでNginxのWelcomeページにアクセスできることまでを確認しました。

検証環境イメージ図

前述の通りPodが3つ展開できている状態ですが、K8s環境ではPodのIPアドレスはバラバラに割り当てられます。そして、有事の際はPodが再起動されることを前提としたコンセプトとなっています。

この状態では、毎回PodのIPアドレスを確認してアクセスする必要があります

Serviceリソース

そこで登場してくるのが、 ServiceというK8sリソースです。

svc

Serviceは、K8s環境におけるネットワーク経路を管理するリソースで、PodのIPアドレスを抽象化し、複数Podへの通信を分散したりK8sクラスタの外部へ公開したりします。

今回はよく使うものとしては下記2つをご紹介します。(実際には他にも存在します)

  1. ClusterIP
  2. NodePort

ClusterIP

まずはClusterIPからみていきましょう。

ClusterIPとは

ClusterIPはK8sクラスター内からアクセスできるL4ロードバランサーです。

K8s環境においてPodは常に起動・削除を繰り返します。そしてその都度PodのIPアドレスが変わります。

ClusterIPはこの「毎回変わるIPアドレス」を抽象化し、代表IPアドレスを提供します。

ClusterIPマニフェストとロードバランシング

ClusterIPを展開してみます。まずはマニフェストの作成から。

 vi nginx-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
  labels:
    app: nginx
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx

kindServiceに、そして spectypeClusterIP と指定します。

port ClusterIPの待受ポートtargetPortPod側の待受ポート(今回はNginxの80番)を指定します。

そして最後に selector で、ClusterIPにのバックエンドとなるPodを指定しています。

Deploymentのマニフェストを見返すと、このようにラベルが付与されています。keyが「app」、valueが「nginx」というラベルが付与されているリソースを探して紐付ける ということを自動的にやってくれています。

これが「サービスディスカバリ」機能です。

それではClusterIPを展開します。

# マニフェストからClusterIPリソースを展開
$ kubectl apply -f nginx-clusterip.yaml
service/nginx created

# 展開したClusterIPリソースのIPアドレスを確認
$ kubectl get service
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.43.228.90   <none>        80/TCP    38s

ClusterIPが展開できたので、ClusterIPアドレスにHTTPリクエストを投げてみましょう。

$ watch -n 1 "curl -s http://10.43.228.90/"
ClusterIP動作確認

毎回表示されるコンテナ名が変化している、つまりアクセス先のPodが変化していることがわかります。

ClusterIPが3つのPodに対するHTTPリクエストを分散してくれているわけですね!

図示するとこのようなイメージ↓です。今回はノードが1台ですが、複数ノードで構成されていても問題ありません。

ClusterIP実装後のイメージ図

NodePort

ClusterIPでPodへの通信分散もできるようになりました。

せっかくNginxPodが起動してるんだから、そろそろPCのWebブラウザでアクセスしてみようと思った方、、、

ざんねんですが、この時点ではまだWebブラウザでNginxへアクセスすることはできません(泣)

なぜかというと、、

さきほどClusterIPのIPアドレスを調べたところ、「10.42.228.90」でした。

そしてわたしのPCのIPアドレスは「10.10.1.1/24」です。

PCとK8sは別のネットワークなので通信ができないんです。(このあたりはTCP/IPネットワークの基礎知識が必要ですが割愛します)

そんなときに登場するのが K8s Serviceリソースの NodePort になります。

NodePortとは

NodePort はClusterIPを機能拡張したリソースで、ノードのIPアドレスをつかってPodへの接続経路をクラスタ外部に公開することができます。もちろんPodへの通信分散もしてくれます。

今回、わたしのPCのWebブラウザから(つまりK8sの外の世界から)Podへのアクセスを実現しようとしているので、NodePortが必要になります。

わたしのPCから検証用ノードはネットワーク接続済みなので、あとはいいかんじにアドレス変換してくれてPodへ到達できるようになります。

NodePortとPodの外部公開

NodePortをためしてみましょう。

$ vi nginx-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
  labels:
    app: nginx-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx

さきほど登場したClusterIPのマニフェストとほとんど違いはありません。spec.type の指定がNodePort になっているくらいです。

それでは展開しましょう。

$ kubectl apply -f nginx-nodeport.yaml

$ kubectl get service
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP   10.43.0.1      <none>        443/TCP        5d1h
nginx-clusterip   ClusterIP   10.43.202.73   <none>        80/TCP         22h
nginx-nodeport    NodePort    10.43.133.51   <none>        80:32704/TCP   22h

NodePortが ポート番号32704 で公開されていることが確認できました。

ちなみに、NodePortリソースで公開されるポート番号はデフォルト状態だと30000~32767のいずれかランダムに割り当てられます。

それではわたしのPCからブラウザでアクセスしてみます。。。!

これまで curl コマンドで確認していた内容がブラウザで確認することができました!

これでNodePortによるK8sクラスタ外へのPod公開は完了です。図示するとこのような状況になります。

まとめ

今回はK8sのネットワークリソース Service のうち、ClusterIPとNodePortをご紹介しました。

デモでご覧いただきませんでしたが、ClusterIPについては例えばWebサーバコンテナからPHPアプリコンテナへの通信分散/冗長化に利用したりもしますので、ぜひマスターしてください。

さて、つづいてもネットワークに関するリソースである Ingress をご紹介します。

IngressはL7ロードバランサーになります。

今回ご紹介したServiceと組み合わせることで、より柔軟なK8sネットワークを構築することができるようになる非常に重要なリソースですので、ぜひ次回をおたのしみに。

今回は以上です。

それじゃあまたね。

タイトルとURLをコピーしました