在CSDN学Golang云原生(Kubernetes Service)
一,service的定义与基本用法
在 Kubernetes 中,Service 是一种抽象概念,用于定义一组 Pod 并为它们提供访问入口。通过 Service,您可以将多个 Pod 组合成一个逻辑单元,并使用标签选择器来确定哪些 Pod 属于该 Service。
下面是一个简单的 Service 定义示例:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app # 标签选择器,用于确定哪些 Pod 属于该 Service
ports:
- name: http
port: 80 # 外部暴露的端口
targetPort: 9376 # 绑定的 Pod 端口
在上面的示例中,我们创建了一个名为 my-service
的 Service,并指定了一个标签选择器 app=my-app
来确定哪些 Pod 属于该 Service。此外,我们还指定了一个绑定端口(端口号为 80
),并将其绑定到后端 Pod 的某个端口(这里为 9376
)。
使用此配置文件部署该服务后,Kubernetes 将自动创建一个负载均衡器,并分配给该服务一个稳定的 IP 地址和 DNS 名称。其他应用程序可以使用这个 IP 地址或 DNS 名称来访问该服务。
需要注意的是,在 Kubernetes 中,Service 可以有不同类型:ClusterIP、NodePort、LoadBalancer 和 ExternalName。每种类型都有不同的用途和配置方式。
下面是一些常见的 Service 使用示例:
- ClusterIP Service:将一组 Pod 组成一个逻辑单元,并在集群内部提供访问入口。
apiVersion: v1
kind: Service
metadata:
name: my-service-clusterip
spec:
selector:
app: my-app # 标签选择器,用于确定哪些 Pod 属于该 Service
ports:
- name: http
port: 80 # 外部暴露的端口
targetPort: 9376 # 绑定的 Pod 端口
- NodePort Service:除了提供 ClusterIP Service 的功能外,还可以在每个节点上绑定一个静态端口号,从而允许外部流量进入 Kubernetes 集群。
apiVersion: v1
kind: Service
metadata:
name: my-service-nodeport
spec:
selector:
app: my-app # 标签选择器,用于确定哪些 Pod 属于该 Service
ports:
- name: http
port: 80 # 外部暴露的端口(在所有节点上都会监听此端口)
targetPort: 9376 # 绑定的 Pod 端口(Pod 内容器监听此端口)
nodePort: 30001 # 在每个节点上绑定的静态端口号(范围为:30000-32767)
- LoadBalancer Service:除了提供 NodePort Service 的功能外,还可以使用云供应商提供的负载均衡器来平衡流量,从而允许外部流量进入 Kubernetes 集群。
apiVersion: v1
kind: Service
metadata:
name: my-service-loadbalancer
spec:
selector:
app: my-app # 标签选择器,用于确定哪些 Pod 属于该 Service
ports:
- name: http
port: 80 # 外部暴露的端口(在所有节点上都会监听此端口)
targetPort: 9376 # 绑定的 Pod 端口(Pod 内容器监听此端口)
type: LoadBalancer # 指定为 LoadBalancer 类型的 Service
- ExternalName Service:将一个服务映射到集群外部的另一个服务或域名,从而允许集群内部使用相同的 DNS 名称来访问集群外部服务。
apiVersion: v1
kind: Service
metadata:
name: my-service-externalname
spec:
externalName: some.api.com # 将该 Service 映射到 some.api.com 域名或 IP 地址上
这里仅列出了一些常见的示例。
二,service 4种发布类型
在 Kubernetes 中,Service 可以有不同的发布类型,常见的包括以下四种:
- ClusterIP:默认类型。将 Service 暴露在集群内部,并分配一个虚拟 IP 地址(Cluster IP)给该 Service。其他 Pod 和 Service 可以使用这个 IP 地址来访问该 Service。
- NodePort:除了提供 ClusterIP 的功能外,还会在每个节点上绑定一个静态端口号,并将流量转发到该端口号。这允许外部流量进入 Kubernetes 集群并访问该 Service。
- LoadBalancer:除了提供 NodePort 的功能外,还可以使用云服务提供商的负载均衡器来平衡流量。当您创建一个 LoadBalancer 类型的 Service 时,Kubernetes 会自动创建一个负载均衡器,并将其配置为将请求转发到后端 Pod 上。
- ExternalName:将一个服务映射到集群外部的另一个服务或域名,从而允许集群内部使用相同的 DNS 名称来访问集群外部服务。与其他类型不同,ExternalName 不需要选择任何 Pod 或 Endpoint。
需要注意的是,在进行发布之前,请确保已经创建了相关的 Deployment 或 StatefulSet 等资源,并且已经正确标记了相关的 Pod 和 Endpoint。否则,即使正确配置了发布类型和其他参数,Service 也无法正常工作。
三,service 无选择符service
在 Kubernetes 中,Service 有一个叫做选择器(selector)的属性,用于定义该 Service 所要代理的 Pod。但是有些时候我们需要将 Service 直接映射到外部 IP 或者 DNS 名称,而不是 Kubernetes 内部的 Pod,这时就可以使用无选择符(selector-less)Service。
无选择符 Service 的作用主要有两个:
- 将外部服务(如数据库或缓存)的访问与应用程序解耦,从而更容易地进行管理和维护。
- 在没有合适的标签或注释来匹配目标 Pod 的情况下,仍然可以使用 Service 进行暴露和路由。
注意:由于无选择符 Service 不涉及任何 Pod,并且不能通过 IP 地址进行流量分配,因此它只能使用 NodePort 或 LoadBalancer 类型。
四,service HeadLess Service
在 Kubernetes 中,Headless Service 是一种特殊类型的 Service,它没有 Cluster IP,也没有负载均衡器。相反,它返回一个由 Pod IP 地址组成的集合。
Headless Service 的作用是将服务发现和负载均衡交给应用程序自己来处理。这样一来,客户端可以直接连接到服务中的任何一个 Pod 上,并且不需要经过 Service 层进行代理或转发。
Headless Service 常用于以下场景:
- StatefulSet:StatefulSet 控制器需要为每个 Pod 分配唯一标识符和网络主机名。如果使用 ClusterIP 类型的 Service,则所有 Pod 共享同一个 DNS 名称和 IP 地址,无法满足这个需求。因此,在 StatefulSet 控制器中通常使用 Headless Service 来提供服务发现功能。
- 数据库集群:数据库集群通常需要使用 DNS 名称或 IP 地址来定位节点。如果使用 ClusterIP 类型的 Service,则只能将流量转发到单个节点上,不能实现负载均衡和故障恢复。因此,在数据库集群中通常使用 Headless Service 来提供服务发现功能。
- 自定义网络拓扑:某些场景下需要控制容器之间的网络拓扑结构,这时候就可以通过 Headless Service 将容器之间的连接直接暴露出去,并且由应用程序自己进行管理和调度。
需要注意的是,由于 Headless Service 没有 Cluster IP 和负载均衡器,所以不能使用 NodePort 或 LoadBalancer 类型。并且,在访问 Headless Service 时需要使用完整的 DNS 名称或 IP 地址来定位 Pod。
五,service 环境变量与DNS服务发现
Kubernetes中,Service是一个抽象的逻辑概念,用于定义一组后端Pod的访问方式。当创建一个Service时,Kubernetes会自动在集群内部创建一个虚拟IP(Cluster IP),并将该IP绑定到Service上。这样,在集群内部可以通过该虚拟IP来访问Service所代表的一组Pod。
对于运行在容器中的应用程序,可以通过环境变量或DNS服务发现来访问其他服务。
- 环境变量
当我们创建一个Service时,Kubernetes会自动为该Service中所有Pod设置一些环境变量。其中包括:
- SERVICE_HOST:Service所绑定的虚拟IP地址。
- SERVICE_PORT:Service所监听的端口号。
使用这些环境变量,我们就可以在容器中直接访问同一个Service中的其他Pod了。
- DNS服务发现
除了使用环境变量外,Kubernetes还提供了DNS服务发现机制。每个 Service 都有一个 DNS 名称,默认情况下是“servicename.namespace.svc.cluster.local”。通过DNS名称解析,就可以轻松地实现跨命名空间和跨节点的服务发现和通信。
例如,在Python代码中使用requests库调用另一个 Service:
import requests
url = "http://otherservice.default.svc.cluster.local:8080/api/v1/getdata"
response = requests.get(url)
这里,“default”是命名空间名称,“otherservice”是Service名称,“svc.cluster.local”是默认的Kubernetes集群域名。
Kubernetes中的Service提供了一种高效、灵活、可靠的服务发现和通信机制,能够满足微服务架构下各个组件之间的调用需求。
六,service TLS
在Kubernetes中,我们可以使用Service来暴露一组Pod作为一个服务。当需要对服务进行加密通信时,可以通过在Service和Pod之间添加TLS层来实现。
以下是一些步骤:
- 创建证书和私钥
首先,我们需要创建用于加密通信的证书和私钥。这里假设已经有了自签名证书和私钥。
- 创建Secret对象
然后,将证书和私钥打包到一个Kubernetes Secret对象中:
$ kubectl create secret tls mytlssecret --cert=server.crt --key=server.key
这里创建了一个名为“mytlssecret”的Secret对象,并将“server.crt”和“server.key”两个文件打包成为该对象的数据部分。
- 修改Service定义
接着,在Service定义中添加如下部分:
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- name: https
port: 443
targetPort: 80
selector:
app: myapp
type: ClusterIP
tls:
- hosts:
- myservice.example.com
secretName: mytlssecret
其中,“hosts”指定了该TLS配置所要绑定的域名,“secretName”指定了上一步创建的Secret对象名称。
- 更新应用程序
最后,在应用程序中更新相关代码,使其支持HTTPS协议即可。如果使用HTTP客户端库(如requests)调用其他服务时,也需要相应地修改代码以支持HTTPS协议。
需要注意的是,在使用Service TLS时,我们还需要考虑证书和私钥的管理、更新和分发等问题。可以使用工具如cert-manager来自动化这些任务,使TLS证书管理更加便捷和安全。
七,ingress http 7层路由机制
Kubernetes Ingress是一种可以将HTTP和HTTPS流量路由到集群中不同服务的API对象,通常用于实现七层(应用层)路由。
在Ingress配置中,可以定义多个规则(Rule),每个规则包含一个Host名称和若干条Path规则。对于每条Path规则,可以指定要将请求转发到哪个Service上。因此,在使用Ingress时,需要先定义好所需的Service,并将它们标记为需要通过Ingress暴露出来的服务。
Ingress主要有以下几种类型:
- Nginx Ingress:使用Nginx作为负载均衡器实现七层路由。
- Traefik Ingress:使用Traefik作为负载均衡器实现七层路由。
- Istio Ingress Gateway:基于Istio实现网关功能,并支持灰度发布、流量控制等高级特性。
当客户端发送请求时,Ingress会根据请求中的Host和Path信息匹配对应的规则,并将请求转发给相应的后端Service。如果没有匹配到任何规则,则会返回404错误。
总之,Kubernetes Ingress提供了一种方便易用的方式来管理应用程序的入口流量,并支持多种七层路由机制和高级特性。
八,ingress Controller 安装
安装Kubernetes Ingress Controller可以使用多种不同的方案,这里介绍一些常见的方法:
- 使用官方提供的Nginx Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/cloud/deploy.yaml
- 使用Helm安装Nginx Ingress Controller
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install my-release ingress-nginx/ingress-nginx
- 使用官方提供的Traefik Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.4/examples/k8s/traefik-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.4/examples/k8s/ui.yaml
- 使用Helm安装Traefik Ingress Controller
helm repo add traefik https://helm.traefik.io/traefik
helm install my-release traefik/traefik
需要注意的是,在部署Ingress Controller之前,需要确保已经正确设置了Kubernetes集群中的网络插件,并且Node节点都已经正确配置和准备好。
九,ingress转发策略配置
Kubernetes Ingress资源可以使用不同的策略来实现请求转发。这里列出一些常见的Ingress转发策略:
- Path-Based Routing:根据请求URL路径进行路由,可使用nginx ingress或traefik ingress实现
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /v1
backend:
serviceName: service-v1
servicePort: 80
- path: /v2
backend:
serviceName: service-v2
servicePort: 80
- Host-Based Routing:根据请求的主机名(host)进行路由,可使用nginx ingress或traefik ingress实现
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /path/to/service
backend:
serviceName: my-service
servicePort : my-service-port
- TCP/UDP routing:将TCP/UDP流量路由到特定服务的端口,通过MetalLB等负载均衡器实现
apiVersion : v1
kind : Service
metadata :
name : mysql-svc
labels :
app : mysql-db
spec :
ports :
- port : 3306
targetPort : mysql
selector :
app : mysql-db
---
apiVersion : networking.k8s.io/v1beta1
kind : Ingress
metadata :
name : mysql-ingress
spec :
rules:
- host: mysql.example.com
http:
paths:
- path: /
backend:
serviceName: mysql-svc
servicePort: 3306
- Fanout:将请求路由到多个服务,可使用traefik ingress实现
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: fanout-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /serviceA/*
backend:
serviceName: service-a
servicePort: 80
- path: /serviceB/*
backend:
serviceName: service-b
servicePort: 80
需要根据实际需求选择合适的Ingress转发策略。
十,ingress TLS 配置
Kubernetes Ingress可以配置TLS证书,提供HTTPS服务。下面是一个简单的Ingress TLS配置示例:
- 生成TLS证书和私钥
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048
-out /path/to/tls.crt
-keyout /path/to/tls.key
-subj "/CN=example.com"
- 创建k8s secret
$ kubectl create secret tls example-tls --cert=/path/to/tls.crt --key=/path/to/tls.key
- 配置Ingress规则
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
tls:
- hosts:
- example.com
secretName: example-tls #引用上一步创建的secret名称
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: service-name
servicePort : service-port
在这个例子中,我们使用了tls
字段来配置TLS证书信息。我们指定了hosts为example.com,并且将之前创建的名为example-tls的secret用于TLS证书。
需要注意的是,此处只给出了一个简单的TLS配置示例,请根据实际需求进行相应修改。同时,还需要确保您的域名和证书匹配。