重生之我爱上了k8s!

时间:2024-10-22 07:57:00
内容不全,待补充中...... 

目录

一、k8s的部署

1.1.集群环境初始化

1.1.1.所有主机禁用swap

1.1.2.安装k8s部署工具

1.1.2.所有节点安装cri-docker

1.1.3.在master节点拉取K8S所需镜像

1.1.4.集群初始化

1.1.5.其他两台主机加入集群

1.1.6.安装flannel网络插件

1.1.7.查看所有node的状态

三、pod的管理和优化

3、pod的生命周期

(1)、INIT容器

2、探针

四、控制器

1、replicaset

2、deployment控制器

3、daemonset控制器

4、job控制器

5、cronjob控制器

k8s的存储

1、Configmap

(1)、congifmap的创建方式

(2)、configmap的使用方式

使用configmap 填充环境变量

通过数据卷使用configmap

利用configmap填充pod的配置文件

 2、secrets

(1)、secrets的创建

(2)、secrets的应用

挂载卷

向指定路径映射 secret 密钥

将secrets设置为环境变量

 存储docker registry的认证信息

3、volumes

(1)、emptyDir卷

(2)、hostpath卷

(3)、nfs卷

(4)、持久卷

4、存储类


 

准备工作:

1、准备一台主机为harbor镜像仓库

搭建私人镜像仓库

2、新建三台主机连接到该镜像仓库

实验环境:

主机名 ip
k8s-master 172.25.254.100
k8s-node1 172.25.254.10
k8s-node2 172.25.254.20
docker-harbor(reg.gaoyingjie.org) 172.25.254.250

操作:

(1)、配置三台主机的解析

vim /etc/hosts

内容:
172.25.254.100  k8s-master
172.25.254.10   k8s-node1
172.25.254.20   k8s-node2
172.25.254.250  reg.gaoyingjie.org

(2)、检查三台主机的软件仓库

(3)、三台主机安装docker

(4)、从harbor主机将认证证书传输给三台主机

[root@k8s-master docker]# mkdir -p  /etc/docker/certs.d/reg.gaoyingjie.org

[root@docker-harbor ~]# scp /data/certs/gaoyingjie.org.crt root@172.25.254.100:/etc/docker/certs.d/reg.gaoyingjie.org/ca.crt

(5)、设置镜像源

[root@k8s-master reg.gaoyingjie.org]# vim /etc/docker/daemon.json
内容;

{
        "registry-mirrors":["https://reg.gaoyingjie.org"]
}

(6)、传输

将100主机的所有文件传输给10、20主机

[root@k8s-master ~]# scp *.rpm root@172.25.254.10:/root
[root@k8s-master ~]# scp *.rpm root@172.25.254.20:/root
[root@k8s-node1 ~]# dnf install *.rpm -y
[root@k8s-node2 ~]# dnf install *.rpm -y


[root@k8s-master ~]# scp -r /etc/docker/ root@172.25.254.10:/etc/
[root@k8s-master ~]# scp -r /etc/docker/ root@172.25.254.20:/etc/

(7)、登录

三台主机都可以登录仓库reg.gaoyingjie.org

docker login reg.gaoyingjie.org

一、k8s的部署

1.1.集群环境初始化

1.1.1.所有主机禁用swap

[root@k8s- ~]# systemctl mask dev-nvme0n1p3.swap
[root@k8s- ~]# swapoff -a
[root@k8s- ~]# systemctl status dev-nvme0n1p3.swap
[root@k8s- ~]# vim /etc/fstab 

内容:
注释swap

1.1.2.安装k8s部署工具

[root@k8s-master ~]# dnf install kubelet-1.30.0 kubeadm-1.30.0 kubectl-1.30.0 -y

#设置kubectl命令自动补全功能
[root@k8s-master ~]# dnf install bash-completion -y
[root@k8s-master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@k8s-master ~]# source  ~/.bashrc

1.1.2.所有节点安装cri-docker

[root@k8s-master ~]# dnf install libcgroup-0.41-19.el8.x86_64.rpm \
> cri-dockerd-0.3.14-3.el8.x86_64.rpm -y

[root@k8s-master ~]# vim /lib/systemd/system/cri-docker.service

编辑内容:

#指定网络插件名称及基础容器镜像
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.9

[root@k8s-master ~]# systemctl daemon-reload
[root@k8s-master ~]# systemctl start cri-docker
[root@k8s-master ~]# ll /var/run/cri-dockerd.sock

将该配置文件拷贝给其他两台主机:

[root@k8s-master ~]# scp /lib/systemd/system/cri-docker.service root:/172.25.254.10:/lib/systemd/system/cri-docker.service
[root@k8s-master ~]# scp /lib/systemd/system/cri-docker.service root:/172.25.254.20:/lib/systemd/system/cri-docker.service

1.1.3.在master节点拉取K8S所需镜像

#拉取k8s集群所需要的镜像
[root@k8s-master ~]# kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.30.0 --cri-socket=unix:///var/run/cri-dockerd.sock​

#上传镜像到harbor仓库
[root@k8s-master ~]# docker images | awk '/google/{ print $1":"$2}' \| awk -F "/" '{system("docker tag "$0" reg.gaoyingjie.org/k8s/"$3)}'​

