9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ローカルのKubernetesの実験環境としてminikubeを使用する

Posted at

はじめに

ローカルに実験的にKubernetesを立てようと思った時、本番環境との構成の違いに悩んでしまうことがあります。Kubernetes自体は動かすことはできますが、PODのボリュームやIngressを同じように作成できないことなどがあります。そのすべてを解決するものではありませんが、ある程度の機能を持つものとしてminikubeがあります。

この記事では、minikubeのインストールからリソースの作成を行い、ローカルでのKubernetesを少しでも身近に感じてもらえれば幸いです。

minikubeの特徴

この記事では以下のminikubeの特徴について、後述のハンズオンで触れてみます。

・PersistentVolumeの動的プロビジョニングの機能を持つ
 クラウドのKubernetesクラスタでは、ボリュームの場所を動的に確保しPVを作成できるものがあります。minikubeでもVMドライバーの場所を動的に確保しPVを作成することができます。

・ローカルのDockerイメージを使用できる
 クラウドではコンテナレジストリを使用しますが、minikubeでは不要でローカルのイメージを使用できます。

・Ingressコントローラーをアドオンとして使うことができる
 minikubeにはアドオンの機能があり、楽にNginxのIngressコントローラーを作成することができます。お手軽にIngressに触れることができます。

詳細は以下のドキュメントになります。

minikubeを動かすためのCPU,メモリー

参考にKubernetesも載せておきます。minikubeが軽いわけではないですね。

CPUコア数 メモリー 参照URL
minikube 2 2GB https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
Kubernetes 2 2GB https://minikube.sigs.k8s.io/docs/start/

minikubeのインストールとstart

前提としてOSはAmazon Linux 2です。
まずはDockerをインストールします。

$ sudo yum install -y docker-20.10.17-1.amzn2.0.1
$ sudo systemctl start docker
$ sudo systemctl enable docker
$ sudo gpasswd -a ec2-user docker

ユーザーのグループを変更したので、いったん再ログインします。
その後、minikubeをインストールします。

$ curl -LO https://storage.googleapis.com/minikube/releases/v1.27.1/minikube-linux-amd64
$ sudo install minikube-linux-amd64 /usr/local/bin/minikube

minikubeをstartさせます。オプションとしてKubernetesのバージョン指定やリソースの制限などができます。

[ec2-user@ip-10-0-0-50 ~]$ minikube start \
--cpus='2' \
--memory='2g' \
--driver='docker' \
--kubernetes-version=v1.25.2
😄  minikube v1.27.1 on Amazon 2 (xen/amd64)MINIKUBE_ACTIVE_DOCKERD=minikube
✨  Using the docker driver based on user configuration
📌  Using Docker driver with root privileges
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
💾  Downloading Kubernetes v1.25.2 preload ...
    > preloaded-images-k8s-v18-v1...:  385.41 MiB / 385.41 MiB  100.00% 41.56 M
🔥  Creating docker container (CPUs=2, Memory=2048MB) ...
🐳  Preparing Kubernetes v1.25.2 on Docker 20.10.18 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: default-storageclass, storage-provisioner
💡  kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

この時点で、kubectlコマンドを使うことができます。

$ minikube kubectl -- get node
NAME       STATUS   ROLES           AGE     VERSION
minikube   Ready    control-plane   2m34s   v1.25.3

しかし、コマンドが長く面倒なのでaliasを設定します。

$ alias k="minikube kubectl --"
$ echo 'alias k="minikube kubectl --"' >> ~/.bash_profile

これで「minikube kubectl --」から「k」にコマンドを短くできました。
また、このままではDockerでビルドしたイメージを使うことができません。以下のコマンドを実行します。

$ eval $(minikube docker-env)
$ echo 'eval $(minikube docker-env)' >> ~/.bash_profile

ハンズオン

PVの動的プロビジョニングの確認

それではクラスター上にKubernetesリソースを作成してみます。
以下のサンプルからStatefulSet、Serviceを作成します。

