Helmを使用してDigitalOceanKubernetesでNginxIngressを設定する方法

提供:Dev Guides
移動先:案内検索

著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

序章

Kubernetes Ingresses は、クラスターを超えて内部のKubernetesサービスにトラフィックをルーティングする柔軟な方法を提供します。 Ingress Resources は、HTTPおよびHTTPSトラフィックをサービスにルーティングするためのルールを定義するKubernetesのオブジェクトです。 これらが機能するには、Ingress Controllerが存在する必要があります。 その役割は、トラフィックを受け入れ(ほとんどの場合ロードバランサーを介して)、適切なサービスにルーティングすることでルールを実装することです。 ほとんどのIngressControllerは、すべてのIngressに対して1つのグローバルロードバランサーのみを使用します。これは、公開するサービスごとにロードバランサーを作成するよりも効率的です。

Helm は、Kubernetesを管理するためのパッケージマネージャーです。 KubernetesでHelmChartsを使用すると、Kubernetesアプリケーションを更新、ロールバック、削除するための構成可能性とライフサイクル管理が提供されます。

このガイドでは、Helmを使用してKubernetesで管理されている Nginx IngressControllerをセットアップします。 次に、入力リソースを作成して、ドメインからのトラフィックをHelloWorldバックエンドサービスの例にルーティングします。 Ingressを設定したら、 Certificate Manager をクラスターにインストールして、Let'sEncryptTLS証明書を自動的にプロビジョニングしてIngressを保護できるようにします。

前提条件

  • 接続構成がkubectlデフォルトとして構成されているDigitalOceanKubernetes1.16+クラスター。 kubectlの構成方法については、クラスターの作成時に表示されるクラスターへの接続の手順を参照してください。 DigitalOceanでKubernetesクラスタを作成する方法については、 KubernetesQuickstartをご覧ください。
  • ローカルマシンにインストールされているHelm3パッケージマネージャー。 Helm 3 PackageManagerチュートリアルを使用してKubernetesクラスターにソフトウェアをインストールする方法のステップ1を完了します。
  • 2つの利用可能なAレコードを持つ完全に登録されたドメイン名。 このチュートリアルでは、全体を通してhw1.your_domainhw2.your_domainを使用します。 Namecheap でドメイン名を購入するか、 Freenom で無料でドメイン名を取得するか、選択したドメイン登録事業者を使用できます。

ステップ1—HelloWorldデプロイメントのセットアップ

このセクションでは、Nginx Ingressをデプロイする前に、 hello-kubernetesというHelloWorldアプリをデプロイして、トラフィックをルーティングするサービスをいくつか用意します。 次の手順でNginxIngressが正しく機能することを確認するために、Nginx Ingressを2回デプロイします。そのたびに、ブラウザーからアクセスしたときに表示される異なるウェルカムメッセージが表示されます。

展開構成をローカルマシンに保存します。 最初の展開構成は、hello-kubernetes-first.yamlという名前のファイルになります。 テキストエディタを使用して作成します。

nano hello-kubernetes-first.yaml

次の行を追加します。

hello-kubernetes-first.yaml

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes-first
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-kubernetes-first
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes-first
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes-first
  template:
    metadata:
      labels:
        app: hello-kubernetes-first
    spec:
      containers:
      - name: hello-kubernetes
        image: paulbouwer/hello-kubernetes:1.8
        ports:
        - containerPort: 8080
        env:
        - name: MESSAGE
          value: Hello from the first deployment!

この構成は、デプロイメントとサービスを定義します。 デプロイメントは、paulbouwer/hello-kubernetes:1.7イメージの3つのレプリカと、MESSAGEという名前の環境変数で構成されます。アプリにアクセスするとその値が表示されます。 ここでのサービスは、ポート80でクラスター内のデプロイメントを公開するように定義されています。

ファイルを保存して閉じます。

次に、次のコマンドを実行して、Kubernetesでhello-kubernetesアプリのこの最初のバリアントを作成します。

kubectl create -f hello-kubernetes-first.yaml

次の出力が表示されます。

