前言

Pod 需要一种寻找其他 pod 的方法来使用其他 pod 提供的服务,不像在没有 Kubernetes 的世界,系统管理员要在用户端配置文件中明确指出服务的精确的 IP 地址或者主机名来配置每个客户端应用,但是同样的方式在 Kubernetes 中并不适用,因为:

pod 的是短暂,随时启动或者关闭,客户端不能提前知道 pod 的 IP,多个 pod 提供相同的服务;水平伸缩意味着多个 pod 可能会提供相同的服务 – 每个 pod 都有自己的 IP 地址,客户端无须关心后端提供服务 pod 的数量,以及各自对应的 IP 地址。它们无须记录每个 pod的 IP 地址。所有的 pod 可以通过一个单一的 IP 地址进行访问。

为了解决上述问题,Kubernetes 提供了一种资源类型——服务
(service)

Service

Service: 提供单一不变的接入点的资源,服务的 IP 不会变,变的是 pod 的 IP;

创建 service

使用之前的 rs_test.yaml

labels:
        app: rs-nginx

containerPort 80

service_test.yaml

apiVersion: v1
kind: Service
metadata:
  name: service-nginx
spec:
  ports: 
  - port: 8080			//该服务的端口
    targetPort: 80		//转发到的容器端口
  selector:
    app: rs-nginx		//具有app=rs-nginx标签的 pod 都属于该 service

查看 service 描述信息,Endpoints 为所有服务管理的 pod。当然,一般就绪探针正常的才会被添加到 endpoint 中

$ kubectl apply -f service_test.yaml
$ kubectl describe   services service-nginx
Name:              service-nginx
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=rs-nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.103.127.82
IPs:               10.103.127.82
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.16:80,10.244.1.144:80,10.244.2.245:80
Session Affinity:  None
Events:            <none>

通过 service clusterIP 访问服务

$ curl 10.103.127.82:8080
<!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>

当然可以暴露多个端口

spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
    - name: https
      port: 443
      targetPort: 8443

通过 dns 来发现访问服务

kubernetes 内部 pod 的 dns server 都指向 kube-dns 的服务地址,所以通过访问 FQDN 连接服务,如上面创建的 service,default 为 namespace,如果同一个 namespace,也可以直接访问 service-nginx。

service-nginx.default.svc.cluster.local
$ kubectl get services -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   26d

$ kubectl exec rs-nginx-7tmjq -- cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

$ dig service-nginx.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.8 <<>> service-nginx.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32397
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;service-nginx.default.svc.cluster.local. IN A

;; ANSWER SECTION:
service-nginx.default.svc.cluster.local. 30 IN A 10.103.127.82		// clusterIP

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Dec 06 23:24:30 CST 2021
;; MSG SIZE  rcvd: 123

将服务暴露给外部客户端

可以将 Service 的类型设置为 NodePort,LoadBalance 和 Ingress。可以见下章 4.2 对三种 Service 的解析。

需要注意
外部访问时,客户端的 IP 是不被记录的,因为当通过节点端口接收连接时,对数据包执行了 SNAT。

headless

也可以创建 headless 服务,headless 没有 clusterIP,通过 DNS 直接发现 pod IP。DNS 服务器会返回多个 A 记录;
可以通过设置 clusterIP 为 None 来创建;
修改之前的 services

$ kubectl edit  services service-nginx
spec:
  clusterIP: None
  clusterIPs:
  - None
$ dig service-nginx.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.8 <<>> service-nginx.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54321
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;service-nginx.default.svc.cluster.local. IN A

;; ANSWER SECTION:
service-nginx.default.svc.cluster.local. 30 IN A 10.244.1.144
service-nginx.default.svc.cluster.local. 30 IN A 10.244.2.245
service-nginx.default.svc.cluster.local. 30 IN A 10.244.0.16

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Dec 06 23:52:59 CST 2021
;; MSG SIZE  rcvd: 233
Logo

开源、云原生的融合云平台

更多推荐