Kubernetesの実体はPodやServiceなどのリソースです。したがって、どういったリソースがあるかをつかむことでKubernetesの全体像をイメージできます。

リソースに関する記述はYAMLであるため、少し割り切って言えば、Kubernetesを理解することは、YAMLにおけるリソースの記述方法を理解することとほぼ同義です。

Kubernetesのリソースは5つのリソースタイプに分類されます。前回説明したPod/ReplicaSet/DeploymentはWorkloadsに分類され、ServiceはDiscovery & LBに分類されます。リソースを定義するYAMLの記述方法の詳細はAPIドキュメントを参照ください。

Workloadsは前回紹介したPod/ReplicaSet/Deploymentなど、Kubernetesを構成する基本的なリソースです。今回は、Pod/ReplicaSet/Deployment以外のWorkloadsリソースを紹介します。

リソースタイプ

KubernetesのAPIドキュメント

DaemonSet

まずは、DaemonSetです。ReplicaSetがノードにいくつPodが配置されるかはKubernetesに委ねられるのに対し、DaemonSetはノードに1つずつPodを配置します。具体的な利用シーンとしては、ログ収集のエージェントなどがあります。

なお、特定ノードにのみリソースを配置する場合には、ノードに対してTaints/Tolerations設定を行います。

$cat daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      # NodeにTaints設定されているkey-valueを設定することで、配置可能となる
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: k8s.gcr.io/fluentd-elasticsearch:1.20
        # ボリューム設定
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
$kubectl apply -f daemonset.yaml
daemonset.apps/fluentd-elasticsearch created
$kubectl get daemonsets
NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluentd-elasticsearch   1         1         0       1            0           <none>          21s

StatefulSet

次にStatefulSetです。データベースなど、データの永続化の用途で利用されます。StatefultSetに2つのPodを立て、データを[index.html]ファイルに永続化する例をみてみましょう。

$cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        # マウントするボリュームのパス
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
$kubectl apply -f statefulset.yaml
service/nginx created
statefulset.apps/web created
$kubectl get statefulset web
NAME      DESIRED   CURRENT   AGE
web       2         1         37s

Pod名が[web-0]、[web-1]といった形で連番になるのが特徴です。以下の例では、連番である特徴を使って[for i in 0 1; do kubectl exec web-$i]の形でforループで各Podに対して処理を実行しています 。

$kubectl get pods -l app=nginx
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          2m
web-1     1/1       Running   0          1m
$for i in 0 1; do kubectl exec web-$i -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'; done
$for i in 0 1; do kubectl exec -it web-$i -- curl localhost; done
hello web-0
hello web-1

Job/CronJob

最後にJobとCronJobです。Jobはバッチ処理のようなケースを想定し、処理が終わったらPodが(正常)終了します。CronJobはJobをスケジュール実行するためのリソースです。LinuxのCrontabのようなイメージで実行時間は、分、時、日、月、曜日を指定できます。例えば、毎月10日の12:30に実行する場合は、「30 12 10 * *」といった形で指定します。

JobとCronJobの関係をつかむために、1分ごとに日時と「Hello Kubernetes」と返すだけのジョブを実行してみましょう 。

$vi cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello Kubernetes
          restartPolicy: OnFailure

$kubectl apply -f cronjob.yaml
cronjob.batch/hello created
$kubectl get cronjob
NAME      SCHEDULE      SUSPEND   ACTIVE    LAST SCHEDULE   AGE
hello     */1 * * * *   False     0         <none>          14s
$kubectl get job
NAME               DESIRED   SUCCESSFUL   AGE
hello-1539424740   1         0            5s
$kubectl get pods --selector=job-name=hello-1539425040 --output=jsonpath={.items..metadata.name}
hello-1539425040-9w7gf$
$kubectl logs hello-1539425040-9w7gf
Sat Oct 13 10:04:13 UTC 2018
Hello Kubernertes

*  *  *

今回は、5つのリソースタイプのうち、Workloadsを説明しました。前回説明したPod/ReplicaSet/Deploymentと併せて理解しておきましょう。

次回以降、Discovery&LBなどの残りのリソースタイプを説明していきます。

著者紹介


正野 勇嗣 (SHONO Yuji ) - NTTデータ 課長

2011年まで開発自動化技術のR&Dに従事。その後、開発プロジェクト支援やトラブルシューティング等に主戦場を移す。「ソースコード自動生成」に加えて、JenkinsやMaven等の「ビルド自動化」、JsTestDriverやSelenium等の「テスト自動化」を扱うようになり、多様化する開発自動化技術動向に興味。

最近は第四の自動化であるInfrastructure as Code等の「基盤自動化」の魅力に惹かれている。開発自動化技術に関する雑誌・記事執筆も行う。3児のパパ。