例: クラスタでのNginxイングレス・コントローラの設定

Container Engine for Kubernetes (OKE)を使用して作成したクラスタでサンプルのNginxイングレス・コントローラを設定および使用する方法を確認します。

Kubernetesアプリケーション・トラフィックを管理するために、Container Engine for Kubernetesで作成したクラスタに様々なオープン・ソース・イングレス・コントローラを設定できます。

このトピックでは、サンプルのNginxイングレス・コントローラを、既存のクラスタ上の対応するアクセス制御とともに設定する方法について説明します。このトピックでは、イングレス・コントローラを設定した後、サンプルのhello-worldバックエンドでイングレス・コントローラを使用する方法と、イングレス・コントローラが期待どおりに動作していることを確認する方法について説明します。イングレス・コントローラの例を引き続き使用する場合は、アップグレード手順に従います。また、イングレス・コントローラの例をこれ以上使用しない場合、このトピックではその削除方法を示します。

サンプル・コンポーネント

例には、イングレス・コントローラおよびhello-worldバックエンドが含まれています。

イングレス・コントローラ・コンポーネント

イングレス・コントローラは次で構成されています:

  • ingress-nginx-controllerというイングレス・コントローラ・デプロイメント。このデプロイメントでは、イングレス・コントローラおよびNginxのバイナリを含むイメージがデプロイされます。バイナリは、イングレスがKubernetesで作成されるときに、/etc/nginx/nginx.conf構成ファイルを操作およびリロードします。Nginxアップストリームは、指定されたセレクタと一致するサービスを指します。
  • ingress-nginx-controllerというイングレス・コントローラ・サービス。このサービスでは、LoadBalancerタイプのサービスとしてイングレス・コントローラ・デプロイメントが公開されます。Container Engine for KubernetesOracle Cloud Infrastructure統合/クラウド・プロバイダを使用するため、ロード・バランサはバックエンド・セットとして構成された正しいノードを使用して動的に作成されます。

バックエンド・コンポーネント

hello-worldバックエンドは次で構成されています:

  • docker-hello-worldというバックエンド・デプロイメント。このデプロイメントでは、ヘルス・チェックと404レスポンスのデフォルト・ルートが処理されます。これは、デフォルトのバックエンドに最低限必要なルートを提供する標準hello-worldイメージを使用して行われます。
  • docker-hello-world-svcというバックエンド・サービス。このサービスは、イングレス・コントローラ・デプロイメントによる消費のバックエンド・デプロイメントを公開します。

サンプルのイングレス・コントローラの設定

この項では、イングレスのアクセス・ルールを作成します。次に、サンプルのイングレス・コントローラ・コンポーネントを作成し、それらが実行されていることを確認します。

イングレス・コントローラのアクセス・ルールの作成

  1. まだ実行していない場合は、ステップに従って、クラスタのkubeconfig構成ファイルを設定し、(必要に応じて)そのファイルを指すようにKUBECONFIG環境変数を設定します。自分のkubeconfigファイルを設定する必要があります。別のユーザーが設定したkubeconfigファイルを使用してクラスタにアクセスすることはできません。クラスタ・アクセスの設定を参照してください。
  2. Oracle Cloud Infrastructureユーザーがテナンシ管理者の場合は、次のステップをスキップして、イングレス・コントローラおよび関連するリソースのデプロイに進みます。
  3. Oracle Cloud Infrastructureユーザーがテナンシ管理者でない場合は、ターミナル・ウィンドウで、次のように入力して、クラスタでKubernetes RBAC cluster-admin clusterroleをユーザーに付与します:

    kubectl create clusterrolebinding <my-cluster-admin-binding> --clusterrole=cluster-admin --user=<user-OCID>

    ここでは:

    • <my-cluster-admin-binding>は、ユーザーとKubernetes RBAC cluster-admin clusterrole間のバインディングの名前として使用される選択した文字列です。たとえば、jdoe_clst_admです
    • <user-OCID>は、ユーザーのOCIDです(コンソールから取得)。たとえば、ocid1.user.oc1..aaaaa...zutq (読みやすさのために省略)です。

    例:

    kubectl create clusterrolebinding jdoe_clst_adm --clusterrole=cluster-admin --user=ocid1.user.oc1..aaaaa...zutq

イングレス・コントローラおよび関連リソースのデプロイ

