KubernetesクラスタのDNSサーバーの構成

Container Engine for Kubernetes (OKE)を使用して作成したKubernetesクラスタ用にDNSサーバーを構成する方法を確認します。

組込みDNSサーバー(kube-dns、CoreDNS)の構成

Container Engine for Kubernetesによって作成されるクラスタには、自動的に起動される組込みKubernetesサービスとしてDNSサーバーが含まれます。各ワーカー・ノードのkubeletプロセスは、個々のコンテナをDNSサーバーに向け、DNS名をIPアドレスに変換します。

Kubernetesバージョン1.14より前のContainer Engine for Kubernetesでは、DNSサーバーとしてkube-dnsを使用してクラスタが作成されました。ただし、Kubernetesバージョン1.14以降では、Container Engine for KubernetesはDNSサーバーとしてCoreDNSを使用してクラスタを作成します。CoreDNSは、モジュール式でプラガブルな汎用の認可DNSサーバーです。

CoreDNSのデフォルトの動作は、Corefileと呼ばれる構成ファイルによって制御されます。Corefileは、CoreDNSの動作を定義するCorefileセクションを持つKubernetes ConfigMapです。Corefileを直接変更することはできません。CoreDNSの動作をカスタマイズする必要がある場合は、独自のConfigMapを作成して適用し、Corefileの設定をオーバーライドします(このトピックで説明します)。基本クラスタでは、CoreDNSのデフォルト動作をカスタマイズしない場合、カスタマイズはクラスタへの内部更新中に定期的に削除されることに注意してください(拡張クラスタでは、カスタマイズは削除されません)。

Container Engine for Kubernetesによって作成されたクラスタを以前のバージョンからKubernetes 1.14以降にアップグレードすると、クラスタのkube-dnsサーバーは自動的にCoreDNSサーバーに置き換えられます。元のkube-dns ConfigMapを使用してkube-dnsの動作をカスタマイズした場合、それらのカスタマイズはCoreDNS ConfigMapに引き継がれないことに注意してください。CoreDNS Corefileの設定をオーバーライドするには、カスタマイズを含む新しいConfigMapを作成して適用する必要があります。

CoreDNSのカスタマイズおよびKubernetesの詳細は、KubernetesのドキュメントおよびCoreDNSのドキュメントを参照してください。

CoreDNS Corefileの設定をオーバーライドするConfigMapを作成するには:

  1. yamlファイルに次の形式でConfigMapを定義します:

    apiVersion: v1
    kind: ConfigMap
    metadata:  
      name: coredns-custom  
      namespace: kube-system 
    data:
      <customization-options>

    例:

    apiVersion: v1
    kind: ConfigMap
    metadata:  
      name: coredns-custom  
      namespace: kube-system 
    data:
      example.server: | # All custom server files must have a ".server" file extension. 
        # Change example.com to the domain you wish to forward.
        example.com {
          # Change 1.1.1.1 to your customer DNS resolver.
          forward . 1.1.1.1
        }

    CoreDNSの動作のカスタマイズに使用するConfigMapオプションの詳細は、KubernetesのドキュメントおよびCoreDNSのドキュメントを参照してください。

  2. 次のように入力してConfigMapを作成します:

    kubectl apply -f <filename>.yaml
  3. 次のように入力して、カスタマイズが適用されたことを確認します:

    kubectl get configmaps --namespace=kube-system coredns-custom -o yaml
  4. 次のように入力して、CoreDNSでConfigMapを強制的にリロードします:

    kubectl delete pod --namespace kube-system -l k8s-app=kube-dns

Oracle Cloud Infrastructure DNSを使用するためのExternalDNSの構成

ExternalDNSは、Kubernetesの外部にあるDNSプロバイダにサービスのDNSレコードを作成できるKubernetesのアドオンです。外部DNSプロバイダでDNSレコードを設定して、そのDNSプロバイダを介してKubernetesサービスを検出可能にし、DNSレコードを動的に制御できるようにします。詳細は、ExternalDNSを参照してください。

ExternalDNSをクラスタにデプロイした後、external-dns.alpha.kubernetes.io/hostname注釈をサービスに追加することで、クラスタで実行されているサービスを公開できます。ExternalDNSは、クラスタ用に構成した外部DNSプロバイダにサービスのDNSレコードを作成します。

ExternalDNS自体は、CoreDNSのようなDNSサーバーではなく、他の外部DNSプロバイダを構成する方法です。Oracle Cloud Infrastructure DNSは、そのような外部DNSプロバイダの一種です。DNSの概要を参照してください。

便宜上、クラスタにExternalDNSを設定し、Oracle Cloud Infrastructure DNSを使用するように構成する手順を次に示します。これらの手順は、GitHubで入手可能なSetting up ExternalDNS for Oracle Cloud Infrastructure (OCI) tutorialに基づいたサマリーです。

