minikubeで始めるk8s入門

はじめに

この記事は、普段Kubenetes(k8s)を触らないエンジニアがMinikubeというツールを用いて雑にk8sの環境を作ってみたという内容になります。なので、概念的な説明はPerplexityくんに任せます。

下記リポジトリで色々試しています。

必要なツール

$ docker --version
$ kubectl version
$ minikube version

Kubenetes(k8s)とは?

以下はPerplexityが要約した内容になります。詳しい内容は、公式ドキュメントを見てください。

Kubernetesは、コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化するオープンソースのコンテナオーケストレーションプラットフォームです123。「クバネティス」「クーべネティス」などと読み、略して「K8s」や「kube」とも呼ばれます12

主な特徴

  • 自動化: 複数のホストにまたがるコンテナの運用管理を自動化し、システム開発・管理の効率を大幅に向上させます3
  • スケーラビリティ: アプリケーションの負荷に応じて自動的にスケーリングを行います35
  • 自己修復: システムの障害を検知し、自動的に修復を試みる機能を持っています3
  • 負荷分散: サービスディスカバリーと負荷分散機能を提供します3

利点

  1. システムダウンタイムの減少
  2. 複雑なタスクの簡素化
  3. クラウドネイティブ開発のサポート
  4. マルチクラウド環境での運用が容易

Kubernetesは、現在コンテナオーケストレーションのデファクトスタンダードとなっており、多くのクラウドプロバイダーやソフトウェアベンダーがKubernetesベースのサービスを提供しています45

Minikubeとは?

Minikubeとは、ローカル環境で小規模なk8s環境を簡単に構築するためのツールです。

MacOSの場合はhomebrewで導入することができます。

$ brew install minikube

そのほかの方は、こちらのドキュメントを参照してください。

Minikubeを起動する

Minikubeを実行するドライバーにはいくつか選択肢があります。(参照:https://minikube.sigs.k8s.io/docs/drivers/

  • Docker
  • KVM2
  • VirtualBox
  • Parallels
  • etc...

おそらくDockerが一番手軽に立てられると思うので、Dockerを先に起動しておきましょう。

Dockerを起動したら、下記コマンドでMinikubeを起動します。Dockerが立ち上がっている場合は、自動でドライバーにDockerが使用されます。

$ minikube start
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

$ kubectl config current-context
minikube

Dockerコンテナを見てみると、Minikubeコンテナが立ち上がっていることを確認できます。

$ docker ps
CONTAINER ID   IMAGE                                 COMMAND                   CREATED         STATUS         PORTS                                                                                                                                  NAMES
e37e0f61bb7f   gcr.io/k8s-minikube/kicbase:v0.0.46   "/usr/local/bin/entr…"   3 minutes ago   Up 3 minutes   127.0.0.1:53174->22/tcp, 127.0.0.1:53175->2376/tcp, 127.0.0.1:53177->5000/tcp, 127.0.0.1:53173->8443/tcp, 127.0.0.1:53176->32443/tcp   minikube

初期状態だと、ClusterIPのみが存在するはずです。

$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8m11s

NginxのWebサーバーをk8sで作ってみる

Nginxを用いた簡単なWebサーバーの例で、k8sを体験してみます。まず最終的な構成図は以下のようになります。

flowchart LR
    User<-->|port forward|NodePort

    subgraph Cluster
    NodePort-->PodA
    NodePort-->PodB
    NodePort-->PodC

    subgraph Node
    NodePort
    subgraph Replicaset
    PodA
    PodB
    PodC
    end
    end

    end

Podを作る

PodについてはPerplexityの回答をご覧ください。

Kubernetes (k8s) のPodは、1つ以上のコンテナをグループ化した、最小のデプロイ可能な単位です123。Podの主な特徴と役割は以下の通りです

  1. リソース共有: Pod内のコンテナは、ネットワークとストレージリソースを共有します1。これにより、コンテナ間のデータや通信の効率が向上します。
  2. ネットワーキング: 各Podには固有のIPアドレスが割り当てられ、Pod内のコンテナはこのIPアドレスとポートスペースを共有します23
  3. スケジューリング: Podは常に同じノード上で実行され、同じスケジュールに従います2
  4. 自己修復機能: 障害が発生した場合、Podは自動的に再起動され、アプリケーションの可用性が維持されます1
  5. スケーラビリティ: Podを基準にアプリケーションの自動スケーリングが実現されます1
  6. 負荷分散とサービスディスカバリ: Podを通じて外部トラフィックの負荷分散と内部サービスディスカバリが容易になります1

Podは、アプリケーション固有の「論理ホスト」をモデル化しており、密接に結合された複数のアプリケーションコンテナを含むことができます2。例えば、Webサーバーとデータベースのコンテナを1つのPodにまとめることができます。Kubernetesでは、通常Podは直接作成されず、Deploymentなどのワークロードリソースを通じて作成・管理されます3。これにより、アプリケーションの管理やスケーリングが容易になります。

Nginxを用いたWebサーバーのPodを立ててみます。まず、nginx-deployment.yamlを作成し、Podの情報を記載します。

$ touch nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

上記の構成ファイルは、nginxのDockerイメージからnginxのWebサーバーをポート番号80で起動するPodを3つ作成します。

では、構成ファイルを適用し、Podを作成してみましょう。

$ kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created

下記コマンドを実行するとPodが作成されていることを確認できます。

$ kubectl get pod
NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-647677fc66-8k4pr   0/1     ContainerCreating   0          6s
nginx-deployment-647677fc66-ljz8c   0/1     ContainerCreating   0          6s
nginx-deployment-647677fc66-tsl9q   0/1     ContainerCreating   0          6s

NodePortを作る

Podだけだとネットワークから参照できないので、NodePortを作成します。NodePortについてはPerplexityの回答をご覧ください。

NodePortは、Kubernetesクラスタ内の特定のServiceとそれに関連するPodに外部からのトラフィックを転送するサービスタイプです14

では、nginx-service.yamlを作成し、NodePortの情報を記載します。

$ touch nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app: nginx

上記の構成ファイルは、先ほど作成したNginxのPodに外部からのトラフィックを転送するNodePortを作成します。

では、構成ファイルを適用し、NodePortを作成してみましょう。

$ kubectl apply -f nginx-service.yaml
service/nginx-service created

下記コマンドを実行するとNodePortが作成されていることを確認できます。

$ kubectl get service
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        27m
nginx-service   NodePort    10.108.205.30   <none>        80:30863/TCP   22s

localhostでアクセスできるようにする

今のままでは外部からアクセスできないので、ポートフォワードする必要があります。

$ kubectl port-forward service/nginx-service 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

http://localhost:8080/ にアクセスすると、Webサーバーにアクセスすることができます。

そのほかのk8sサンプルを紹介

https://github.com/Alesion30/mini-k8s-playground では他にもいろんなケースの構成を試しています。

  • lb-sample: ロードバランサーのサービスを用いた構成
  • local-image-sample: ローカルでビルドしたDockerイメージを用いた構成