8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kubernetesローカル環境構築

Last updated at Posted at 2023-11-27

目次

(1)概要
(2)準備・前提条件
(3)構築手順
・(3-1)フォルダ構成
・(3-2)DockerDesktop設定
・(3-3)Dockerローカル環境設定
・(3-4)今回使用するKubernetes要素4つ
・(3-5)DBポッド起動
・(3-6)APIポッド起動
・(3-7)FRONTポッド起動
・(3-8)ブラウザ動作確認

(1)概要

本記事では、DockerDesktopを使用し、以下の技術構成の「Kubernetesローカル環境」をしていきます。

- Go
- MySQL
- TypeScript
- React

ローカル環境でもKubernetesを使用し、「本番環境」や「検証環境」でもKubernetesを使用している場合に、環境間の差異を無くすことができます。環境間の差異により、ローカルではうまくいっていても本番環境でポッドが起動しない等のエラーを未然に防ぎましょう!

Kubernetes初学者にとっても無料でKubernetesをいじれるのでおすすめです!

(2)準備・前提条件

【準備するもの】

  • VSCode等のエディタ
  • DockerDesktop
  • asdf等のバージョン管理パッケージ

【前提条件】

  • 既にDockerのローカル開発環境があることを前提といたします。
  • バックエンド、フロントエンドは無理に合わせる必要はありません。

(3)構築手順

【3-1 フォルダ構成】

以下のようなフォルダ構成で、「api」「front」「db」それぞれのpodを立てる構成で構築します。

sample_app/

    - api/
    
        - Dockerfile

        - local-k8s.yaml
    
        - その他アプリファイル..
    
    - front/
    
        - Dockerfile
    
        - local-k8s.yaml
    
        - その他アプリファイル..
    
    - test/
    
        - db/
    
            - Dockerfile
    
            - local-k8s.yaml
    
            - docker-compose.yml

【3-2 DockerDesktop設定】

DockerDesktopのKubernetesの設定をします。

  • DockerDesktopを起動し、右上の設定ボタンで設定画面に遷移します。

    スクリーンショット 2023-11-15 22.28.17.png

  • 設定画面に遷移したら、サイドメニューの「Kubernetes」を選択し、「Enable Kubernetes」にチェックを入れてください。すると右下の「Apply & restart」ボタンが活性化するのでクリックします。

    ※ 再起動するまで少し時間がかかります。

    スクリーンショット 2023-11-15 22.29.25.png

  • 右下に黄緑色のKubernetesのマークが表示されていれば設定完了です。

    スクリーンショット 2023-11-15 22.33.05.png

【3-3 Dockerローカル環境設定】

Docker環境設定はほぼ関係ありませんが、一部設定するとKubernetesのローカル環境構築に役立つので、設定します。

  • docker-compose.ymlの各サービスに「コンテナ名」「イメージ名」を指定します。Kubernetes設定でDockerの「コンテナ名」と「イメージ名」を指定するためです。

    version: '3.8'
    services:
      front:
        image: sample-app-front:latest
        container_name: sample-app-front
    		
    		その他設定....
    	api:
        image: sample-app-api:latest
        container_name: sample-app-api
    
    		その他設定....
    	db:
        image: sample-app-db:latest
        container_name: sample-app-db
    
    		その他設定....
    
    

【3-4 今回使用するKubernetes要素4つ】

「ポッド起動」のために必要なKubernetesの要素4つの解説をします。Kubernetesの基礎を理解している方は、構築とは関係ないので読み飛ばしてください!

【3-4-1 Secret

【概要】

  • 機密データを保存し、ポッドに渡す

【本記事での使用用途】

  • パスワード等を環境変数として、ポッドに渡すことができるので、DBの接続情報を渡します

【メリット】

  • 機密データを安全にポッドに渡すことができる

【3-4-2 Persistent VolumeClaim(PVC)

【概要】

  • データストレージ(PV)へ要求を行う

