k8s的Service和持久化存储
一、Service
service是一组Pod的逻辑集合,这一组Pod能够被Service访问到,通常是通过Label Selector实现的。
1.service的工作原理
k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)
2.kube-proxy
- kube-proxy 是K8S的一个重要组件,是管理service的访问入口,包括集群内的pod到serivce 的访问和集群外访问service 。
- kube-proxy 管理service的Endpoint,service要暴露一个虚拟的ip地址,称为集群地址:Cluster IP,通过这个Clusterip去访问pod。
3.service四种类型
ClusterIP:
描述:这是默认类型。ClusterIP 服务只在集群内部暴露服务,无法从集群外部访问。
使用场景:适合集群内部的通信,如服务间的通信、数据库服务等。
访问:通过服务的 ClusterIP 地址和指定的端口访问。
NodePort:
描述:NodePort 服务在每个 Node 上开放一个端口,并将该端口转发到 ClusterIP 服务上。这允许外部流量通过集群的任意节点和端口访问服务。
使用场景:适用于需要从集群外部访问服务的情况,但不需要负载均衡器的情况下。
访问:通过 : 地址访问。
LoadBalancer:
描述:LoadBalancer 服务通过集群外部的负载均衡器(通常是云提供商提供的)暴露服务。负载均衡器会分发流量到集群中的服务。
使用场景:适用于需要外部访问并且需要负载均衡的服务,比如 Web 应用或 API 服务。
访问:通过负载均衡器提供的外部 IP 地址访问。
ExternalName:
描述:ExternalName 服务将服务的 DNS 名称映射到外部的主机名。它不会创建代理或负载均衡器,只是提供了一个集群内部 DNS 名称到外部资源的映射。
使用场景:适用于需要在集群内部以 DNS 名称访问外部资源的情况,比如访问外部数据库或服务。
访问:通过服务的 DNS 名称访问。
clusterip例子
apiVersion: v1
kind: Service
metadata:
name: my-web-app-service
namespace: default
spec:
type: ClusterIP
selector:
app: my-web-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
说明:
apiVersion: 指定 API 版本为 v1。
kind: 表示资源类型为 Service。
metadata:
name: Service 的名称为 my-web-app-service。
namespace: Service 所在的命名空间,默认为 default。
spec:
type: 设置为 ClusterIP,表示只在集群内部暴露。
selector: 指定 Service 选择哪些 Pod。这里选择了标签为 app: my-web-app 的 Pod。
ports:
protocol: 使用的协议,通常是 TCP。
port: 集群内部访问的端口,外部访问时用这个端口。
targetPort: 目标 Pod 中容器的端口,这里是 8080。
二、持久化存储
在 Kubernetes (K8s) 中,持久化存储是为了确保数据的持久性,即使 Pod 被删除或重启,数据仍然能够保留。
1.PersistentVolume (PV)
描述:PersistentVolume 是一个集群级别的资源,表示一个存储卷。它由管理员预先配置,并被提供给集群中的 Pod 使用。
生命周期:PersistentVolume 的生命周期独立于 Pod,当 Pod 被删除或重建时,PersistentVolume 不会受到影响。
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data
2.PersistentVolumeClaim (PVC)
ersistentVolumeClaim 是用户或应用程序请求存储的资源对象。它描述了用户所需的存储容量、访问模式等。当用户创建 PersistentVolumeClaim 时,Kubernetes 会尝试将其绑定到一个符合要求的 PersistentVolume 上。如果没有可用的 PersistentVolume,系统可以根据 StorageClass 的定义动态创建一个新的 PersistentVolume。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
3.PV 和 PVC 的关系
绑定:
用户创建 PersistentVolumeClaim,系统会尝试找到一个符合要求的 PersistentVolume 来满足该声明。若找到符合条件的 PV,PersistentVolumeClaim 和 PersistentVolume 将会绑定在一起,形成持久化存储的使用。
PersistentVolume 和 PersistentVolumeClaim 之间的绑定是自动完成的,基于PersistentVolumeClaim 中的请求和 PersistentVolume 的属性。
动态供应:
在某些情况下,集群管理员会配置 StorageClass 以支持动态供应存储。这样,当 PersistentVolumeClaim 创建时,如果没有可用的 PV,Kubernetes 可以自动创建新的 PV,并将其与 PVC 绑定。
4.存储类 storageclass ---- 动态创建
自动创建pv,k8s集群管理员通过创建storageclass可以动态生成一个存储卷pv供k8s pvc使用。
Kubernetes 存储解决方案实验
1.创建一个sa账户,并授权
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
说明:
这个 nfs-provisioner 服务账户被用于运行 NFS Provisioner Pod,允许它执行需要访问 Kubernetes API 的操作,如创建动态 PV(PersistentVolume)等。
2.安装并配置nfs-server
apt install nfs-kernel-server
mkdir -p /data/nfs_pro
vim /etc/exports
/data/nfs_pro *(rw,sync,no_subtree_check)
sudo exportfs -a
sudo systemctl start nfs-kernel-server
sudo systemctl enable nfs-kernel-server
sudo exportfs -v
3.启动一个pod用于管理 NFS Provisioner Pod 的部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-provisioner
spec:
selector:
matchLabels:
app: nfs-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: example.com/nfs
- name: NFS_SERVER
value: 172.16.1.30
- name: NFS_PATH
value: /data/nfs_pro
volumes:
- name: nfs-client-root
nfs:
server: 172.16.1.30
path: /data/nfs_pro
4.创建StorageClass,动态pv
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: nfs
provisioner: example.com/nfs
说明:
这个 StorageClass 对象定义了一个名为 nfs 的存储类,它使用 example.com/nfs 作为其 Provisioner。这意味着,当 Kubernetes 用户创建一个 PersistentVolumeClaim (PVC) 并指定使用这个 nfs 存储类时,example.com/nfs Provisioner 将会被触发来动态地分配一个满足 PVC 要求的 NFS 存储卷。
5.创建PVC,通过storageClass去实现
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim1
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 1Gi
storageClassName: nfs
6.创建测试pod
kind: Pod
apiVersion: v1
metadata:
name: read-pod
spec:
containers:
- name: read-pod
image: harbor.hiuiu.com/nginx/nginx:1.21.5
volumeMounts:
- name: nfs-pvc
mountPath: /usr/share/nginx/html
restartPolicy: "Never"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim1
这个 Pod 配置的目的是启动一个 Nginx 容器,该容器从 PVC test-claim1 中挂载了一个目录,以便容器可以读取或写入这个持久化存储。Pod 的重启策略设置为 Never,表明容器不会因为退出而自动重启。这个配置对于需要将数据持久化并共享给多个 Pod 使用的场景非常有用。
7.验证
kubectl cp /opt/cc.html read-pod:/usr/share/nginx/html
cd /data/nfs_pro
#去nfs共享存储目录下查看是否有成功存储文件