TechLunch

The free lunch is over.

Kubebuilder: Kubernetes APIを開発するためのSDK

Kubernetesブログで、Kuberbuilderに関する記事がポストされました。

Kubebuilderは、KubernetesのCRD (Custom Resource Definition)を利用して、独自のKubernetes APIとカスタムコントローラを構築するためのSDK (Software Development Kit) です。 これを利用し独自APIとコントローラを開発することで、MySQLやSpark, CassandraといったアプリケーションをKubernetesのPodと同じように管理することができるようになります。つまり、アプリケーションをStatefulSetやSevice、ConfigMapのコレクションではなく、ファーストクラスのAPIで管理可能となります。

Kubebuilderを利用せずに独自コントローラを開発するには、

However, while it has been possible for trailblazers to build new Controllers on top of the raw API machinery, doing so has been a DIY “from scratch” experience, requiring developers to learn low level details about how Kubernetes libraries are implemented, handwrite boilerplate code, and warp their own solutions for integration testing, RBAC configuration, documentation, etc.

と記事に書かれているように、Kubernetesについて深い知識が必要でしたが、Kubebuilderを利用することで詳細が隠蔽されるため、比較的容易にコントローラを開発することができるようです。

Kuberbuilderの書籍もあるようなので、興味がある方は試してみたらいかがでしょうか。

PrometheusがKubernetesに続きCNCFのGraduatedプロジェクトになりました

モニタリングツールとして広く使われているPrometheusが、CNCFのGraduatedプロジェクトとなったことを発表しました。

Kubernetesに続く卒業となります。CNCFがホストするプロジェクトは多くあり、既に商用で利用されているOSSもありますが、現在のところGraduatedは、KubernetesとPrometheusの2つだけです。Graduation Stageに到達するためには、CNCFの定めた規準を満たす必要があり、両者の成熟度や安定度は高いといえるでしょう。 既にPrometheusを利用してる企業も多くあるかと思いますが、今後ますます案件が増えそうです。

記事では、incubatingからgraduatedとなるまでに、Prometheusコミュニティであったさまざまな出来事について述べています。

・We completely rewrote our storage back-end to support high churn in services

・We had a large push towards stability, especially with 2.3.2

・We started a documentation push with a special focus on making Prometheus adoption and joining the community easier

筆者も、Prometheus2.0でPrometheusのTSDBがスクラッチで書き換えられた話は、当時驚いた記憶があります。

OpenMetricsがCNCFのSandboxプロジェクトとなるなど、モニタリングの重要度は今後も高いと思いますので、Prometheusコミュニティが、Graduatedとなったことでどのようになっていくのか楽しみです。

Kubernetesのパッケージマネージャ: Helmを試してみよう

数ヶ月前にCNCFのIncubation-leveのプロジェクトとなったKubernetesのパッケージマネージャHelmに関する記事が、CNCFブログにポストされましたので、これを参考にしつつ試してみました。

Helmとは

HelmはKubernets上にアプリケーションコンテナをPodとしてデプロイすることを容易にすることを目的としています。KubernetesLinuxなどのオペレーティングシステムと位置付けた時に、Helmはyumやaptといったパッケージ管理システムの役割を果たします。

KubernetesではPodをデプロイする際にManifestを定義しますが、HelmではChartsと呼ばれるアプリケーション定義を記述するそうです。物は試しということでHelmを利用してPodをデプロイしてみようと思います。

前提

Helmを試すには、自由に利用可能なKubernetesクラスタが必要です。minikubeを利用するのがもっとも簡単ですので、環境がない方はインストールしてみてください。 techlunch.hatenablog.com

インストール

インストールはとても簡単で以下のコマンドを実行するだけです。

$ curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
$ helm init

WordPressを動かしてみる

Chartsとして提供されてるアプリケーションを探すには次のコマンドを打ちます。

$ helm search
NAME                                    CHART VERSION   APP VERSION                     DESCRIPTION                                       
stable/acs-engine-autoscaler            2.2.0           2.1.1                           Scales worker nodes within agent pools
...
stable/wordpress                        2.1.8           4.9.8                           Web publishing platform for building blogs and ...

