13
13

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 3 years have passed since last update.

【Kubernetes入門】ローカル環境にReactアプリをデプロイする

Posted at

やること

今回は簡単にKubernetes環境が作れる「Minikube」を用いてローカル環境にReactアプリケーションをデプロイし、疎通確認をしていきます。
また、今回のソースコードはGitHubに乗せています。
MobilitySDG/react-k8s - GitHub

使用する環境

  • OS : Apple M1 macOS BigSur 11.4
  • docker : v20.10.7

Minikubeのインストール

こちらのサイトからインストールを行ってください。
(Intel版、Apple M1版ありますので、自分の環境にあったものをインストールしてください。)
M1のMacの場合は以下で入手できます。

$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-arm64
$ sudo install minikube-darwin-arm64 /usr/local/bin/minikube

また、上記のURLページ内にも記載がありますが、Minikubeを使うにはDocker等のコンテナ、仮想マシン環境が必要になるので別途インストールをお願いします。

kubectlのインストール

Kubernetesを使用する際には「kubectl」コマンドを使うため使えるようにします。
こちらのサイトからインストールを行ってください。
M1のMacの方は以下で入手できます。

$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl.sha256"
$ echo "$(<kubectl.sha256)  kubectl" | shasum -a 256 --check
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
$ sudo chown root: /usr/local/bin/kubectl

Minikubeの動作確認

インストールしたminikubeとkubectlの確認をしてみましょう。
以下コマンドで起動できます。

$ minikube start
😄  Darwin 11.4 (arm64) 上の minikube v1.21.0
✨  dockerドライバーが自動的に選択されました
👍  コントロールプレーンのノード minikube を minikube 上で起動しています
🚜  イメージを Pull しています...
🔥  docker container (CPUs=2, Memory=1988MB) を作成しています...

🧯  Docker is nearly out of disk space, which may cause deployments to fail! (87% of capacity)
💡  提案: 

    Try one or more of the following to free up space on the device:
    
    1. Run "docker system prune" to remove unused Docker data (optionally with "-a")
    2. Increase the storage allocated to Docker for Desktop by clicking on:
    Docker icon > Preferences > Resources > Disk Image Size
    3. Run "minikube ssh -- docker system prune" if using the Docker container runtime
🍿  Related issue: https://github.com/kubernetes/minikube/issues/9024

🐳  Docker 20.10.7 で Kubernetes v1.20.7 を準備しています...
    ▪ 証明書と鍵を作成しています...
    ▪ Control Plane を起動しています...
    ▪ RBAC のルールを設定中です...
🔎  Kubernetes コンポーネントを検証しています...
    ▪ イメージ gcr.io/k8s-minikube/storage-provisioner:v5 を使用しています
🌟  有効なアドオン: storage-provisioner, default-storageclass
🏄  完了しました! kubectl が「"minikube"」クラスタと「"default"」ネームスペースを使用するよう構成されました

kubectlコマンドも確認しましょう。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.2", GitCommit:"092fbfbf53427de67cac1e9fa54aaa09a28371d7", GitTreeState:"clean", BuildDate:"2021-06-16T12:59:11Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"darwin/arm64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.7", GitCommit:"132a687512d7fb058d0f5890f07d4121b3f0a2e2", GitTreeState:"clean", BuildDate:"2021-05-12T12:32:49Z", GoVersion:"go1.15.12", Compiler:"gc", Platform:"linux/arm64"}

また、minikubeではダッシュボードを用いてデプロイ状況をGUIで確認することができるので、合わせてみておくと良いと思います。

$ minikube dashboard

スクリーンショット 2021-07-03 22.08.19.png

ローカルのDockerイメージを使えるように設定

後ほどminikubeでデプロイする際に、ローカルのイメージを使うことができるように環境変数を設定します。

$ eval $(minikube docker-env)

※この後の作業で、Dockerイメージのビルド、Kubernetesのymlファイルの実行は上記コマンドを実行したターミナルで行ってください。

Reactアプリケーションの準備

今回はアプリの中までは作成しないため、簡単にcreate-react-appで作成します。

$ npx create-react-app react-k8s
$ cd react-k8s

せっかくなので文言を少し変えておきましょう。
10行目の文言を変えておきます。

/src/App.js
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          {/* Edit <code>src/App.js</code> and save to reload. */}
          {/* ↑ここを変える */} 
          Hello React Application!!
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

変更できたら、以下コマンドで起動させてlocalhost:3000へアクセス。

$ yarn start

スクリーンショット 2021-07-03 16.30.02.png
OKですね!

Dockerfileの作成

デプロイする際にはdockerイメージが必要なので、そこに使うためにDockerfileを作成します。

Dockerfile
# nodeの軽量版を使用
FROM node:14.17.0-alpine

# ワークディレクトリを設定
WORKDIR /app

# ホストの.(カレントディレクトリ)に作成したreactアプリをコンテナの.(=/app)にコピー
COPY . .

# 依存関係のインストール
RUN yarn install

# 起動コマンド
CMD ["yarn", "start"]

イメージを作成して動かしてみましょう。

$ docker build -t mobilitysdg/react-k8s:1.0 .
$ docker images
REPOSITORY                           TAG          IMAGE ID       CREATED         SIZE
mobilitysdg/react-k8s                1.0          9c30bb0dd575   3 minutes ago   589MB

できていますね!イメージを起動して動くか確認しましょう。

$ docker run -p 3000:3000 mobilitysdg/react-k8s:1.0
yarn run v1.22.5
$ react-scripts start
ℹ 「wds」: Project is running at http://172.17.0.3/
ℹ 「wds」: webpack output is served from 
ℹ 「wds」: Content not from webpack is served from /app/public
ℹ 「wds」: 404s will fallback to /
Starting the development server...

