8
0

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】GKE StandardでLAMP環境を構築してみた

Posted at

はじめに

こんにちは!

本記事は「本気で学ぶKubernetes」シリーズの第20回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。

このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!

Kubernetesとは?クラスタ構成の全体像をつかむ

今回はもう少し複雑な構成を想定して、レガシーなLAMPスタックのシステムをKubernetesにリフトしてみたいと思います。

この記事は人間がKubernetesの公式ドキュメントを読み漁りながら書いていますのでご安心ください!

TL;DR

忙しい方のために要点だけ図示しておきます!

gke-day20-tldr.png

GKEへのリフト計画について

多くの企業でまだオンプレミスのレガシーなLAMP構成やVMで稼動するシステム、Kubernetesクラスタを運用しているシステムなどがあります。
運用負荷軽減やシステム拡張性を求めてクラウド環境に移行する場合、GKE Standardも1つの選択肢ですね。

GKE Standardは既存のk8sのマニフェストを活用することでほぼそのまま動作させることができますし、ノードの種類も細かく指定できオンプレKubernetesと同じ感覚で扱えるうえ、クラウドネイティブな構成にシフトさせていくことも可能です。

概要

全体としては以下の順番で進めていきたいと思います。

  1. minikubeでLAMP構成を構築
  2. GKE Standardクラスタを作成
  3. kubectxでクラスタを切り替え
  4. minikubeで使ったマニフェストをGKEにそのまま適用
  5. 同じように動作することを確認

kubectx/kubensのインストール

まずクラスタとnamespace切り替えを便利にするkubectxkubensをインストールします。

実際の運用では、複数のKubernetesクラスタを使い分けたり、defaultnamespaceではなくアプリケーションごとにnamespaceを分けるのが一般的です。

今回もminikubeGKEの2つのクラスタを扱いますが、これらの効率よく使い分けられるツールがありますので活用していきたいと思います。

# kubectx/kubensをインストール
brew install kubectx

インストールが完了すると、kubectxkubensコマンドが使えるようになります。

minikubeクラスタのセットアップ

ローカル環境でminikubeクラスタを起動します。

# minikubeクラスタを起動
minikube start

# クラスタ情報を確認
kubectl cluster-info

# Kubernetes control plane is running at https://127.0.0.1:xxxxx
# CoreDNS is running at https://127.0.0.1:xxxxx/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

minikubeクラスタが無事に起動しましたので、先ほどインストールしたkubectxでクラスタを確認してみます。

kubectx

# minikube

現在はminikubeクラスタだけが表示されていることがわかりました。

namespaceの作成と切り替え

lamp-appというnamespaceを作成して、kubensで切り替えます。

# namespaceを作成
kubectl create namespace lamp-app

# namespace/lamp-app created

# namespaceを切り替え
kubens lamp-app

# Context "minikube" modified.
# Active namespace is "lamp-app".

# 現在のnamespaceを確認
kubens

# default
# kube-node-lease
# kube-public
# kube-system
# lamp-app(太字で表示される)

これ以降のkubectlコマンドは全てlamp-appnamespace内で実行されるようになります

MySQLのデプロイ

Secretの作成

MySQLのrootパスワードをSecretに格納します。
SecretはAPIキーやDBの接続情報など機密情報を保存するためのサービスでしたね。

以前の記事でも触れているので、忘れた方はぜひご確認ください!

【本気で学ぶKubernetes】SecretとVolumeで機密情報とデータを扱う

# MySQLのrootパスワードを格納
kubectl create secret generic mysql-secret \
  --from-literal=password=mypassword123

# secret/mysql-secret created

StatefulSetマニフェストの作成

StatefulSetはデータベースやキューなどの状態を保持する必要があるサービスを動作させる際にKubernetesで利用される機能です。

こちらも以前の記事で触れていますので併せてご確認ください!

【本気で学ぶKubernetes】StatefulSet入門 - Deploymentとの違いを理解する

mysql-statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  clusterIP: None  # Headless Service
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        - name: MYSQL_DATABASE
          value: testdb
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

過去の記事でも触れたようにvolumeClaimTemplatesを作成することによりPodごとにPersistentVolumeClaimを自動作成することができます。

マニフェストを適用してみます。

kubectl apply -f mysql-statefulset.yaml

# service/mysql created
# statefulset.apps/mysql created

StatefulSetとPodが作成されていることを確認しておきます。

kubectl get statefulset

# NAME    READY   AGE
# mysql   1/1     30s

kubectl get pods -l app=mysql

