aws-minikube: ELB とも連携できてフットワークが軽い AWS k8s 環境

k8s 環境として minikube, eks, aws-minikube を比較してみました(k3s は未経験)。個人的には aws-minikube がコスト面/機能面でよさそうに思えたので紹介です。

aws-minikube とは?

EC2 1 台で k8s 環境が整うツールです。Red Hat 社の Jakub Scholz 氏が 2017 年から開発しています。最新の k8s への対応も早いです。 terraform ベースの aws-minikube と kubeadm ベースの aws-kubernetes の 2 段揃えの構成です。

github.com

(日本ではあまり知られていないようです... 私は minikube で ELB も使えるような拡張がないかな... とぐぐっていた時にたまたま見つけました)

使用する AWS リソース

terrafrom apply すると my-minikube という EC2 と f:id:kyagi:20220221201110p:plain

my-minikube.<your.domain.here> という Route53 レコードが追加されます。 f:id:kyagi:20220221201142p:plain

Security Group も作成されます。以下では自宅 IP に変更していますがデフォルトは 0.0.0.0/0。6443 は k8s の API をたたくポートで専用の .kube/config (認証情報を含む設定ファイル) が構築時に発行されます。 f:id:kyagi:20220221202550p:plain

何が嬉しいのか

  • 1 台で k8s 環境がそろう
  • 使う ec2 は t2.medium でコストが安い。1 ヶ月 4377 円(= 0.0608 USD * 100 * 24 * 30)。これはデフォルトで t3.medium 2 台を使って EKS 代も徴収する EKS の 1/3。環境構築のスピードも早いのでそのたびに作って壊してもストレスがない。
  • 環境構築のスピードがはやい。EKS だと cluster 作成に 20 分くらいかかるけどこちらは 5 分ほど。
  • minikube の制約だったサービスの外部公開が簡単に可能。service を type:LoadBalancer で create/delete すると応じて ELB が作られる/削除される
  • いじる aws リソースが最小限(EC2, Route53, SecurityGroup)
  • terraform apply/destroy でまるごと消せる

想定する使い方

開発者ごとに t2.medium の EC2 1 台を支給し、手軽に k8s を試してもらって組織の k8s 力をあげる、といった使い方がよさそうです。

minkube, aws-minikube, eks の比較

候補 お手軽さ 時間 できること コスト 後始末
minikube
aws-minikube
eks

コスト内訳

候補 コスト構成 コスト/日 コスト/月
minikube ローカルの Mac で動かせば無料、EC2 の場合は EC2 料金(*1) 146円 4,377 円
aws-minikube EC2 料金(*1) 146円 4,377円
EKS EC2 料金(*2) + EKS 料金 440円 13,200円
  • *1 t2.medium で計算(vCPU が 2 つある EC2)
  • *2 t3.medium * 2 で計算(EKS がデフォルトで選択する)

使い方

*ほぼ README 通りですが AWS MarketPlace の centos AMI を subscribe する必要があります。無料です)

1. centos の AMI を subscribe する(これをしないと terraform apply 時に止まります)

https://aws.amazon.com/marketplace/pp/prodview-qkzypm3vjr45g

f:id:kyagi:20220221201412p:plain

2. 設定ファイルを書き換える

$ git diff
diff --git a/example.tfvars b/example.tfvars
index 177a1fe..a16914c 100644
--- a/example.tfvars
+++ b/example.tfvars
@@ -1,5 +1,5 @@
 # AWS region where should the Minikube be deployed
-aws_region = "eu-central-1"
+aws_region = "ap-northeast-1"

 # Name for role, policy and cloud formation stack (without DBG-DEV- prefix)
 cluster_name = "my-minikube"
@@ -8,13 +8,13 @@ cluster_name = "my-minikube"
 aws_instance_type = "t2.medium"

 # SSH key for the machine
-ssh_public_key = "~/.ssh/id_rsa.pub"
+ssh_public_key = "~/.ssh/id_rsa.ubuntu.com.amazonaws.info.myservice.dev.all.pub"

 # Subnet ID where the minikube should run
-aws_subnet_id = "subnet-8a3517f8"
+aws_subnet_id = "subnet-0a102dc87cd20932e"

 # DNS zone where the domain is placed
-hosted_zone = "my-domain.com"
+hosted_zone = "my.service.com"
 hosted_zone_private = false

 # AMI image to use (if empty or not defined, latest CentOS 7 will be used)

3. terraform apply する

f:id:kyagi:20220221201437p:plain

(... snip ...)

f:id:kyagi:20220221201452p:plain

4. EC2 がたちあがるので SSH ログインする

5. config ファイル作成して完了

[centos@ip-10-0-0-87 ~]$ mkdir .kube
[centos@ip-10-0-0-87 ~]$ cp kubeconfig ~/.kube/config
[centos@ip-10-0-0-87 ~]$ kubectl get svc --all-namespaces
NAMESPACE     NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP                  11h
kube-system   dashboard-metrics-scraper   ClusterIP   10.103.238.218   <none>        8000/TCP                 11h
kube-system   kube-dns                    ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP   11h
kube-system   kubernetes-dashboard        ClusterIP   10.96.254.133    <none>        443/TCP                  11h
kube-system   metrics-server              ClusterIP   10.103.193.240   <none>        443/TCP                  11h

6. サービスを作って ELB で外部公開

[centos@ip-10-0-0-87 ~]$ kubectl create deployment kubia --image=kyagi/kubia --replicas=3 --port=8080
deployment.apps/kubia created

[centos@ip-10-0-0-87 ~]$ kubectl expose deployment kubia --port=8080 --target-port=8080 --type=LoadBalancer --name=kubia
service/kubia exposed

[centos@ip-10-0-0-87 ~]$ kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                                    PORT(S)          AGE
kubernetes   ClusterIP      10.96.0.1       <none>                                                                         443/TCP          11h
kubia        LoadBalancer   10.97.188.164   a81e8fb4f947f444f9bae599cf38ca3a-2070947448.ap-northeast-1.elb.amazonaws.com   8080:31678/TCP   10s

[centos@ip-10-0-0-87 ~]$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
kubia-7f585c778c-k4t5h   1/1     Running   0          10m
kubia-7f585c778c-nkzbr   1/1     Running   0          10m
kubia-7f585c778c-p77hr   1/1     Running   0          10m

(外部公開を確認) f:id:kyagi:20220221201516p:plain

(ELB が作られている) f:id:kyagi:20220221201537p:plain