🗂

minikubeでマルチサービスを立ち上げる(2)

2021/04/04に公開

(前回)[https://zenn.dev/tkomatsu/articles/bbb3a4e5f63aae869a74]はnginxのサービスの立ち上げを行いました。
今回はphpMyAdmin, mariaDBを立ち上げます。

ソースコードはこちらです。
https://github.com/tkomatsu/mini_services

mariaDBを立ち上げる

phpMyAdminで使用するため、ノード内で共有するデータベースを構築します。
また、データベースのため、Podが異常終了するような場合でもデータが永続化されるようにしていきます。

Deploymentではなく、StatefulSetを用いることにします。

以下の2つのyamlファイルを作成します。

mariadb-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mariadb
spec:
  selector:
    matchLabels:
      app: mariadb
  serviceName: "mariadb"
  replicas: 1
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      containers:
      - name: mariadb
        image: mariadb:latest
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: rootpass
        - name: MYSQL_DATABASE
          value: wordpress
        - name: MYSQL_USER
          value: wp_user
        - name: MYSQL_PASSWORD
          value: password
        volumeMounts:
        - name: mariadb-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mariadb-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi
mariadb-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mariadb
spec:
  clusterIP: None
  selector:
    app: mariadb
  ports:
  - name: mariadb
    port: 3306

StatefulSetのマニフェストは基本的にはDeploymentと共通する項目が多いです。
spec.serviceNameにはStatefulSetと紐付けるServiceの名前を記載します。
spec.volumeClaimTemplates[]を指定することで、PersistentVolumeを使い安定したストレージを使えるようになります。

mariaDBは(公式イメージ)[https://hub.docker.com/_/mariadb]をそのまま使用しています。
環境変数を利用して、データベースの名前やユーザー名、パスワードなどを指定することができます。
マニフェストで指定するにはspec.template.spec.containers[].env[]namevalueを記載します。

Serviceではspec.clusterIPNoneに指定しています。
Noneにすることでヘッドレスサービスとして起動するようになります。

$ kubectl apply -f mariadb/
service/mariadb created
statefulset.apps/mariadb created
$ kubectl get all
NAME                        READY   STATUS    RESTARTS   AGE
pod/mariadb-0               1/1     Running   0          2m32s
pod/nginx-c7d66576c-8kq2b   1/1     Running   0          3m7s

NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
service/kubernetes   ClusterIP      10.96.0.1       <none>          443/TCP                      3m38s
service/mariadb      ClusterIP      None            <none>          3306/TCP                     2m32s
service/nginx        LoadBalancer   10.96.224.211   192.168.49.50   80:30888/TCP,443:32666/TCP   3m7s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           3m7s

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-c7d66576c   1         1         1       3m7s

NAME                       READY   AGE
statefulset.apps/mariadb   1/1     2m32s

うまく立ち上がっているかコマンドを実行して確認します。

$ kubectl run mysql-client --image=mysql:5.7 -it --rm --restart=Never --  mysql -h mariadb-0.mariadb -u wp_user -ppassword
If you don't see a command prompt, try pressing enter.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| wordpress          |
+--------------------+
2 rows in set (0.00 sec)

mysql>

$MYSQL_USER$MYSQL_PASSWORDでmysqlを実行し、データベースが作成されていることを確認します。

phpMyAdminをたちあげる

mariaDBサーバーにアクセスできるphpMyAdminを立ち上げていきます。

phpmyadmin-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: phpmyadmin
  labels:
    app: phpmyadmin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: phpmyadmin
  template:
    metadata:
      name: phpmyadmin
    spec:
      containers:
      - name: phpmyadmin
        image: phpmyadmin:latest
        ports:
        - containerPort: 5000
        env:
          - name: PMA_USER
            value: wp_user
          - name: PMA_PASSWORD
            value: password
          - name: PMA_HOST
            value: mariadb-0.mariadb

このままでも問題ないのですが、mariaDBで設定したユーザー名とパスワードが再び登場しています。
複数のマニフェストにまたがる設定をまとめるためにConfigMapが使用できます。
MetalLBの時にも使用していますね。
ただ、ConfigMapだとパスワードなどのセンシティブなものが平打ちされてしまうので、ここではSecretというものを使用します。

Secretの作成方法はいくつかあるのですが、今回はyamlファイルで作成することにします。

mini-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mini-secret
type: Opaque
stringData:
  mysql_root_password: rootpass
  db_name: wordpress
  db_user: wp_user
  db_password: password

yamlファイルで作る場合は、エンコード済のものを記載する方法(data)とエンコードなしの文字列を記載する方法(stringData)があり、今回は内容を確認しやすいよう後者を採用しました。
dataを使う場合は、Base64でエンコードしたものを記載してください。

secretを作成したので、mariaDBとphpMyAdminのyamlファイルを以下のように書き換えます。

mariadb-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mariadb
spec:
  serviceName: "mariadb"
  selector:
    matchLabels:
      app: mariadb
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      containers:
      - name: mariadb
        image: mariadb:latest
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mini-secret
              key: mysql_root_passowrd
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: mini-secret
              key: db_name
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mini-secret
              key: db_user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mini-secret
              key: db_password
        volumeMounts:
        - name: mariadb-data
          mountPath: /var/lib/mysql
  replicas: 1
  volumeClaimTemplates:
  - metadata:
      name: mariadb-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi
phpmyadmin-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: phpmyadmin
  labels:
    app: phpmyadmin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: phpmyadmin
  template:
    metadata:
      labels:
        app: phpmyadmin
    spec:
      containers:
      - name: phpmyadmin
        image: phpmyadmin
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        env:
        - name: PMA_USER
          valueFrom:
            secretKeyRef:
              name: mini-secret
              key: db_user
        - name: PMA_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mini-secret
              key: db_password
        - name: PMA_HOST
          value: mariadb-0.mariadb

phpMyAdminのServiceも併せて立ち上げましょう。

phpmyadmin-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: phpmyadmin
spec:
  selector:
    app: phpmyadmin
  type: ClusterIP
  ports:
  - name: http
    port: 80
  - name: https
    port: 443

これまで作成したマニフェストをKubernetesに反映させていきましょう。

kubectl apply -f <manifest file>

正しく設定できていれば、下記のようになっているはずです。

$ kubectl get all
NAME                              READY   STATUS    RESTARTS   AGE
pod/mariadb-0                     1/1     Running   0          7m26s
pod/nginx-c7d66576c-sbml5         1/1     Running   1          7m27s
pod/phpmyadmin-797f98c4b6-vfds2   1/1     Running   0          7m25s

NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
service/kubernetes   ClusterIP      10.96.0.1       <none>          443/TCP                      7m53s
service/mariadb      ClusterIP      None            <none>          3306/TCP                     7m25s
service/nginx        LoadBalancer   10.105.38.183   192.168.49.50   80:31869/TCP,443:30009/TCP   7m26s
service/phpmyadmin   ClusterIP      10.105.200.23   <none>          80/TCP,443/TCP               7m25s

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx        1/1     1            1           7m27s
deployment.apps/phpmyadmin   1/1     1            1           7m25s

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-c7d66576c         1         1         1       7m27s
replicaset.apps/phpmyadmin-797f98c4b6   1         1         1       7m25s

NAME                       READY   AGE
statefulset.apps/mariadb   1/1     7m26s

このままではphpMyAdminに外部からアクセスできないので、nginxからリバースプロキシで接続するように設定します。

nginx.conf
server {
	listen 80;
	listen [::]:80;

	server_name	_;

	return 301 https://$host$request_uri;
}

server {
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;

	server_name _;

	ssl_certificate /etc/nginx/ssl/server.crt;
	ssl_certificate_key /etc/nginx/ssl/server.key;

	root /usr/share/nginx/html;

	index index.html;

	location /phpmyadmin/ {
		rewrite ^/phpmyadmin(.*)$ $1  break;
		proxy_redirect / /phpmyadmin/;
		proxy_pass http://phpmyadmin:80;
	}

	location / {
		try_files $uri $uri/ =404;
	}
}

再度、コンテナをビルドして反映させてください。

以上でphpMyAdminの立ち上げが完了しました。
ブラウザで確認してみましょう。

browser

終わりに

今回は以下のオブジェクトの実装を行いました。より詳しく知りたい場合は公式APIリファレンスを参照してください。

  • StatefulSet
  • Secret

さらに複数のService間接続を確認し、Serviceオブジェクトの有効性を確認しました。
次回はWordpressの実装を行っていきます。

Discussion