# NAME      READY   STATUS    RESTARTS   AGE
# mysql-0   1/1     Running   0          40s

WordPressのデプロイ

次にアプリケーション部分のWordPressをデプロイします。
WordPressは言わずもがなMySQLに接続して動作する代表的なPHPアプリケーションです。

以下のマニフェストを作成して適用します。

wordpress-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 2
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress:latest
        ports:
        - containerPort: 80
        env:
        - name: WORDPRESS_DB_HOST
          value: mysql
        - name: WORDPRESS_DB_NAME
          value: testdb
        - name: WORDPRESS_DB_USER
          value: root
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: LoadBalancer
  selector:
    app: wordpress
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

上記では環境変数でMySQLの接続情報を渡すようになっています。
マニフェストを適用します。

kubectl apply -f wordpress-deployment.yaml

# deployment.apps/wordpress created
# service/wordpress created

DeploymentとServiceの状態を確認してみます。

kubectl get deployment

# NAME        READY   UP-TO-DATE   AVAILABLE   AGE
# wordpress   2/2     2            2           1m

kubectl get pods -l app=wordpress

# NAME                         READY   STATUS    RESTARTS   AGE
# wordpress-xxxxxxxxxx-aaaaa   1/1     Running   0          1m
# wordpress-xxxxxxxxxx-bbbbb   1/1     Running   0          1m

kubectl get service wordpress

# NAME        TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# wordpress   LoadBalancer   10.xxx.xx.xx    <pending>     80:xxxxx/TCP   1m

minikubeでの動作確認

minikubeでLoadBalancer Serviceにアクセスする方法としてminikube tunnelもありますが、今回はminikube serviceコマンドを使って確認していきます。

# minikube serviceでアクセス用のURLを取得
minikube service wordpress -n lamp-app --url

# http://127.0.0.1:xxxxx

このコマンドは、LoadBalancer Serviceに対してポートフォワーディングを自動的に設定し、アクセス可能なURLを表示してくれます。

表示されたURLにブラウザでアクセスしてみます。

スクリーンショット 2025-12-21 18.38.28.png

Worpressの初期画面が表示されました!

GKE Standardクラスタの作成

ここからはminikubeで動作確認できたマニフェストを、そのままGKE Standardにも適用してみます。

まず、GKE APIを有効化します。

# GKE APIを有効化
gcloud services enable container.googleapis.com

次に、GKE Standardクラスタを作成します。

# Standardクラスタを作成(東京ゾーン)
gcloud container clusters create lamp-cluster \
  --zone=asia-northeast1-a \
  --machine-type=e2-medium \
  --num-nodes=2 \
  --disk-size=20

GKE Standardではcreateコマンドを使い、--machine-type--num-nodesを明示的に指定する必要があります。
今回はe2-mediumインスタンスを2台用意しました。

クラスタが作成されたら、kubectlでGKEに接続できるようにkubeconfigを取得します。(クラスタの作成には5〜10分ほどかかります)

# kubeconfigを取得
gcloud container clusters get-credentials lamp-cluster \
  --zone=asia-northeast1-a

# Fetching cluster endpoint and auth data.
# kubeconfig entry generated for lamp-cluster.

kubectxでクラスタを切り替え

kubectxを使ってクラスタを確認してみます。

# クラスタ一覧を確認
kubectx

# gke_PROJECT-ID_asia-northeast1-a_lamp-cluster
# minikube

minikubeとGKE両方のクラスタが表示されました!

現在のクラスタはGKEになっているはずですが、念の為確認してみます。

# 現在のクラスタを確認
kubectl config current-context

# gke_PROJECT-ID_asia-northeast1-a_lamp-cluster

# ノードを確認
kubectl get nodes

# NAME                                          STATUS   ROLES    AGE   VERSION
# gke-lamp-cluster-default-pool-xxxxx-xxxx      Ready    <none>   2m    v1.28.x-gke.xxx
# gke-lamp-cluster-default-pool-xxxxx-yyyy      Ready    <none>   2m    v1.28.x-gke.xxx

GKEクラスタに接続できていることが確認できました。

GKEコンソールでもクラスタの詳細を確認できます。Standardモードで作成されており、ノード数や構成が確認できます。

スクリーンショット 2025-12-21 18.40.15.png

GKEにnamespaceを作成

GKEにも同じようにnamespaceを作成します。

# namespaceを作成
kubectl create namespace lamp-app

# namespace/lamp-app created

# namespaceを切り替え
kubens lamp-app

# Context "gke_PROJECT-ID_asia-northeast1-a_lamp-cluster" modified.
# Active namespace is "lamp-app".

