Skip to content

Latest commit

 

History

History

chapter_cilium

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Cilium

What is Ciliumで説明されるように、CiliumはKubernetesクラスターやその他のクラウドネイティブ環境にネットワーキング、セキュリティ、可観測性を提供するオープンソースプロジェクトです。 Ciliumの基盤となっているのは、eBPFと呼ばれるLinuxカーネルの技術であり、セキュリティや可視性、ネットワーク制御ロジックをLinuxカーネルに動的に挿入することが可能です。 eBPFについてはeBPF.ioをご確認ください。

(出典:https://github.com/cilium/cilium/blob/36b7802b2e5c3e5a3f262b53a5d7abe8bbac18c4/Documentation/images/cilium-overview.png)

CNI (Container Network Interface)

Ciliumは広義的にはCNIの1つとして挙げられます。

  • CNIとは、Cloud Native Computing Foundationプロジェクトの1つになります
  • CNIは、LinuxやWindowsコンテナーのネットワーク機能を抽象化し、APIインターフェイス仕様として切り出したものです
  • コンテナのネットワーク接続性にのみ関与し、コンテナが削除されると割り当てられたリソースを削除します
  • CNIの仕様など詳細については、こちらをご参照ください

Cilium以外にもCNIとして提供されているプラグインは数多くあります。 その中のいくつかをご紹介します。

  • Flannel
    • シンプルなセットアップで利用可能で、Kubernetesクラスター内でのネットワーク通信を容易にするために適しています
    • VXLANやHost-GWモードを使用したオーバーレイネットワークにもサポートしてます
    • 単一Kubernetesクラスターのシンプルなネットワーキングが必要なときや、シンプルな設定と高い拡張性が求められる場合に適しています
  • Calico
    • BGPを使用したルーティングでスケーラビリティが高いと言われています
    • セキュリティポリシーやセグメンテーションの管理が可能です
    • また、ポリシードリブンで柔軟な通信制御も可能です
    • 大規模かつ複雑なネットワーク環境がある場合や、セキュリティポリシーを重視し、通信の制御が必要な場合に適しています
  • Weave
    • メッシュネットワークを提供し、コンテナの動的な発見が可能です
    • オーバーレイネットワークをサポートしており、シンプルで軽量な設計です
    • 動的なワークロードディスカバリが必要な場合や、シンプルで効率的なネットワーキングが求められる場合に適しています

Components

Ciliumは下記の主要コンポーネントで構成されています。 詳細についてはComponent Overviewをご参照ください。

  • Agent
    • Kubernetesクラスターの各ノードで実行され、Kubernetes APIサーバーとの接続を確立し、ネットワークおよびセキュリティポリシーを維持する役割を果たします
    • Linuxカーネルがコンテナのネットワークアクセスを制御するために使用するeBPFプログラムの管理を行います
  • Operator
    • Kubernetesクラスター全体に対して実行されるタスクの管理を行います
    • 構成にもよりますが、一時的に利用できなくてもKubernetesクラスターは機能し続けます
  • Client(CLI)
    • Cilium Agentとともにインストールされるコマンドラインツールです
    • 同じノード上で動作するCilium AgentのREST APIと対話を行うことができ、Agentの状態やステータスの検査ができます
    • Ciliumのインストールや管理、トラブルシュートなどに使用されるCLIとは別物になります
  • CNI Plugin
    • PodがNode上でスケジュールまたは終了される時にKubernetesによって呼び出されます
    • Cilium APIと対話し、ネットワーキング/ロードバランシング/ネットワークポリシーを提供するために必要な設定を起動します

chapter Cluster Createで導入したCiliumに対して、上記のコンポーネントを簡単に確認してみます。

最初にAgentはDaemonSetリソース、OperatorはDeploymentリソースとしてデプロイされていることを確認します。

kubectl get -n kube-system -l app.kubernetes.io/part-of=cilium ds,deploy

下記のような出力になるはずです。hubble-relayやhubble-uiに関してはchapter_hubbleにて説明します。

NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/cilium   3         3         3       3            3           kubernetes.io/os=linux   113m

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cilium-operator   2/2     2            2           113m
deployment.apps/hubble-relay      1/1     1            1           113m
deployment.apps/hubble-ui         1/1     1            1           113m

次に、Cilium AgentにインストールされるClient CLIのバージョンを確認します。

kubectl exec -n kube-system ds/cilium -c cilium-agent -- cilium version

下記のようにバージョンが確認できます。

Client: 1.16.1 68579055 2024-08-13T13:29:59+00:00 go version go1.22.5 linux/amd64
Daemon: 1.16.1 68579055 2024-08-13T13:29:59+00:00 go version go1.22.5 linux/amd64

この章ではCiliumの機能として下記について説明します。

  • Networking
    • Network Policy
  • ServiceMesh
    • Ingress
    • Gateway API
    • Traffic Management

Networkingに関しては、Netowrk Policyを利用した特定のPodに対するL7のトラフィック制御を行います。 ServiceMeshに関しては、まず初めに、CiliumのIngressClassを設定したIngressリソースを利用するデモを行います。 次に、トラフィックを9:1に分割するデモをGateway APIとCiliumのEnvoy Configを利用した2パターン説明します。 今回はトラフィック分割のデモのみですが、他にもヘッダー変更、URLの書き換えなど行うことができます。 その他の例については下記のページをご参照ください。

Note

Observabilityについてはchapter_hubbleにて説明します。

Networking

Network Policy

Ciliumでは3種類のリソースでNetwork Policyを定義できます。 詳細はNetwork Policyを参照してください。

  • NetworkPolicy
    • PodのIngress/Egressに対しL3/L4のポリシーを定義することが可能です
    • 詳細はNetwork Policiesを参照してください
  • CiliumNetworkPolicy
    • NetworkPolicyリソースとよく似ていますが、NetworkPolicyと異なりL7のポリシーを定義することが可能です
  • CiliumClusterwideNetworkPolicy
    • クラスター全体のポリシーを設定するためのリソースです
    • CiliumNetworkPolicyと同じ設定が可能ですが、CiliumNetworkPolicyと異なり名前空間の指定はありません

この節ではCiliumNetworkPolicyの動作確認を行います。

動作確認はchapter_cluster-createでデプロイしたアプリケーションを利用します。 また、このアプリケーションに接続するためのクライアントを2種類デプロイします。

kubectl run curl-allow -n handson --image=curlimages/curl --labels="app=curl-allow" --command -- sleep infinity
kubectl run curl-deny  -n handson --image=curlimages/curl --labels="app=curl-deny"  --command -- sleep infinity

下記図のような構成になります。

現状は何も設定を行っていないので、curl-allow/curl-denyの両方から//colorにアクセスできます。 また、HTTPステータスコードはすべて200が返ってきます。

kubectl exec -n handson curl-allow -- /bin/sh -c "echo -n 'curl-allow -> /     : ';curl -s -o /dev/null handson:8080 -w '%{http_code}\n'"
kubectl exec -n handson curl-allow -- /bin/sh -c "echo -n 'curl-allow -> /color: ';curl -s -o /dev/null handson:8080/color -w '%{http_code}\n'"
kubectl exec -n handson curl-deny  -- /bin/sh -c "echo -n 'curl-deny  -> /     : ';curl -s -o /dev/null handson:8080 -w '%{http_code}\n'"
kubectl exec -n handson curl-deny  -- /bin/sh -c "echo -n 'curl-deny  -> /color: ';curl -s -o /dev/null handson:8080/color -w '%{http_code}\n'"

下記のような実行結果になります。

curl-allow -> /     : 200
curl-allow -> /color: 200
curl-deny  -> /     : 200
curl-deny  -> /color: 200

動作確認として下記設定のCiliumNetworkPolicyをデプロイしてみます。

  • /へはcurl-allowからのみアクセス可能
  • /colorへはcurl-allowcurl-denyの両方からアクセスが可能
kubectl apply -f manifest/cnp.yaml

CiliumNetworkPolicyリソースをデプロイした後に先ほどと同じコマンドを打ってみてください。

kubectl exec -n handson curl-allow -- /bin/sh -c "echo -n 'curl-allow -> /     : ';curl -s -o /dev/null handson:8080 -w '%{http_code}\n'"
kubectl exec -n handson curl-allow -- /bin/sh -c "echo -n 'curl-allow -> /color: ';curl -s -o /dev/null handson:8080/color -w '%{http_code}\n'"
kubectl exec -n handson curl-deny  -- /bin/sh -c "echo -n 'curl-deny  -> /     : ';curl -s -o /dev/null handson:8080 -w '%{http_code}\n'"
kubectl exec -n handson curl-deny  -- /bin/sh -c "echo -n 'curl-deny  -> /color: ';curl -s -o /dev/null handson:8080/color -w '%{http_code}\n'"

すると、curl-denyから/へのアクセスがHTTPステータスコード403でできなくなっています。 このように、Ciliumでは、CiliumNetworkPolicyを利用することで、L7のトラフィック制御が可能です。

curl-allow -> /     : 200
curl-allow -> /color: 200
curl-deny  -> /     : 403
curl-deny  -> /color: 200

Note

L3/L4のポリシーとL7のポリシーでルール違反の際の挙動が変わります。 L3/L4のポリシーに違反した場合は、パケットがDropされますが、L7のポリシー違反の場合は、HTTP 403 Access Deniedが返されます。 上記の例ではパスベースの制御が行われており、L7ポリシーのルール違反になるため、HTTP 403 Access Deniedとなります。

次節へ行く前に、作成したCiliumNetworkPolicyリソースを削除しておきます。

kubectl delete -f manifest/cnp.yaml

Service Mesh

Ingress

CiliumはIngressリソースをサポートしており、第1章でIngress NGINX Controllerをデプロイしましたが、Ingress NGINX Controllerを使わずとも、Cilium単体でIngressリソースを利用できます。 Ingressリソースを利用するためには、CiliumのHelm ChartでingressController.enabled: trueを指定する必要があります。 この設定はすでにchapter_cluster-createで行っており、現時点でIngressリソースは利用できる状態になっています。 詳細についてはKubernetes Ingress Supportを参照ください。

この節では、IngressClassとしてCiliumを利用したトラフィックルーティングのデモを行います。 Ingressリソースを利用するためには、ingressClassNameフィールドにciliumを設定したIngressをアプライすればIngressリソースを利用できます。

kubectl apply -f manifest/ingress.yaml

app.cilium.example.comの名前解決が可能な端末から、curlコマンドでHTTPステータスコード200が返ってくることを確認します。

curl -I app.cilium.example.com:8080

下記のような応答が返ってきます。

HTTP/1.1 200 OK
accept-ranges: bytes
content-length: 1395
content-type: text/html; charset=utf-8
last-modified: Tue, 22 Jun 2021 05:40:33 GMT
date: Wed, 01 Nov 2023 18:08:01 GMT
x-envoy-upstream-service-time: 0
server: envoy

Gateway API

CiliumはGateway APIをサポートしており、Gateway APIを利用することで、トラフィックの分割、ヘッダー変更、URLの書き換えなどのより高度なルーティング機能を利用することが可能です。 この節ではGateway APIを利用したトラフックの分割を行います。 Gateway APIの詳細はKubernetes Gateway APIを参照してください。

まず、デモのために第1章でデプロイしたblueイメージに加えて、yellowイメージをデプロイします。 また、yellowイメージとblueイメージのそれぞれにアクセスするためのServiceリソースを作成します。

kubectl apply -Rf ../chapter_cluster-create/manifest/app -n handson -l color=yellow
kubectl apply -f manifest/service.yaml

次に、トラフィック分割機能を利用して下記のように9:1にトラフィックを分割してみます。

トラフィックを分割するためにGatewayリソースとHTTPRouteリソースをデプロイします。

kubectl apply -n handson  -f manifest/gateway_api.yaml

上記をデプロイすると、GatewayリソースとHTTPRouteリソース、そしてGatewayリソースに紐付くServiceリソースのType:Loadbalancerが作成されます。

kubectl get gateway,httproute,svc -n handson
NAME                                         CLASS    ADDRESS        PROGRAMMED   AGE
gateway.gateway.networking.k8s.io/color-gw   cilium                  True         52s

NAME                                                HOSTNAMES   AGE
httproute.gateway.networking.k8s.io/color-route-1               52s

NAME                              TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
service/cilium-gateway-color-gw   LoadBalancer   10.96.50.28     <pending>   80:32720/TCP   52s
service/handson                   ClusterIP      10.96.131.226   <none>         8080/TCP       24m
service/handson-blue              ClusterIP      10.96.164.242   <none>         8080/TCP       113s
service/handson-yellow            ClusterIP      10.96.189.95    <none>         8080/TCP       113s

ここで、Type:LoadbalancerのEXTERNAL-IPが<pending>表示になっていることが分かります。 ServiceリソースのType:Loadbalancerとは、awsやGoogle Cloudなどのクラウドプロバイダーで利用できる外部のロードバランサーを利用するためのリソースになります。 そのため、別途ロードバランサーが必要になるのですが、今回のハンズオン環境では用意していないので、<pending>表示のまま固まっています。

クラウドプロバイダーで利用できる外部のロードバランサーと説明しましたが、オンプレミスやローカルの開発環境でもType:Loadbalancerを利用することは可能です。 やり方はいろいろありますが、有名なものとしてはMetalLBを利用する方法があげられます。 今回はせっかくCiliumについて学んでいるので、Cilium v1.14からサポートが始まったL2 Announcementを利用してみましょう。

Note

L2 Announcementの詳細についてはここで解説しませんが、より深く知りたい方は 公式ドキュメント: L2 AnnouncementCilium L2 Announcement を使ってみるを参照してください。

Warning

ハンズオン作成時点で、L2 Announcementはβ機能なので本番利用には注意が必要です。

L2 Announcementを利用するためには、現行の設定に加えて、追加でCiliumL2AnnouncementPolicyCiliumLoadBalancerIPPoolを設定する必要があります。 下記コマンドでリソースを適用しましょう。

kubectl apply -f manifest/l2announcement.yaml

再度ServiceリソースのType:Loadbalancerを確認すると、EXTERNAL-IPが振られていることが分かります。 docker network kindのIP帯を設定しているため、dockerを起動しているホストからのみアクセスすることが可能です。

kubectl get svc -n handson
NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
cilium-gateway-color-gw   LoadBalancer   10.96.36.91     172.18.0.200   80:30183/TCP   12m
handson                   ClusterIP      10.96.238.128   <none>         8080/TCP       24m
handson-blue              ClusterIP      10.96.244.167   <none>         8080/TCP       23m
handson-yellow            ClusterIP      10.96.80.215    <none>         8080/TCP       23m

Warning

manifest/l2announcement.yamlでデプロイしたCiliumLoadBalancerIPPoolリソースのspec.blocksに設定する値は、docker kindネットワークのアドレス帯から選択する必要があります。 今回は既に設定済みのため意識する必要はありせんが、別環境でL2 Announcementを利用するときには注意してください。

ServiceリソースのType:LoadbalancerのIPアドレスを取得します。

LB_IP=$(kubectl get -n handson svc -l io.cilium.gateway/owning-gateway=color-gw -o=jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')

取得したIPアドレス宛に10回ほどアクセスし、おおよそ9:1に分散していることを確認します。

for in in {1..10}; do \
echo -n "Color is "
curl ${LB_IP}/color;echo
sleep 0.1
done

次節へ行く前に、作成したGatewayリソースとHTTPRouteリソースを削除しておきます。

kubectl delete -f manifest/gateway_api.yaml

Note

今回のようなルーティング機能はCilium Service Meshの機能を利用しても提供することができます。 次節でCilium Service Meshを利用したトラフィック分割のデモを説明します。

Traffic Management

Ciliumでは、Network Policyで定義されたL7トラフィックなどの処理にEnvoyを利用します。 デフォルトでEnvoyはCiliumのAgentに埋め込まれていますが、Deploymentリソースとして外だしすることも可能です。 cilium statusコマンドを実行することで、現在どちらのモードで動作しているか確認することが可能です。

cilium status

Envoy DaemonSetがdisabledであれば、Cilium AgentにEnvoyが埋め込まれて動作しています。

    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       OK
    \__/       ClusterMesh:        disabled

Deployment             cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2
DaemonSet              cilium-envoy       Desired: 3, Ready: 3/3, Available: 3/3
Deployment             hubble-relay       Desired: 1, Ready: 1/1, Available: 1/1
Deployment             hubble-ui          Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet              cilium             Desired: 3, Ready: 3/3, Available: 3/3
Containers:            cilium-operator    Running: 2
                       cilium-envoy       Running: 3
                       hubble-ui          Running: 1
                       hubble-relay       Running: 1
                       cilium             Running: 3
Cluster Pods:          21/21 managed by Cilium
Helm chart version:    
Image versions         hubble-relay       quay.io/cilium/hubble-relay:v1.16.1@sha256:2e1b4c739a676ae187d4c2bfc45c3e865bda2567cc0320a90cb666657fcfcc35: 1
                       cilium             quay.io/cilium/cilium:v1.16.1@sha256:0b4a3ab41a4760d86b7fc945b8783747ba27f29dac30dd434d94f2c9e3679f39: 3
                       cilium-operator    quay.io/cilium/operator-generic:v1.16.1@sha256:3bc7e7a43bc4a4d8989cb7936c5d96675dd2d02c306adf925ce0a7c35aa27dc4: 2
                       cilium-envoy       quay.io/cilium/cilium-envoy:v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51@sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b: 3
                       hubble-ui          quay.io/cilium/hubble-ui:v0.13.1@sha256:e2e9313eb7caf64b0061d9da0efbdad59c6c461f6ca1752768942bfeda0796c6: 1
                       hubble-ui          quay.io/cilium/hubble-ui-backend:v0.13.1@sha256:0e0eed917653441fded4e7cdb096b7be6a3bddded5a2dd10812a27b1fc6ed95b: 1

Envoyの設定は、CRDとして定義されたCiliumEnvoyConfigCiliumCllusterwideEnvoyConfigを利用することで、L7トラフィック制御が可能です。 詳細はL7-Aware Traffic Managementを参照してください。

EnvoyのSupported API versionsにも記載がありますが、Envoy APIにはv1/v2/v3の3種類が存在します。 このうちCiliumでは、Envoy API v3のみをサポートしています。 なお、Envoy Extension Resource Typeへの対応状況に関してはEnvoy extensions configuration fileを確認してください。

この節では、envoy.filters.http.routerを利用したトラフィックシフトを行います。

handson-blue"に10%、handson-yellowに90%のトラフィックを流すように設定します。

kubectl apply -f manifest/cec.yaml

下記コマンドを実行すると、handson-blue"に10%、handson-yellowに90%のトラフィックが流れることが確認できます。

for in in {1..10}; do \
kubectl exec -n handson curl-allow -- /bin/sh -c "echo -n 'curl-allow: Color is ';curl -s handson:8080/color -w '\n'"
sleep 0.1
done

確認が終わったら本章でデプロイしたリソースを削除しておきます。

kubectl delete -f manifest/cec.yaml
kubectl delete -Rf ../chapter_cluster-create/manifest/app -n handson -l color=yellow
kubectl delete -f manifest/service.yaml
kubectl delete -n handson pod curl-allow --force
kubectl delete -n handson pod curl-deny  --force