VOLUME

VOLUME

bash 复制代码
[root@master30 ~ 10:39:56]# kubectl create ns storage
Error from server (AlreadyExists): namespaces "storage" already exists
[root@master30 ~ 10:40:24]# kubectl config set-context --current --namespace storage
Context "kubernetes-super-admin@kubernetes" modified.

Volume 类型

Kubernetes支持Volume类型有:

  • emptyDir
  • hostPath
  • gcePersistentDisk
  • awsElasticBlockStore
  • nfs
  • iscsi
  • fc (fibre channel)
  • flocker
  • glusterfs
  • rbd
  • cephfs
  • gitRepo
  • secret
  • persistentVolumeClaim
  • downwardAPI
  • projected
  • azureFileVolume
  • azureDisk
  • vsphereVolume
  • Quobyte
  • PortworxVolume
  • ScaleIO
  • StorageOS
  • local

emptyDir

默认情况下,当Pod分配到Node上时,将会创建emptyDir,只要Node上的Pod一直运行,Volume就会一直存。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。

bash 复制代码
[root@master30 ~ 10:42:25]# kubectl apply -f pod-with-emptyDir.yaml
pod/busybox created
[root@master30 ~ 11:06:55]# kubectl describe pod busybox |grep Node:
Node:             worker32.my.cloud/10.1.8.32
[root@master30 ~ 11:07:07]# kubectl exec busybox -c busybox1 -- touch /data/b1-f1
[root@master30 ~ 11:10:22]# kubectl exec busybox -c busybox2 -- ls /data
b1-f1
[root@master30 ~ 11:10:30]# kubectl describe pod busybox |grep Node:
Node:             worker32.my.cloud/10.1.8.32
[root@master30 ~ 11:12:22]# kubectl describe pod busybox |egrep -o 'Container ID.*//.{12}'
Container ID:  containerd://36fb0dadfa81
Container ID:  containerd://d7f6b052ce70
[root@worker32 ~ 11:12:02]# crictl inspect 36fb0dadfa81|grep datavolume
        "hostPath": "/var/lib/kubelet/pods/eadb379a-65f9-47bf-9d0c-a0e66af33341/volumes/kubernetes.io~empty-dir/datavolume",
          "host_path": "/var/lib/kubelet/pods/eadb379a-65f9-47bf-9d0c-a0e66af33341/volumes/kubernetes.io~empty-dir/datavolume"
          "source": "/var/lib/kubelet/pods/eadb379a-65f9-47bf-9d0c-a0e66af33341/volumes/kubernetes.io~empty-dir/datavolume",
[root@worker32 ~ 11:13:05]# ls /var/lib/kubelet/pods/eadb379a-65f9-47bf-9d0c-a0e66af33341/volumes/kubernetes.io~empty-dir/datavolume
b1-f1
[root@worker32 ~ 11:15:36]# ls /var/lib/kubelet/pods/eadb379a-65f9-47bf-9d0c-a0e66af33341/volumes/kubernetes.io~empty-dir/datavolume
ls: cannot access '/var/lib/kubelet/pods/eadb379a-65f9-47bf-9d0c-a0e66af33341/volumes/kubernetes.io~empty-dir/datavolume': No such file or directory

hostPath

bash 复制代码
[root@master30 ~ 11:15:12]# vim pod-with-hostPath.yaml
[root@master30 ~ 11:17:01]#  kubectl apply -f pod-with-hostPath.yaml
pod/busybox created
[root@master30 ~ 11:17:07]# kubectl describe pod busybox |egrep -o 'Container ID.*//.{12}'
Container ID:  containerd://f339b36a4589
Container ID:  containerd://1854b7e63a26
[root@master30 ~ 11:17:16]# kubectl describe pod busybox |grep Node:
Node:             worker32.my.cloud/10.1.8.32
[root@master30 ~ 11:17:26]# kubectl exec busybox -c busybox1 -- touch /data/b1-f1
[root@master30 ~ 11:18:27]# kubectl delete pod busybox --force
Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "busybox" force deleted
[root@worker32 ~ 11:16:04]# crictl inspect f339b36a4589|grep busyboxdir
        "hostPath": "/busyboxdir",
          "host_path": "/busyboxdir"
          "source": "/busyboxdir",
