NnmnLog

MinikubeでKubernetesのローカル環境を構築する

作成: 2020-08-04
更新: 2020-08-04

Minikubeとは

Minikubeは、dockerのオーケストレーションツールであるKubernetesをローカル環境に構築するツールです。

仮想マシンやHyperKitなどの仮想化ツールでクラスターを作成し、その上にKubernetes環境を構築します。 仮想マシンには、VirtualBoxVMwareなどを選択できます。 今回はDocker for Macで使われているHyperKitを使って構築していきたいと思います。

Minikubeをインストールする

  • Macの場合
$ brew install minikube
  • Ubuntu 20.04の場合(dockerがインストール済みであること)
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube
$ sudo mkdir -p /usr/local/bin/
$ sudo install minikube /usr/local/bin/

クラスターを作成する

  • Macの場合
$ minikube start --vm-driver=hyperkit
  • Ubuntu 20.04の場合
$ minikube start --driver=docker

kubectlの設定にminikubeが追加されます。

$ kubectl config get-contexts
CURRENT   NAME       CLUSTER    AUTHINFO   NAMESPACE
*         minikube   minikube   minikube

アプリケーションのイメージをビルドする

docker環境の切り替え

Kubernetesにデプロイするアプリケーションのコンテナイメージを作成します。 アプリケーションのイメージはHost OSでビルドしますが、そのままではKubernetesへデプロイする際にイメージにアクセスできないため、minikubeが構築したKubernetesと同じ環境にイメージを作成する必要があります。

そのためには、以下を実行してdockerの実行環境を切り替えます。

$ eval $(minikube docker-env)
# 以降、dockerコマンドはminikubeが使用している環境を参照するため、Kubernetesの管理用Podが見えるようになります。
$ docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
e9de15406e53        70f311871ae1           "/coredns -conf /etc…"   21 hours ago        Up 21 hours                             k8s_coredns_coredns-6955765f44-7z9zg_kube-system_28f5a3bc-8fd7-41e8-876d-3efc193d86f5_0
f45a11c68f6a        70f311871ae1           "/coredns -conf /etc…"   21 hours ago        Up 21 hours                             k8s_coredns_coredns-6955765f44-n5wvp_kube-system_a6e855bf-1411-4764-9a08-16d00bd26813_0
...

dockerイメージをbuildする

RubyのSinatraを使った簡単なアプリをデプロイしてみます。

デプロイするスクリプトは以下のような構成になっています。

$ tree
.
├── README.md
├── app
│   ├── Dockerfile
│   ├── Gemfile
│   └── app.rb
└── deployments.yaml

デプロイするGemfileとスクリプトは以下。

app/app.rb
# frozen_string_literal: true

source 'https://rubygems.org'

git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }

gem 'sinatra'
app/app.rb
# frozen_string_literal: true

require 'sinatra'

set :bind, '0.0.0.0'

get '/' do
  'Hello world'
end

アプリケーションのDocker Imageは以下のDockerfileで作成します。

app/app.rb
FROM ruby:2.7.0

WORKDIR /app
ADD . $WORKDIR

RUN bundle install

CMD bundle exec ruby app.rb -e production

アプリケーションのイメージをビルドします。 イメージ名は<Docker Hubのユーザー名>/<アプリ名>:<タグ>としました。

$ docker build ./app/ -t nnnamani/sample-app:v1

Kubernetes にデプロイする

Kubernetesへのデプロイは、コマンドで直接デプロイする場合と、マニフェストファイルを使った方法があります。

コマンドで直接デプロイする

コマンドで直接デプロイする場合は、kubectl create deploymentでサービスを作成した後、kubectl expose deploymentでサービスを公開します。

$ kubectl create deployment sample-app --image=nnnamani/sample-app:v1
$ kubectl expose deployment sample-app --type=LoadBalancer --port=4567

以下のコマンドを実行することで、ブラウザが開きデプロイしたアプリケーションを確認できます。

$ minikube service sample-app

マニフェストファイルを使ってデプロイする

deployments.yamlというyamlファイルを作成して、kubectl apply -f deployments.yamlコマンドでデプロイします。 コマンドで直接デプロイする方法と同様にminikube service sample-appを実行するとブラウザでアプリにアクセスできます。

今回は、以下の内容でマニフェストファイルを作成しました。マニフェストファイルの詳しい内容についてはここでは詳しく調べません。

ざっくりとした内容としては、kind: DeploymentでDeploymentオブジェクトというアプリケーションに関する情報を記述することと、kind: Serviceでアプリケーションを公開するためにネットワーク情報Portなどを作成するという感じです。

deployments.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
spec:
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: sample-app
        image: nnnamani/sample-app:v1
        ports:
        - containerPort: 4567
---
apiVersion: v1
kind: Service
metadata:
  name: sample-app
spec:
  type: NodePort
  selector:
    app: sample-app
  ports:
  - nodePort: 30000
    protocol: TCP
    port: 4567
    targetPort: 4567

まとめ

minikubeでKubernetesのローカル環境を構築する方法を確認してみました。 今回使ったソースコードはこちらにあります。 とりあえず、Minikube上にデプロイして確認してみるまで確認できましたが、マニフェストファイルについてなど、学習することは多そうです。

課題

  • アプリケーションのイメージをKubernetesと同じ環境でbuildするため、Kubernetesが利用するdocker環境を汚染してしまう
    • イメージのbuildは、Cloud Buildなど外部サービスを使い、GCRなどにPushした方が良いかもしれない
  • GKEなどへのデプロイを考えると、作成したイメージグローバルな場所にプライベートリポジトリを作ってPushした方が良さそう
  • マニフェストファイルに関して学習したい
    • デプロイやネットワークの情報の他にJobなどもマニフェストファイルで定義可能なので、Kubernetes オブジェクトに関する理解を深めるためには重要そう