Amazon EKS クラスターにある複数の Kubernetes サービスへの外部アクセスを提供する方法を教えてください。

最終更新日: 2021 年 2 月 16 日

Amazon Elastic Kubernetes Service (Amazon EKS) クラスターにある複数の Kubernetes サービスへの外部アクセスを提供したいと考えています。

簡単な説明

NGINX Ingress Controller for Kubernetes を使用して、Amazon EKS クラスターにある複数の Kubernetes サービスへの外部アクセスを提供できます。

注: Ingress Controller は、ロードバランサーよりも効率的でコスト効率が高い場合があります。さまざまなマイクロサービスにトラフィックを送信するために、ロードバランサーを予約する必要がある場合もあります。

重要: (Kubernetes ウェブサイトの) Ingress Controller は、(Kubernetes のウェブサイトの) Ingress とは異なります。Ingress は、クラスターの外部からクラスター内のサービスへの HTTP および HTTPS ルートを公開する Kubernetes リソースです。Ingress Controller が入力を実行します(通常はロードバランサーを使用します)。Ingress Controller なしで Ingress を使用することはできません。

解決方法

注意: 次の解決策では、NGINX GitHub ウェブサイトの nginxinc/kubernetes-ingress Ingress Controller を使用します。パブリックに使用できる他の Ingress Controller は、Kubernetes GitHub サイトの kubernetes/ingress-nginx です。詳細については、NGINX ウェブサイトの Differences Between nginxinc/kubernetes-ingress and kubernetes/ingress-nginx Ingress Controllers をご参照ください。

NGINX Ingress Controller for Kubernetes をデプロイする

1.    NGINX Ingress Controller for Kubernetes をダウンロードするには、次のコマンドを実行します。

git clone https://github.com/nginxinc/kubernetes-ingress.git

2.    Ingress Controller をデプロイするディレクトリを選択するには、次のコマンドを実行します。

cd kubernetes-ingress/deployments/

注: 次の手順のすべてのコマンドは、デプロイディレクトリから実行します。

3.    デフォルトサーバー専用の名前空間、サービスアカウント、TLS 証明書(キー付き)を作成するには、次のコマンドを実行します。

kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f common/default-server-secret.yaml

注: デフォルトのサーバーは、Ingress ルールが定義されていないドメインのリクエストすべてに対して、404 ステータスコードを含む「見つかりません」ページを返します。テストの目的で生成した自己署名証明書とキーを使用できます。本番環境では、独自の証明書とキーを使用することをお勧めします。

4.    NGINX 設定をカスタマイズする ConfigMap を作成するには、次のコマンドを実行します。

kubectl apply -f common/nginx-config.yaml

注: 設定の例については、NGINX GitHub サイトの ConfigMap と Annotations をご参照ください。

5.    ロールベースのアクセス制御 (RBAC) を設定するには、ClusterRole を作成し、 ステップ 3 の ClusterRole をサービスアカウントにバインドします。例:

kubectl apply -f rbac/rbac.yaml

注: ClusterRole は、Amazon EKS クラスターを操作するためのアクセス許可を Ingress Controller に付与します。

6.    Kubernetes クラスターのバージョンが 1.18 以上の場合は、次のコマンドを実行して NGINX Ingress Class を作成します。

kubectl apply -f common/ingress-class.yaml

7.    Ingress Controller をデプロイするには、次のコマンドを実行します。

注: Deployment または DaemonSet オプションを使って、Ingress Controller をデプロイできます。Deployment オプションでは、Ingress Controller のレプリカの数を動的に変更できます。DaemonSet オプションでは、すべてのノードまたはノードのサブセットに Ingress Controller をデプロイできます。ステップ 6 では、Deployment オプションを使用します。

kubectl apply -f deployment/nginx-ingress.yaml
kubectl get pods --namespace=nginx-ingress

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

NAME                            READY   STATUS    RESTARTS   AGE
nginx-ingress-fb4f4b44c-xmq6z   1/1     Running   0          3d7h

Ingress Controller が Ingress オブジェクトからのリクエストを受け入れることができるようになりました。

Ingress Controller にアクセスし、アプリケーションを実行する

Deployment ingress-controllerの場合、タイプ NodePort または LoadBalancer のサービスオブジェクトを使用できます。次のステップでは、LoadBalancer タイプを使用します。

1.    設定を適用するには、次のコマンドを実行します。

kubectl apply -f service/loadbalancer-aws-elb.yaml

kubectl get svc --namespace=nginx-ingress

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

NAME          TYPE         EXTERNAL-IP                                      PORT(S)
nginx-ingress LoadBalancer aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com 80:32462/TCP,443:32226/TCP

注: Amazon EKS はクライアントの情報(IP アドレスとポート)を渡すために PROXY プロトコルが有効になっている TCP モードで Classic Load Balancer を割り当てます。このプロキシ情報を Ingress Controller に渡す必要があります。

2.    プロキシ情報を Ingress Controller に渡すため PROXY プロトコルを使用するように NGINX を設定するには、ステップ 1 の nginx-config.yaml ファイルに次のキーを追加します。例:

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress
data:
  proxy-protocol: "True"
  real-ip-header: "proxy_protocol"
  set-real-ip-from: "0.0.0.0/0"

注: プロキシ情報は、前に作成した ConfigMap を介して Ingress Controller に渡されます。