Compiled successfully!

You can now view reacr-k8s in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://172.17.0.3:3000

Note that the development build is not optimized.
To create a production build, use yarn build.

良さそうですね!

Kubenetesのymlファイルを書く

1.deployment.yml

deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: react-k8s
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-k8s
  template:
    metadata:
      labels:
        app: react-k8s
    spec:
      containers:
      - name: react-k8s
        image: mobilitysdg/react-k8s:1.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000
        command: ["yarn", "start"]
         

ローカルのイメージを使用する場合は、imagePullPolicyIfNotPresentNeverに設定してください。

2.service.yml

上記deployment.ymlで設定した内容をクラスター外へ公開するためにserviceを作成するための設定を書きます。

service.yml
apiVersion: v1
kind: Service
metadata:
  name: react-k8s
spec:
  type: NodePort
  selector:
    app: react-k8s
  ports:
    - port: 3000
      targetPort: 3000
      protocol: TCP
      name: react-k8s

クラスターの外部からアクセスする際には typeNodePortLoadBalancerを使用しますが、今回はNodePortを使用します。
またこれらにはL4ロードバランサーの役割しかないため、ipアドレスのみでの接続となります。
本番運用する際にはIngressという別のサービスを使用してHTTPでのアクセスができるようにします。

デプロイする

上で作成したdeployment.ymlservice.ymlを用いて実際にデプロイをしていきます。

まずはdeployment.ymlから。

$ kubectl apply -f deployment.yml 
deployment.apps/react-k8s created

$ kubectl get all
NAME                             READY   STATUS    RESTARTS   AGE
pod/react-k8s-75cf4d8ff6-4ksf2   1/1     Running   0          17s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   3h51m

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/react-k8s   1/1     1            1           17s

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/react-k8s-75cf4d8ff6   1         1         1       17s

podがRunning状態になっており、replicasetdeploymentが作成されているのがわかります。

ちなみにダッシュボードを見てみると以下のようにデプロイされていることが確認できます。
スクリーンショット 2021-07-03 22.18.42.png

次にservice.ymlです。

$ kubectl apply -f service.yml
service/react-k8s created

$ kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP          3h59m
react-k8s    NodePort    10.110.66.69   <none>        3000:31609/TCP   23s

react-k8sというserviceが作成されていますね。
これでデプロイ作業は終了です!

ちなみに、今回は役割ごとにdelpoyment.ymlとservie.ymlを分けて書きましたが、一つのファイルにすることもできます。その場合は---でつなげて以下のように書くことができます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: react-k8s
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-k8s
  template:
    metadata:
      labels:
        app: react-k8s
    spec:
      containers:
      - name: react-k8s
        image: mobilitysdg/react-k8s:1.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000
        command: ["yarn", "start"]
         
---
apiVersion: v1
kind: Service
metadata:
  name: react-k8s
spec:
  type: NodePort
  selector:
    app: react-k8s
  ports:
    - port: 3000
      targetPort: 3000
      protocol: TCP
      name: react-k8s

このファイルをkubectl applyすることでまとめてデプロイすることができます。

接続確認

本来であればminikube ipコマンドで取得できるipアドレスと、service作成時に決められたポート(今回は31609)を用いてブラウザからアクセス可能(例えば192.168.49.2:31609)ですが、m1のMacは接続ができないようです、、
なのでminikube serviceを使用します。サービス名は今回react-k8sとしたので以下コマンドでサービスへの接続先を確認します。

$ minikube service react-k8s --url
🏃  Starting tunnel for service react-k8s.
|-----------|-----------|-------------|------------------------|
| NAMESPACE |   NAME    | TARGET PORT |          URL           |
|-----------|-----------|-------------|------------------------|
| default   | react-k8s |             | http://127.0.0.1:60778 |
|-----------|-----------|-------------|------------------------|
http://127.0.0.1:60778

上記で確認したURLにアクセスすると、、
スクリーンショット 2021-07-03 23.01.57.png

アクセスが確認できました!
確認ができたらデプロイしたリソースは削除しておきます。

$ kubectl delete -f service.yml
service "react-k8s" deleted

$ kubectl delete -f deployment.yml 
deployment.apps "react-k8s" deleted

まとめ

今回はアプリ作成〜デプロイまでを広く浅くの形で一通り実施してみました。
Kubernetesを用いたデプロイの参考になればと思います!

宣伝

パーソルプロセス&テクノロジー株式会社(以下パーソルP&T)、システムソリューション(SSOL)事業部所属の戸田です。

私はモビリティソリューションデザインチームに所属しており、モビリティ(ここでは移動手段全般)に関するサービスを考えたり、アプリを構築したりしております。

いわゆる「MaaS」に取り組んでおります。

私たちが「MaaS」に取り組む中で、現在活用している、もしくは活用する予定の技術やサービスやとりあえず発信したいことなどなど、幅広くチームメンバーと共に執筆していきたいと思います。
メンバーごとに違った内容を発信していきますので、お楽しみに!

また、「MaaS」について詳しく知りたい方は、チームメンバーの吉田が記事を掲載しておりますので、
ぜひそちらをご覧ください。

「MaaSとは」でたどり着いて欲しい記事 (1/3 前編)
「MaaSとは」でたどり着いて欲しい記事 (2/3 中編)
「MaaSとは」でたどり着いて欲しい記事 (3/3 後編)

最後まで読んでいただき、ありがとうございました!

13
13
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
13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?