如何创建 nfs storageClass 详见link
下面是将nginx容器里的/usr/share/nginx/html挂载在nfs storageClass共享的目录下
vim nginx.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-nfs-pvc
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs-storage"
resources:
requests:
storage: 10Mi
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: nginx-nfs-pvc
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
type: NodePort # service类型
ports:
- port: 80
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 80
应用上面的资源
kubectl apply -f nginx.yaml
查看pv与pvc
kubectl get pv && kubectl get pvc
查看nfs storageClass共享的目录(该目录由创建nfs storageClass的配置路径决定),我这里是/root/nfs
ls /root/nfs
进入上面的共享目录,创建一个index.html文件
cd default-nginx-nfs-pvc-pvc-40bb028a-f2e0-459f-8ab1-5acb4106c270
echo "hello k8s" > index.html
访问服务
curl 127.0.0.1:30001
vim mysql.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-nfs-pvc
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs-storage"
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: admin
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: mysql-nfs-pvc
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql
type: NodePort # service类型
ports:
- port: 3306
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 3306
kubectl apply -f mysql.yaml
查看service
kubectl get services mysql-service
创建成功后,有两种访问方式集群内和集群外
1.集群内
先创建一个mysql pods用来连接测试
kubectl run mysql-client --image=mysql:5.6 --env="MYSQL_ROOT_PASSWORD=admin"
进入mysql-client pods 连接测试,使用service的服务名+端口或者service的ip+端口
kubectl exec -it mysql-client -- bash
#service名+端口
mysql -h mysql-service -P 3306 -uroot -padmin
#service ip+端口
mysql -h 192.168.207.29 -P 3306 -uroot -padmin
2.集群外
用docker创建mysql客户端容器,模拟容器外的环境
docker run -d -e MYSQL_ROOT_PASSWORD=admin --name mysql-client mysql:5.6
进入容器
docker exec -it mysql-client bash
#连接k8s部署的mysql,服务器ip+端口
mysql -h 118.195.140.6 -P 30001 -uroot -padmin
PS:服务器防火墙30001要打开
vim redis.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: redis-nfs-pvc
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs-storage"
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis:5.0.7
name: redis
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: redis-volume
mountPath: /data
volumes:
- name: redis-volume
persistentVolumeClaim:
claimName: redis-nfs-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
type: NodePort # service类型
ports:
- port: 6379
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 6379
连接方式也是分为集群内和集群外两种,与上面mysql连接类似,下面展示集群外的连接方式
#先创建docker redis客户端
docker run --name redis-cli -d redis:5.0.7
#进入redis-cli容器
kubectl exec -it redis-66bf575488-k6gt6 -- bash
#连接k8s部署的redis
redis-cli -h 43.137.12.76 -p 30001
Deployment适合无状态应用程序的部署,它的优点是可以自动创建和管理Pod,并支持快速水平扩展。但是像MySQL/Redis这种有状态的应用程序,它需要稳定的网络标识符(hostname),以便跨Pod保持持久的连接和数据一致性。
StatefulSet提供了有状态应用程序的部署和管理,它会给每个Pod分配稳定的网络标识符,支持Pod的有序部署和有序回收,保证了Pod之间的数据稳定性。在数据处理应用程序中,StatefulSet通常是更好的选择。
比如说上面的mysql应用,虽然将mysql里的数据持久化保存了,但是在重新创建mysql后,之前mysql里的数据无法自动关联到现在创建的mysql应用里
PS:为什么Deployment部署的应用无法复用pv/pvc,我的理解是Deployment部署的pods在销毁和创建后,那没有一个统一的标识,这也意味着无法再将pods和pv/pvc重新绑定
Deployment的配置文件与StatefulSet配置文件大致有3点不同
vim nginx.yaml
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-volume
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: nginx-volume
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-storage
resources:
requests:
storage: 512M
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
type: NodePort # service类型
ports:
- port: 80
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 80
PS:因为将nfs的共享目录下的某个位置挂载在 pod的/usr/share/nginx/html目录上,所以现在直接访问service会报404(可以去pod里创建index.html或者去挂载的nfs目录下创建对应的文件)
#进入pod测试
kubectl exec -it nginx-0 -- bash
#分别用service名,service的ip和服务器的公网ip访问测试
区别于Deployment部署应用,StatefulSet这种方式部署可为每个副本创建单独的pv/pvc(当然也可以都共享一个pv/pvc)
还有就是spec里面可以指定serviceName,指定了该配置后,就可以通过pod名定向访问对应的pod,示例如下
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: nginx
spec:
serviceName: nginx-service #增加该配置,service对应创建的服务名
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-volume
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: nginx-volume
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-storage
resources:
requests:
storage: 512M
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
type: NodePort # service类型
ports:
- port: 80
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 80
应用配置文件后,到nfs的共享目录下分别给对应的pod创建index.html文件
进入pod容器测试
部署的配置文件与上面的ngxin配置相似,如果要做主从复制,读写分离之类的还需做一些单独的配置
vim mysql.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: admin
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-volume
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-storage
resources:
requests:
storage: 512M
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql
type: NodePort # service类型
ports:
- port: 3306
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 3306
连接测试就不做了,与Deployment部署的mysql连接测试方式相同
部署的配置文件与上面的mysql配置相似,如果要部署集群之类的还需做一些单独的配置
vim redis.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis:5.0.7
name: redis
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: redis-volume
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-volume
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-storage
resources:
requests:
storage: 512M
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
type: NodePort # service类型
ports:
- port: 6379
nodePort: 30001 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
targetPort: 6379
写这些,仅记录自己学习使用k8s的过程。如果有什么错误的地方,还请大家批评指正。最后,希望小伙伴们都能有所收获。