[root@worker32 ~ 11:18:10]# ls /busyboxdir/
b1-f1
[root@worker32 ~ 11:18:37]# ls /busyboxdir/
b1-f1

NFS存储

bash 复制代码
[root@master30 ~ 11:18:45]# apt install -y nfs-kernel-server
[root@master30 ~ 11:20:24]# mkdir -m 777 /nfsshares
[root@master30 ~ 11:21:07]# echo hello 伊良波五月 > /nfsshares/index.html
[root@master30 ~ 11:21:35]# cat << EOF > /etc/exports
/nfsshares *(rw)
EOF
[root@master30 ~ 11:21:52]# systemctl restart nfs-server.service
[root@master30 ~ 11:21:58]# vim pod-with-nfs.yaml
[root@master30 ~ 11:23:07]# kubectl apply -f pod-with-nfs.yaml
pod/nginx created
[root@master30 ~ 11:23:14]# kubectl describe pod nginx |egrep -o 'Container ID.*//.{12}'
[root@master30 ~ 11:23:20]# kubectl describe pod nginx |egrep -o 'Container ID.*//.{12}'
[root@master30 ~ 11:23:37]# kubectl describe pod nginx |egrep -o 'Container ID.*//.{12}'
Container ID:   containerd://fecfa77e7f73
[root@master30 ~ 11:23:51]# kubectl describe pod nginx |grep Node:
Node:             worker32.my.cloud/10.1.8.32
[root@master30 ~ 11:24:02]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE                NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          97s   10.224.125.132   worker32.my.cloud   <none>           <none>
[root@master30 ~ 11:25:11]# curl 10.224.125.132
hello 伊良波五月
[root@worker31 ~ 11:22:35]# apt install -y nfs-kernel-server
[root@worker32 ~ 11:22:35]# apt install -y nfs-kernel-server
[root@worker32 ~ 11:22:23]# crictl inspect fecfa77e7f73|grep /usr/share/nginx/html
        "containerPath": "/usr/share/nginx/html",
          "container_path": "/usr/share/nginx/html",
          "destination": "/usr/share/nginx/html",

持久性存储

学习参考:持久卷

Kubernetes 使用 persistent volume(PV)架构为集群提供永久存储。

PV 和 PVC 架构

创建PV

bash 复制代码
[root@master30 ~ 11:37:46]# vim pv.yaml
[root@master30 ~ 11:42:06]# kubectl apply -f pv.yaml
persistentvolume/web created
[root@master30 ~ 11:42:11]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
web    5Gi        RWO            Retain           Available                          <unset>                          4s

创建PVC

bash 复制代码
[root@master30 ~ 11:42:15]# vim pvc.yaml
[root@master30 ~ 11:43:17]# kubectl apply -f pvc.yaml
persistentvolumeclaim/webclaim created
[root@master30 ~ 11:43:23]# kubectl get pvc
NAME       STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
webclaim   Bound    web      5Gi        RWO                           <unset>                 5s

创建Pod使用PV

bash 复制代码
[root@master30 ~ 11:43:28]# vim pod-with-pvc.yaml
[root@master30 ~ 11:44:20]#  kubectl apply -f pod-with-pvc.yaml
pod/web created
[root@master30 ~ 11:44:28]# kubectl get pod -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP               NODE                NOMINATED NODE   READINESS GATES
nginx   1/1     Running             0          21m   10.224.125.132   worker32.my.cloud   <none>           <none>
web     0/1     ContainerCreating   0          5s    <none>           worker31.my.cloud   <none>           <none>
[root@master30 ~ 11:44:33]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE                NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          21m   10.224.125.132   worker32.my.cloud   <none>           <none>
web     1/1     Running   0          21s   10.224.15.65     worker31.my.cloud   <none>           <none>
[root@master30 ~ 11:44:49]# curl http://10.224.15.65
hello 伊良波五月
[root@master30 ~ 11:45:02]# echo hello 黑川美佳子 > /nfsshares/test.html
[root@master30 ~ 11:46:32]# curl http://10.224.15.65
hello 伊良波五月
[root@master30 ~ 11:46:43]# curl http://10.224.15.65/test.html
hello 黑川美佳子
[root@master30 ~ 11:47:13]# kubectl delete pod web --force
Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "web" force deleted

