[lv4] ft_services(3/6) phpmyadmin + mysql連携

<- 前(2/6) port5000指定でphpmyadminアクセス
-> 次(4/6) wordpress

1. metallb+nginx
2. basecamp作る
3. phpmyadmin作る
4. nginxからphpmyadminにリバースプロキシ
5. mysqlのDB作成
6. pypmyadminとmysqlの連携

7. wordpress立ち上げ
8. nginxからwordpressにリダイレクト

3. phpmyadminの実装
Q. ゴールは?
A1. 次の2パターンでアクセスができること
1. https://192.168.10.10:5000/ ポートで直接アクセス
2. https://192.168.10.10/phpmyadmin リバースプロキシを利用してアクセス

A2. ログインできること

A1. 2を目指します。
/srcs/nginx/default.conf

server {
        ...
----------------------追記----------------------
		location /phpmyadmin/ {
			rewrite ^/phpmyadmin(.*)$ $1 break;
			#          https://$host:5000/; と大違い。rewriteてphpmyadminを消しているので/なし。https://cobapen.com/doc/server/nginx_proxy_pass.html
			proxy_pass https://$host:5000;
			# 404になる。proxy_passのあと判定走っているかも
			proxy_redirect / /phpmyadmin/;
-----------------------------------------------
		}
}

Q. location /phpmyadmin/ ?
A. pathが一致すればこの処理に入ります。全部読むとルールわかるかも。
nginx連載3回目: nginxの設定、その1
nginx連載4回目: nginxの設定、その2 - バーチャルサーバの設定
nginx連載5回目: nginxの設定、その3 - locationディレクティブ

Q. proxy_pass?
A. 指定URIにnginxがリクエストを送り、nginxがリクエスト結果を受け取る、までします。リクエスト先に行ったきりではありません。そこがリダイレクトと違います。

Q. rewriteとは?
A. $uriの書き換えを行っています。

Q. $uri?
A. ドメイン以下の/から始まる部分が、$uriに入っています。(※nginxでの定義) Nginxのproxy_passを書くときの注意点
そもそも、この処理が必要な理由がありまして。。
proxy_passのリクエストを飛ばした先では、変数$uriをもとに処理がされていそうです。

Q. $uri?何が入っているの?
A. https://192.168.10.10:5000 でphpmyadminにポートアクセスし、logsでphpmyadmin側の変数を確認すると
$uri=/index.phpです。
phpmyadmin側のdefault.confにて、index index.php の設定が付与されているので、$uri=/で受けて、indexが付与された、と予想できます。
なので、nginx側では$uri=/で渡せばよさそうです。

https://192.168.10.10/phpmyadmin でnginx側の変数を確認すると、
$uri=/phpmyadmin/です。
これをなんとかして $uri=/ にできれば勝ちです。

Q. rewrite ^/phpmyadmin(.*)$ $1?
A. rewrite A B = AをBに置換します。^や$は、検索[正規表現]。

Q. $1?
A.
https://192.168.10.10/phpmyadmin/aaa の場合
$1=/aaa
https://192.168.10.10/phpmyadmin/ の場合
$1=/
です。locationで一致した以降のpathが入っていそうです。
このrewriteの指示で$uriを意図した形に編集できました。

Q.  proxy_redirect / /phpmyadmin/ ?
A. これがないと404エラーになった気がしますが、再現しません。不要かもしれません。

https://192.168.10.10/phpmyadmin/ にアクセス。


三三\     /三
三三三\   /三三
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 Nice boat.  ~~~
        ~~~~
   _ィ†N==ュ_  ~~~
  /互巫乢/"/L ~~
  Lェェェェェイ"/L|彡~
  「ロロロロロロロイL/|彡
 ∥ ̄ ̄ ̄7/ /彡
 ∥===/ /彡
