Docker/Kubernetes 実践コンテナ開発入門:書籍案内|技術評論社
前回は、オンプレミス環境での k8s クラスタ構築について読み進めました。
今回は k8s の応用についてやっていきます。
7.Kubernetes の発展的な利用
7.1 Kubernetes の様々なリソース
- 常駐型のサーバアプリケーション構築する上で基本となるリソース
- Pod、ReplicaSet、Deployment、Service、Ingress
- 上記以外にもジョブサーバなど多様な使い道がある
7.1.1 Job
一つ以上の Pod を作成し、指定された数の Pod が正常に完了するまでを管理するリソース
Job による全ての Pod が正常に終了しても Pod は削除されずに保持される => Docker のコンテナと似ている
バッチ処理に向いている
simple-job.yaml
apiVersion: batch/v1
kind: Job # Jobリソース
metadata:
name: pingpong # リソース名
labels:
app: pingpong # リソースのラベル
spec:
parallelism: 3 # 同時に実行されるPod数
template:
metadata:
labels:
app: pingpong
spec:
containers:
- name: pingpong
image: gihyodocker/alpine:bash # Alpine Linuxにbashをインストールしたイメージ
command: ["/bin/sh"]
args:
- "-c"
- |
echo [`date`] ping!
sleep 10
echo [`date`] pong!
restartPolicy: Never # Pod終了時の再実行の設定。失敗時にPodを再作成して実行する
- Job をデプロイするとエラー
$ kubectl apply -f simple-job.yaml
Unable to connect to the server: dial tcp 35.221.107.8:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
先日クラスタ削除したためのエラーだと思われる。
クラスタを作り直す(PowerShell で実行)
$ gcloud container clusters create gihyo --cluster-version=1.16.13-gke.401 --machine-type=n1-standard-1 --num-nodes=3
WARNING: Warning: basic authentication is deprecated, and will be removed in GKE control plane versions 1.19 and newer. For a list of recommended authentication methods, see: https://cloud.google.com/kubernetes-engine/docs/how-to/api-server-authentication
WARNING: Currently VPC-native is not the default mode during cluster creation. In the future, this will become the default mode and can be disabled using `--no-enable-ip-alias` flag. Use `--[no-]enable-ip-alias` flag to suppress this warning.
WARNING: Newly created clusters and node-pools will have node auto-upgrade enabled by default. This can be disabled using the `--no-enable-autoupgrade` flag.
WARNING: Starting with version 1.18, clusters will have shielded GKE nodes by default.
WARNING: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
Creating cluster gihyo in asia-northeast1-a... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/marine-proposal-295213/zones/asia-northeast1-a/clusters/gihyo].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/asia-northeast1-a/gihyo?project=marine-proposal-295213
kubeconfig entry generated for gihyo.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
gihyo asia-northeast1-a 1.16.13-gke.401 104.xxx.xxx.xxx n1-standard-1 1.16.13-gke.401 3 RUNNING
Updates are available for some Cloud SDK components. To install them,
please run:
$ gcloud components update
- コンポーネントアップデート
$ gcloud components update
- 再度デプロイ
$ kubectl apply -f simple-job.yaml
job.batch/pingpong created
- ログを確認
- ping!を表示し 10 秒 sleep した後に「ping!」を表示し終了する
$ kubectl logs -l app=pingpong
[Tue Nov 17 13:58:37 UTC 2020] ping!
[Tue Nov 17 13:58:47 UTC 2020] pong!
[Tue Nov 17 13:58:35 UTC 2020] ping!
[Tue Nov 17 13:58:45 UTC 2020] pong!
[Tue Nov 17 13:58:35 UTC 2020] ping!
[Tue Nov 17 13:58:45 UTC 2020] pong!
- 終了した Pod は Completed として表示される
$ kubectl get pod -l app=pingpong
NAME READY STATUS RESTARTS AGE
pingpong-hcd7j 0/1 Completed 0 8m1s
pingpong-tzc8v 0/1 Completed 0 8m1s
pingpong-vd9j9 0/1 Completed 0 8m1s
7.1.2 CronJob
Job は一度きりの Pod の実行
対して CronJob はスケジューリングして定期的に Pod を実行
simple-cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: pingpong
spec:
schedule: "*/1 * * * *" # Cron記法でPodの起動スケジュールを定義できる
jobTemplate:
spec:
template:
metadata:
labels:
app: pingpong
spec:
containers:
- name: pingpong
image: gihyodocker/alpine:bash
command: ["/bin/sh"]
args:
- "-c"
- |
echo [`date`] ping!
sleep 10
echo [`date`] pong!
restartPolicy: OnFailure
- CronJob をデプロイ
$ kubectl apply -f simple-cronjob.yaml
cronjob.batch/pingpong created
- job の確認
$ kubectl get job -l app=pingpong
NAME COMPLETIONS DURATION AGE
pingpong 3/1 of 3 18s 14m
pingpong-1605622260 1/1 11s 87s
pingpong-1605622320 1/1 12s 27s
- ログの確認
$ kubectl logs -l app=pingpong
[Tue Nov 17 14:11:04 UTC 2020] ping!
[Tue Nov 17 14:11:14 UTC 2020] pong!
[Tue Nov 17 14:12:04 UTC 2020] ping!
[Tue Nov 17 14:12:14 UTC 2020] pong!
[Tue Nov 17 14:13:04 UTC 2020] ping!
[Tue Nov 17 14:13:14 UTC 2020] pong!
[Tue Nov 17 13:58:37 UTC 2020] ping!
[Tue Nov 17 13:58:47 UTC 2020] pong!
[Tue Nov 17 13:58:35 UTC 2020] ping!
[Tue Nov 17 13:58:45 UTC 2020] pong!
[Tue Nov 17 13:58:35 UTC 2020] ping!
[Tue Nov 17 13:58:45 UTC 2020] pong!
- 従来の非コンテナ環境では Linux の crontab にスケジュールと実行するスクリプトを定義する手法が中心だった。
- k8s の CronJob を利用すれば全てをコンテナベースで解決できる
7.1.3 Secret
- Secret リソースを定義すると、機密情報の文字列を Base64 文字列に変換
- 例として、Nginx の Basic 認証の認証情報を記述したファイルを Secret で管理
- openssl を利用してユーザー名とパスワードを暗号化し、その結果を Base64 文字列に変換
$ echo "your_username:$(openssl passwd -quiet -crypt your_password)" | base64
eW91cl91c2VybmFtZTpPOWhncjF3UXZIY1ZFCg==
- nginx-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: nginx-secret
type: Opaque
data:
.htpasswd: eW91cl91c2VybmFtZTpyejc5SXpTalplaWZvCg== # .htpasswdというファイルを生成し、内容にはBase64化された文字列を指定
- Secret をデプロイ
$ kubectl apply -f nginx-secret.yaml
secret/nginx-secret created
- ダッシュボードで Secret 確認
- basic-auth.yaml
apiVersion: v1
kind: Service
metadata:
name: basic-auth
spec:
type: NodePort
selector:
app: basic-auth
ports:
- protocol: TCP
port: 80
targetPort: http
nodePort: 30060
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: basic-auth
labels:
app: basic-auth
spec:
replicas: 1
selector:
matchLabels:
app: basic-auth
template:
metadata:
labels:
app: basic-auth
spec:
containers:
- name: nginx
image: "gihyodocker/nginx:latest"
imagePullPolicy: Always
ports:
- name: http
containerPort: 80
env:
- name: BACKEND_HOST
value: "localhost:8080"
- name: BASIC_AUTH_FILE
value: "/etc/nginx/secret/.htpasswd" # nginx-secretで.htpasswdとして設定したBase64文字列は復号される
volumeMounts:
- mountPath: /etc/nginx/secret
name: nginx-secret
readOnly: true
- name: echo
image: "gihyodocker/echo:latest"
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: HTTP_PORT
value: "8080"
volumes: # すでに作成しているSecretであるnginx-secretをボリュームとしてマウント
- name: nginx-secret
secret:
secretName: nginx-secret
- Deployment をデプロイ
$ kubectl apply -f basic-auth.yaml
service/basic-auth unchanged
deployment.apps/basic-auth created
- 認証されるか HTTP リクエスト送信するとエラー
$ curl http://127.0.0.1:30060
curl: (7) Failed to connect to 127.0.0.1 port 30060: Connection refused
- コンテナ作成中になっている。。時間がかかるのだろうか。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
basic-auth-67667776f9-zj47j 0/2 ContainerCreating 0 5m22s
kubernetes で ContainerCreating (FailedMount) で Pod が起動しない時 | ytyng.com
- 以下のような警告が出ている。
- マウントできずにタイムアウトしてしまったようだ。
- basic-auth.yaml のボリュームの t がコピペミスでなくなっていた。。修正したところちゃんと起動した。
$ kubectl describe pods
47j to gke-gihyo-default-pool-477390af-djj8
Warning FailedMount 2m38s (x2 over 4m56s) kubelet, gke-gihyo-default-pool-477390af-djj8 Unable to attach or mount volumes: unmounted volumes=[nginx-secret], unattached volumes=[default-token-wxrm6 nginx-secret]: timed out waiting for the condition
Warning FailedMount 62s (x12 over 9m16s) kubelet, gke-gihyo-default-pool-477390af-djj8 MountVolume.SetUp failed for volume "nginx-secret" : secret "nginx-secre" not found
Warning FailedMount 24s (x2 over 7m13s) kubelet, gke-gihyo-default-pool-477390af-djj8 Unable to attach or mount volumes: unmounted volumes=[nginx-secret], unattached volumes=[nginx-secret default-token-wxrm6]: timed out waiting for the condition
- 再度 curl すると認証されるはずだが、やっぱりエラーのまま…なぜ・・・!?
コラム 認証情報をセキュアに環境変数へ設定する
- valueFrom.secretKeyRef を利用して Secret の data を渡すことができる。
今日の学び
- ハンズオン時にはログを残しておくとあとで役にたつ。
- 単発のバッチ処理には Job、スケジューリングしたバッチ処理には CronJob が便利。
- セキュリティ対策として Secret を使える。