文章目录
- [Service 和 Ingress](#Service 和 Ingress)
Service 和 Ingress
service 和 ingress 是kubernetes 中用来转发网络请求的两个服务,两个服务用处不同,service 主要提供集群内部网络调用、负载均衡(四层负载),ingress 提供外部访问,反向代理,负载均衡(七层负载)
Service
在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。
为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务
可以说 Service 是一个应用服务的抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。Service 代理 Pod 集合,对外表现为一个访问入口,访问该入口的请求将经过负载均衡,转发到后端 Pod 中的容器。
Endpoint
每一个service 都会有一个 Endpoint controller , 在endponit 里面会维护 address,targetPort 和 容器之间的关系。整个访问链是 通过 service -> endpoint -iptables->kube-proxy -> 容器
service 的定义
Yaml 文件案例
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc # service name
labels:
app: nginx-svc # service 自己的标签
spec:
ports:
- name: http # service 端口配置的名称
protocol: TCP # 端口绑定的协议,支持 TCP、UDP、SCTP,默认为 TCP
port: 1080 # service 自己的端口
targetPort: 80 # 目标 pod 的端口
type: NodePort # 默认是ClusterIP 类型,只能在集群内部使用
# NodePort 用于将服务暴露给外部访问
selector: # 选中当前 service 匹配哪些 pod,对哪些 pod 的东西流量进行代理
app: nginx
使用命令
sh
# 创建 service
kubectl create -f nginx-svc.yaml
# 查看 service 信息,通过 service 的 cluster ip 进行访问
kubectl get svc
# 查看 pod 信息,通过 pod 的 ip 进行访问
kubectl get po -owide
# 创建其他 pod 通过 service name 进行访问(推荐)
kubectl exec -it busybox -- sh
curl http://nginx-svc
# 默认在当前 namespace 中访问,如果需要跨 namespace 访问 pod,则在 service name 后面加上 .<namespace> 即可
curl http://nginx-svc.default
代理集群外部服务
用于解决外部服务迁移到k8s 集群,各个环境访问名称统一,容器内部访问外部服务等需求
实现方式:
-
编写 service 配置文件时,不指定 selector 属性
yamlapiVersion: v1 kind: Service metadata: name: nginx-svc # service name labels: app: nginx-svc # service 自己的标签 spec: ports: - name: http # service 端口配置的名称 protocol: TCP # 端口绑定的协议,支持 TCP、UDP、SCTP,默认为 TCP port: 1080 # service 自己的端口 targetPort: 80 # 目标 pod 的端口 type: ClusterIP # 默认是ClusterIP 类型,只能在集群内部使用 # NodePort 用于将服务暴露给外部访问
-
自己创建 endpoint
yaml
apiVersion: v1
kind: Endpoints
metadata:
labels:
app: nginx-svc-external # 与 service 一致
name: nginx-svc-external # 与 service 一致
namespace: default # 与 service 一致
subsets: # 子网设置
- addresses:
- ip: <target ip> # 目标 ip 地址
ports: # 与 service 一致
- name: http # service 中ports.name 属性保持一致
port: 80
protocol: TCP
反向代理外部域名
直接通过在容器内部直接通过外部域名去访问
yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: baidu-external-domain
name: baidu-external-domain
spec:
type: ExternalName
externalName: www.baidu.com
Service 常用类型
Type | 用途 | 补充 |
---|---|---|
ClusterIP | 只能在集群内部使用,不配置类型的话默认就是 ClusterIP | |
ExternalName | 返回定义的 CNAME 别名,可以配置为域名 | |
LoadBalancer | 使用云服务商(阿里云、腾讯云等)提供的负载均衡器服务 | |
NodePort | 在所有安装了 kube-proxy 的节点都绑定一个端口,此端口可以代理至对应的 Pod,集群外部可以使用任意节点 ip + NodePort 的端口号访问到集群中对应 Pod 中的服务。 | 一般用于测试环境,生产环境使用ingress |
补充:
NodePort 映射是一个O(N) 的时间复杂度,当节点数越多的时候,效率越低,内部代码是通过轮询来处理的
当类型设置为 NodePort 后,可以在 ports 配置中增加 nodePort 配置指定端口,需要在下方的端口范围内,如果不指定会随机指定端口
端口范围:30000~32767
端口范围配置在 /usr/lib/systemd/system/kube-apiserver.service 文件中
Ingress
Ingress 可以提供外网访问 Service 的能力。可以把某个请求地址映射、路由到特定的 service。
ingress 需要配合 ingress controller 一起使用才能发挥作用,ingress 只是相当于路由规则的集合而已,真正实现路由功能的,是 Ingress Controller,ingress controller 和其它 k8s 组件一样,也是在 Pod 中运行。
Ingress-nginx
Ingress 是一个更高层的抽象,具体实现还需要借助于Ingress controller 列如 Ingress-nginx 其他控制器参考 官网文档 https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers
安装
参考官网地址:https://kubernetes.github.io/ingress-nginx/deploy/#using-helm
官网默认采用helm,因此需要先安装helm
- 下载安装包 wget https://get.helm.sh/helm-v3.14.2-linux-amd64.tar.gz
- tar -zxvf helm-v3.2.3-linux-amd64.tar.gz
- cp helm /usr/local/bin/
sh
# 添加ingree 仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# 查看仓库列表
helm repo list
# 搜索 ingress-nginx
helm search repo ingress-nginx
# 下载安装包
helm pull ingress-nginx/ingress-nginx --version 4.4.2
# 解压安装包
tar -zxvf ingress-nginx-4.4.2.tgz
# 解压后,进入解压完成的目录
cd ingress-nginx
# 修改 values.yaml
镜像地址:修改为国内镜像
registry: registry.cn-hangzhou.aliyuncs.com
image: google_containers/nginx-ingress-controller
image: google_containers/kube-webhook-certgen
tag: 两个image 版本保持一致 或者 不动也行
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
修改部署配置的 kind: /DaemonSet # Deployment 改成 DaemonSet
nodeSelector:
ingress: "true" # 增加选择器,如果 node 上有 ingress=true 就部署
将 admissionWebhooks.enabled 修改为 false
将 service 中的 type 由 LoadBalancer 修改为 ClusterIP,如果服务器是云平台才用 LoadBalancer
# 为 ingress 专门创建一个 namespace
kubectl create ns ingress-nginx
# 为需要部署 ingress 的节点上加标签
kubectl label node k8s-master ingress=true
# 安装 ingress-nginx
helm install ingress-nginx -n ingress-nginx .
使用
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress # 资源类型为 Ingress
metadata:
name: demo-nginx-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: / # 重写路径
spec:
rules: # ingress 规则配置,可以配置多个
- host: k8s.demo.cn #域名配置,可以使用通配符 * 可以配置多个host 也可以不配置host 直接通过ip:port 方式访问 配置了host 就只能通过host 不能选择ip:port 的形式
http:
paths: # 相当于 nginx 的 location 配置,可以配置多个 paths
- path: /api # 等价于 nginx 中的 location 的路径前缀匹配
pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配
backend:
service:
name: nginx-svc # 代理到哪个 service
port: # 可以直接写 80 也可以如下写法
number: 80 # service 的端口