著者はhttps://www.brightfunds.org/funds/foss-nonprofits [無料およびオープンソース基金]を選択して、https://do.co/w4do-cta [Donationsのために書く]の一部として寄付を受け取りましたプログラム。

前書き

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

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

このガイドでは、Helmを使用してKubernetesが管理するhttps://github.com/kubernetes/ingress-nginx[Nginx Ingress Controller]をセットアップします。 次に、ドメインからのトラフィックをサンプルのHello WorldバックエンドサービスにルーティングするIngressリソースを作成します。 Ingressをセットアップしたら、https://github.com/jetstack/cert-manager [Cert-Manager]をクラスターにインストールして、Let ‘Encrypt TLS証明書を自動的にプロビジョニングしてIngressを保護できるようにします。

前提条件

  • 接続設定が `+ kubectl `デフォルトとして設定されたDigitalOcean Kubernetesクラスター。 ` kubectl +`の設定方法については、クラスターを作成するときに表示される[クラスターに接続]ステップの下に表示されます。 DigitalOceanでKubernetesクラスターを作成する方法については、https://www.digitalocean.com/docs/kubernetes/quickstart/ [Kubernetes Quickstart]を参照してください。

  • ローカルマシンにインストールされたHelmパッケージマネージャー、およびクラスターにインストールされたTiller。 https://www.digitalocean.com/community/tutorials/how-to-install-software-on-kubernetes-clusters-with-the-helm-package-manager [ソフトウェアのインストール方法]のステップ1と2を完了します。 Helm Package Managerを使用したKubernetesクラスター]チュートリアル。

  • 2つの使用可能なAレコードを持つ完全に登録されたドメイン名。 このチュートリアルでは、全体で「」と「」を使用します。 Namecheapでドメイン名を購入するか、https://www.freenom.com/en/index.html?lang = en [Freenom]で無料で入手できます。または選択したドメインレジストラーを使用します。

手順1-Hello World展開のセットアップ

このセクションでは、Nginx Ingressをデプロイする前に、https://hub.docker.com/r/paulbouwer/hello-kubernetes/ [+ hello-kubernetes +]というHello Worldアプリをデプロイして、トラフィックをルーティングします。 次の手順で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.5
       ports:
       - containerPort: 8080
       env:
       - name: MESSAGE
         value: Hello from the first deployment!

この構成は、展開とサービスを定義します。 デプロイメントは、「+ paulbouwer / hello-kubernetes:1.5+」イメージの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      <none>        80:31623/TCP   35s

新しく作成されたサービスには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.5
       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          <none>          80:31623/TCP                 54s
hello-kubernetes-second         ClusterIP          <none>          80:30303/TCP                 12s
kubernetes                      ClusterIP             <none>          443/TCP                      5m

`+ hello-kubernetes-first `と ` hello-kubernetes-second +`の両方がリストされます。これは、Kubernetesがそれらを正常に作成したことを意味します。

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

ステップ2-Kubernetes Nginx Ingress Controllerのインストール

次に、Helmを使用してKubernetes-maintained Nginx Ingress Controllerをインストールします。 いくつかのhttps://github.com/nginxinc/kubernetes-ingress/blob/master/docs/nginx-ingress-controllers.md[Nginx Ingresses]があることに注意してください。

Nginx Ingress Controllerは、ポッドとサービスで構成されています。 Podはコントローラーを実行します。コントローラーは、使用可能なIngressリソースの更新のために、クラスターのAPIサーバー上の「+ / ingresses +」エンドポイントを常にポーリングします。 サービスのタイプはLoadBalancerであり、これをDigitalOcean Kubernetesクラスターにデプロイしているため、クラスターはhttps://www.digitalocean.com/products/load-balancer/[DigitalOcean Load Balancer]を自動的に作成します。外部トラフィックはコントローラーに流れます。 コントローラは、入力リソースで定義されているように、適切なサービスにトラフィックをルーティングします。