GKEに同じマニフェストを適用

minikubeで使ったマニフェストをGKEにそのまま適用していきます。

Secretの作成

kubectl create secret generic mysql-secret \
  --from-literal=password=mypassword123

# secret/mysql-secret created

マニフェストの適用

# MySQL StatefulSetを適用
kubectl apply -f mysql-statefulset.yaml

# service/mysql created
# statefulset.apps/mysql created

# WordPress Deploymentを適用
kubectl apply -f wordpress-deployment.yaml

# deployment.apps/wordpress created
# service/wordpress created

minikubeで使ったマニフェストを何も変更せずそのまま適用しただけです!

リソースの確認

GKEコンソールで確認してみます。Workloadsの画面では、WordPressのDeploymentとMySQLのStatefulSetが正常に稼働していることが確認できます。

スクリーンショット 2025-12-21 18.39.26.png

ConfigMapsとSecretsの画面では、作成したmysql-secretが確認できます。

スクリーンショット 2025-12-21 18.41.01.png

LoadBalancer Serviceの確認

外部公開用のロードバランサーが作成されているので、コマンドで確認します。

kubectl get service wordpress

# NAME        TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
# wordpress   LoadBalancer   34.118.xxx.xx   <pending>        80:xxxxx/TCP   1m

kubectl get service wordpress -w

# NAME        TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
# wordpress   LoadBalancer   34.118.xxx.xx   34.xxx.xxx.xxx   80:xxxxx/TCP   2m

外部IPが割り当てられていることが確認できました。

GKEコンソールのServicesの画面でも、wordpress ServiceがExternal Load Balancerとして作成され、外部IPが割り当てられていることが確認できます。

!スクリーンショット 2025-12-21 18.41.38.png

GKEでの動作確認

それでは、GKEでも同じように動作するか確認してみます。

# EXTERNAL-IPを環境変数に格納
EXTERNAL_IP=$(kubectl get service wordpress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "http://$EXTERNAL_IP"

# http://34.xxx.xxx.xxx

ブラウザでhttp://34.xxx.xxx.xxxにアクセスすると、WordPressのセットアップ画面が表示されます!

スクリーンショット 2025-12-21 18.38.28.png

GKEでも同じように動作することが確認できました!

今回はデータを用意していないので構成をそのまま移行しただけですが、実際はデータ移行やオンプレ特有の設定情報などがあるかと思いますので各自設定調整してください。

クリーンアップ

GKEのクリーンアップ

# GKEに切り替え
kubectx gke_PROJECT-ID_asia-northeast1-a_lamp-cluster

namespaceを使っている場合はnamespace自体を削除すれば中のリソースも全て削除されます。
LoadBalancer Serviceは外部のGoogle Cloud Load Balancerを作成するため、念の為先に個別削除しておきます。

# LoadBalancer Serviceを先に削除(外部リソース解放のため)
kubectl delete service wordpress

# service "wordpress" deleted from lamp-app namespace

# namespaceごと削除
kubectl delete namespace lamp-app

# namespace "lamp-app" deleted

クラスタ自体を削除します。

gcloud container clusters delete lamp-cluster \
  --zone=asia-northeast1-a

# The following clusters will be deleted.
#  - [lamp-cluster] in [asia-northeast1-a]

# Do you want to continue (Y/n)?  Y

# Deleting cluster lamp-cluster...done.
# Deleted [https://container.googleapis.com/v1/projects/<project>/zones/asia-northeast1-a/clusters/lamp-cluster].

削除忘れのためコンソールでも確認しておいてください!

minikubeのクリーンアップ

minikubeクラスタをクリーンアップしておきます

# minikubeに切り替え
kubectx minikube

# namespaceごと削除
kubectl delete namespace lamp-app

# namespace "lamp-app" deleted

まとめと次回予告

minikubeとGKE StandardでLAMP構成(MySQL + Apache + PHP)を構築してみました。

minikube上で作成した際と全く同じマニフェストをそのまま適用して、両方の環境で同じように動作することを確認できました。

今回はクラスタやnamespaceの切り替えが行えるkubectxとkubensをツールを使いましたが、これは実際のKubernetesの運用でもほぼほぼ必須のツールになってくると思いますのでぜひ押さえておきたいですね!

次回は、Kubernetesのトラブルシューティングについて学んでいきます。kubectl logskubectl describekubectl eventsを使ったデバッグ方法や、よくあるエラーパターンと対処法を実践していければと思います!

それでは、また次回!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?