TechLunch

The free lunch is over.

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割り当てについて試して見たいと思います。

Kubernetes入門1: Hello Minikube

Kubernetesは公式ドキュメントが充実しており、さまざまなチュートリアルも用意されています。今回はその中の一つである、Hello Minikubeを参考にチュートリアル記事を書いてみました。*1

Minikubeとは

いざKubernetesを試してみようと思った時に、たくさんサーバを用意することは出来ない、インストールが難しい、といった理由で断念してしまう人もいるかもしれません。*2

Minikubeは、MacLinuxなど手元のマシンで簡単にKubernetesを試すことができるツールです。 例えば、Macでminikubeを試すと、Mac上に一台VMを立ち上げて、その中に自動的にKubernetesをインストールして、一台構成のKubernetesお試し環境が出来上がります。 ちょっとKubernetesを試して見たい人にはおすすめの環境ですのでぜひ利用してみてください。

インストール

ここでは、Macでのインストール方法を載せておきます。LinuxWindowsでもワンライナーでインストール可能のようですので、ご自身の環境に合わせてインストールしてください。

$ brew cask install minikube

これで、インストール終了です。 他にも、Macで利用するためのkubectlなどのインストールが必要なのですが、詳細は Install Minikube - Kubernetes をご参照ください。

All-in-one VMの起動

起動も簡単で、virtualboxをインストールしてあるときは、以下のコマンドを実行します。

$ minikube --vm-driver=virtualbox start

// Virtualboxのコンソールや以下のコマンドでVMが出来てることを確認
$ VBoxManage list vms
"minikube" {xxx}

これでKurbernetesがインストール済のVMが作成され、起動しました。

Podを作成してから削除するまでの一連のコマンドを試す

Pod起動

Dockerチュートリアルでもよくみるnginxが含まれたPodを起動します。

$ kubectl run hello-node --image=nginx --port=80

Pod取得

$ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
hello-node-79c9b49558-dtq8d   1/1       Running   0          54s

Service作成

KubernetesはPodを作成しただけでは、外部からそのPodにアクセスできませんので、Serviceを作成して外部からアクセス可能とします。

$ kubectl expose deployment hello-node --type=NodePort
service/hello-node exposed

Serviceにアクセス

起動したコンテナには、minikube VMのIP:portでアクセスすることができます。

$ curl  $(minikube service hello-node --url)
...
// nginxのhtmlが返ってきます

ブラウザでアクセスするには、

$ minikube service hello-node --url

のコマンドでIPとPortを取得して、それをブラウザで開けばアクセスすることが可能です。

ServiceとPodの削除

$ kubectl delete services hello-node
$ kubectl delete deployments hello-node

ダッシュボードの利用

$ minikube dashboard

ブラウザ経由でKubernetesクラスタの管理をすることができます。kubectlを利用して作成したPod情報なども見ることができ、直感的な理解の助けになるので、ぜひ試してみてください。

これで、チュートリアルその1は終了です。次回はこの環境を活用して、Kubernetesの他のチュートリアルなども試してみたいと思います。

*1:公式チュートリアルでは自分でDockerイメージを作成しており敷居が高ので、より簡略化しています。

*2:今はkubeadmなどで比較的容易にインストール可能ですが、初期のKubernetesは少し難しかったのです

Googleの新サービスCloud Service Platform。Istioなどを利用。

Googleの新サービス基盤 Cloud Service Platform について、Googleの公式ブログで発表されています。 Cloud Services Platformについては、Google Cloud Next '18でも発表されており、日本語の記事もいくつか出ています。 本サービスは、オンプレとクラウド上で動く全てのITシステムに対して、一貫性のあるフレームワークを提供することを目的としている。おそらく、オンプレにシステムを抱えているユーザに対し、クラウドへの緩やかな移行を促すことを目的としているのではないかと思われる。

https://3.bp.blogspot.com/-0PF8lTgs2mc/W1ZeqBT0wAI/AAAAAAAAGHo/SirNgEV8SAQuepeZjrhRtdqi3t7abzyxgCLcBGAs/s1600/The%2BCloud%2BServices%2BPlatform%2Bfamily.png

本サービスの特徴として、

  • Service mesh: マネージドなIstioの提供
  • Hybrid Computing: GKE On-premによるオンプレとクラウドのマルチクラスタ管理
  • Policy enforcement: Kubernetes workloadの制御を可能とするGKEポリシー管理
  • Ops tooling: 監視を一元的に可能なStackdriver Service Monitoring
  • Serverless computing: GKE Serverless add-onとKnative
  • Developer tools: マネージドなCI/CD環境

などが挙げられます。本サービスを活用し、オンプレで稼働しているレガシーなアプリケーションのコンテナ化をすることで、即座にクラウドレディなマイクロサービスを開発することができると思われます。*1

ここ数日、Googleクラウド関連のサービスについて注目し記事にしていっている通り、Googleはオンプレに閉じているレガシーな顧客に対し、アプリケーションのコンテナ化とKubernetesの導入の敷居を下げるようなサービスを発表していっています。

今後、比較的レガシーな開発を実施することが多いSIerに対してもますますKubernetesなどの導入要望は強まっていくと思われますので、今後の業界動向について目を離すことはできない状況となっています。

*1:もちろんレガシーなアプリケーションをコンテナ化するという部分が即座にできるとは思えません。

KubernetesやIstio、Knativeに関するPodcastが公開されました

RedHatにより提供されているPodcastにて、v1.0の公開から3周年を迎えたKubernetes、Istio、Knative、およびGoogle Next '18Kubernetes関連の発表について議論されています。