イングレス・コントローラおよび関連リソース(Kubernetes RBACロールおよびバインディング、およびLoadBalancerタイプのingress-nginx-controllerイングレス・コントローラ・サービスを含む)をデプロイする方法は、管理対象/自己管理ノードを含むクラスタにデプロイするか、仮想ノードを含むクラスタにデプロイするかによって異なります。

  • 管理対象ノードおよび自己管理ノード

    Nginxイングレス・コントローラをデプロイするには、次のコマンドを実行します:

    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v<vnum>/deploy/static/provider/cloud/deploy.yaml

    <vnum>は、ingress-nginx-controllerイングレス・コントローラ・デプロイメント・スクリプトの最新バージョンのバージョン番号です。たとえば、書き込み時のスクリプトの最新バージョンにはバージョン番号1.1.3があるため、実行するコマンドは次のとおりです。

    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/cloud/deploy.yaml

    スクリプトの最新バージョンのバージョン番号を確認するには、GitHubのkubernetes/ingress-nginxのドキュメントを参照してください。

  • 仮想ノード

    仮想ノードでは、イングレス・コントローラのデプロイメント・マニフェストを変更し、fsgroupallowprivilegeEscalationおよびcapabilitiesセキュリティ・コンテキストをコメント・アウトする必要があります。このような変更されたデプロイメント・マニフェストの例は、https://github.com/oracle-devrel/oci-oke-virtual-nodes/tree/main/ingress-nginxを参照してください。

    この変更されたマニフェストに基づいてNginxイングレス・コントローラをデプロイするには、次のコマンドを実行します:

    kubectl apply -f https://raw.githubusercontent.com/oracle-devrel/oci-oke-virtual-nodes/main/ingress-nginx/deploy.yaml

ingress-nginx-controllerイングレス・コントローラ・サービスがLoad Balancerサービスとして実行中であることの確認

  1. 次のように入力して、実行中のサービスのリストを表示します:

    kubectl get svc -n ingress-nginx

    前述のコマンドの出力に、実行中のサービスが表示されます:

    
    NAME                       TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                       AGE
    ingress-nginx-controller   LoadBalancer   10.96.229.38   <pending>      80:30756/TCP,443:30118/TCP    1h
    

    ingress-nginx-controllerイングレス・コントローラ・サービスの外部IPは、ロード・バランサがOracle Cloud Infrastructureで完全に作成されるまで、<pending>として表示されます。

  2. ingress-nginx-controllerイングレス・コントローラ・サービスの外部IPが表示されるまで、kubectl get svcコマンドを繰り返します:

    kubectl get svc -n ingress-nginx
    

    前述のコマンドの出力は、ingress-nginx-controllerイングレス・コントローラ・サービスのEXTERNAL-IPを示しています:

    
    NAME                       TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)                       AGE
    ingress-nginx-controller   LoadBalancer   10.96.229.38   129.146.214.219   80:30756/TCP,443:30118/TCP    1h

TLSシークレットの作成

TLSシークレットは、イングレス・コントローラでのSSL終了に使用されます。

  1. 新しいキーをファイルに出力します。たとえば、次のように入力します:

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"

    この例のシークレットを生成するには、自己署名証明書が使用されます。これはテストでは問題ありませんが、本番環境では、認証局によって署名された証明書を使用してください。

    ノート

    Windowsでは、"/CN=nginxsvc/O=nginxsvc""//CN=nginxsvc\O=nginxsvc"に置き換えることが必要な場合があります。たとえば、これはGit Bashシェルからopensslコマンドを実行する場合に必要です。
  2. 次のように入力してTLSシークレットを作成します:

    kubectl create secret tls tls-secret --key tls.key --cert tls.crt

サンプルのバックエンドの設定

この項では、hello-worldバックエンド・サービスおよびデプロイメントを定義します。

docker-hello-worldサービス定義の作成

  1. 次のコードを含むファイルhello-world-ingress.yamlを作成します。このコードは、Docker Hubから公開されているhello-worldイメージを使用しています。同様の方法で実行できる、選択した別のイメージに置き換えることができます。

    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: docker-hello-world
      labels:
        app: docker-hello-world
    spec:
      selector:
        matchLabels:
          app: docker-hello-world
      replicas: 3
      template:
        metadata:
          labels:
            app: docker-hello-world
        spec:
          containers:
          - name: docker-hello-world
            image: scottsbaldwin/docker-hello-world:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: docker-hello-world-svc
    spec:
      selector:
        app: docker-hello-world
      ports:
        - port: 8088
          targetPort: 80
      type: ClusterIP
    

    docker-hello-worldサービスのタイプはLoadBalancerではなくClusterIPです。このサービスはingress-nginx-controllerイングレス・コントローラ・サービスによってプロキシ設定されます。docker-hello-worldサービスは、直接パブリック・アクセスを必要としません。かわりに、パブリック・アクセスはロード・バランサからイングレス・コントローラに、イングレス・コントローラからアップストリーム・サービスにルーティングされます。

  2. 次のコマンドを実行して、クラスタ内のノードで新しいhello-worldデプロイメントおよびサービスを作成します:

    kubectl create -f hello-world-ingress.yaml

