落とし穴に立て札を立てるが如く

ハマりどころの解決が少しでも早くなることを願って書いていきます

今更ながら学ぼう kubernetes での Pod の立て方

この記事はfixer tech blogにもマルチポストしています。

tech-blog.cloud-config.jp

f:id:nam_yu_sql:20211201150118j:plain

はじめに

これを読んでいる方は普段 kubernetes で Pod 立てるときどんなふうに立てているでしょうか?
多くの場合、既に作成されているマニフェストファイルを共有されて、それを一部書き換えて apply するやり方をしているのではないかと思います。
それはそうすることで作成する kubernetes リソースをスクリプトとして管理できるという便利な側面があるからなのですが、一方でその後ろで行っていることの理解はしづらくなることもあるかと思います。
普通にアプリケーションを kubernetes 環境にデプロイする業務をするにはそこまで深く理解しなくても問題ないのですが、その後ろでどのようにして Pod が立っているか理解したくなっている気分の方はこの記事を読んでみてください。

そもそも Pod ってなんだ

Pod の概観
kubernetes での Pod というのは、アプリケーションのデプロイができる最小単位のリソースです。
この中には、一つまたは複数のコンテナが動いています。
コンテナというのは・・・・・
それぞれの中でアプリケーションなどが動いている環境です。
今回はコンテナについてはこれ以上掘り下げません。
kubernetes ではアプリケーションをコンテナ単位で動かすことはできず、アプリケーションをデプロイするということはほぼイコール Pod をデプロイするということになります。
ただ、Pod をデプロイする方法が kubernetes にはいくつか用意されており、それによって同時にデプロイされるリソースや機能が変わってきます。
以下ではその種類について解説します。

Pod の立て方その 1、Pod をそのまま立てる

Pod をそのまま立てる方法です。
Pod を立てるにはマニフェストファイルを作成してそれを apply する方法もあるのですが、Pod を立てることそれ自体はコマンド一つで実行できます。
今回は nginx のコンテナが一つ動く Pod を作成します。

kubectl run nginx --image=nginx  

実行が成功したら、以下のコマンドで作成されたリソースを確認してみましょう。

kubectl get all  

コマンドの出力としては、以下のようなものになるはずです。
Pod のリソースができました。
これが、Pod をそのまま立てる方法になります。

NAME        READY   STATUS    RESTARTS   AGE  
pod/nginx   1/1     Running   0          67s  

確認出来たら、今回作成した Pod は以下のコマンドで削除できます。

kubectl delete pod nginx  

Pod の立て方その 2、ReplicaSet を立てる

ReplicaSet
次は、ReplicaSet と呼ばれるリソースを作成する方法です。
この方法はコマンドだけで実行することはできず、マニフェストファイルの作成が必要になります。
新しい yaml ファイルを作成し、以下のコードを書き写して保存します。

apiVersion: apps/v1  
kind: ReplicaSet  
metadata:  
  name: nginx-replica-set  
  labels:  
    app: nginxReplicaSet  
spec:  
  replicas: 3  
  selector:  
    matchLabels:  
      app: nginxPod  
  template:  
    metadata:  
      labels:  
        app: nginxPod  
    spec:  
      containers:  
        - name: nginx  
          image: nginx  

保存出来たら、以下のコマンドで作成したマニフェストを apply し、kubernetes 上にリソース作成を指示します。

kubectl apply -f <作成したマニフェストファイルのパス>  

コマンドの実行が成功したら、以下のコマンドを実行してどのようなリソースが作成されたか確認してみましょう。

kubectl get all  

結果としては以下のようなものになるはずです。(STATUS 等は状態によって変わるかと思います。)
マニフェストファイルで定義したのは ReplicaSet のみですが、その定義の中にある template の内容に従って、Pod のリソースも同時に作成されています。
ReplicaSet は同じ Pod が常に複数立っている状態を維持してくれるリソースで、これが生きている限り template で指定した設定の Pod の個数をreplicas:のパラメータで指定した個数に保とうとしてくれます。
この働きによって、ReplicaSet のリソースを作成するとその ReplicaSet によってコントロールされている Pod が個別にコマンド実行することなく自動生成されます。
なので、ここで例えば作成されている Pod を一つ削除したりすると、すぐに新しい Pod が立ち上がってきて頭数を合わせてくれます。

