はじめに
最近Ciliumが気になっていて、ちょっと触ってみたいなと思っていたところ、
EKS上でCiliumを動かすサンプルをAWSがGitHubで公開しているのを見つけたので試してみました!
Ciliumとは
Ciliumはextended Berkeley Packet(eBPF)というカーネル技術を用いてワークロード間のネットワークの接続を提供、保護、監視するOSSです。
eBPFを用いることで従来のサービスメッシュの様なサイドカーコンテナが不要になる、Pod間通信の経路がシンプルになりオーバーヘッドが少なる事による通信レイテンシが大幅に改善される、などの多くのメリットがあります。
Ciliumはネットワークを管理するCilium CNI,サービスメッシュ機能を提供するCilium Service Mesh,オブザーバビリティ機能を提供するCilium Hubbleから構成されています。
Ciliumは2023/10/11にCNCFのGraduationプロジェクトに認定されており、Ciliumが本番システムで稼動できる品質になっている事が証明されています。
前提条件
このサンプルを稼動させるためには以下を用意する必要があります。
- AWSおよびKubernetes API Serverに接続可能な端末
→ 私はAWSコンソールからCloudShellを起動して使いました - 端末に以下のCLIツールがインストールされていること
- AWS CLI
- Terraform
- kubectl
- Cilium CLI
- Helm
Step 1 - GitHubリポジトリをクローン
まず公式サンプルのリポジトリをクローンします。
git clone https://github.com/aws-samples/cilium-mesh-on-eks/
cd cilium-mesh-on-eks
[cloudshell-user@ip-10-2-1-25 ~]$ git clone https://github.com/aws-samples/cilium-mesh-on-eks/
Cloning into 'cilium-mesh-on-eks'...
remote: Enumerating objects: 445, done.
remote: Counting objects: 100% (268/268), done.
remote: Compressing objects: 100% (168/168), done.
remote: Total 445 (delta 158), reused 169 (delta 100), pack-reused 177
Receiving objects: 100% (445/445), 412.77 KiB | 4.86 MiB/s, done.
Resolving deltas: 100% (248/248), done.
[cloudshell-user@ip-10-2-1-25 ~]$ cd cilium-mesh-on-eks
[cloudshell-user@ip-10-2-1-25 cilium-mesh-on-eks]$ ls
CODE_OF_CONDUCT.md CONTRIBUTING.md images LICENSE productapp README.md terraform values_cilium.yaml
Step 2 - TerraformでEKSクラスタをデプロイ
クローンしたリポジトリ内にあるTerraformテンプレートファイルを使って、EKSクラスタをデプロイします。
cd terraform
terraform init
terraform apply --auto-approve
d=terraform:initial-20240720080453271400000012]
module.eks.aws_eks_addon.this["vpc-cni"]: Creating...
module.eks.aws_eks_addon.this["coredns"]: Creating...
module.eks.aws_eks_addon.this["kube-proxy"]: Creating...
module.eks.aws_eks_addon.this["kube-proxy"]: Creation complete after 7s [id=terraform:kube-proxy]
module.eks.aws_eks_addon.this["vpc-cni"]: Still creating... [10s elapsed]
module.eks.aws_eks_addon.this["coredns"]: Still creating... [10s elapsed]
module.eks.aws_eks_addon.this["coredns"]: Creation complete after 14s [id=terraform:coredns]
module.eks.aws_eks_addon.this["vpc-cni"]: Still creating... [20s elapsed]
module.eks.aws_eks_addon.this["vpc-cni"]: Still creating... [30s elapsed]
module.eks.aws_eks_addon.this["vpc-cni"]: Still creating... [40s elapsed]
module.eks.aws_eks_addon.this["vpc-cni"]: Creation complete after 44s [id=terraform:vpc-cni]
Apply complete! Resources: 66 added, 0 changed, 0 destroyed.
Outputs:
configure_kubectl = "aws eks --region us-west-2 update-kubeconfig --name terraform"
オレゴンリージョンにterraform
という名前のEKSクラスタが作成されました。
Terraformコマンドの出力結果の最後に表示されるコマンドを実行して、作成したEKSクラスタに接続できる様にkubeconfigを書き換えます。
[cloudshell-user@ip-10-130-34-57 ~]$ aws eks --region us-west-2 update-kubeconfig --name terraform
Added new context arn:aws:eks:us-west-2:623649842711:cluster/terraform to /home/cloudshell-user/.kube/config
[cloudshell-user@ip-10-130-34-57 ~]$ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-10-0-12-137.us-west-2.compute.internal Ready <none> 8m49s v1.29.3-eks-ae9a62a
ip-10-0-39-27.us-west-2.compute.internal Ready <none> 8m49s v1.29.3-eks-ae9a62a
ちゃんとkubectl
コマンドで作成したEKSクラスタに接続できましたね!
Step 3 - EKSクラスタにCiliumをデプロイ
いよいよ、ciliumをインストールします。helmでインストールします、簡単ですねー
helm repo add cilium https://helm.cilium.io/
helm upgrade --install cilium cilium/cilium --version 1.14.7 \
--namespace kube-system \
--reuse-values -f ../values_cilium.yaml \
--set hubble.enabled=true \
--set hubble.tls.auto.enabled=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,icmp,http}" \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort \
--set hubble.relay.service.type=NodePort \
--set kubeProxyReplacement=strict \
--set encryption.enabled=false \
--set encryption.nodeEncryption=false \
--set routingMode=native \
--set ipv4NativeRoutingCIDR="0.0.0.0/0" \
--set bpf.masquerade=false \
--set nodePort.enabled=true \
--set autoDirectNodeRoutes=true \
--set hostLegacyRouting=false \
--set ingressController.enabled=true \
--set ingressController.loadbalancerMode=shared \
--set cni.chainingMode=aws-cni \
--set cni.install=true
[cloudshell-user@ip-10-130-34-57 terraform]$ pwd
/home/cloudshell-user/cilium-mesh-on-eks/terraform
[cloudshell-user@ip-10-130-34-57 ~]$ helm repo add cilium https://helm.cilium.io/
"cilium" has been added to your repositories
[cloudshell-user@ip-10-130-34-57 terraform]$ helm upgrade --install cilium cilium/cilium --version 1.14.7 \
> --namespace kube-system \
> --reuse-values -f ../values_cilium.yaml \
> --set hubble.enabled=true \
> --set hubble.tls.auto.enabled=true \
> --set hubble.metrics.enabled="{dns,drop,tcp,flow,icmp,http}" \
> --set hubble.relay.enabled=true \
> --set hubble.ui.enabled=true \
> --set hubble.ui.service.type=NodePort \
> --set hubble.relay.service.type=NodePort \
> --set kubeProxyReplacement=strict \
> --set encryption.enabled=false \
> --set encryption.nodeEncryption=false \
> --set routingMode=native \
> --set ipv4NativeRoutingCIDR="0.0.0.0/0" \
> --set bpf.masquerade=false \
> --set nodePort.enabled=true \
> --set autoDirectNodeRoutes=true \
> --set hostLegacyRouting=false \
> --set ingressController.enabled=true \
> --set ingressController.loadbalancerMode=shared \
> --set cni.chainingMode=aws-cni \
> --set cni.install=true
Release "cilium" does not exist. Installing it now.
NAME: cilium
LAST DEPLOYED: Sat Jul 20 08:30:59 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
You have successfully installed Cilium with Hubble Relay and Hubble UI.
Your release version is 1.14.7.
For any further help, visit https://docs.cilium.io/en/v1.14/gettinghelp
↑のコマンドのオプションの重要ポイントは以下です。
-
kubeProxyReplacement=strict
- kube-proxyをeBPFベース実装のものに置き換えます。 -
ingressController.enabled=true
- Cilium Ingressコントローラを有効にします。 -
--reuse-values -f ../values_cilium.yaml
-values_cilium.yaml
ファイルにIngressControllerのアノテーションが記載されています。これにより、インターネットからAWS Network Loadbalancer経由でCilium Ingressコントローラに接続できる様になります。
ingressController:
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
-
hubble.enabled=true
- ObservabilityツールであるHubbleを有効にします。
Cilium関連のPodが起動されているか確認してみましょう。
[cloudshell-user@ip-10-130-34-57 terraform]$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-load-balancer-controller-999bf8598-n6fmh 1/1 Running 0 39m
kube-system aws-load-balancer-controller-999bf8598-wkllq 1/1 Running 0 39m
kube-system aws-node-7bbjh 2/2 Running 0 37m
kube-system aws-node-7r4sp 2/2 Running 0 37m
kube-system cilium-5qm5f 1/1 Running 0 13m
kube-system cilium-7mdgf 1/1 Running 0 13m
kube-system cilium-operator-689df79c69-6dj27 1/1 Running 0 13m
kube-system cilium-operator-689df79c69-8n7jg 1/1 Running 0 13m
kube-system coredns-5b8cc885bc-96s2q 1/1 Running 0 12m
kube-system coredns-5b8cc885bc-fxxnp 1/1 Running 0 13m
kube-system hubble-relay-6f6f5476d9-5kh86 1/1 Running 0 13m
kube-system hubble-ui-644d9df97c-l72lc 2/2 Running 0 13m
kube-system kube-proxy-mffff 1/1 Running 0 38m
kube-system kube-proxy-xnkcn 1/1 Running 0 38m
それらしいPodがちゃんと起動していますね!
Cilium Ingressの為のNLBもLoadBalancerタイプのServiceとして作成されています。
[cloudshell-user@ip-10-130-34-57 terraform]$ kubectl get svc -A | grep cilium
kube-system cilium-ingress LoadBalancer 172.20.254.89 k8s-kubesyst-ciliumin-2ba9716b18-dfe80b478d25f342.elb.us-west-2.amazonaws.com 80:31121/TCP,443:31115/TCP 17m
values_cilium.yaml
ファイルで指定したとおり、internet-facing
で作成されていますねー
Step 3.1 - kube-proxyアドオンをアンインストール(オプション)
上述の通りkube-proxy
はCiliumで置き換えられますので、EKSアドオンとして稼動しているkube-proxy
は削除が可能です。
以下のコマンドで現状インストールされているアドオンを確認してみましょう。
aws eks list-addons --cluster-name terraform --region us-west-2
[cloudshell-user@ip-10-132-51-169 ~]$ aws eks list-addons --cluster-name terraform --region us-west-2
{
"addons": [
"coredns",
"kube-proxy", ← ★kube-proxyアドオンがインストールされている。
"vpc-cni"
]
}
kube-proxyアドオンがインストールされている事が分りますね。
では削除してみましょう。以下のコマンドで削除できます。
aws eks delete-addon --cluster-name terraform --addon-name kube-proxy --region us-west-2
[cloudshell-user@ip-10-132-51-169 terraform]$ aws eks delete-addon --cluster-name terraform --addon-name kube-proxy --region us-west-2
{
"addon": {
"addonName": "kube-proxy",
"clusterName": "terraform",
"status": "DELETING",
"addonVersion": "v1.29.0-eksbuild.1",
"health": {
"issues": []
},
"addonArn": "arn:aws:eks:us-west-2:623649842711:addon/terraform/kube-proxy/bac86796-b972-ec67-b07d-ba05add90120",
"createdAt": "2024-07-20T08:06:20.865000+00:00",
"modifiedAt": "2024-07-20T14:10:11.400000+00:00",
"tags": {
"Blueprint": "terraform",
"GithubRepo": "github.com/aws-ia/terraform-aws-eks-blueprints"
}
}
}
再度インストールされているアドオン一覧を確認しましょう。
[cloudshell-user@ip-10-132-51-169 terraform]$ aws eks list-addons --cluster-name terraform --region us-west-2
{
"addons": [
"coredns",
"vpc-cni"
]
}
削除されている事が分りますね!
kubectl get pod -A
を実行してみても先程まであったkube-proxy
Podが無くなっていました。cilium
Podが代りになってkube-proxy
の仕事をするみたいです。面白いですね!!
[cloudshell-user@ip-10-132-51-169 terraform]$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-load-balancer-controller-999bf8598-n6fmh 1/1 Running 0 6h9m
kube-system aws-load-balancer-controller-999bf8598-wkllq 1/1 Running 0 6h9m
kube-system aws-node-7bbjh 2/2 Running 0 6h8m
kube-system aws-node-7r4sp 2/2 Running 0 6h8m
kube-system cilium-5qm5f 1/1 Running 0 5h43m
kube-system cilium-7mdgf 1/1 Running 0 5h43m
kube-system cilium-operator-689df79c69-6dj27 1/1 Running 0 5h43m
kube-system cilium-operator-689df79c69-8n7jg 1/1 Running 0 5h43m
kube-system coredns-5b8cc885bc-96s2q 1/1 Running 0 5h43m
kube-system coredns-5b8cc885bc-fxxnp 1/1 Running 0 5h43m
kube-system hubble-relay-6f6f5476d9-5kh86 1/1 Running 0 5h43m
kube-system hubble-ui-644d9df97c-l72lc 2/2 Running 0 5h43m
最近発表されたアップデートで、Amazon VPC CNI
, CoreDNS
, kube-proxy
アドオンをインストールしないでEKSクラスタを構築できる様になりました。EKSクラスタ構築時点からCiliumを使うのであればここでインストールしない様にしておけば手間を省けますね。
Step 4 - サンプルアプリケーションをデプロイ
リポジトリ内にあるサンプルアプリをhelmでインストールします。
kubectl create namespace workshop
cd ..
cd productapp
helm install productapp . -n workshop
[cloudshell-user@ip-10-132-51-169 terraform]$ kubectl create namespace workshop
namespace/workshop created
[cloudshell-user@ip-10-132-51-169 terraform]$ cd ..
[cloudshell-user@ip-10-132-51-169 cilium-mesh-on-eks]$ cd productapp
[cloudshell-user@ip-10-132-51-169 productapp]$ helm install productapp . -n workshopNAME: productapp
LAST DEPLOYED: Sat Jul 20 14:29:42 2024
NAMESPACE: workshop
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Product Catalog Application is succesfully installed !
インストール成功したみたいですねー
Step 5 - サンプルアプリの構成を確認
サンプルアプリはFrontend
,Product Catalog
,Catalog Detail
という3種類のPodから構成されています。マイクロサービスアーキテクチャですね。
サンプルアプリの構成図(AWS公式サンプルのGitHubから引用)
サンプルアプリのk8sリソースは以下のコマンドで確認できます。
kubectl get deployment,pod,service -n workshop
[cloudshell-user@ip-10-132-51-169 productapp]$ kubectl get deployment,pod,service -n workshop
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/catalogdetail 1/1 1 1 9m58s
deployment.apps/catalogdetail2 1/1 1 1 9m58s
deployment.apps/frontend 1/1 1 1 9m58s
deployment.apps/productcatalog 1/1 1 1 9m58s
NAME READY STATUS RESTARTS AGE
pod/catalogdetail-5896fff6b8-4z48j 1/1 Running 0 9m58s
pod/catalogdetail2-7d7d5cd48b-zwdfq 1/1 Running 0 9m58s
pod/frontend-78f696695b-sgb79 1/1 Running 0 9m58s
pod/productcatalog-64848f7996-skk9d 1/1 Running 0 9m58s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/catalogdetail ClusterIP 172.20.189.226 <none> 3000/TCP 9m58s
service/frontend ClusterIP 172.20.5.113 <none> 9000/TCP 9m58s
service/productcatalog ClusterIP 172.20.134.52 <none> 5000/TCP 9m58s
catalogdetail
はバージョンが違うのか、2種類のDeployment,Podが作成されています。このあたり、Ciliumのサービスメッシュの機能であるTraffic Shiftingでproductcatalog
からのリクエストを振り分けられそうです。
Step 6 - サンプルアプリにアクセスするためにIngressを設定
エンドユーザからのアクセスを受け付けるためにはIngressを作成する必要があります。
以下のコマンドで作成します。
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace : workshop
name: productappingress # name given to the ingress
spec:
ingressClassName: cilium
rules:
- http:
paths:
- path: / # this rule applies to all requests that specifies this path
pathType: Prefix
backend:
service:
name: frontend # route all these requests to this service
port:
number: 9000 # route the requests to this port of the frontend service
EOF
ingressClassName
をcilium
で設定しているのが特徴的ですね。それ以外は通常のIngressと変らないシンプルな設定になっています。
[cloudshell-user@ip-10-132-51-169 productapp]$ cat <<EOF | kubectl apply -f -
> apiVersion: networking.k8s.io/v1
> kind: Ingress
> metadata:
> namespace : workshop
> name: productappingress # name given to the ingress
> spec:
> ingressClassName: cilium
> rules:
> - http:
> paths:
> - path: / # this rule applies to all requests that specifies this path
> pathType: Prefix
> backend:
> service:
> name: frontend # route all these requests to this service
> port:
> number: 9000 # route the requests to this port of the frontend service
> EOF
ingress.networking.k8s.io/productappingress created
[cloudshell-user@ip-10-132-51-169 productapp]$ kubectl get ingress -A
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
workshop productappingress cilium * k8s-kubesyst-ciliumin-2ba9716b18-dfe80b478d25f342.elb.us-west-2.amazonaws.com 80 11s
Ingressも正常に作成できました!
Step 7 - サンプルアプリにアクセス
ブラウザからサンプルアプリにアクセスしてみましょう。
以下のコマンドでURLを取得します。
CILIUM_INGRESS_URL=$(kubectl get svc cilium-ingress -n kube-system -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
echo "http://$CILIUM_INGRESS_URL"
[cloudshell-user@ip-10-132-51-169 productapp]$ CILIUM_INGRESS_URL=$(kubectl get svc cilium-ingress -n kube-system -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
[cloudshell-user@ip-10-132-51-169 productapp]$ echo "http://$CILIUM_INGRESS_URL"
http://k8s-kubesyst-ciliumin-2ba9716b18-dfe80b478d25f342.elb.us-west-2.amazonaws.com
URLが返ってきましたねー このURLをブラウザに入れるとサンプルアプリが表示されます。
httpプロトコルが原因だと思いますが、ブラウザをシークレットモードにしないと以下のメッセージが出てアプリが正常に表示されませんでした。
upstream connect error or disconnect/reset before headers. reset reason: connection failure
Githubのページにも書いてあったのですが、、気付かずアプリが悪いのかと思いログを見たりで時間を潰してしまいました。。。ご注意ください。
Step 8 - Cilium Hubbleにアクセスして可視化されたPod間の通信を確認する
上述の通りCiliumをhelmでインストールする際にHubbleを合せてインストールしています。
ちょっとHubbleに接続してみましょう。
Githubのページでは、以下のコマンドが紹介されています。
cilium hubble ui
このコマンドを実行するとポートフォワード設定が自動で行われてHubble画面を表示できる様になります。ただ、私はAWS Cloud Shellを使って検証を行っておりポートフォワーディングで自分のブラウザからアクセスができませんでした。。
なので、以下の様にHubble用のIngressを作ってインターネット経由でアクセスしました。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hubbleuiingress
namespace: kube-system
annotations:
ingress.cilium.io/loadbalancer-mode: dedicated
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
ingressClassName: cilium
rules:
- http:
paths:
- backend:
service:
name: hubble-ui
port:
number: 80
path: /
pathType: Prefix
ingress.cilium.io/loadbalancer-mode: dedicated
でこのIngressリソース専用のNLBを立てる様にしています。
このAnnotationを付与しないと、サンプルアプリのIngressリソースとNLBを共用しますが、Pathでの振り分けが上手くいかなかったのでNLBから分ける様にしました。
[cloudshell-user@ip-10-136-121-133 ~]$ kubectl apply -f hubbleui_ingress.yaml
ingress.networking.k8s.io/hubbleuiingress created
[cloudshell-user@ip-10-136-121-133 ~]$ kubectl get ingress -A
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
kube-system hubbleuiingress cilium * k8s-kubesyst-ciliumin-2a89af3008-e3d4b9f38bec70b3.elb.us-west-2.amazonaws.com 80 6s
workshop productappingress cilium * k8s-kubesyst-ciliumin-2ba9716b18-dfe80b478d25f342.elb.us-west-2.amazonaws.com 80 9h
作成されたNLBのDNS名をブラウザに入れてみましょう。Hubbleの画面が表示されました!各Pod間の繋りがちゃんと表示できています。
productcatalog
Podからcatalogdetail
Podとcatalogdetail2
の両方に線で伸びている事が分ります。
これはServiceがcatalogdetail
の1つだけ作成されており、このServiceからcatalogdetail
Podとcatalogdetail2
の両方に振り分けられる様に設定されているためです。
[cloudshell-user@ip-10-136-121-133 ~]$ kubectl get svc -n workshop
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
catalogdetail ClusterIP 172.20.189.226 <none> 3000/TCP 10h ← ★Serviceがcatalogdetailの一つだけ
frontend ClusterIP 172.20.5.113 <none> 9000/TCP 10h
productcatalog ClusterIP 172.20.134.52 <none> 5000/TCP 10h
[cloudshell-user@ip-10-136-121-133 ~]$ kubectl get deployment -n workshop
NAME READY UP-TO-DATE AVAILABLE AGE
catalogdetail 1/1 1 1 10h
catalogdetail2 1/1 1 1 10h
frontend 1/1 1 1 10h
productcatalog 1/1 1 1 10h
Step 9 - Ciliumサービスメッシュの機能でPodのTraffic Shifting を試す
catalogdetail
Podとcatalogdetail2
Podを使ってCiliumのTraffic Shiftingを試してみましょう。
まずは現状1つだったServiceリソースをcatalogdetail
とcatalogdetail2
のそれぞれに振り分けるために2つ作成します。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
labels:
app: catalogdetail
name: catalogdetailv1
namespace: workshop
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: catalogdetail
version: v1
---
apiVersion: v1
kind: Service
metadata:
labels:
app: catalogdetail
name: catalogdetailv2
namespace: workshop
spec:
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
selector:
app: catalogdetail
version: v2
EOF
selector
としてapp: catalogdetail
タグに加えてversion
タグを使う事でcatalogdetail
とcatalogdetail2
を区別します。
[cloudshell-user@ip-10-136-121-133 ~]$ cat <<EOF | kubectl apply -f -
> apiVersion: v1
> kind: Service
> metadata:
> labels:
> app: catalogdetail
> name: catalogdetailv1
> namespace: workshop
> spec:
> ports:
> - name: http
> port: 3000
> protocol: TCP
> targetPort: 3000
> selector:
> app: catalogdetail
> version: v1
> ---
> apiVersion: v1
> kind: Service
> metadata:
> labels:
> app: catalogdetail
> name: catalogdetailv2
> namespace: workshop
> spec:
> ports:
> - name: http
> port: 3000
> protocol: TCP
> targetPort: 3000
> selector:
> app: catalogdetail
> version: v2
> EOF
service/catalogdetailv1 created
service/catalogdetailv2 created
[cloudshell-user@ip-10-136-121-133 ~]$ kubectl get svc -n workshop
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
catalogdetail ClusterIP 172.20.189.226 <none> 3000/TCP 10h
catalogdetailv1 ClusterIP 172.20.31.251 <none> 3000/TCP 44s ← ★追加された
catalogdetailv2 ClusterIP 172.20.103.189 <none> 3000/TCP 44s ← ★追加された
frontend ClusterIP 172.20.5.113 <none> 9000/TCP 10h
productcatalog ClusterIP 172.20.134.52 <none> 5000/TCP 10h
次にTraffic Shifting の設定を行います。公式ものですと50%/50%で振り分ける設定になっていますが、Traffic Shiftingが効いているかより分りやすくするためcatalogdetailv1
:70%、catalogdetailv2
:30%で設定してみました。
cat <<EOF | kubectl apply -f -
apiVersion: cilium.io/v2
kind: CiliumEnvoyConfig
metadata:
name: traffic-shifting-test
namespace: workshop
spec:
services:
- name: catalogdetail
namespace: workshop
backendServices:
- name: catalogdetailv1
namespace: workshop
- name: catalogdetailv2
namespace: workshop
resources:
- "@type": type.googleapis.com/envoy.config.listener.v3.Listener
name: traffic-shifting-test
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: traffic-shifting-test
rds:
route_config_name: lb_route
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration
name: lb_route
virtual_hosts:
- name: "lb_route"
domains: [ "*" ]
routes:
- match:
prefix: "/"
route:
weighted_clusters:
clusters:
- name: "workshop/catalogdetailv1"
weight: 70 ← ★v1を70%に設定
- name: "workshop/catalogdetailv2"
weight: 30 ← ★v2を30%に設定
retry_policy:
retry_on: 5xx
num_retries: 3
per_try_timeout: 1s
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
name: "workshop/catalogdetailv1"
connect_timeout: 2s
lb_policy: ROUND_ROBIN
type: EDS
outlier_detection:
split_external_local_origin_errors: true
consecutive_local_origin_failure: 2
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
name: "workshop/catalogdetailv2"
connect_timeout: 2s
lb_policy: ROUND_ROBIN
type: EDS
outlier_detection:
split_external_local_origin_errors: true
consecutive_local_origin_failure: 2
EOF
[cloudshell-user@ip-10-136-121-133 ~]$ cat <<EOF | kubectl apply -f -
> apiVersion: cilium.io/v2
> kind: CiliumEnvoyConfig
> metadata:
> name: traffic-shifting-test
> namespace: workshop
> spec:
> services:
> - name: catalogdetail
> namespace: workshop
> backendServices:
> - name: catalogdetailv1
> namespace: workshop
> - name: catalogdetailv2
> namespace: workshop
> resources:
> - "@type": type.googleapis.com/envoy.config.listener.v3.Listener
> name: traffic-shifting-test
> filter_chains:
> - filters:
> - name: envoy.filters.network.http_connection_manager
> typed_config:
> "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
> stat_prefix: traffic-shifting-test
> rds:
> route_config_name: lb_route
> http_filters:
> - name: envoy.filters.http.router
> typed_config:
> "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
> - "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration
> name: lb_route
> virtual_hosts:
> - name: "lb_route"
> domains: [ "*" ]
> routes:
> - match:
> prefix: "/"
> route:
> weighted_clusters:
> clusters:
> - name: "workshop/catalogdetailv1"
> weight: 70
> - name: "workshop/catalogdetailv2"
> weight: 30
> retry_policy:
> retry_on: 5xx
> num_retries: 3
> per_try_timeout: 1s
> - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
> name: "workshop/catalogdetailv1"
> connect_timeout: 2s
> lb_policy: ROUND_ROBIN
> type: EDS
> outlier_detection:
> split_external_local_origin_errors: true
> consecutive_local_origin_failure: 2
> - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
> name: "workshop/catalogdetailv2"
> connect_timeout: 2s
> lb_policy: ROUND_ROBIN
> type: EDS
> outlier_detection:
> split_external_local_origin_errors: true
> consecutive_local_origin_failure: 2
> EOF
ciliumenvoyconfig.cilium.io/traffic-shifting-test created
[cloudshell-user@ip-10-136-121-133 ~]$ kubectl get ciliumenvoyconfig -n workshop
NAME AGE
traffic-shifting-test 101s
設定できました!
Traffic Shiftingが効いているか試してましょう。productcatalog
Podから↑で作成したServiceに対して10回連続でcurlを打ってみましょう。
productcatalogpod=$(kubectl get pods -n workshop | awk '{print $1}' | grep -e "productcatalog")
for i in {1..10}; do echo "Output $i:"; kubectl -n workshop exec -it $productcatalogpod -- curl catalogdetail:3000/catalogDetail; echo ""; done
[cloudshell-user@ip-10-136-121-133 ~]$ for i in {1..10}; do echo "Output $i:"; kubectl -n workshop exec -it $productcatalogpod -- curl catalogdetail:3000/catalogDetail; echo ""; done
Output 1:
{"version":"1","vendors":["ABC.com"]}
Output 2:
{"version":"2","vendors":["ABC.com, XYZ.com"]}
Output 3:
{"version":"1","vendors":["ABC.com"]}
Output 4:
{"version":"1","vendors":["ABC.com"]}
Output 5:
{"version":"1","vendors":["ABC.com"]}
Output 6:
{"version":"1","vendors":["ABC.com"]}
Output 7:
{"version":"2","vendors":["ABC.com, XYZ.com"]}
Output 8:
{"version":"2","vendors":["ABC.com, XYZ.com"]}
Output 9:
{"version":"1","vendors":["ABC.com"]}
Output 10:
{"version":"1","vendors":["ABC.com"]}
"version":"1"
が7回、"version":"2"
が3回返ってきました。Traffic Shiftingで設定した割合と同じですね。ちゃんと効いている様です!
まとめ
今回はGitHubで公開されているEKS上でCiliumを稼動させるサンプルを動かしてみました。
Ciliumを使う事で従来のkube-proxyやIngress Controllerが置き換わる事が判りとても勉強になりました。
また、Ciliumにはオブザーバビリティ機能であるHubbleも用意されており、これまでのEKSクラスタのコンポーネントの大部分を大胆に置き換わるものなのだなぁと実感しました。
今度は時間があればCiliumの性能検証なんかも試してみたいと思います。ではまた!