[ec2-user@ip-10-0-0-50 ~]$ k apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/ja/examples/application/web/web.yaml
service/nginx created
statefulset.apps/web created

StatefulSetのボリュームテンプレートから、自動で動的にボリュームが作成されます。

[ec2-user@ip-10-0-0-50 ~]$ k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
pvc-257531da-0c5f-4142-b50b-faf3f91897a0   1Gi        RWO            Delete           Bound    default/www-web-0   standard                12m
pvc-af257a5b-ddd5-40be-b753-d836a2e5757a   1Gi        RWO            Delete           Bound    default/www-web-1   standard                11m
[ec2-user@ip-10-0-0-50 ~]$ k get pvc
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pvc-257531da-0c5f-4142-b50b-faf3f91897a0   1Gi        RWO            standard       12m
www-web-1   Bound    pvc-af257a5b-ddd5-40be-b753-d836a2e5757a   1Gi        RWO            standard       12m

どこにボリュームの場所が作成されているかですが、PVをdescribeするとわかります。

[ec2-user@ip-10-0-0-50 ~]$ k describe pv pvc-257531da-0c5f-4142-b50b-faf3f91897a0
Name:            pvc-257531da-0c5f-4142-b50b-faf3f91897a0
Labels:          <none>
Annotations:     hostPathProvisionerIdentity: 8481dbd2-eea1-4c46-90ba-17db4f7a928b
                 pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    standard
Status:          Bound
Claim:           default/www-web-0
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp/hostpath-provisioner/default/www-web-0
    HostPathType:
Events:            <none>

minikubeではVMドライバー上に場所が確保されます。minikubeの起動ログにUsing Docker driver with root privilegesとあったのでroot権限でコンテナを動かしていそうです。確認してみます。

[ec2-user@ip-10-0-0-50 ~]$ sudo docker ps
CONTAINER ID   IMAGE                                 COMMAND                  CREATED          STATUS          PORTS                                                                                                                                  NAMES
440ec508be92   gcr.io/k8s-minikube/kicbase:v0.0.35   "/usr/local/bin/entr…"   20 minutes ago   Up 20 minutes   127.0.0.1:49162->22/tcp, 127.0.0.1:49161->2376/tcp, 127.0.0.1:49160->5000/tcp, 127.0.0.1:49159->8443/tcp, 127.0.0.1:49158->32443/tcp   minikube
[ec2-user@ip-10-0-0-50 ~]$ sudo docker exec -it minikube bash
root@minikube:/# ls /tmp/hostpath-provisioner/default/
www-web-0  www-web-1

minikubeのコンテナ上にPVの場所を確認することができました。コンテナ上なので、再起動すると消える一時的なものになると思います。

ローカルのDockerイメージの使用

コンテナのイメージを別のNginxに切り替えてみます。

$ docker pull nginx
$ docker tag nginx:latest my-nginx:v1.0
$ k edit statefulset web #imageをmy-nginx:v1.0に書き換える。

PODの参照するイメージが切り替わり、再起動できていればローカルのイメージを使えていそうです。

[ec2-user@ip-10-0-0-20 ~]$ k get pod
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          10s
web-1   1/1     Running   0          14s
[ec2-user@ip-10-0-0-20 ~]$ k describe pod web-0 | grep 'Image:'
    Image:          my-nginx:v1.0

自動で再起動されていました。もしeval $(minikube docker-env)を実行しなければローカルのイメージを使えず、実行後イメージの再ビルドをすることになりました。。

Ingressコントローラーをアドオンとして使用する

Ingressコントローラーをminikubeで使いたい場合、アドオンとして楽に作成できます。しかし、以下のドキュメントのようにクラウド、クラスタによって適したIngressコントローラーは異なります。環境毎に違うものになってしまうため、お手軽にIngressを試したい場合に以下の手順が参考になると思います。

以下のコマンドで作成します。

$ minikube addons enable ingress

