k8s in action 服务

service,是在 pod 上层定义的资源对象,为了对集群内外部提供一个统一,稳定的访问入口。
为什么需要呢?
pod 短暂,ip 易变,服务使得水平伸缩不影响服务提供。

在内部创建和测试服务

image.png
三种方式从集群内部测试服务

  1. 创建一个 pod,从 pod 内部请求服务 cluster-ip,然后通过 pod 日志查看服务响应
  2. 使用 ssh 登陆 k8s 集群一个 node,使用 curl 命令
  3. 使用 kubectl exec 命令在集群已存在 pod 中执行 curl 命令
1
kubectl exec podname -- curl -s http://cluster-ip

同一个服务可暴露多个端口,在 spec.ports 中写就行

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443

如果在 pod 中给端口命名了,spec.containers.ports.name=http ,spec.containers.ports.containerPort=8080,在 service 中 targetPort 就可以直接用 port 的名字 。
image.png
pod 中的 client,或则 node 中的 curl 怎么发现服务呢,怎么通过 cluster-ip 访问到服务的呢?

  • 通过环境变量 kubectl exec podname env
  • 通过 DNS
  • 通过 FQDN
1
2
3
4
5
6
kubectl exec -it podname bash
#容器中
curl http://kubia.default.svc.cluster.local
curl http://kubia.default
curl http://kubia
# 在Node中不能curl http://kubia 成功,原因为node不在pod的网络空间中。

连接集群外部的服务

endpoint 是暴露一个服务的 ip 地址和端口的列表。endpoint 是 service 之下的对象。2 步将外部服务引入集群内部,1 创建一个 endpoint,2 创建一个没有 pod 选择器的服务。选择第一步创建的 endpoint。配对通过 metadata 中的 name 匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Endpoints
metadata:
name: external-service
subsets:
- addresses:
- ip: 11.11.11.11
- ip: 22.22.22.22
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
ports:
- port: 80

image.png
还可以不创建 endpoint,直接为 service 指定 ExternalName,pod 可以通过 service.name 连接到外部服务。起作用的原因是 dns 谭家了 CNAME 记录。CNAEME 只能指向域名,不能指向 ip。

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: ExternalName
externalName: someapi.somecompany.com
ports:
- port: 80

将服务暴露给外部

  • 服务的类型设置为 NodePort
  • 服务的类型设置为 LoadBalance
  • 创建一个 Ingress 资源 ,通过一个 ip 地址公开多个服务,运行在 http 层。

NodePort 示例

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
Nodeport: 30123
selector:
app: kubia

内部 pod 可以通过 clusterip:80,访问。集群外部可以通过 NodeIP:30123 访问,如果有多个 Node,每个 node 的 30123 端口都可以。
image.png
负载均衡器暴露服务
image.png

ingress 定义:进入或进入的行为。
为什么需要 ingress
每个 loadbalance 服务都需要自己的负载均衡器,以及独有的公网 ip 地址,而 Ingress 只需要一个公网 ip,就能为许多服务提供访问。
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubia
spec:
rules:
- host: kubia.ex.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubia-nodeport
port:
number: 80

异常,需要手动启动 ingress 控制器
image.png
使用 kubeadm 部署的集群需要手动启动 ingress 控制器

参考 https://www.cnblogs.com/zhanglianghhh/p/13721288.html
完成 nginx 控制器部署,在集群内部,
https://stackoverflow.com/questions/63558461/endpoints-default-http-backend-not-found-in-ingress-resource