|
| 1 | +本节,我们将通过实际的例子来体验`Service`所提供的功能。 |
| 2 | + |
| 3 | +## 创建 |
| 4 | +创建`Service`对象时,`Kubernetes`会根据`spec.selector`来查找拥有指定标签的`Pod`,查找到`Pod`就维护一组拓扑关系,如果查找不到也不会自动创建`Pod`(配置中没有`Pod`模版),所以本例中用到的`Pod`对象需要单独创建,在开始之前,假定我们已使用前面介绍`Deployment`时使用的配置创建了一组label为`app: nginx`的`Pod`对象,这些`Pod`通过端口`80`对外提供服务。 |
| 5 | + |
| 6 | +首先,我们将以下配置保存到名为`service.yaml`的文件中: |
| 7 | +``` |
| 8 | +apiVersion: v1 |
| 9 | +kind: Service |
| 10 | +metadata: |
| 11 | + name: nginx-service |
| 12 | +spec: |
| 13 | + selector: |
| 14 | + app: nginx |
| 15 | + ports: |
| 16 | + - protocol: TCP |
| 17 | + port: 80 |
| 18 | + targetPort: 80 |
| 19 | +``` |
| 20 | +然后,创建`Service`对象: |
| 21 | +``` |
| 22 | +[root@ecs-d8b6 manifests]# kubectl create -f service.yaml |
| 23 | +service/nginx-service created |
| 24 | +``` |
| 25 | +## 查看 |
| 26 | +接着查看刚刚创建的`Service`对象: |
| 27 | +``` |
| 28 | +[root@ecs-d8b6 manifests]# kubectl get services nginx-service -o wide |
| 29 | +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR |
| 30 | +nginx-service ClusterIP 10.0.0.83 <none> 80/TCP 56s app=nginx |
| 31 | +``` |
| 32 | +命令行输出中各字段含义如下: |
| 33 | +- NAME:`Service`对象名称,对应配置中的`metadata.name`; |
| 34 | +- TYPE:`Service`类型,默认为`ClusterIP`类型,更多的类型将在后面的章节中介绍; |
| 35 | +- CLUSTER-IP:自动分配的`Cluster IP`; |
| 36 | +- EXTERNAL-IP:外部IP地址,用于接收集群外部流量的地址,在后面介绍`Service`类型时详细介绍; |
| 37 | +- PORT(S):`Service`对外暴露的端口列表,本例中只对外暴露一个端口,对应配置中的`spec.ports`; |
| 38 | +- AGE:创建至今经历的时间; |
| 39 | +- SELECTOR:标签选择器,`Service`根据此选择器查看后端`Pod`,对应配置中的`spec.selector`。 |
| 40 | + |
| 41 | +当前`Kubernetes`支持多种`Service`类型,来应对不同的使用场景: |
| 42 | +- ClusterIP:Service通过一个只能在集群内部访问的 Cluster IP来暴露服务; |
| 43 | +- NodePort:Service通过Node上的某个端口来暴露服务; |
| 44 | +- LoadBalancer:Service通过具体云厂商提供的负载均衡器来暴露服务; |
| 45 | +- ExternalName:Service仅对外暴露一个域名; |
| 46 | + |
| 47 | +### 查看Pod 拓扑 |
| 48 | +尽管`Service`会通过`selector`来查找`Pod`,但查找到的`Pod`信息并不直接记录到`Service`对象中,而是记录到一个`Endpoints`对象中,进一步说当创建`Service`对象时,`Kubernetes`还会创建一个同名的`Endpoints`对象,来记录后端的`Pod`拓扑。 |
| 49 | +关于`Endpoints`,我们会在后续的章节中详细介绍,此处仅做初步介绍。 |
| 50 | + |
| 51 | +查看随`Service`一并创建的`Endpoints`对象: |
| 52 | +``` |
| 53 | +[root@ecs-d8b6 manifests]# kubectl get endpoints nginx-service |
| 54 | +NAME ENDPOINTS AGE |
| 55 | +nginx-service 172.17.0.4:80,172.17.0.5:80,172.17.0.6:80 20m |
| 56 | +``` |
| 57 | +可以看到,该`Endpoints`对象记录了`Service`匹配到的所有`Pod`地址。 |
| 58 | + |
| 59 | +### 访问Service |
| 60 | +在集群内部,可以直接访问`Service`的`Cluster IP`,流量将会被自动转发到后端的某个`Pod`中: |
| 61 | +``` |
| 62 | +[root@ecs-d8b6 manifests]# curl 10.0.0.83 |
| 63 | +<!DOCTYPE html> |
| 64 | +<html> |
| 65 | +<head> |
| 66 | +... |
| 67 | +</head> |
| 68 | +<body> |
| 69 | +<h1>Welcome to nginx!</h1> |
| 70 | +... |
| 71 | +</body> |
| 72 | +</html> |
| 73 | +``` |
| 74 | + |
| 75 | +## 更新 |
| 76 | +当更新`Service`的`spec.selector`时,`Kubernetes`会自动按照新的`spec.selector`配置查找`Pod`,并更新`Endpoints`对象。 |
| 77 | + |
| 78 | +使用`kubectl edit service nginx-service`命令来修改`Service`,并指定一个无法匹配到任何`Pod`的`spec.selector`,可以看到 |
| 79 | +`Endpoints`对象中的`Pod`拓扑信息也会相应地消失掉,如下所示: |
| 80 | +``` |
| 81 | +[root@ecs-d8b6 manifests]# kubectl get endpoints nginx-service |
| 82 | +NAME ENDPOINTS AGE |
| 83 | +nginx-service <none> 31m |
| 84 | +``` |
| 85 | +## 删除 |
| 86 | +当删除`Service`对象时,随`Service`对象创建而自动创建的`Endpoints`对象也会一并删除,后端的`Pod`不会被删除,它仍然受相应的`Pod`控制器管理。 |
| 87 | + |
| 88 | +``` |
| 89 | +[root@ecs-d8b6 manifests]# kubectl delete service nginx-service |
| 90 | +service "nginx-service" deleted |
| 91 | +[root@ecs-d8b6 manifests]# kubectl get endpoints nginx-service |
| 92 | +Error from server (NotFound): endpoints "nginx-service" not found |
| 93 | +[root@ecs-d8b6 manifests]# kubectl get pods |
| 94 | +NAME READY STATUS RESTARTS AGE |
| 95 | +nginx-deployment-5f67bd6bb-9nspj 1/1 Running 0 37m |
| 96 | +nginx-deployment-5f67bd6bb-hl8xw 1/1 Running 0 37m |
| 97 | +nginx-deployment-5f67bd6bb-pkv7h 1/1 Running 0 37m |
| 98 | +``` |
0 commit comments