Retain

bash 复制代码
[root@master30 ~ 13:44:29]# vim pv-pvc-Retain.yaml
[root@master30 ~ 13:55:08]# kubectl apply -f pv-pvc-Retain.yaml
persistentvolume/web unchanged
persistentvolumeclaim/webclaim unchanged
[root@master30 ~ 13:55:17]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
web    5Gi        RWO            Retain           Bound    storage/webclaim                  <unset>                          133m
[root@master30 ~ 13:55:22]# kubectl get pvc
NAME       STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
webclaim   Bound    web      5Gi        RWO                           <unset>                 132m

ConfigMap

bash 复制代码
[root@master30 ~ 13:30:19]# kubectl get all,pv,pvc
NAME        READY   STATUS    RESTARTS      AGE
pod/nginx   1/1     Running   1 (14m ago)   141m

NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/web   5Gi        RWO            Retain           Bound    storage/webclaim                  <unset>                          122m

NAME                             STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/webclaim   Bound    web      5Gi        RWO                           <unset>                 121m
[root@master30 ~ 13:44:29]# vim pv-pvc-Retain.yaml
[root@master30 ~ 13:55:08]# kubectl apply -f pv-pvc-Retain.yaml
persistentvolume/web unchanged
persistentvolumeclaim/webclaim unchanged
[root@master30 ~ 13:55:17]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
web    5Gi        RWO            Retain           Bound    storage/webclaim                  <unset>                          133m
[root@master30 ~ 13:55:22]# kubectl get pvc
NAME       STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
webclaim   Bound    web      5Gi        RWO                           <unset>                 132m
[root@master30 ~ 13:55:28]# vim pod-cm-env.yaml
[root@master30 ~ 14:39:40]# kubectl apply -f pod-cm-env.yaml
pod/mysql created
[root@master30 ~ 14:39:47]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS      AGE     IP               NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     ContainerCreating   0             5s      <none>           worker31.my.cloud   <none>           <none>
nginx   1/1     Running             1 (70m ago)   3h16m   10.224.125.133   worker32.my.cloud   <none>           <none>
[root@master30 ~ 14:39:52]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS      AGE     IP               NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     ContainerCreating   0             25s     <none>           worker31.my.cloud   <none>           <none>
nginx   1/1     Running             1 (70m ago)   3h16m   10.224.125.133   worker32.my.cloud   <none>           <none>
[root@master30 ~ 14:40:12]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS      AGE     IP               NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     ContainerCreating   0             54s     <none>           worker31.my.cloud   <none>           <none>
nginx   1/1     Running             1 (70m ago)   3h17m   10.224.125.133   worker32.my.cloud   <none>           <none>
[root@master30 ~ 14:40:41]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS      AGE     IP               NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     ContainerCreating   0             117s    <none>           worker31.my.cloud   <none>           <none>
nginx   1/1     Running             1 (71m ago)   3h18m   10.224.125.133   worker32.my.cloud   <none>           <none>
[root@master30 ~ 14:41:44]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS      AGE     IP               NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     ContainerCreating   0             2m51s   <none>           worker31.my.cloud   <none>           <none>
nginx   1/1     Running             1 (72m ago)   3h19m   10.224.125.133   worker32.my.cloud   <none>           <none>
[root@master30 ~ 14:42:38]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS      AGE     IP               NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     ContainerCreating   0             4m12s   <none>           worker31.my.cloud   <none>           <none>
nginx   1/1     Running             1 (74m ago)   3h20m   10.224.125.133   worker32.my.cloud   <none>           <none>
[root@master30 ~ 14:43:59]# kubectl create ns configure
namespace/configure created
[root@master30 ~ 14:44:05]# kubectl config set-context --current --namespace configure
Context "kubernetes-admin@kubernetes" modified.
[root@master30 ~ 14:44:11]# kubectl delete ns storage
namespace "storage" deleted
[root@master30 ~ 14:44:37]# kubectl apply -f pod-cm-env.yaml
pod/mysql created
[root@master30 ~ 14:44:54]# kubectl get pods -o wide
NAME    READY   STATUS                       RESTARTS   AGE   IP             NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     CreateContainerConfigError   0          11s   10.224.15.67   worker31.my.cloud   <none>           <none>
[root@master30 ~ 14:45:05]# kubectl get pods -o wide
NAME    READY   STATUS                       RESTARTS   AGE   IP             NODE                NOMINATED NODE   READINESS GATES
mysql   0/1     CreateContainerConfigError   0          33s   10.224.15.67   worker31.my.cloud   <none>           <none>
[root@master30 ~ 14:45:27]# kubectl describe pod mysql
Name:             mysql
Namespace:        configure
Priority:         0
Service Account:  default
Node:             worker31.my.cloud/10.1.8.31
Start Time:       Thu, 25 Jun 2026 14:44:54 +0800
Labels:           name=mysql
Annotations:      cni.projectcalico.org/containerID: aaa300afb7152a6abb45ee2b4a831b174728cd165163d42d8fcf5a48551d644f
                  cni.projectcalico.org/podIP: 10.224.15.67/32
                  cni.projectcalico.org/podIPs: 10.224.15.67/32
