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

所要時間7分
0

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

簡単な説明

NGINX Ingress Controller または AWS Load Balancer Controller for Kubernetes を使用して、Amazon EKS クラスター内の複数の Kubernetes サービスへの外部アクセスを提供します。NGINX Ingress Controller は、主に NGINX によって管理されています。NGINX Ingress Controller で問題を確認するには、GitHub ウェブサイトの問題の一覧を参照してください。AWS Load Balancer Controller は、アマゾン ウェブ サービス (AWS) によって管理されています。AWS Load Balancer Controller の問題を確認するには、GitHub ウェブサイトの問題リストを参照してください。

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

前提条件:AWS Load Balancer Controller をインストールします。AWS Load Balancer Controller を使用して、Amazon EKS の LoadBalancer タイプのサービスオブジェクト用の Network Load Balancer を作成および管理するのがベストプラクティスです。

解決方法

次の解決策では、Kubernetes GitHub ウェブサイトの kubernetes/ingress-nginx Ingress Controller を使用します。公開されている他の Ingress Controller は、NGINX GitHub ウェブサイトの nginxinc/kubernetes-ingress です。

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

NGINX Ingress Controller for Kubernetes は、伝送制御プロトコル (TCP) または Transport Layer Security (TLS) のいずれかによってデプロイできます。

**注意:**次の解決策は、Amazon EKS バージョン 1.22、NGINX Ingress Controller バージョン 1.3.0、および AWS Load Balancer Controller バージョン 2.4.3 でテストされています。

(オプション 1) Network Load Balancer の TCP 搭載 NGINX Ingress Controller

1.    YAML ファイルを取得して、次の Kubernetes オブジェクトをデプロイします。namespaceserviceaccountsconfigmapclusterrolesclusterrolebindingsrolesrolebindingsservicesdeploymentsingressclasses、および validatingwebhookconfigurations

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml

2.    ファイルを編集します。次に、ingress-nginx-controller サービスオブジェクトセクションで、すべての service.beta.kubernetes.io アノテーションを以下に置き換えます。

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

3.    マニフェストを適用します。

kubectl apply -f deploy.yaml

出力例:

namespace/ingress-nginx created 
serviceaccount/ingress-nginx created 
configmap/ingress-nginx-controller created 
clusterrole.rbac.authorization.k8s.io/ingress-nginx created 
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created 
role.rbac.authorization.k8s.io/ingress-nginx created 
rolebinding.rbac.authorization.k8s.io/ingress-nginx created 
service/ingress-nginx-controller-admission created 
service/ingress-nginx-controller created 
deployment.apps/ingress-nginx-controller created 
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created 
serviceaccount/ingress-nginx-admission created 
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created 
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created

(オプション 2) NGINX ingress controller TLS termination on Network Load Balancer

デフォルトでは、前のソリューションは NGINX Ingress Controller で TLS を終了します。また、Network Load Balancer で TLS を終了するように NGINX Ingress サービスを設定することもできます。

1.    deploy.yaml テンプレートをダウンロードします。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml

2.    ファイルを編集します。次に、 ingress-nginx-controller サービスオブジェクトセクションで、すべての service.beta.kubernetes.io アノテーションを以下に置き換えます。

service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

**注意:**必ず service.beta.kubernetes.io/aws-load-balancer-ssl-cert の ARN を含めてください。

3.    ファイルを編集し、Kubernetes クラスターの Amazon Virtual Private Cloud (Amazon VPC) CIDR を変更します。

proxy-real-ip-cidr: XXX.XXX.XXX/XX

4.    マニフェストを適用します。

kubectl apply -f deploy.yaml

注意:前のマニフェストでは、 ExternalTrafficPolicyローカルとして使用し、ソース (クライアント) の IP アドレスを保持しています。Amazon VPC でカスタム DHCP 名によりこの設定を使用すると、問題が発生します。この問題の発生を防ぐには、以下のパッチを kube-proxy に適用します。

kubectl edit daemonset kube-proxy -n kube-system

5.    マニフェストを編集して、次のスニペットを含めます。

spec:
  template:
    spec:
      containers:
        - name: kube-proxy
          command:
            - kube-proxy
            - --hostname-override=$(NODE_NAME)
            - --v=2
            - --config=/var/lib/kube-proxy-config/config
           env:
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: spec.nodeName

デプロイされたリソースを確認する

AWS Load Balancer Controller

コマンド:

kubectl get all -n kube-system --selector app.kubernetes.io/instance=aws-load-balancer-controller

出力例:

