Kubernetes Service 服务
2020-04-10 by dongnan
开始之前
在前面的三篇文章中,至此我们已经准备好了K8S
集群环境。
接下来我们将以在K8S
集群运行一个真实的项目为目标,依次介绍项目所使用的K8S
资源对象。
这个项目是一个典型的Web
系统,使用 Java Spring Boot
框架开发,需要使用 MySql
、Redis
数据库、NFS
共享存储(多个Pod
容器间共享文件)。
由于K8S
环境部署在阿里云上,所以这里使用了阿里云提供的 RDS-Mysql
、RDS-Redis
数据库服务、NAS(NFS)
网络附加存储等中间件产品,对于K8S
集群来说,我们需要将这些服务映射为K8S
的资源对象。
项目使用的K8S
的资源对象包括:
- PV&PVC,用于Pod数据卷(NFS)。
- Pod (volumeMounts、readinessProbe),挂载数据卷、健康检查。
- Secret,存储机密数据。
- Service,服务-外部域名(ExternalName)。
- NetworkPolicy,网络策略。
- LimitRange,限制资源。
- Ingress
环境
测试的k8s
集群由一个Master
管理节点、两个Worker
计算节点组成,详细请参考这里。
目标
将阿里云的 RDS-Mysql
、RDS-Redis
产品映射为Kubernetes
的Service
对象。
举个栗子
Yaml文档
这里定义两个Service
服务,yyi-db
为Mysql数据库,yyi-rds
为Redis数据库:
apiVersion: v1
kind: Service
metadata:
namespace: yyi-prod
name: yyi-db
spec:
type: ExternalName # 注意这里
externalName: rm-8vxxxxxxxxxx7.mysql.zxxxxx.rds.aliyuncs.com
---
apiVersion: v1
kind: Service
metadata:
namespace: yyi-prod
name: yyi-rds
spec:
type: ExternalName # 注意这里
externalName: r-8vxxxxxxxxxxro.redis.zxxxxx.rds.aliyuncs.com
创建Service
kubectl apply -f yii-dbs.yaml
验证
查看 Service
详细信息:
# Mysql
kubectl -n yyi-prod describe svc yyi-db
Name: bulk-db
Namespace: yyi-prod
Labels: <none>
#...省略
Selector: <none>
Type: ExternalName
IP:
External Name: rm-8vxxxxxxxxxx7.mysql.zxxxxx.rds.aliyuncs.com
Session Affinity: None
Events: <none>
# Reids
kubectl -n yyi-prod describe svc yyi-rds
Name: bulk-rds
Namespace: yyi-prod
Labels: <none>
#...省略
Selector: <none>
Type: ExternalName
IP:
External Name: r-8vxxxxxxxxxxro.redis.zxxxxx.rds.aliyuncs.com
Session Affinity: None
Events: <none>
尝试使用yyi-server
Pod容器访问创建的Service
对象:
# 登录Pod控制台
kubectl -n yyi-prod exec -ti yyi-server-7xxxx94d-gxt6r /bin/bash
# 访问Mysql数据库
telnet yyi-db 3306
Trying 10.0.xx.215...
Connected to rm-8vxxxxxxxxxx7.mysql.zxxxxx.rds.aliyuncs.com.
Escape character is '^]'.
N
5.7.26-log�DP+Ag/#!D3\rUR.-rmysql_native_passworduqit
ot packets out of orderConnection closed by foreign host.
# 访问Redis数据库
telnet yyi-rds 6379
Trying 10.0.xx.227...
Connected to r-8vxxxxxxxxxxro.redis.zxxxxx.rds.aliyuncs.com.
Escape character is '^]'.
quit
+OK
Connection closed by foreign host.
Pod
容器成功访问到两个Service
对象。
Service
Kubernetes 中 Service
是一个 API
对象,可以将符合Service
指定条件的Pod
作为可通过网络访问的服务,提供给服务调用者。
Service
具有服务发现机制:
Pod
拥有自己的IP
地址。Service
被赋予一个唯一的DNS
名称。Service
通过label selector
选定一组Pod
。Service
实现负载均衡,可将请求均衡分发到选定这一组Pod
中。
Service类型
Service
服务类型如下:
ClusterIP
:通过集群的内部IP
暴露服务,选择该类型服务只能够在集群内部访问,这是默认的选项。NodePort
:通过每个节点上的IP
和静态端口(NodePort
)暴露服务。通过请求节点IP:端口
可以从集群的外部访问这个NodePort
服务。LoadBalancer
:使用云提供商的负载均衡器向外部暴露服务。外部负载均衡器可以将流量路由到自动创建的NodePort
服务和ClusterIP
服务上。ExternalName
:通过返回CNAME
和对应值,可以将服务映射到externalName
字段的内容,无需创建任何类型代理。
ClusterIP 示例
再来看一个Service
例子:
---
apiVersion: v1
kind: Service
metadata:
namespace: yyi-prod
name: yyi-server-svc
labels:
app: yyi-server-svc
spec:
selector:
app: yyi-server
ports:
- name: yyi-server-svc
protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP # ClusterIP/NodePort/LoaderBalancer
# sessionAffinity: ClientIP # ClientIP/None
这个Service
类型为ClusterIP
用于K8S
集群内部的Pod
访问,
可以通过 yyi-server-svc:8080
这个地址进行访问的,这个 yaml
指定后端Pod
必须带有 app:yyi-server
这个标签。
这与 Kubernetes Pod 数据卷与健康检查 Deployment
定义的 spec.template.metadata.labels
相对应:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: yii-prod
name: yii-server
#...省略
spec:
replicas: 1
selector:
matchLabels:
app: yii-server
template:
metadata:
labels:
app: yii-server # 这里
spec:
#...省略
创建Service
kubectl apply -f yii-svc.yaml
验证
新创建了 yyi-asset-sv
服务,至此拥有3个Service
对象:
kubectl -n yyi-prod get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
yyi-db ExternalName <none> rm-8vxxxxxxxxxx7.mysql.zxxxxx.rds.aliyuncs.com <none> 159d
yyi-rds ExternalName <none> r-8vxxxxxxxxxxro.redis.zxxxxx.rds.aliyuncs.com <none> 159d
yyi-server-svc ClusterIP 172.19.xxx.231 <none> 80/TCP 159d
NodePort 实例
之前我们部署 Ingress控制器时,所使用的 Service
类型就是 NodePort
:
kubectl -n ingress-nginx get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 172.19.xxx.223 <none> 80:32001/TCP,443:32002/TCP 613d
选择NodePort
类型就是希望暴露ECS
的端口给上游的SLB
负载均衡器使用,也就是从集群的外部访问这个服务。
验证
通过请求节点IP:端口
的方式,访问到了Ingress
控制器:
# 节点 host1
curl -IL host1:32001
HTTP/1.1 404 Not Found
Server: nginx/1.17.8
Date: Wed, 08 Dec 2021 05:47:16 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
小结
- Kubernetes 的
Service
对象底层使用了诸如iptables
、ipvs
等技术。 - 此外
Service
对象还有其它的形式,如Headless Service
、不带标签选择器的外部服务Service
、多端口Service
等等。
详细信息请参考 kubernetes 官方文档 。