k8s集群验证

继上次k8s集群部署完成之后,接下来开始对集群做简单的测试。

首先这里文件存储的方式采用nfs,因此先得部署本地nfs服务器来做后续测试。


环境准备

  • nfs服务器centos7.8(阿里云ECS)
    机器名: k8s-master
    公网ip:47.9x.17x.9x
  • nfs客户端centos7.9(腾讯云EVM)
    机器名: k8s-node1
    公网ip:121.4x.9x.7x

nfs服务器搭建(服务器和客户端都需要安装)

yum -y install rpcbind nfs-utils

# 启动nfs,并开机自启

systemctl start rpcbind
systemctl enable rpcbind

# NFS依赖rpcbind进行通讯,所以要先启动rpcbind

systemctl start nfs-server
systemctl enable nfs-server

# 查看服务是否已启动(服务端和客户端都要测试)

rpcinfo -p localhost
k8s集群验证_第1张图片
clipboard.png

一般showmount -e localhost命令都是好使的,在使用showmount -e 公网ip时会显示如下问题
showmount -e 47.9x.17x.9x
clnt_create: RPC: Port mapper failure - Timed out

出现这问题就说明nfs的端口没有对外开放,服务端需要开放的端口如下:

协议 方向 端口 源地址 说明
UDP 入站 111/111 0.0.0.0/0 nfs portmapper
TCP 入站 111/111 0.0.0.0/0 nfs portmapper
UDP 入站 20048/20048 0.0.0.0/0 nfs mountd
TCP 入站 20048/20048 0.0.0.0/0 nfs mountd
TCP 入站 2049/2049 0.0.0.0/0 nfs
UDP 入站 2049/2049 0.0.0.0/0 nfs

至此,nfs的服务端和客户端就安装成功了,客户端不用开通这些端口。


在nfs服务器创建 挂载目录

 mkdir -pv /data/volumes

然后可以再这里目录里创建 nginx default v2 v3 v5 这5个目录供后续测试使用

# 可以共享给指定IP(192.168.1.7),也可以共享给指定网段(192.168.1.0/16),还可以共享给所有IP(*).rw代表读写权限。

vim /etc/exports

 /data/volumes/nginx 47.9x.17x.9x(insecure,rw,async,no_root_squash)
 /data/volumes/nginx 121.4x.9x.7x(insecure,rw,async,no_root_squash)

此处我将两台服务器都配置了挂载目录的权限

/etc/exports配置文件中权限参数常用的有如下五个:
  ro只读权限
  rw读写权限
  sync同步写入内存与磁盘当中
  no_all_squash保留共享文件的UID和GID(默认)
  no_root_squash使得root用户具有根目录的完全访问权限

# 重新读取配置文件,而不中断服务

exportfs -rv

# 成功后在两台服务器上都重新执行看目录是否挂载成功

showmount -e 47.9x.17x.9x
k8s集群验证_第2张图片
clipboard.png

可以看到目录共享成功


节点上将挂载点挂载到nfs服务的共享目录(选做,这是测试nfs用,不涉及到k8s后续操作)

mount -t nfs 47.9x.17x.9x:/data/volumes /mnt

可能会报错误: mount: can't find /mnt in /etc/fstab
首先解释下命令含义,mount常用来挂载文件系统,本质nfs就是一个文件系统。上面命令就是将客户端目录/data/volumes做为挂载点,挂载到nfs服务端的共享目录/mnt下,nfs服务端的ip是47.9x.17x.9x。通俗讲就是将客户端目录/data/volumes与服务端的共享目录/mnt实现共享。
执行此命令之前必须保证nfs服务端的export文件内已经配置/mnt为共享目录了。
接着继续看我们的问题,/etc/fstab文件是配置nfs挂载点的文件,问题也就很明显了,我们需要在该文件的末尾新增一行配置一个挂载点,配置如下。
47.9x.17x.9x:/mnt    /data/volumes     nfs    default 0       0

第一列是需要挂载的文件系统或者是存储设备或者是需要挂载的目录。
第二列是挂载点,挂载点就是客户端挂载的目录。
第三列是文件系统或者是分区的类型(其实分区类型就是中文件系统)
第四列是以何种形式挂载,比如rw读写, auto自动挂载,ro只读等等参数。不过最常用的是default。default是rw,suid,dev,exec,auto,nouser,async等的组合。
第五列为dump选项,设置是否让备份程序dump备份文件系统,0为忽略,1为备份。
第六列为fsck选项,告诉fsck程序以什么顺序检查文件系统,0为忽略。