NAME                                                READY   STATUS    RESTARTS   AGE   IP               NODE                                           NOMINATED NODE   READINESS GATES
pod/aws-load-balancer-controller-85cd8965dc-ctkjt   1/1     Running   0          48m   192.168.37.36    ip-192-168-59-225.us-east-2.compute.internal   none             none 
pod/aws-load-balancer-controller-85cd8965dc-wpwx9   1/1     Running   0          48m   192.168.53.110   ip-192-168-59-225.us-east-2.compute.internal   none>         none 
NAME                                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR 
service/aws-load-balancer-webhook-service   ClusterIP   10.100.154.44   none          443/TCP   19h   app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller 
NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS                   IMAGES                                                                                    SELECTOR 
deployment.apps/aws-load-balancer-controller   2/2     2            2           19h   aws-load-balancer-controller 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0   app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller 
NAME                                                      DESIRED   CURRENT   READY   AGE   CONTAINERS                     IMAGES                                                                                    SELECTOR 
replicaset.apps/aws-load-balancer-controller-85cd8965dc   2         2         2       19h   aws-load-balancer-controller   602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0   app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller,pod-template-hash=85cd8965dc

NGINX Ingress Controller

コマンド:

kubectl get all -n ingress-nginx --selector app.kubernetes.io/instance=ingress-nginx

出力例:

NAME                                           READY  STATUS   RESTARTS  AGE   IP               NODE                                           NOMINATED NODE  READINESS GATES
pod/ingress-nginx-controller-54d8b558d4-k4pdf  1/1    Running  0         56m   192.168.46.241   ip-192-168-59-225.us-east-2.compute.internal   none            none
NAME                                        TYPE           CLUSTER-IP      EXTERNAL-IP                                                                     PORT(S)                      AGE   SELECTOR
service/ingress-nginx-controller            LoadBalancer   10.100.99.129   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80:32578/TCP,443:30724/TCP   15h   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
service/ingress-nginx-controller-admission  ClusterIP      10.100.190.61   none                                                                            443/TCP                      15h   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
NAME                                       READY   UP-TO-DATE   AVAILABLE    AGE   CONTAINERS   IMAGES                                                                                                               SELECTOR
deployment.apps/ingress-nginx-controller   1/1     1            1            15h   controller   k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
NAME                                                  DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                                                                                                               SELECTOR
replicaset.apps/ingress-nginx-controller-54d8b558d4   1         1         1       15h   controller   k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx,pod-template-hash=54d8b558d4
NAME                                       COMPLETIONS   DURATION   AGE   CONTAINERS   IMAGES                                                                                                                         SELECTOR
job.batch/ingress-nginx-admission-create   1/1           2s         15h   create       k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660   controller-uid=242bdf56-de16-471d-a691-1ca1dbc10a41
job.batch/ingress-nginx-admission-patch    1/1           2s         15h   patch        k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660   controller-uid=a9e710d2-5001-4d40-a435-ddc8993bfe42

IngressClass

コマンド:

kubectl get ingressclass

出力例:

NAME    CONTROLLER             PARAMETERS                             AGE 
alb     ingress.k8s.aws/alb    IngressClassParams.elbv2.k8s.aws/alb   19h 
nginx   k8s.io/ingress-nginx   none                                   15h

デプロイ設定をテストする

**注意:**次の手順では、2 つのマイクロサービスを実行しています。マイクロサービスは、デフォルトタイプとして Kubernetes を使用して内部に公開されます。

1.    デプロイメントまたはマイクロサービスをセットアップします。例えば、hostname-appapache-app などです。

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

apiVersion: apps/v1 
kind: Deployment 
metadata:
  name: hostname-app
  namespace: default 
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
  namespace: default 
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
  namespace: default 
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
  namespace: default
  labels: 
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: apache-app

2.    設定を適用します。

hostname-app:

kubectl apply -f hostname-app-svc.yaml

apache-app:

kubectl apply -f apache-app-svc.yaml

3.    リソースが作成されていることを確認します。

デプロイ

コマンド:

kubectl get deployment hostname-app apache-app -n default

出力例:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE 
hostname-app   2/2     2            2           29m
apache-app     2/2     2            2           29m

サービス

コマンド:

kubectl get svc apache-svc hostname-svc -n default

出力例:

NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE 
apache-svc     ClusterIP   10.100.73.51    none          80/TCP    29m 
hostname-svc   ClusterIP   10.100.100.44   none          80/TCP    29m

NGINX Ingress Controller をテストする

1.    コマンドラインから以前に取得したロードバランサーの DNS URL にアクセスします。

curl -I ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com

出力例:

HTTP/1.1 404 Not Found 
Date: Thu, 03 Mar 2022 14:03:11 GMT 
Content-Type: text/html 
Content-Length: 146 
Connection: keep-alive

