Chapter I: AWS 上で Tanzu Community Edition のデプロイ
デプロイ方法はこちら VMware JP Blog に記載があるため、詳細を省きます。
[TKG 1.4.0 on AWS の構築][link-01]
[link-01]:https://blogs.vmware.com/vmware-japan/2021/10/tkg-1-4-0-on-aws.html
Management Cluster と Workload Cluster 構成後の AWS アーキテクチャは下記の図になります。
2つの ELB(Classic)は自動的に作られ、Control Plane の API サーバアクセスとして構成されます。
Chapter I.5 TKG on AWS の LB Service の検証
Ingress を検証する前に、Default の LB Service を検証します。
下記シンプルな LB Service を Workload Cluster でデプロイします。
apiVersion: v1
kind: Service
metadata:
name: lb-svc-1
spec:
type: LoadBalancer
selector:
app: lb-svc-1
ports:
- protocol: TCP
port: 80
targetPort: 80
結果として
$ k get service -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 5d5h
lb-svc-1 LoadBalancer 100.68.125.217 aebc093baba6d43e18262210da62530b-296707719.us-east-2.elb.amazonaws.com 80:30904/TCP 29s
ELB(Classic) が自動的に作成されます。Instance に Workload Cluster の Worker Node が設定されています。
結論として、TCE on AWS をデプロイしたら、ELB が LB Service のバックエンドとして自動的にインテグレートされます。
Chapter II: Contour を使った Ingress の実現
Contour のインストールは[こちらの記事][link-02]を参照します。
[link-02]:https://ik.am/entries/674
Contour は VMware が管理する Open Source Ingress Controller です。データープレーンは Envoy Proxy を使います。
TCE での Contour デプロイは [tanzu package の仕組み][link-03]を利用すれば容易にデプロイできます。
[link-03]:https://tanzucommunityedition.io/docs/latest/package-management/
#####Step 1: リポジトリを追加
tanzu package repository add tce-repo --url projects.registry.vmware.com/tce/main:0.9.1 --namespace tanzu-package-repo-global
#####Step 2: 使用可能な package を確認
$ tanzu package available list
- Retrieving available packages...
NAME DISPLAY-NAME SHORT-DESCRIPTION
cert-manager.community.tanzu.vmware.com cert-manager Certificate management
contour.community.tanzu.vmware.com Contour An ingress controller
external-dns.community.tanzu.vmware.com external-dns This package provides DNS synchronization functionality.
正しい Package を利用するためには TCE を最新版にアップグレードした方がいいです。
#####Step 3: Contour をデプロイします。
tanzu package install contour --package-name contour.community.tanzu.vmware.com --version 1.19.1
これで Contour と Envoy がデプロイされます。
$ k get pods -n projectcontour
NAME READY STATUS RESTARTS AGE
contour-649bdcf7fd-6ttd4 1/1 Running 0 66m
contour-649bdcf7fd-zblx5 1/1 Running 0 66m
contour-certgen-v1.18.1-m5q8h 0/1 Completed 0 66m
envoy-8hf85 2/2 Running 0 66m
#####Step 4: Ingress をデプロイしてみます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: lb-svc-nginx
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: lb-svc-1
template:
metadata:
labels:
app: lb-svc-1
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: storage
mountPath: /usr/share/nginx/html
volumes:
- name: storage
hostPath:
path: "/data/html"
type: Directory
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: lb-svc-nginx-old
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: lb-svc-2
template:
metadata:
labels:
app: lb-svc-2
spec:
containers:
- name: nginx
image: nginx:1.20.1
ports:
- containerPort: 80
volumeMounts:
- name: storage
mountPath: /usr/share/nginx/html/old
volumes:
- name: storage
hostPath:
path: "/data/html/old"
type: Directory
---
apiVersion: v1
kind: Service
metadata:
name: lb-svc-1
spec:
type: NodePort
selector:
app: lb-svc-1
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: lb-svc-2
spec:
type: NodePort
selector:
app: lb-svc-2
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: contour-test-ingress
annotations:
kubernetes.io/ingress.class: contour
spec:
rules:
- host:
http:
paths:
- path: /old
pathType: Prefix
backend:
service:
name: lb-svc-2
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: lb-svc-1
port:
number: 80
上記は2つバージョン(Latest & 1.20.1)の Nginx をデプロイし、それぞれの deployment に対して NodePort を作り、さらに、URL path (/ & /old)で区別するように Ingress を構成します。
見た目上分けるために、host path volume を使って、簡易な html ファイルをマウントしています。
host path volume を使うので、workload cluster の worker node にアクセスし、/data/html ディレクトリと index.html ファイルを作る必要があります。
worker node にアクセスするのには、踏み台の workload-cluster-bastion インスタンスを経由してアクセスします。
デプロイ後、Ingress と Service を確認します。
$ k get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
contour-test-ingress <none> * xxxx.us-east-2.elb.amazonaws.com 80 50m
$ k get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 19h
lb-svc-1 NodePort 100.66.23.98 <none> 80:32549/TCP 50m
lb-svc-2 NodePort 100.65.103.44 <none> 80:31707/TCP 50m
Ingress に ELB のアドレスが関連されていることが分かりました。
さらに AWS コンソルで確認します。
ELB(classic) は確かに払い出されています。
ELB の DNS 名を使ってアクセスしてみますと
確かに、想定通りに振り分けています。
Chapter III: AWS ALB を使って Ingress を実現
Contour の代わりに AWS ALB と AWS Load Balancer Controller の組み合わせで Ingress を実現してみます。
AWS Load Balancer Controller の[デプロイおよびユーザガイド][link-04]を参照します。
[link-04]:https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.3/deploy/installation/
#####Step 1: IAM の設定
Ingress Controller が ALB/NLB を操作できるようにするためには IAM role を設定してあげる必要があります。
EKS を使用するなら、Controller 用 Service Account と IAM role を作り、eksctl コマンドで関連付けますが、TCE などの 3rd Party K8s を使用する場合、手動で追加する必要があります。
Service Account を使用するためには OIDC provider が必要になるので、今回の検証は Service Account を使わず、直接 Workload Cluster の Worker Node に IAM Role を付与します。
Controller に必要な [IAM Policy][link-05] をダウンロードし、Policy を作成します。
[link-05]:https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.3.1/docs/install/iam_policy.json
専用の IAM Role を作成してもいいですが、今回は TCE デプロイ時に worker node に付与された nodes.tkg.cloud.vmware.com Role に上記 Policy を追加します。
"nodes.tkg.cloud.vmware.com" Role は management cluster の worker node にも適用されています。
既存の policy に controller 用の policy もアタッチします。
#####Step 2: Subnet Discovery の設定
AWS load balancer ingress controller は ALB を利用して Ingress を実現します。AWS ALB をデプロイするためには最低限2つ異なるAZにそれぞれSubenetを用意する必要があります。([AWS ALB Doc][link-06])
[link-06]:https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html
ただ、マルチAZ をコンフィグしない限り、TCE のデプロイは基本1つのAZ内で完結します。ALB を利用するためには、手動でもう1つのAZ用のSubenet を手動で作成します。
既存の public subnet と private subnet にまねして、2つ目のAZのsubnetを作ります。
Ingress Controller に Subnet を識別させるために、Subnet に下記のタグをつける必要があります。
Subnet 種別 | Key | Value |
---|---|---|
Public subnets | kubernetes.io/role/elb | 1 or `` |
Private subnets | kubernetes.io/role/internal-elb | 1 or `` |
:::note info | ||
TCE デプロイ時に自動で作られた Subnet にすでに上記タグは設定済み | ||
::: | ||
本来であれば、新規作成される Subnet に igw や nat も設定すべきですが、TCE worker node はマルチAZ構成していないので、こちら設定しなくてもALBは問題なく動きます。 |
#####Step 3: AWS Load Balancer Ingress Controller のデプロイ
helm に EKS の repo を追加します。
helm repo add eks https://aws.github.io/eks-charts
helm chart をインストールします。
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=<cluster-name>
インストールされたcontroller を確認します。
$ k get all -n kube-system | grep aws
pod/aws-load-balancer-controller-6bc577994f-r842f 1/1 Running 0 21h
pod/aws-load-balancer-controller-6bc577994f-snb77 1/1 Running 0 21h
service/aws-load-balancer-webhook-service ClusterIP 100.69.91.239 <none> 443/TCP 21h
deployment.apps/aws-load-balancer-controller 2/2 2 2 21h
replicaset.apps/aws-load-balancer-controller-6bc577994f 2 2 2 21h
#####Step 4: AWS Load Balancer Ingress Controller のテスト
Contour のテストで作られた Nginx Pod と Nodeport Service を流用します。
Ingress は下記の yaml をデプロイします。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: aws-alb-test-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
spec:
rules:
- host:
http:
paths:
- path: /old
pathType: Prefix
backend:
service:
name: lb-svc-2
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: lb-svc-1
port:
number: 80
テストのために、alb.ingress.kubernetes.io/scheme: internet-facing の Annotation を追加し、インターネットからALBへのアクセスを許可します。
デプロイ後の Ingress を確認すると、ALB の DNS 名が紐付けられています。
NAME CLASS HOSTS ADDRESS PORTS AGE
aws-alb-test-ingress <none> * k8s-default-awsalbte-xxxxx.us-east-2.elb.amazonaws.com 80 91m
早速 ALB の public DNS 名でアクセスしてみます。
想定通り、振り分けくれています。
AWS Load Balancer の詳細設定等はUser Guideを参照してください。
#Chapter Last
今回はデプロイと極シンプルのテストをやってみただけですが、ContourとALBにはそれぞれの特性(Contour の HTTP Proxy や ALB の TargetGroup および AWS WAFなど)があるので、それらの比較、そしてTCEとEKSの比較等にも興味がありますので、今後ちょっとずつ書いてみたいです。