Kubernetesのオブジェクトについて ~マニフェストを添えて~


記事の目的

kubernetes(以下k8s)を触り始めるにあたり、Podなどの概念を理解していなかったので、リソース操作の基本的なオブジェクトの概要、マニフェストの書き方についてまとめておく。

オブジェクトについて

k8sのクラスターを表現するためのエンティティ。
k8sはオブジェクトで定義した状態を、コントロールプレーンが常に現在の状態の差分を埋め、理想の状態に管理します。
オブジェクトの操作方法は基本的にはkubectlコマンドを通して、マニフェストに記載したオブジェクトの状態を操作することが可能です。

オブジェクトでは以下のような状態を管理することができます。下の例はあくまでk8sでできることの一部であることに注意してください。

  • どのようなコンテナ化されたアプリケーションをデプロイするか
  • デプロイしたアプリのヒーリング機能
  • アプリのアップデート戦略

次の章からこれらの機能について具体的にどのオブジェクトを操作することで実現できるのかをまとめていきます。

なお、オブジェクトの説明については各章で説明の記載をしていますが、kubectl explain <object>で確認することが可能です。
たとえば、Podのspecフィールドにどのような項目を指定できるかなどはkubectl explain pods.specで確認することができます。

Pod

Podはk8sで管理できる最小のデプロイ可能な単位。
Podは1つ以上のコンテナを持ち、ストレージ、ネットワークのリソースを共有。
また、コンテナには実行方法に関するルールが指定可能です。

Pod内のコンテナは、コントロールプレーンによって、クラスター内の同じホスト上に自動的に配置、スケジュールされます。

基本的にはPodは直接デプロイされるものではありません。代わりにDeploymentやJobなどのワークロードリソースと呼ばれるものを使用してPodの作成を行います。

Podを直接デプロイする場合のマニフェストは以下の通り。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.18-alpine
    ports:
    - containerPort: 80
項目 説明
apiVersion オブジェクトが定義されているバージョン
kind オブジェトを表す文字列
metadata オブジェクトのメタデータ
metadata.name ネームスペース内で自身を表す一意な文字列
spec Podのふるまいを定義する
spec.containers Podで動作するコンテナの一覧。少なくとも1つの要素を持つ
spec.containers[].name DNS_LABELとしてのPod内でユニークな名前
spec.containers[].image Dockerイメージ名
spec.containers[].ports コンテナから公開するポート
spec.containers[].ports[].containerPort PodのIPアドレスで公開するポート番号

ReplicaSet

Podを指定した個数で維持することを目的としたオブジェクト。
Podの個数維持はk8sのセルフヒーリング機能で実現しています。

通常、DeploymentというReplicaSetにPodのアップデート機能を追加したオブジェクトを介してPodの個数維持を定義するため、アップデート機能を必要としない限りはReplicaSetを直接使うことは基本的にはないとおもいます。

ReplicaSetを作成するマニフェストは以下の通りです。

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: replicaset-nginx
  template:
    metadata:
      labels:
        app: replicaset-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18-alpine
        ports:
        - containerPort: 80
項目 説明
apiVersion オブジェクトが定義されているバージョン
kind オブジェトを表す文字列
metadata オブジェクトのメタデータ
metadata.name ネームスペース内で自身を表す一意な文字列
spec ReplicaSetのふるまいを定義する
spec.replicas 希望したいPod数
spec.selector ReplicaSetでスケールさせたいPodに一致させるためのクエリ。replica countと一致する必要がある
spec.selector.matchLabels スケールさせたいPodが持つラベルを指定。複数指定可能で、それらはAND条件
spec.template Pod章のspec配下の説明と同じ

Deployment

DeploymentはReplicaSetの機能に、Podのアップデート機能を追加したもの。

Deploymentを利用することで、ReplicaSetを作成したり、既存のDeploymentを新しいDeploymentにアップデートすることが可能になります。
アップデートではイメージなどの更新が走った際に、更新ルールにのっとってPodが順に切り替わっていきます。
試しにdeploymentをデプロイしたマニフェストのイメージなどのバージョンを変更して再度applyしなおすと、Podが切り替わっていく様子がkubectl get podsを通して確認できます。
アップデートの方法はいくつかの方法が存在し、マニフェストのspec.strategyで指定可能です。

Deploymentのマニフェストは以下の通りです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  labels:
    name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: deployment-nginx
  template:
    metadata:
      labels:
        app: deployment-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21-alpine
        ports:
        - containerPort: 80
項目 説明
apiVersion オブジェクトが定義されているバージョン
kind オブジェトを表す文字列
metadata オブジェクトのメタデータ
metadata.name ネームスペース内で自身を表す一意な文字列
metadata.labesl オブジェクトに付与するラベル
spec Deploymentのふるまいを定義する
spec.replicas 希望したいPod数
spec.selector Podに付与されたラベルを指定。これと一致するPodを持つReplicaSetをDeploymentで管理する
spec.selector.matchLabels スケールさせたいPodが持つラベルを指定。複数指定可能で、それらはAND条件
spec.template Pod章のspec配下の説明と同じ

Service

Podの集合に対して、ネットワークサービスとして公開するためのオブジェクト。

PodはそれぞれにIPアドレスが割り当てられますが、状況によってはPodは削除され再作成されます。
このとき、再作成されたPodのIPアドレスはもともとのPodのIPアドレスは異なってきます。
ServiceはこのPodの特定のために、セレクター機能を使うことで解決します。下のマニフェスト例ではspec.selectorapp: deployment-nginxのラベルを持つPodに対してservice-nginxという名前でアクセス可能になります。

また、Pod以外への通信も抽象化可能です。この場合、セレクターによる指定ではなくEndpointsオブジェクトを明示的に組み合わせることでk8s以外のコンポーネントへの通信も抽象化できます。

Serviceのマニフェストは以下の通りです。

apiVersion: v1
kind: Service
metadata:
  name: service-nginx
spec:
  selector:
    app: deployment-nginx
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80
項目 説明
apiVersion オブジェクトが定義されているバージョン
kind オブジェトを表す文字列
metadata オブジェクトのメタデータ
metadata.name ネームスペース内で自身を表す一意な文字列
spec Serviceのふるまいを定義する
spec.selector Podに付与されたラベルを指定。これと一致するPodを持つPodに対してServiceが通信を転送する
spec.ports サービスによって展開されるポートのリスト
spec.ports[].protocol Serviceで扱うプロトコル
spec.ports[].port Serviceによって公開したいPod側のポート
spec.ports[].targetPort portへの通信で、外部からアクセスする際に使用する外部のポート

参考資料