Status:           Pending
IP:               10.224.15.67
IPs:
  IP:  10.224.15.67
Containers:
  mysql:
    Container ID:
    Image:          docker.io/library/mysql:latest
    Image ID:
    Port:           3306/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       CreateContainerConfigError
    Ready:          False
    Restart Count:  0
    Environment:
      MYSQL_ROOT_PASSWORD:  <set to the key 'password' of config map 'mysql'>  Optional: false
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-g2x4w (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       False
  ContainersReady             False
  PodScheduled                True
Volumes:
  kube-api-access-g2x4w:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  66s               default-scheduler  Successfully assigned configure/mysql to worker31.my.cloud
  Normal   Pulled     1s (x8 over 65s)  kubelet            Container image "docker.io/library/mysql:latest" already present on machine
  Warning  Failed     1s (x8 over 65s)  kubelet            Error: configmap "mysql" not found
[root@master30 ~ 14:46:00]# vim pod-cm-env.yaml
[root@master30 ~ 14:46:40]# kubectl create configmap mysql --from-literal=password redhat -n configure
error: exactly one NAME is required, got 2
See 'kubectl create configmap -h' for help and examples
[root@master30 ~ 14:47:28]# kubectl create configmap mysql --from-literal=password=redhat -n configure
configmap/mysql created
[root@master30 ~ 14:47:45]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP             NODE                NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          3m22s   10.224.15.67   worker31.my.cloud   <none>           <none>
[root@master30 ~ 14:48:16]# kubectl exec -it mysql -- bash -c 'echo $MYSQL_ROOT_PASSWORD'
redhat
[root@master30 ~ 14:48:27]# apt install -y mysql-client
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  mysql-client-8.0 mysql-client-core-8.0 mysql-common
The following NEW packages will be installed:
  mysql-client mysql-client-8.0 mysql-client-core-8.0 mysql-common
0 upgraded, 4 newly installed, 0 to remove and 258 not upgraded.
Need to get 2778 kB of archives.
After this operation, 61.8 MB of additional disk space will be used.
Get:1 http://mirrors.huaweicloud.com/ubuntu noble-updates/main amd64 mysql-client-core-8.0 amd64 8.0.46-0ubuntu0.24.04.3 [2740 kB]
Get:2 http://mirrors.huaweicloud.com/ubuntu noble/main amd64 mysql-common all 5.8+1.1.0build1 [6746 B]
Get:3 http://mirrors.huaweicloud.com/ubuntu noble-updates/main amd64 mysql-client-8.0 amd64 8.0.46-0ubuntu0.24.04.3 [22.4 kB]
Get:4 http://mirrors.huaweicloud.com/ubuntu noble-updates/main amd64 mysql-client all 8.0.46-0ubuntu0.24.04.3 [9414 B]
Fetched 2778 kB in 8s (358 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package mysql-client-core-8.0.
(Reading database ... 76946 files and directories currently installed.)
Preparing to unpack .../mysql-client-core-8.0_8.0.46-0ubuntu0.24.04.3_amd64.deb ...
Unpacking mysql-client-core-8.0 (8.0.46-0ubuntu0.24.04.3) ...
Selecting previously unselected package mysql-common.
Preparing to unpack .../mysql-common_5.8+1.1.0build1_all.deb ...
Unpacking mysql-common (5.8+1.1.0build1) ...
Selecting previously unselected package mysql-client-8.0.
Preparing to unpack .../mysql-client-8.0_8.0.46-0ubuntu0.24.04.3_amd64.deb ...
Unpacking mysql-client-8.0 (8.0.46-0ubuntu0.24.04.3) ...
Selecting previously unselected package mysql-client.
Preparing to unpack .../mysql-client_8.0.46-0ubuntu0.24.04.3_all.deb ...
Unpacking mysql-client (8.0.46-0ubuntu0.24.04.3) ...
Setting up mysql-common (5.8+1.1.0build1) ...
update-alternatives: using /etc/mysql/my.cnf.fallback to provide /etc/mysql/my.cnf (my.cnf) in auto mode
Setting up mysql-client-core-8.0 (8.0.46-0ubuntu0.24.04.3) ...
Setting up mysql-client-8.0 (8.0.46-0ubuntu0.24.04.3) ...
Setting up mysql-client (8.0.46-0ubuntu0.24.04.3) ...
Scanning processes...
Scanning linux images...

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
[root@master30 ~ 14:49:13]# mysql -u root -predhat -h 10.224.15.67
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 9.7.1 MySQL Community Server - GPL

Copyright (c) 2000, 2026, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
mysql> exit
Bye
[root@master30 ~ 14:50:11]# kubectl exec -it mysql -- bash
bash-5.1# echo $MYSQL_ROOT_PASSWORD
redhat

haproxy+web

bash 复制代码
[root@master30 ~ 15:24:06]# kubectl create cm webapp-1 \
  --from-literal=index.html="hello webapp-1" \
  --from-literal=error.html="sorry, error."
configmap/webapp-1 created
[root@master30 ~ 15:24:11]# vim pod-webapp-1.yaml
[root@master30 ~ 15:24:27]# kubectl apply -f pod-webapp-1.yaml
pod/webapp-1 created
[root@master30 ~ 15:24:32]# kubectl create cm webapp-2 \
  --from-literal=index.html="hello webapp-2" \
  --from-literal=error.html="sorry, error."
configmap/webapp-2 created
[root@master30 ~ 15:24:36]# vim pod-webapp-2.yaml
[root@master30 ~ 15:25:05]# kubectl apply -f pod-webapp-2.yaml
pod/webapp-2 created
[root@master30 ~ 15:25:08]# kubectl get pods -o wide | grep webapp
webapp-1   1/1     Running   0          41s   10.224.15.68     worker31.my.cloud   <none>           <none>
webapp-2   1/1     Running   0          5s    10.224.125.135   worker32.my.cloud   <none>           <none>
[root@master30 ~ 15:25:13]# vim haproxy.cfg
[root@master30 ~ 15:25:47]# cat > haproxy.cfg <<EOF
global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http-in
    bind *:8080
    default_backend servers

backend servers
> server app1 10.224.15.68 80:80 check
> server app2 10.224.125.135^C
[root@master30 ~ 15:26:54]# cat > haproxy.cfg <<EOF
global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend http-in
    bind *:8080
    default_backend servers

backend servers
server app1 10.224.15.68:80 check
server app2 10.224.125.135:80 check
> EOF
[root@master30 ~ 15:27:34]# kubectl create cm haproxy.cfg --from-file=haproxy.cfg=./haproxy.cfg
configmap/haproxy.cfg created
[root@master30 ~ 15:27:42]# vim haproxy.yaml
[root@master30 ~ 15:27:57]# kubectl apply -f haproxy.yaml
pod/haproxy created
[root@master30 ~ 15:28:01]# kubectl get pods -o wide
NAME       READY   STATUS              RESTARTS   AGE     IP               NODE                NOMINATED NODE   READINESS GATES
haproxy    0/1     ContainerCreating   0          6s      <none>           worker31.my.cloud   <none>           <none>
webapp-1   1/1     Running             0          3m35s   10.224.15.68     worker31.my.cloud   <none>           <none>
webapp-2   1/1     Running             0          2m59s   10.224.125.135   worker32.my.cloud   <none>           <none>
[root@master30 ~ 15:28:07]# kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE     IP               NODE                NOMINATED NODE   READINESS GATES
haproxy    1/1     Running   0          27s     10.224.15.69     worker31.my.cloud   <none>           <none>
webapp-1   1/1     Running   0          3m56s   10.224.15.68     worker31.my.cloud   <none>           <none>
webapp-2   1/1     Running   0          3m20s   10.224.125.135   worker32.my.cloud   <none>           <none>
[root@master30 ~ 15:28:28]# curl http://10.224.15.69:8080
hello webapp-1[root@master30 ~ 15:28:46]# curl http://10.224.15.69:8080
hello webapp-2[root@master30 ~ 15:28:48]#

Secret

bash 复制代码
[root@master30 ~ 15:44:19]# kubectl create ns blog
namespace/blog created
[root@master30 ~ 16:39:31]# kubectl create secret generic mysql-secret -n blog \
  --from-literal=MYSQL_ROOT_PASSWORD=rootpass \
  --from-literal=MYSQL_DATABASE=wordpress \
  --from-literal=MYSQL_USER=wpuser \
  --from-literal=MYSQL_PASSWORD=wppass
secret/mysql-secret created
[root@master30 ~ 16:40:24]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=blog.example.com"

kubectl create secret tls wordpress-tls -n blog \
  --cert=tls.crt --key=tls.key
.+..............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+...+......+.........+...+...+.......+..+.+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+.................+....+.....+............+....+......+..+...............+............+...+......+.+...+..+.+...........................+.....+...+...+.......+...+.........+..+.+...+...............+.....+....+..+...+......+....+..+.+.....+...+......+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.+.....+.+.....+......+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+........+.......+..+....+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+...........+.+..+.+...........+...+...+.......+...+.........+.....+....+.....+.+......+........+.+...+...........+.......+.....+...+..........+.........+..+.........+.+........+.+.....+.......+..+............+.+...+..+...+.........+...+....+.........+.....+..........+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
secret/wordpress-tls created
[root@master30 ~ 16:40:39]# cat > wordpress.conf <<EOF
<VirtualHost *:80>
    ServerName blog.example.com
    Redirect permanent / https://blog.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName blog.example.com
    DocumentRoot /var/www/html

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/tls.crt
    SSLCertificateKeyFile /etc/ssl/private/tls.key

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
EOF

kubectl create configmap wordpress-vhost -n blog --from-file=wordpress.conf
configmap/wordpress-vhost created
[root@master30 ~ 16:41:27]# vim mysql-deploy.yaml
[root@master30 ~ 16:42:23]# vim mysql-svc.yaml
[root@master30 ~ 16:42:51]# kubectl apply -f mysql-deploy.yaml
kubectl apply -f mysql-svc.yaml
deployment.apps/mysql created
service/mysql created
[root@master30 ~ 16:42:55]# vim wordpress-deploy.yaml
[root@master30 ~ 16:44:12]# vim wordpress-svc.yaml
[root@master30 ~ 16:44:45]# kubectl apply -f wordpress-deploy.yaml
kubectl apply -f wordpress-svc.yaml
deployment.apps/wordpress created
service/wordpress created
[root@master30 ~ 16:44:48]# kubectl get pods -n blog
NAME                        READY   STATUS              RESTARTS   AGE
mysql-6b88dd5775-hcz8l      1/1     Running             0          118s
wordpress-89749f487-bbxt5   0/1     ContainerCreating   0          5s
[root@master30 ~ 16:44:53]# kubectl get pods -n blog
NAME                        READY   STATUS              RESTARTS   AGE
mysql-6b88dd5775-hcz8l      1/1     Running             0          2m57s
wordpress-89749f487-bbxt5   0/1     ContainerCreating   0          64s
[root@master30 ~ 16:45:52]# kubectl get pods -n blog
NAME                        READY   STATUS    RESTARTS      AGE
mysql-6b88dd5775-hcz8l      1/1     Running   0             3m57s
wordpress-89749f487-bbxt5   0/1     Error     1 (14s ago)   2m4s
[root@master30 ~ 16:46:52]# kubectl describe pod wordpress-89749f487-bbxt5 -n blog
Name:             wordpress-89749f487-bbxt5
Namespace:        blog
Priority:         0
Service Account:  default
Node:             worker31.my.cloud/10.1.8.31
Start Time:       Thu, 25 Jun 2026 16:44:48 +0800
Labels:           app=wordpress
                  pod-template-hash=89749f487
Annotations:      cni.projectcalico.org/containerID: 44b70b318e86de39945163bc8a96208f1f6fd6d070a0ce26d14c83285f2da6a2
                  cni.projectcalico.org/podIP: 10.224.15.70/32
                  cni.projectcalico.org/podIPs: 10.224.15.70/32
Status:           Running
IP:               10.224.15.70
IPs:
  IP:           10.224.15.70
Controlled By:  ReplicaSet/wordpress-89749f487
Containers:
  wordpress:
    Container ID:   containerd://64b9d6799c8f93960fefe451f08dbbb245b56ca5e3edc08f3c5b4223923a8c72
    Image:          wordpress:latest
    Image ID:       docker.io/library/wordpress@sha256:6d37018d26165824c0dfb5d612e205c70adf760fed9c614187d18091646c9e31
    Ports:          80/TCP, 443/TCP
    Host Ports:     0/TCP, 0/TCP
    State:          Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Thu, 25 Jun 2026 16:46:53 +0800
      Finished:     Thu, 25 Jun 2026 16:46:54 +0800
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Thu, 25 Jun 2026 16:46:40 +0800
      Finished:     Thu, 25 Jun 2026 16:46:41 +0800
    Ready:          False
    Restart Count:  2
    Environment:
      WORDPRESS_DB_HOST:      mysql:3306
      WORDPRESS_DB_USER:      <set to the key 'MYSQL_USER' in secret 'mysql-secret'>      Optional: false
      WORDPRESS_DB_PASSWORD:  <set to the key 'MYSQL_PASSWORD' in secret 'mysql-secret'>  Optional: false
      WORDPRESS_DB_NAME:      <set to the key 'MYSQL_DATABASE' in secret 'mysql-secret'>  Optional: false
    Mounts:
      /etc/apache2/sites-enabled/000-default.conf from vhost-config (ro,path="wordpress.conf")
      /etc/ssl/certs/tls.crt from tls-certs (ro,path="tls.crt")
      /etc/ssl/private/tls.key from tls-certs (ro,path="tls.key")
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d64cb (ro)
      /var/www/html from wordpress-storage (rw)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       False
  ContainersReady             False
  PodScheduled                True
Volumes:
  vhost-config:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      wordpress-vhost
    Optional:  false
  tls-certs:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  wordpress-tls
    Optional:    false
  wordpress-storage:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  kube-api-access-d64cb:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  2m14s             default-scheduler  Successfully assigned blog/wordpress-89749f487-bbxt5 to worker31.my.cloud
  Normal   Pulling    2m13s             kubelet            Pulling image "wordpress:latest"
  Normal   Pulled     26s               kubelet            Successfully pulled image "wordpress:latest" in 1m46.655s (1m46.655s including waiting). Image size: 268956550 bytes.
  Normal   Created    9s (x3 over 26s)  kubelet            Created container wordpress
  Normal   Started    9s (x3 over 26s)  kubelet            Started container wordpress
  Normal   Pulled     9s (x2 over 22s)  kubelet            Container image "wordpress:latest" already present on machine
  Warning  BackOff    8s (x2 over 21s)  kubelet            Back-off restarting failed container wordpress in pod wordpress-89749f487-bbxt5_blog(759ee9a0-a63c-49b2-8d3d-91fa2080cb0f)
[root@master30 ~ 16:47:02]# kubectl exec -it mysql-6b88dd5775-hcz8l -n blog -- mysql -uroot -prootpass -e "SHOW DATABASES;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wordpress          |
+--------------------+
[root@master30 ~ 16:48:06]# kubectl logs wordpress-89749f487-bbxt5 -n blog
AH00526: Syntax error on line 10 of /etc/apache2/sites-enabled/000-default.conf:
Invalid command 'SSLEngine', perhaps misspelled or defined by a module not included in the server configuration
[root@master30 ~ 16:49:01]# vim wordpress-deploy.yaml                                                     [root@master30 ~ 16:51:37]# kubectl apply -f wordpress-deploy.yaml -n blog
kubectl delete pod -l app=wordpress -n blog
deployment.apps/wordpress configured
pod "wordpress-58ffdb8874-t2mvj" deleted
pod "wordpress-89749f487-bbxt5" deleted
[root@master30 ~ 16:51:46]# kubectl get pods -n blog -l app=wordpress
NAME                         READY   STATUS    RESTARTS   AGE
wordpress-58ffdb8874-djw95   1/1     Running   0          22s
[root@master30 ~ 16:52:06]# kubectl get svc -n blog
NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
mysql       ClusterIP   10.100.232.214   <none>        3306/TCP                     9m48s
wordpress   NodePort    10.109.27.168    <none>        80:30080/TCP,443:30443/TCP   7m55s
[root@master30 ~ 16:52:43]# kubectl get nodes -o wide
NAME                STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
master30.my.cloud   Ready    control-plane   2d5h   v1.30.2   10.1.8.30     <none>        Ubuntu 24.04 LTS   6.8.0-31-generic   containerd://1.7.20
worker31.my.cloud   Ready    <none>          2d5h   v1.30.2   10.1.8.31     <none>        Ubuntu 24.04 LTS   6.8.0-31-generic   containerd://1.7.20
worker32.my.cloud   Ready    <none>          2d5h   v1.30.2   10.1.8.32     <none>        Ubuntu 24.04 LTS   6.8.0-31-generic   containerd://1.7.20
[root@master30 ~ 16:54:28]# curl -s http://10.1.8.31:30080 | head -10
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://blog.example.com/">here</a>.</p>
<hr>
<address>Apache/2.4.67 (Debian) Server at 10.1.8.31 Port 30080</address>
</body></html>
[root@master30 ~ 16:55:13]# curl -s http://10.1.8.30:30080 | head -10
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://blog.example.com/">here</a>.</p>
<hr>
<address>Apache/2.4.67 (Debian) Server at 10.1.8.30 Port 30080</address>
</body></html>
[root@master30 ~ 16:58:26]#

运行结果

dy>

Moved Permanently

The document has moved here.


Apache/2.4.67 (Debian) Server at 10.1.8.31 Port 30080 root@master30 \~ 16:55:13# curl -s http://10.1.8.30:30080 | head -10 301 Moved Permanently

Moved Permanently

The document has moved here.


Apache/2.4.67 (Debian) Server at 10.1.8.30 Port 30080 root@master30 \~ 16:58:26# ~~~

运行结果