Linux云计算 |【第五阶段】CLOUD-DAY9

主要内容:

Metrics资源利用率监控、存储卷管理(临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC))

一、Metrics介绍

metrics是一个监控系统资源使用的插件,可以监控Node节点上的CPU、内存的使用率,或Pod对资源的占用率,通过对资源占用的了解,可以更加合理的部署容器应用;

补充:metrics从Kubernetes 1.8开始,资源使用情况的监控可以通过Metrics API的形式获取,具体的组件为Metrics Server,用来替换之前的heapster插件,所以heapster从1.11开始逐渐被放弃;

报错说明:没有http:heapster插件,该插件已被Metrics Server替换,需安装Metrics插件;

[root@master ~]# kubectl top node    //查看资源占用情况
Error from server (NotFound): the server could not find the requested resource (get services http:heapster:)

部署metrics-server服务示例:

① 开启聚合服务参数

② 签发Kubelet证书

③ 安装metrics-server插件

④ 执行所有资源文件

- apiservice.yaml    //注册集群API的资源文件

- deployment.yaml   //主进程metrics的资源文件

- metrisc-server.tar.gz   //metrisc-server插件镜像压缩包

- pdb.yaml     //中断控制器

- rbac.yaml      //授权控制器

- service.yaml   //后端是metrics主进程的服务

1)开启聚合服务

Metrics-server是扩展的Apiserver,依赖于kube-aggregator,因此需要在Apiserver中开启聚合API相关参数(-- enable-aggregator-routing=true)

修改Api-server启动参数流程:

① 配置文件:/etc/kubernetes/manifests/kube-apiserver.yaml

  • - 配置spec.containers.command添加:- -- enable-aggregator-routing=true

② 重启服务:systemctl restart kubelet

③ 验证配置:kubectl -n kube-system get pod 容器名 -o yaml | grep enable-aggregator-routing

步骤1:开启apiserver聚合服务参数

① 备份配置文件(强烈建议备份)

[root@master ~]# cd /etc/kubernetes/manifests/
[root@master manifests]# cp kube-apiserver.yaml kube-apiserver.yaml.bak   //备份文件
[root@master manifests]# mv kube-apiserver.yaml.bak /root/

注意:K8S默认会载入所有配置文件,该目录下的两个文件即使修改差一个参数不同,也会一并载入可能导致覆盖,所以必须将备份文件放在其它目录,避免干扰;

② 修改配置文件,并重启验证服务

# 在spec.containers.command 最下面手动添加如下一行

[root@master manifests]# vim kube-apiserver.yaml
    - --enable-aggregator-routing=true
[root@master manifests]# systemctl restart kubelet    //重启服务
[root@master manifests]# kubectl -n kube-system get pod kube-apiserver-master -o yaml | grep enable-aggregator-routing     //验证服务
- --enable-aggregator-routing=true

常见报错:配置文件修改错误,会导致Apiserver无法使用,需备份文件还原

修改配置示例:

2)kubelet证书

metrics插件需使用kubelet证书,需手动为kubelet签发证书;

证书的申请与签发流程:

① 配置文件:/var/lib/kubelet/config.yaml

  • - 配置:serverTLSBootstrap: true    //文件的最后一行添加

② 重启服务:systemctl restart kubelet

③ 签发证书:

查看证书

  • - 格式:kubectl get certificatesigningrequests

签发证书

  • - 格式:kubectl certificate approve 证书名称

删除证书(多余证书)

  • - 格式:kubectl delete certificatesigningrequests 证书名称

步骤2:证书的申请与签发(master,node-0001,node-0002,node-0003操作)

补充:证书在签发过程中是有时效性的,当证书申请后一直未签发,kubelet会认为证书失效或丢弃,重新创建带Pending的证书,只要将该些证书签发即可,申请多余证书可删除;

① 修改配置文件,并重启服务(以master为例)

[root@master ~]# vim /var/lib/kubelet/config.yaml
serverTLSBootstrap: true     //在文件的最后一行添加(申请证书参数开启)
[root@master ~]# systemctl restart kubelet    //重启服务

② 签发证书(必须在 master 上执行)

[root@master ~]# kubectl get certificatesigningrequests    //查看证书
NAME        AGE   REQUESTOR            CONDITION
csr-5zbkt   13m     system:node:node-0001   Pending
csr-7g67s   13m     system:node:node-0002   Pending
csr-bqzjk   14m     system:node:master      Pending
csr-cw9dz   12m     system:node:node-0003   Pending

# 在Master上,为每个节点的证书进行签发

[root@master ~]# kubectl certificate approve csr-bqzjk
certificatesigningrequest.certificates.k8s.io/csr-bqzjk approved
[root@master ~]# kubectl certificate approve csr-5zbkt
certificatesigningrequest.certificates.k8s.io/csr-5zbkt approved
[root@master ~]# kubectl certificate approve csr-7g67s
certificatesigningrequest.certificates.k8s.io/csr-7g67s approved
[root@master ~]# kubectl certificate approve csr-cw9dz
certificatesigningrequest.certificates.k8s.io/csr-cw9dz approved

