DNS problem of Job on Kubernetes

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

実行環境

漁った資料

Kubernetes + curl + DNS をキーワードにGoogleして以下の資料を得たが、解決には至らなかった。

トラブルシューティング

/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

optionsndotsの値が原因でalpineベースのイメージには意図しない動作があったらしいが、結論から言えばcurlimages/curl:7.85.0では解決済みのようである。

curlimages/curlのダウングレード

Issueで述べられていた7.77.0まで落としてみたが直らず。

別の人がビルドしたcurlイメージも試してみたが手ごたえなし。

デプロイしたPod内からcurl

以下のマニフェストを適用して、kubectl execcurlを叩いた。

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 execcurlを叩いたら通ったり通らなかったりしたので以下の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した結果、複雑な問題まで深追いしてしまう」ってやつ。 触りたての時期は知識も技量も浅いから手あたり次第解決策を試すしかないんだけど、頭を冷やして系の挙動をじっくり観察するというのも大切ね。