NAME                          READY   STATUS              RESTARTS   AGE  
pod/nginx-replica-set-fb9vq   0/1     ContainerCreating   0          9s  
pod/nginx-replica-set-hz2cb   1/1     Running             0          9s  
pod/nginx-replica-set-zxxfp   1/1     Running             0          9s  
  
NAME                                DESIRED   CURRENT   READY   AGE  
replicaset.apps/nginx-replica-set   3         3         2       9s  

今回作成した ReplicaSet は以下のコマンドで削除できます。
ReplicaSet を削除すると、コントロールされていた Pod も同時に削除されます。

kubectl delete replicaset nginx-replica-set  

Pod の立て方その 3、Deployment を立てる

Deployment
3 つ目の方法は、Deployment を立てる方法です。
Deployment を立てることによっても Pod が立ちます。
Deployment についてはマニフェストを実行する以外にもコマンド一つで立ち上げる方法があります。

kubectl create deployment nginx-deployment --image=nginx --replicas=3  

コマンドが成功したら、どのようなリソースが作成されたか見てみましょう。

kubectl get all  

コマンドの事項結果は以下のようなものになるはずです。
今回立てた Deployment のほかに、Pod、さらに先程は手動で作成していた ReplicaSet も自動生成されています。
この Deployment というリソースは、Pod のデプロイ周りをコントロールしてくれるリソースで、デプロイされている Pod の個数を維持するために、Pod だけでなく ReplicaSet もコントロールします。
Pod の個数を維持するだけであれば ReplicaSet で十分な気もしますが、Deployment にはもう一つ別の機能があります。
それは、アプリケーションの更新時に Pod を止めずに更新することです。
例えば、Deployment 作成のコマンドの image を nginx から redis に更新して実行すると、Pod を全部削除せず、新しい Pod を作成しながら一部分だけ削除して全体を置き換えていくような動きをします。
これによって、例えば Pod で動かすコンテナのバージョンを上げた際にアプリケーション全体を止めることなく、更新をかけることができます。
ReplicaSet だと、例えばマニフェストファイルの中の image を redis に変えて実行するとそれだけだと Pod の更新が行われません。
更新するには、Pod を手動で削除して置き換えていく必要があります。
Deployment だとそのあたりもコントロールしてくれます。

NAME                                    READY   STATUS              RESTARTS   AGE  
pod/nginx-deployment-84cd76b964-578g2   1/1     Running             0          8s  
pod/nginx-deployment-84cd76b964-bf67f   0/1     ContainerCreating   0          8s  
pod/nginx-deployment-84cd76b964-j2ltp   1/1     Running             0          8s  
  
NAME                               READY   UP-TO-DATE   AVAILABLE   AGE  
deployment.apps/nginx-deployment   2/3     3            2           8s  
  
NAME                                          DESIRED   CURRENT   READY   AGE  
replicaset.apps/nginx-deployment-84cd76b964   3         3         2       8s  

この辺りのことを弄り終わったら、以下のコマンドで deployment を削除できます。
deployment を削除すると、自動的に ReplicaSet も Pod も削除されます。

kubectl delete deployment nginx-deployment  

おわりに

今回は、Pod をデプロイするということについて、kubernetes の機能を段階的に紹介しました。
一般的には Pod をデプロイする際には Deployment リソースをデプロイしていると思います。
なぜなら、レプリカ数の設定による可用性の維持や、更新時にもアプリケーションの動作を止めないようにすることなどは Web アプリとしては目指すべきところである上にコストもほとんどかからないためです。
ただ、その後ろでは ReplicaSet が立って、さらにそれが Pod を立てて・・・みたいなことをやっていることを知ることで、kubernetes についてもう一段深く知ることができるのではないかと思います。

参考