[root@k8s-master ~]# docker images  | awk '/k8s/{system("docker push "$1":"$2)}'  

1.1.4.集群初始化

[root@k8s-master ~]# systemctl enable --now  kubelet.service
[root@k8s-master ~]# systemctl status kubelet.service

#执行初始化命令
[root@k8s-master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.gaoyingjie.org/k8s \
--kubernetes-version v1.30.0 \
--cri-socket=unix:///var/run/cri-dockerd.sock

#指定集群配置文件变量[root@k8s-master ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile​

#当前节点没有就绪,因为还没有安装网络插件,容器没有运行
[root@k8s-master ~]# kubectl get node

[root@k8s-master ~]# kubectl get pod -A

1.1.5.其他两台主机加入集群

在此阶段如果生成的集群token找不到了可以重新生成

[root@k8s-master ~]#   kubeadm token create --print-join-command kubeadm join 172.25.254.100:6443 --token 5hwptm.zwn7epa6pvatbpwf --discovery-token-ca-cert-hash 
[root@k8s-node1 ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
[root@k8s-node1 ~]# kubeadm join 172.25.254.100:6443 --token baujlw.w4xhwevafprh8uk9 --discovery-token-ca-cert-hash sha256:f05eb014ffdee15265806a1bc7a54270d8b28cccf90b88cb2b2910fe3aaab05f --cri-socket=unix:///var/run/cri-dockerd.sock


[root@k8s-node2 ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
[root@k8s-node2 ~]# kubeadm join 172.25.254.100:6443 --token baujlw.w4xhwevafprh8uk9 --discovery-token-ca-cert-hash sha256:f05eb014ffdee15265806a1bc7a54270d8b28cccf90b88cb2b2910fe3aaab05f --cri-socket=unix:///var/run/cri-dockerd.sock

1.1.6.安装flannel网络插件

#注意关闭防火墙,并且seinux的状态都是disabled

#现在镜像:
[root@k8s-master ~]# docker pull docker.io/flannel/flannel:v0.25.5
[root@k8s-master ~]# docker pull docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel1

​#上传镜像到仓库[root@k8s-master ~]# docker tag flannel/flannel:v0.25.5 reg.gaoyingjie.org/flannel/flannel:v0.25.5
[root@k8s-master ~]# docker push reg.gaoyingjie.org/flannel/flannel:v0.25.5

​#编辑kube-flannel.yml 修改镜像下载位置
[root@k8s-master ~]# vim kube-flannel.yml

#需要修改以下几行
[root@k8s-master ~]# grep -n image kube-flannel.yml
146:        image: reg.timinglee.org/flannel/flannel:v0.25.5
173:        image: reg.timinglee.org/flannel/flannel-cni-plugin:v1.5.1-flannel1
184:        image: reg.timinglee.org/flannel/flannel:v0.25.5

#安装flannel网络插件
[root@k8s-master ~]# kubectl apply -f kube-flannel.yml

1.1.7.查看所有node的状态

都是ready说明k8s集群已经完成。

三、pod的管理和优化

3、pod的生命周期

(1)、INIT容器

init容器可以独立于Pod应用容器运行,init容器必须在应用容器启动前完成,它可以检测某个自定义任务是否完成,若没有完成,则会一直检测直到完成为止,若该任务完成后,init容器则会启动,当init容器启动后应用容器才会并行启动。也就是说,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。

[root@k8s-master ~]# vim pod.yml
[root@k8s-master ~]# kubectl apply -f pod.yml
pod/initpod created
[root@k8s-master ~]# kubectl get pods
NAME      READY   STATUS     RESTARTS      AGE
initpod   0/1     Init:0/1   0             43s     #可以看到status没有running
nginx1    1/1     Running    1 (40h ago)   2d
[root@k8s-master ~]# kubectl logs pod/initpod init-myservice 
wating for myservice
wating for myservice
wating for myservice
wating for myservice
wating for myservice
wating for myservice
wating for myservice
wating for myservice
[root@k8s-master ~]# kubectl exec -it pods/initpod -c init-myservice -- /bin/sh
/ # 
/ # touch testdfile
/ # ls
bin        etc        lib        proc       sys        tmp        var
dev        home       lib64      root       testdfile  usr
/ # exit
[root@k8s-master ~]# kubectl get pods
NAME      READY   STATUS     RESTARTS      AGE
initpod   0/1     Init:0/1   0             2m47s     #建立文件后init容器已经running
nginx1    1/1     Running    1 (40h ago)   2d

2、探针

(1)、存活探针

配置文件内容:

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: initpod
  name: initpod
spec:
  containers:
    - image: myapp:v1
      name: myapp
      livenessProbe:
        tcpSocket:                ##检测端口存在性
          port: 8080
        initalDelaySeconds: 3        #容器启动后要等待多少秒后就探针开始工作,默认是 0
        periodSeconds: 1             #执行探测的时间间隔,默认为 10s 如果监测成功,每1s检测一次
        timeoutSeconds: 1            #探针执行检测请求后,如果检测失败,等待响应的超时时间,默认为1s

(2)、就绪探针

四、控制器

1、replicaset

  • ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行

  • 虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制

#生成yml文件
[root@k8s-master ~]# kubectl create deployment replicaset --image myapp:v1 --dry-run=client -o yaml > replicaset.yml​

配置文件内容:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset		#指定pod名称,一定小写,如果出现大写报错
spec:
  replicas: 2			#指定维护pod数量为2
  selector:				#指定检测匹配方式
    matchLabels:		#指定匹配方式为匹配标签
      app: myapp		#指定匹配的标签为app=myapp

  template:				#模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp

2、deployment控制器

  • Deployment控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod

  • Deployment管理ReplicaSet,ReplicaSet管理Pod

  • 主要用来:创建Pod和ReplicaSet、滚动更新和回滚、扩容和缩容、暂停与恢复

#生成yaml文件
[root@k8s-master ~]# kubectl create deployment deployment --image myapp:v1  --dry-run=client -o yaml > deployment.yml

配置文件内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  replicas: 4
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp

 查看:

版本升级:

  

版本回滚:

版本滚动更新策略:

 

版本更新暂停:

[root@k8s2 pod]# kubectl rollout pause deployment deployment-example

查看:还是原来的版本

 版本更新恢复:

[root@k8s2 pod]# kubectl rollout resume deployment deployment-example

3、daemonset控制器

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod ,当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod

master有污点:

设置对污点容忍后:master被控制器分配pod

4、job控制器

Job,主要用于负责批量处理(一次要处理指定数量任务)短暂的一次性(每个任务仅运行一次就结束)任务。

Job特点如下:

  • 当Job创建的pod执行成功结束时,Job将记录成功结束的pod数量

  • 当成功结束的pod达到指定的数量时,Job将完成执行

前提:上传perl镜像到harbor:用来计算。

[root@k8s-master ~]# kubectl create job testjob --image perl:5.34.0 --dry-run=client -o yaml > job.yml

配置文件内容: 

apiVersion: batch/v1
kind: Job
metadata:
  creationTimestamp: null
  name: testjob
spec:
  completions: 6        #一共完成任务数为6
  parallelism: 2        #每次并行完成2个
  backoffLimit: 4        #运行失败后尝试4重新运行
  template:
    spec:
      containers:
      - image: perl:5.34.0
        name: testjob
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never        #关闭后不自动重启

 可以看到并行任务数两个,一共开启6个pod进行运算:

查看任务完成后的日志结果:

5、cronjob控制器

  • Cron Job 创建基于时间调度的 Jobs。

  • CronJob控制器以Job控制器资源为其管控对象,并借助它管理pod资源对象。

  • CronJob可以以类似于Linux操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。

  • CronJob可以在特定的时间点(反复的)去运行job任务。

生成cronjob的yml文件
[root@k8s-master ~]# kubectl create cronjob testcronjob --image busyboxplus:latest --schedule="* * * * *" --restart Never --dry-run=client -o yaml > cronjob.yml

配置文件内容:

apiVersion: batch/v1
kind: CronJob
metadata:
  creationTimestamp: null
  name: testcronjob
spec:
  schedule: '* * * * *'
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - image: busyboxplus:latest
            name: testcronjob
            command: ["/bin/sh","-c","date;echo Hello from the Kubernetes cluster"]
          restartPolicy: Never

查看:是否每分钟建立一个pod并且输出一句话

[root@k8s-master ~]# watch -n 1 kubectl get pods

ClusterIP

直接解析到service的虚拟ip上

无头模式:

 

nodeport

ingress1

基于域名

https加密

用户加密

重定向

金丝雀

基于header

基于权重

k8s的存储

1、Configmap

(1)、congifmap的创建方式

通过字面值创建

[root@k8s-master storage]# kubectl create  configmap userlist  --from-literal name=gyj --from-literal age=23
configmap/userlist created
[root@k8s-master storage]# kubectl describe cm userlist 
Name:         userlist
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
age:
----
23
name:
----
gyj

BinaryData
====

Events:  <none>
[root@k8s-master storage]# 

通过文件创建

[root@k8s-master storage]# kubectl create cm configmap2 --from-file /etc/resolv.conf 
configmap/configmap2 created
[root@k8s-master storage]# kubectl describe cm configmap2 
Name:         configmap2
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
resolv.conf:
----
# Generated by NetworkManager
nameserver 114.114.114.114


BinaryData
====

Events:  <none>

通过目录创建

[root@k8s-master storage]# mkdir test
[root@k8s-master storage]# cp /etc/hosts /etc/rc.d/rc.local /root/storage/test/
[root@k8s-master storage]# kubectl create cm configmap2 --from-file test/
configmap/configmap2 created
[root@k8s-master storage]# kubectl describe cm configmap2 
Name:         configmap2
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
hosts:
----
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.100  k8s-master
172.25.254.10   k8s-node1
172.25.254.20   k8s-node2
172.25.254.250  reg.gaoyingjie.org

rc.local:
----
#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.

touch /var/lock/subsys/local
mount /dev/cdrom /rhel9/


BinaryData
====

Events:  <none>

通过yaml文件创建

[root@k8s-master storage]# kubectl create cm configmap3 --from-literal db_host=172.25.254.100 --from-literal db_port=3306 --dry-run=client -o yaml > configmap3.yaml
[root@k8s-master storage]# vim configmap3.yaml 
[root@k8s-master storage]# kubectl apply -f configmap3.yaml 
configmap/configmap3 created
[root@k8s-master storage]# kubectl describe configmaps configmap3 
Name:         configmap3
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db_port:
----
3306
db_host:
----
172.25.254.100

BinaryData
====

Events:  <none>

(2)、configmap的使用方式

  • 使用configmap 填充环境变量
[root@k8s-master storage]# vim testpod1.yml 
[root@k8s-master storage]# kubectl apply -f testpod1.yml 
pod/configmap-pod created
[root@k8s-master storage]# kubectl get pods
NAME            READY   STATUS      RESTARTS   AGE
configmap-pod   0/1     Completed   0          7s
test            1/1     Running     0          5m51s
[root@k8s-master storage]# kubectl logs pods/configmap-pod 
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=configmap-pod
SHLVL=1
HOME=/
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
key1=172.25.254.100
key2=3306
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1
[root@k8s-master storage]# 
[root@k8s-master storage]# vim testpod1.yml 

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: configmap-pod
  name: configmap-pod
spec:
  containers:
  - image: busyboxplus:latest
    name: configmap-pod
    command:
    - /bin/sh
    - -c
    - env
    envFrom:
    - configMapRef:
        name: configmap3
  restartPolicy: Never

[root@k8s-master storage]# kubectl apply -f testpod1.yml 
pod/configmap-pod created
[root@k8s-master storage]# kubectl logs pods/configmap-pod 
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=configmap-pod
SHLVL=1
HOME=/
db_port=3306
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1
db_host=172.25.254.100
#在pod命令行中使用变量
[root@k8s-master ~]# vim testpod3.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: busyboxplus:latest
    name: testpod
    command:
    - /bin/sh
    - -c
    - echo ${db_host} ${db_port}		#变量调用需
    envFrom:
    - configMapRef:
        name: lee4-config
  restartPolicy: Never

#查看日志
[root@k8s-master ~]# kubectl logs pods/testpod
172.25.254.100 3306
  • 通过数据卷使用configmap

声明一个卷并挂载,把configmap里的键变为挂载目录下的文件名字、把值变为文件内容。

[root@k8s-master storage]# vim testpod2.yml 

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: busyboxplus:latest
    name: testpod
    command:
    - /bin/sh
    - -c
    - sleep 1000000
    volumeMounts:
    - name: config-volume
      mountPath: /config
  volumes:
  - name: config-volume
    configMap:
      name: configmap3       #配置文件
  restartPolicy: Never

  • 利用configmap填充pod的配置文件

举例:当容器运行nginx时,nginx的配置文件可以放在configmap(通过文件创建configmap),修改配置时可以直接修改configmap文件内容,就不用修改每个pod的nginx配置文件

#建立配置文件模板
[root@k8s-master ~]# vim nginx.conf
server {
  listen 8000;
  server_name _;
  root /usr/share/nginx/html;
  index index.html;
}
#利用nging模板文件生成cm(通过文件创立cm)
root@k8s-master ~]# kubectl create cm nginx-conf --from-file nginx.conf     #通过nginx.conf 这个文件创建名为nginx-conf的cm
configmap/nginx-conf created
[root@k8s-master ~]# kubectl describe cm nginx-conf
Name:         nginx-conf
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx.conf:                           #该cm的键
----
server {                              #该cm的值
  listen 8000;
  server_name _;
  root /usr/share/nginx/html;
  index index.html;
}


BinaryData
====

Events:  <none>
#建立nginx控制器文件
[root@k8s-master ~]# kubectl create deployment nginx --image nginx:latest --replicas 1 --dry-run=client -o yaml > nginx.yml

#设定nginx.yml中的卷
[root@k8s-master ~]# vim nginx.yml
[root@k8s-master ~]# cat nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d     #挂载目录,在该目录下cm的键成为文件名,值成为文件内容

      volumes:
        - name: config-volume
          configMap:
            name: nginx-conf               #cm名字

测试:

测试可以访问该pod;

在该pod的nginx的目录下也有挂载的配置文件:

通过cm热更新修改配置:

所以当想要修改nginx的配置时,比如修改端口,只需要修改cm的配置,不用一个一个pod去修改。

[root@k8s-master storage]# kubectl edit cm nginx-conf   #修改cm

#配置文件内容

apiVersion: v1
data:
  nginx.conf: "server{\n\tlisten 80;\n\tserver_name _;\n\troot /usr/share/nginx/html;\n\tindex
    index.html;\n}\n"
kind: ConfigMap
metadata:
  creationTimestamp: "2024-09-15T08:21:02Z"
  name: nginx-conf
  namespace: default
  resourceVersion: "188837"
  uid: 15396d74-0151-4d02-8509-3f3234fb8a9e

#修改配置后,原有的pod的配置并不会修改,所以删除pod,pod会重启,重启后的pod遵循修改后的配置

[root@k8s-master storage]# kubectl delete pods nginx-8487c65cfc-9st6s 
pod "nginx-8487c65cfc-9st6s" deleted
[root@k8s-master storage]# kubectl get pods 
\NAME                     READY   STATUS    RESTARTS   AGE
nginx-8487c65cfc-d8kqd   1/1     Running   0          3s

测试:端口改为80,是nginx的默认端口,所以可以直接访问

 2、secrets

  • Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。

  • 敏感信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活

  • Pod 可以用两种方式使用 secret:

    • 作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里。

    • 当 kubelet 为 pod 拉取镜像时使用。

  • Secret的类型:

    • Service Account:Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改 pod 以使用此类型的 secret。

    • Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。

    • kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息

(1)、secrets的创建

从文件创建

[root@k8s-master secrets]# echo -n gaoyingjie > username.txt
[root@k8s-master secrets]# echo -n gyj > username.txt
[root@k8s-master secrets]# kubectl create secret generic userlist --from-file username.txt --from-file ^C
[root@k8s-master secrets]# echo -n gaoyingjie > username.txt
[root@k8s-master secrets]# echo -n gaoyingjie > password.txt
[root@k8s-master secrets]# kubectl create secret generic userlist --from-file username.txt --from-file password.txt 
secret/userlist created
[root@k8s-master secrets]# kubectl get secrets userlist -o yaml
apiVersion: v1
data:
  password.txt: Z2FveWluZ2ppZQ==           #username已加密
  username.txt: Z2FveWluZ2ppZQ==           #password已加密
kind: Secret
metadata:
  creationTimestamp: "2024-09-15T11:54:24Z"
  name: userlist
  namespace: default
  resourceVersion: "200519"
  uid: 4a144911-0b46-4e1e-95b1-13b403cac262
type: Opaque

编写yml文件建立

#将要存储的username和password用base64加密
[root@k8s-master secrets]# echo -n gaoyingjie | base64
Z2FveWluZ2ppZQ==
[root@k8s-master secrets]# echo -n gyj | base64
Z3lq

#生成secrets配置文件
[root@k8s-master secrets]# kubectl create secret generic userlist --dry-run=client -o yaml > userlist.yml
[root@k8s-master secrets]# vim userlist.yml 

#配置文件内容
apiVersion: v1
kind: Secret
metadata:
  creationTimestamp: null
  name: userlist
type: Opaque
data:
  username: Z2FveWluZ2ppZQ==
  password: Z3lq


[root@k8s-master secrets]# kubectl apply -f userlist.yml 
secret/userlist created
[root@k8s-master secrets]# kubectl get secrets 
NAME           TYPE                             DATA   AGE
docker-login   kubernetes.io/dockerconfigjson   1      4d9h
userlist       Opaque                           2      10s
#查看
[root@k8s-master secrets]# kubectl describe secrets userlist 
Name:         userlist
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
username:  10 bytes
password:  3 bytes

[root@k8s-master secrets]# kubectl get secrets userlist -o yaml
apiVersion: v1
data:
  password: Z3lq
  username: Z2FveWluZ2ppZQ==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"Z3lq","username":"Z2FveWluZ2ppZQ=="},"kind":"Secret","metadata":{"annotations":{},"creationTimestamp":null,"name":"userlist","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2024-09-15T12:02:45Z"
  name: userlist
  namespace: default
  resourceVersion: "201277"
  uid: 3ef997b4-aed7-4b2a-b05d-15064df95bae
type: Opaque

(2)、secrets的应用

  • 挂载卷
[root@k8s-master secrets]# vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - name: secrets                 #卷的名字
      mountPath: /secret            #挂载路径
      readOnly: true                #卷为只读类型
#声明卷
  volumes:
  - name: secrets                    #声明卷的名字为secrets
    secret:
      secretName: userlist           #卷内的数据是secrets,名为userlist的sercrets也是以键值对的形式存储,
                                     #userlist里有两个键,那么挂载目录secret下就有两个文件名,userlist内键值对的两个值就是这两个文件的内容

[root@k8s-master secrets]# kubectl apply -f userlist.yml 
secret/userlist created
[root@k8s-master secrets]# kubectl apply -f pod1.yml
pod/nginx created
[root@k8s-master secrets]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          4s
[root@k8s-master secrets]# kubectl describe pod nginx
[root@k8s-master secrets]# kubectl exec pods/nginx -it -- /bin/bash      #进入容器查看

可以看到secret挂载点下有userlist的两个键,分别是两个文件username和password: 

集群资源的唯一凭证是建立k8s的时候自动建立的,删除后pod就不能使用集群资源了。

  • 向指定路径映射 secret 密钥
[root@k8s-master secrets]# vim pod2.yml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx1
  name: nginx1
spec:
  containers:
  - image: nginx
    name: nginx1
    volumeMounts:
    - name: secrets
      mountPath: /secret
      readOnly: true

  volumes:
  - name: secrets
    secret:
      secretName: userlist
      items:                       #指定userlist的个别键放在指定路径下
      - key: username              #将userlist的键username放在my-users/username目录下
        path: my-users/username    #也可以指定别的键或者指定别的路径,比如 -key: password path: auth/password


[root@k8s-master secrets]# kubectl apply -f pod2.yml 
pod/nginx1 created
[root@k8s-master secrets]# kubectl get pods 
NAME     READY   STATUS    RESTARTS   AGE
nginx1   1/1     Running   0          6s
[root@k8s-master secrets]# kubectl exec -it pods/nginx1 -- /bin/bash

可以看到只有username:

  • 将secrets设置为环境变量
[root@k8s-master secrets]# vim pod3.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: busybox
  name: busybox
spec:
  containers:
  - image: busybox
    name: busybox
    command:
    - /bin/sh
    - -c
    - env
    env:
    - name: USERNAME            #将userlist的键username赋给USERNAME
      valueFrom:
        secretKeyRef:
          name: userlist
          key: username
    - name: PASS                #将userlist的键password赋给PASS    
      valueFrom:
        secretKeyRef:
          name: userlist
          key: password
  restartPolicy: Never

[root@k8s-master secrets]# kubectl apply -f pod3.yml 
pod/busybox created

  •  存储docker registry的认证信息

docker registry的私有仓库上传和下载都需要验证,而共有仓库上传需要验证,下载不需要验证。

当k8s集群的某个节点想要下载私有仓库的镜像时,必须要登录认证,所以要进行集群化认证。

登录172.25.254.250(reg.gaoyingjie.org)创建名gyj的私有仓库
#登陆仓库
[root@k8s-master secrets]# docker login  reg.gaoyingjie.org
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores

Login Succeeded

#上传镜像
[root@k8s-master secrets]# docker tag nginx:latest reg.gaoyingjie.org/gyj/nginx:latest
[root@k8s-master secrets]# docker push reg.gaoyingjie.org/gyj/nginx:latest
latest: digest: sha256:8a34fb9cb168c420604b6e5d32ca6d412cb0d533a826b313b190535c03fe9390 size: 1364
#建立用于docker认证的secret
[root@k8s-master secrets]# kubectl create secret docker-registry docker-auth --docker-server reg.gaoyingjie.org --docker-username admin --docker-password gyj --docker-email gaoyingjie@gaoyingjie.org 
secret/docker-auth created

#查看secrets
[root@k8s-master secrets]# kubectl get secrets 
NAME           TYPE                             DATA   AGE
docker-auth    kubernetes.io/dockerconfigjson   1      4m53s        #集群拉取镜像需要认证的secrets
docker-login   kubernetes.io/dockerconfigjson   1      4d11h
userlist       Opaque                           2      102m


[root@k8s-master secrets]# vim pod4.yml

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
    - image: reg.gaoyingjie.org/gyj/nginx:latest      #从私有仓库下载时要使用绝对路径
    name: nginx
  imagePullSecrets:                #添加创建的集群认证secrets,不设定docker认证时无法下载
  - name: docker-auth

#若没有 imagePullSecrets:- name: docker-auth(不添加集群认证secrtes),那么拉取镜像时会报错
[root@k8s-master secrets]# kubectl get pod
NAME    READY   STATUS         RESTARTS   AGE
nginx   0/1     ErrImagePull   0          35s        #拉取镜像报错errimagepull


#添加secrets后
[root@k8s-master secrets]# kubectl apply -f pod4.yml 
pod/nginx created
[root@k8s-master secrets]# kubectl get pods 
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          7s

3、volumes

  • 容器中文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题

  • 当容器崩溃时,kubelet将重新启动容器,容器中的文件将会丢失,因为容器会以干净的状态重建。

  • 当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。

  • Kubernetes 卷具有明确的生命周期与使用它的 Pod 相同

  • 卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留

  • 当一个 Pod 不再存在时,卷也将不再存在。

  • Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。

  • 卷不能挂载到其他卷,也不能与其他卷有硬链接。 Pod 中的每个容器必须独立地指定每个卷的挂载位置。

静态卷:emptyDir卷、hostpath卷、nfs卷。都是需要管理员手动指定,不能自动调用

(1)、emptyDir卷

当Pod指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要 Pod 在该节点上运行,卷就一直存在。卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会永久删除,也就是说,emptyDir的生命周期和pod一样。

emptyDir 的使用场景:

  • 主要作用就是共享,对于所有pod之间的共享资源。
  • 缓存空间,例如基于磁盘的归并排序。

  • 耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。

  • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

[root@k8s-master ~]# mkdir volumes
[root@k8s-master volumes]# vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: vol1    #pod的名字
spec:
  containers:
  - image: busyboxplus:latest        #开启的镜像
    name: vm1                        #名字
    command:                    
    - /bin/sh
    - -c
    - sleep 30000000
    volumeMounts:
    - mountPath: /cache            #挂载目录
      name: cache-vol            #指定的卷的名字
  - image: nginx:latest
    name: vm2
    volumeMounts:
    - mountPath: /usr/share/nginx/html        
#挂载目录,在该目录下存储的内容就是存储到cache-vol卷中,同样,在该目录下存储的内容,可以在busyboxplus的挂载目录/cache下可以看到。
      name: cache-vol
  volumes:                          #声明卷
  - name: cache-vol                 #卷的名字
    emptyDir:                       #卷的类型
      medium: Memory                #卷的设备:内存    
      sizeLimit: 100Mi              #大小


[root@k8s-master volumes]# kubectl describe pod vol1
#进入容器查看
[root@k8s-master volumes]# kubectl exec -it pods/vol1 -c vm1 -- /bin/sh
/ # ls
bin      dev      home     lib64    media    opt      root     sbin     tmp      var
cache    etc      lib      linuxrc  mnt      proc     run      sys      usr
/ # cd cache/
/cache # echo gaoyingjie > index.html
/cache # ls
index.html
/cache # curl localhost        #basybox和nginx在一个pod内,共享网络栈,所以可以curl localhost
gaoyingjie
/cache # 

/cache # dd if=/dev/zero of=bigfile bs=1M count=99        #卷设置了100M 测试
99+0 records in
99+0 records out
/cache # dd if=/dev/zero of=bigfile bs=1M count=100
100+0 records in
99+1 records out
/cache # dd if=/dev/zero of=bigfile bs=1M count=101        #超过100则没有空间
dd: writing 'bigfile': No space left on device
101+0 records in
99+1 records out
/cache # 

(2)、hostpath卷

功能:

hostPath 卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中,不会因为pod关闭而被删除。也就是将该pod的一些资源存在本机上。

hostPath 的一些用法

  • 运行一个需要访问 Docker 引擎内部机制的容器,挂载 /var/lib/docker 路径。

  • 在容器中运行 cAdvisor(监控) 时,以 hostPath 方式挂载 /sys。

  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在

hostPath的安全隐患

  • 具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。

  • 当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由 hostPath 使用的资源。

  • 基础主机上创建的文件或目录只能由 root 用户写入。您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

[root@k8s-master volumes]# vim pod2.yml
apiVersion: v1
kind: Pod
metadata:
  name: vol1
spec:
  containers:
  - image: nginx:latest
    name: vm1                                
    volumeMounts:
    - mountPath: /usr/share/nginx/html         #挂载目录,将主机/data的内容挂载到当前目录
      name: cache-vol
  volumes:
  - name: cache-vol                    #声明卷
    hostPath:                          #卷的类型
      path: /data                      #卷的路径(主机上的路径)
      type: DirectoryOrCreate		   #当/data目录不存在时自动建立


[root@k8s-master volumes]# kubectl apply -f pod2.yml 
pod/vol1 created
[root@k8s-master volumes]# kubectl get -o wide pods 
NAME   READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
vol1   1/1     Running   0          21s   10.244.36.85   k8s-node1   <none>           <none>

#pod在node1上
#node1是pod的主机,node1上有data目录
[root@k8s-node1 ~]# ll /data
总用量 0
[root@k8s-node1 ~]# cd /data
[root@k8s-node1 data]# echo gaoyingjie > index.html    #写入内容
[root@k8s-node1 data]# ls
index.html

[root@k8s-master volumes]# curl 10.244.36.85    #可以看到pod下/usr/share/nginx/html内容
gaoyingjie
#当pod被删除后
[root@k8s-master volumes]# kubectl delete -f pod2.yml --force

#主机hostpath卷不会删除
[root@k8s-node1 data]# ls
index.html
[root@k8s-node1 data]# cat index.html 
gaoyingjie
[root@k8s-node1 data]# 

(3)、nfs卷

NFS 卷允许将一个现有的 NFS 服务器上的目录挂载到 Kubernetes 中的 Pod 中。这对于在多个 Pod 之间共享数据或持久化存储数据非常有用

例如,如果有多个容器需要访问相同的数据集,或者需要将容器中的数据持久保存到外部存储,NFS 卷可以提供一种方便的解决方案。

意义:用另外一台主机做存储,k8s集群和集群数据资源不在同一台主机上,实现了存储分离。

准备工作:

4台主机都要安装nfs,175.25.254.250是nfs服务器,其他主机是为了访问nfs服务器。

[root@docker-harbor ~]# dnf install nfs-utils -y
[root@docker-harbor rhel9]# systemctl enable --now nfs-server.service
[root@docker-harbor rhel9]# systemctl status nfs-server.service 
#编辑策略文件
[root@docker-harbor ~]# vim /etc/exports
/nfsdata   *(rw,sync,no_root_squash)
#rw:读写,sync:数据完完整性同步,async:实时性同步,no_root_squash:设置权限,欣慰nfsdata是需要root权限

[root@docker-harbor ~]# exportfs -rv
exporting *:/nfsdata
#关闭火墙后查看,每台主机都能看到
[root@docker-harbor ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *
[root@k8s-master ~]# showmount -e 172.25.254.250
Export list for 172.25.254.250:
/nfsdata *

部署nfs卷:

[root@k8s-master volumes]# vim pod3.yml
apiVersion: v1
kind: Pod
metadata:
  name: vol1
spec:
  containers:
  - image: nginx:latest
    name: vm1
    volumeMounts:
    - mountPath: /usr/share/nginx/html        #卷挂载目录
      name: cache-vol
  volumes:                                    #声明卷
  - name: cache-vol                           #卷的名称
    nfs:                                      #使用的是nfs卷
      server: 172.25.254.250                  #nfs服务器的ip,就是挂载点ip
      path: /nfsdata                          #nfs共享出来的目录

#pod开启后会将/usr/share/nginx/html下的内容挂载到nfs服务器的/nfsdata目录下

[root@k8s-master volumes]# kubectl apply -f pod3.yml 
pod/vol1 created
[root@k8s-master volumes]# kubectl describe pod vol1 

#nfsdata目录下还没有内容,所以访问nginx的首发目录是403
[root@k8s-master volumes]# curl 10.244.36.87
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
#进入nfsdata的目录下写入内容
[root@docker-harbor ~]# cd  /nfsdata/
[root@docker-harbor nfsdata]# echo gaoyingjie > index.html
[root@docker-harbor nfsdata]# ls
index.html

#再次查看,可以看到网页内容了
[root@k8s-master volumes]# curl 10.244.36.87
gaoyingjie

动态卷:持久卷。就是在使用资源时卷会自动建立。

(4)、持久卷

静态pv卷:

管理员手动建立pv,然后才能建立pvc,pod才能使用pvc申请pv。

[root@k8s-master pvc]# vim pv.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1        #pv的名字
spec:                
  capacity:
    storage: 5Gi        #pv的大小
  volumeMode: Filesystem        #文件系统
  accessModes:
    - ReadWriteOnce        #访问模式:单点读写
  persistentVolumeReclaimPolicy: Retain      #回收模式:保留
  storageClassName: nfs        #存储类为nfs
  nfs:
    path: /nfsdata/pv1           #访问路径,将pv1的存储数据挂载到该目录下
    server: 172.25.254.250

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 15Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany            #多点读写
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv2
    server: 172.25.254.250
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  capacity:
    storage: 25Gi
  volumeMode: Filesystem
  accessModes:
    - ReadOnlyMangy            #多点只读
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv3
    server: 172.25.254.250

[root@k8s-master pvc]# kubectl apply -f pv.yml 
persistentvolume/pv1 unchanged
persistentvolume/pv2 unchanged
persistentvolume/pv3 created
[root@k8s-master pvc]# kubectl get pv
\NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pv1    5Gi        RWO            Retain           Available           nfs            <unset>                          37s
pv2    15Gi       RWX            Retain           Available           nfs            <unset>                          37s
pv3    25Gi       ROX            Retain           Available           nfs            <unset>  
[root@k8s-master pvc]# vim pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1               #名字可以随机,只看pvc的访问模式和请求大小这两个是否有匹配的pv
spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteOnce            #pv和pvc的方式必须一致
  resources:
    requests:
      storage: 1Gi             #pvc1的请求大小比pv小,不能超过pv的大小

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
spec:
  storageClassName: nfs
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 15Gi

[root@k8s-master pvc]# kubectl apply -f pvc.yml 
persistentvolumeclaim/pvc1 created
persistentvolumeclaim/pvc2 created
persistentvolumeclaim/pvc3 created
[root@k8s-master pvc]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc1   Bound    pv1      5Gi        RWO            nfs            <unset>                 10s
pvc2   Bound    pv2      15Gi       RWX            nfs            <unset>                 10s
pvc3   Bound    pv3      25Gi       ROX            nfs            <unset>                 10s
[root@k8s-master pvc]# vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: gaoyingjie
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html      #pv1挂载到该目录下,该目录最终访问的就是pv1的内容
      name: vol1
  volumes:                #声明卷
  - name: vol1
    persistentVolumeClaim:       #持久卷请求,用请求使用卷pv1
      claimName: pvc1


[root@k8s-master pvc]# kubectl apply -f pod1.yml 
pod/gaoyingjie created
[root@k8s-master pvc]# kubectl get pods 
NAME         READY   STATUS    RESTARTS   AGE
gaoyingjie   1/1     Running   0          10s
[root@k8s-master pvc]# kubectl describe pods gaoyingjie 
#pv1中没有内容时,访问不到
[root@k8s-master pvc]# kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE    IP             NODE        NOMINATED NODE   READINESS GATES
gaoyingjie   1/1     Running   0          6m8s   10.244.36.88   k8s-node1   <none>           <none>
[root@k8s-master pvc]# curl 10.244.36.88 
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>

#在pv1中写入内容
[root@docker-harbor nfsdata]# echo gaoyingjie > pv1/index.html
#可以看到写入的内容
[root@k8s-master pvc]# curl 10.244.36.88 
gaoyingjie
#也可以进入容器中,看到pv1的内容已挂载到/usr/share/nginx/html/目录下
[root@k8s-master pvc]# kubectl exec -it pods/gaoyingjie -- /bin/bash
root@gaoyingjie:/# cd /usr/share/nginx/html/
root@gaoyingjie:/usr/share/nginx/html# ls
index.html
root@gaoyingjie:/usr/share/nginx/html# cat index.html 
gaoyingjie

4、存储类

动态pv

创建pvc的时候会调用存储类去自动创建目录,如果没有指定存储类则调用默认存储类(前提是有默认存储类,没有则pvc状态显示pending)

1、集群授权

[root@k8s-master storageclass]# vim rbac.yml
apiVersion: v1
kind: Namespace
metadata:
  name: nfs-client-provisioner        #名命空间
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["stora