[root@master ~]# kubectl get certificatesigningrequests   //查看证书
NAME        AGE   REQUESTOR               CONDITION
csr-5zbkt   11m   system:node:node-0001   Approved,Issued
csr-7g67s   10m   system:node:node-0002   Approved,Issued
csr-bqzjk   11m   system:node:master      Approved,Issued
csr-cw9dz   10m   system:node:node-0003   Approved,Issued

3)安装Metrics-server插件

方法1:官网https://github.com/kubernetes-sigs/metrics-server

方法2:下载镜像和资源文件,并导入私有仓库

  • - 格式:kubectl top node   //查询节点的资源占用率(CPU、内存的占用情况)

步骤3:安装mertics插件

# 拷贝云盘的kubernetes/v1.17.6/metrics 目录到 master 上

[root@ecs-proxy v1.17.6]# rsync -av metrics/ 192.168.1.21:/root
[root@master ~]# tree metrics/
metrics/
├── apiservice.yaml         //注册集群API的资源文件
├── deployment.yaml         //主进程metrics的资源文件
├── metrisc-server.tar.gz   //metrisc-server插件镜像压缩包
├── pdb.yaml                //中断控制器
├── rbac.yaml               //授权控制器
└── service.yaml            //后端是metrics主进程的服务
0 directories, 6 files

① 导入mertics插件镜像,并上传私有镜像仓库

[root@master ~]# cd metrics/
[root@master metrics]# docker load -i metrisc-server.tar.gz
[root@master metrics]# docker tag gcr.io/k8s-staging-metrics-server/metrics-server:master 192.168.1.100:5000/metrics-server:master
[root@master metrics]# docker push 192.168.1.100:5000/metrics-server:master

② 修改deployment资源文件

[root@master metrics]# vim deployment.yaml
29: image: 192.168.1.100:5000/metrics-server:master    //修改镜像地址

③ 执行资源文件(按照顺序依次创建)

[root@master metrics]# kubectl apply -f rbac.yaml    //授权控制器
[root@master metrics]# kubectl apply -f pdb.yaml    //中断控制器
[root@master metrics]# kubectl apply -f deployment.yaml   //主进程metrics
[root@master metrics]# kubectl apply -f service.yaml   //后端是metrics主进程的服务
[root@master metrics]# kubectl apply -f apiservice.yaml   //注册集群API

④ 查询验证

# Metrics插件默认将pod、service、apiservices放在kube-system系统命名空间

[root@master metrics]# kubectl -n kube-system get pod    //查看Pod资源
metrics-server-67fbd5bb7b-qbgkx   1/1     Running   0          2m2s

[root@master metrics]# kubectl -n kube-system get service  //查看service资源
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
kube-dns         ClusterIP   10.254.0.10     <none>        53/UDP,53/TCP,9153/TCP   4d22h
metrics-server   ClusterIP   10.254.60.149   <none>        443/TCP                  2m28s

[root@master metrics]# kubectl -n kube-system get apiservices   //查看apiservices资源

注意:当kube-system/metrics-server的状态为True,部署Metrics插件才完成;

⑤ 验证:查询节点的资源占用率(CPU、内存的占用情况)

[root@master metrics]# kubectl top node
NAME        CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
master      79m          3%     2322Mi          62%
node-0001   23m          1%     938Mi           25%
node-0002   20m          1%     943Mi           25%
node-0003   20m          1%     1150Mi          31%

扩展:CPU毫核:CPU的计量单位叫毫核。集群中的每一个节点可以通过操作系统确认本节点的CPU内核数量,将这个数量乘以1000,得到的就是节点总的CPU总数量。

⑥ 验证:监控POD容器资源利用率

[root@master ~]# kubectl apply -f myapache.yaml
deployment.apps/myapache configured
[root@master ~]# watch -n 1 'kubectl top pod'    //使用watch实时监控(每秒)

# 打开另个终端测试nodePort访问

[root@master ~]# kubectl apply -f mynodeport.yaml
service/mynodeport created
[root@master ~]# kubectl get service

[root@master ~]# curl http://192.168.1.31:30625
this is apache

# 循环访问测试

[root@master ~]# while true; do curl 192.168.1.31:30625; done

# 查看CPU监控状态

常见问题:Metrics-server服务启动后,需要等待大约 30 秒的时间用来监测资源利用率,正常现象

[root@master ~]# kubectl top pod
error: metrics not available yet

二、存储卷管理

1、ConfigMap(临时卷)

ConfigMap是在Pod中映射(文件/目录)的一种方式,允许将配置文件与镜像文件分离,以使容器化的应用程序具有可移植性;