【本記事での使用用途】

  • データストレージの作成

【メリット】

  • サイズ、アクセスモードを指定してストレージを作成できる
  • データベースのデータをポッドが終了しても永続化できる
  • DB以外のポッドでも使用できる

【用語】

※ Persistent Volume (PV)は、Kubernetesクラスター内のストレージのこと、Persistent VolumeClaim(PVC)はPVへの要求

【 3-4-3 Deployment

【概要】

  • ポッドの管理方法の指定

    ※ Kubernetesのメインの設定はほぼここで設定します。

【本記事での使用用途】

  • 指定したポッドの設定をKubernetesクラスター内にデプロイする
  • 維持するポッド(レプリカ)の数の指定
  • ポッド作成に使うDockerイメージ、コンテナの指定、設定

【メリット】

  • ポッドが停止する等の異常が起こった際も、指定したポッド数を維持するため自動で新しいポッドの作成を行ってくれる

  • アクセスを複数のポッドに分散できる

    ※ DockerデスクトップのKubernetesではこの分散機能は提供していません。 EKS等の本番環境用のKubernetesではこの恩恵を受けることができます。

  • deploymentの設定をあとから変えることで、ポッドの増減を容易に操作できる

【用語】

※ レプリカは、指定したポッドの設定を元にコピーされたポッドのこと。deploymentによって作成されるレプリカ数の指示書のようなものを「ReplicaSet」 という

【3-4-5 Service

【概要】

  • ポッド間、外部からのアクセスを設定します

【本記事での使用用途】

  • 「NodePort」を設定して、外部からアクセスできる設定をします。

【メリット】

  • ポッド毎に柔軟なアクセス制限が可能になる

【3-5 DBポッド起動】

dbポッドを作成します。Kubernetesでは、yamlファイルに設定を記述し、Kubernetesにデプロイすることで作成されます。

yamlファイルはフォルダ構成の「test/db/local-k8s.yaml」に記載していきます。

- test/
    
    - db/
    
        - Dockerfile
    
        - local-k8s.yaml
    
        - docker-compose.yml

DBのポッド作成に使用する要素は以下の4つです。

  • Secret
  • Persistent VolumeClaim(PVC)
  • Deployment
  • Service

最終的な完成コードは以下です。

# 認証情報の設定
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  MYSQL_ROOT_PASSWORD: 「Base64でエンコードしたルートパスワード」
  MYSQL_DATABASE: 「Base64でエンコードしたデータベース名」
  MYSQL_USER: 「Base64でエンコードしたユーザー名」
  MYSQL_PASSWORD: 「Base64でエンコードしたユーザーパスワード」

---

# ストレージの設定
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

---

# deploymentの設定
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
      - name: sample-app-db
        image: sample-app-db:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_ROOT_PASSWORD
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_DATABASE
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_USER
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_PASSWORD
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: db-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: db-persistent-storage
        persistentVolumeClaim:
          claimName: db-pvc

---

# serviceの設定
apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  selector:
    app: db
  ports:
  - protocol: TCP
    port: 3306
    targetPort: 3306
    nodePort: 31306
  type: NodePort

【3-5-1 Secret

  • 以下がSecret完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

## KubernetesAPIのバージョンの指定
apiVersion: v1
## 作成するリソースをSecretにする
kind: Secret
## Secretの名前を指定
metadata:
  name: db-secret
## Secretのタイプを「Opaque」に指定します
## Opaqueは任意のキーと値のペアで機密情報を格納できる
type: Opaque
## DB接続に必要な情報を設定します
## 接続情報は何のルールでもいいので、Base64にエンコードした値を記述するようにしましょう
data:
  MYSQL_ROOT_PASSWORD: 「Base64でエンコードしたルートパスワード」
  MYSQL_DATABASE: 「Base64でエンコードしたデータベース名」
  MYSQL_USER: 「Base64でエンコードしたユーザー名」
  MYSQL_PASSWORD: 「Base64でエンコードしたユーザーパスワード」