Outputservice/hello-kubernetes-first created
deployment.apps/hello-kubernetes-first created

サービスの作成を確認するには、次のコマンドを実行します。

kubectl get service hello-kubernetes-first

出力は次のようになります。

OutputNAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
hello-kubernetes-first   ClusterIP   10.245.124.46   <none>        80/TCP    7s

新しく作成されたサービスにはClusterIPが割り当てられていることがわかります。これは、サービスが正しく機能していることを意味します。 そこに送信されたすべてのトラフィックは、ポート8080で選択されたデプロイメントに転送されます。 hello-kubernetesアプリの最初のバリアントをデプロイしたので、2番目のバリアントで作業します。

hello-kubernetes-second.yamlというファイルを編集用に開きます。

nano hello-kubernetes-second.yaml

次の行を追加します。

hello-kubernetes-second.yaml

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes-second
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-kubernetes-second
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes-second
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes-second
  template:
    metadata:
      labels:
        app: hello-kubernetes-second
    spec:
      containers:
      - name: hello-kubernetes
        image: paulbouwer/hello-kubernetes:1.8
        ports:
        - containerPort: 8080
        env:
        - name: MESSAGE
          value: Hello from the second deployment!

ファイルを保存して閉じます。

このバリアントは、前の構成と同じ構造を持っています。 唯一の違いは、衝突を回避するためのデプロイメント名とサービス名、およびメッセージです。

次のコマンドを使用して、Kubernetesで作成します。

kubectl create -f hello-kubernetes-second.yaml

出力は次のようになります。

Outputservice/hello-kubernetes-second created
deployment.apps/hello-kubernetes-second created

すべてのサービスを一覧表示して、2番目のサービスが稼働していることを確認します。

kubectl get service

出力は次のようになります。

OutputNAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
hello-kubernetes-first    ClusterIP   10.245.124.46    <none>        80/TCP    49s
hello-kubernetes-second   ClusterIP   10.245.254.124   <none>        80/TCP    10s
kubernetes                ClusterIP   10.245.0.1       <none>        443/TCP   65m

hello-kubernetes-firsthello-kubernetes-secondの両方が一覧表示されます。これは、Kubernetesがそれらを正常に作成したことを意味します。

hello-kubernetesアプリの2つのデプロイメントを、付随するサービスとともに作成しました。 それぞれにデプロイメント仕様に異なるメッセージセットがあり、テスト中にそれらを区別することができます。 次のステップでは、NginxIngressController自体をインストールします。

ステップ2— Kubernetes NginxIngressControllerをインストールする

次に、Helmを使用してKubernetesで管理されている Nginx IngressControllerをインストールします。 NginxIngressesがいくつかあることに注意してください。

Nginx Ingress Controllerは、ポッドとサービスで構成されています。 ポッドはコントローラーを実行します。コントローラーは、クラスターのAPIサーバー上の/ingressesエンドポイントを常にポーリングして、使用可能な入力リソースの更新を確認します。 サービスのタイプはLoadBalancerであり、DigitalOcean Kubernetesクラスターにデプロイしているため、クラスターは自動的に DigitalOcean Load Balancer を作成し、これを介してすべての外部トラフィックがコントローラーに流れます。 次に、コントローラは、入力リソースで定義されているように、トラフィックを適切なサービスにルーティングします。

LoadBalancerサービスのみが、自動的に作成されたロードバランサーのIPアドレスを認識します。 一部のアプリ( ExternalDNS など)はそのIPアドレスを知る必要がありますが、Ingressの構成のみを読み取ることができます。 helm install中にcontroller.publishService.enabledパラメーターをtrueに設定することにより、各入力でIPアドレスを公開するようにコントローラーを構成できます。 ロードバランサーのIPアドレスに依存する可能性のあるアプリケーションをサポートするには、この設定を有効にすることをお勧めします。

Nginx Ingress Controllerをクラスターにインストールするには、最初に次のコマンドを実行してリポジトリをHelmに追加する必要があります。

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

出力は次のようになります。

Output"ingress-nginx" has been added to your repositories