场景:在日常工作中经常要修改各种配置文件的参数,数据库的地址、用户名密码等,这些操作在容器内非常麻烦,POD在重启或者迁移时候又会恢复到初始的状态,使用ConfigMa[就可以解决这样的问题;

常见ConfigMap案例:web集群(nginx+php),nginx需修改配置文件才能支持PHP,例如:

定义ConfigMap

ConfigMap可以映射单一文件,也可以映射一个目录

创建ConfigMap卷

  • - 格式:kubectl create configmap 名称 --from-file=文件路径

查看ConfigMap卷

  • - 格式:kubectl get configmaps

补充:创建完ConfigMap之后,要在资源文件中引用ConfigMap才能生效

资源文件引用ConfigMap模板:


示例:创建ConfigMap存储卷

步骤1:修改Nginx配置文件,并创建ConfigMap

① 清除所有POD(由于apache与nginx都使用 80 端口,需把实验容器全部删除)

[root@master ~]# kubectl delete -f myapache.yaml
[root@master ~]# kubectl delete -f mypod.yaml
[root@master ~]# kubectl get pod
No resources found in default namespace.

② 拷贝myos:nginx容器的Nginx配置文件,并完成修改

[root@master ~]# mkdir /var/webconf
[root@master ~]# docker run -itd --name mynginx 192.168.1.100:5000/myos:nginx     //启动容器
[root@master ~]# docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS               NAMES
b24b9f2e5f34        192.168.1.100:5000/myos:nginx   "/usr/local/nginx/sb…"   28 seconds ago      Up 27 seconds       80/tcp              mynginx
[root@master ~]# docker cp mynginx:/usr/local/nginx/conf/nginx.conf /var/webconf/   //拷贝容器目录
[root@master ~]# docker rm -f mynginx
mynginx
[root@master ~]# ls -l /var/webconf/nginx.conf
-rw-r--r-- 1 root root 2656 Jul 25  2020 /var/webconf/nginx.conf
[root@master ~]# vim /var/webconf/nginx.conf     //修改配置文件
...
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            include        fastcgi.conf;
        }
...

③ 创建ConfigMap卷

  • 格式:kubectl create configmap 名称 --from-file=文件路径
[root@master ~]# kubectl create configmap nginx-conf --from-file=/var/webconf/nginx.conf
configmap/nginx-conf created
[root@master ~]# kubectl get configmaps    //查看ConfigMap卷
NAME         DATA   AGE
nginx-conf   1      6s

步骤2:在webnginx.yaml资源文件中,引用Configmap存储卷定义

[root@master ~]# vim webnginx.yaml
---
kind: Deployment       //定义资源的类型
apiVersion: apps/v1
metadata:
  name: webnginx       //资源类型的名称
spec:
  selector:            //标签选择器
    matchLabels:
      myapp: nginx
  replicas: 1         //副本数为1
  template:           //POD资源模板
    metadata:
      labels:
        myapp: nginx
    spec:             //POD资源的详细定义
      volumes:                //卷的定义,映射存储卷
      - name: nginx-php       //卷的名称(标记1)
        configMap:            //定义ConfigMap卷(加载的卷可以写多个)
          name: nginx-conf    //加载的configmap,必须与create configmap命令创建的卷名称相同
      containers:     //容器的定义
      - name: nginx
        image: 192.168.1.100:5000/myos:nginx
        volumeMounts:           //挂载存储卷
        - name: nginx-php       //指定卷的名称,必须与(标记1)名称相同
          subPath: nginx.conf   //指定映射单一文件路径(映射哪一个存储卷)
          mountPath: /usr/local/nginx/conf/nginx.conf    //存储卷加载在容器的路径
        ports:
        - protocol: TCP
          containerPort: 80
      restartPolicy: Always

[root@master ~]# kubectl apply -f webnginx.yaml
deployment.apps/webnginx created
[root@master ~]# kubectl get pod     //查询POD资源
NAME                        READY   STATUS    RESTARTS   AGE
webnginx-6fdf585d7d-lptqb   1/1     Running   0          7s

# 验证服务,进入容器查看配置文件是否改变

[root@master ~]# kubectl exec -it webnginx-6fdf585d7d-lptqb -- /bin/bash
[root@webnginx-6fdf585d7d-lptqb html]# cat /usr/local/nginx/conf/nginx.conf

[root@webnginx-6fdf585d7d-lptqb html]# ss -ltun

[root@webnginx-6fdf585d7d-lptqb html]# exit
Exit
[root@master ~]# kubectl delete -f webnginx.yaml
deployment.apps "webnginx" deleted

补充:以上步骤只完成了ConfigMap卷的创建、存储卷的映射,但由于PHP文件需要后端PHP程序解析,还需添加PHP容器;其次两个容器通信需要共享网卡,最简单的方法即将两个容器写在同一个资源文件中;

步骤3:在webnginx.yaml资源文件的基础上,添加 php 容器

① 在资源文件template.spec.containers添加PHP容器

[root@master ~]# vim webnginx.yaml
 
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: webnginx
spec:
  selector:
    matchLabels:
      myapp: nginx
  replicas: 1
  template:
    metadata:
      labels:
        myapp: nginx
    spec:
      volumes:
      - name: nginx-php
        configMap:
          name: nginx-conf
      containers:
      - name: nginx
        image: 192.168.1.100:5000/myos:nginx
        volumeMounts:
        - name: nginx-php
          subPath: nginx.conf
          mountPath: /usr/local/nginx/conf/nginx.conf
        ports:
        - protocol: TCP
          containerPort: 80
      - name: php-backend                       //添加PHP容器
        image: 192.168.1.100:5000/myos:php-fpm  //指定私有仓库PHP的镜像
      restartPolicy: Always

