はじめに
この手順を辿れば、ARM64 Kubernetes 上で Docker Official Image を使ったデータベース Pod を起動できます。
この記事について
実践的に Kubernetes を学習できればと思い、2時間でRaspberry Piを使ったKubernetes クラスタを作るという記事を書いたのですが、Pod の作成手順もあった方が良いと思い、この記事を書きました。
前提条件
この記事を書く時に使った環境は下記の通りです。
- K3s: v1.21.1+k3s1
- Raspberry Pi 4B 4GB Memory
- インターネットアクセス環境
- LinuxをCLIのみで触る程度の知識
ソフトウェア
ARM64対応のOfficial Imageは以下のバージョン以降
- MySQL: 8.0.29以降
- MongoDB: 3.4.20以降
事前確認事項の整理
ハードウェアのシステムアーキテクチャを確認
Pod をデプロイする対象が X86-64(AMD64) なのか、ARM64 なのか確認します。
Intel CPU や AMD CPU の場合は AMD64、Raspberry Pi の場合は ARM64 となります。
注意: コンテナイメージが対応していないシステムアーキテクチャの Pod は起動しません
Official Docker Imageの対応状況を確認
目的とするコンテナイメージが自分の持っているKubernetesシステムアーキテクチャに対応することを確認
docker hub で mysql を検索すると、x86−64 と ARM64 の両方に対応していることが確認できます。
同じバージョンで、複数のアーキテクチャに対応したイメージを提供していることが確認できます。
こちらは、AMD64 のみのイメージとなります。よって、Raspberry Pi を使った Kubernetes では動作しません。
同じくdocker hub で mongo を検索すると、x86-64 と ARM64 の両方に対応していることが確認できました。
MongoDB は、3.4.20 以降、AMD64 と ARM64 の両方が提供されています。
デプロイの準備と実行
各コンテナイメージの環境変数(Environment Variables)を確認
コンテナイメージを起動する際に初期値として渡す環境変数の条件を確認します。コンテナイメージを作った時に決まる要素なので、都度確認する必要があります。そうでなければ、コンテナ(Pod)起動後に個別設定が必要となってしまうでしょうから、必須の確認項目となるかと。
Docker Official Imagesでは、以下のような形で環境変数が説明されています。これは提供されているイメージの説明ページによって記載方法が違うため、都度確認が必要となります。
Docker Official Images: MySQLの環境に関する説明
Docker Official Images: Mongoの環境変数に関する説明
Pod 作成準備
Pod 作成の準備を行います。ちなみに、こちらの例はセキュアではありませんので、ご注意下さい。
パスワードは都度個別にsecretで運用すべきですが、説明用としてsecretを使うものと直書きの両方を案内します。
下記のように設定するとMySQL ROOTのパスワードがrootpass01
となります。適宜変更して使って下さい。
kubectl create secret generic mysql-pass --from-literal=password=rootpass01
Pod作成用yamlの用意
apiVersion: v1
kind: Pod
metadata:
name: watashino-mysql
labels:
name: label-mysql
spec:
containers:
- name: mysql
image: mysql:8.0.29 # このように指定するとdocker hubのMySQL 8.0.29 となります
env:
- name: MYSQL_USER # 環境変数を直接指定
value: user01 # ユーザー名
- name: MYSQL_PASSWORD # 環境変数を直接指定
value: password01 # 上記にて設定するユーザーのパスワード
- name: MYSQL_DATABASE # 環境変数を直接指定
value: database01 # データベース名称
- name: MYSQL_ROOT_PASSWORD # secretを使った環境変数の指定
valueFrom: #
secretKeyRef: # secretsを参照
name: mysql-pass # secretsの名称
key: password # secretsのkey
ports:
- name: mysql
containerPort: 3306 # コンテナのポート番号
protocol: TCP
volumeMounts:
- name: watashino-mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: watashino-mysql-storage
emptyDir: {}
Pod のデプロイと確認
上記で作ったsecretとyamlを使ってPodを作成します。
kubectl apply -f mysql-pod.yaml
確認しましょう。
kubectl get pods
NAME READY STATUS RESTARTS AGE
watashino-mysql 1/1 Running 0 3m
Podが起動したら中身を確認します。
kubectl exec -it pods/watashino-mysql -- /bin/sh
sh-4.4# mysql -u user01 -h localhost -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.29 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| database01 |
| information_schema |
+--------------------+
2 rows in set (0.02 sec)
mysql> \q
Bye
sh-4.4#
Pod の起動失敗の例
AMD64 対応の 8.0.28 のイメージをRaspberry Pi の Kubernetes 環境で実行起動しようとすると、起動に失敗します。
kubectl get pods
NAME READY STATUS RESTARTS AGE
watashino-mysql 0/1 ErrImagePull 0 29s
MySQL 8.0.28 をデプロイするとno match for platform in manifest
というエラーが出力されます。これは、ARM64 プラットフォームに対応した適切なイメージが pull できない、というエラーになります。
kubectl describe pods/watashino-mysql
Name: watashino-mysql
Namespace: default
Priority: 0
Node: worker1/192.168.1.21
Start Time: Mon, 21 Nov 2022 15:21:29 +0000
Labels: name=label-mysql
Annotations: <none>
Status: Pending
IP: 10.42.1.23
IPs:
IP: 10.42.1.23
Containers:
mysql:
Container ID:
Image: mysql:8.0.28
Image ID:
Port: 3306/TCP
Host Port: 0/TCP
State: Waiting
Reason: ImagePullBackOff
Ready: False
Restart Count: 0
Environment:
MYSQL_USER: user01
MYSQL_PASSWORD: password01
MYSQL_DATABASE: database01
MYSQL_ROOT_PASSWORD: <set to the key 'password' in secret 'mysql-pass'> Optional: false
Mounts:
/var/lib/mysql from watashino-mysql-storage (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pzb75 (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
watashino-mysql-storage:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
kube-api-access-pzb75:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 46s default-scheduler Successfully assigned default/watashino-mysql to worker1
Warning Failed 21s kubelet Failed to pull image "mysql:8.0.28": rpc error: code = NotFound desc = failed to pull and unpack image "docker.io/library/mysql:8.0.28": no match for platform in manifest: not found
Warning Failed 21s kubelet Error: ErrImagePull
Normal BackOff 21s kubelet Back-off pulling image "mysql:8.0.28"
Warning Failed 21s kubelet Error: ImagePullBackOff
Normal Pulling 6s (x2 over 45s) kubelet Pulling image "mysql:8.0.28"
備考
Podのアンインストール方法
kubectl delete pods/watashino-mysql
Secretのアンインストール方法
kubectl delete secrets/mysql-pass