//pvc名称用的地方 当需要使用pvc的时候 volumes: - name:>pvc访问模式 accessModes| 访问模式 | 缩写 | 含义 |
|---|
| ReadWriteOnce | RWO | 卷可以被单个节点以读写方式挂载。 |
| ReadOnlyMany | ROX | 卷可以被多个节点以只读方式挂载。 |
| ReadWriteMany | RWX | 卷可以被多个节点以读写方式挂载。 |
| ReadWriteOncePod | RWOP | 卷只能被单个 Pod 以读写方式挂载。这是最严格的限制,防止同一节点上多个 Pod 共享卷。 |
storageClassName pvc存储类别
//一般使用默认的就行 storageClassName 是 PVC 中用来指定存储类别的字段,它告诉 Kubernetes: “我要用哪一种存储类型来给我动态创建 PV。”
//查看可用类别 root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-client (default) cluster.local/nfs-subdir-external-provisioner Delete Immediate true 59d
PVC 的核心作用是给 Pod 提供一块持久的“外部磁盘”,既可以“把容器里的数据存出去”,也可以“把外部数据读进来”,但最主要的目的还是前者——持久化保存容器产生的数据。
和 ConfigMap 的区别(避免混淆) ConfigMap / Secret:是把集群里的配置数据“映射进去”给容器读,通常是只读,主要用来注入配置。 PVC:是挂载一个可读写的持久化卷,主要用来存放应用自己产生或需要长期保留的数据。
headless service
一般用来配合 StatefulSet 提供稳定网络标识
apiVersion: v1 kind: Service metadata: name: mysql-headless spec: clusterIP: None # 关键:置为 None 与普通服务区别 selector: app: mysql-master ports: - port: 3306 targetPort: 3306
sts
//pvc一般和sts写在一个文件里面 # StatefulSet apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-master spec: //sts必填字段 必须显式绑定 Headless Service //StatefulSet 会给每个 Pod 一个固定的 DNS 名: //pod-name.service-name.namespace.svc.cluster.local serviceName: mysql-headless replicas: 1 //这个是给sts管理pod用的 selector: matchLabels: app: mysql-master //pod模板 template: metadata: labels: app: mysql-master //和上面对应 spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-root-password key: MYSQL_ROOT_PASSWORD - name: MYSQL_DATABASE valueFrom: configMapKeyRef: name: mysql-config key: MYSQL_DATABASE //时区非常重要 一定要设置为中国 可以进容器里面使用date命令查看当前时间 - name: TZ value: "Asia/Shanghai" //启动参数(args) args: - "--default-authentication-plugin=mysql_native_password" - "--character-set-server=utf8mb4" - "--collation-server=utf8mb4_general_ci" - "--explicit_defaults_for_timestamp=true" - "--lower_case_table_names=1" - "--max_allowed_packet=128M" ports: - containerPort: 3306 # 挂载 SQL 初始化脚本 volumes: # 定义这个 Pod 有哪些卷 - name: init-sql # 给这个卷在 Pod 内部起一个别名/引用名 configMap: name: mysql-init-sql # ConfigMap 的 name: mysql-init-sql //持久化数据库文件 //将 Pod 中定义好的卷(volumes)挂载到容器内的具体路径, //最开始是把外面挂载进里面,但是后面读写数据过后都同时作用于外面 volumeMounts: - name: mysql-data //name 必须与 PVC 模板的名字一致 mountPath: /var/lib/mysql //容器内的挂载路径 # 关键:自动执行 SQL // /docker-entrypoint-initdb.d 是 MySQL 官方镜像提供的自动初始化入口。容器首次启动时,会自动执行该目录下所有 .sql、.sh、.sql.gz 文件。 - name: init-sql mountPath: /docker-entrypoint-initdb.d //这里开始自动为每一个pod创建一个pvc volumeClaimTemplates: - metadata: name: mysql-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi
root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# cat mysql-svc.yaml # 普通 Service(供应用访问) apiVersion: v1 kind: Service metadata: name: mysql spec: selector: app: mysql-master ports: - port: 6379 targetPort: 6379 type: ClusterIP
redis
--- # Headless Service(用于稳定 DNS) apiVersion: v1 kind: Service metadata: name: redis-headless spec: clusterIP: None selector: app: redis ports: - port: 6379 targetPort: 6379 --- # 普通 Service(供应用访问) apiVersion: v1 kind: Service metadata: name: redis spec: selector: app: redis ports: - port: 6379 targetPort: 6379 type: ClusterIP --- # StatefulSet apiVersion: apps/v1 kind: StatefulSet metadata: name: redis spec: serviceName: redis-headless replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:6.2 env: - name: TZ value: "Asia/Shanghai" command: - redis-server - --appendonly yes # 开启持久化 - --requirepass "" # 可选:设置密码(建议用 Secret) ports: - containerPort: 6379 volumeMounts: - name: redis-data mountPath: /data volumeClaimTemplates: - metadata: name: redis-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi
blogx-server
//configmap root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# kubectl describe configmap blogx-server-config Name: blogx-server-config Namespace: default Labels: <none> Annotations: <none> Data ==== settings.yaml: ---- system:\r ip: 0.0.0.0\r port: 8080\r gin_mode: debug\r env: dev\r log:\r app: blogx_server\r dir: logs\r
//pvc root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# cat blogx-server-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: blogx-server-config spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# cat blogx-server-pvc2.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: blogx-server-data spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# cat blogx-server-pvc3.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: blogx-server-logs spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi
//查看pvc的存储路径 root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE blogx-server-config Bound pvc-60dba83b-6863-438c-a0a5-ac2de6db518e 5Gi RWO nfs-client <unset> 19h blogx-server-data Bound pvc-c104ba38-883d-4b5c-a82a-1df20618e7bc 5Gi RWO nfs-client <unset> 7d12h blogx-server-logs Bound pvc-79514763-2d8a-4f30-8850-3a572aed5d17 5Gi RWO nfs-client <unset> 19h mysql-data-mysql-master-0 Bound pvc-1d58907c-d217-46c3-9122-f734e026a475 10Gi RWO nfs-client <unset> 24h redis-data-redis-0 Bound pvc-d4a629d4-b92f-4772-9a96-e07f9f27197a 1Gi RWO nfs-client <unset> 7d12h root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# kubectl describe pvc blogx-server-config Name: blogx-server-config Namespace: default StorageClass: nfs-client Status: Bound Volume: pvc-60dba83b-6863-438c-a0a5-ac2de6db518e Labels: <none> Annotations: pv.kubernetes.io/bind-completed: yes pv.kubernetes.io/bound-by-controller: yes volume.beta.kubernetes.io/storage-provisioner: cluster.local/nfs-subdir-external-provisioner volume.kubernetes.io/storage-provisioner: cluster.local/nfs-subdir-external-provisioner Finalizers: [kubernetes.io/pvc-protection] Capacity: 5Gi Access Modes: RWO VolumeMode: Filesystem Used By: blogx-server-5996b7dc46-mg64k Events: <none> root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# kubectl describe pv pvc-60dba83b-6863-438c-a0a5-ac2de6db518e Name: pvc-60dba83b-6863-438c-a0a5-ac2de6db518e Labels: <none> Annotations: pv.kubernetes.io/provisioned-by: cluster.local/nfs-subdir-external-provisioner Finalizers: [kubernetes.io/pv-protection] StorageClass: nfs-client Status: Bound Claim: default/blogx-server-config Reclaim Policy: Delete Access Modes: RWO VolumeMode: Filesystem Capacity: 5Gi Node Affinity: <none> Message: Source: Type: NFS (an NFS mount that lasts the lifetime of a pod) Server: 10.17.210.200 Path: /data/default-blogx-server-config-pvc-60dba83b-6863-438c-a0a5-ac2de6db518e ReadOnly: false Events: <none> root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# cd /data/default-blogx-server-config-pvc-60dba83b-6863-438c-a0a5-ac2de6db518e root@dennis:/data/default-blogx-server-config-pvc-60dba83b-6863-438c-a0a5-ac2de6db518e# ls settings.yaml
//deployment root@dennis:/home/dennis/Blogx/init/deploy/blogx_server# cat blogx-server-dep.yaml apiVersion: apps/v1 kind: Deployment metadata: name: blogx-server spec: replicas: 1 selector: matchLabels: app: blogx-server template: metadata: labels: app: blogx-server spec: containers: - name: blogx-server image: docker.io/library/blogx_server:v3 env: - name: TZ value: "Asia/Shanghai" ports: - containerPort: 8080 volumeMounts: - name: config mountPath: /app/settings.yaml //注意这个路径下你要先有这个东西 不然挂进去是一个目录 subPath: settings.yaml - name: data mountPath: /app/uploads subPath: uploads - name: logs mountPath: /app/logs subPath: logs # 建议添加健康检查(如果你的应用有健康检查接口) # livenessProbe: # httpGet: # path: /health # port: 8080 # initialDelaySeconds: 30 # periodSeconds: 10 # readinessProbe: # httpGet: # path: /ready # port: 8080 # initialDelaySeconds: 5 # periodSeconds: 5 volumes: - name: config persistentVolumeClaim: claimName: blogx-server-config - name: data persistentVolumeClaim: claimName: blogx-server-data - name: logs persistentVolumeClaim: claimName: blogx-server-logs
blogx-web
//configmap root@dennis:/home/dennis/Blogx/init/deploy/blogx_web# cat web-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: blogx-web-config data: nginx.conf: | user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; server { listen 80; server_name localhost; client_header_buffer_size 32k; large_client_header_buffers 4 32k; location / { root /usr/share/nginx/html/; index index.html index.htm; try_files $uri $uri/ /index.html; } # 后端 API 代理 location /api/ { proxy_pass http://blogx-server:8080; //这里直接写servicename proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 20M; } } }
//deployment root@dennis:/home/dennis/Blogx/init/deploy/blogx_web# cat blogx_web.yaml apiVersion: apps/v1 kind: Deployment metadata: name: blogx-web spec: replicas: 1 selector: matchLabels: app: blogx-web template: metadata: labels: app: blogx-web spec: volumes: - name: nginx-conf # 这个名字必须和下面 volumeMounts 一致 configMap: name: blogx-web-config # 对应你的 ConfigMap 名称 containers: - name: nginx image: nexus.dennis.com.cn:8082/blogx_web:v1 volumeMounts: - name: nginx-conf # 这里必须和上面 volumes.name 一样!!! mountPath: /etc/nginx/nginx.conf subPath: nginx.conf env: - name: TZ value: "Asia/Shanghai" imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: blogx-web spec: type: NodePort //类型为nodeport 后面我自动暴露一个30000以上的端口供外部访问 不然默认为ClusterIP selector: app: blogx-web ports: - port: 80 targetPort: 80