GKE上にWordpress環境作ってみる【vol.3 ConfigMapとSecretに環境変数書いてみる！編】

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回はWordpress＋MySQL環境をGKE上に構築するにあたり、ConfigMapだけではなくSecretをも用いてみたいと思います。

今までの記事は以下を参照ください。

https://qiita.com/ohtsuka-shota/items/48545c2b34bb251aa0e7

https://qiita.com/ohtsuka-shota/items/f4796366cfa966b33f4c

# 構築する環境

以下が今までに構築した環境です。
ConfigMapを用いて、環境変数をpodに設定しておりました。

![名称未設定ファイル-ページ23のコピー drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/da143a8e-c0b2-43f6-af22-5e06ed58a7b5)

今回はConfigMapだけではなくSecretも使用しpodに環境変数をアタッチしていきたいと思います。ConfigMapを使用すると環境変数をpodやdeployment等から分離して扱うことが出来、柔軟性が向上するのですが、暗号化しないでそのままのデータとして管理されるためセキュリティの面で不安が残ります。Secretはbase64でエンコードされたデータを扱うのでセキュリティの面をある程度払拭することが出来ます。（個人的には気休め位だと思いますが。。。）

![名称未設定ファイル-ページ23のコピーのコピー drawio](https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/d0e90db4-8ad3-4133-82ea-aae0d1f9c542)

# 用意したファイル一覧

#### wordpress-pod.yaml
前回とほぼ差分は無いですが、spec.containers.envFromの配下にsecretRef欄を追加しています。
この欄でこのpodが使用するSecretを指定しています。ConfigMapとの併用も可能です。
```wordpress-configmap.yaml
apiVersion: v1  
kind: Pod  
metadata:  
  name: wordpress-pod  
  labels:  
    app: wordpress 
spec:  
  containers:  
    - name:  wordpress-con  
      image: wordpress:php8.1-apache  
      ports:  
      - containerPort : 80  
      envFrom: 
      - configMapRef: 
          name: wp-cm 
      - secretRef: 
          name: wp-sec
```

#### wordpress-configmap.yaml
```wordpress-configmap.yaml
apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: wp-cm 
data: 
  WORDPRESS_DB_HOST: mysql-clusterip 
  WORDPRESS_DB_NAME : gke-wordpress-database 
  WORDPRESS_DB_USER : devuser
```

#### wordpress-secret.yaml
今回の主テーマとなるSecretファイルです。
"cGFzc3dvcmQK"という文字列は"password"という文字列をbase64でエンコードしたものになります。この辺りは後程。書きっぷりはConfigMapと同じです。
```wordpress-secret.yaml
apiVersion: v1 
kind: Secret 
metadata: 
  name: wp-sec 
data: 
  WORDPRESS_DB_PASSWORD : cGFzc3dvcmQK
```

#### wordpress-loadbalancer.yaml
```wordpress-loadbalancer.yaml
apiVersion: v1  
kind: Service  
metadata:  
  name: wordpress-loadbalancer  
spec:  
  type: LoadBalancer  
  selector:  
    app: wordpress 
  ports:  
  - protocol: TCP  
    port: 60000 
    targetPort: 80
```

#### mysql-pod.yaml
これもwordpress-pod.yamlと同じです。
spec.containers.envFromの配下にsecretRef欄を追加しています。
この欄でこのpodが使用するSecretを指定しています。
```mysql-pod.yaml
apiVersion: v1   
kind: Pod   
metadata: 
  name: mysql-pod 
  labels: 
    app: mysql    
spec:   
  containers:   
    - name:  mysql-con    
      image: mysql:8.0-debian 
      ports:    
      - containerPort: 3306 
      envFrom:  
      - configMapRef:  
          name: mysql-cm 
      - secretRef:  
          name: mysql-sec
```

#### mysql-configmap.yaml
```mysql-configmap.yaml
apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: mysql-cm 
data: 
  MYSQL_DATABASE : gke-wordpress-database 
  MYSQL_USER : devuser 
  MYSQL_ROOT_PASSWORD : password
```

#### mysql-secret.yaml
```mysql-secret.yaml
apiVersion: v1 
kind: Secret 
metadata: 
  name: mysql-sec 
data: 
  MYSQL_PASSWORD : cGFzc3dvcmQK
```

