作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/240906085714/
相关话题:https://www.cnsre.cn/tags/kubernetes/
实现Kubernetes跨Namespace Service访问的最佳实践
在Kubernetes运维场景中,经常会遇到跨Namespace(名称空间)的Service访问需求。为了实现不同Namespace下的Pod能够通过Service名称进行跨Namespace访问,我们可以利用Kubernetes的ExternalName
类型Service来解决这个问题。
在本文中,我将展示如何配置和实现这种跨Namespace的通信。我们将通过一个完整的示例来详细说明配置过程和关键步骤。
1. 场景需求
假设我们有两个不同Namespace下的两个Service和Pod:
- Namespace A:ServiceA (PodA)
- Namespace B:ServiceB (PodB)
我们希望实现PodA通过ServiceB的名称进行通信,而不是通过Service的IP地址。由于Service的IP地址可能会在重启时发生变化,而Service的名称则保持不变,这样可以确保通信的稳定性。
2. 创建Service和Pod
首先,我们需要为两个Namespace分别创建对应的Pod和Service。
在myns
Namespace中创建Pod和Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
apiVersion: v1
kind: Namespace
metadata:
name: myns
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy1
namespace: myns
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: v1
template:
metadata:
labels:
app: myapp
release: v1
spec:
containers:
- name: myapp
image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myapp-clusterip1
namespace: myns
spec:
type: ClusterIP
selector:
app: myapp
release: v1
ports:
- name: http
port: 80
targetPort: 80
|
在mytest
Namespace中创建Pod和Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
apiVersion: v1
kind: Namespace
metadata:
name: mytest
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy2
namespace: mytest
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: v2
template:
metadata:
labels:
app: myapp
release: v2
spec:
containers:
- name: myapp
image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v2
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myapp-clusterip2
namespace: mytest
spec:
type: ClusterIP
selector:
app: myapp
release: v2
ports:
- name: http
port: 80
targetPort: 80
|
3. 检查创建结果
运行以下命令来应用这些YAML文件并检查Service和Pod的状态:
1
2
3
4
5
6
|
kubectl apply -f deply_service_myns.yaml
kubectl apply -f deply_service_mytest.yaml
kubectl get svc -n myns -o wide
kubectl get svc -n mytest -o wide
kubectl get pod -A -o wide
|
4. 跨Namespace Service通信问题
在默认情况下,PodA无法通过Service名称直接访问Namespace B中的Service。下面是PodA尝试访问PodB的日志输出:
1
2
3
|
# kubectl exec -it -n myns myapp-deploy1-36ds6g873r8-asy2us sh
/ # ping myapp-clusterip2
ping: bad address 'myapp-clusterip2'
|
这是因为默认的Kubernetes DNS解析只支持在同一Namespace内解析Service名称。
5. 解决方案:使用ExternalName
类型的Service
为了解决这个问题,我们可以在每个Namespace中创建一个ExternalName
类型的Service。ExternalName
允许通过指定的FQDN(完全限定域名)来指向其他Namespace中的Service。
以下是实现跨Namespace通信的Service配置:
在myns
Namespace中创建ExternalName
Service
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: v1
kind: Service
metadata:
name: myapp-clusterip1-externalname
namespace: myns
spec:
type: ExternalName
externalName: myapp-clusterip2.mytest.svc.cluster.local
ports:
- name: http
port: 80
targetPort: 80
|
在mytest
Namespace中创建ExternalName
Service
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: v1
kind: Service
metadata:
name: myapp-clusterip2-externalname
namespace: mytest
spec:
type: ExternalName
externalName: myapp-clusterip1.myns.svc.cluster.local
ports:
- name: http
port: 80
targetPort: 80
|
运行以下命令来应用这些新的Service配置:
1
|
kubectl apply -f svc_ExternalName_visit.yaml
|
6. 验证跨Namespace通信
现在我们可以再次尝试从PodA访问PodB,应该可以成功解析并进行通信:
1
2
|
kubectl exec -it -n myns myapp-deploy1-36ds6g873r8-asy2us sh
/ # ping myapp-clusterip2.mytest.svc.cluster.local
|
这样,PodA就可以通过Service名称访问不同Namespace中的PodB了。
7. 总结
通过使用Kubernetes的ExternalName
类型Service,我们成功实现了跨Namespace的Service名称解析和通信。此方法避免了直接使用IP地址通信的局限性,确保了即使Service的IP地址发生变化,通信依然可以通过名称进行。
这种跨Namespace通信的场景在多租户、多环境隔离的Kubernetes集群中尤为常见。如果你的集群架构中需要不同Namespace之间的Service互访,ExternalName
是一个有效的解决方案。
作者:SRE运维博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/240906085714/
相关话题:https://www.cnsre.cn/tags/kubernetes/