【入門】Kubernetes で nginx をたててデフォルトページを表示させる
目次
こんにちは。
【入門】記事ばっかり書いてるシステムソリューション部のインフラわっしょいマンです。
そんな生粋のゲートガーディアンである私ですが、今回は Kubernetes について書いていきます。
入門記事は丁寧なものが世の中にたくさんあって記事を書く前から心折れそうになりますが、自分なりに嚙み砕いたことをわかりやすいようにまとめてみます。
ぬるりと。
今回は実際に nginx を Kubernetes で用意して、ウェルカムページを表示させてみます。
開発者の方で、がっつり触ることは珍しいかもしれませんが、 Kubernetes で作成された環境で、アプリケーションのパフォーマンスを最大化させるには、ある程度 Kubernetes に合わせたアプリ設計を行わないといけないので、こちらの記事を踏み台にして、ぜひ入門してみてください!
Kubernetes とは
ドキュメントの説明はこうです。
Kubernetesは、宣言的な構成管理と自動化を促進し、コンテナ化されたワークロードやサービスを管理するための、ポータブルで拡張性のあるオープンソースのプラットフォームです。Kubernetesは巨大で急速に成長しているエコシステムを備えており、それらのサービス、サポート、ツールは幅広い形で利用可能です。
公式ドキュメント:https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/
よくわからないので順に説明していきますが、まず前提として Kubernetes はコンテナオーケストレーションツール(たくさんのコンテナを指揮者みたいに管理するイメージ)ですので、コンテナの知識が前提として必要になります。
宣言的な構成管理と自動化
Kubernetes ではマニフェストファイルと呼ばれるファイル内に「こうあってほしい状態」を記載しておく(宣言する)と、その内容に沿って Pod(コンテナとボリュームをまとめたもの)を作成してくれます。
例えば、「コンテナ4つください」と注文しておいた後に、ミスって1つコンテナ消しちゃったとしても、Kubernetes 側が「1個足りねーじゃん」と自動的に作って足しておいてくれます。
Docker Compose 等ではコンテナを作ったら作りっぱなしでしたが、 Kubernetes はそれに上記のような管理機能が加わったものという違いがあります。
コンテナ化されたワークロードやサービスを管理
Docker を学習済みの方はご存じかもしれませんが、 Docker では1つのマシン上でコンテナを実行していました。
それに対して、Kubernetes では複数のマシン上にあるコンテナを管理してくれます。
大規模なアプリケーションですと、複数のマシンを連携させて負荷や機能を分散させたりしますが、このときに1台1台 マシン上で docker run を実行していかなくても先述のマニフェストファイルを用意すれば、各マシンに良い感じに展開してくれるので、大規模サービスを展開する際には、ありがたい存在です。
メリット
このように大規模サービスをコンテナで展開する場合のデファクトスタンダードとなっている点に加えて、
Docker と同様に設定ファイル含め納品可能な点やレプリカセットというものを使ってバージョン管理し、コンテナを停止させることなく更新できたりとメリットは複数あります。
オープンソースコミュニティが世界的な規模で活発に動いていることも大きな利点です。
Kubernetes の用語解説
Kubernetes ではいろいろと独自の概念や言葉が出てきます。
この辺りは覚えるしかないので、ざっくり解説していきます。
現段階ではなんとなくそんな奴いるんだなーくらいで読んでいただければと思います。使っていれば嫌でも覚えます。
マスターノード
我々が命令する部分です。この後出てきますがワーカーノードというのもいて、そのワーカーノードへ指示するのがマスターノードの役割です。
「kube-apierver(我々からのコマンドを受け取って処理する)」
「etcd(受け取った「望ましい状態」を保持するデータベース)」
「kube-scheduler(ワーカーノードに Pod を割り当てしてくれる)」
など、管理機能を実現してくれる集まりです。
ワーカーノード
マスターノードと連携して動き、実際に Pod が配置される領域。
「kube-let(kube-schedule とやり取りしてくれる)」
「kube-proxy(ネットワークをうまいことやってくれる)」
などが存在します。
Pod
コンテナとボリューム(保存領域)を取りまとめたものの事です。
もし、ボリュームを使わないとしても Kubernetes では Pod を1つのまとまりとして管理します。
service
Pod をまとめる役割を持っています。
service ごとに1つの IP が割り振られ、その IP にアクセスすると service が配下の Pod にロードバランシングしてくれます。
このロードバランシングはワーカーノード単位の話なので複数のワーカーノード間の負荷分散は Service の範疇外となります。
レプリカセット
Pod が止まった時や削除されたとき、Kubernetes が自動で望ましい数に戻すと説明しましたが、そのために Pod 数を管理する必要があります。
その管理を担当してくれるのがレプリカセットです。
デプロイメント
Pod のデプロイを管理するものです。
上述の「Pod」「service」「レプリカセット」はマニフェストファイル(yaml 形式)に記載できますが、そのうち「Pod」と「レプリカセット」についてはこの「デプロイメント」に包括する形で記載することが多いです。
つまり Pod を作る際は「デプロイメント」用のマニフェストと「service」用のマニフェストがあればとりあえず動きます。
環境について
百聞は一見に如かず、ということで前項目で説明した用語の入り混じったマニフェストファイルを見ていただこうと思います。
が、その前に、マニフェストファイルを適用させる Kubernetes の実行環境が必要です。
各クラウドで提供されている Kubernetes 用のサービス(AWS なら EKS、GCP なら GKE、Azure なら AKS、OCI なら OKE、Alibaba Cloud なら ACK など...... )を使ってもよいのですが、初学者の学習用としてはお値段が高めなので「Docker Desktop」に付属している拡張機能を利用するのがおススメです。
設定方法は簡単です。
Docker Desktop の「setting」⇒「Kubernetes」⇒「Enable Kubernetes」にチェックを入れる。
いろいろインストールされるのを待っていれば OK です。最高ですね。
これだけで、とりあえず Kubernetes の学習を始められます。
例 of マニフェストファイル
では、実際にマニフェストファイルの例をみてみましょう。
例として、 ドキュメントより nginx を作成するデプロイメントを記述した yaml ファイルを拝借してきました。
こんな感じです。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service labels: app: nginx spec: type: NodePort ports: - port: 8080 targetPort: 80 nodePort: 30080 protocol: TCP selector: app: nginx
「---」で区切られた上側がデプロイメント、下側が service の記述です。
別々のマニフェストファイルに分けて記述し、管理を別にすることも可能ですが、同じファイルに記述する場合はこのようにリソースをハイフンで区切って記述します。
各項目について上から説明するとこんな感じです。
■「apiVersion」 ⇒ Kubernetes のリソースは API バージョンを持っていますので、適切なものを記述します。
調べ方はものによっては少し複雑ですが、デプロイメントと service の場合は「kubectl api-resources | grep Deployment」、「kubectl api-resources | grep Services」のコマンドでそれぞれ APIVERSION の欄に「apps/v1」、「v1」と記載されているのを確認できます。
■「kind」 ⇒ リソースの種類を記載します。今回の場合デプロイメントと service を作成するのでそれぞれ「Deployment」、「Service」です。
■「metadata」 ⇒ その名の通りメタデータです。リソースにラベルを付けられます。
とりあえず「name」と「labels」だけ覚えておきましょう。
■「spec」 ⇒ リソースの内容を記述します。リソースによって下位の項目は異なります。
【今回のデプロイメントには下記のものが含まれます。】
selector
デプロイメントが Pod を管理するために使います。 例ではラベルを貼っていますね。後で使います。
replica
レプリカセットの指定をします。上記の例では2つの Pod を要求しています。
spec
Pod のスペックです。コンテナで使うイメージの指定やポートを指定しています。
【今回の service には下記のものが含まれます。】
type
こちらの項目には、サービスと外部との通信をどのように行うか、いくつかある種類から選んで指定します。
具体的には
「ClusterIP(ClusterIP で接続できる。内部でのやり取りに使用し、外部アクセスは不可)」
「NodePort(ワーカーノードの IP で接続できる)」
「LoadBalancer(ロードバランサーの IP で接続できる)」
「ExternalName(Pod から外部へ向けて接続するために使う特殊な設定)」が存在します。
外部からアクセスさせる場合、ここは基本的に「LoadBalancer」を使用しますが、今回は公開無しなので、ワーカーノードへ直接接続する「NodePort」を指定しています。
(外部公開には L7 のロードバランサーとして機能し、SSL終端になれる Ingress というリソースを利用することも多いと思いますが、今回は使わないので一旦横に置いてます。なお 「LoadBalancer」 も SSL化が可能ですが、クラウドで作成する場合、ベンダーによっては仕様上、対応していなかったりします。)
また、「NodePort」 は今回のようなテスト時だけでなく NodePort 単位で何らかの操作をしたい状況にも使用できます。
ports
ここではプロトコルを TCP にしていることに加えて、3つのポートについて定義しています。
「port」は、serviceのポート
「targetPort」はコンテナのポート
「nodePort」はワーカノードのポートです。
今回 type で NodePort を指定しているため、この「nodePort」で nginx へアクセスすることになります。
selector
この項目には Pod で設定したラベルを指定します。
リソースの作成
だいたいの説明が済んだので、実際にマニフェストファイルを作成して実行し、リソースを作成してみましょう。
ちなみに Kubernetes で使うファイルの名前はなんでも OK です。
Dockerfile や docker-compose.yml と違い、特定の名前でなくても問題ないので管理しやすい規則で各々作成してください。
# vi でファイルを開き、例のソースを貼り付けて保存したあと、kubectl コマンドでデプロイメントを作成 vi example.yml kubectl apply -f example.yml
Pod を確認します
$ kubectl get po -l app=nginx NAME READY STATUS RESTARTS AGE nginx-deployment-6595874d85-7mt97 1/1 Running 0 52s nginx-deployment-6595874d85-mds2z 1/1 Running 0 52s
2つの Pod が作成されて「Running」となっていることが確認できます。
例えば、yml ファイル内の「replicas」の数を変えると Pod の数も増減します。
続いて、service は下記コマンドで確認できます
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 26h nginx-service NodePort 10.106.92.238 8080:30080/TCP 21m
上手く nodePort と service のポートがリンクしているようなのでブラウザへ「http://localhost:30080/」と入力して Pod までアクセスしてみましょう。
はい、いつものウェルカムページが出ました!
まとめ
「入門」ということで、さわりだけ解説しました。
実際に外部公開してサービス提供するには、他にも調整が必要な箇所があるのですが、なんとなくわけのわからない存在という意識を払えたらなぁと願ってます。
入門後の記事も書いてみたいので、しばらくお待ちくださいね。
よろしくお願いいたします!