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

最終更新日: 2020 年 1 月 29 日

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

簡単な説明

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

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

重要: Ingress ControllerIngress と同じではありません。Ingress は Kubernetes リソースで、クラスターの外部から HTTP および HTTPS ルートをクラスター内部のサービスに公開します。Ingress Controller はイングレスを実現します (通常はロードバランサーを使用)。Ingress Controller なしで Ingress を使用することはできません。

解決方法

次の解決方法では、nginxinc/kubernetes-ingress Ingress Controller を使用します。パブリックに使用できるもう 1 つの Ingress Controller は、kubernetes/ingress-nginx です。詳細については、nginxinc/kubernetes-ingress Ingress Controller と kubernetes/ingress-nginx Ingress Controller の違いを参照してください。

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/

注意: 以下のステップのすべてのコマンドは、deployments ディレクトリから実行されます。

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

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

注意: デフォルトのサーバーは、Ingress ルールが定義されていないドメインのすべてのリクエストについて、ステータスコード 404 を含む「Not Found」ページを返します。テスト目的で生成された自己署名証明書とキーを使用できます。独自の証明書とキーを本稼働環境で使用するのがベストプラクティスです。

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

kubectl apply -f common/nginx-config.yaml

注意: 設定例については、ConfigMap と注釈を参照してください。

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

kubectl apply -f rbac/rbac.yaml

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

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

注意: [Deployment] または [DaemonSet] オプションを使用して Ingress Controller をデプロイできます。[Deployment] オプションを使用すると、Ingress Controller レプリカの数を動的に変更できます。[Daemon set] オプションを使用すると、すべてのノードまたはノードのサブセットに 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
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

注意: 詳細については、名前ベースの仮想ホスティングを参照してください。

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

kubectl apply -f micro-ingress.yaml

注意: この Ingress リソースは、hostname.mydomain.com のものを hostname-svc にリダイレクトし、apache.mydomain.com のものを apache-svc にリダイレクトするルールを定義します。ルールに一致しないリクエストは 404「Not Found」エラーメッセージを返します。

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)

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 を含む「Not Found」ページを返します。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 レスポンスが返されます。 


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

改善できることはありますか?


さらにサポートが必要な場合