**注意:**デフォルトのサーバーは、ingress ルールが定義されていないすべてのドメインリクエストに対して 404 Not Found ページを返します。Ingress Controller は、定義されたルールに基づいて、リクエストが設定と一致しない限り、指定されたバックエンドサービスにトラフィックを振り分けることはありません。host フィールドは Ingress オブジェクト用に設定されているため、同じホスト名でリクエストの Host ヘッダーを指定する必要があります。テスト環境では、curl フラグを使用して Host ヘッダーを指定します。本番環境では、ロードバランサーの DNS 名を Amazon Route 53 などの任意の DNS プロバイダーのホスト名にマッピングします。

2.    Ingress を実装して、NGINX Ingress Controller によって提供される単一のロードバランサーを使用してサービスとインターフェイスで接続します。

micro-ingress.yaml の例:

apiVersion: networking.k8s.io/v1 
kind: Ingress 
metadata:
  name: micro-ingress
  namespace: default
  annotations: 
    kubernetes.io/ingress.class: nginx 
spec:
  rules:
    - host: hostname.mydomain.com
      http:
        paths:
        - backend:
            service:
              name: hostname-svc
              port:
                number: 80
          path: /
          pathType: Prefix
  - host: apache.mydomain.com
    http:
      paths:
      - backend:
          service:
            name: apache-svc
            port:
              number: 80
        path: /
        pathType: Prefix

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

3.    リソースが作成されていることを確認します。

Ingress

コマンド:

kubectl get ingress -n default

出力例:

NAME           CLASS   HOSTS                                       ADDRESS                                                                         PORTS   AGE 
micro-ingress  none    hostname.mydomain.com,apache.mydomain.com   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80      29m

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

最初に構成されたドメイン:

curl -i -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/

出力例:

HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 18:50:38 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive

2 番目に構成されたドメイン:

curl -i -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/

出力例:

HTTP/1.1 200 OK 
Date: Sat, 26 Mar 2022 18:51:00 GMT 
Content-Type: text/html 
Content-Length: 45 
Connection: keep-alive 
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT 
ETag: "2d-432a5e4a73a80" 
Accept-Ranges: bytes

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

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

以下はその例です。

apiVersion: networking.k8s.io/v1 
kind: Ingress 
metadata:
  name: path-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginxd
    nginx.ingress.kubernetes.io/rewrite-target: / 
spec:
  rules:
  - host: mydomain.com
    http:
      paths:
      - backend:
          service:
            name: hostname-svc
            port:
              number: 80
        path: /hostname
        pathType: Prefix
  - host: mydomain.com
    http:
      paths:
      - backend:
          service:
            name: apache-svc
            port:
              number: 80
        path: /apache
        pathType: Prefix

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

5.    パスベースのルーティングが追加されていることを確認します。

コマンド:

kubectl get ingress -n default

出力:

NAME            CLASS  HOSTS                                       ADDRESS                                                                         PORTS  AGE
micro-ingress   none   hostname.mydomain.com,apache.mydomain.com   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     164m
path-ingress    none   mydomain.com,mydomain.com                   ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     120m

コマンド:

curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/hostname
  • または -
curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/apache

AWS Load Balancer Controller を使用して Ingress をテストする

1.    次の例の Ingress マニフェストを使用して、Application Load Balancer を起動します。

apiVersion: networking.k8s.io/v1 
kind: Ingress 
metadata:
  name: micro-ingress-alb
  namespace: default
  annotations:
    kubernetes.io/ingress.class: alb 
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip 
spec:
  rules:
  - host: alb.hostname.mydomain.com
    http:
      paths:
      - backend:
          service:
            name: hostname-svc
            port:
              number: 80
        path: /
        pathType: Prefix
   - host: alb.apache.mydomain.com
     http:
       - backend:
            service:
              name: apache-svc
              port:
                number: 80
         path: /
         pathType: Prefix

2.    Application Load Balancer が起動することを確認します。

コマンド:

kubectl get ingress -n default

出力:

NAME               CLASS  HOSTS                                               ADDRESS                                                                         PORTS  AGE
micro-ingress      none   hostname.mydomain.com,apache.mydomain.com           ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     164m
micro-ingress-alb  none   alb.hostname.mydomain.com,alb.apache.mydomain.com   k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com          80     18m
path-ingress       none   mydomain.com,mydomain.com                           ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com   80     120m

最初に構成されたドメインに基づくリクエスト:

curl -i -H "Host: alb.hostname.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com

出力例:

HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 20:46:02 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive

2 番目に構成されたドメインに基づくリクエスト:

curl -i -H "Host: alb.apache.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com

出力例:

HTTP/1.1 200 OK 
Date: Sat, 26 Mar 2022 20:46:14 GMT 
Content-Type: text/html Content-Length: 45 
Connection: keep-alive 
Server: Apache/2.4.53 (Unix) 
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT 
ETag: "2d-432a5e4a73a80" 
Accept-Ranges: bytes

AWS公式
AWS公式更新しました 1年前
コメントはありません

関連するコンテンツ