サンプル・イングレス・コントローラを使用したサンプル・バックエンドへのアクセス

この項では、イングレス・コントローラを使用してバックエンドにアクセスするイングレスを作成します。

イングレス・リソースの作成

  1. ファイルingress.yamlを作成し、次のコードを移入します:

    
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ing
      annotations:
        kubernetes.io/ingress.class: "nginx"
    spec:
      tls:
      - secretName: tls-secret
      rules:
      - http:
          paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: docker-hello-world-svc
                  port:
                    number: 8088
    

    前述の例では、YAMLは、Kubernetesバージョン1.19.x以降を実行しているクラスタと連携しています。

  2. 次のように入力して、リソースを作成します:

    kubectl create -f ingress.yaml

サンプル・コンポーネントが期待どおりに動作していることの確認

この項では、すべてのサンプル・コンポーネントが正常に作成され、期待どおりに動作していることを確認します。docker-hello-world-svcサービスはClusterIPサービスとして実行され、ingress-nginx-controllerサービスはLoadBalancerサービスとして実行される必要があります。イングレス・コントローラに送信されたリクエストは、クラスタ内のノードにルーティングされる必要があります。

ロード・バランサの外部IPアドレスの取得

ingress-nginx-controllerサービスがLoadBalancerサービスとして動作していることを確認するには、次のように入力して外部IPアドレスを取得します:

kubectl get svc --all-namespaces

前述のコマンドの出力に、実行中のサービスが表示されます:


NAMESPACE       NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
default         docker-hello-world-svc      ClusterIP      10.96.83.247    <none>           8088/TCP                     16s
default         kubernetes                  ClusterIP      10.96.0.1       <none>           443/TCP                      1h
ingress-nginx   ingress-nginx-controller    LoadBalancer   10.96.229.38    129.146.214.219  80:30756/TCP,443:30118/TCP   5m			
kube-system     kube-dns                    ClusterIP      10.96.5.5       <none>           53/UDP,53/TCP                1h

cURLリクエストのロード・バランサへの送信

  1. 次のように入力して、ingress-nginx-controllerサービスの外部IPアドレス(たとえば、129.146.214.219)を使用して、httpリクエストを処理します:

    curl -I http://129.146.214.219
    

    前述のコマンドの出力例:

    HTTP/1.1 301 Moved Permanently
    Via: 1.1 10.68.69.10 (McAfee Web Gateway 7.6.2.10.0.23236)
    Date: Thu, 07 Sep 2017 15:20:16 GMT
    Server: nginx/1.13.2
    Location: https://129.146.214.219/
    Content-Type: text/html
    Content-Length: 185
    Proxy-Connection: Keep-Alive
    Strict-Transport-Security: max-age=15724800; includeSubDomains;
    

    出力には、httpトラフィックがhttpsにリダイレクトされていることを示す301リダイレクトとLocationヘッダーが表示されます。

  2. https urlに対してcURLを実行するか、Locationヘッダーに自動的に従うように-Lオプションを追加します。-kオプションは、SSL証明書を検証しないようにcURLに指示します。たとえば、次のように入力します:
    curl -ikL http://129.146.214.219

    前述のコマンドの出力例:

    HTTP/1.1 301 Moved Permanently
    Via: 1.1 10.68.69.10 (McAfee Web Gateway 7.6.2.10.0.23236)
    Date: Thu, 07 Sep 2017 15:22:29 GMT
    Server: nginx/1.13.2
    Location: https://129.146.214.219/
    Content-Type: text/html
    Content-Length: 185
    Proxy-Connection: Keep-Alive
    Strict-Transport-Security: max-age=15724800; includeSubDomains;
    
    HTTP/1.0 200 Connection established
    
    HTTP/1.1 200 OK
    Server: nginx/1.13.2
    Date: Thu, 07 Sep 2017 15:22:30 GMT
    Content-Type: text/html
    Content-Length: 71
    Connection: keep-alive
    Last-Modified: Thu, 07 Sep 2017 15:17:24 GMT
    ETag: "59b16304-47"
    Accept-Ranges: bytes
    Strict-Transport-Security: max-age=15724800; includeSubDomains;
    
    <h1>Hello webhook world from: docker-hello-world-1732906117-0ztkm</h1>
    

    出力の最後の行には、ホスト名がdocker-hello-world-1732906117-0ztkmのポッドから返されるHTMLが表示されます

  3. cURLリクエストを複数回発行して、HTML出力の変更にホスト名を表示し、ロード・バランシングが発生していることを示します:

    $ curl -k https://129.146.214.219
    
    <h1>Hello webhook world from: docker-hello-world-1732906117-6115l</h1>
    
    $ curl -k https://129.146.214.219
    
    <h1>Hello webhook world from: docker-hello-world-1732906117-7r89v</h1>
    
    $ curl -k https://129.146.214.219
    
    <h1>Hello webhook world from: docker-hello-world-1732906117-0ztkm</h1>

