突然ですが、AWS App Meshは皆さんお使いでしょうか?
AWS製のサービスメッシュ構築サービスですね。
サービスメッシュといえばIstioが有名ですが、AWS App MeshはAWS製だけあってEKSはもちろんEC2やECSのインスタンス・コンテナもメッシュに組み込むことができるのが強みという印象です。
そんなApp MeshをEKS上でいろいろと実験してみたので、自分の理解の反芻のためにもまとめてみたいと思います。
試した環境は kubernetes 1.20, App Meshコントローラ 1.3.0 でした。
- 準備
ドキュメントに従ってコントローラをインストールします。
Getting started with AWS App Mesh and Kubernetes - AWS App Mesh
手順はドキュメントの通りなのでここでは書きませんが、完了するとappmesh-system
ネームスペースでコントローラのポッドができていました。
$ kubectl get pod -n appmesh-system
NAME READY STATUS RESTARTS AGE
appmesh-controller-6c55b46558-8s363 1/1 Running 0 1d
- mesh作成
メッシュを作成します。
egressFilter
はメッシュ内部から外部へのアクセスを許可するかどうかですね。許可しない場合はDROP_ALLにします。
namespaceSelecter
も何でもいいので書いておきましょう。
apiVersion: appmesh.k8s.aws/v1beta2
kind: Mesh
metadata:
name: mesh-1
spec:
egressFilter:
type: ALLOW_ALL
namespaceSelector:
matchLabels:
mesh: sitateru-mesh
- namespace作成
メッシュのリソースを配置するネームスペースを宣言します。
上のMeshで指定した namespaceSelector
とラベルを合わせておきましょう。
App Meshの機能を使うにはappmesh.k8s.aws/sidecarInjectorWebhook
をenabledにしてEnvoyサイドカーが入れられるようにしておく必要があります。
apiVersion: v1
kind: Namespace
metadata:
name: mesh-test
labels:
mesh: mesh-1
appmesh.k8s.aws/sidecarInjectorWebhook: enabled
- サービスアカウント作成
IAMで以下のポリシーを作成します。
今回は動作検証なので mesh-1
メッシュの全ての仮想ノードと仮想ゲートウェイに対して StreamAggregatedResources
を許可していますが、実使用の際には適宜リソース名を指定するほうが望ましいですね。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "appmesh:StreamAggregatedResources",
"Resource": [
"arn:aws:appmesh:ap-northeast-1:111122223333:mesh/mesh-1/virtualNode/*",
"arn:aws:appmesh:ap-northeast-1:111122223333:mesh/mesh-1/virtualGateway/*"
]
}
]
}
続いてこのポリシーをアタッチしたサービスアカウントをEKSクラスターに作成します。
$ eksctl create iamserviceaccount \
--cluster test-cluster \
--namespace mesh-test \
--name appmesh-proxyauth \
--attach-policy-arn arn:aws:iam::111122223333:policy/appmesh-proxyauth \
--override-existing-serviceaccounts \
--approve
- 仮想ノード用サービス作成
仮想ノードの実体にするdeploymentとserviceを作成します。コンテナイメージは何でもいいのですが、今回はただのnginxにしています。
serviceAccountName
には👆で作成したサービスアカウント名を指定します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-1
namespace: mesh-test
labels:
app: sample0
spec:
selector:
matchLabels:
app: sample0
template:
metadata:
labels:
app: sample0
server: nginx
spec:
serviceAccountName: appmesh-proxyauth
containers:
- name: nginx
image: nginx:1.19.0
ports:
- containerPort: 80
resources:
limits:
cpu: 10m
memory: 10Mi
---
apiVersion: v1
kind: Service
metadata:
name: svc-1
namespace: mesh-test
labels:
app: sample0
spec:
selector:
app: sample0
server: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
- 仮想ノード作成
今作ったsvc-1
を実体とする仮想ノードを作成します。
serviceDiscovery
で仮想ノードとする実体を指定するのですが、ここでは目的のサービスのDNSホスト名( サービス名.名前空間.svc.cluster.local
)を指定します。
ServiceとPodに対するDNS | Kubernetes
ちなみにDNSではなくCloud Mapを使って指定することもできるみたいです。
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualNode
metadata:
name: vnode-1
namespace: mesh-test
spec:
podSelector:
matchLabels:
app: sample0
listeners:
- portMapping:
port: 80
protocol: http
serviceDiscovery:
dns:
hostname: svc-1.mesh-test.svc.cluster.local
うまくできていればAWSコンソールでもメッシュや仮想ノードが表示されているはずです。
できていない場合は appmesh-controller
ポッドのログを見れば何かわかるかもしれないのでチェックしてみてください。
そこそこ長くなってきたのでここまでにしようと思います。
ここまで作ったものだけではぜんぜんサービスメッシュになっていないのですが、続きは近いうちにまた書きます!
ちなみに、メッシュのリソース作成はkubernetes的にはカスタムリソースの作成になっています。
そのカスタムリソースの定義は👇なので、yamlをどう書けばいいのかこちらを見つつやるのがいいのではないかと思います!
eks-charts/crds.yaml at master · aws/eks-charts