はじめに
こんにちは!インフラエンジニアのnaya(@NayaTaiyo)です。前回は、Kubernetesについての基礎知識をまとめて記事にしたのですが、今回はローカルのKubernetesを利用してWordPressの立ち上げてみましたので、ブログにしたいと思います。
構築環境
OS
- Windows11
Tool
- Docker Desktop
- v4.38.0
- WSL2
- Ubuntu v24.04.2
kubectl version
- Client Version
- v1.30.5
- Kustomize Version
- v5.0.4-0.20230601165947-6ce0bf390ce3
- Server Version
- v1.30.5
Docker images
- web
- nginx:1.27.3-alpine
- app
- php:8.3-fpm-alpine
- db
- mysql:8.0.28
Namespace
- dev-techbull-k8s
Pods
- WordPressPod
- nginxコンテナ(nginx.service)
- appコンテナ(php-fpm.service)
- MySQLPod
- mysqlコンテナ(mysql.service)
※本記事では、Dockerfile を用いてカスタムイメージを作成しています。
構成図
- マシン環境図
- Kubernetes構成図
ディレクトリ階層
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
(~/Desktop/techbull.cloud/Kubernetes)$ ls -la tree docker docker ├── app │ ├── Dockerfile │ └── php │ ├── php-fpm.conf │ ├── php.ini │ └── www.conf ├── mysql │ ├── Dockerfile │ ├── my.cnf │ └── mysql.gpg └── nginx ├── Dockerfile └── conf ├── dev-k8s.techbull.cloud.conf └── nginx.conf tree k8s k8s ├── app.yml ├── ingress.yml ├── mysql.yml ├── .gitignore └── secrets.yml # ignore └── wordpress └── wp-***** # ignore |
Dockerfile
Dockerコンテナの定義ファイル
php/
phpの設定ファイル類
mysql/
phpの設定ファイル類
nginx/
nginxの設定ファイル類
app.yml
app Pod(nginx、php)を定義
ingress.yml
LBやServiceの設定を一括で定義
mysql.yml
mysql Pod(mysql)を定義
secrets.yml
Kubernetesで使用する変数や機密情報(パスワード情報など)を管理
wordpress
WordPressのソースファイル
.gitignore
ignoreの対象を指定
※secrets.yml
や、wordpress
などの大量のファイルはGitなどでバージョン管理をする際はignore設定に入れましょう。
- Kubernetes/k8s/.gitignore
1 2 |
wordpress secrets.yml |
Files
それでは、各設定ファイルを見ていきましょう。 WordPress関連の設定ファイルは省きますので、気になる方は以下のリンクをご確認ください。
Dockerfile
※ 一部イメージファイルによって使用できるコマンドが異なります。また、vimはデバッグ用として導入しております。
- Kubernetes/docker/app/Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# イメージファイルの指定とコンテナ内の作業ディレクトリの指定 FROM php:8.3-fpm-alpine ENV APP_ROOT=/var/www/app WORKDIR $APP_ROOT # タイムゾーンの設定 RUN apk --update add tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ apk del tzdata && \ # 必要パッケージのインストール apk update && \ apk upgrade && \ apk add --update --no-cache \ autoconf \ bash \ build-base \ curl-dev \ freetype-dev \ g++ \ gcc \ libjpeg-turbo-dev \ libpng-dev \ libxml2-dev \ libxslt-dev \ linux-headers \ make \ mysql-dev \ mysql-client \ tzdata \ vim \ redis \ re2c \ yaml-dev \ zlib-dev # pdo_mysql soap mysqli のインストール RUN docker-php-ext-install pdo_mysql soap mysqli # GDモジュール(画像処理機能)の設定を追加後インストール RUN docker-php-ext-configure gd \ --with-freetype=/usr/include/ \ --with-jpeg=/usr/include/ && \ NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ docker-php-ext-install -j${NPROC} gd # コンテナ内でのコマンド処理 RUN addgroup -S nginx RUN adduser -S nginx -G nginx RUN mkdir /var/run/php-fpm RUN rm -f /usr/local/etc/php-fpm.conf.default RUN rm -f /usr/local/etc/php-fpm.d/zz-docker.conf COPY docker/app/php/php-fpm.conf /usr/local/etc/php-fpm.conf COPY docker/app/php/php.ini /usr/local/etc/php/php.ini COPY docker/app/php/www.conf /usr/local/etc/php-fpm.d/www.conf RUN mkdir /var/www/dev-k8s.techbull.cloud COPY k8s/wordpress/ /var/www/dev-k8s.techbull.cloud/ # Redis 拡張をインストール RUN pecl install redis \ && docker-php-ext-enable redis # php-fpmをフォアグラウンドで実行 CMD ["/usr/local/sbin/php-fpm", "-F"] |
12~14行目:
※Linuxディストリビューションalpineとubuntu/debianではパッケージマネージャーが異なります。
alpine
:apk
ubuntu/debian
: apt
また、aptとapkでキャッシュの処理が異なります。apkの場合 --update --no-cache
でキャッシュを残さずパッケージをインストールすることが可能。aptの場合 && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
でキャッシュの削除
40~45行目:
➀GDの設定にfreetypeとjpegを追加
freetype
フォント描画機能 コードを文字として可視化してくれる。
jpeg
jpegファイルの管理、編集を可能にする。
➁NPROCに論理プロセッサ(スレッド)の個数の格納
➂エラーの場合は1を導入
➃拡張機能であるgdをスレッド分の並列処理を有効化にしてインストール
プロセスとスレッドの違いとは?超わかりやすく解説!【図解とプログラム付き】
47~56行目:
nginxユーザーを作成後、PHP-FPMの設定や実行フォルダを整えています。
あとはWordPressのファイルを /var/www/dev-k8s.techbull.cloud/ にコピーして準備完了です。
60行目:
フォアグラウンドで実行理由
コンテナはプロセス単位で動作しております。なのでPID1をフォアグラウンドで固定化するためフォアグラウンドで実行しております。※バックグラウンドでの動作だと一時的にPID1が終了するためそのタイミングでコンテナが停止してしまうため。
- Kubernetes/docker/mysql/Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# イメージファイルの指定とロケール設定 FROM mysql:8.0.28 ENV TZ=Asia/Tokyo ENV LC_ALL=ja_JP.UTF-8 # 必要パッケージのインストール RUN rm -f /etc/apt/sources.list.d/mysql.list \ && apt-get update \ && apt-get install -y --no-install-recommends \ curl \ gnupg \ ca-certificates \ && curl -fsSL https://repo.mysql.com/RPM-GPG-KEY-mysql-2023 | gpg -o /usr/share/keyrings/mysql-archive-keyring.gpg \ && apt-get update \ && apt-get install -y --no-install-recommends \ locales \ python3 \ vim \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* # コンテナ内でのコマンド処理 RUN echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen \ && locale-gen ja_JP.UTF-8 # ログファイルの作成(mysqld.log )と所有者変更、ディレクトリ作成(/var/mysql)と所有者変更 RUN touch /var/log/mysqld.log \ && chown mysql:adm /var/log/mysqld.log\ && rm -rf /etc/mysql/conf.d # my.cnfファイルのコピーをアクセス権限の変更 COPY docker/mysql/my.cnf /etc/mysql/ RUN chmod 644 /etc/mysql/my.cnf |
- Kubernetes/docker/nginx/Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# イメージファイルの指定 FROM nginx:1.27.3-alpine # タイムゾーンの設定 RUN apk --update add tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ apk del tzdata && \ rm -rf /var/cache/apk/* # 必要パッケージのインストール RUN apk update && \ apk upgrade && \ apk add --update --no-cache \ bash \ nginx \ tzdata \ vim # コンテナ内でのコマンド処理 COPY docker/nginx/conf/nginx.conf /etc/nginx/nginx.conf COPY docker/nginx/conf/dev-k8s.techbull.cloud.conf /etc/nginx/conf.d/dev-k8s.techbull.cloud.conf # 80番ポートでフォアグラウンド実行(バックグラウンドとしての実行をoffにしています) EXPOSE 80 CMD ["/usr/sbin/nginx", "-g", "daemon off;"] |
25行目:
※フォアグラウンド実行理由については「# php-fpmをフォアグラウンドで実行」と同じになります。
Kubernetes
- Kubernetes/k8s/ingress.yml ※Serviceの設定も併せて記述してます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# ingress設定(クラスタ外からクラスタ内へのアクセス設定) apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wordpress labels: app: wordpress spec: ingressClassName: nginx rules: - host: dev-k8s.techbull.cloud http: paths: - pathType: Prefix path: / backend: service: name: wordpress port: number: 80 --- # Service設定(WordPressPodへのアクセス) apiVersion: v1 kind: Service metadata: name: wordpress labels: app: wordpress spec: ports: - protocol: TCP port: 80 targetPort: 80 selector: app: wordpress --- # Service設定(MysqlPodへのアクセス) apiVersion: v1 kind: Service metadata: name: mysql labels: app: mysql spec: ports: - protocol: TCP port: 3306 selector: app: mysql clusterIP: None |
2~20行目:
ClusterIP Service(デフォルト)を使用。
- Kubernetes クラスタ内では、各 Service に対して仮想IP(ClusterIP)が割り当てられ、クライアントはこの仮想IPに通信することで、背後にある複数の Pod へアクセスできます。
40~52:
Headless Service(clusterIP: Noneで指定)を使用。
- PodへDNS RoundRobin(DNS RR)を用いた通信を行う。TTLの保持期間についても注意しましょう。
- ホスト名やIPアドレスに変更がないようにStatefulSetで使用。
※ClusterIP Serviceでは仮想IPアドレスへの通信後各Podへ負荷分散を行うのですが、Headless Serviceでは各Podに対して通信を行うイメージになります。
- Kubernetes/k8s/secrets.yml
base64でデコードしています。
1 2 3 4 5 6 7 8 9 10 |
apiVersion: v1 kind: Secret metadata: name: mysql-secret type: Opaque data: MYSQL_ROOT_PASSWORD: {デコード情報} MYSQL_DATABASE: {デコード情報} MYSQL_USER: {デコード情報} MYSQL_PASSWORD: {デコード情報} |
- Kubernetes/k8s/app.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# レプリカセット(Deployment)の設定 apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: replicas: 1 selector: matchLabels: app: wordpress template: metadata: labels: app: wordpress # initContainersでのファイル操作 spec: initContainers: - name: init image: Kubernetes/app:v1.0.0 command: - "sh" - "-c" - "cp -r /var/www/dev-k8s.techbull.cloud/* /wordpress-data/" volumeMounts: - name: documentroot mountPath: "/wordpress-data" # 各メインコンテナ(nginxコンテナ、appコンテナ)の作成 containers: - name: nginx image: Kubernetes/nginx:v1.0.0 ports: - containerPort: 80 volumeMounts: - name: php-socket mountPath: "/var/run" - name: documentroot mountPath: "/var/www/dev-k8s.techbull.cloud" - name: app image: Kubernetes/app:v1.0.0 env: - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_DATABASE - name: MYSQL_USER valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_USER - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_PASSWORD volumeMounts: - name: php-socket mountPath: "/var/run" # 空ボリュームの作成 volumes: - name: php-socket emptyDir: {} - name: documentroot emptyDir: {} |
18~28行目:
処理としては以下の通りです。
➀ initContainersと呼ばれるコンテナがメインコンテナ(ここではnginxやappコンテナのこと)作成の前に作成される。メインコンテナ作成前に行いたい処理などがある場合に用いられる。
➁ wordpress-data配下に空のdocumentrootボリュームマウント
➂ dev-k8s.techbull.cloud配下のファイルをwordpress-data配下(documentrootボリューム)にコピー これによりdocumentrootボリュームを用いて元々dev-k8s.techbull.cloud配下のファイルだったものを共有することが可能
- Kubernetes/k8s/mysql.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# 要求する永続ボリュームの設定 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi --- # レプリカセット(StatefulSet)の設定 apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql labels: app: mysql spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: terminationGracePeriodSeconds: 10 # メインコンテナ(mysqlコンテナ)の作成 containers: - name: mysql image: Kubernetes/mysql:v1.0.0 env: - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_DATABASE - name: MYSQL_USER valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_USER - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_PASSWORD - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: MYSQL_ROOT_PASSWORD ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-data mountPath: "/var/lib/mysql" # このPodが使用する永続ボリュームを定義 volumes: - name: mysql-data persistentVolumeClaim: claimName: mysql-data |
事前準備
- wp-config.phpの作成
1 2 |
$ cd Kubernetes $ cp wordpress/wp-config-sample.php wordpress/wp-config.php |
- 認証情報デコード化
以下のリンク先で発行されるコードをwp-config.phpにコピペしましょう。
https://api.wordpress.org/secret-key/1.1/salt/
1 |
$ sudo vi wordpress/wp-config.php |
1 2 3 4 5 6 7 8 |
define( 'AUTH_KEY', 'put your unique phrase here' ); define( 'SECURE_AUTH_KEY', 'put your unique phrase here' ); define( 'LOGGED_IN_KEY', 'put your unique phrase here' ); define( 'NONCE_KEY', 'put your unique phrase here' ); define( 'AUTH_SALT', 'put your unique phrase here' ); define( 'SECURE_AUTH_SALT', 'put your unique phrase here' ); define( 'LOGGED_IN_SALT', 'put your unique phrase here' ); define( 'NONCE_SALT', 'put your unique phrase here' ); |
コンテナイメージのビルド
※ 今回の構成だとホストマシンからのファイル操作が発生するのでコマンド実行のディレクトリに注意
1 2 3 |
(~/Desktop/Dev-Environments/Kubernetes)$ docker build -f docker/nginx/Dockerfile -t Kubernetes/nginx:v1.0.0 . (~/Desktop/Dev-Environments/Kubernetes)$ docker build -f docker/app/Dockerfile -t Kubernetes/app:v1.0.0 . (~/Desktop/Dev-Environments/Kubernetes)$ docker build -f docker/mysql/Dockerfile -t Kubernetes/mysql:v1.0.0 . |
ネームスペース作成+コンテキストの指定
1 2 3 |
$ kubectl config get-contexts $ kubectl config use-context docker-desktop $ kubectl create namespace dev-techbull-k8s |
Pod適用+nginxコントローラ導入
1 |
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.3/deploy/static/provider/cloud/deploy.yaml |
1 2 3 4 |
(~/Desktop/Dev-Environments/Kubernetes)$ kubectl -n dev-techbull-k8s apply -f k8s/secrets.yml (~/Desktop/Dev-Environments/Kubernetes)$ kubectl -n dev-techbull-k8s apply -f k8s/ingress.yml (~/Desktop/Dev-Environments/Kubernetes)$ kubectl -n dev-techbull-k8s apply -f k8s/app.yml (~/Desktop/Dev-Environments/Kubernetes)$ kubectl -n dev-techbull-k8s apply -f k8s/mysql.yml |
Access
http://dev-k8s.techbull.cloud/
以下の画像の通りに画面が表示されること
インストール後問題なくログインできること
おまけ
- Podの内容確認
1 |
$ kubectl describe pod {Pod名} -n {Namespace} |
- Podのログ確認
1 |
$ kubectl logs {Pod名} -n {Namespace} |
- Podの状態確認
1 |
$ kubectl -n {Namespace} get ingress,secret,service,deployment,statefulset,pod,pvc |
- Podのデバッグコマンド
1 |
$ kubectl debug {Pod名} -n {Namespace} -it --image={image} -- /bin/bash |
上記のコマンドを使用するとエフェメラルコンテナと呼ばれる一時的なコンテナを作成してエフェメラルコンテナ内に接続することが可能です。(実際の基となるメインコンテナ(本記事で言うとweb、app、dbコンテナ)を操作することは不可です。)
メインコンテナには導入されていないパッケージを導入することが可能なので本番環境などで好きなようにパッケージを導入できない場合などはこちらのコマンドを使用して調査など行うとよいと思います。イメージファイルもお好みで使用できます。
また、メインコンテナをデバッグする場合は以下のコマンドを使用します。
1 |
$ kubectl debug {Pod名} -n {Namespace} -it -- target= {container} --image={image} -- /bin/bash |
/proc/メインコンテナのPID/root
でメインコンテナ内のルートディレクトリにアクセスすることも可能なのでメインコンテナ内のデバッグをすることが可能です。
上記のコマンドは同じPod内にエフェメラルコンテナを作成するのですが、以下のコマンドを使用することで新たなデバッグ用のPodを作成することが可能です。
1 |
kubectl debug {Pod名} -n {Namespace} -it --copy-to={作成されるPod名} --image={image} -- /bin/bash |
完全に別のPodなので複製基のPodが終了をした際も影響はないです。
まとめ
Kubernetesの動作は非常に複雑で、基本を抑えるのにも時間がかかります。しかし、Kubernetesを学んでいく中で、コンテナ仮想化技術への理解が個人的には深まったと感じています。もし興味があれば、ぜひ一度試してみてください。思った以上に多くのことを学べると思います。今後はクラウドの Kubernetes にも取り組む予定なので、機会があれば記事にまとめたいです。また、今回の記事について、ありがとうございました!
参考リンク
https://kubernetes.io/ja/docs/setup/
https://www.f5.com/ja_jp/glossary/dns-round-robin
https://www.nic.ad.jp/ja/newsletter/No51/0800.html
https://www.miraiserver.ne.jp/column/about_linux-user-group/
https://kubernetes.io/ja/docs/tasks/debug/debug-application/debug-running-pod/#ephemeral-container-example
参考にした技術書
・Kubernetes完全ガイド 第2版
・Kubernetesの知識地図 —— 現場での基礎から本番運用まで

2000年生まれ。社会人2年目の駆け出しエンジニア。SESにてインフラエンジニアとして従事。この先、設計や構築の案件に関われるようなエンジニアになりたいという思いからTechBullに加入し、日々勉強中。主に駆け出しエンジニアに向けて、手助けになるような記事を執筆中。