kubernetes(k8s)を構築してデプロイやスケールで遊んでみた

この記事は:birthday:アイスタイル Advent Calendar 2020:birthday:15日目の記事になります

みなさんこんにちは
istyle入社2年目のkuriyamayです

私は普段、@cosmeのアプリやwebページのいろんなところに表示されている記事フィードを扱う配信基盤を担当しています

アドカレでは循環的複雑度(Cyclomatic complexity)について書こうかと思っていましたが、最近kubernetesを勉強しているので、復習も兼ねてkubernetesのことを書いていきます

目次

  • kubernetesをテーマにした理由
  • kubernetesとは
  • kubernetesをさわってみる
    • ローカル環境構築
    • アプリケーションのデプロイ
    • 動作確認
    • スケールと自動復旧
  • 今後の展望
  • 最後に

kubernetesをテーマにした理由

私が現在担当してるプロダクトはJava11 + Spring Boot/Vue.jsの構成となっています

今まで携わってきた業務もGolangやPHPを使ったプロダクトでインフラはほぼ未経験
そんな私がどうしてkubernetesに手を出したのか・・・

理由は簡単
おもしろそうだから、ですね:smile:

一応他にも
IaCの知識を深めたいとか
業務でもっとコンテナを活用していきたいとか
いつかはインフラやりたいとか
いろいろとありますが、きっかけとしてはこの理由になります:smile:

kubernetesとは

Dockerを取り巻くオーケストレーションシステムのデファクトスタンダードとしてkubernetes(k8s)が挙げられますね

  • コンテナを用いたアプリケーションのデプロイ
  • Dockerホストの管理
  • サーバリソースを考慮したコンテナ配置
  • スケーリング
  • ロードバランサー
  • 死活監視

等々、いろんな仕組みを備えているコンテナオーケストレーションシステムです

kubernetesをさわってみる

まずローカル環境にkubernetesを構築していき、それをもとにいろいろとさわりながら理解を深めていこうと思います

環境情報はこちら

macOS Catalina: v10.15.7
Docker for Mac
Docker Engine: v19.03.13
Kuvernetes: v1.19.3

ローカル環境構築

Docker for Mac ~ kubernetes有効化

dockerアカウントを作成しDocker for Macをインストール
https://hub.docker.com/editions/community/docker-ce-desktop-mac/

インストールが完了し、dockerが起動したら :whale: さんマークが出てくるので、そこを押してDashboardを開きます

続いて、settings -> Kubernetesを開きKubernetesを有効にします

kubernetesが有効になるとrunningと表示されますね
簡単!

この状態でいくつかのコマンドを叩いてみましょう

$ docker version
Client: Docker Engine - Community
 Cloud integration: 1.0.2
 Version:           19.03.13
 ...省略

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:50:19Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:41:49Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"}
$ kubectl get pods --namespace=kube-system
NAME                                     READY   STATUS    RESTARTS   AGE
coredns-f9fd979d6-282wr                  1/1     Running   6          12d
coredns-f9fd979d6-77kzs                  1/1     Running   6          12d
etcd-docker-desktop                      1/1     Running   6          12d
kube-apiserver-docker-desktop            1/1     Running   6          12d
kube-controller-manager-docker-desktop   1/1     Running   6          12d
kube-proxy-9hw4c                         1/1     Running   6          12d
kube-scheduler-docker-desktop            1/1     Running   26         12d
kubernetes-dashboard-6ff6454fdc-xwzxx    1/1     Running   8          10d
storage-provisioner                      1/1     Running   27         12d
vpnkit-controller                        1/1     Running   6          12d

kubectlというコマンドが出てきました
これはkubernetesのコマンドラインツールで、リソースやクラスタの操作の他、コンテナのシェルに入ったりすることも出来ます
よく使うコマンドは覚えておきたいですね

Kubernetes Dashboard

kubernetesにはDashboardが用意されています
https://github.com/kubernetes/dashboard

READMEに書いてある通りやっていきましょう

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.5/aio/deploy/recommended.yaml
namespace/kubernetes-dashboard unchanged
serviceaccount/kubernetes-dashboard unchanged
service/kubernetes-dashboard unchanged
secret/kubernetes-dashboard-certs unchanged
secret/kubernetes-dashboard-csrf configured
secret/kubernetes-dashboard-key-holder unchanged
configmap/kubernetes-dashboard-settings unchanged
role.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard unchanged
deployment.apps/kubernetes-dashboard configured
service/dashboard-metrics-scraper unchanged
deployment.apps/dashboard-metrics-scraper configured
$ kubectl proxy
Starting to serve on 127.0.0.1:8001

