📚

kubernetesの基礎を学ぼう!~第1章 Workload API~

2023/12/28に公開

こんにちは!ヒロケイと申します!

ここ最近kubernetesに興味を持ち始め、基礎知識を蓄えてきました。

そこで、本シリーズからkubernetesの概要について、Dockerをほんのちょっと触ったことがある初学者でも分かるように解説していきます。

本シリーズでは特に、Kubernetesが提供しているAPIリソースでできることを網羅していきます。

以下のような読者を想定しています。

想定する読者

  • コンテナ技術については知っているが、複数のコンテナを管理、運用する方法を探している方
  • Kubernetesについて勉強したいけど、何から始めれば良いかわからない方
  • 公式ドキュメントや技術書を読むのが面倒くさくて、全体像を掴みたい方

Dockerを使って開発環境を整えたりした経験があれば、難なく読み進められるかと思います。

このシリーズでKubernetesでできることについて大枠を理解していただき、公式ドキュメントや技術書、勉強会での理解のサポートができればとても嬉しく思います!

第1章~第4章まで理解すると得られるもの

  • Kubernetesを使うとできることの半分くらいが理解できる
  • 技術イベントや勉強会で出てくる言葉の意味を理解でき、内容が大体理解できるようになる。
  • APIリソースの全体像を掴むことができる

扱わないテーマ

  • kubernetes環境を構築する方法
  • コンテナオーケストレーションを実現する上でのテクニック
  • kubernetesが提供する詳細な機能

まずは前提知識を揃えるために、kubernetesがなんなのかについて軽くまとめておきます!

kubernetesとは?

コンテナ化されたアプリケーションを効率的に管理するためのツール。

負荷によって柔軟にコンテナ数を増減

自動でコンテナをデプロイ

ローリングアップデートやロールバックによるコンテナのメンテナンス時間の削減

大量のコンテナを運用、管理するコンテナオーケストレーションを実現するツールの一つ。

参考プロダクショングレードのコンテナ管理基盤Kubernetes

コンテナオーケストレーションツールはKubernetes以外にも以下のようなものがある

  • Docker Swarm
  • AWS ECS
  • Apache Mesos

(本記事ではそれぞれの技術の違いについては詳しく解説していない。)

それでは、kubernetesの基礎学習へいってらっしゃい!

Workload API

Kubernetesを学習する上でまず一番最初に必要になるのが、APIリソースの理解です。

APIリソースとは、コンテナを管理するために提供している機能という認識で大丈夫です。

具体的なAPIリソースでできることを理解できると厳密な言葉の意味も自ずと理解できてきます。

Kubernetesが提供しているAPIリソースには、大きく分けて次のようなものがあります。

API名 概要
Workload API コンテナの実行に関するリソース
Service API コンテナを外部公開するときにエンドポイントを提供するリソース
Config, Strage API 環境変数や永続化に関するリソース
Cluster API セキュリティや割り当てに関するリソース
Metadata API クラスタ内の他のリソースを操作するリソース

今回は特にWorkload APIに着目して解説していきます。

Workload APIは、Kubernetesクラスタ内でコンテナを実行する際に使われる機能です。

コンテナに実行を管理するので、オーケストレーションを実装する上で一番重要となる基礎のリソースです。

そんなWorkload API。以下のようなリソースで構成されています。

Workload API 構成要素

  • Pod
  • ReplicaSet
  • Deployment
  • DaemonSet
  • StatefulSet
  • Job
  • CronJob

Pod

まずはPodから学んでいきましょう。

Podは、Kubernetesクラスタを構築する上での最小のデプロイメント単位です。

Podの中にDocker コンテナが格納されている構造です。

基本的にはPodの中に格納されているコンテナは1つであることが多いです。

しかし、コンテナへのリクエストの履歴を記録したり、コンテナをサポートするような機能を持ったサブのコンテナが格納されていることもあります。

Podの中にコンテナを配置するパターンについてはこちらが参考になりますので、是非ご覧ください。

参考Kubernetesで学ぶ分散システムデザインパターン

kubernetesクラスタは、Podの集合でできているといっても良いですね!

作ってみる