【3-5-2 Persistent VolumeClaim(PVC)

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

.... 前の項目のコード

## 「---」を記述することは1つのyamlファイルで複数リソースを記述できます。
---

apiVersion: v1
## 作成するリソースをPersistentVolumeClaimにする
kind: PersistentVolumeClaim
## PersistentVolumeClaimの名前を指定
metadata:
  name: db-pvc
## ストレージボリュームへアクセス設定
## 一度に一つのノードからのみアクセスできるよう設定
spec:
  accessModes:
    - ReadWriteOnce
    ## PVの最小ストレージ容量を1ギガバイトに指定
  resources:
    requests:
      storage: 1Gi

【3-5-3 Deployment

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

.... 前の項目のコード

---

apiVersion: apps/v1
## 作成するリソースをDeploymentにする
kind: Deployment
## Deploymentの名前を指定
metadata:
  name: db
spec:
    ## 実行するポッドのレプリカ数を1つに設定
  replicas: 1
    ## ポッドのラベル名を指定
  selector:
    matchLabels:
      app: db
    ## ポッド作成のためのテンプレートを定義
    ## metadata.labelsに「app: db」を設定し、selectorと一致させる
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
      ## コンテナ名を指定
      - name: sample-app-db
        ## コンテナに使用するイメージを指定
        image: sample-app-db:latest
        ## ローカルのイメージを優先的に取得し、ない場合にイメージをプルする設定
        imagePullPolicy: IfNotPresent
        ## Secretsで設定した値を環境変数として設定
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_ROOT_PASSWORD
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_DATABASE
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_USER
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: MYSQL_PASSWORD
        ## ポートを3306で指定
        ports:
        - containerPort: 3306
        ## コンテナ内でマウントされるボリュームを指定
        volumeMounts:
        - name: db-persistent-storage
          mountPath: /var/lib/mysql
        ## Pod内で使用されるボリュームを指定
        ## 作成したPVCをclaimNameに指定する
      volumes:
      - name: db-persistent-storage
        persistentVolumeClaim:
          claimName: db-pvc

【3-5-4 Service】

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

apiVersion: v1
## 作成するリソースをServiceにする
kind: Service
## Serviceの名前をdbに指定
metadata:
  name: db
## Serviceがリクエストを転送する対象とするポッド名を指定
spec:
  selector:
    app: db
  ports:
  - protocol: TCP
    ## クラスタ内部からServiceにアクセスするためのポート
    port: 3306
    ## Serviceがリクエストを転送するポッドのポート番号
    targetPort: 3306
    ## クラスター外部からServiceにアクセスするためのノードのポートを指定
    nodePort: 31306
  type: NodePort

【3-5-5 ポッド起動】

  • ポッド起動に必要な「kubectlコマンド」がインストール済みか以下のコマンドで確認します。

コマンドの説明が出力されたらインストール済みです。

$ kubectl
  • インストールがされていない場合は、brewや、asdfでkubectlをインストールしましょう。

    以下はasdfの例です。

    $ asdf plugin add kubectl
    
    ## インストールできるバージョンを出力
    $ asdf list all kubectl
    
    ## kubectlをインストール
    $ asdf install kubectl 1.28.3
    
    ## インストールしたバージョンを一覧表示
    $ asdf list kubectl
    
    ## グローバルでの使用するkubectlバージョンを宣言
    $ asdf global kubectl 1.28.3
    
    ## ローカルでの使用するkubectlバージョンを宣言
    $ asdf local kubectl 1.28.3
    
    $ kubectl
    
  • yamlファイルのあるフォルダまで移動する

    $ cd test/db
    
  • yamlファイルの内容をデプロイします。

    $ kubectl apply -f local-k8s.yaml
    