`ミ\j_/ /彡
 ミヽ__/彡
  ミ 彡


次はログインを目指します。mysqlが立っていないため、まだログインできません。

4. mysqlのDB作成
(参考元) github: alpine-mysql

/srcs/mysql/Dockerfile

FROM basecamp

# These lines moved to the end allow us to rebuild image quickly after only these files were modified.
COPY start.sh /tmp/start.sh
COPY mariadb-server.cnf /etc/my.cnf.d

RUN chmod -R 755 /tmp

EXPOSE 3306
CMD ["/tmp/start.sh"]

Q. /etc/my.cnf.d?
A. ここにはサブ設定ファイルが置かれています。メイン設定は/etc/my.cnf。メインを直接いじるのがスマートかもしれません。
今回はサブコンフィグのmariadb-server.cnfを編集してみます。

/srcs/mysql/mariadb-server.cnf

[server]

[mysqld]
# skip-networking
port = 3306
# datadir have to be mounted
datadir = /app/mysql 

[galera]
bind-address=0.0.0.0

[embedded]

[mariadb]

[mariadb-10.5]

(参照元) MySQL データベースサーバへのリモートアクセスを有効化するには
Q. skip-networking?
A. 必ずコメントアウトします。skipさせません。初期設定では外部通信を受け付けない仕様になっているようです。

Q. datadir?
A. start.shにてデータベースを作成しますが、そのパスを設定できます。

Q. bind-address=0.0.0.0?
A. ワイルドカードのようです。どの外部ポートからでも受け付けるのが0.0.0.0
(参考) Bind Addressの意味がようやく分かった

/srcs/mysql/start.sh

#!/bin/sh

# origin
# https://github.com/wangxian/alpine-mysql/blob/master/Dockerfile
# bash commands
# https://qiita.com/wakayama-y/items/a9b7380263da77e51711

# -d = is directory?
if [ ! -d "/run/mysqld" ]; then
 mkdir -p /run/mysqld
fi

# /app/mysqlはもともと存在しない。mysql_install_db --datadir=/app/mysqlによって作成される。
# mountpath = /app/mysql とすると、空フォルダが作られてしまう。
if [ -d "/app/mysql" ]; then
 echo "[i] MySQL directory already present, skipping creation"
else
 echo "[i] MySQL data directory not found, creating initial DBs"
 
 mysql_install_db --user=root > /dev/null

 if [ "$MYSQL_ROOT_PASSWORD" = "" ]; then
   MYSQL_ROOT_PASSWORD=root
   echo "[i] MySQL root Password: $MYSQL_ROOT_PASSWORD"
 fi
# ${ENV:-"word"} === (ENV?)ENV:word
 MYSQL_DATABASE=${MYSQL_DATABASE:-"services"}
 MYSQL_USER=${MYSQL_USER:-"user42"}
 MYSQL_PASSWORD=${MYSQL_PASSWORD:-"user42"}

 # mktemp make a random name file
 # /tmp/tmp.LCOCdE
 tfile=`mktemp`
 # -f = is normal file?
 if [ ! -f "$tfile" ]; then
     return 1
 fi

 cat << EOF > $tfile
USE mysql;
FLUSH PRIVILEGES;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY "$MYSQL_ROOT_PASSWORD" WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
ALTER USER 'root'@'localhost' IDENTIFIED BY '';
EOF

 if [ "$MYSQL_DATABASE" != "" ]; then
   echo "[i] Creating database: $MYSQL_DATABASE"
   # COLLATE = set sort database rule
   echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` CHARACTER SET utf8 COLLATE utf8_general_ci;" >> $tfile

   if [ "$MYSQL_USER" != "" ]; then
     echo "[i] Creating user: $MYSQL_USER with password $MYSQL_PASSWORD"
     # %:wildcatd host
     echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* to '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';" >> $tfile
   fi
 fi

# verbose=0: logを出さない
 /usr/bin/mysqld --user=root --bootstrap --verbose=0 < $tfile
 rm -f $tfile
fi
# console: (Windows のみ。)このオプションが使用されている場合、エラーログメッセージを stderr に書き込み、stdout. mysqld はコンソールウィンドウを閉じません。
# exec 外部プロセスで実行。 pkillしても残ってしまう
/usr/bin/mysqld --user=root

# mysqldは動き続けるので、tail -fいらない

​Q.  mysql_install_db --user=root > /dev/null?
A. データベースを作成する大事な行です。データベースがない場合(初回起動だけ)のみ実行したいですが。その判定を
if [ -d "/app/mysql" ]; then
すなわち、/app/mysqlが存在するかで判定します。(datadirで指定しているpath)
永続ボリュームのpath指定と絡んできます。

5. pypmyadminとmysqlの連携
/srcs/mysql/mysql.yaml
(参考) 単一レプリカのステートフルアプリケーションを実行する

# https://kubernetes.io/ja/docs/tasks/run-application/run-single-instance-stateful-application/
apiVersion: apps/v1
kind: Deployment
metadata:
 name: mysql
spec:
-------------------追加------------------
  replicas: 1