今回は、WordPressをサンプルとしてインストールします。

$ helm repo update

これで完了です。WordPressとバックエンドのMariaDBの2つのPodが動作してることが確認できます。

$ kubectl get pods
NAME                                           READY     STATUS    RESTARTS   AGE
intended-aardwolf-mariadb-0                    1/1       Running   0          1m
intended-aardwolf-wordpress-646bd6955b-vj4px   1/1       Running     1          1m

HelmコマンドでもChartがインストールされていることを確認できます。

$ helm list
NAME                REVISION    UPDATED                     STATUS      CHART           NAMESPACE
intended-aardwolf   1           Sun Aug 12 15:08:58 2018    DEPLOYED    wordpress-2.1.8 default  

Kubernetesの導入の敷居の高さにはさまざまな理由があるのですが、一つはKubernetesマニフェストを書くことだと思っています。 Helmを利用することで、よく利用するアプリケーションが簡単にKubernetes上にデプロイできるようになるので、ますますKubernetesユーザは増えるかもしれません。

Helmについては、今後もしばらく動向をウォッチしていきたいと思います。

OpenMetricsがCNCFのSandboxプロジェクトになることが発表

OpenMetricsが、CNCFのSandboxプロジェクトになりました。CNCFによってホストされているプロジェクトは、数多くありますが、プロジェクトの成熟度でいうとSandboxは一番下に位置付けられています。「卒業」を示すGraduated projectは、現在のところKubernetesPromehteus*1のみとなります。

VMwareが開発したHarborも最近Sandbox入りすることが発表されており、クラウドネイティブ界隈でのCNCFの存在感はますます大きくなってきていると言えるでしょう。

OpenMetricsは具体的にどのようなものなのか気になるところですが、記事には、

The open source initiative, focused on creating a neutral metrics exposition format, provides a sound data model for current and future needs of users, and embeds this into a standard that is an evolution of the widely-adopted Prometheus exposition format. While there are numerous monitoring solutions available today, many do not focus on metrics and are based on old technologies with proprietary, hard-to-implement and hierarchical data models.

という記述がありますので、OpenMetricsはソフトウェアというよりは、監視サーバに送るメトリクスの標準的なメッセージフォーマットやデータモデルを定義することを目的にしているように見えます。

コンテナの監視はPrometheusが使われることが多く、アプリケーション自身の監視もPrometheusでモニタリングできるように、独自Exporterを作成して監視していますが、事実上のデファクトであるPrometheusを参考にしつつ、その他の監視ツールも含めて、標準的な仕様を定義することを目的としているのかもしれません。

*1:Prometheusもここ数日の間にGraudatedになったばかりです。

CNCFブログにKubernetesのRBACに関する記事がポストされました。

少し前の話になりますが、CNCFブログにKubernetesのRBACに関する解説記事がPOSTされました

記事によると、RBACはKubernetes1.6でベータ版となりましたが、当初は不満を抱えるユーザも少なくなく、StackOverflowやGithubでさまざまなissueがあげられていたそうです。なぜなら、ほとんどのドキュメントやサンプルがRBACを考慮したものではなかったからです。*1

ただ、RBACが重要であるということは、当然全員認識してしていたようです。全てのリソースを管理者権限で操作するなど、商用環境ではできないので。記事では以下のような機能が必要であると述べられています。

  • さまざまなプロパティをもつ複数のユーザを用意し、適切に認証
  • ユーザやユーザグループが実行できる操作の制御
  • Pod内プロセスが実行できる操作の制御
  • Namespaceの特定リソースのvisibilityの制御

英語が得意な方は、次のプレゼンも、是非ご参照ください。 youtu.be

また、KubernetesのRBACについて学ぶ前に、ロールベースアクセス制御(Role-based access control: RBAC)について勉強しておくと、より理解が進むと思います。RBACは一般的な技術ですので、日本語でもさまざまな解説記事がでていますが、概要を理解するには、Wikipediaの記事が良いでしょう。