【3-5-6 5つの要素の作成確認】

  • secret確認

    $ kubectl get secrets
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-21 22.36.49.png

  • pvc確認

    $ kubectl get pvc
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-21 22.38.25.png

  • deployment確認

    $ kubectl get deploy
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-21 22.39.55.png

  • pod確認

    $ kubectl get po
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-21 22.35.12.png

  • service確認

    $ kubectl get service
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-21 22.42.11.png

【3-6 APIポッドの起動】

次はAPIポッドを作成します。

yamlファイルはapiフォルダ配下の「local-k8s.yaml」に記載していきます。

sample_app/

    - api/
    
        - Dockerfile

        - local-k8s.yaml
    
        - その他アプリファイル..

APIポッド作成に使用する要素は以下2つです。

  • Deployment
  • Service

最終的な完成コードは以下です。

apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  ports:
  - nodePort: 31000
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: api
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - image: sample-app-api:latest
        imagePullPolicy: IfNotPresent
        name: sample-app-api
        ports:
        - containerPort: 8080
        volumeMounts:
        - mountPath: /api
          name: api-volume
      volumes:
      - hostPath:
          path: /Users/自身のPCのユーザー名/sample-app/api
        name: api-volume

【3-6-1 Service】

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

apiVersion: v1
## 作成するリソースをServiceにする
kind: Service
## Serviceの名前をapi-serviceに指定
metadata:
  name: api-service
spec:
  ports:
    ## クラスター外部からServiceにアクセスするためのノードのポートを指定
  - nodePort: 31000
    ## クラスタ内部からServiceにアクセスするためのポート
    port: 8080
    protocol: TCP
    ## Serviceがリクエストを転送するポッドのポート番号
    targetPort: 8080
    ## Serviceがリクエストを転送する対象とするポッド名を指定
  selector:
    app: api
  type: NodePort

【3-6-2 Deployment

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

.... 前の項目のコード

---
apiVersion: apps/v1
## 作成するリソースをDeploymentにする
kind: Deployment
## Deploymentの名前を指定
metadata:
  name: api
spec:
    ## 実行するポッドのレプリカ数を1つに設定
  replicas: 1
    ## ポッドのラベル名を指定
  selector:
    matchLabels:
      app: api
    ## ポッド作成のためのテンプレートを定義
    ## metadata.labelsに「app: api」を設定し、selectorと一致させる
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        ## コンテナに使用するイメージを指定
      - image: sample-app-api:latest
        ## ローカルのイメージを優先的に取得し、ない場合にイメージをプルする設定
        imagePullPolicy: IfNotPresent
        ## コンテナ名を指定
        name: sample-app-api
        ports:
        - containerPort: 8080
        ## 下で設定するボリュームをマウント対象として指定
        volumeMounts:
        - mountPath: /api
          name: api-volume
        ## ボリュームの設定
      volumes:
      - hostPath:
          path: /Users/自身のPCのユーザー名/sample-app/api
        name: api-volume

【3-6-3 ポッド起動】

  • api用のyamlファイルのあるフォルダまで移動する

    $ cd api
    
  • yamlファイルの内容をデプロイします。

    $ kubectl apply -f local-k8s.yaml
    

【3-6-4 3つの要素の作成確認】

  • deployment確認

    $ kubectl get deploy
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-23 12.57.00.png

  • pod確認

    $ kubectl get po
    

    以下のような内容が出力されたらOKです
    スクリーンショット 2023-11-23 12.57.34.png

  • service確認

    $ kubectl get service
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-23 12.58.31.png

【3-7 FRONTポッドの起動】

次はFRONTポッドを作成します。

yamlファイルはfrontフォルダ配下の「local-k8s.yaml」に記載していきます。

sample_app/
    
    - front/
    
        - Dockerfile
    
        - local-k8s.yaml
    
        - その他アプリファイル..

FRONTポッド作成に使用する要素は以下4つです。

  • Deployment
  • Service

最終的な完成コードは以下です。