LoadBalancerサービスのみが、自動的に作成されたロードバランサーのIPアドレスを知っています。 一部のアプリ(https://github.com/kubernetes-incubator/external-dns[ExternalDNS]など)はIPアドレスを知る必要がありますが、Ingressの設定のみを読み取ることができます。 Controllerは、「+ helm install 」中に「 controller.publishService.enabled 」パラメーターを「 true +」に設定することで、各イングレスでIPアドレスを公開するように設定できます。 ロードバランサーのIPアドレスに依存する可能性のあるアプリケーションをサポートするには、この設定を有効にすることをお勧めします。

Nginx Ingress Controllerをクラスターにインストールするには、次のコマンドを実行します。

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

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

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

OutputNAME:   nginx-ingress
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                      DATA  AGE
nginx-ingress-controller  1     0s

==> v1/Pod(related)
NAME                                            READY  STATUS             RESTARTS  AGE
nginx-ingress-controller-7658988787-npv28       0/1    ContainerCreating  0         0s
nginx-ingress-default-backend-7f5d59d759-26xq2  0/1    ContainerCreating  0         0s

==> v1/Service
NAME                           TYPE          CLUSTER-IP     EXTERNAL-IP  PORT(S)                     AGE
nginx-ingress-controller       LoadBalancer  10.245.9.107   <pending>    80:31305/TCP,443:30519/TCP  0s
nginx-ingress-default-backend  ClusterIP     10.245.221.49  <none>       80/TCP                      0s

==> v1/ServiceAccount
NAME           SECRETS  AGE
nginx-ingress  1        0s

==> v1beta1/ClusterRole
NAME           AGE
nginx-ingress  0s

==> v1beta1/ClusterRoleBinding
NAME           AGE
nginx-ingress  0s

==> v1beta1/Deployment
NAME                           READY  UP-TO-DATE  AVAILABLE  AGE
nginx-ingress-controller       0/1    1           0          0s
nginx-ingress-default-backend  0/1    1           0          0s

==> v1beta1/Role
NAME           AGE
nginx-ingress  0s

==> v1beta1/RoleBinding
NAME           AGE
nginx-ingress  0s

NOTES:
...

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

以下を実行することにより、Load Balancerが利用可能になるのを見ることができます。

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

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

ステップ3-Ingressを使用してアプリを公開する

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

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

nano hello-kubernetes-ingress.yaml

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

hello-kubernetes-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: hello-kubernetes-ingress
 annotations:
   kubernetes.io/ingress.class: nginx
spec:
 rules:
 - host:
   http:
     paths:
     - backend:
         serviceName: hello-kubernetes-first
         servicePort: 80
 - host:
   http:
     paths:
     - backend:
         serviceName: hello-kubernetes-second
         servicePort: 80

上記のコードでは、 `+ hello-kubernetes-ingress `という名前のIngressリソースを定義します。 次に、2つのホストルールを指定して、 “が `+ hello-kubernetes-first +`サービスにルーティングされ、 “が2番目のデプロイからサービスにルーティングされるようにします( ` hello-kubernetes-second + `)。

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

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

kubectl create -f hello-kubernetes-ingress.yaml

次に、2つのドメインがAレコードを介してロードバランサーを指していることを確認する必要があります。 これは、DNSプロバイダーを介して行われます。 DigitalOceanでDNSレコードを構成するには、https://www.digitalocean.com/docs/networking/dns/how-to/manage-records/ [DNSレコードの管理方法]を参照してください。

ブラウザで「++」に移動できるようになりました。 以下が表示されます。

image:https://assets.digitalocean.com/articles/nginx_ingress_helm/step3a.png [Hello Kubernetes-最初の展開]

2番目のバリアント( ++)は異なるメッセージを表示します:

image:https://assets.digitalocean.com/articles/nginx_ingress_helm/step3b.png [Hello Kubernetes-2番目の展開]

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

ドメインで「+ hello-kubernetes +」アプリの展開を提供するIngressリソースを作成して設定しました。 次のステップでは、Cert-Managerをセットアップします。これにより、Let’s Encryptからの無料のTLS証明書でIngressリソースを保護できます。

ステップ4-Cert-Managerを使用してイングレスを保護する

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

Helmを介してクラスターにCert-Managerをインストールする前に、必要なhttps://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/[CRDs](カスタムリソース定義)を手動で適用します次のコマンドを実行して、jetstack / cert-managerリポジトリから:

kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml

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

Outputcustomresourcedefinition.apiextensions.k8s.io/certificates.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/challenges.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/issuers.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/orders.certmanager.k8s.io created

これは、Kubernetesがcert-managerに必要なカスタムリソースを適用したことを示しています。

次に、Cert-ManagerチャートをホストするHelmにhttps://charts.jetstack.io [Jetstack Helm repository]を追加する必要があります。 これを行うには、次のコマンドを実行します。

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

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

Output"jetstack" has been added to your repositories

最後に、Cert-Managerを `+ cert-manager`名前空間にインストールします:

helm install --name cert-manager --namespace cert-manager jetstack/cert-manager

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

OutputNAME:   cert-manager
LAST DEPLOYED: ...
NAMESPACE: cert-manager
STATUS: DEPLOYED

RESOURCES:
==> v1/ClusterRole
NAME                                    AGE
cert-manager-edit                       3s
cert-manager-view                       3s
cert-manager-webhook:webhook-requester  3s

==> v1/Pod(related)
NAME                                     READY  STATUS             RESTARTS  AGE
cert-manager-5d669ffbd8-rb6tr            0/1    ContainerCreating  0         2s
cert-manager-cainjector-79b7fc64f-gqbtz  0/1    ContainerCreating  0         2s
cert-manager-webhook-6484955794-v56lx    0/1    ContainerCreating  0         2s

...

NOTES:
cert-manager has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://docs.cert-manager.io/en/latest/reference/issuers.html

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://docs.cert-manager.io/en/latest/reference/ingress-shim.html

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

Let’s Encrypt証明書を発行する証明書を作成し、その設定を `+ production_issuer.yaml +`という名前のファイルに保存します。 作成して編集用に開きます。

nano production_issuer.yaml

次の行を追加します。

production_issuer.yaml

apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
 name: letsencrypt-prod
spec:
 acme:
   # The ACME server URL
   server: https://acme-v02.api.letsencrypt.org/directory
   # Email address used for ACME registration
   email:
   # Name of a secret used to store the ACME account private key
   privateKeySecretRef:
     name: letsencrypt-prod
   # Enable the HTTP-01 challenge provider
   http01: {}

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

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

`+ kubectl +`でロールアウトします:

kubectl create -f production_issuer.yaml

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

Outputclusterissuer.certmanager.k8s.io/letsencrypt-prod created

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

nano hello-kubernetes-ingress.yaml

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

hello-kubernetes-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: hello-kubernetes-ingress
 annotations:
   kubernetes.io/ingress.class: nginx

spec:





 rules:
 - host: hw1.example.com
   http:
     paths:
     - backend:
         serviceName: hello-kubernetes-first
         servicePort: 80
 - host: hw2.example.com
   http:
     paths:
     - backend:
         serviceName: hello-kubernetes-second
         servicePort: 80

`+ spec `の下の ` tls `ブロックは、サイトの証明書( ` hosts +`の下にリストされている)がそれらの証明書を保存する秘密を定義します。 これは、作成するIngressごとに異なる必要があります。

`+ hw1.example.com `と ` hw2.example.com +`を自分のドメインに置き換えてください。 編集が終了したら、ファイルを保存して閉じます。

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

kubectl apply -f hello-kubernetes-ingress.yaml

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

Outputingress.extensions/hello-kubernetes-ingress configured

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

kubectl describe certificate letsencrypt-prod

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

OutputEvents:
 Type    Reason              Age   From          Message
 ----    ------              ----  ----          -------
 Normal  Generated           56s   cert-manager  Generated new private key
 Normal  GenerateSelfSigned  56s   cert-manager  Generated temporary self signed certificate
 Normal  OrderCreated        56s   cert-manager  Created Order resource "hello-kubernetes-1197334873"
 Normal  OrderComplete       31s   cert-manager  Order "hello-kubernetes-1197334873" completed successfully
 Normal  CertIssued          31s   cert-manager  Certificate issued successfully

出力の最後の行が「証明書が正常に発行されました」と表示されたら、「+ CTRL + C +」を押して終了できます。 ブラウザでドメインの1つに移動してテストします。 ブラウザのアドレスバーの左側に南京錠が表示され、接続が安全であることを示します。

この手順では、Helmを使用してCert-Managerをインストールし、Let’s Encrypt ClusterIssuerを作成しました。 その後、イングレスリソースを更新して、発行者を利用してTLS証明書を生成しました。 最後に、ブラウザでドメインの1つに移動して、HTTPSが正しく機能することを確認しました。

結論

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

Helmパッケージマネージャーの詳細については、https://www.digitalocean.com/community/tutorials/an-introduction-to-helm-the-package-manager-for-kubernetes [紹介記事]をご覧ください。