商用環境でKubernetesを利用する場合は、RBACの利用は避けて通れませんので、商用導入を検討してる方は、是非勉強して見てください。また、RBACを使いこなすにはKubernetesで管理できるリソースやAPIについても勉強していく必要があります。APIドキュメントを参考に、さまざまなAPIを実際に打ち込んで学んでいくのが良いでしょう。

*1:現在は修正されているようです。

Kubernetesチュートリアルその3: Podに割り当てるCPU時間を制限する

Kubernetesでは、VMを管理するとき同様に、Podに割り当てるリソースを制限することができます。

前回の記事のメモリの時と同様に、公式ドキュメントを参照しながら、Podに割り当てるCPU時間を制限する方法と挙動について試してみました。

  • Podが制限以上のCPU時間を消費
  • Podがノードに搭載されているCPU時間を要求する

の2パターンを試して、実際にどのような挙動となるか見ていきます。

準備

メモリの時と同じように、metrics-serverというadd-onsを有効にします。

$ minikube addons enable metrics-server

metrics-serverが実行されているかどうかは次のコマンドで確認できます。

$ kubectl get apiservices
NAME
v1beta1.metrics.k8s.io

今回のチュートリアル用にnamespaceを作成します。

$ kubectl create namespace cpu-example
namespace/cpu-example created

$ kubectl get namespaces
NAME          STATUS    AGE
cpu-example   Active    18s

Podが要求通りのCPU時間を消費

Podを構成するコンテナのCPU要求を0.5cpu、CPU制限を1cpuとして設定します。また、2cpuを消費するコンテナを実行しています。

# https://k8s.io/examples/pods/resource/cpu-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr
    image: vish/stress
    resources:
      limits:
        cpu: "1"
      requests:
        cpu: "0.5"
    args:
    - -cpus
    - "2"

Podを作成。

$ kubectl create -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example

作成したPodが使用中のCPU時間を表示。

$ kubectl top pods cpu-demo  --namespace=cpu-example
NAME       CPU(cores)   MEMORY(bytes)   
cpu-demo   998m         1Mi 

Podはstressコマンドによって、2CPUを消費しようとしていますが、制限値を超えて利用することはできないことがわかります。

Podを削除。

$ kubectl delete pods cpu-demo --namespace=cpu-example

Podがノードに搭載されているCPU時間を要求する

最後に膨大なCPU(設定では100cpu)を要求した時の挙動を見ていきます。

# https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo-2
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr-2
    image: vish/stress
    resources:
      limits:
        cpu: "100"
      requests:
        cpu: "100"
    args:
    - -cpus
    - "2"

Podの作成

$ kubectl create -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example

Podの情報を取得すると、STATUSが、 Pending となっています。つまり、Podはスケジューリングされておらず、どのノードでも動作していない状態となります。

$ kubectl get pod cpu-demo-2 --namespace=cpu-example

Podの詳細情報を表示すると、

$ kubectl describe pod cpu-demo-2 --namespace=cpu-example

次のように、ノード上のCPU不足により、スケジューリングができないことがわかります。

Events:
  Type     Reason            Age               From               Message
  ----     ------            ----              ----               -------
  Warning  FailedScheduling  32s (x7 over 1m)  default-scheduler  0/1 nodes are available: 1 Insufficient cpu.

PodとNamespaceを削除して終了。

$ kubectl delete pod cpu-demo-2 --namespace=cpu-example
$ kubectl delete namespaces cpu-example

以上で、CPU時間割り当てに関するチュートリアルは終了となります。Kubernetesで管理できるリソースはCPUやメモリ以外にもボリュームなどさまざまなものがあり、VMと同じようにリソース管理するための機能が備わっています。次は、拡張リソースやボリュームなど、管理するには難易度が少し高いリソースについてまとめていきたいと思います。

Kubernetesチュートリアルその2: Podに割り当てるメモリを制限する