② 执行资源文件,创建资源对象

[root@master ~]# kubectl apply -f webnginx.yaml
deployment.apps/webnginx created
[root@master ~]# kubectl get pod -o wide

③ 进入容器验证服务(1个POD有2个容器,需使用-c 指定容器)

[root@master ~]# kubectl exec -it webnginx-6c9f6fd675-hkqth -c nginx -- /bin/bash  
[root@webnginx-6c9f6fd675-hkqth html]# ss -ltun

[root@webnginx-6c9f6fd675-hkqth html]# exit
exit
[root@master ~]# curl http://10.244.2.22/info.php    //访问POD容器IP
<pre>
Array
(
    [REMOTE_ADDR] => 10.244.0.0
    [REQUEST_METHOD] => GET
    [HTTP_USER_AGENT] => curl/7.29.0
    [REQUEST_URI] => /info.php
)
php_host:       webnginx-6c9f6fd675-hkqth
1229

补充:在同一个POD中,两个容器共享了主机名、信号向量、网卡、进程等,但没有文件系统,需要通过持久卷的加持,才能完成nginx+php方案

2、临时卷

用途:有些应用程序需要额外的存储,但并不关心数据在重启后仍然可用,即数据是否被持久地保存;例如:缓存服务经常受限于内存大小,将不常用的数据转移到比内存慢、但对总体性能的影响很小的存储中;

常见的临时卷:emptyDir、configMap、downwardAPI、secret

2.1 emptyDir卷

emptyDir是最基础的Volume类型(存储卷),用于存储临时数据的简单空目录,当Pod设置了emptyDir类型存储卷,Pod被分配到Node上时候会创建emptyDir;只要运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod产生迁移,emptyDir也会被删除,并且永久丢失)

emptyDir可以实现同一个Pod中数据的共享;

资源文件引用emptyDir模板:


示例:创建emptydir存储卷

① 编写资源文件,引用emptydir定义

[root@master ~]# vim webcache.yaml
---
kind: Deployment           //定义资源的类型
apiVersion: apps/v1
metadata:
  name: webcache           //定义资源的名称
spec:
  selector:
    matchLabels:
      myapp: cache
  replicas: 1
  template:
    metadata:
      labels:
        myapp: cache
    spec:
      volumes:                //卷的定义,映射存储卷
      - name: empty-data      //卷的名称(标记1)
        emptyDir: {}          //定义存储临时数据空目录(卷类型)
      containers:
      - name: apache
        image: 192.168.1.100:5000/myos:httpd
        stdin: false
        tty: false
        volumeMounts:              //挂载存储卷
        - name: empty-data         //指定卷的名称,必须与(标记1)名称相同
          mountPath: /var/cache    //存储卷加载在容器的路径
        ports:
        - protocol: TCP
          containerPort: 80
      restartPolicy: Always

② 执行资源文件

[root@master ~]# kubectl apply -f webcache.yaml
deployment.apps/webcache created
[root@master ~]# kubectl get pod     //查看POD资源
NAME                        READY   STATUS    RESTARTS   AGE
webcache-6444646d9d-4nwkc   1/1     Running   0          11s

③ 进入容器,验证测试

[root@master ~]# kubectl exec -it webcache-6444646d9d-4nwkc -- /bin/bash
[root@webcache-6444646d9d-4nwkc html]# df -h

3、持久卷

用途:容器磁盘上的文件的生命周期是短暂的(容器本质是进程),这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,Kubelet会重启容器,但是容器中的文件将丢失,容器以干净的状态(镜像最初的状态)重新启动,其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件,而Kubernetes中的Volume抽象就很好的解决这些问题;

目前K8S支持的Volume存储卷类型:


3.1 HostPath卷

HostPath类型则是映射node文件系统中的文件或者目录到Pod里(类似Dokcer -v),在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、Socket、CharDevice和BlockDevice。

注意:配置相同Pod,可能在不同的Node上表现不同,因为不同节点上映射的文件内容不同;

hostPath里面的数据不会随着Pod的结束而消失;

资源文件引用hostPath模板


示例:创建hostpath存储卷

① 映射本地目录/var/weblog到容器中

[root@master ~]# vim webcache.yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: webcache
spec:
  selector:
    matchLabels:
      myapp: cache
  replicas: 1
  template:
    metadata:
      labels:
        myapp: cache
    spec:
      volumes:                       //卷的定义,映射存储卷
      - name: empty-data
        emptyDir: {}
      - name: log-data               //卷的名称(标记1)
        hostPath:                    //定义HostPath卷
          path: /var/weblog          //Node节点加载路径
          type: DirectoryOrCreate    //当目录不存在,则创建
      containers:
      - name: apache
        image: 192.168.1.100:5000/myos:httpd
        stdin: false
        tty: false
        volumeMounts:               //挂载存储卷
        - name: empty-data
          mountPath: /var/cache
        - name: log-data            //指定卷的名称,必须与(标记1)名称相同
          mountPath: /var/log/httpd   //存储卷映射在容器的路径
        ports:
        - protocol: TCP
          containerPort: 80
      restartPolicy: Always

