minikubeでWordPress環境を構築
こちらKubernetes ハンズオンをやりました。 適宜コマンドや説明を修正、補足した作業メモです。
ゴール
VirtualBox環境の1VM上にk8s環境をつくりwordpressを構築していきます。
事前知識
Pod
Podはk8sでアプリケーションを動かす最小単位のリソースです。 同じプロセス空間、ネットワーク、ストレージを共有する1つ以上のコンテナから構成されます。 Podは必ずNode上で実行されます。
Node
Nodeはk8sのワーカーマシンで、仮想マシンか物理マシンです。 今回はvirtualbox上にminikubeというNodeが作られることを確認できます。
k8s環境の準備
minikubeとkubectlをMacにインストールします
brew cask install minikube
brew install kubectl
minikubeでローカルにk8s環境作成
minikube start
でk8sv1.10.0のシングルクラスタが作成できました。
minikube start Starting local Kubernetes v1.10.0 cluster... Starting VM... Getting VM IP address... Moving files into cluster... Setting up certs... Connecting to cluster... Setting up kubeconfig... Starting cluster components... Kubectl is now configured to use the cluster. Loading cached images from config file.
minikube status
で minikube
と cluster
がRunningになっていることを確認
minikube status minikube: Running cluster: Running kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.102
冒頭でもいいましたが、Nodeとしてminikubeが確認できます。
kubectl get nodes NAME STATUS ROLES AGE VERSION minikube Ready master 24s v1.10.0
k8s上にWordpressを構築
k8s上にwordpressとmysqlのコンテナを立ち上げていきます。 DockerStoreにあるものを使っていきます。
DBのパスワードの秘密情報をk8sに保存
k8sの昨日でSecretsというものがあります。
これは秘密情報を Secrets
というデータベースで管理して、
パスワードなどを必要とする Pod のみに送ります。
Secrets の中身は Key-Value
ペアのリストでパスワードを保存し、対象のpodに送ります。
今回は password.txt
というファイルを作成し、 Secrets
に登録します。
vim password.txt
kubectl ceate secret
コマンドで登録
kubectl create secret generic mysql-pass --from-file=password.txt secret "mysql-pass" created
kubectl get secrets
コマンドで、Secretsの一覧を取得できます。
kubectl get secrets NAME TYPE DATA AGE default-token-g46vb kubernetes.io/service-account-token 3 3h mysql-pass Opaque 1 8s
MySQLを起動
MySQLのPodをつくりMySQLを起動させます。
以下の内容で ./manifests/mysql-pod.yaml
を作成します。
apiVersion: v1 kind: Pod metadata: name: wordpress-mysql labels: app: wordpress tier: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 3306 name: mysql
- apiVersion
- kind
- リソースの種類
- metadata
- Podに設定するメタデータ
- Podの名前とラベルを設定することで同じアプリケーションが動作するPodが複数存在するときに絞り込みを行うことが可能
- spec
kubectl apply
コマンドでPodを作成
kubectl apply -f ./manifests/mysql-pod.yaml pod "wordpress-mysql" created
kubectl get pods
コマンドで、mysqlが起動していることを確認
kubectl get pods NAME READY STATUS RESTARTS AGE wordpress-mysql 0/1 Pending 0 1m
-l
でラベルを使って絞り込みもできます。
kubectl get pods -l app=wordpress -l tier=mysql NAME READY STATUS RESTARTS AGE wordpress-mysql 0/1 Pending 0 59s
kubectl logs
コマンドでMySQLのログも確認できます
kubectl logs wordpress-mysql | tail -n 5 2018-05-05 08:04:52 1 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory . 2018-05-05 08:04:52 1 [Warning] 'proxies_priv' entry '@ root@wordpress-mysql' ignored in --skip-name-resolve mode. 2018-05-05 08:04:52 1 [Note] Event Scheduler: Loaded 0 events 2018-05-05 08:04:52 1 [Note] mysqld: ready for connections. Version: '5.6.40' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
mysqld: ready for connections.
と出力されていることを確認できます。
MySQLに接続
kubectl port-forward
コマンドで、Podのポートをフォワードさせます。
kubectl port-forward wordpress-mysql 13306:3306 Forwarding from 127.0.0.1:13306 -> 3306 Forwarding from [::1]:13306 -> 3306 Handling connection for 13306 Handling connection for 13306 Handling connection for 13306
ポート 13306
をしていしてMySQLクライアントでMySQLに接続できることを確認できました。
mysql -s -uroot -p -h127.0.0.1 --port=13306 Enter password: mysql> show databases; Database information_schema mysql performance_schema
DBのデータを永続的に保存させる
MySQLのデータはPod上にあるので、Podが消えたらDBのデータも消えてしまいます。 なのでDBのデータを PersistentVolume に保存するようにします。
kubernetesでPersistent Volumesを使ってみる
./manifests/mysql-volume.yaml
でPersistentVolumeを定義します。
local-volume-1
というPersistentVolumeを作成します。
apiVersion: v1 kind: PersistentVolume metadata: name: local-volume-1 labels: type: local spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce hostPath: path: /tmp/data/lv-1 persistentVolumeReclaimPolicy: Recycle
適用すると、PersistentVolumeが作成されます。
kubectl apply -f ./manifests/mysql-volume.yaml persistentvolume "local-volume-1" created
PersistentVolume一覧からlocal-volume-1が作成されていることを確認できました。
kubectl get persistentvolume NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE local-volume-1 20Gi RWO Recycle Available
次に、PodがPersistentVolumeを取得できるようにします。
PersistentVolumeClaim というリソースを使いますので
./manifests/mysql-persistent-volume-claim.yaml
で定義します。
PV(PersistentVolume)からPodに紐付けるための領域がPVC(PersistentVolumeClaim)です。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-lv-claim labels: app: wordpress tier: mysql spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi
- Access Modes
- Claimsは特定のアクセスモードでストレージを要求するときにボリュームと同じ規則を使用します。
- Resources
- Claimsはポッドのように、特定の量のリソースを要求することができます。この場合、要求はストレージ用です。同じリソース・モデルがボリュームと要求の両方に適用されます。
適用してPVC(PersistentVolumeClaim)を作成します。 PVCをつくることでPodにストレージを追加することができます。
kubectl apply -f ./manifests/mysql-persistent-volume-claim.yaml persistentvolumeclaim "mysql-lv-claim" created
それではmysql PodがPVを使うようにマウント設定を行います。Deploymentsにもしておきます。 Deployment については以下もこちらも確認しました。
Kubernetes Deploymentを理解する Kubernetes: Deployment の仕組み
Deployment
は ReplicaSet
を生成・管理し、 ReplicaSet
は Pod
を生成・管理します。
Rolling Back
やローリングアップデート、Scaling
でセルフヒーリングといった仕組みを提供してくれます。
./manifests/mysql-deployment-with-volume.yaml
で定義します。
apiVersion: apps/v1 kind: Deployment metadata: name: wordpress-mysql labels: app: wordpress tier: mysql spec: selector: matchLabels: app: wordpress tier: mysql template: metadata: labels: app: wordpress tier: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-local-storage mountPath: /var/lib/mysql volumes: - name: mysql-local-storage persistentVolumeClaim: claimName: mysql-lv-claim
kubectl apply
して、mysql Deploymentを作成
kubectl apply -f manifests/mysql-deployment-with-volume.yaml deployment.apps "wordpress-mysql" created
Deploymentを作ったので、Deploymentによって作られたPodと、最初に作成したPodがいる状態です。
wordpress-mysql-7584cf4c49-xx9t4
がDeploymentによって作られたPodです。
kubectl get pod -l app=wordpress -l tier=mysql NAME READY STATUS RESTARTS AGE wordpress-mysql 1/1 Running 0 48m wordpress-mysql-7584cf4c49-xx9t4 1/1 Running 0 14s
kubectl delete pod wordpress-mysql pod "wordpress-mysql" deleted
Deploymentが作ったPodを見ると、 ReplicaSet
でPodが管理されており、
Volumes
にmysql-lv-claimが登録されているのがわかります。
kubectl describe pod wordpress-mysql-7584cf4c49-xx9t4 Name: wordpress-mysql-7584cf4c49-xx9t4 (略) Controlled By: ReplicaSet/wordpress-mysql-7584cf4c49 (略) Volumes: mysql-local-storage: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: mysql-lv-claim ReadOnly: false default-token-cwnn6: Type: Secret (a volume populated by a Secret) SecretName: default-token-cwnn6 Optional: false (略)
WordPressの起動
次は ./manifests/wordpress-pod.yaml
に定義し、WordPressのPodを作成します。
apiVersion: v1 kind: Pod metadata: name: wordpress labels: app: wordpress tier: front-end spec: containers: - image: wordpress name: wordpress env: - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 80 name: wordpress
kubectl apply
をします。
kubectl apply -f ./manifests/wordpress-pod.yaml pod "wordpress" created
Podが立ち上がりませんでした。
kubectl get pods -l app=wordpress -l tier=front-end NAME READY STATUS RESTARTS AGE wordpress 0/1 CrashLoopBackOff 7 17m
ログを確認
kubectl logs wordpress | tail -n 5 MySQL Connection Error: (2002) php_network_getaddresses: getaddrinfo failed: Name or service not known Warning: mysqli::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known in Standard input code on line 22 Warning: mysqli::__construct(): (HY000/2002): php_network_getaddresses: getaddrinfo failed: Name or service not known in Standard input code on line 22
WordPressのPod定義で、MySQLのホストを指定していないからので、
環境変数WORDPRESS_DB_HOST
として渡してあげましょう。
WordPressとMySQLの接続
Service
というリソースを作ります。
サービスの転送先のポッドのセットは、ラベルとセレクターによって判別されます。
Serviceのspecとしては、ポート情報とどのPodにつなぐかを決めるselectorとclusterIPです。
Services Kubernetes "サービス"の概要についての自習ノート
./manifests/mysql-service.yaml
でMySQLの接続情報を定義します。
apiVersion: v1 kind: Service metadata: name: wordpress-mysql labels: app: wordpress tier: mysql spec: ports: - port: 3306 selector: app: wordpress tier: mysql clusterIP: None
今回はまずService wordpress-mysql
という名前の新しいオブジェクトを作成しました。
このオブジェクトは、TCPポート 3306
をラベルのある任意のPod、ここでは wordpress
で使用できるようにします。
kubectl apply -f manifests/mysql-service.yaml service "wordpress-mysql" created
Service一覧で確認
kubectl get service -l app=wordpress -l tier=mysql NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE wordpress-mysql ClusterIP None <none> 3306/TCP 8s
Serviceを作成したら、wordpress Podを一度消して、 DB接続できるwordpress Podを作り直します。
kubectl delete pod wordpress pod "wordpress" deleted kubectl get pods -l app=wordpress -l tier=frontend No resources found.
mysqlのホストとしてmysql Serviceを使うように定義を追加します。
spec/containers/envに、WORDPRESS_DB_HOSTを追加して、値に、wordpress-mysql Serviceの3306を指定しています。
./manifests/wordpress-pod-with-mysql-host.yaml
という名前で以下のを記述します。
apiVersion: v1 kind: Pod metadata: name: wordpress labels: app: wordpress tier: frontend spec: containers: - image: wordpress name: wordpress env: - name: WORDPRESS_DB_HOST value: wordpress-mysql:3306 - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 80 name: wordpress
kubectl apply
して、再度Podを作成。
kubectl apply -f ./manifests/wordpress-pod-with-mysql-host.yaml pod "wordpress" created
ログをみてみます。 WordPressが無事起動されています。 wordpressからwordpress-mysqlに繋がりました。
kubectl logs wordpress | tail -n 5 Complete! WordPress has been successfully copied to /var/www/html AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppres s this message AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message [Sat May 05 09:32:32.910938 2018] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.25 (Debian) PHP/7.2.5 configured -- resuming normal operations [Sat May 05 09:32:32.911000 2018] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
しかし、k8sの外からwordpressに繋ぐことができないので、wordpress用のサービスも作ります。 mysqlとは違い、外部から接続したいので、typeとしてNodePortというものを選択します。 これは、PodのポートとNodeのポートを接続するものです。
./manifests/wordpress-service.yaml
で以下のyamlを作成します。
apiVersion: v1 kind: Service metadata: labels: app: wordpress tier: frontend name: wordpress spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30180 selector: app: wordpress tier: frontend
kubectl apply
コマンドで、wordpress Serviceを作成。
applyすればブラウザからアクセス可能になります。
kubectl apply -f ./manifests/wordpress-service.yaml service "wordpress" created
Service一覧から確認
kubectl get service -l app=wordpress -l tier=frontend NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE wordpress NodePort 10.101.18.94 <none> 80:30180/TCP 9s
minikubeでは、以下のコマンドでブラウザで開くことができます。 Wordpressのセットアップ画面が表示されることができます。
minikube service wordpress Opening kubernetes service default/wordpress in default browser...
セルフヒーリング
wordpressコンテナがクラッシュした時に繋がらなくなってしまいます。
対応したくないものです。運用はラクにしたいですね。
Podはコンテナとストレージボリュームの集合というだけで、自分自身を管理するということをしませんでした。
DeploymentのリソースをつかうことでPodの管理が可能になります。
Deployment
は ReplicaSet
を生成・管理し、 ReplicaSet
は Pod
を生成・管理でしたね。
./manifests/wordpress-deployment.yaml
という名前で、以下のyamlを作成。
apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress tier: frontend spec: selector: matchLabels: app: wordpress tier: frontend template: metadata: labels: app: wordpress tier: frontend spec: containers: - image: wordpress name: wordpress env: - name: WORDPRESS_DB_HOST value: wordpress-mysql:3306 - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password.txt ports: - containerPort: 80 name: wordpress
applyしてDeploymentによって自動的にwodpress Podが作成されることが確認できます。 古いPod(wordpress)は削除します。
kubectl apply -f ./manifests/wordpress-deployment.yaml deployment.apps "wordpress" created
kubectl get deployment
コマンドで、wordpress Deploymentが作成されていることを確認
kubectl get deployment -l app=wordpress -l tier=frontend NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE wordpress 1 1 1 0 7s
Deployment
によってPodが自動作成されていることを確認。
wordpressはPodとして作成したもので、wordpress-5644c5ff4-fgbgbは Deployment
によって自動作成されたものです。
また、最初に作成したwordpress Podは消しておきましょう。
kubectl get pods -l app=wordpress -l tier=frontend NAME READY STATUS RESTARTS AGE wordpress 1/1 Running 0 8m wordpress-5644c5ff4-fgbgb 1/1 Running 0 23s kubectl delete po/wordpress pod "wordpress" deleted
Deploymentは定義した状態を維持しようとします。 例えば、Podを削除しても新しいPodが自動的に作成され、Podが1台動いているという状態が維持されるます。
kubectl delete pod wordpress-5644c5ff4-fgbgb pod "wordpress-5644c5ff4-fgbgb" deleted kubectl get pods -l app=wordpress -l tier=frontend NAME READY STATUS RESTARTS AGE wordpress-5644c5ff4-fgbgb 0/1 Terminating 0 54s wordpress-5644c5ff4-w7h9z 1/1 Running 0 6s
このように wordpress-5644c5ff4-fgbgb
が削除されると、
wordpress-5644c5ff4-w7h9z
というPodがDeploymentにより作られます。
これはk8sの特徴で、状態を維持しようとする機能があります。 これにより、アプリケーションがクラッシュしたりしても自動的に復旧され、 サービスの運用の負担を下げることができます。
Deploymentを使うように変えてもPodは1つのままですがPodの数を変更することも可能です。 次は kubectl scale コマンドでレプリカ数を変更して、Podの数を変えてみましょう。
kubectl scale deployment wordpress --replicas 5 deployment.extensions "wordpress" scaled
kubectl get pods
でPodが4台追加されていることが確認できました。
kubectl get pods -l app=wordpress -l tier=frontend NAME READY STATUS RESTARTS AGE wordpress-5644c5ff4-9kt5l 0/1 ContainerCreating 0 12s wordpress-5644c5ff4-kvb4q 1/1 Running 0 12s wordpress-5644c5ff4-vhkhq 0/1 ContainerCreating 0 12s wordpress-5644c5ff4-w7h9z 1/1 Running 0 33s wordpress-5644c5ff4-zq6sz 0/1 ContainerCreating 0 12s
これで、スケールアウトできる、wordpress環境の完成です。