デジタルオーシャンの Kubernetes 上で Helm を使用して Nginx Ingress をセットアップする方法
著者は、Write for Donationsプログラムの一環として寄付をするために、フリー&オープンソース基金を選びました。
はじめに
KubernetesのIngressは、クラスターの外部から内部のKubernetesサービスへトラフィックをルーティングする柔軟な方法を提供します。Ingressリソースは、HTTPおよびHTTPSトラフィックをサービスへルーティングするためのルールを定義するKubernetes内のオブジェクトです。これらが機能するためには、トラフィックを受け入れて適切なサービスへルーティングするルールを実装するIngressコントローラーが存在する必要があります(ほとんどの場合、ロードバランサーを介して最も可能性があります)。ほとんどのIngressコントローラーでは、すべてのIngressに対して1つのグローバルなロードバランサーのみを使用しており、公開したいサービスごとにロードバランサーを作成するより効率的です。
HelmはKubernetesのパッケージマネージャーです。KubernetesとHelm Chartsを使用することで、Kubernetesアプリケーションの設定とライフサイクル管理を行い、アップデート、ロールバック、削除が可能となります。
このガイドでは、Helmを使用して、Kubernetesが管理するNginx Ingress Controllerをセットアップします。その後、Ingressリソースを作成して、ドメインからHello Worldバックエンドサービスへのトラフィックをルーティングします。Ingressを設定したら、クラスタにCert Managerをインストールして、Ingressを保護するためにLet’s Encrypt TLS証明書を自動的に提供します。
もし、マネージドKubernetesホスティングサービスをお探しであれば、成長を重視した当社のシンプルでマネージドなKubernetesサービスをご覧ください。
前提条件
- A Kubernetes cluster above version 1.20, set up with your connection configuration configured as the kubectl default. This setup will use a Silicon Cloud Kubernetes cluster with three nodes, but you could also create a cluster manually. To create a Kubernetes cluster in the Silicon Cloud Cloud Panel, see our Kubernetes Quickstart.
- The kubectl command-line tool installed in your local environment and configured to connect to your cluster. You can read more about installing kubectl in the official documentation. If you are using a Silicon Cloud Kubernetes cluster, instructions on how to configure kubectl are in the Connect to your Cluster section when you create your cluster, and you can also refer to the How to Connect to a Silicon Cloud Kubernetes Cluster docs.
- The Silicon Cloud command-line client, doctl, installed on your machine. See How To Use doctl for more information on using doctl.
- The Helm 3 package manager available in your development environment. Complete Step 1 of the How To Install Software on Kubernetes Clusters with the Helm 3 Package Manager tutorial.
- A fully registered domain name with two available A records. This tutorial will use hw1.your_domain and hw2.your_domain throughout. You can purchase a domain name on Namecheap, get one for free on Freenom, or use the domain registrar of your choice. These A records will be directed to a Load Balancer that you will create in Step 2.
ステップ1 – HelloWorldの展開設定
Nginx Ingressをデプロイする前に、トラフィックをルーティングするためのいくつかのサービスが必要なので、「Hello World」というアプリケーションのhello-kubernetesをデプロイします。次のステップでNginx Ingressが正常に機能していることを確認するために、異なるウェルカムメッセージで2回デプロイします。ブラウザからアクセスした際に表示されるメッセージが異なります。
デプロイメントの設定をローカルマシンに保存します。もしご希望であれば、このチュートリアルのためにディレクトリを作成し、設定をそこに保存することもできます。最初のデプロイメント設定は、hello-kubernetes-first.yamlというファイルに保存されます。お好きなテキストエディタで作成してください。
- nano 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.10
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
-fオプションは、createコマンドがファイルhello-kubernetes-first.yamlを使用するよう指示します。
以下の出力を受け取ります。
service/hello-kubernetes-first created deployment.apps/hello-kubernetes-first created
サービスの作成を確認するために、次のコマンドを実行してください。
- kubectl get service hello-kubernetes-first
以下が出力結果となります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-kubernetes-first ClusterIP 10.245.124.46 <none> 80/TCP 7s
新しく作成されたServiceには、ClusterIPが割り当てられているため、正常に動作していることがわかります。それに送信されたすべてのトラフィックは、ポート8080で選択されたDeploymentに転送されます。今はhello-kubernetesアプリの最初のバリアントを展開したため、2番目のバリアントに取り組むことになります。
こんにちは、kubernetes-second.yamlという名前の新しいファイルを作成してください。
- nano 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.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: Hello from the second deployment!
このバリアントは、以前の構成と同じ構造を持っています。衝突を避けるために、デプロイメントとサービスの名前を変更します。また、ブラウザにロードされるメッセージの値も更新します。
ファイルを保存して閉じてください。 (Fairu o hozon shite tojite kudasai.)
以下のコマンドを使用して、Kubernetesでそれを作成してください。
- kubectl create -f hello-kubernetes-second.yaml
出力は次のようになります。
service/hello-kubernetes-second created deployment.apps/hello-kubernetes-second created
自分の全てのサービスをリストアップし、第二のサービスが正常に動作しているかを確認してください。
- kubectl get service
出力結果は、これに似るようになります。
NAME 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
ハロー・クーバネティスファーストとハロー・クーバネティスセカンドが両方リストに掲載されているため、Kubernetesはこれらを正常に作成しました。
「hello-kubernetes」アプリのデプロイメントを2つ作成し、それに関連するサービスも作成しました。各デプロイメントの仕様で異なるメッセージを設定することで、テスト時に区別します。次のステップでは、Nginx Ingress Controllerをインストールします。
ステップ2 — KubernetesのNginx Ingress Controllerのインストール
今度は、Helmを使用してKubernetesがメンテナンスするNginx Ingress Controllerをインストールします。
Nginx Ingress ControllerはPodとServiceで構成されています。PodはControllerを実行し、クラスターのAPIサーバーの/ingressesエンドポイントを定期的にポーリングして利用可能なIngressリソースの更新を確認します。ServiceはLoadBalancerタイプです。Silicon CloudのKubernetesクラスターにデプロイするため、クラスターは自動的にSilicon Cloudロードバランサーを作成し、外部トラフィックをControllerに流します。Controllerはその後、Ingressリソースで定義された適切なServiceにトラフィックをルーティングします。
自動的に作成されたロードバランサーのIPアドレスは、LoadBalancerサービスだけが知っています。一部のアプリ(ExternalDNSなど)は、そのIPアドレスを知る必要がありますが、Ingressの構成しか読み取ることができません。Controllerは、helm install中に controller.publishService.enabled パラメータをtrueに設定することで、各IngressにIPアドレスを公開するように構成できます。ロードバランサーのIPアドレスに依存する可能性があるアプリケーションをサポートするために、この設定を有効にすることが推奨されています。
クラスターにNginx Ingress Controllerをインストールするには、まずHelmにそのリポジトリを追加する必要があります。次のコマンドを実行してください。
- helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
結果は、以下の通りになります。
“ingress-nginx” has been added to your repositories
システムをアップデートして、Helmに含まれている内容を知らせてください。
- helm repo update
ロードするのに少し時間がかかるかもしれません。
Hang tight while we grab the latest from your chart repositories… …Successfully got an update from the “ingress-nginx” chart repository Update Complete. ⎈Happy Helming!⎈
最後に、次のコマンドを実行してNginx Ingressをインストールしてください。
- helm install nginx-ingress ingress-nginx/ingress-nginx –set controller.publishService.enabled=true
このコマンドは、stableチャートリポジトリからNginx Ingress Controllerをインストールし、Helmリリースをnginx-ingressと名付け、publishServiceパラメータをtrueに設定します。
一度実行されると、次のような出力が受け取れます(この出力は省略されています)。
NAME: nginx-ingress LAST DEPLOYED: Thu Dec 1 11:40:28 2022 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: …
ヘルムは、チャートのインストールの一部として、Kubernetesで作成されたリソースを記録しました。
「ロードバランサーが利用可能になるまで、次のコマンドを実行してください。」
- kubectl –namespace default get services -o wide -w nginx-ingress-ingress-nginx-controller
このコマンドはデフォルトの名前空間にあるNginx Ingressサービスを取得し、その情報を出力しますが、コマンドはすぐに終了しません。-w引数を使用すると、変更が発生した際に出力を監視して更新します。
ロードバランサが利用可能になるまで待っている間に、保留中の応答を受け取ることがあります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR nginx-ingress-ingress-nginx-controller LoadBalancer 10.245.3.122 <pending> 80:30953/TCP,443:30869/TCP 36s …
しばらく時間が経った後、新しく作成したロードバランサーのIPアドレスが表示されます。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR nginx-ingress-ingress-nginx-controller LoadBalancer 10.245.3.122 167.99.16.184 80:30953/TCP,443:30869/TCP 2m29s …
次に、2つのドメインがAレコード経由でロードバランサーに指し示されていることを確認する必要があります。これは、DNSプロバイダーを通じて行われます。Silicon CloudでDNSレコードを設定するには、「DNSレコードの管理方法」を参照してください。
あなたはKubernetesコミュニティによって管理されているNginx Ingressをインストールしました。それは、ロードバランサーからIngressリソースで設定された適切なバックエンドサービスへのHTTPおよびHTTPSトラフィックをルーティングします。次のステップでは、Ingressリソースを使用してhello-kubernetesアプリの展開を公開します。
ステップ3 — Ingressを使用してアプリを公開する。
あなたは今、Ingressリソースを作成し、それを使用してhello-kubernetesアプリのデプロイを希望するドメインで公開します。それをブラウザからアクセスしてテストします。
エディタを使用して、Ingressをhello-kubernetes-ingress.yamlという名前のファイルに保存します。
- nano 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
ハロークベルネティスイングレスという名前のイングレスリソースを定義します。そして、hw1.your_domainがハロークベルネティスの最初のサービスに、hw2.your_domainがセカンドの展開(hello-kubernetes-second)のサービスにルーティングされるように、2つのホストルールを指定します。
ハイライトされたドメインをお客様自身のもので置き換えてから、ファイルを保存して閉じることを忘れずにお願いします。
以下のコマンドを実行して、Kubernetesで作成してください。
- kubectl apply -f hello-kubernetes-ingress.yaml
ブラウザでhw1.your_domainに移動できます。最初のデプロイメントがロードされます。
第2のバリアント(hw2.your_domain)は、異なるメッセージが表示されます。
あなたは、この場合において、あなたの2つのドメインから2つの異なるサービスへのリクエストを正しくルーティングするIngress Controllerが動作していることを確認しました。
あなたは、ドメイン上でhello-kubernetesアプリの展開を提供するために、Ingressリソースを作成し設定しました。次のステップでは、Cert-Managerをセットアップして、Let’s Encryptから無料のTLS証明書でIngressリソースを安全に保護します。
ステップ4 — Cert-Managerを使用してイングレスを保護する
あなたの Ingress リソースを保護するために、Cert-Manager をインストールし、本番用の ClusterIssuer を作成し、Ingress の設定を変更して TLS 証明書を使用します。インストールと設定が完了すると、あなたのアプリケーションはHTTPSで実行されます。
ClusterIssuersは、Kubernetes内のCert-Managerリソースであり、クラスタ全体のTLS証明書を提供します。ClusterIssuerは、特定のタイプのIssuerです。
Helmを使用してCert-Managerをクラスターにインストールする前に、それに対して名前空間を作成します。
- kubectl create namespace cert-manager
以下のコマンドを実行して、Cert-Managerのチャートを配布しているJetstack HelmリポジトリをHelmに追加する必要があります。
- helm repo add jetstack https://charts.jetstack.io
ヘルムは、次の出力を返します。
“jetstack” has been added to your repositories
それから、Helmのチャートキャッシュを更新してください。
- helm repo update
アップデートには少し時間がかかるかもしれません。
Hang tight while we grab the latest from your chart repositories… …Successfully got an update from the “ingress-nginx” chart repository …Successfully got an update from the “jetstack” chart repository Update Complete. ⎈Happy Helming!⎈
最後に、次のコマンドを実行して、Cert-Managerをcert-managerの名前空間にインストールしてください。
- helm install cert-manager jetstack/cert-manager –namespace cert-manager –version v1.10.1 –set installCRDs=true
このコマンドでは、Helmのインストール中にcert-managerのCustomResourceDefinitionマニフェストをインストールするために、installCRDsパラメータをtrueに設定します。執筆時点では、最新バージョンはv1.10.1でした。最新バージョン番号を確認するために、ArtifactHubを参照することができます。
以下の出力を受け取ります。 (Anata wa kōnyū o uketorimasu)
NAME: cert-manager LAST DEPLOYED: Wed Nov 30 19:46:39 2022 NAMESPACE: cert-manager STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: cert-manager v1.10.1 has been deployed successfully! …
出力結果には、インストールが成功したことが示されています。
上記の表示で切り詰められた出力のノートによると、TLS証明書を発行するためにIssuerを設定する必要があると述べています。
今、Let’s Encrypt証明書を発行するプログラムを作成し、その設定をproduction_issuer.yamlというファイルに保存します。このファイルを作成し、開いてください。
- nano production_issuer.yaml
以下の行を追加してください。 (I just added the lines natively in Japanese)
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’s Encryptに接続するClusterIssuerを定義しています。証明書のセキュリティや期限に関する通知を受け取るために、your_email_addressをご自身のメールアドレスに置き換える必要があります。
保存してファイルを閉じてください。
kubectlを使用して展開してください。
- kubectl apply -f production_issuer.yaml
以下の出力を受け取ります。
clusterissuer.cert-manager.io/letsencrypt-prod created
Cert-Managerをインストールしたら、前のステップで定義したIngressリソースに証明書を導入する準備が整いました。編集するためにhello-kubernetes-ingress.yamlを開いてください。
- nano 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 ブロックは、letsencrypt-prod ClusterIssuer が発行するサイト(hosts の下にリストされている)の証明書を Secret が保存する方法を定義しています。secretName は作成する Ingress ごとに異なっている必要があります。
以下の要素を自分自身のドメイン(例:hw1.your_domain、hw2.your_domain)に置き換えることを忘れないでください。編集が終わったら、ファイルを保存して閉じてください。
以下のコマンドを実行して、この設定をクラスターに再適用してください。
- kubectl apply -f hello-kubernetes-ingress.yaml
次の出力を受け取ります。
ingress.networking.k8s.io/hello-kubernetes-ingress configured
「あなたのドメインのために証明書を発行するために、数分間お待ちいただく必要があります。その間、以下のコマンドの出力を調べることで進捗状況を追跡できます。」
- kubectl describe certificate hello-kubernetes-tls
出力の結果は、おおよそ以下のようになるでしょう。
Events: Type Reason Age From Message —- —— —- —- ——- Normal Issuing 2m34s cert-manager-certificates-trigger Issuing certificate as Secret does not exist Normal Generated 2m34s cert-manager-certificates-key-manager Stored new private key in temporary Secret resource “hello-kubernetes-tls-hxtql” Normal Requested 2m34s cert-manager-certificates-request-manager Created new CertificateRequest resource “hello-kubernetes-tls-jnnwx” Normal Issuing 2m7s cert-manager-certificates-issuing The certificate has been successfully issued
出力の最後の行に「証明書が正常に発行されました」と表示されたら、[CTRL + C]を押して終了できます。
ブラウザで自分のドメインのいずれかに移動してください。すると、URLの隣にパッドロックが表示され、接続が安全になったことを示しています。
この手順では、Helmを使用してCert-Managerをインストールし、Let’s Encrypt ClusterIssuerを作成しました。次に、TLS証明書を生成するためにIssuerを活用するために、Ingressリソースを更新しました。結果的に、ブラウザで自分のドメインの1つに移動することで、HTTPSが正しく動作することを確認しました。
結論
現在、Helmを使用してSilicon Cloud KubernetesクラスタにNginx Ingress ControllerとCert-Managerを正常にセットアップしました。Let’s EncryptのTLS証明書を使用して、自分のドメイン上でアプリケーションをインターネットに公開することができるようになりました。
Helmパッケージマネージャーに関する詳細情報は、このHelmの概要を読んでください。