#### mysql-clusterip.yaml
```mysql-clusterip.yaml
apiVersion: v1   
kind: Service   
metadata:   
  name: mysql-clusterip  
spec:   
  selector:   
    app: mysql   
  type: ClusterIP   
  ports:   
  - name: mysql   
    port: 3306   
    protocol: TCP   
    targetPort: 3306
```

# 構築

コマンドのログは残しておりませんが、それぞれのyamlファイルを"kubectl apply -f (yaml)"でデプロイします。
私の環境下では、デプロイ結果は以下となりました。
```
$ kubectl get pod,svc,cm,secret -o wide 
NAME                READY   STATUS    RESTARTS   AGE     IP             NODE                          NOMINATED NODE   READINESS GATES 
pod/mysql-pod       1/1     Running   0          3m23s   10.112.0.130   gk3-my-pool-1-8d22bf08-r8mk   <none>           <none> 
pod/wordpress-pod   1/1     Running   0          3m8s    10.112.0.131   gk3-my-pool-1-8d22bf08-r8mk   <none>           <none> 

NAME                             TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)           AGE     SELECTOR 
service/kubernetes               ClusterIP      10.112.128.1     <none>           443/TCP           9m56s   <none> 
service/mysql-clusterip          ClusterIP      10.112.130.3     <none>           3306/TCP          3m18s   app=mysql 
service/wordpress-loadbalancer   LoadBalancer   10.112.128.108   34.170.136.140   60000:32700/TCP   2m49s   app=wordpress 

NAME                         DATA   AGE 
configmap/kube-root-ca.crt   1      9m7s 
configmap/mysql-cm           3      3m29s 
configmap/wp-cm              3      2m56s 

NAME               TYPE     DATA   AGE 
secret/mysql-sec   Opaque   1      3m43s 
secret/wp-sec      Opaque   1      3m1s
```

LoadBalancerにアタッチされるEXTERNAL-IPとポート番号を指定してWebブラウザでアクセスしてみます。
結果として以下の通り、問題無くアクセス出来ました。

<img width="1128" alt="2023052101" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/63cda809-7392-4282-9bd5-e4bf371af405">

<img width="1128" alt="2023052102" src="https://github.com/ohtsuka-shota/ascii0-python-encrypt-decrypt/assets/127835743/bb8c0c0b-8551-4309-80a0-e35def49b175">

# 余談

Secretファイルにbase64でエンコードしたデータを格納しましたが、エンコードの仕方ですが以下の様にコマンドを実行すればOKです。echoコマンドの引数にbase64でエンコードしたい文字列を入力して、それをbase64にパイプで引き渡します。出力されたデータをSecretのyamlファイルに入力します。
```
$ echo password | base64 
cGFzc3dvcmQK
```

base64でエンコードしていない文字列をSecretのyamlに入力し、そのyamlを元に出プ下ろい仕様とすると以下の様なエラーを吐きます。
```
$ kubectl apply -f wordpress-secret.yaml  
Error from server (BadRequest): error when creating "wordpress-secret.yaml": Secret in version "v1" cannot be handled as a Secret: illegal base64 data at input byte 4 
$ kubectl apply -f mysql-secret.yaml  
Error from server (BadRequest): error when creating "mysql-secret.yaml": Secret in version "v1" cannot be handled as a Secret: illegal base64 data at input byte 4
```

secretをdescribeすることも出来ます。
ConfigMapだと内部のデータを閲覧することが出来ましたが、Secretだとdescribeをしても中身を確認することは出来ません。
```
$ kubectl describe secret wordpress-secret  
Name:         wordpress-secret 
Namespace:    default 
Labels:       <none> 
Annotations:  <none> 
Type:  Opaque 
Data 
==== 
WORDPRESS_DB_PASSWORD:  9 bytes 
```

また、Secretに環境変数を設定しまうことでpodが上手く作成されない事例が確認出来ました。
今回の私の場合、MySQLのpodの環境変数MYSQL_ROOT_PASSWORDの値をSecretで扱うとpodがrunningになったりcrashしたりerrorになったりしました。
もし、上手くpodがデプロイ出来なくなったりしましたら、Secretを疑ってみても良いかもと思いました。