3.    ConfigMap を更新するには、次のコマンドを実行します。

kubectl apply -f common/nginx-config.yaml

4.    デプロイまたはマイクロサービス(hostname-appapache-app など)をセットアップします。以下の例をご覧ください。

注: このステップでは、(デモ用に)2 つのマイクロサービスを実行していることを前提としています。マイクロサービスは、デフォルトタイプとして Kubernetes を使用して内部に公開されます。

hostname-apphostname-app-svc.yaml ファイルの例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostname-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hostname-app
  template:
    metadata:
      labels:
        app: hostname-app
    spec:
      containers:
      - name: hostname-app
        image: k8s.gcr.io/serve_hostname:1.1

---
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc
spec:
  ports:
  - port: 80
    targetPort: 9376
    protocol: TCP
  selector:
    app: hostname-app

apache-appapache-app-svc.yaml ファイルの例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: apache-app
  template:
    metadata:
      labels:
        app: apache-app
    spec:
      containers:
      - name: apache-app
        image: httpd:latest
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: apache-svc
  labels:
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: apache-app

設定を適用するには、次のコマンドを実行します。

kubectl apply -f hostname-app-svc.yaml
kubectl apply -f apache-app-svc.yaml

5.    Ingress を実装して、Ingress Controller によって提供される単一のロードバランサーを使用してサービスとインターフェイスで接続します。次の micro-ingress.yaml の例を参照してください。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: micro-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: hostname.mydomain.com
      http:
        paths:
          - backend:
              serviceName: hostname-svc
              servicePort: 80
    - host: apache.mydomain.com
      http:
        paths:
          - backend:
              serviceName: apache-svc
              servicePort: 80

注: 詳細については、Kubernetes ウェブサイトの Name based virtual hosting をご参照ください。

6.    設定を適用するには、次のコマンドを実行します。

kubectl apply -f micro-ingress.yaml

注: この Ingress リソースは、hostname.mydomain.com のすべてを hostname-svc にリダイレクトし、apache.mydomain.com のすべてを apache-svc にリダイレクトするルールを定義します。ルールに一致しないリクエストは、404「見つかりません」エラーメッセージを返します。

Ingress について説明すると、次のようなメッセージが表示されます。

Name:             micro-ingress
 Namespace:        default
 Address:          
 Default backend:  default-http-backend:80 (<none>)
 Rules:
  Host                   Path  Backends
  ----                   ----  --------
  hostname.mydomain.com  
                            hostname-svc:80 (192.168.2.45:9376,192.168.3.236:9376)
  apache.mydomain.com    
                            apache-svc:80 (192.168.2.47:80,192.168.3.45:80)
Annotations:             kubernetes.io/ingress.class: nginx

NGINX Ingress Controller をテストする

1.    コマンドラインからロードバランサーの DNS URL にアクセスするには、次のコマンドを実行します。

curl -I
http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

注: ロードバランサーのエンドポイントは、前述の Ingress Controller にアクセスし、アプリケーションを実行するセクションを実行します。

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

HTTP/1.1 404 Not Found
Server: nginx/1.17.5
Date: Mon, 25 Nov 2019 20:50:58 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

注: デフォルトのサーバーは、Ingress ルールが定義されていないドメインのリクエストすべてに対して、404 ステータスコードを含む「見つかりません」ページを返します。Ingress Controller は、定義されたルールに基づいて、リクエストが設定と一致しない限り、指定されたバックエンドサービスにトラフィックを振り分けることはありません。host フィールドは Ingress オブジェクト用に設定されているため、同じホスト名でリクエストの Host ヘッダーを指定する必要があります。

2.    Host ヘッダーにリクエストを追加します。

これは、最初に設定したドメインに基づくリクエストです。

curl -I -H "Host: hostname.mydomain.com"
http://aaa25a5010daa11eaa41e121e71bd6ca-113564610.us-east-1.elb.amazonaws.com/

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

HTTP/1.1 200 OK
Server: nginx/1.17.5
Content-Type: text/html
Content-Length: 612
Connection: keep-alive

これは、2 番目に設定したドメインに基づくリクエストです。

curl -I -H "Host: apache.mydomain.com"
http://aaa25a5010daa11eaa41e121e71bd6ca-113564610.us-east-1.elb.amazonaws.com/

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

HTTP/1.1 200 OK
Server: nginx/1.17.5
Content-Type: text/html
Content-Length: 45
Connection: keep-alive

Host ヘッダーを追加すると、Ingress Controller は Ingressで定義した設定と一致するため、トラフィックをバックエンドで設定されたサービスにリダイレクトできます。

同じドメイン名を維持したいが、アクセスしたパスに基づいてトラフィックを迂回させたい場合は、Ingress でパスベースのルーティングを追加する必要があります。例:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: path-ingress
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: hostname.mydomain.com
  http:
        paths:
        - path: /login
          backend:
                serviceName: service1
                servicePort: 4200
        - path: /cart
          backend:
                serviceName: service2
                servicePort: 8080

前の例では、リクエストに hostname.mydomain.com がホストヘッダーとして含まれている場合、200 レスポンスのみを返します。リクエストは、/login または /cart パスでアクセスされます。他のすべてのリクエストでは、404 レスポンスが返されます。


この記事はお役に立ちましたか?


請求に関するサポートまたは技術サポートが必要ですか?