proxyサーバを立ち上げ下記URLを開くとこのような画面になります

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

tokenでログインしたいので下記コマンドでtokenを探しましょう

kubectl -n kube-system get secret

default-token-*をコピったら次はこちらのコマンドを実行しtokenをコピー、Dashboardに貼り付けてSign inします

kubectl -n kube-system describe secret default-token-*

おけおけ!いい感じですね!
ここまでがローカル環境構築です
次はアプリケーションのデプロイに挑戦します

アプリケーションのデプロイ

deploymentとserviceのマニフェストファイル作成

deployment.yml

アプリケーションのデプロイをするのに必要なdeploymentのマニフェストファイルを作成します
このdeploymentとは

  • ReplicaSetの世代管理をする
  • ReplicaSetは同じ仕様のPodを複数生成・管理をする
  • Podはコンテナ集合体の単位でコンテナを実行する方法を定義する

というものですが、、、うーんいきなり複雑になりましたね:persevere:

deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-app
spec:
  selector:
    matchLabels:
      app: go-app
  replicas: 1
  template:
    metadata:
      labels:
        app: go-app
    spec:
      containers:
      - name: go-app
        image: nyankuri/golang-gin
        ports:
        - containerPort: 8080

使用してるimageは今回のアドカレ用に作成したGo + ginのアプリケーションです

service.yml

deploymentのマニフェストファイルを作ったら次はserviceです
serviceとは

  • Podの集合にアクセスするための経路を定義する

こちらは理解しやすいですね:yum:

service.yml

apiVersion: v1
kind: Service
metadata:
  name: go-app-service
spec:
  type: NodePort
  ports:
  - port: 8080
  selector:
    app: go-app

動作確認

deploymentとserviceのマニフェストファイルが用意できたのでkubernetesにデプロイしていきます

$ kubectl apply -f k8s/deployment.yml
deployment.apps/go-app created
$ kubectl apply -f k8s/service.yml 
service/go-app-service created

この状態でDashboardを見てみます

Deployments/Pods/Replica Setsが動いてるのがわかりますね:yum:

Servicesはこのようになっています

go-app-service -> Internal Endpointsの下にあるportに接続してみましょう

deployment.ymlのimageに定義したアプリケーションに繋ぐことができました!よかった:yum:

スケール

kubernetesの動きをもうちょっと見たいのでスケールさせます

まずは今の状態

$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
go-app-df6ddf76d-rtp9b   1/1     Running   0          15m

次にdeployment.ymlのreplicasを1 -> 4に変更してapplyします

$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
go-app-df6ddf76d-bzz4p   1/1     Running   0          22s
go-app-df6ddf76d-dvmmb   1/1     Running   0          22s
go-app-df6ddf76d-rtp9b   1/1     Running   0          18m
go-app-df6ddf76d-tr67c   1/1     Running   0          22s

マニフェストファイルの定義を変更するだけで簡単にスケールすることが出来ました

自動復旧

続いて自動復旧をさせてみます
tr67cのpodに消えてもらいましょう:innocent:

$ kubectl delete pod go-app-df6ddf76d-tr67c
pod "go-app-df6ddf76d-tr67c" deleted

そしてまたpodの状態を見ると、、、

$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
go-app-df6ddf76d-bzz4p   1/1     Running   0          2m20s
go-app-df6ddf76d-dvmmb   1/1     Running   0          2m20s
go-app-df6ddf76d-dxrvf   1/1     Running   0          10s
go-app-df6ddf76d-rtp9b   1/1     Running   0          20m

tr67cが消えて新たにdxrvfが出来てます
podが消えても自動で復旧してくれましたね

今後の展望

ゆくゆくは本番環境でkubernetesを使ってみたいなと思っていますが、それまでには覚えること、やるべきことがいっぱいあります
Dockerフレンドリなアプリケーションを作ったり、運用方法をしっかり考えたり、Linuxの知識をもっと身につけたりと、自分にできることを少しずつやってゴールに向かっていきたいと思います

最後に

kubernetesの構築とアプリケーションのデプロイ等を確認しましたがけっこう長くなってしまいました
ここまで読んで頂きありがとうございます:whale:

明日のアドベントカレンダーはsakohさんのCompletableFutureをJSのPromise.allっぽく扱う(Java)ですね
どんな内容なのかとても楽しみです:yum:

ネコ好きエンジニア Docker/kubernetes勉強中 業務では主にJavaを書いています