KubernetesでWeb APIを叩くジョブを作ろうとしたらDNS名前解決で3日詰まったのでメモ。
問題の概要
以下のマニフェストのようなJobをKubernetesで動かしたところ、curl: (6) Could not resolve Host: github.com; Name or service not known
のエラーが出てジョブを完了できなかった。
apiVersion: batch/v1 kind: Job metadata: name: curl-test spec: parallelism: 1 completions: 1 backoffLimit: 3 ttlSecondsAfterFinished: 100 template: spec: containers: - name: curl image: curlimages/curl:7.85.0 command: - curl - -I - https://github.com restartPolicy: Never
実行環境
- OS: Ubuntu 22.04
- Linux kernel: 5.15.0-1015-raspi(aarch64)
- Kubernetes: MicroK8s v1.25 (1 node)
- RAM: 4GB
漁った資料
Kubernetes + curl + DNS をキーワードにGoogleして以下の資料を得たが、解決には至らなかった。
- dns - Kubernetes: Pods Can't Resolve Hostnames - Stack Overflow
- Dns resolution problem with Alpine and Kubernetes · Issue #65 · curl/curl-docker · GitHub
- DockerのAlpineのapkが名前解決に失敗しててハマった - Qiita
トラブルシューティング
/etc/resolv.conf
の確認
$ kubectl run curl --image=curlimages/curl:7.85.0 -- cat /etc/resolv.conf pod/curl created $ kubeclt logs curl search default.svc.cluster.local svc.cluster.local cluster.local nameserver 10.152.183.10 options ndots:5
options
のndots
の値が原因でalpineベースのイメージには意図しない動作があったらしいが、結論から言えばcurlimages/curl:7.85.0
では解決済みのようである。
curlimages/curl
のダウングレード
Issueで述べられていた7.77.0
まで落としてみたが直らず。
別の人がビルドしたcurl
イメージも試してみたが手ごたえなし。
デプロイしたPod内からcurl
以下のマニフェストを適用して、kubectl exec
でcurl
を叩いた。
apiVersion: apps/v1 kind: Deployment metadata: name: curl-test spec: selector: matchLabels: app: curl-test template: metadata: labels: app: curl-test spec: containers: - name: curl-test image: curlimages/curl:7.85.0 resources: limits: memory: "128Mi" cpu: "500m" command: - sleep - "3600"
$ kubectl exec -it curl-test-<id> -- curl -I https://github.com HTTP/2 200 server: GitHub.com date: Tue, 04 Oct 2022 15:14:23 GMT content-type: text/html; charset=utf-8 ...
なぜか通り困惑。 Job特有のバクかと当たりをつけGoogleするが、それらしき情報は見当たらず。 未報告のバグだとしても、どのレイヤー(MicroK8s? Kubernetes? CoreDNS? cURL?)で起こっているバグか特定できない限りコントリビュートできないので半ば諦め状態。
解決編
同様にしばらくスリープするcurl
コンテナのJobを作って、kubectl exec
でcurl
を叩いたら通ったり通らなかったりしたので以下のJobを作成。
apiVersion: batch/v1 kind: Job metadata: name: curl-test spec: parallelism: 1 completions: 1 backoffLimit: 3 ttlSecondsAfterFinished: 100 template: spec: containers: - name: curl image: curlimages/curl:7.85.0 command: - sh - -c - | while (true); do curl -I https://github.com if [ ! $? -eq 6 ]; then # Exit code 6 is the DNS error break fi sleep 1 done restartPolicy: Never
無事JobがComplete状態になってトラブルシューティング終了。
どうやらいろいろデプロイしたせいか、システムに負荷がかかっていてDNS周りのリソース割り当てに1分以上かかっていたらしい。
反省
未知のバグじゃなくて良かったけど、Googleするときはできるだけ新しい情報を漁らないと既に解決済みの問題の解決法まで試すことになって良くないと思った。
今回の問題の本質は、新技術に触ったときにありがちな「実は単純な問題をGoogleした結果、複雑な問題まで深追いしてしまう」ってやつ。 触りたての時期は知識も技量も浅いから手あたり次第解決策を試すしかないんだけど、頭を冷やして系の挙動をじっくり観察するというのも大切ね。