Kuberntes 101
ここでは Kubernetes における主要なリソースの作成方法について紹介します。
細かい説明は省略していますので、適宜リソースについて調べながら進めてください。
また、manifest の内容も適宜確認してください。
Namespace を作成する
$ kubectl create namespace sandbox
$ kubens sandbox
$ kubectl get pods
No resources found in sandbox namespace.
Pod を作成する
nginx の Pod を作成します。Running
になれば動いています。
$ kubectl apply -f pod.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 89s
kubectl port-forward
で Pod への接続を確立し、curl で nginx Pod にリクエストを送信します。
$ kubectl port-forward pod/nginx 12345:80
Forwarding from 127.0.0.1:12345 -> 80
Forwarding from [::1]:12345 -> 80
$ curl -I localhost:12345
HTTP/1.1 200 OK
Server: nginx/1.23.0
kubectl logs
でコンテナのログを確認できます。
$ kubectl logs nginx
...
2022/07/03 09:41:19 [notice] 1#1: start worker process 33
2022/07/03 09:41:19 [notice] 1#1: start worker process 34
127.0.0.1 - - [03/Jul/2022:09:44:06 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.81.0" "-"
Pod を削除しておきます。
$ kubectl delete -f pod.yaml
Deployment を作成する
nginx の Deployment を作成します。replicas
に 2
を設定しているので Pod は2つ起動します。
$ kubectl apply -f deployment.yaml
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 7s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-8d545c96d-kgmmv 1/1 Running 0 10s
nginx-8d545c96d-nhr6n 1/1 Running 0 10s
Pod を1つ選び、削除します。
$ kubectl delete pod nginx-8d545c96d-kgmmv
pod "nginx-8d545c96d-kgmmv" deleted
Pod を削除しても、自動で新しい Pod が起動します。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-8d545c96d-nhr6n 1/1 Running 0 82s
nginx-8d545c96d-s62c6 1/1 Running 0 4s 👈
replicas
を5に変更すると Pod は5つ起動します。
$ kubectl patch deployment nginx -p '{"spec":{"replicas":5}}'
deployment.apps/nginx patched
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-8d545c96d-2929h 0/1 ContainerCreating 0 3s
nginx-8d545c96d-l8w6l 0/1 ContainerCreating 0 3s
nginx-8d545c96d-mzks5 0/1 ContainerCreating 0 3s
nginx-8d545c96d-nhr6n 1/1 Running 0 4m1s
nginx-8d545c96d-s62c6 1/1 Running 0 2m43s
Deployment を削除しておきます。
$ kubectl delete -f deployment.yml
deployment.apps "nginx" deleted
Service を作成する
$ kubectl apply -f deployment.yml
$ kubectl apply -f service.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-8d545c96d-fpn88 1/1 Running 0 7s
nginx-8d545c96d-jpnmj 1/1 Running 0 7s
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.101.128.111 <none> 80/TCP 7s
Service は <service name>.<namespace name>.svc.cluster.local
で Pod から名前解決できます。
$ kubectl run --rm -it --image=ubuntu:22.04 bash
If you don't see a command prompt, try pressing enter.
root@bash:/# apt update && apt install -y curl
root@bash:/# curl nginx.sandbox.svc.cluster.local
<!DOCTYPE html>
<html>
...
Pod から何度か curl でリクエストを送信し、Service から各 Pod にリクエストが振り分けられていることを確認します。
$ stern nginx
...
nginx-8d545c96d-fpn88 nginx 172.17.0.1 - - [03/Jul/2022:10:04:17 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
nginx-8d545c96d-jpnmj nginx 172.17.0.1 - - [03/Jul/2022:10:04:18 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
nginx-8d545c96d-fpn88 nginx 172.17.0.1 - - [03/Jul/2022:10:04:18 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
nginx-8d545c96d-fpn88 nginx 172.17.0.1 - - [03/Jul/2022:10:04:19 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
nginx-8d545c96d-jpnmj nginx 172.17.0.1 - - [03/Jul/2022:10:04:20 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
nginx-8d545c96d-fpn88 nginx 172.17.0.1 - - [03/Jul/2022:10:04:20 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
Service と Deployment を削除しておきます。
$ kubectl delete -f service.yaml
$ kubectl delete -f deployment.yaml
Ingress を作成する
最初に minikube の NGINX Ingress コントローラーを有効化します。
$ minikube addons enable ingress
Deployment, Service, Ingress をそれぞれ作成します。
$ kubectl apply -f deployment.yaml
$ kubectl apply -f service.yaml
$ kubectl apply -f ingress.yaml
しばらくすると ingress に IP アドレスが割り当てられます。
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx nginx nginx.local 192.168.59.100 80 27s
Ingress 経由で Pod にリクエストが届くことを確認します。
$ curl -H 'Host: nginx.local' http://192.168.59.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
リソースを削除しておきます。
$ kubectl delete -f deployment.yaml
$ kubectl delete -f service.yaml
$ kubectl delete -f ingress.yaml
データの永続化と Secrets リソース
ここでは MySQL コンテナを起動します。MySQL コンテナを起動するにあたり、以下のことを考慮する必要があります。
- MySQL root ユーザーのパスワードの設定
- データの永続化
まず、パスワードの設定についてですが、Kuberntes ではクレデンシャルなどの機密情報を Secrets リソースで扱うのが一般的です。
$ kubectl create secret generic mysql-pass --from-literal=pass=MySQLP@ssW0rd --dry-run -o yaml > secret.yaml
$ cat secret.yaml
apiVersion: v1
data:
pass: TXlTUUxQQHNzVzByZA==
kind: Secret
metadata:
creationTimestamp: null
name: mysql-pass
$ kubectl apply -f secret.yaml
$ kubectl get secrets
NAME TYPE DATA AGE
default-token-cn86n kubernetes.io/service-account-token 3 53m
mysql-pass Opaque 1 6m34s
Secret は Pod に環境変数として設定したり、ファイルとしてマウントすることができます。今回は MYSQL_ROOT_PASSWORD
環境変数として設定します。
mysql
イメージは起動時に MYSQL_ROOT_PASSWORD
環境構築を root ユーザーのパスワードとして設定します。
$ cat deployment.yaml
...
containers:
- image: mysql:8
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: pass
続いてデータの永続化についてですが、Kuberntes クラスタでは PV(Persistent Volume) を使ってデータを永続化することができます。
Pod から PV を使用するには PVC(Persistent Volume Claim) と呼ばれる「Pod から PV を使うための条件」を記したリソースを別途作成します。
$ cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
$ kubectl apply -f pvc.yaml
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pvc Bound pvc-c2311ff5-d7ab-404d-aeb3-4d4e373902f2 1Gi RWO standard 2s
Pod に PVC のデータをマウントするには volumes
で作成した PVC を指定し、volumeMounts
にマウント先を指定します。
$ cat deployment.yaml
...
containers:
- image: mysql:8
name: mysql
...
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: mysql-pvc
Secrets と PVC が作成できたら Deployment を作成します。
$ kubectl apply -f deployment.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-849d9779bb-2cs4b 1/1 Running 0 30s
パスワード MySQLP@ssW0rd
でログインできることを確認します。
$ kubectl exec -it mysql-849d9779bb-2cs4b -- mysql -u root -p
Enter Password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
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.
テスト用データベースを作成し、Pod を削除します。
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> exit
Bye
$ kubectl scale deployment mysql --replicas=0
deployment.apps/mysql scaled
$ kubectl get pods
No resources found in sandbox namespace.
$ kubectl scale deployment mysql --replicas=1
deployment.apps/mysql scaled
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-849d9779bb-lfzw8 1/1 Running 0 4s
再び MySQL に接続し、test
データベースが永続化していることを確認します。
$ kubectl exec -it mysql-849d9779bb-lfzw8 -- mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
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 |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
リソースを削除しておきます。
$ kubectl delete -Rf .
deployment.apps "mysql" deleted
persistentvolumeclaim "mysql-pvc" deleted
secret "mysql-pass" deleted
その他のリソース
DaemonSet
Kubernetes は複数のノードから構成されるクラスタとして動作することが期待されています。今回はシングルノードでの構成ですが、通常は3ノード以上から構成されることがほとんどです。
DaemonSet は Pod をすべてのノードに配置するためのリソースです。これはノードを監視するようなソフトウェアを動かす際に使用されます。
ConfigMap
ソフトウェアの設定ファイルなどを Pod にマウントするために使用されるリソースです。コンテナイメージをビルドしたりしなくても ConfigMap を更新するだけで、新しくソフトウェアを構成することができます。