创建服务
在 Kubernetes 中,Service 是一种用于暴露运行在集群中一个或多个 Pod 上的网络应用的方法。
目录
为什么需要 Service
-
Pod 有自己的 IP,但:
-
Service 通过提供以下功能解决了这个问题:
-
稳定的 IP 和 DNS 名称。
-
自动负载均衡到匹配的 Pods。
ClusterIP 类型 Service 示例:
# simple-service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 80
- 可用的 type 值及其行为包括
ClusterIP
、NodePort
、LoadBalancer
、ExternalName
- Service 目标的 Pod 集合通常由你定义的 selector 决定。
Service
端口。
- 将 Service 的
targetPort
绑定到 Pod 的 containerPort
。此外,也可以引用 Pod 容器下的 port.name
。
Headless Service(无头服务)
有时你不需要负载均衡和单一的 Service IP,这种情况下可以创建所谓的无头服务:
无头服务适用于:
-
你想要发现单个 Pod 的 IP,而不仅仅是单一的服务 IP。
-
你需要直接连接到每个 Pod(例如,像 Cassandra 或 StatefulSet 这类数据库)。
-
你使用 StatefulSet,且每个 Pod 必须有稳定的 DNS 名称。
通过 Web 控制台创建服务
-
进入 Container Platform。
-
在左侧导航栏点击 Network > Services。
-
点击 Create Service。
-
参考以下说明配置相关参数。
参数 | 说明 |
---|
虚拟 IP 地址 | 如果启用,将为该 Service 分配一个 ClusterIP,可用于集群内的服务发现。 如果禁用,则创建无头服务,通常用于 StatefulSet。 |
类型 | - ClusterIP:在集群内部 IP 上暴露 Service。选择此值时,Service 只能从集群内部访问。
- NodePort:在每个节点的 IP 上以静态端口(NodePort)暴露 Service。
- ExternalName:将 Service 映射到 externalName 字段的内容(例如,主机名 api.foo.bar.example)。
- LoadBalancer:使用外部负载均衡器在外部暴露 Service。Kubernetes 本身不直接提供负载均衡组件,你需要自行提供,或者将 Kubernetes 集群与云服务商集成。
|
目标组件 | - Workload:Service 会将请求转发到特定的工作负载,匹配标签如
project.cpaas.io/name: projectname 和 service.cpaas.io/name: deployment-name 。
- Virtualization:Service 会将请求转发到特定的虚拟机或虚拟机组。
- Label Selector:Service 会将请求转发到带有指定标签的某类工作负载,例如
environment: release 。
|
端口 | 用于配置该 Service 的端口映射。以下示例中,集群内其他 Pod 可以通过虚拟 IP(如果启用)和 TCP 端口 80 调用该 Service;访问请求将被转发到目标组件 Pod 外部暴露的 TCP 端口 6379 或 redis。- 协议:Service 使用的协议,支持的协议包括:
TCP 、UDP 、HTTP 、HTTP2 、HTTPS 、gRPC 。 - Service 端口:Service 在集群内暴露的端口号,即 Port,例如 80。
- 容器端口:Service 端口映射到的目标端口号(或名称),即 targetPort,例如 6379 或 redis。
- Service 端口名称:会自动生成,格式为
<protocol>-<service port>-<container port> ,例如:tcp-80-6379 或 tcp-80-redis。
|
会话亲和性 | 基于源 IP 地址(ClientIP)的会话亲和性。如果启用,来自同一 IP 地址的所有访问请求在负载均衡期间将保持在同一服务器上,确保同一客户端的请求被转发到同一服务器处理。 |
-
点击 Create。
通过 CLI 创建服务
kubectl apply -f simple-service.yaml
基于已有的部署资源 my-app
创建服务。
kubectl expose deployment my-app \
--port=80 \
--target-port=8080 \
--name=test-service \
--type=NodePort \
-n p1-1
示例:集群内访问应用
# access-internal-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip
spec:
type: ClusterIP
selector:
app: nginx
ports:
- port: 80
targetPort: 80
-
应用该 YAML:
kubectl apply -f access-internal-demo.yaml
-
启动另一个 Pod:
kubectl run test-pod --rm -it --image=busybox -- /bin/sh
-
在 test-pod
Pod 中访问 nginx-clusterip
服务:
wget -qO- http://nginx-clusterip
# 或使用 Kubernetes 自动创建的 DNS 记录:<service-name>.<namespace>.svc.cluster.local
wget -qO- http://nginx-clusterip.default.svc.cluster.local
你应该能看到包含 “Welcome to nginx!” 字样的 HTML 响应。
示例:集群外访问应用
# access-external-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
-
应用该 YAML:
kubectl apply -f access-external-demo.yaml
-
查看 Pods:
kubectl get pods -l app=nginx -o wide
-
curl 访问 Service:
curl http://{NodeIP}:{nodePort}
你应该能看到包含 “Welcome to nginx!” 字样的 HTML 响应。
当然,也可以通过创建 LoadBalancer 类型的 Service 从集群外访问应用。
注意:请提前配置 LoadBalancer 服务。
# access-external-demo-with-loadbalancer.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-lb-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
-
应用该 YAML:
kubectl apply -f access-external-demo-with-loadbalancer.yaml
-
获取外部 IP 地址:
kubectl get svc nginx-lb-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service LoadBalancer 10.0.2.57 34.122.45.100 80:30005/TCP 30s
EXTERNAL-IP
即为你从浏览器访问的地址。
curl http://34.122.45.100
你应该能看到包含 “Welcome to nginx!” 字样的 HTML 响应。
如果 EXTERNAL-IP 显示为 pending
,说明 LoadBalancer 服务尚未在集群中部署。
示例:ExternalName 类型 Service
apiVersion: v1
kind: Service
metadata:
name: my-external-service
namespace: default
spec:
type: ExternalName
externalName: example.com
-
应用该 YAML:
kubectl apply -f external-service.yaml
-
在集群内的 Pod 中尝试解析:
kubectl run test-pod --rm -it --image=busybox -- sh
然后执行:
nslookup my-external-service.default.svc.cluster.local
你会看到它解析为 example.com
。
LoadBalancer 类型 Service 注解
AWS EKS 集群
有关 EKS LoadBalancer Service 注解的详细说明,请参阅 Annotation Usage Documentation 。
Key | Value | 说明 |
---|
service.beta.kubernetes.io/aws-load-balancer-type | external: 使用官方 AWS LoadBalancer Controller。 | 指定 LoadBalancer 类型的控制器。
注意:请提前联系平台管理员部署 AWS LoadBalancer Controller。 |
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type | - instance:流量通过 NodePort 发送到 Pods。
- ip:流量直接路由到 Pods(集群必须使用 Amazon VPC CNI)。
| 指定流量如何到达 Pods。 |
service.beta.kubernetes.io/aws-load-balancer-scheme | - internal:私有网络。
- internet-facing:公网网络。
| 指定使用私有网络还是公网网络。 |
service.beta.kubernetes.io/aws-load-balancer-ip-address-type | | 指定支持的 IP 地址栈。 |
华为云 CCE 集群
有关 CCE LoadBalancer Service 注解的详细说明,请参阅 Annotation Usage Documentation 。
Key | Value | 说明 |
---|
kubernetes.io/elb.id | | 填写云负载均衡器的 ID,必须使用已有的云负载均衡器。 |
kubernetes.io/elb.autocreate | 示例:{"type":"public","bandwidth_name":"cce-bandwidth-1551163379627","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","available_zone":["cn-north-4b"],"l4_flavor_name":"L4_flavor.elb.s1.small"}
注意:请先阅读 填写说明,并根据需要调整示例参数。 | 新建云负载均衡器。 |
kubernetes.io/elb.subnet-id | | 集群所在子网的 ID。当 Kubernetes 版本为 1.11.7-r0 或更低时,创建新云负载均衡器时必须填写此字段。 |
kubernetes.io/elb.class | - union:共享负载均衡。
- performance:独享负载均衡,仅支持 Kubernetes 1.17 及以上版本。
| 指定新建云负载均衡器的类型,详情请参阅 独享与共享弹性负载均衡的区别。 |
kubernetes.io/elb.enterpriseID | | 指定新建云负载均衡器所属的企业项目。 |
Azure AKS 集群
有关 AKS LoadBalancer Service 注解的详细说明,请参阅 Annotation Usage Documentation 。
Key | Value | 说明 |
---|
service.beta.kubernetes.io/azure-load-balancer-internal | | 指定使用私有网络还是公网网络。 |
Google GKE 集群
有关 GKE LoadBalancer Service 注解的详细说明,请参阅 Annotation Usage Documentation 。
Key | Value | 说明 |
---|
networking.gke.io/load-balancer-type | Internal | 指定使用私有网络。 |
loud.google.com/l4-rbs | enabled | 默认为公网。如果配置此参数,流量将直接路由到 Pods。 |