GKE On-Premは、本ブログでも何度か記事にしましたが、Kubernetesをユーザのデータセンターなどのオンプレ環境で利用するためのサービスです。まずはアルファ版の提供からとなりますので、早く試してみたい方は早期利用リクエストを投げることをお薦めします。

Knativeは、Kubernetes上でサーバレスなワークロードを動かすための基本的なビルディングブロックを提供します。AWS Lambdaによりサーバレス自体は前々から注目されてきていますが、今後より一般的な概念になり利用ユーザも増えていくことが見込まれます。

Istioは、マイクロサービスにより構成されるサービスメッシュを管理するためのソフトウェアで、CNCFの一員として開発されているOSSです。GKEとも連携して使うことができるようになりました。

今後もしばらくはGoogle Cloud Next '18の発表内容を踏まえた議論が多くされていきそうで、ますますクラウドKubernetes、コンテナ界隈から目を離すことができません。 ITエンジニアとしては、動向をウォッチするだけでなく、自らOSSやサービスを利用して知見をためていく必要がありそうです。 本ブログは、動向をウォッチするためのポインタとなることを目指しつつ、月数回の頻度で詳細な解説記事を載せていく予定です。

GoogleによるクラウドイベントGoogle Cloud Next ‘18が盛況のうちに終了

GKE On-PremKnativeなど、日本でもバズるような興味深い発表が多くあったGoogle Cloud Next ‘18が終了しました。 Keynoteによると、Google過去最大規模のイベントとなったそうで、25,000以上の参加登録があったようです。 日本語でもさまざまな記事が出ていますが、どんな発表があったのか、気になる方はrecap記事を是非参照してみてください。 www.blog.google

イベントの名前にもあるCloud関連については新サービス含め、機能強化などさまざまな発表がありました。

GKE On-Prem

techlunch.hatenablog.com 本イベントの目玉の一つですね。詳細は過去記事やその先のリンクをご参照ください。

Serverless containers, Knative

cloudplatform.googleblog.com こちらも目玉の一つで、日本語記事もたくさん書かれています。筆者は実はserverlessの使いどころが明確に見えておらず、現時点で利用したことがありませんし、引き合いもそこまで多くありませんでした。 しかし、今後話を聞かれることはますます多くなると思いますので、勉強して詳細な記事を書きたいと思っています。

Stackdriver Service Monitoring

GCPAWSなどのクラウドで実行されるアプリケーションのパフォーマンスやアップタイムなどをグラフィカルに確認することができます。NginxやApacheなどよく利用されるアプリケーションに対応しており、さまざまな情報が取得することができます。 もちろんアラート機能も具備していますので、slackやメール通知など運用に役立てることが可能です。 独自のビジネスアプリケーションを監視するための設定も可能なようなので、幅広く利用ができそうです。

Cloud Functions

サーバレスプラットフォームであるCloud Functionの一般供用が開始されました。100ms単位に丸められて課金されるようですので、バッチ処理など常駐しないアプリケーションが多いユーザはコスト削減につながるかもしれません。

マネージドサービスの拡充

フルマネージドなサービスのラインナップが拡充されました。今まで、特定の製品に縛られて自分たちで運用せざるを得なかったユーザもどんどんとクラウドに移行していくことになるだろうと思われます。

その他にも、今流行りのAI関連やIoT、エッジ向けの話など幅広い話がありました。9月には東京でGoogle Cloud Next ’18 in Tokyo | 9 月 19 ~ 20 日、東京が開催される予定ですので、時間があるかたは是非参加して見てはいかがでしょうか。

KubernetesのCPU Managerの解説記事を見て勉強しよう

Kubernetesの公式ブログで、Feature Highlight: CPU Manager - Kubernetes という記事が上がっていました。デファクトのコンテナオーケストレーターであるKubernetesの概要を掴むチャンスですので、概説します。

Kubernetesアーキテクチャ

https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.1/docs/design/architecture.png

そもそもKubernetesはどのようなシステムで構成されているのか疑問に思っている方も多いかと思いますので、Githubに上がっていた図を貼り付けておきます。

CPU Managerは名前から類推されるとおり、controller managerと呼ばれるシステムコンポーネントの一機能となります。

controller managerは、Podのレプリカ数の管理など、コンテナ化されたアプリケーションが正常に動作するためのさまざまな制御機能を有しています。

CPU Manager

When CPU manager is enabled with the “static” policy, it manages a shared pool of CPUs. Initially this shared pool contains all the CPUs in the compute node. When a container with integer CPU request in a Guaranteed pod is created by the Kubelet, CPUs for that container are removed from the shared pool and assigned exclusively for the lifetime of the container. Other containers are migrated off these exclusively allocated CPUs.

簡単に言うと、特定のPodのみがCPUを排他的に利用すること可能となるようです。引用文を読む限り、排他的に割り当てられたCPUを他のPod(コンテナ)は利用することはできなくなるように見えます。

これにより、CPU-intensiveなワークロードは、CPU時間を有効活用することができるため、純粋な処理時間が増えるだけでなく、context switchやcache missによるオーバヘッドも削減することが可能となります。

CPU-intensiveなワークロードって何?と感じるかたもいるかもしれませんが、I/Oが少なく、計算が多く走るような処理のことです。

CPUの配分方法としては、CPU配分をワークロードごとに重み付けをする方法や、スケジューリング期間中にPodに割り当てる実時間を指定する方法などもありますが、CPUを排他的に利用することが可能になれば、複雑なスケジューリングも考える必要がなくなるため、有用な手段と言えるかと思います。

 元記事には性能評価結果も載っているので興味ある方は参照ください。

 

まだbeta featuresのようですが、ワークロードの特性によっては一度試してみたい機能となります。