Serviceでポッドを見つけ設定とストレージを付ける
目標
Serviceがどのようにして、Podを見つけるのか、見つけられないときはどんな姿になるのかを自分で作って確かめ、ConfigMap/Secretの注入とPVCの申請、サービスのDNS名のルールまで、手で確認します。
なぜ重要なのか
Service関連の障害の圧倒的多数は、「サービスが作られていない」ではなく、「サービスは作られているのに、背後に何もない」ことです。Kubernetesは、セレクターが実際にPodを捕捉しているかを検証してくれないからです。タイプミス1つでエンドポイントが0件になっても、kubectl get svcは問題なさそうに見えます。そのため、このラボではわざとその状況を作ってみます。一度手で作って経験した失敗は、現場では3分で診断できます。
ConfigMap/Secretは、12-factorの「設定は環境から」をKubernetesが実装した形です。イメージはどこでも同じで、違うのは注入される値であるべきです。ただしSecretは、名前に反して、デフォルト設定では暗号化されないという点を覚えておいてください。これはKCSAの重要なテーマです。
PVCは「申請書」という比喩がすべてです。Podは「NFSサーバー10.0.0.5の/export/data」を指さず、「1GiのRWOストレージ」を申請します。この間接層のおかげで、同じマニフェストがノートPCのクラスターでも本番でも動きます。
ステップ
- ネームスペース
kcna-netを作成し、その中にDeploymentshopを作成してください。イメージはnginx:1.27-alpine、replicasは2、Podテンプレートのラベルはapp=shopです。 - Service
shop-svcを作成してください。タイプはClusterIP、portは80、セレクターはapp=shopです。エンドポイントが2件捕捉されているか確認してください。 - Service
broken-svcを同じネームスペースに作成してください。portは80ですが、セレクターはわざとapp=shopp(pが1つ多い)にします。エンドポイントが0件であることを確認し、このサービスを直す正しいセレクターを、/root/kcna-net/diagnosis.txtにapp=shopの形式で1行で保存してください。 - Service
shop-npを作成してください。タイプはNodePort、portは80、nodePortは30080、セレクターはapp=shopです。 - ConfigMap
shop-configを作成してください(キーAPP_MODE、値production)。Secretshop-secretを作成してください(キーAPI_KEY、値は任意の文字列)。そしてPodshop-clientを作成し、環境変数APP_MODEはshop-configのAPP_MODEキーから、環境変数API_KEYはshop-secretのAPI_KEYキーから取得するようにしてください。イメージはnginx:1.27-alpineです。 - PVC
shop-dataを作成してください。要求容量は1Gi、accessModesはReadWriteOnce、storageClassNameはstandardです。 shop-svcの完全修飾DNS名(FQDN)を/root/kcna-net/dns.txtに1行で保存し、同じネームスペースにヘッドレスサービスshop-headlessを作成してください。セレクターはapp=shop、portは80、clusterIPはヘッドレスとして指定します。
参考
- エンドポイントの確認は、
kubectl get endpointslice -n kcna-net -l kubernetes.io/service-name=shop-svc -o yamlで見られます。kubectl describe svcのEndpoints行も手軽です。 - ステップ5のPodのenv項目には、
valueFrom.configMapKeyRef/valueFrom.secretKeyRefを使います。それぞれnameとkeyの2つのフィールドが必要です。 - クラスタードメインのデフォルト値は
cluster.localです。 - よくあるミス1: ステップ3で、タイプミスのあるサービスを作るとすぐに直してしまうことです。このステップは、間違った状態のままにしておかないと通過しません。
- よくあるミス2: ステップ6のPVCがPendingなので、間違って作ったのだと思い、削除して作り直してしまうことです。動的プロビジョナーがなければPendingが正常であり、採点は申請内容だけを見ます。
バックエンドのDeploymentを立ち上げる
ネームスペースkcna-netを作成し、その中にDeploymentshopを作成してください。イメージはnginx:1.27-alpine、replicasは2、Podテンプレートのラベルはapp=shopです。
サービスが向かう対象が、先に存在している必要があります。Podテンプレートに付くラベルが、あとでセレクターと合っていなければならないので、どのラベルが付くかを確認しておいてください。
ClusterIPサービスとエンドポイントを確認する
Serviceshop-svcを作成してください。タイプはClusterIP、portは80、セレクターはapp=shopです。エンドポイントが2件捕捉されているか確認してください。
kubectl exposeで作ることも、YAMLで書くこともできます。作成後、エンドポイントが実際に捕捉されたかを必ず確認してください。サービスが作られたことと、トラフィックの行き先があることは別の話です。
セレクターのタイプミスをわざと再現する
Servicebroken-svcを同じネームスペースに作成してください。portは80ですが、セレクターはわざとapp=shopp(pが1つ多い)にします。エンドポイントが0件であることを確認し、このサービスを直す正しいセレクターを、/root/kcna-net/diagnosis.txtにapp=shopの形式で1行で保存してください。
このステップは、失敗を作ることが目標です。セレクターの値に1文字多く入れたサービスを作り、エラーが出ないことと、エンドポイントが0件であることの両方を確認してください。診断ファイルには、このサービスを直すための正しいセレクターを、key=valueの1行で書きます。
NodePortで外から入ってくる入口を作る
Serviceshop-npを作成してください。タイプはNodePort、portは80、nodePortは30080、セレクターはapp=shopです。
NodePortの範囲は、デフォルトで30000-32767です。番号を指定しないと任意に割り当てられるので、採点対象の番号を使うには、マニフェストに明示する必要があります。
ConfigMapとSecretを注入する
ConfigMapshop-configを作成してください(キーAPP_MODE、値production)。Secretshop-secretを作成してください(キーAPI_KEY、値は任意の文字列)。そしてPodshop-clientを作成し、環境変数APP_MODEはshop-configのAPP_MODEキーから、環境変数API_KEYはshop-secretのAPI_KEYキーから取得するようにしてください。イメージはnginx:1.27-alpineです。
kubectl create configmapとkubectl create secret genericに--from-literalを使うと手早くできます。Pod側は、env項目ごとにvalueFromでconfigMapKeyRef / secretKeyRefを指定する形です。どのキーをどの名前で公開するか、2か所とも書く必要があります。
PVCでストレージの申請書を書く
PVCshop-dataを作成してください。要求容量は1Gi、accessModesはReadWriteOnce、storageClassNameはstandardです。
PVCは「申請書」です。このラボのクラスターには動的プロビジョナーがないため、Pendingのままになることがありますが、それ自体が正常であり、採点はspecを見ます。accessModesは配列で、storageClassNameは文字列です。
DNS名のルールとヘッドレスサービス
shop-svcの完全修飾DNS名(FQDN)を/root/kcna-net/dns.txtに1行で保存し、同じネームスペースにヘッドレスサービスshop-headlessを作成してください。セレクターはapp=shop、portは80、clusterIPはヘッドレスとして指定します。
サービスの完全修飾DNS名は、4つの断片でできています。そしてヘッドレスサービスは、clusterIPフィールドに特定の値を明示して作ります。この値はkubectl exposeでは指定しにくいので、YAMLを使うほうがよいです。