クラスタでExternalDNSを設定し、Oracle Cloud Infrastructure DNSを使用するように構成するには:

  1. Oracle Cloud Infrastructure DNSに新しいDNSゾーンを作成して、ExternalDNSがクラスタ用に作成するDNSレコードを含めます。「ゾーンの作成」を参照してください。
  2. まだ実行していない場合は、ステップに従って、クラスタのkubeconfig構成ファイルを設定し、(必要に応じて)そのファイルを指すようにKUBECONFIG環境変数を設定します。自分のkubeconfigファイルを設定する必要があります。別のユーザーが設定したkubeconfigファイルを使用してクラスタにアクセスすることはできません。クラスタ・アクセスの設定を参照してください。
  3. 作成したDNSゾーンにDNSレコードを挿入および更新するためにOracle Cloud Infrastructure APIに接続する際に使用する、ExternalDNSのOracle Cloud Infrastructureユーザー認証の詳細を含むKubernetesシークレットを作成します。
    1. テキスト・エディタで、DNSゾーンへのアクセスに使用するOracle Cloud Infrastructureユーザー資格証明を含む資格証明ファイルを作成します:
      auth:
        region: <region-identifier>
        tenancy: <tenancy-ocid>
        user: <user-ocid>
        key: |
          -----BEGIN RSA PRIVATE KEY-----
         <private-key>
          -----END RSA PRIVATE KEY-----
        fingerprint: <fingerprint>
        # Omit if there is not a password for the key
        passphrase: <passphrase>
      compartment: <compartment-ocid>

      ここでは:

      • <region-identifer>は、ユーザーのリージョンを識別します。たとえば、us-phoenix-1です
      • <tenancy-ocid>は、ユーザーのテナンシのOCIDです。たとえば、ocid1.tenancy.oc1..aaaaaaaap...keqです(読みやすさのために省略しています)。
      • <user-ocid>は、ユーザーのOCIDです。たとえば、ocid1.user.oc1..aaaaa...zutq (読みやすさのために省略)です。
      • <private-key>はRSAキーで、-----BEGIN RSA PRIVATE KEY-----で始まり、-----END RSA PRIVATE KEY-----で終わります
      • passphrase: <passphrase>はオプションで、キーのパスフレーズを指定します(存在する場合)
      • <compartment-ocid>は、DNSゾーンが属するコンパートメントのOCIDです
      例:
      auth:
        region: us-phoenix-1
        tenancy: ocid1.tenancy.oc1..aaaaaaaap...keq
        user: ocid1.user.oc1..aaaaa...zutq
        key: |
          -----BEGIN RSA PRIVATE KEY-----
          this-is-not-a-secret_Ef8aiAk7+I0...
          -----END RSA PRIVATE KEY-----
        fingerprint: bg:92:82:9f...
        # Omit if there is not a password for the key
        passphrase: Uy2kSl...
      compartment: ocid1.compartment.oc1..aaaaaaaa7______ysq
    2. 選択した名前で資格証明ファイルを保存します(例: oci-creds.yaml)。
    3. 次のように入力して、作成した資格証明ファイルからKubernetesシークレットを作成します:
      kubectl create secret generic <secret-name> --from-file=<credential-filename>

      例:

      kubectl create secret generic external-dns-config --from-file=oci-creds.yaml
  4. クラスタにExternalDNSをデプロイします。
    1. テキスト・エディタで、構成ファイル(external-dns-deployment.yamlなど)を作成してExternalDNSデプロイメントを作成し、先ほど作成したKubernetesシークレットの名前を指定します。例:
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: external-dns
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: external-dns
      rules:
      - apiGroups: [""]
        resources: ["services","endpoints","pods"]
        verbs: ["get","watch","list"]
      - apiGroups: ["extensions","networking.k8s.io"]
        resources: ["ingresses"]
        verbs: ["get","watch","list"]
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["list"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: external-dns-viewer
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: external-dns
      subjects:
      - kind: ServiceAccount
        name: external-dns
        namespace: default
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: external-dns
      spec:
        strategy:
          type: Recreate
        selector:
          matchLabels:
            app: external-dns
        template:
          metadata:
            labels:
              app: external-dns
          spec:
            serviceAccountName: external-dns
            containers:
            - name: external-dns
              image: k8s.gcr.io/external-dns/external-dns:v0.7.3
              args:
              - --source=service
              - --source=ingress
              - --provider=oci
              - --policy=upsert-only # prevent ExternalDNS from deleting any records, omit to enable full synchronization
              - --txt-owner-id=my-identifier
              volumeMounts:
                - name: config
                  mountPath: /etc/kubernetes/
            volumes:
            - name: config
              secret:
                secretName: external-dns-config
    2. 構成ファイルを保存して閉じます。
    3. 次のように入力して、構成ファイルを適用し、ExternalDNSをデプロイします:
      kubectl apply -f <filename>

      <filename>は、以前に作成したファイルの名前です。例:

      kubectl apply -f external-dns-deployment.yaml

      前述のコマンドの出力により、デプロイメントが確認されます:

      serviceaccount/external-dns created
      clusterrole.rbac.authorization.k8s.io/external-dns created
      clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
      deployment.apps/external-dns created
      
  5. ExternalDNSが正常にデプロイされ、nginxデプロイメントおよびnginxサービスを作成して、Oracle Cloud Infrastructureで以前に作成したDNSゾーンにレコードを挿入できることを確認します:
    1. テキスト・エディタで、構成ファイル(nginx-externaldns.yamlなど)を作成して、nginxデプロイメントと、external-dns.alpha.kubernetes.io/hostname注釈を含むnginxサービスを作成します。例:
      apiVersion: v1
      kind: Service
      metadata:
        name: nginx
        annotations:
          external-dns.alpha.kubernetes.io/hostname: example.com
      spec:
        type: LoadBalancer
        ports:
        - port: 80
          name: http
          targetPort: 80
        selector:
          app: nginx
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx
      spec:
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - image: nginx
              name: nginx
              ports:
              - containerPort: 80
                name: http
    2. 次のように入力して、構成ファイルを適用し、nginxサービスおよびデプロイメントを作成します:
      kubectl apply -f <filename>

      <filename>は、以前に作成したファイルの名前です。例:

      kubectl apply -f nginx-externaldns.yaml

      前述のコマンドの出力により、デプロイメントが確認されます:

      service/nginx created
      deployment.apps/nginx created
      
    3. 数分待って、Oracle Cloud Infrastructure DNSゾーンでnginxサービスのDNSレコードが作成されたことを確認します(ゾーンを参照)。