Linkerd による kubernetes クラスタ間通信
概要
Linkerd について
Linkerd は kubernetes でサービスメッシュを実現するための proxy です。
kubernetes 用のサービスメッシュでは Istio が有名ですが、linkerd も CNCF の Graduate project となっているためプロジェクトの成熟度は高く使用ユーザーも多いことが伺えます。Github Star は 2024/10 時点で約 10.6 k 程度。
linkerd は各 pod に proxy の役割を果たす proxy コンテナを inject し、proxy コンテナが linkerd の control plane と通信することでサービスメッシュを実現します(lstio における envoy と同じような感じ)。その他にも ドキュメント に記載されているように様々な機能がありますが、今回はこの中の Multi-cluster communication の機能を試してみます。
Linkerd におけるクラスタ間通信
linkerd では接続対象のクラスタの k8s service リソースを接続元のクラスタに複製し、この複製されたサービスを経由して接続先クラスタにアクセスする構成によりクラスタ間の通信を実現します(ドキュメントでは mirroring や service mirror 等と呼ばれている)。複製されたサービスの通信先は対象クラスタ上に存在する外部アクセス可能な Gateway となっており、これを経由して対象の svc, pod に接続しに行きます。そしてこの通信を制御するのが linkerd の micro proxy コンテナ (linkerd-proxy) となっています。linkerd ではこのような Gateway を経由してクラスタ間通信を実現する Hierarchical Network mode と、 gateway を使用せずクラスタの POD 間で直接通信を行う Flat Network mode (Pod-to-Pod 通信) もサポートされています。
Hierarchical Network mode と Flat Network mode の構成 (Multi-cluster communication より引用)
まずは Hierarchical Network mode によるクラスタ間通信の動作を確認していきます。
構築の準備
実行環境
クラスタ間通信のためには 2 つ以上のクラスタが必要となるので、ローカル環境の openstack 上に独立したネットワークを作成し、各ネットワーク内に以下のようにクラスタを構築します。linkerd のドキュメントでは各クラスタを east, west としているのでここでのクラスタ名も合わせます。
実行環境の構成図
ノード名や ip address は以下。
クラスタ名 | ノード名 | ip address | floating ip | kubernetes version |
---|---|---|---|---|
east | k8s-m1 | 10.0.0.40 | 192.168.3.131 | 1.30.0 |
east | k8s-w1 | 10.0.0.41 | 192.168.3.132 | 1.30.0 |
west | kata-m1 | 10.0.0.30 | 192.168.3.206 | 1.30.0 |
west | kata-w1 | 10.0.0.31 | 192.168.3.207 | 1.30.0 |
各ネットワークの CIDR は一致していますがネットワーク自体が独立しているため、各ノードの IP アドレスではお互いに通信することができない構成にしています。ただ openstack 側で floating IP を付加しているため、floating ip 経由ではアクセスできるようになっています。
今回は openstack 上のネットワークで上記の構成としていますが、同様のネットワーク構成であればパブリッククラウド上でも同様に検証できるかと思います(要確認)。
クラスタ間通信の前提条件
クラスタ間通信に必要な環境や前提条件は Requirements に書いてあるので見ていきます。
Two clusters.
これは 2 つのクラスタを用意すれば ok
A control plane installation in each cluster that shares a common trust anchor. If you have an existing installation, see the trust anchor bundle documentation to understand what is required.
2 つのクラスタでそれぞれ linkerd をインストールする際に共通の trust anchor を指定する必要があります。後述の手順の中で実行します。
Each of these clusters should be configured as kubectl contexts.
各クラスタを操作できるように kubeconfig 内に各クラスタの context を追加する必要があります。
Elevated privileges on both clusters. We’ll be creating service accounts and granting extended privileges, so you’ll need to be able to do that on your test clusters.
クラスタの Link (後述) を実行する際に Service Account などが作成されるので、リソースを作成できる権限が必要になります。今回はテストなのでクラスタの admin 権限で操作しますが、必要に応じて適切な権限を設定します。
Support for services of type LoadBalancer in the east cluster. Check out the documentation for your cluster provider or take a look at inlets. This is what the west cluster will use to communicate with east via the gateway.
クラスタ間通信で使用される Gateway は k8s svc リソースの LoadBalancer
type として作成されますが、クラスタ外から通信できるように EXTERNAL-IP を設定する必要があります。なので上記の条件は EXTERNAL-IP を付加できるような provider が必要であることを示しています。
今回の検証では openstack 上に構築しているため、cloud-provider-openstack を使って openstack のロードバランサー (octavia) から IP アドレスを付加するようにします。ネットワーク構成によっては MetalLB とかで代用できる他、パブリッククラウド上で構築する場合は各クラウドが提供するロードバランサーとの連携機能が利用できます。
構築
クラスタ間通信までの流れは大まかに以下のようになります。
- Trust Anchor Bundle の作成
- linkerd CRD のインストール
- linkerd (control plane) のインストール
- linkerd viz のインストール(多分任意)
- linkerd multicluster のインストール
- クラスタの Link
基本的には Installing Multi-cluster Components の手順に沿って実行します。内容がやや被っていますが Multi-cluster communication にも上記より詳しめの手順やデモアプリを使った検証が記載されているので適宜参照。
Trust Anchor Bundle の作成
マルチクラスタ間の通信では共有の trust anchor certificate を利用して通信を暗号化するため、まずアプリケーションの証明書を作成する必要があります。これは実際にクラスタ間で linkerd-proxy が mTLS 通信を行う際に使用される模様。
証明書は openssl や step で作成することができますが、ドキュメントでは step で作成する手順 が記載されているのでそのまま実行します。step のインストールは Install step を参照。
CA 証明証を作成。
step certificate create root.linkerd.cluster.local ca.crt ca.key \
--profile root-ca --no-password --insecure
issuer 証明書とキーペアを作成。
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
--profile intermediate-ca --not-after 8760h --no-password --insecure \
--ca ca.crt --ca-key ca.key
これにより以下の証明書、キーが作成されます。
ca.crt
ca.key
issuer.crt
issuer.key
Linkerd のインストール
Linkerd の各コンポーネントは helm でインストールできます。
east クラスタ上で以下を実行していきます。まずリポジトリを追加。
helm repo add linkerd-edge https://helm.linkerd.io/edge
後でいろいろ使うので linkerd の CLI をインストールします。手順は Step 1: Install the CLI にあるもので ok。
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install-edge | sh
# Add path to .zshrc
echo 'export PATH=$HOME/.linkerd2/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
次に linkerd CRD をインストールする必要があります。CRD も helm でインストールできますが、手元で試してみるとエラーが発生してうまくいかなかっため、ここでは linkerd CLI から直接インストールします。
# これでインストールできるはずだが以下のエラーとなる
$ helm install linkerd-crds linkerd-edge/linkerd-crds -n linkerd --create-namespace
Error: INSTALLATION FAILED: Unable to continue with install: CustomResourceDefinition "grpcroutes.gateway.networking.k8s.io" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "linkerd-crds"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "linkerd"
linkerd install --crds | kubectl apply -f -
次に linkerd control plane をインストール。これにより linkerd control plane を構築するための pod 等が作成され、任意の pod に linkerd proxy を注入できるようになります。インストール時に先程作成した TrustAnchors, issuer のファイルを指定。
helm install linkerd-control-plane \
-n linkerd \
--set-file identityTrustAnchorsPEM=ca.crt \
--set-file identity.issuer.tls.crtPEM=issuer.crt \
--set-file identity.issuer.tls.keyPEM=issuer.key \
linkerd-edge/linkerd-control-plane --create-namespace
次に linkerd-viz
をインストール。これにより linkerd 用の dashboard やモニタリング関連の pod が作成されます。クラスタ間通信ではおそらく使用されませんが、ドキュメントに記載があるのでインストールしておきます。
helm install linkerd-viz -n linkerd-viz --create-namespace linkerd-edge/linkerd-viz
次に multicluster をインストール
linkerd multicluster install | kubectl apply -f -
helm install linkerd-multicluster -n linkerd-multicluster --create-namespace linkerd-edge/linkerd-multicluster
インストールによって linkerd-multicluster
namespace が作成され、Gateway pod や svc などが作成されます。svc は type: LoadBalancer で作成されるので外部の provider 等によって EXTERNAL-IP
が付加される必要があります。今回の検証では openstack 側から 外部アクセス可能な ip が付加されるように設定しているため、 EXTERNAL-IP として 192.168.3.179
が設定されました。
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
linkerd-gateway LoadBalancer 10.111.187.50 192.168.3.179 4143:30681/TCP,4191:30778/TCP 3h51m
east クラスタ上で上記の設定が終わったら west クラスタでも同様に multicluster のインストールまで実行します。
クラスタの Link
クラスタ間通信を行うためにはクラスタの link を実行する必要があります。link では link 元のクラスタ名、link 先の context 名が必要となるので事前に確認。
$ k config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* east east admin default
west sub-k8s sub-k8s-admin test
linkerd multicluster link
コマンドで各クラスタを link するためのマニフェストを作成します。ここでは east のクラスタ名は east
としているので --cluster-name east
を指定してコマンドを実行、マニフェストが出力されれば ok
linkerd multicluster link --cluster-name east
これを west クラスタで apply することで link が完了します。
$ linkerd multicluster link --cluster-name east | kubectl --context=west apply -f -
secret/cluster-credentials-east created
secret/cluster-credentials-east created
link.multicluster.linkerd.io/east created
clusterrole.rbac.authorization.east.io/linkerd-service-mirror-access-local-resources-east created
clusterrolebinding.rbac.authorization.east.io/linkerd-service-mirror-access-local-resources-east created
role.rbac.authorization.east.io/linkerd-service-mirror-read-remote-creds-east created
rolebinding.rbac.authorization.east.io/linkerd-service-mirror-read-remote-creds-east created
serviceaccount/linkerd-service-mirror-east created
deployment.apps/linkerd-service-mirror-east created
service/probe-gateway-east created
各クラスタで linkerd multicluster check
を実行して link が正常に完了したか確認。例えば以下では west クラスタが east クラスタの api server に接続できずにエラーとなっています。
$ linkerd multicluster check
linkerd-multicluster
--------------------
√ Link CRD exists
√ Link resources are valid
* east
× remote cluster access credentials are valid
* failed to connect to API for cluster: [east]: Get "https://10.0.0.40:6443/version?timeout=30s": dial tcp 10.0.0.40:6443: connect: no route to host
see https://linkerd.io/2/checks/#l5d-smc-target-clusters-access for hints
× clusters share trust anchors
Problematic clusters:
* east: unable to fetch anchors: Get "https://10.0.0.40:6443/api/v1/namespaces/linkerd/configmaps/linkerd-config?timeout=30s": dial tcp 10.0.0.40:6443: connect: no route to host
see https://linkerd.io/2/checks/#l5d-multicluster-clusters-share-anchors for hints
√ service mirror controller has required permissions
* east
√ service mirror controllers are running
* east
× probe services able to communicate with all gateway mirrors
probe-gateway-east.linkerd-multicluster mirrored from cluster [east] has no endpoints
see https://linkerd.io/2/checks/#l5d-multicluster-gateways-endpoints for hints
√ multicluster extension proxies are healthy
√ multicluster extension proxies are up-to-date
√ multicluster extension proxies and cli versions match
Status check results are ×
link では実行したクラスタ内の kubeconfig を読み取ってマニフェストに出力するため、kubeconfig 内の api server のアドレスはクラスタ外部から接続可能な ip address に指定する必要があります。実際に linkerd multicluster link --cluster-name east
実行時のマニフェストを見てみると data.kubeconfig
に kubeconfig を base64 encode したものが書いてあります。base64 decode すると中身を確認可能。
kubeconfig 内の cluster.server を外部接続できる ip address に修正した上で再度 link を実行。west クラスタ側で linkerd multicluster check
を実行してエラーが出なければ ok。
$ linkerd --context=west multicluster check
linkerd-multicluster
--------------------
√ Link CRD exists
√ Link resources are valid
east
√ remote cluster access credentials are valid
east
√ clusters share trust anchors
east
√ service mirror controller has required permissions
east
√ service mirror controllers are running
east
√ probe services able to communicate with all gateway mirrors
east
√ all mirror services have endpoints
√ all mirror services are part of a Link
√ multicluster extension proxies are healthy
√ multicluster extension proxies are up-to-date
√ multicluster extension proxies and cli versions match
Status check results are √
クラスタの link が正常に完了すると、マニフェストを kubectl apply
クラスタ(ここでは west)側で links.multicluster.linkerd.io
リソースが作成されます。このリソースでは接続先クラスタの情報や Gateway の external ip などの情報が含まれています。
$ k describe links.multicluster.linkerd.io east
Name: east
Namespace: linkerd-multicluster
Labels: <none>
Annotations: <none>
API Version: multicluster.linkerd.io/v1alpha1
Kind: Link
Metadata:
Creation Timestamp: 2024-09-29T10:58:25Z
Generation: 1
Resource Version: 205716
UID: 456d4cff-b6bc-4d18-823a-2fd162ed64ec
Spec:
Cluster Credentials Secret: cluster-credentials-east
Gateway Address: 192.168.3.179
Gateway Identity: linkerd-gateway.linkerd-multicluster.serviceaccount.identity.linkerd.cluster.local
Gateway Port: 4143
Probe Spec:
Failure Threshold: 3
Path: /ready
Period: 3s
Port: 4191
Timeout: 30s
Remote Discovery Selector:
Match Labels:
mirror.linkerd.io/exported: remote-discovery
Selector:
Match Labels:
mirror.linkerd.io/exported: true
Target Cluster Domain: cluster.local
Target Cluster Linkerd Namespace: linkerd
Target Cluster Name: east
Events: <none>
ちなみにこの状態では west → east は link されていますが east → west の link は完了していない状態なので、east クラスタ側で link リソースは作成されていません。
$ k get links.multicluster.linkerd.io
No resources found in linkerd-multicluster namespace.
east → west の link も行うには上記と同様に west クラスタ側で生成したマニフェストを east クラスタ側で kubectl apply する必要があります。
$ linkerd --context=west multicluster link --cluster-name sub-k8s | kubectl --context=east apply -f -
クラスタ間通信の動作確認
クラスタの Link まで完了したので、後はクラスタ間通信に使用する service リソースに mirror.linkerd.io/exported: "true"
のラベルを設定して公開することで他クラスタから通信できるようになります。Multi-cluster communication ではデモアプリを使って動作確認を行っているのでこれを使ってもいいですが、今後の拡張性も含めてここではシンプルな nginx pod を使って検証します。
また、linkerd では pod 内に inject された linker-proxy コンテナが通信を制御するので、nginx pod 内にコンテナを入れる必要があります。これは linkerd inject コマンドで入れるか namespace に annotation を設定する ことで追加できるので、ここでは後者にします。
上記のリソースをまとめて作成するためのマニフェストは以下。
---
apiVersion: v1
kind: Namespace
metadata:
name: test-linkerd
annotations:
linkerd.io/inject: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: test-linkerd
labels:
mirror.linkerd.io/exported: "true"
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx-test
namespace: test-linkerd
labels:
mirror.linkerd.io/exported: "true"
app: nginx
spec:
selector:
app: nginx
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
これを kubectl apply -f nginx.yml
で east クラスタ側にデプロイします。クラスタ内に mirror.linkerd.io/exported: "true"
のラベルが設定された svc が作成されると、link されているクラスタに通信用の mirror svc が作成されます。
実際やってみると svc を作成した namespace が link 先クラスタにないと作成されないようなので、west クラスタにも test-linkerd
namespace を作成。すると west クラスタに [元サービス名]-[クラスタ名]
という名前のサービスが自動で作成されていることが確認できます。
# east クラスタ
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-test ClusterIP 10.108.193.135 <none> 80/TCP 20h
$ ctx west
Switched to context "west".
# west クラスタ
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-test-east ClusterIP 10.100.61.162 <none> 80/TCP 20h
west クラスタ側で endpoint も同時に作成され、宛先には east 側の gateway サービスに設定された external-ip 192.168.3.179
が設定されます。
$ k get endpoints -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: Endpoints
metadata:
annotations:
mirror.linkerd.io/remote-gateway-identity: linkerd-gateway.linkerd-multicluster.serviceaccount.identity.linkerd.cluster.local
mirror.linkerd.io/remote-svc-fq-name: nginx-test.test-linkerd.svc.cluster.local
creationTimestamp: "2024-09-29T12:53:02Z"
labels:
mirror.linkerd.io/cluster-name: east
mirror.linkerd.io/mirrored-service: "true"
name: nginx-test-east
namespace: test-linkerd
resourceVersion: "222971"
uid: 9e9893c8-6086-42e9-b9ec-774efa1ffa0b
subsets:
- addresses:
- ip: 192.168.3.179
ports:
- port: 4143
protocol: TCP
kind: List
metadata:
resourceVersion: ""
実際に west → east クラスタへのクラスタ間通信ができるか確認するために、west クラスタにも linkerd-proxy を設定した pod を作成します。pod については通信確認できれば何でもいいので先程の nginx マニフェストを流用します。
---
apiVersion: v1
kind: Namespace
metadata:
name: test-linkerd
annotations:
linkerd.io/inject: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: test-linkerd
labels:
mirror.linkerd.io/exported: "true"
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
pod を作成して kubectl exec
で nginx コンテナに接続、nginx-test-east
サービスに向けて curl を実行します。
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-test-east ClusterIP 10.100.61.162 <none> 80/TCP 20h
$ k exec -it nginx-7745d7cf5c-h9gp2 -c nginx -- bash
root@nginx-7745d7cf5c-h9gp2:/# curl nginx-test-east
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@nginx-7745d7cf5c-h9gp2:/#
nginx のレスポンスが返ってきているので正常に east クラスタの nginx pod に接続できていること確認できます。east クラスタの pod 側のログを見てみると、west クラスタの nginx pod の ip アドレス 10.244.1.57
からの通信がアクセスログに記録されています。
$ k logs nginx-d556bf558-lhc25 nginx
10.244.1.57 - - [29/Sep/2024:12:47:24 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.88.1" "-"
このときの経路は west クラスタの nginx pod → west クラスタの nginx-test-east
svc → east クラスタの Gateway svc → east クラスタの nginx svc → east クラスタの nginx pod という経路になっています。
経路の概要
また、west クラスタ側の pod から定期的に curl を実行してみます。
while true; do curl nginx-test-east; sleep 1;done
このときの通信を east クラスタ側の linkerd viz の web で確認すると、gateway から対象の nginx pod に向けた通信が発生していることが確認できます。ちなみに prometheus, tap は linkerd-viz インストール時に作成される pod に対応。
east クラスタの linkerd web
一方で west クラスタ側の linkerd web もみてみると、具体的な宛先は表示されませんが 192.168.3.179
への通信が発生していることが確認できます。これは east クラスタの gateway の EXTERNAL-IP となっているので、こちら側からも nginx pod → gateway に向けた通信が発生していることが確認できます。
west クラスタの linkerd web
このように service mirror
によって作成される svc にアクセスすることでクラスタを超えて pod に通信することが可能となります。
ちなみにクラスタ間の通信は pod に注入された linkerd-proxy を介して行われるため、linkerd-proxy が注入されていない pod からクラスタ間通信を行うとするとうまくいきません。
$ curl nginx-test-east -v
* Trying 10.100.61.162:80...
* Connected to nginx-test-east (10.100.61.162) port 80 (#0)
> GET / HTTP/1.1
> Host: nginx-test-east
> User-Agent: curl/7.88.1
> Accept: */*
>
* Empty reply from server
* Closing connection 0
curl: (52) Empty reply from server
Pod-to-Pod 通信
linkerd のクラスタ間通信ではもう一つのモードとして Gateway を使用せず、各クラスタの Pod 間で直接通信を行う Flat network mode (Pod-to-Pod 通信) がサポートされています。Gateway を使用する方法と比較すると以下のメリットがあるようです。
- Gateway を経由しないのでレイテンシが改善する。
- Gateway を使う方法では LoadBalancer type のサービスに EXTERNAL-IP を設定するため、パブリッククラウドでは各種ロードバランサー等と組み合わせて使用する必要がある。Pod-to-Pod 通信ではこの部分をまるごと削除できるのでその分のコストが削減できる。
- 通信間で workload identity が保持される。workload identity に関してはこのあたりに記事がある。
Pod-to-Pod 通信では Gateway を使用しないので EXTERNAL-IP が設定可能という前提条件はありませんが、代わりにクラスタ上の Pod が別クラスタの Pod に直接アクセス可能な Flat Network 上に各クラスタが構築されているという条件が必要になります。例えば AWS では pod にサブネット内の IP アドレスが割り当てられており、その IP アドレスにアクセスすると pod に到達できるような構成が該当します。
Flat Network では linkerd を使わなくても Pod 間で直接通信可能な状態になっているので、わざわざ linkerd を使ってクラスタ間通信する必要はないのでは?という疑問が湧いてきますが、Enterprise multi-cluster at scale: supporting flat networks in Linkerd にこれに対する回答が書いてあります。要は通常の k8s クラスタでlinkerd を使う動機と同様で、linkerd のセキュリティや可観測性を享受できるメリットがあるから、とのこと。
If pods are routable, why use Linkerd? For exactly the same reasons you’re using it within the cluster: to provide the security, reliability, and observability guarantees beyond what a baseline TCP connection provides.
上記の検証で使用した east, west クラスタではネットワークが分離されているので、ここでは west クラスタと同じネットワーク上に新しく north クラスタを設定します。
クラスタ名 | ノード名 | ip address | floating ip | kubernetes version |
---|---|---|---|---|
west | kata-m1 | 10.0.0.30 | 192.168.3.206 | 1.30.0 |
west | kata-w1 | 10.0.0.31 | 192.168.3.207 | 1.30.0 |
north | linkerd-m1 | 10.0.0.32 | 192.168.3.208 | 1.30.0 |
pod-to-pod 通信の手順は以下に書いてあります。
multicluster install の際に --gateway=false
を指定することで、gateway が作成されず pod-to-pod 通信のモードになります。
linkerd multicluster install --gateway=false | kubectl apply -f -
helm install linkerd-multicluster -n linkerd-multicluster --create-namespace linkerd-edge/linkerd-multicluster \
--set gateway.enabled=false
クラスタの Link は gateway のときと同様ですが、こちらも --gateway=false
を指定します。
linkerd --context west multicluster link --cluster-name=west --gateway=false | kubectl --context north apply -f -
動作確認のため west クラスタに以下の nginx pod, svc を作成します。
- ローカルの環境では Flat network を構築するのが難しいので、ここでは pod で
hostNetwork: true
を指定して Pod の ip アドレスに node の ip アドレスに指定する。 - サービスを公開するため、svc に
mirror.linkerd.io/exported: remote-discovery
のラベルを設定
---
apiVersion: v1
kind: Namespace
metadata:
name: pod-to-pod-linkerd
annotations:
linkerd.io/inject: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: pod-to-pod-linkerd
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx:
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx-test
namespace: pod-to-pod-linkerd
labels:
mirror.linkerd.io/exported: remote-discovery
app: nginx
spec:
selector:
app: nginx
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
north クラスタには同じ namespace を作成
apiVersion: v1
kind: Namespace
metadata:
name: pod-to-pod-linkerd
annotations:
linkerd.io/inject: enabled
作成された nginx pod は node と同じ ip アドレス 10.0.0.31
が割り当てられており、north クラスタからもアクセス可能な状態になっています。
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-7b49b57ff8-gr7ls 1/1 Running 0 19m 10.0.0.31 kata-w1 <none> <none>
# north クラスタノードから curl を実行
$ curl 10.0.0.31
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
north クラスタでは上記の pod にアクセスするための mirroring service が作成されます。svc 名は gateway のときと同じで [元サービス名]-[link クラスタ名]
になります。
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-test-west ClusterIP 10.108.191.96 <none> 80/TCP 22m
north クラスタに検証用の pod を作成し、先ほどと同様に north クラスタ内の svc にアクセスすると west クラスタの pod に到達します。
$ k exec -it nginx-6cfb64b7c5-p69bf -c nginx -- bash
root@nginx-6cfb64b7c5-p69bf:/# curl nginx-test-west
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
このときの west クラスタ側の nginx のログでは、上記の north クラスタの nginx pod が起動したノードの IP アドレス 10.0.0.32
からのアクセスログが記録されます。
10.0.0.32 - - [03/Oct/2024:16:55:03 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.88.1" "-"
Discussion