まず、どんなPodを作りたいかをマニフェストを描いて定義します。

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
      ports:
        - containerPort: 80

nginxイメージを使って80番ポートでコンテナを走らせる、nginx-podを作成します。

$ kubectl apply -f ./pod.yaml
pod/nginx-pod created
$ kubectl get po
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          47s

ReplicaSet

次にReplicaSetです。

ReplicaSetの役割は、同じ機能を持ったPodを複数起動させてくれるものです。

まさにコンテナオーケストレーションで提供できる機能の中核と言っても良いでしょう!

ReplicaSetのマニフェストにて指定したPodが常に起動されるように調整ができます。

起動しているPodが少なかったら増やすし、多かったら減らしてくれます。

Podを複数用意することで何が良いの?

高可用性

一部のコンテナが稼働していなくても、他のコンテナが処理を担ってくれるが故にサービスを利用することができる点。

負荷分散

コンテナに届くアクセス(トラフィック)や負荷が均等に分散されます。その結果、アプリケーションのパフォーマンスが向上する点。

セルフヒーリング

誤ってコンテナを削除、停止してしまっても、自動的にコンテナが立ち上がってくれるので、リスクマネジメントができる点

作ってみる

replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: sample-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: nginx:latest
          ports:
            - containerPort: 80
$ kubectl apply -f ./replicaset.yaml
replicaset.apps/sample-replicaset created
// 指定されたReplica数のPodが立ち上がっていることが確認できる
$ kubectl get pods -l app=my-app
sample-replicaset-6tsjf   1/1     Running   0          65s
sample-replicaset-6vw25   1/1     Running   0          65s
sample-replicaset-8l745   1/1     Running   0          65s

実は基本的にReplicaSet単体でマニフェストを書いて稼働させることはありません。

「もしコンテナをアップデートしよう!」となったとき、一度Podを全て停止して作り直す必要があります。

稼働しているPodが0になってしまう状態が発生するので、結果アプリケーションが利用できないダウンタイムが発生します。(サービスが利用できない時間が発生してしまう)

この課題を解決してくれるDeploymentを次で紹介しましょう!

Deployment

次はDeploymentです。

Deploymentは、ReplicaSetで管理している複数のPodのアップデートを宣言的に行えるリソースです。

宣言的アップデートとは、アップデート方法を細かく指定できるという認識で大丈夫です。

Deploymentの目玉となるアップデート戦略が、ローリングアップデート、ロールバック機能です。

稼働しているPodを残しつつ、徐々にアップデートできる機能です。

おかげでダウンタイムをかけずにアップデートできるようになっています。

また、失敗してもロールバックによってアップデート前の状態に戻せるため、失敗時のリスクも最小限に抑えることができる点が魅力的です。

アップデートが失敗しても障害が起きないことから人間がリアルタイムに監視している必要がないので、アップデート作業を自動化できるのも嬉しいポイントですね!

作ってみる

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: nginx:latest
          ports:
            - containerPort: 80
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
$ kubectl apply -f ./deployment.yaml
deployment.apps/sample-deployment created

イメージのバージョンを更新します。

-          image: nginx:latest  
+	  image: nginx:1.16
$ kubectl apply -f ./deployment.yaml
deployment.apps/sample-deployment configured
$ kubectl get po
sample-deployment-544587cc57-zg9sp   0/1     ContainerCreating   0          2s
sample-deployment-869fdcd9ff-6xkbd   1/1     Running             0          3m22s
sample-deployment-869fdcd9ff-q424l   1/1     Running             0          3m22s

maxUnavailable, maxSurgeに設定した値が反映され、1つのPodが削除され、新しく1つのPodが作成されているのが確認できますね!

DaemonSet

次はDaemonSetです。

DaemonSetは、各Node上にPodを一つ起動させるリソースです。

名前からどんな機能なのかがわからないですよねw

Daemonの意味

Daemonは悪魔(Demon)ではなく、ラテン語で霊を意味します。

一般にはコンピューターサイエンスの用語で、バックグラウンドで実行されるプログラムやプロセスを指しますね!

Nodeのトラフィックを監視したり、Podの出力ログを取得するためのPodを建てるときに使われることが多いです。

作ってみる

daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-daemonset
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-logging
  template:
    metadata:
      labels:
        name: fluentd-logging
    spec:
      containers:
      - name: fluentd
        image: fluent/fluentd:v1.12-debian-1
        ports:
        - containerPort: 24224
          protocol: TCP
        - containerPort: 5140
          protocol: UDP
        # (必要に応じて、追加の設定やマウントをここに追加)
$ kubectl apply -f ./daemonset.yaml
daemonset.apps/fluentd-daemonset created
// 今回の場合はNodeを一つ用意しているので、1つのfluentdPodが起動している。
$ kubectl get po
NAME                                 READY   STATUS    RESTARTS   AGE
fluentd-daemonset-n7j7h              1/1     Running   0          49s

StatefulSet

次はStatefulSetです。

StatefulSetは名前の通り、ステートフルなアプリケーションを構築する際に使われます。

ステートフルって?

「状態を持っている」ということ。

例えばデータベースが持っているデータとかは典型的ですね。

またStatefulSetは、扱うPodのホスト名を一貫してくれます。

Podが再起動した後でも、ホスト名が維持されるということですね。

作ってみる

statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-statefulset
spec:
  serviceName: "nginx"
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-data
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: nginx-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
$ kubectl apply -f ./statefulset.yaml
statefulset.apps/nginx-statefulset created
$ kubectl get statefulsets
NAME                READY   AGE
nginx-statefulset   3/3     31s

Job

次はJobです。

Jobは、単発の処理を行うPodを管理するものとして扱われています。

単発の処理を行うコンテナイメージってどんなものがあるの?
  • データベースのバックアップ取得
  • 不要なデータの削除(クリーンアップ)
  • DBに直接データを取得、編集

Podの稼働に直接影響はしないけど、運用上の操作が自動化できたり、同じ操作を何回も行える再利用性が便利ですね!

先ほど紹介したDeploymentやReplicaSetと違う点は、コンテナが正常終了することを前提としてPodを管理しているかです。

DeploymentやReplicaSetはPodが正常終了すると、指定したレプリカ数に達するまで新しくPodを起動し続けます。

しかし、Jobは指定した数のPodが正常終了したら処理が終わってくれます。

とても大きな違いですね!

作ってみる

job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: nginx-job
spec:
  template:
    spec:
      containers:
      - name: nginx-container
        image: nginx:latest
        command: ["echo", "Hello from the Job"]
      restartPolicy: Never
$ kubectl apply -f ./job.yaml
job.batch/nginx-job created
$ kubectl logs nginx-job-tnbp2
Hello from the Job

CronJob

次はCronJobです。

先ほどJobについて説明しましたが、Jobは手動で起動しないと処理を実行してくれません。

もし運用者が手動で動かさずにKubernetes側で自動でJobを実行してくれたら、めちゃめちゃ便利じゃないですか?

そこでCronJobの登場です。

CronJobとは、指定した時間に定期的にJobを実行させてくれるものです。

CronJobの使用例
  • データのクリーンアップ
  • データ分析結果を定期的にレポートとして作成
  • セキュリティチェック

作ってみる

cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nginx-cronjob
spec:
  schedule: '*/1 * * * *' # 1分ごとに実行
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: nginx-container
              image: nginx:latest
              command: ['echo', 'Hello from the CronJob']
          restartPolicy: OnFailure
$ kubectl apply -f ./cronjob.yaml
cronjob.batch/nginx-cronjob created
// 1分ごとに新しいPodが起動している
$ kubectl get po
nginx-cronjob-28395399-p95hd         0/1     Completed   0          67s
nginx-cronjob-28395400-82zlz         0/1     Completed   0          7s
$ kubectl logs nginx-cronjob-28395399-p95hd
Hello from the CronJob

まとめ

いかがでしたでしょうか?

Kubernetesクラスタを構築するためのベースがWorkload APIなので、このAPIの機能を理解できたらコンテナオーケストレーションを構築する力が身についていることでしょう!

次回は、Service APIです。
Podのネットワークを構築するために必要なAPIですので、ぜひ読んでみてくださいね!
kubernetesの基礎を学ぼう!~第2章 Service API~

Discussion