设置完毕后重新执行挂载
mount -t nfs 47.9x.17x.9x:/data/volumes /mnt

成功后分别在nfs服务器和节点服务器做文件测试,会发现是双方同步


卸载挂载目录
umount /mnt
如果提示设备繁忙,那么先退出当前连接,重新连接服务器再执行该命令

创建k8s集群的pv

PV 的全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象,PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。

执行以下脚本

vim pv.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nginx
  labels:
    name: pv-nginx
spec:
  nfs:
    path: /data/volumes/nginx
    server: 47.9x.17x.9x
  accessModes: ['ReadWriteMany', 'ReadWriteOnce']
  capacity:
    storage: 500Mi

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: 47.9x.17x.9x
  accessModes: ['ReadWriteMany', 'ReadWriteOnce']
  capacity:
    storage: 2Gi

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: 47.9x.17x.9x
  accessModes: ['ReadWriteMany', 'ReadWriteOnce']
  capacity:
    storage: 2Gi

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-default
  labels:
    name: pv-default
spec:
  nfs:
    path: /data/volumes/default
    server: 47.9x.17x.9x
  accessModes: ['ReadWriteMany', 'ReadWriteOnce']
  capacity:
    storage: 4Gi

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: 47.9x.17x.9x
  accessModes: ['ReadWriteMany', 'ReadWriteOnce']
  capacity:
    storage: 7Gi

执行

kubectl apply -f pv.yml

查看创建好的5个pv。可以发现这里pv的存储方式采用的是nfs

kubectl get pv -o wide
clipboard.png

可以看到5个新建的pv状态都是未绑定状态,请忽略上述的pv-nginx的状态,这是我后续绑定了pvc造成的,后续会说明。

pv创建好之后,接下来需要使用它。


创建pvc

PVC的全称是: PersistenVolumeClaim (持久化卷声明),PVC是用户存储的一种声明,PVC和Pod比较类型,Pod是消耗节点,PVC消耗的是PV资源,Pod可以请求CPU的内存,而PVC可以请求特定的存储空间和访问模式。对于真正存储的用户不需要关心底层的存储实现细节,只需要直接使用PVC即可

vim pvc-nginx.yml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nginx
  namespace: nginx
spec:
  accessModes: ['ReadWriteMany']
  resources:
    requests:
      storage: 500Mi

上述代码可以看到pvc其实并没有指定需要使用哪个pv,只是说明了需要的存储空间是500M(G的写法是Gi),然后访问模式是多次读写(ReadWriteMany)。

首先需要明白一点,存储卷 (PV) 的访问模式 () 决定的是 PV 支持那几种被节点 (nodes) 挂载的方式,。一个存储卷 (PV) 可支持多种模式。几种模式如下:
* (RWO) ReadWriteOnce 可被一个节点读写挂载
* (ROX) ReadOnlyMany 可被多个节点只读挂载
* (RWX) ReadWriteMany 可被多个节点读写挂载
执行

 kubectl apply -f pvc-nginx.yml

然后在查看pv使用情况,就会发现是我上面截图的那种情况,pv会根据pvc申请的空间大小自动去匹配合适的pv卷,然后进行绑定,刚好pv-nginx满足他的需要,因此nginx和pvc绑定成功。

pvc的查看命令是:


image.png

创建nginx deployment

先单独创建nginx 的namespace

kubectl create namespace nginx

接下来使用nginx的测试都在nginx namespace中进行。

创建nginx configmap文件

configmap文件用来存储nginx.conf配置文件。之所以将nginx的配置文件和nginx的pod分开部署,是由于在大部分情况下nginx服务本身其实并不会改动,改动的也只是nginx配置文件,所以单独拿出来部署。
而部署nginx配置文件其实有很多种方式,可以使用configmap,也可以使用pvc来将配置文件挂载到本地或者其他的储存文件系统中去。

另外要注意的一点是,configmap文件可以随时更改。但是nginx配置文件更改之后,通常情况下需要nginx reload。而且nginx采用deployment部署的话,你即使重新apply -f deployment文件的话,它也不会起作用。因为此时的deployment文件并没有任何改动,k8s会认为该pod没有做变动,不会重新启动pod。这一点在后续会说明,可以采用别的方式来强制apply -f deplyment文件。

vim nginx-configmap.yml

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configmap
  namespace: nginx