-----------------------------------------
  selector:
   matchLabels:
     app: mysql
 strategy:
   type: Recreate
 template:
   metadata:
     labels:
       app: mysql
   spec:
     containers:
     - image: mymysql
       imagePullPolicy: Never
       name: mysql
       env:
         # Use secret in real usage
       - name: MYSQL_ROOT_PASSWORD
----------------------変更----------------------
         value: root
------------------------------------------------
       ports:
       - containerPort: 3306
         name: mysql
       volumeMounts:
       - name: mysql-persistent-storage
----------------------変更----------------------
         mountPath: /app
------------------------------------------------
     volumes:
     - name: mysql-persistent-storage
       persistentVolumeClaim:
         claimName: mysql-pv-claim

---
apiVersion: v1
kind: Service
metadata:
----------------------変更----------------------
 name: mysql # wp-config.phpの名前解決で使われる
-----------------------------------------------
spec:
 ports:
 - port: 3306
 selector:
   app: mysql
 clusterIP: None

Q.  mountPath?
A. 永続ボリュームの設定です。
ポッドは使い捨てなので、削除される前提で扱います。消えたら困るようなデータは、ポッド外のストレージに保存します。
mountPathを設定することで、ポッド外のストレージにつながる空ファイルが、ポッド内に作られます。
mysqlのdatadir = /app/mysqlに指定しているので、
mountPath = /appとすれば、/app以下のフォルダは、ポッドが死んでも残ります。再度ポッドを立ち上げた際に読み込まれます。

Q. mountPathで空フォルダが作られる?
A. setup.shにて、初回DB作成の条件がフォルダの有無でした。
if [ -d "/app/mysql" ]; then
mountPath=/app/mysqlにすると、空フォルダが作られてしまうので、DB作成されない事件発生するため、/appにしてます。

Q. kind:Serviceのmetadata.name:mysql?
A. srcs/phpmyadmin/congif.inc.phpの
$cfg['Servers'][$i]['host'] = 'mysql';
とセットです。名前解決に使われます。今回は外部IP=192.168.10.10が固定で入ります。


/srcs/mysql/mysql-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
 name: mysql-pv-volume
 labels:
   type: local
spec:
 storageClassName: manual
 capacity:
   storage: 100Mi
 accessModes:
   - ReadWriteOnce
-------------変更----------------
# hostpath use only test single node. https://qiita.com/sotoiwa/items/09d2f43a35025e7be782#hostpathpersistentvolume
# minikube内の保存先かも
 hostPath:
   path: "/data"
---------------------------------

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: mysql-pv-claim
spec:
 storageClassName: manual
 accessModes:
   - ReadWriteOnce
 resources:
   requests:
     storage: 100Mi

Q. hostpath?
A. 外部ストレージの場所。どこでもいいわけではないようです。
/dataは指定できます。

※/data/mysqlフォルダが作成されます。すでに同じ名称のフォルダがあった場合の動作確認ができていないため、既存ファイルがないか要注意。

ローカルにてcd /dataを確認すると、
/data/mysqlが作成されていることを確認できます。
/data/mysql をdeleteするまで、phpmyadminのユーザ情報は残り続けます。
(参考) minikubeでmysqlを動かす


/run.sh

#!/bin/sh

# stop services
kubectl delete -f srcs/metallb/metallb-config.yaml
kubectl delete -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
kubectl delete -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
kubectl delete -f srcs/nginx/nginx.yaml
kubectl delete -f srcs/phpmyadmin/phpmyadmin.yaml
kubectl delete -f srcs/mysql/mysql.yaml
kubectl delete -f srcs/mysql/mysql-pv.yaml

# images
docker build -t basecamp srcs/basecamp/.
docker build -t mynginx srcs/nginx/.
docker build -t mypma srcs/phpmyadmin/.
docker build -t mymysql srcs/mysql/.

# metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
kubectl apply -f srcs/metallb/metallb-config.yaml

# containers
kubectl apply -f srcs/nginx/nginx.yaml
kubectl apply -f srcs/phpmyadmin/phpmyadmin.yaml
kubectl apply -f srcs/mysql/mysql-pv.yaml
kubectl apply -f srcs/mysql/mysql.yaml

sh run.sh

-> https://192.168.10.10/phpmyadmin アクセス。
-> login(user42/user42)
-> 左のダッシュボードにて、DB:servicesはある?

これで、phpmyadminとmysqlが連携されました。

-> 次(4/6) wordpress

この記事が気に入ったらサポートをしてみませんか?