② 执行资源文件

[root@master ~]# kubectl apply -f webcache.yaml
deployment.apps/webcache configured
[root@master ~]# kubectl get pod -o wide

[root@master ~]# curl http://10.244.1.17    //测试访问容器IP地址
this is apache

③ 登录Node节点上,查看挂载的目录是否有文件

[root@master ~]# ssh 192.168.1.31
[root@node-0001 ~]# ls -l /var/weblog/
total 8
-rw-r--r-- 1 root root  86 Jul  6 16:42 access_log
-rw-r--r-- 1 root root 489 Jul  6 16:41 error_log
[root@node-0001 ~]# cat /var/weblog/access_log
10.244.0.0 - - [06/Jul/2021:08:42:12 +0000] "GET / HTTP/1.1" 200 15 "-" "curl/7.29.0"

④ 删除POD资源,查看挂载的目录中,文件是否保留

[root@master ~]# kubectl delete -f webcache.yaml
deployment.apps "webcache" deleted
[root@master ~]# ssh 192.168.1.31
[root@node-0001 ~]# ls -l /var/weblog/
total 8
-rw-r--r-- 1 root root  86 Jul  6 16:42 access_log
-rw-r--r-- 1 root root 489 Jul  6 16:41 error_log
[root@node-0001 ~]# cat /var/weblog/access_log
10.244.0.0 - - [06/Jul/2021:08:42:12 +0000] "GET / HTTP/1.1" 200 15 "-" "curl/7.29.0"

3.2 NFS共享卷

在生产环境中经常需要多个Pod或多个APP应用中共享数据,而这些应用又在不同的机器的不同Pod里面,网络文件系统经常用来解决这一问题;Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持并发写操作,当然cephfs、glusterfs等都能很好的解决这个问题;

PV、PVC配置

① PersistentVolume(持久卷,PV)

PV是资源的提供者,根据集群的基础设施变化而变化,由K8S集群管理员配置;

  • - 格式:kubectl get pv

② Persistent VolumeClaim(持久卷声明,PVC)

PVC是资源的使用者,根据业务服务的需求变化来配置;

  • - 格式:kubectl get pvc

(PC/PVC的引入,是K8S集群具备了存储的逻辑抽象能力)

配置PV(NFS资源)模板:

配置PVC(使用PV资源)模板:

引用配置文件模板:


示例:创建NFS持久卷

步骤1:搭建NFS服务器(registry操作)

[root@registry ~]# yum install -y nfs-utils
[root@registry ~]# mkdir -m 777 /var/webroot     //创建共享目录
[root@registry ~]# ls -ld /var/webroot/
drwxrwxrwx 2 root root 4096 Jul  6 16:58 /var/webroot/
[root@registry ~]# vim /etc/exports
/var/webroot *(rw)
[root@registry ~]# systemctl enable --now nfs

# 所有节点都需要nfs软件包(master,node-0001,node-0002,node-0003)

[root@ecs-proxy node-install]# ansible nodes --list-hosts
  hosts (3):
    192.168.1.31
    192.168.1.33
    192.168.1.32
[root@ecs-proxy ~]# cd node-install/
[root@ecs-proxy node-install]# ansible nodes -m yum -a 'name="nfs-utils" state=present'

# 在任意其他节点测试NFS

[root@master ~]# yum install -y nfs-utils
[root@master ~]# showmount -e 192.168.1.100
Export list for 192.168.1.100:
/var/webroot *

步骤2:创建 PV持久卷

官网:持久卷 | Kubernetes

[root@master ~]# vim mypv.yaml
---
kind: PersistentVolume      //定义PV持久卷类型
apiVersion: v1
metadata:
  name: pv-nfs              //类型的名称
spec:                       //PV类型的详细定义
  volumeMode: Filesystem    //Volume模型(支持Filesystem文件系统、Block块设备)
  capacity:                //定义卷的容量
    storage: 30Gi         //提供卷的大小
  accessModes:            //支持的模式(RWO、ROX,RWX,查看官网查询)
  - ReadWriteOnce         //卷可以被一个节点以读写方式挂载;
  - ReadOnlyMany          //卷可以被多个节点以只读方式挂载;
  - ReadWriteMany         //卷可以被多个节点以读写方式挂载
  persistentVolumeReclaimPolicy: Retain   //卷资源回收方式Retain自动删除,Delete手动删除
  nfs:            //指定NFS共享
    server: 192.168.1.100    //指定NFS服务器地址
    path: /var/webroot       //指定共享目录

[root@master ~]# kubectl apply -f mypv.yaml
persistentvolume/pv-nfs created
[root@master ~]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs   30Gi       RWO,ROX,RWX    Retain           Available                                   8s

步骤3:创建PVC持久卷声明

[root@master ~]# vim mypvc.yaml
---
kind: PersistentVolumeClaim   //定义PVC持久卷声明类型
apiVersion: v1
metadata:
  name: pvc-nfs             //类型的名称