data:
  nginx_conf: |-
    #user  nobody;
    worker_processes  1;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        server {
            listen       80;
            server_name  localhost;
            location / {
                root   /usr/share/nginx/html;
                index  index.html index.htm;
            }
            location /data {
                root   /usr/share/nginx;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   /usr/share/nginx/html;
            }
        }
    }

此处的nginx 添加了/data 映射是为了后续访问index.html首页时能实时打印出当前节点的hostname,以便能明显区分出k8s对pod的负载均衡功能。

执行configmap文件

kubectl apply -f nginx-configmap.yml

查看cm

kubectl -n nginx get cm -o wide

创建nginx deployment文件
vim nginx-deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-cluster
  name: nginx-cluster
  namespace: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-cluster
  template:
    metadata:
      labels:
        app: nginx-cluster
    spec:
      containers:
        - name: nginx-cluster
          image: nginx
          command:
            - /bin/sh
          args:
            - '-c'
            - |
              set -ex
              mkdir -pv /usr/share/nginx/data
              echo $HOSTNAME>/usr/share/nginx/data/hostname.data
              exec nginx -g 'daemon off;'
          env:
            - name: RESTART_
              value: v202012101554
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
            - name: nginx
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: pvc-nginx
        - name: nginx
          configMap:
            name: nginx-configmap
            items:
              - key: nginx_conf
                path: nginx.conf

这里着重说下command、args和env三个属性,command属性用来输入命令,一般建议就输入/bin/sh即可,想执行多条shell命令的话,在args中输入,-c用来解析后面的字符串执行其中的指令,文件中的命令很简单,先创建目录,再将主机名输入该目录下的文件中存储。唯一注意的是最后的这条命令 exec nginx -g 'daemon off;'

Docker 容器启动时,默认会把容器内部第一个进程,也就是pid=1的程序,作为docker容器是否正在运行的依据,如果 docker 容器pid=1的进程挂了,那么docker容器便会直接退出。

Docker未执行自定义的CMD之前,nginx的pid是1,执行到CMD之后,nginx就在后台运行,bash或sh脚本的pid变成了1。

所以一旦执行完自定义CMD,nginx容器也就退出了。

上述这一点在今后部署服务时一定要注意。

而env中的环境参数就是用来控制deployment文件强制重启的,每次想重新启动deployment的话,直接修改RESATRT_的值,然后再执行 kubectl apply -f deployment.yml 即可。

创建nginx deployment

kubectl apply -f nginx-deployment.yml

查看运行情况

kubectl -n nginx get pod -o wide
image.png

会发现nginx的两个pod已经运行起来了,它运行的机器是由k8s自行调度的,本文这里是刚好俩pod都调度到了k8s-node1节点上。
现在在k8s-mater节点和k8s-node1节点分别ping这俩ip地址。如果都能ping通的话说明集群间的地址通讯没有问题。

将index.html文件放入nfs服务器中的/data/volumes/nginx目录下面





  
  
  Document



  
hello。

再检查 curl 10.244.1.3:80 或者curl 10.244.1.2:80 看能不能请求成功。

都成功的话现在部署svc,通过svc来对外暴露pod

创建nginx service

vim nginx-service.yml

apiVersion: v1
kind: Service
metadata:
  name: nginx-service #定义service名称为nginx-service
  namespace: nginx
  labels:
    app: nginx-service #为service打上app标签
spec:
  type: NodePort #使用NodePort方式开通,在每个Node上分配一个端口作为外部访问入口
  selector:
    app: nginx-cluster
  ports:
    - port: 8000 #port是k8s集群内部访问service的端口,即通过clusterIP: port可以访问到某个service
      targetPort: 80 #targetPort是pod的端口,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最后进入容器
      nodePort: 32500 #nodePort是外部访问k8s集群中service的端口,通过nodeIP: nodePort可以从外部访问到某个service

执行

kubectl apply -f nginx-serivce.yml

查看

kubectl get svc -n nginx -o wide
image.png

可以看到svc也部署成功
先测试看该ip地址能否在master和node1节点上都能ping通,
检查 curl 10.1.220.172:8000 能否请求成功
都没问题的话即可以使用外用ip访问32500端口了。

47.9x.17x.9x和121.4x.9x.7x这两个外网地址访问32500都可以

多开几个客户端请求地址查看。可以发现每次返回的主机名都不一样。

至此,验证工作完成。接下来是完善k8s生态,待后续。

你可能感兴趣的:(k8s集群验证)