nginx.confの調査

ingress-nginx-controllerイングレス・コントローラ・デプロイメントは、実行中のポッドでnginx.confファイルを操作します。

  1. 次のように入力して、ingress-nginx-controllerイングレス・コントローラ・デプロイメントを実行しているポッドの名前を見つけます:

    kubectl get po -n ingress-nginx
    

    前述のコマンドの出力には、ingress-nginx-controllerイングレス・コントローラ・デプロイメントを実行しているポッドの名前が表示されます:

    
    NAME                                       READY     STATUS    RESTARTS   AGE
    ingress-nginx-controller-110676328-h86xg   1/1       Running   0          1h
    
  2. 次のkubectl execコマンドを入力して、ingress-nginx-controllerイングレス・コントローラ・デプロイメントを実行しているポッドの名前を使用して、nginx.confの内容を表示します:

    kubectl exec -n ingress-nginx -it ingress-nginx-controller-110676328-h86xg -- cat /etc/nginx/nginx.conf
    
  3. 出力でproxy_passを探します。デフォルトのバックエンド用と、次に示すような別のものがあります:

    proxy_pass http://upstream_balancer;
    

    これは、Nginxがupstream_balancerというアップストリームへのリクエストをプロキシ設定していることを示しています。

  4. 出力でアップストリーム定義を見つけます。次のように表示されます:

    upstream upstream_balancer {
                    server 0.0.0.1:1234; # placeholder
    
                    balancer_by_lua_block {
                            tcp_udp_balancer.balance()
                    }
            }
    
    

    アップストリームはLuaを介してプロキシ設定しています。

(オプション)サンプルのイングレス・コントローラのアップグレード

このオプション・セクションでは、すぐに削除するのではなく、Kubernetesアプリケーション・トラフィック管理用のイングレス・コントローラの例を使用する方法を説明します。

必要に応じて、前に作成したイングレス・コントローラの例を引き続き使用できます。ただし、新しいバージョンのNginxは定期的にリリースされることに注意してください。したがって、イングレス・コントローラの例を引き続き使用する場合は、イングレス・コントローラが使用するNginxのバージョンを定期的にアップグレードする必要があります。通常、Nginxをアップグレードするときに、イングレス・コントローラの既存のEXTERNAL- IPアドレスを保持する必要があります。

既存のOracle Cloud Infrastructureロード・バランサを削除せずに既存のイングレス・コントローラをアップグレードする(それによって既存のEXTERNAL- IPアドレスを保持する)には、NginxドキュメントのNginx Without Helmのアップグレードの手順に従います。

Nginxのアップグレード時に参照するNginxイメージを確認するには、NginxドキュメントのNginx Changelogを参照してください。

(オプション)サンプルのイングレス・コントローラの削除

このオプション・セクションでは、以前に作成したイングレス・コントローラの例を削除します。次に例を示します:

  • ingress-nginx-controllerイングレス・コントローラ・デプロイメント
  • Kubernetes RBACのロールおよびバインディング
  • タイプLoadBalancerのingress-nginx-controllerイングレス・コントローラ・サービス

イングレス・コントローラ・デプロイメント・スクリプトを後で適用してサンプル・イングレス・コントローラを再作成することにした場合、以前のサービスに異なるEXTERNAL-IPアドレスを持つLoadBalancerタイプの新しいingress-nginx-controllerサービスが作成されます。

引き続き使用する場合は、サンプル・イングレス・コントローラを削除する必要はありません。ただし、イングレス・コントローラの例を引き続き使用する場合は、イングレス・コントローラが使用するNginxのバージョンを定期的にアップグレードする必要があります。(オプション)サンプル・イングレス・コントローラのアップグレードを参照してください。

イングレス・コントローラの例の削除

  1. 次のコマンドを実行して、以前に作成したイングレス・コントローラの例を削除します:

    kubectl delete -f <deployment-script-location>

    ここで、<deployment-script-location>は、サンプル・イングレス・コントローラの作成に以前使用したデプロイメント・スクリプトの場所です。

    例:

    kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/cloud/deploy.yaml