apiVersion: v1
kind: Service
metadata:
  name: front-service
spec:
  ports:
  - nodePort: 31001
    port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    app: front
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: front
spec:
  replicas: 1
  selector:
    matchLabels:
      app: front
  template:
    metadata:
      labels:
        app: front
    spec:
      containers:
      - image: sample-app-front:latest
        imagePullPolicy: IfNotPresent
        name: sample-app-front
        ports:
        - containerPort: 3000
        volumeMounts:
        - mountPath: /front
          name: front-volume
      volumes:
      - hostPath:
          path: /Users/自身のPCのユーザー名/sample-app/front
        name: front-volume

【3-7-1 Service】

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

apiVersion: v1
## 作成するリソースをServiceにする
kind: Service
## Serviceの名前をfront-serviceに指定
metadata:
  name: front-service
spec:
  ports:
    ## クラスター外部からServiceにアクセスするためのノードのポートを指定
  - nodePort: 31001
    ## クラスタ内部からServiceにアクセスするためのポート
    port: 3000
    protocol: TCP
    ## Serviceがリクエストを転送するポッドのポート番号
    targetPort: 3000
    ## Serviceがリクエストを転送する対象とするポッド名を指定
  selector:
    app: front
  type: NodePort

【3-7-2 Deployment

  • 以下が完成コードです。コメントの解説を読んでみてください。

local-k8s.yaml

.... 前の項目のコード

---
apiVersion: apps/v1
## 作成するリソースをDeploymentにする
kind: Deployment
## Deploymentの名前を指定
metadata:
  name: front
spec:
    ## 実行するポッドのレプリカ数を1つに設定
  replicas: 1
    ## ポッドのラベル名を指定
  selector:
    matchLabels:
      app: front
    ## ポッド作成のためのテンプレートを定義
    ## metadata.labelsに「app: front」を設定し、selectorと一致させる
  template:
    metadata:
      labels:
        app: front
    spec:
      containers:
        ## コンテナに使用するイメージを指定
      - image: sample-app-front:latest
        ## ローカルのイメージを優先的に取得し、ない場合にイメージをプルする設定
        imagePullPolicy: IfNotPresent
        ## コンテナ名を指定
        name: sample-app-front
        ports:
        - containerPort: 3000
        ## 下で設定するボリュームをマウント対象として指定
        volumeMounts:
        - mountPath: /front
          name: front-volume
        ## ボリュームの設定
      volumes:
      - hostPath:
          path: /Users/自身のPCのユーザー名/sample-app/front
        name: front-volume

【3-7-3 ポッドの起動】

  • front用のyamlファイルのあるフォルダまで移動する

    $ cd front
    
  • yamlファイルの内容をデプロイします。

    $ kubectl apply -f local-k8s.yaml
    

【3-7-4 3つの要素の作成確認】

  • deployment確認

    $ kubectl get deploy
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-23 13.37.09.png

  • pod確認

    $ kubectl get po
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-23 13.37.45.png

  • service確認

    $ kubectl get service
    

    以下のような内容が出力されたらOKです

    スクリーンショット 2023-11-23 13.38.34.png

【3-8 ブラウザでの動作確認】

  • ブラウザでAPIのポートにアクセスしましょう。

    • 現在は「localhost:31000」でアクセスできる設定にしているので、APIで設定した適当な「Hello, World!」等の文字がブラウザ上に表示されればOKです!

      スクリーンショット 2023-11-23 13.41.37.png

  • 続いてブラウザでfrontのポートにアクセスします。

    • frontは「localhost:31001」でアクセスできる設定にしているので、ブラウザ上で以下のreactの画面が表示されればOKです!

      スクリーンショット 2023-11-23 13.46.28.png

解説は以上になります、お疲れ様でした!

「kustomize」というKubernetesの設定を環境別に変更できるツールもあるのでぜひ試してみてください!

8
3
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
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?