Ingressコントローラーを追加できると、Namespace「ingress-nginx」が自動で作られDeploymentができています。

[ec2-user@ip-10-0-0-20 ~]$ k get deployment -n ingress-nginx
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx-controller   1/1     1            1           107s
[ec2-user@ip-10-0-0-20 ~]$ k get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-l5qzs        0/1     Completed   0          2m3s
ingress-nginx-admission-patch-2tnrq         0/1     Completed   0          2m3s
ingress-nginx-controller-5959f988fd-bvfww   1/1     Running     0          2m3s

早速Ingressコントローラーを使って、前に作ったStatefulSetのPODにアクセスできるようにしてみます。
まず、POD内部でアクセスできるようになっているか確認します。

[ec2-user@ip-10-0-0-20 ~]$ k exec web-0 -it -- bash
root@web-0:/# curl localhost #htmlファイルがないのでエラーになります。
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.23.2</center>
</body>
root@web-0:/# echo "hogehoge web-0" > /usr/share/nginx/html/index.html #表示できればよいので内容はなんでも良しとします。
root@web-0:/# curl localhost
hogehoge web-0
</html>

同様にもう1台のPODもhtmlファイルを作成しておきます。
次にIngressを作成します。

test-nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-nginx
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - host: test-nginx
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
$ k apply -f test-nginx-ingress.yaml

Ingressが存在して、バックエンドにPODが存在しているかを確認します。

[ec2-user@ip-10-0-0-20 ~]$ k get ingress
NAME         CLASS   HOSTS        ADDRESS        PORTS   AGE
test-nginx   nginx   test-nginx   192.168.49.2   80      83s
[ec2-user@ip-10-0-0-20 ~]$ k describe ingress
Name:             test-nginx
Labels:           <none>
Namespace:        default
Address:          192.168.49.2
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  test-nginx
              /   nginx:80 (172.17.0.3:80,172.17.0.4:80)
Annotations:  nginx.ingress.kubernetes.io/rewrite-target: /$1
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    47s (x2 over 94s)  nginx-ingress-controller  Scheduled for sync

バックエンドにはPODが2台ともいました。
また、Ingressの設定におかしなところがないかはIngressコントローラーのログを見るとわかります。

$ k logs -n ingress-nginx ingress-nginx-controller-5959f988fd-bvfww

また、IngressにはIPアドレス「192.168.49.2」が割り当てられており、アクセスすることができます。

[ec2-user@ip-10-0-0-20 ~]$ curl 192.168.49.2:80
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

404エラーなので、バックエンドのPODには到達せずIngressコントローラーから応答が返ってきています。
バックエンドのPODにアクセスするには、ホスト名を指定します。

[ec2-user@ip-10-0-0-20 ~]$ curl 192.168.49.2:80 -H "Host:test-nginx"
hogehoge web-0
[ec2-user@ip-10-0-0-20 ~]$ curl 192.168.49.2:80 -H "Host:test-nginx"
hogehoge web-1
[ec2-user@ip-10-0-0-20 ~]$ curl 192.168.49.2:80 -H "Host:test-nginx"
hogehoge web-1
[ec2-user@ip-10-0-0-20 ~]$ curl 192.168.49.2:80 -H "Host:test-nginx"
hogehoge web-0

アクセスできました。繰り返すと応答が異なっており2台のPODにアクセスしていることがわかります。

minikube実験後のKubernetesへの移行について

minikubeでの実験後、Kubernetes本番で検証することになると思います。この時、どうしても設定の違いは出て切ると思います(annotations,パラメータなど)。
そのため、minikubeとKubernetesを行き来するたび、設定を書き換えなくてはならないかと思ってしまいます。
そこでKustomizeの使用が検討されることになると思いますので、今後調べたいと思っています。

終わりに

今回はローカルでKubernetesを動かす方法について触れました。
記事にすると、今まで学んだ様々なことを俯瞰して整理できてよいと思いました。
今後も勉強します。

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?