spec:                       //PVC类型的详细定义
  volumeMode: Filesystem    //需要Volume模型(Filesystem文件系统、Block块设备)
  accessModes:              //需要支持的模式
  - ReadWriteMany          //卷可以被多个节点以读写方式挂载
  resources:               //计算所需的资源
    requests:              //描述所需的最小计算资源量
      storage: 25Gi        //需要提供卷的空间

[root@master ~]# kubectl apply -f mypvc.yaml
persistentvolumeclaim/pvc-nfs created

# 查看PV和PVC服务的状态

[root@master ~]# kubectl get pv

[root@master ~]#  kubectl get pvc

补充:当PV持久卷被Bound绑定后,就不能同时被其它服务绑定;

步骤4:在webnginx.yaml资源文件中,引用持久卷

[root@master ~]# vim webnginx.yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: webnginx
spec:
  selector:
    matchLabels:
      myapp: nginx
  replicas: 1
  template:
    metadata:
      labels:
        myapp: nginx
    spec:
      volumes:                       //卷的定义
      - name: nginx-php
        configMap:
          name: nginx-conf
      - name: website                //卷的名称(标签1)
        persistentVolumeClaim:       //定义PVC卷类型
          claimName: pvc-nfs         //PVC的名称
      containers:          //容器的定义
      - name: nginx
        image: 192.168.1.100:5000/myos:nginx
        volumeMounts:                //挂载存储卷
        - name: nginx-php
          subPath: nginx.conf
          mountPath: /usr/local/nginx/conf/nginx.conf
        - name: website               //指定卷的名称(标签1)
          mountPath: /usr/local/nginx/html   //存储卷映射在容器的路径
        ports:
        - protocol: TCP
          containerPort: 80
      - name: php-backend   //PHP容器定义
        image: 192.168.1.100:5000/myos:php-fpm
        volumeMounts:                 //挂载存储卷
        - name: website               //指定卷的名称(标签1)
          mountPath: /usr/local/nginx/html   //存储卷映射在容器的路径
      restartPolicy: Always

[root@master ~]# kubectl delete -f webnginx.yaml
deployment.apps "webnginx" deleted
[root@master ~]# kubectl apply -f webnginx.yaml
deployment.apps/webnginx created
[root@master ~]# kubectl get pod -o wide

# 拷贝网页文件到NFS服务器上,然后在容器端访问测试

[root@ecs-proxy ~]# scp kubernetes/docker-images/info.* 192.168.1.100:/var/webroot/
[root@master ~]# kubectl exec -it webnginx-d488b9447-ddfr4 -- /bin/bash
[root@webnginx-d488b9447-ddfr4 html]# ls
info.html  info.php

[root@master ~]# curl http://10.244.2.23/info.html
<html>
  <marquee  behavior="alternate">
      <font size="12px" color=#00ff00>Hello World</font>
  </marquee>
</html>

[root@master ~]# curl http://10.244.2.23/info.php
<pre>
Array
(
    [REMOTE_ADDR] => 10.244.0.0
    [REQUEST_METHOD] => GET
    [HTTP_USER_AGENT] => curl/7.29.0
    [REQUEST_URI] => /info.php
)
php_host:       webnginx-d488b9447-ddfr4
1229

综合案例:

完整Nginx+php部署案例

  • ① 集群能够解析静态html页面和动态PHP页面(ConfigMap)
  • ② 访问日志,存放到本地Node的/var/weblog中(HostPath)
  • ③ 网页内容,存储到NFS服务器(PC、PVC)
  • ④ 集群至少三节点,发布到互联网(Service\Ingress\nodePort\ELB+VIP)

实验架构图:

[root@master ~]# cat webcluster.yaml
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv-nfs
spec:
  volumeMode: Filesystem
  capacity:
    storage: 30Gi
  accessModes:
  - ReadWriteOnce
  - ReadOnlyMany
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.1.100
    path: /var/webroot
 
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-nfs
spec:
  volumeMode: Filesystem
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 25Gi
 
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-conf
data:
  nginx.conf: |2
 
    #user  nobody;
    worker_processes  1;
 
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
 
    #pid        logs/nginx.pid;
 
 
    events {
        worker_connections  1024;
    }
 
 
    http {
        include       mime.types;
        default_type  application/octet-stream;
 
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
 
        #access_log  logs/access.log  main;
 
        sendfile        on;
        #tcp_nopush     on;
 
        #keepalive_timeout  0;
        keepalive_timeout  65;
 
        #gzip  on;
 
        server {
            listen       80;
            server_name  localhost;
 
            #charset koi8-r;
 
            #access_log  logs/host.access.log  main;
 
            location / {
                root   html;
                index  index.html index.htm;
            }
 
            #error_page  404              /404.html;
 
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
 
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
 
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            location ~ \.php$ {
                root           html;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                include        fastcgi.conf;
            }
 
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
 
 
        # another virtual host using mix of IP-, name-, and port-based configuration
        #
        #server {
        #    listen       8000;
        #    listen       somename:8080;
        #    server_name  somename  alias  another.alias;
 
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
 
 
        # HTTPS server
        #
        #server {
        #    listen       443 ssl;
        #    server_name  localhost;
 
        #    ssl_certificate      cert.pem;
        #    ssl_certificate_key  cert.key;
 
        #    ssl_session_cache    shared:SSL:1m;
        #    ssl_session_timeout  5m;
 
        #    ssl_ciphers  HIGH:!aNULL:!MD5;
        #    ssl_prefer_server_ciphers  on;
 
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
 
    }
 
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: webnginx
spec:
  selector:
    matchLabels:
      myapp: nginx
  replicas: 3
  template:
    metadata:
      labels:
        myapp: nginx
    spec:
      volumes:
      - name: nginx-php
        configMap:
          name: nginx-conf
      - name: log-data
        hostPath:
          path: /var/log/weblog
          type: DirectoryOrCreate
      - name: website
        persistentVolumeClaim:
          claimName: pvc-nfs
      containers:
      - name: nginx
        image: 192.168.1.100:5000/myos:nginx
        volumeMounts:
        - name: nginx-php
          subPath: nginx.conf
          mountPath: /usr/local/nginx/conf/nginx.conf
        - name: log-data
          mountPath: /usr/local/nginx/logs
        - name: website
          mountPath: /usr/local/nginx/html
        ports:
        - protocol: TCP
          containerPort: 80
      - name: php-backend
        image: 192.168.1.100:5000/myos:php-fpm
        volumeMounts:
        - name: website
          mountPath: /usr/local/nginx/html
      restartPolicy: Always
 
---
kind: Service
apiVersion: v1
metadata:
  name: webcluster
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    myapp: nginx
  type: ClusterIP
 
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: myweb
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  backend:
    serviceName: webcluster
    servicePort: 80
 
[root@master ~]# kubectl apply -f webcluster.yaml
persistentvolume/pv-nfs created
persistentvolumeclaim/pvc-nfs created
configmap/nginx-conf created
deployment.apps/webnginx created
service/webcluster created
ingress.extensions/myweb created
[root@master ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
webnginx-647877b59-hdb64   2/2     Running   0          11s
webnginx-647877b59-ljb6g   2/2     Running   0          11s
webnginx-647877b59-rqmdr   2/2     Running   0          11s
[root@master ~]# kubectl get ingresses
NAME    HOSTS   ADDRESS        PORTS   AGE
myweb   *       192.168.1.31   80      17s

# 给 node-0001 绑定弹性公网IP,或使用 ELB 发布到互联网即可验证

小结:

本篇章节为【第五阶段】CLOUD-DAY9 的学习笔记,这篇笔记可以初步了解到 Metrics资源利用率监控、存储卷管理(临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC))。


Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907248.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka 判断一个节点是否还活着有那两个条件?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka 判断一个节点是否还活着有那两个条件&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; Kafka 判断一个节点是否还活着有那两个条件&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Ka…

PyQt5实战——多脚本集合包,UI以及工程布局(二)

个人博客&#xff1a;苏三有春的博客 系列往期&#xff1a; PyQt5实战——多脚本集合包&#xff0c;前言与环境配置&#xff08;一&#xff09; 布局 2.1 UI页面布局 整体框架分为分为三个部分&#xff0c;垂直分布。 第一个部分为功能选择按钮&#xff08;如UTF-8转换&#…

Cpp::set map 的理解与使用(22)

文章目录 前言一、预备知识关联式容器键值对 二、set何为set?set的使用set的特点multiset 三、map何为map?map中的operator[ ]multimap 总结 前言 刚学完二叉搜索树&#xff0c;我们马上来感受一下直接与它相关的两个容器吧&#xff01; 一、预备知识 关联式容器 在以往的 S…

PostgreSQL 学习笔记:PostgreSQL 主从复制

PostgreSQL 笔记&#xff1a;PostgreSQL 主从复制 博客地址&#xff1a;TMDOG 的博客 在现代应用程序中&#xff0c;数据库的高可用性和扩展性是至关重要的。PostgreSQL 提供了主从复制功能&#xff0c;可以在多个数据库实例之间复制数据&#xff0c;以实现冗余和负载均衡。本…

SQL,力扣题目1225,报告系统状态的连续日期【窗口函数】

一、力扣链接 LeetCode_1225 二、题目描述 表&#xff1a;Failed ----------------------- | Column Name | Type | ----------------------- | fail_date | date | ----------------------- 该表主键为 fail_date (具有唯一值的列)。 该表包含失败任务的天数.表…

晶台施密特触发器光耦KLH11LX,1MHz高传输速率

晶台推出KLH11LX系列由一个砷化镓红外发光二极管和一个高速集成电路检测器组成&#xff0c;该输出检测器包含了一个施密特触发器&#xff0c;利用其回滞特性&#xff0c;便于脉冲整形&#xff0c;提高抗噪性能。 功能图Functional Diagram 产品特点Product Features •高传输…

Mac在Typora配置PicGo图床,以github为例

Mac配置PicGo图床 0.准备阶段&#xff1a;下载PicGo https://picgo.github.io/PicGo-Doc/zh/guide/ 根据这个链接选择自己的安装方式 1.PicGo已损坏&#xff0c;无法打开 解决方法 打开iTerm,把sudo xattr -d com.apple.quarantine 输入命令行 然后把软件拖入命令行 sudo xa…

「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用

自定义组件可以帮助开发者实现复用性强、逻辑清晰的界面模块。通过自定义组件,鸿蒙应用能够提高代码的可维护性,并简化复杂布局的构建。本篇将介绍如何创建自定义组件,如何向组件传递数据,以及如何在不同页面间复用这些组件。 关键词 自定义组件复用组件属性传递组件通信组…

redis模板的应用:自定义redisTemplate序列化规则 (RedisTemplate和StringRedisTemplate)

文章目录 引言I 基础知识redis对key和value使用序列化方式RedisTemplate<Object, Object>自定义redisTemplate序列化规则RedisTemplate<String, String>II 存储自定义对象redisTemplate存储自定义对象StringRedisTemplate存储自定义对象引言 StringRedisTemplate只…

二叉苹果树

AcWing 1074. 二叉苹果树【有依赖背包DP】 - AcWing 问题描述 在一棵有权无向树中&#xff0c;从某个节点&#xff08;这里假设为节点 1&#xff09;出发&#xff0c;遍历树的子节点&#xff0c;每经过一条边会获得对应的权重值。在访问节点数的限制下&#xff08;即体积限制…

Linux基础命令(八) 之 alias ,history,stat,type,特殊符号及命令行快捷键

目录 一&#xff0c;命令别名 alias 常见用法 二&#xff0c;命令历史 history 参数及其作用 常见用法 三.显示文件或文件系统的详细信息 stat 参数及其作用 常见用法 四&#xff0c;显示命令的类型 type 参数及其作用 常见用法 五&#xff0c;特殊符号及命令行快捷…

省级-知识产权保护指数(2012-2022年)

省级知识产权保护指数&#xff08;以下简称“指数”&#xff09;正是衡量各省份在知识产权保护方面表现的一个综合指标&#xff0c;它涵盖了立法、执法、审查和监督等多个维度&#xff0c;全面反映了各省份在知识产权保护方面的综合实力。 2012年-2022年省级-知识产权保护指数…

GraphQL 与 Elasticsearch 相遇:使用 Hasura DDN 构建可扩展、支持 AI 的应用程序

作者&#xff1a;来自 Elastic Praveen Durairaju GraphQL 提供了一种高效且灵活的数据查询方式。本博客将解释 Hasura DDN 如何与 Elasticsearch 配合使用&#xff0c;以实现高性能和元数据驱动的数据访问。 此示例的代码和设置可在此 GitHub 存储库 - elasticsearch-subgraph…

filebeat+elasticsearch+kibana日志分析

1 默认配置 1.1 filebeat filebeat-7.17.yml,从网关中下载k8s的配置&#xff0c;指定es和kibana的配置 通过kibana查询可以查询到日志了&#xff0c;但此时还不知道具体怎么用。 1.2 kibana 在Discover中创建索引格式&#xff1a;filebeat-*&#xff0c;得到如下图&#xf…

Rust 力扣 - 2090. 半径为 k 的子数组平均值

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 半径为 k 的子数组平均值 等价于 子数组长度为2 * k 1的总和 除于 2 * k 1 我们遍历长度为2 * k 1的窗口&#xff0c;我们只需要记录窗口内的平均值即可 题解代码 impl Solution {pub fn get_averages(num…

uniapp的video视频属性打包app后层级过高

问题&#xff1a;在使用uniapp开发APP时&#xff0c;使用video标签显示视频发现H5可以正常展示&#xff0c;但是打包到APP后&#xff0c;它的层级过高&#xff0c;把底部导航都盖住了。 官网说明&#xff1a;uni-app官网 官网给了cover-view组件或plus.nativeObj.view、subNVue…

浅谈UI自动化

⭐️前言⭐️ 本篇文章围绕UI自动化来展开&#xff0c;主要内容包括什么是UI自动化&#xff0c;常用的UI自动化框架&#xff0c;UI自动化原理等。 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题…

Vue3+Data-V实现可视化大屏页面布局

目录 一、前言 二、环境准备 1.Vue3安装npm create vuelatest 2.Data-V配置 项目Data-v安装 main.js中注册Data-v到全局 ​编辑可使用按需引入 3.测试 三、导航栏路由跳转配置 1.子组件mainNav组件准备 2.父组件准备导航栏参数传递 3.子组件接收父组件参数 4.导航…

Python 使用 LSTM 进行情感分析:处理文本序列数据的指南

使用 LSTM 进行情感分析&#xff1a;处理文本序列数据的指南 长短期记忆网络&#xff08;LSTM&#xff09;是一种适合处理序列数据的深度学习模型&#xff0c;广泛应用于情感分析、语音识别、文本生成等领域。它通过在训练过程中“记住”过去的数据特征来理解和预测序列数据的…

树莓派5实时时钟(RTC)

树莓派5板载一个实时时钟模块。它可以通过 USB-C 电源插口右侧板上的 J5(BAT) 插口进行电池供电。如果没有互联网连接来通过 NTP 获取时间&#xff0c;RTC 可能会很有用。 可以设置唤醒警报&#xff0c;将树莓派5切换到非常低功耗的状态&#xff08;大约3mA&#xff09;。当到达…