ヘルムに何が含まれているのかを知らせるために更新します。

helm repo update

最後に、次のコマンドを実行してNginx入力をインストールします。

helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.publishService.enabled=true

このコマンドは、stableチャートリポジトリからNginxIngress Controllerをインストールし、Helmリリースにnginx-ingressという名前を付け、publishServiceパラメーターをtrueに設定します。

出力は次のようになります。

OutputNAME: nginx-ingress
LAST DEPLOYED: Fri Apr  3 17:39:05 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
...

Helmは、チャートのインストールの一部として作成したKubernetesのリソースをログに記録しました。

次のコマンドを実行すると、ロードバランサーが使用可能になるのを確認できます。

kubectl --namespace default get services -o wide -w nginx-ingress-ingress-nginx-controller

Kubernetesコミュニティによって管理されているNginxIngressをインストールしました。 ロードバランサーからのHTTPおよびHTTPSトラフィックを、IngressResourcesで構成された適切なバックエンドサービスにルーティングします。 次のステップでは、Ingressリソースを使用してhello-kubernetesアプリのデプロイを公開します。

ステップ3—入力を使用してアプリを公開する

次に、入力リソースを作成し、それを使用して、目的のドメインでhello-kubernetesアプリの展開を公開します。 次に、ブラウザからアクセスしてテストします。

Ingressをhello-kubernetes-ingress.yamlという名前のファイルに保存します。 エディターを使用して作成します。

nano hello-kubernetes-ingress.yaml

次の行をファイルに追加します。

hello-kubernetes-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-kubernetes-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: "hw1.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-first
            port:
              number: 80
  - host: "hw2.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-second
            port:
              number: 80

hello-kubernetes-ingressという名前で入力リソースを定義します。 次に、2つのホストルールを指定して、hw1.your_domainhello-kubernetes-firstサービスにルーティングされ、hw2.your_domainが2番目の展開(hello-kubernetes-secondからサービスにルーティングされるようにします。 ])。

次に、2つのドメインがAレコードを介してロードバランサーを指していることを確認する必要があります。 これは、DNSプロバイダーを介して行われます。 DigitalOceanでDNSレコードを構成するには、DNSレコードの管理方法を参照してください。

強調表示されたドメインを独自のドメインに置き換えてから、ファイルを保存して閉じることを忘れないでください。

次のコマンドを実行して、Kubernetesで作成します。

kubectl apply -f hello-kubernetes-ingress.yaml

これで、ブラウザでhw1.your_domainに移動できます。 次のように表示されます。

2番目のバリアント(hw2.your_domain)は、別のメッセージを表示します。

これにより、IngressControllerがリクエストを正しくルーティングすることを確認しました。 この場合、2つのドメインから2つの異なるサービスへ。

ドメインでhello-kubernetesアプリのデプロイを提供するための入力リソースを作成して構成しました。 次のステップでは、Cert-Managerを設定して、Let'sEncryptからの無料のTLS証明書を使用してIngressリソースを保護できるようにします。

ステップ4—Cert-Managerを使用して入力を保護する

Ingressリソースを保護するには、Cert-Managerをインストールし、本番用のClusterIssuerを作成し、TLS証明書を利用するようにIngressの構成を変更します。 ClusterIssuersは、クラスター全体にTLS証明書をプロビジョニングするKubernetesのCert-Managerリソースです。 インストールして構成すると、アプリはHTTPSの背後で実行されます。

Helmを介してCert-Managerをクラスターにインストールする前に、次のコマンドを実行して、クラスターの名前空間を手動で作成します。

kubectl create namespace cert-manager

Jetstack Helmリポジトリを、Cert-ManagerチャートをホストするHelmに追加する必要があります。 これを行うには、次のコマンドを実行します。

helm repo add jetstack https://charts.jetstack.io

Helmは次の出力を表示します。

Output"jetstack" has been added to your repositories

次に、Helmのチャートキャッシュを更新します。

helm repo update

最後に、次のコマンドを実行して、Cert-Managerをcert-manager名前空間にインストールします。

helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.2.0 --set installCRDs=true

