k8s_clearily_series⑤ Service
kubernetesついて明瞭に説明していく「k8s_clearily_series」の五回目になります。
前回の更新から1年ほど空いてしまいましたが、また徐々に更新をしていきたいと思っております。
第五回はkubernetesにスケジューリングされたPod間連携と外部公開に必要な「Service」について下記に記載の4つの観点から詳細な説明をさせていただきます。
- Serviceにおける目的・役割・用途について
- Pod内通信とPod外部公開通信について
- Serviceリソースの種類について
- ServiceリソースのYamlファイルとコマンドでの入力
Serviceにおける目的・役割・用途について
Serviceリソースは、kubernetesにスケジューリングされたPodに対して、内部に配置されたPod間通信(内部連携)とPodに作成されたアプリケーションを外部に公開するために安定したエンドポイントを提供するkubernetesのオブジェクトになります。
Serviceにおける目的、役割、用途の概要を下記に記載します。
- STEP1:目的
PodのIPアドレスが動的に変化をしてしまう為、それに対応できるようにServiceリソースにて「エンドポイント」「固定IP」「DNS名」の提供を行い、安定したPodへのアクセス手段を提供するための目的があります。

- STEP2:役割
kubernetesクラスター内における通信の境界をなくし、Podへの振り分けを行って、到達までに名前解決を実施する。この3つの役割をもっております。

- STEP3:用途
対象のPodに対して「外部公開」「内部通信」「直接通信」「外部連携通信」など、状況に合わせたServiceリソースの選択を行い、用途によって適用を行います。

Pod内通信とPod外部公開通信について
Serviceリソースの用途として「内部通信」「外部公開」「直接通信」「外部連携通信」。これら4つの用途についてお話させていただきました。ここではServiceの基本となる「内部通信」と「外部公開」の2つについて詳細なお話をさせていただきます。
STEP1:内部通信(Pod間通信)
kubernetesにおける内部通信についてですが、基本はServiceリソースを介しての通信が基本になります。Serviceリソースを介して通信をすることによって、kubernetesクラスター内であれば、Nodeが別であったとしてもServiceリソースを介しての通信になりますので、複数のNodeに対してPod間の連携設定などをしなくてもよいのが特徴になります。

※Pod間通信において制限を掛ける設定もありますが、それはserviceとは別のNetworkpolicyで制限を行うことになります。
STEP2:外部公開(Pod外部公開通信)
Serviceリソース自体に外部からの窓口および振り分けをする役割を与えることによって、外部からPod(アプリケーション)へのアクセスが可能となります。

※kubernetesクラスター外からPodへの通信には、Serviceリソースの「NodePort」や「LoadBalancer」を利用して通信を実施する(Serviceリソースの種類は次項で説明)
つまりkubernetesにおけるServiceリソースとは、kubernetesクラスター内にスケジューリングされたPodへの”ルーティングと負荷分散”を担うゲートのような存在となっております。それは内部連携および外部通信を問わず安定してPodに到達させる仕組みをもっている機能となっております。
Serviceリソースの種類について
kubernetesでServiceリソースの基本として分類されるものは次の5つになります。
「CluserIP」「NodePort」「LoadBalancer」「Headleess Service」「ExternalName Service」ではこの5つについて詳細なお話をさせていただきます。
- ClusterIP
クラスター内部でのみ有効な仮想IPアドレスになります。このIPアドレスをServiceそのものとして使用し、Pod間通信を中継する仕組みです。注意点は外部アクセスができないことです。

- NodePort
Kubernetes クラスタの各Nodeに開放される特定のポート番号を通じて、外部から内部のService(Pod)にアクセスできる仕組みです。

- LoadBalancer
外部公開の最短ルートとして使用するServiceリソースになります。オンプレミスおよびクラウド環境で使用することができ、実際のネットワークにて固定のパブリックIPが払い出されるため、DNSレコードと紐づけて独自ドメインにアクセスすることが可能となるものになります。

※LoadBalancerには、AWSやGoogle Cloudなどのサービスを利用するのが一般的になります。オンプレミスで利用する場合には、MetalLBを使用してLoadBalancerとして使用するケースもございますが、通信の経路は上記と同じになります。
- Headless Service
Kubernetes内部DNSの名前解決だけに特化したServiceとなっており、ロードバランシングせずに、DNS クエリに対して Pod の IP アドレス(複数可)を直接返すものとなります。

- External Name Service
Kubernetes 内から外部の DNS 名(FQDN)へ名前解決でアクセスするためのserviceリソースになります。用途としては、外部DB/API への統一的なアクセス方法を提供したいときなどに使用します。

これら5つのServiceリソースを使い分けることによって、「内部連携」「外部公開」「名前解決とDB連携」「外部サービス連携」などをPodに対し効率的にkubernetesの運用管理を行うことができるようになります。
ServiceリソースのYamlファイル
ServiceリソースにおけるYamlファイルの基本的な記載は方法が下記になります。
apiVersion: v1
kind: Service #⓵
metadata:
name: my-service #⓶
namespace: my-space #⓷
labels:
app: my-app #⓸
spec:
selector:
app: my-app #⓹
ports:
- protocol: TCP #⓺
port: 80 #⓻
targetPort: 8080 #⓼
type: ClusterIP #⓽
①:Serviceリソースの指定(「S」は大文字になります)
②:Serviceの名前
③:指定するNamespace
④:Serviceに付与するラベル
⑤:作成するServiceがターゲットとするPodのラベル
⑥:Serviceを公開するプロトコル(TCP / UDP / SCTPなど)
⑦:Serviceのポート番号
⑧:Podの番号
⑨:Serviceリソースの指定(CluserIP / NodePort / LoadBalancer /ExternalNameなど)
※Headleess Serviceのみtypeの指定することができません。Headleess Serviceを使用する際には、下記のようにSpecの配下にcluserIPと指定を行い、「None」と記載すればHeadleess Serviceとして使用することが可能となります。
apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
clusterIP: None ※
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
kubectlコマンドを使用して作成する方法もあります。
kubectl create service clusterip my-service --tcp=80:8080 --dry-run=client -o yaml
- kubectl コマンドを使用して、「dry-run=client -o yaml」で出力されたYamlファイルが下記になります。
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: my-service
name: my-service
spec:
ports:
- name: 80-8080
port: 80
protocol: TCP
targetPort: 8080
selector:
app: my-service
type: ClusterIP
status:
loadBalancer: {}
また、予めPodが作成されているのであれば kubectl exposeコマンドを使用して、作成されているPodにServiceリソースを当てはめる方法もあります。
kubectl expose pod <pod-Name> --name=my-service --type=ClusterIP --port=80 --targetport=8080
実際にこのコマンドも「dry-run=client -o yaml」でYamlファイルの出力を行うことも可能となっております。
まとめ
今回はServiceの目的・役割と用途。それに加えてPod間通信、Pod外部公開通信の説明を行い、状況によってPodに対して、効率的な通信を行うため、5つのServiceリソースについてお話させていただきました。
次回はDaemonSetのことについてお話させていただきます。