Kubernetesでは、VMを管理するとき同様に、Podに割り当てるリソースを制限することができます。公式ドキュメントを参照しながら、Podに割り当てるメモリを制限する方法と挙動について試してみました。英語が得意な方は元記事をご参照ください。

  • Podが制限以下のメモリを消費
  • Podが制限以上のメモリを消費
  • Podがノードに搭載されているリソース以上のメモリを要求する

の3パターンを試して、実際にどのような挙動となるか見ていきます。

準備

metrics-serverというadd-onsを有効にします。

$ minikube addons enable metrics-server

metrics-serverが実行されているかどうかは次のコマンドで確認できます。

$ kubectl get apiservices
NAME
v1beta1.metrics.k8s.io

今回のチュートリアル用にnamespaceを作成します。

$ kubectl create namespace mem-example
namespace/mem-example created

$ kubectl get namespaces
NAME          STATUS    AGE
mem-example   Active    18s

Podが制限以下のメモリを消費

まず、Podが要求するメモリ量Kubernetesによって制限されるメモリ量を設定ファイルに定義します。 Podが要求するメモリを100MiB、制限を200MiBとし、150MiB程度のメモリを消費するコンテナを定義しています。

# https://k8s.io/examples/pods/resource/memory-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-ctr
    image: polinux/stress
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

Podを作成。

$ kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example

作成したPodが利用中のメモリ量を出力。

$ kubectl top pod --namespace=mem-example
NAME          CPU(cores)   MEMORY(bytes)
memory-demo   61m          150Mi

Podが実際に利用してるメモリ(150MiB)が、要求したメモリ(100MiB)よりも大きな値となっていますが、制限値である200MiBよりも小さな値ですので、Podは問題なく動作しています。

Podを削除。

$ kubectl delete pods memory-demo --namespace=mem-example

Podが制限以上のメモリを消費

次に制限値以上のメモリを消費した場合の挙動を見ていきます。設定ファイルは以下の通りです。制限値100MiBに対し、250MiBのメモリを消費するコンテナを起動するように定義しています。

# https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-2
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-2-ctr
    image: polinux/stress
    resources:
      requests:
        memory: "50Mi"
      limits:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]

Podを作成。

$ kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example

Pod状態を取得すると、STATUSが OOMKilled となっており、メモリ不足により、プロセスがkillされたことがわかります。

$ kubectl get pods --namespace=mem-example
NAME            READY     STATUS      RESTARTS   AGE
memory-demo-2   0/1       OOMKilled   1          10s

このPodは、強制終了されても、再起動を試みていますので、再度情報を取得してみると、STATUSが CrashLoopBackOff となっていることがわかります。

$ kubectl get pods --namespace=mem-example
NAME            READY     STATUS             RESTARTS   AGE
memory-demo-2   0/1       CrashLoopBackOff   3          1m

Podを削除。

$ kubectl delete pods memory-demo-2 --namespace=mem-example

Podがノードに搭載されているリソース以上のメモリを要求する

最後に、膨大なメモリ(設定では1000GiB)を要求するPodを作成した場合にどのような挙動を示すのか見てみます。

# https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-3
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-3-ctr
    image: polinux/stress
    resources:
      limits:
        memory: "1000Gi"
      requests:
        memory: "1000Gi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

Podの作成

$ kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example

Podの情報を取得すると、STATUSが、 Pending となっています。つまり、Podはスケジューリングされておらず、どのノードでも動作していない状態となります。

$ kubectl get pod memory-demo-3 --namespace=mem-example
NAME            READY     STATUS    RESTARTS   AGE
memory-demo-3   0/1       Pending   0          2m

Podの詳細情報を表示すると、

$ kubectl describe pod memory-demo-3 --namespace=mem-example

次のように、ノード上のメモリ不足により、スケジューリングができないことがわかります。

Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  40s (x22 over 5m)  default-scheduler  0/1 nodes are available: 1 Insufficient memory.

PodとNamespaceを削除して終了。

$ kubectl delete pod memory-demo-3 --namespace=mem-example
$ kubectl delete namespaces mem-example

以上で、メモリ割り当てに関するチュートリアルは終了となります。次は、CPU割り当てについて試して見たいと思います。