次の出力が表示されます。

OutputNAME: cert-manager
LAST DEPLOYED: Sun Dec 13 11:29:32 2020
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager has been deployed successfully!
...

出力は、インストールが成功したことを示しています。 出力のNOTESにリストされているように、TLS証明書を発行するために発行者を設定する必要があります。

次に、Let's Encrypt証明書を発行するファイルを作成し、その構成をproduction_issuer.yamlという名前のファイルに保存します。 それを作成し、編集のために開きます。

nano production_issuer.yaml

次の行を追加します。

Production_issuer.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # Email address used for ACME registration
    email: your_email_address
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Name of a secret used to store the ACME account private key
      name: letsencrypt-prod-private-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

この構成は、証明書を発行するためにLet'sEncryptに接続するClusterIssuerを定義します。 証明書のセキュリティと有効期限に関する緊急の通知を受け取るには、your_email_addressを自分のメールアドレスに置き換える必要があります。

ファイルを保存して閉じます。

kubectlで展開します。

kubectl apply -f production_issuer.yaml

次の出力が表示されます。

Outputclusterissuer.cert-manager.io/letsencrypt-prod created

Cert-Managerをインストールすると、前の手順で定義したIngressリソースに証明書を導入する準備が整います。 hello-kubernetes-ingress.yamlを開いて編集します。

nano hello-kubernetes-ingress.yaml

強調表示された行を追加します。

hello-kubernetes-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
annotations:
  kubernetes.io/ingress.class: nginx
  cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - hw1.your_domain
    - hw2.your_domain
    secretName: hello-kubernetes-tls
  rules:
  - host: "hw1.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-first
            port:
              number: 80
  - host: "hw2.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-second
            port:
              number: 80

specの下のtlsブロックは、サイトの証明書(hostsの下にリストされている)が証明書を格納するシークレットを定義します。これは、letsencrypt-prodClusterIssuerが発行します。 これは、作成するすべてのイングレスで異なる必要があります。

hw1.your_domainhw2.your_domainを独自のドメインに置き換えることを忘れないでください。 編集が終了したら、ファイルを保存して閉じます。

次のコマンドを実行して、この構成をクラスターに再適用します。

kubectl apply -f hello-kubernetes-ingress.yaml

次の出力が表示されます。

Outputingress.networking.k8s.io/hello-kubernetes-ingress configured

Let'sEncryptサーバーがドメインの証明書を発行するまで数分待つ必要があります。 それまでの間、次のコマンドの出力を調べることで、進行状況を追跡できます。

kubectl describe certificate hello-kubernetes-tls

出力の終わりは次のようになります。

OutputEvents:
  Type    Reason     Age   From          Message
  ----    ------     ----  ----          -------
  Normal  Issuing    26s   cert-manager  Issuing certificate as Secret does not exist
  Normal  Generated  26s   cert-manager  Stored new private key in temporary Secret resource "hello-kubernetes-tls2-nfsgp"
  Normal  Requested  26s   cert-manager  Created new CertificateRequest resource "hello-kubernetes-tls2-wzl8z"
  Normal  Issuing    24s   cert-manager  The certificate has been successfully issued

出力の最後の行がThe certificate has been successfully issuedになったら、CTRL + Cを押して終了できます。 ブラウザでドメインの1つに移動して、テストします。 ブラウザのアドレスバーの左側に南京錠があり、接続が安全であることを示しています。

このステップでは、Helmを使用してCert-Managerをインストールし、Let'sEncryptClusterIssuerを作成しました。 その後、TLS証明書を生成するために発行者を利用するように入力リソースを更新しました。 最後に、ブラウザでドメインの1つに移動することにより、HTTPSが正しく機能することを確認しました。

結論

これで、Helmを使用してDigitalOceanKubernetesクラスターにNginxIngressControllerとCert-Managerを正常にセットアップできました。 これで、Let's Encrypt TLS証明書を使用して保護された、ドメインでのアプリをインターネットに公開できるようになりました。

Helmパッケージマネージャーの詳細については、この紹介記事をお読みください。