CKA认证模块②-K8S企业运维和落地实战-2

CKA认证模块②-K8S企业运维和落地实战-2

K8S常见的存储方案及具体应用场景分析

k8s存储-empty

emptyDir类型的Volume是在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。

[root@k8s-master01 ~]# mkdir storage
[root@k8s-master01 ~]# cd storage/
# 创建工作目录

[root@k8s-master01 storage]# kubectl explain pod.spec.volumes.
...
# 查看支持哪些存储卷

[root@k8s-master01 storage]# cat emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-empty
spec:
  containers:
  - name: container-empty
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: cache-volume
      mountPath: /cache
  volumes:
  - name: cache-volume
    emptyDir: {}
[root@k8s-master01 storage]# kubectl apply -f emptydir.yaml 
pod/pod-empty created
[root@k8s-master01 storage]# kubectl get pods -owide
NAME        READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
pod-empty   1/1     Running   0          4s    10.244.58.253   k8s-node02   <none>           <none>
# 创建pod
[root@k8s-master01 storage]# kubectl exec -it pod-empty -c container-empty -- /bin/bash
root@pod-empty:/# cd /cache/
root@pod-empty:/cache# touch 123
root@pod-empty:/cache# touch aa
root@pod-empty:/cache# ls
123  aa
# 创建empty挂载文件夹下文件
root@pod-empty:/cache# exit
exit
[root@k8s-master01 storage]# kubectl get pods -oyaml |grep uid
    uid: 8ce8fecc-dc86-4c92-8876-69ac034b6972
[root@k8s-master01 storage]# kubectl get pods -owide
NAME        READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
pod-empty   1/1     Running   0          2m43s   10.244.58.253   k8s-node02   <none>           <none>
# 查看pod的uid,并查看调度节点

[root@k8s-node02 ~]# yum -y install tree
[root@k8s-node02 ~]# tree /var/lib/kubelet/pods/8ce8fecc-dc86-4c92-8876-69ac034b6972
...
[root@k8s-node02 ~]# cd /var/lib/kubelet/pods/8ce8fecc-dc86-4c92-8876-69ac034b6972/
[root@k8s-node02 8ce8fecc-dc86-4c92-8876-69ac034b6972]# cd volumes/kubernetes.io~empty-dir/cache-volume/
[root@k8s-node02 cache-volume]# ls
123  aa
[root@k8s-node02 cache-volume]# pwd
/var/lib/kubelet/pods/8ce8fecc-dc86-4c92-8876-69ac034b6972/volumes/kubernetes.io~empty-dir/cache-volume
# 已经保存到临时文件夹下

[root@k8s-master01 storage]# kubectl delete pod pod-empty 
pod "pod-empty" deleted
# 删除pod

[root@k8s-node02 cache-volume]# ls
[root@k8s-node02 cache-volume]# cd ..
cd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
# 因为整个容器目录都被删除,emptyDir目录自然也被删除,所以不建议使用
k8s存储-hostPath

hostpath存储卷缺点:

单节点

pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失

[root@k8s-node01 images]# ctr -n k8s.io images import tomcat.tar.gz.0
[root@k8s-node02 images]# ctr -n k8s.io images import tomcat.tar.gz.0
# 因为之前上传过同名镜像包,名字不能一样后面加了.0

[root@k8s-master01 storage]# kubectl explain pod.spec.volumes.hostPath.type
# 查看支持哪些类型 https://kubernetes.io/docs/concepts/storage/volumes#hostpath

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[root@k8s-master01 storage]# kubectl explain pod.spec |grep -i nodename
# 查看帮助

[root@k8s-master01 storage]# cat hostpath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath
  namespace: default
spec:
  nodeName: k8s-node01
  containers:
  - name: test-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts: 
    - name: test-volume
      mountPath: /test-nginx
  - name: test-tomcat
    image: tomcat
    imagePullPolicy: IfNotPresent
    volumeMounts: 
    - name: test-volume
      mountPath: /test-tomcat
  volumes:
  - name: test-volume
    hostPath: 
      path: /data1
      type: DirectoryOrCreate  
[root@k8s-master01 storage]# kubectl apply -f hostpath.yaml 
pod/pod-hostpath created
[root@k8s-master01 storage]# kubectl exec -it pod-hostpath -c test-nginx -- /bin/bash
root@pod-hostpath:/# cd test-nginx/
root@pod-hostpath:/test-nginx# touch nginx
root@pod-hostpath:/test-nginx# ls
nginx
root@pod-hostpath:/test-nginx# exit
exit
[root@k8s-master01 storage]# kubectl exec -it pod-hostpath -c test-tomcat -- /bin/bash
root@pod-hostpath:/usr/local/tomcat# cd /test-tomcat/
root@pod-hostpath:/test-tomcat# touch tomcat
root@pod-hostpath:/test-tomcat# ls
nginx  tomcat
root@pod-hostpath:/test-tomcat# exit
exit
[root@k8s-node01 ~]# ls /data1/
nginx  tomcat
# 测试是否为同一卷

[root@k8s-master01 storage]# kubectl delete -f hostpath.yaml 
pod "pod-hostpath" deleted
# 删除pod

[root@k8s-node01 ~]# ll /data1/
total 0
-rw-r--r-- 1 root root 0 Jul  3 16:30 nginx
-rw-r--r-- 1 root root 0 Jul  3 16:31 tomcat
# 数据仍然存在
k8s存储-NFS
注意: NFS服务器配置白名单是node节点网段而不是pod网段

node节点网段,例如我的环境应配置: 192.168.1.0/24

yum -y install nfs-utils
systemctl enable --now nfs
# 所有节点安装nfs

[root@k8s-master01 storage]# mkdir -pv /data/volume
mkdir: created directory ‘/data’
mkdir: created directory ‘/data/volume’
# v参数是展示创建了哪些文件夹
[root@k8s-master01 storage]# cat /etc/exports
/data/volume *(rw,no_root_squash)
[root@k8s-master01 storage]# systemctl restart nfs
[root@k8s-master01 storage]# showmount -e localhost
Export list for localhost:
/data/volume *
# 配置nfs服务
[root@k8s-node01 ~]# mount -t nfs k8s-master01:/data/volume /mnt
[root@k8s-node01 ~]# df -Th |tail -n1
k8s-master01:/data/volume nfs4       38G   11G   27G  29% /mnt
[root@k8s-node01 ~]# umount /mnt 
# 测试nfs服务

[root@k8s-master01 storage]# cat nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nfs-volume
  namespace: default
spec:
  replicas: 3
  selector: 
    matchLabels:
      storage: nfs
  template:
    metadata:
      labels:
        storage: nfs
    spec:
      containers:
      - name: test-nfs
        image: xianchao/nginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: nfs-volumes
          mountPath: /usr/share/nginx/html
      volumes: 
      - name: nfs-volumes
        nfs:
          server: 192.168.1.181
          # 注意nfs服务器的ip一定不能写错
          path: /data/volume
[root@k8s-master01 storage]# kubectl apply -f nfs.yaml 
deployment.apps/test-nfs-volume created
# 创建deployment
[root@k8s-master01 storage]# echo nfs-test > /data/volume/index.html
[root@k8s-master01 storage]# kubectl get pods -owide
NAME                               READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
test-nfs-volume-6656574b86-66m2h   1/1     Running   0          5m37s   10.244.85.233   k8s-node01   <none>           <none>
test-nfs-volume-6656574b86-6nxgw   1/1     Running   0          5m37s   10.244.85.232   k8s-node01   <none>           <none>
test-nfs-volume-6656574b86-cvqmr   1/1     Running   0          5m37s   10.244.58.255   k8s-node02   <none>           <none>
[root@k8s-master01 storage]# curl 10.244.85.232
nfs-test
# 测试nfs
[root@k8s-master01 storage]# kubectl exec -it test-nfs-volume-6656574b86-cvqmr 
-- /bin/bash
root@test-nfs-volume-6656574b86-cvqmr:/# ls /usr/share/nginx/html/
index.html
root@test-nfs-volume-6656574b86-cvqmr:/# cat /usr/share/nginx/html/index.html 
nfs-test
root@test-nfs-volume-6656574b86-cvqmr:/# exit 
exit
# 进入pod测试

[root@k8s-master01 storage]# kubectl delete -f nfs.yaml 
deployment.apps "test-nfs-volume" deleted
# 删除deployment

[root@k8s-master01 storage]# ls /data/volume/
index.html
[root@k8s-master01 storage]# cat /data/volume/index.html 
nfs-test
# 数据仍然存在
k8s存储-PVC
[root@k8s-master01 storage]# mkdir /data/volume-test/v{1..10} -p
[root@k8s-master01 storage]# cat /etc/exports
/data/volume *(rw,no_root_squash)
/data/volume-test/v1 *(rw,no_root_squash)
/data/volume-test/v2 *(rw,no_root_squash)
/data/volume-test/v3 *(rw,no_root_squash)
/data/volume-test/v4 *(rw,no_root_squash)
/data/volume-test/v5 *(rw,no_root_squash)
/data/volume-test/v6 *(rw,no_root_squash)
/data/volume-test/v7 *(rw,no_root_squash)
/data/volume-test/v8 *(rw,no_root_squash)
/data/volume-test/v9 *(rw,no_root_squash)
/data/volume-test/v10 *(rw,no_root_squash)
[root@k8s-master01 storage]# exportfs -arv
# 生效配置

[root@k8s-master01 storage]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v1
  labels:
    app: v1
spec:
  nfs:
    server: 192.168.1.181
    path: /data/volume-test/v1
  accessModes: ["ReadWriteOnce"]
  capacity: 
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v2
  labels:
    app: v2
spec:
  nfs:
    server: 192.168.1.181
    path: /data/volume-test/v2
  accessModes: ["ReadOnlyMany"]
  capacity: 
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v3
  labels:
    app: v3
spec:
  nfs:
    server: 192.168.1.181
    path: /data/volume-test/v3
  accessModes: ["ReadWriteMany"]
  capacity: 
    storage: 3Gi

https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-mod

访问模式有:

  • ReadWriteOnce

    卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。

  • ReadOnlyMany

    卷可以被多个节点以只读方式挂载。

  • ReadWriteMany

    卷可以被多个节点以读写方式挂载。

  • ReadWriteOncePod

    特性状态: Kubernetes v1.27 [beta]卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用 ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。

[root@k8s-master01 storage]# kubectl apply -f pv.yaml 
persistentvolume/v1 created
persistentvolume/v2 created
persistentvolume/v3 created
[root@k8s-master01 storage]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
v1     1Gi        RWO            Retain           Available                                   22s
v2     2Gi        ROX            Retain           Available                                   22s
v3     3Gi        RWX            Retain           Available                                   22s
[root@k8s-master01 storage]# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v1
spec:
  accessModes: ["ReadWriteOnce"]
  selector:
    matchLabels: 
      app: v1
  resources:
    requests: 
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v2
spec:
  accessModes: ["ReadOnlyMany"]
  selector:
    matchLabels: 
      app: v2
  resources:
    requests: 
      storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v3
spec:
  accessModes: ["ReadWriteMany"]
  selector:
    matchLabels: 
      app: v3
  resources:
    requests: 
      storage: 3Gi
[root@k8s-master01 storage]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/pvc-v1 created
persistentvolumeclaim/pvc-v2 created
persistentvolumeclaim/pvc-v3 created
[root@k8s-master01 storage]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-v1   Bound    v1       1Gi        RWO                           4s
pvc-v2   Bound    v2       2Gi        ROX                           4s
pvc-v3   Bound    v3       3Gi        RWX                           4s
# Bound状态就说明pvc已经和pv绑定

RWO: ReadWriteOnce

ROX: ReadOnlyMany

RWX: ReadWriteMany

[root@k8s-master01 storage]# cat deploy_pvc.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pvc-test
spec:
  replicas: 3
  selector:
    matchLabels:
      storage: pvc
  template:
    metadata:
      labels:
        storage: pvc
    spec:
      containers:
      - name: test-pvc
        image: xianchao/nginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts: 
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-html
        persistentVolumeClaim: 
          claimName: pvc-v1
[root@k8s-master01 storage]# kubectl apply -f deploy_pvc.yaml 
deployment.apps/pvc-test created
# 创建deployment使用pvc
[root@k8s-master01 storage]# echo pvc-test > /data/volume-test/v1/index.html
[root@k8s-master01 storage]# kubectl get pods -owide
NAME                        READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
pvc-test-66c48b4c9d-dljv7   1/1     Running   0          46s   10.244.85.236   k8s-node01   <none>           <none>
pvc-test-66c48b4c9d-fcttc   1/1     Running   0          46s   10.244.58.197   k8s-node02   <none>           <none>
pvc-test-66c48b4c9d-kcjvr   1/1     Running   0          46s   10.244.58.198   k8s-node02   <none>           <none>
[root@k8s-master01 storage]# curl 10.244.58.198
pvc-test
# 测试访问成功

**注:**使用pvc和pv的注意事项

1、我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的

2、pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失。

经过测试,如果回收策略是Delete,删除pv,pv后端存储的数据也不会被删除

**回收策略:**persistentVolumeReclaimPolicy字段

删除pvc的步骤:

需要先删除使用pvc的pod

再删除pvc

[root@k8s-master01 storage]# kubectl delete -f deploy_pvc.yaml 
deployment.apps "pvc-test" deleted
[root@k8s-master01 storage]# kubectl delete -f pvc.yaml 
persistentvolumeclaim "pvc-v1" deleted
persistentvolumeclaim "pvc-v2" deleted
persistentvolumeclaim "pvc-v3" deleted
[root@k8s-master01 storage]# kubectl delete -f pv.yaml 
persistentvolume "v1" deleted
persistentvolume "v2" deleted
persistentvolume "v3" deleted
演示pv用Delete回收策略:
[root@k8s-master01 storage]# cat pv-1.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v4
  labels:
    app: v4
spec:
  nfs:
    server: 192.168.1.181
    path: /data/volume-test/v4
  accessModes: ["ReadWriteOnce"]
  capacity: 
    storage: 1Gi
  persistentVolumeReclaimPolicy: Delete
[root@k8s-master01 storage]# kubectl apply -f pv-1.yaml 
persistentvolume/v4 created
# 创建pv
[root@k8s-master01 storage]# cat pvc-1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v4
spec:
  accessModes: ["ReadWriteOnce"]
  selector:
    matchLabels: 
      app: v4
  resources:
    requests: 
      storage: 1Gi
[root@k8s-master01 storage]# kubectl apply -f pvc-1.yaml 
persistentvolumeclaim/pvc-v4 created
# 创建pvc
[root@k8s-master01 storage]# cat deploy_pvc-1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pvc-test-1
spec:
  replicas: 3
  selector:
    matchLabels:
      storage: pvc-1
  template:
    metadata:
      labels:
        storage: pvc-1
    spec:
      containers:
      - name: test-pvc
        image: xianchao/nginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts: 
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-html
        persistentVolumeClaim: 
          claimName: pvc-v4
[root@k8s-master01 storage]# kubectl apply -f deploy_pvc-1.yaml 
deployment.apps/pvc-test-1 created
# 创建deployment使用pvc
[root@k8s-master01 storage]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
pvc-test-1-58fc869c7c-fgl4r   1/1     Running   0          6s
pvc-test-1-58fc869c7c-h5rxb   1/1     Running   0          6s
pvc-test-1-58fc869c7c-nr7cv   1/1     Running   0          6s
[root@k8s-master01 storage]# kubectl exec -it pvc-test-1-58fc869c7c-fgl4r -- /bin/bash
root@pvc-test-1-58fc869c7c-fgl4r:/# cd /usr/share/nginx/html/
root@pvc-test-1-58fc869c7c-fgl4r:/usr/share/nginx/html# echo ReclaimPolicy-Delete_test > index.html
root@pvc-test-1-58fc869c7c-fgl4r:/usr/share/nginx/html# touch 123
# 写入内容
root@pvc-test-1-58fc869c7c-fgl4r:/usr/share/nginx/html# ls
123  index.html
root@pvc-test-1-58fc869c7c-fgl4r:/usr/share/nginx/html# exit
exit
command terminated with exit code 127
# 退出容器
[root@k8s-master01 storage]# kubectl delete -f deploy_pvc-1.yaml 
deployment.apps "pvc-test-1" deleted
[root@k8s-master01 storage]# kubectl delete -f pvc-1.yaml 
persistentvolumeclaim "pvc-v4" deleted
[root@k8s-master01 storage]# kubectl delete -f pv-1.yaml 
persistentvolume "v4" deleted
# 删除deployment,pvc以及pv
[root@k8s-master01 storage]# kubectl get pv
No resources found
[root@k8s-master01 storage]# ls /data/volume-test/v4/
123  index.html
# 可以看到,内容并没有被删除,所以Delete不是像官网说的一样会删除,可能是暂时不支持NFS

Storageclass存储类动态生成存储

存储类动态生成pv
[root@k8s-node01 images]# ctr -n k8s.io images import nfs-subdir-external-provisioner.tar.gz
[root@k8s-node02 images]# ctr -n k8s.io images import nfs-subdir-external-provisioner.tar.gz 
# 工作节点导入镜像

[root@k8s-master01 storageclass]# mkdir /data/nfs_pro -p
[root@k8s-master01 storageclass]# cat /etc/exports
/data/volume 192.168.1.0/24(rw,no_root_squash)
/data/volume-test/v1 *(rw,no_root_squash)
/data/volume-test/v2 *(rw,no_root_squash)
/data/volume-test/v3 *(rw,no_root_squash)
/data/volume-test/v4 *(rw,no_root_squash)
/data/volume-test/v5 *(rw,no_root_squash)
/data/volume-test/v6 *(rw,no_root_squash)
/data/volume-test/v7 *(rw,no_root_squash)
/data/volume-test/v8 *(rw,no_root_squash)
/data/volume-test/v9 *(rw,no_root_squash)
/data/volume-test/v10 *(rw,no_root_squash)
/data/nfs_pro *(rw,no_root_squash)
[root@k8s-master01 storageclass]# exportfs -arv
exporting 192.168.1.0/24:/data/volume
exporting *:/data/nfs_pro
exporting *:/data/volume-test/v10
exporting *:/data/volume-test/v9
exporting *:/data/volume-test/v8
exporting *:/data/volume-test/v7
exporting *:/data/volume-test/v6
exporting *:/data/volume-test/v5
exporting *:/data/volume-test/v4
exporting *:/data/volume-test/v3
exporting *:/data/volume-test/v2
exporting *:/data/volume-test/v1
# 配置nfs服务

[root@k8s-master01 ~]# mkdir storageclass
[root@k8s-master01 ~]# cd storageclass/
# 创建工作目录

[root@k8s-master01 storageclass]# cat serviceaccount.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner

[root@k8s-master01 storageclass]# kubectl apply -f serviceaccount.yaml 
serviceaccount/nfs-provisioner created
# 创建sa
[root@k8s-master01 storageclass]# kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
clusterrolebinding.rbac.authorization.k8s.io/nfs-provisioner-clusterrolebinding created
# 对sa授权

[root@k8s-master01 storageclass]# cat nfs-deployment.yaml 
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-provisioner
spec:
  selector:
    matchLabels:
       app: nfs-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: 192.168.1.181
            - name: NFS_PATH
              value: /data/nfs_pro/
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.181
            path: /data/nfs_pro/

[root@k8s-master01 storageclass]# kubectl apply -f nfs-deployment.yaml 
deployment.apps/nfs-provisioner created
[root@k8s-master01 storageclass]# kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nfs-provisioner-747db885fd-phwm2   1/1     Running   0          60s
# 安装nfs-provisioner程序

[root@k8s-master01 storageclass]# cat nfs-storageclass.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
provisioner: example.com/nfs
# 注意provisioner的值一定要跟安装nfs-provisioner时候的PROVISIONER_NAME一致
[root@k8s-master01 storageclass]# kubectl apply -f nfs-storageclass.yaml 
storageclass.storage.k8s.io/nfs created
[root@k8s-master01 storageclass]# kubectl get sc
NAME   PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs    example.com/nfs   Delete          Immediate           false                  16s
# 创建storageclass,动态供给pv


[root@k8s-master01 storageclass]# cat claim.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes:  ["ReadWriteMany"]
  resources:
    requests:
      storage: 1Gi
  storageClassName:  nfs

[root@k8s-master01 storageclass]# kubectl apply -f claim.yaml 
persistentvolumeclaim/test-claim1 created
# 创建pvc
[root@k8s-master01 storageclass]# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-claim1   Bound    pvc-b334c653-bb8b-4e48-8aa1-469f8ea90fb3   1Gi        RWX            nfs            49s
# 可以看到pvc已经成功创建了

步骤总结:

1、供应商:创建一个nfs provisioner

2、创建storageclass,storageclass指定刚才创建的供应商

3、创建pvc,这个pvc指定storageclass

[root@k8s-master01 storageclass]# cat read-pod.yaml 
kind: Pod
apiVersion: v1
metadata:
  name: read-pod
spec:
  containers:
  - name: read-pod
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
      - name: nfs-pvc
        mountPath: /usr/share/nginx/html
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim1

[root@k8s-master01 storageclass]# kubectl apply -f read-pod.yaml 
pod/read-pod created
# 创建pod,挂载storageclass动态生成的pvc: test-claim1
[root@k8s-master01 storageclass]# kubectl get pods | grep read
read-pod                           1/1     Running   0          88s
# 可以看到pod已经建立成功
[root@k8s-master01 storageclass]# echo nfs-provisioner > /data/nfs_pro/default-test-claim1-pvc-b334c653-bb8b-4e48-8aa1-469f8ea90fb3/index.html
# 写入文件测试
[root@k8s-master01 storageclass]# kubectl get pods -owide
NAME                               READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
nfs-provisioner-747db885fd-phwm2   1/1     Running   0          8m20s   10.244.58.201   k8s-node02   <none>           <none>
read-pod                           1/1     Running   0          3m      10.244.85.238   k8s-node01   <none>           <none>
[root@k8s-master01 storageclass]# curl 10.244.85.238
nfs-provisioner
# 访问成功

K8S控制器Statefulset入门到企业实战应用

StatefulSet资源-YAML编写技巧

StatefulSet是为了管理有状态服务的问题而设计的

扩展:

有状态服务?

**StatefulSet是有状态的集合,管理有状态的服务,**它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、redis集群等。

无状态服务?

**RC、Deployment、DaemonSet都是管理无状态的服务,**它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。

[root@k8s-master01 ~]# kubectl explain statefulset.
# 查看帮助

[root@k8s-master01 ~]# mkdir statefulset
[root@k8s-master01 ~]# cd statefulset/
# 创建工作目录

[root@k8s-master01 statefulset]# cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx  
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx    
  serviceName: nginx
  template: 
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates: 
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: nfs
      resources:
        requests:
          storage: 1Gi
[root@k8s-master01 statefulset]# kubectl apply -f statefulset.yaml 
service/nginx created
statefulset.apps/web created
# 创建statefulset以及对应的service

[root@k8s-master01 statefulset]# kubectl get pods
NAME                               READY   STATUS    RESTARTS       AGE
nfs-provisioner-747db885fd-phwm2   1/1     Running   4 (105m ago)   18h
web-0                              1/1     Running   0              39s
web-1                              1/1     Running   0              38s
[root@k8s-master01 statefulset]# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-claim1   Bound    pvc-b334c653-bb8b-4e48-8aa1-469f8ea90fb3   1Gi        RWX            nfs            18h
www-web-0     Bound    pvc-54ce83ca-698d-4c32-a0a2-1350f8717941   1Gi        RWO            nfs            88s
www-web-1     Bound    pvc-35c5949e-0227-4d8e-bdbb-02c1ba9ce488   1Gi        RWO            nfs            85s
[root@k8s-master01 statefulset]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pvc-35c5949e-0227-4d8e-bdbb-02c1ba9ce488   1Gi        RWO            Delete           Bound    default/www-web-1     nfs                     88s
pvc-54ce83ca-698d-4c32-a0a2-1350f8717941   1Gi        RWO            Delete           Bound    default/www-web-0     nfs                     91s
pvc-b334c653-bb8b-4e48-8aa1-469f8ea90fb3   1Gi        RWX            Delete           Bound    default/test-claim1   nfs                     18h
# 可以看到已经自动帮你创建了pv以及pvc
[root@k8s-master01 statefulset]# kubectl get pods -owide
NAME                               READY   STATUS    RESTARTS       AGE    IP              NODE         NOMINATED NODE   READINESS GATES
nfs-provisioner-747db885fd-phwm2   1/1     Running   4 (109m ago)   18h    10.244.58.203   k8s-node02   <none>           <none>
web-0                              1/1     Running   0              4m1s   10.244.58.204   k8s-node02   <none>           <none>
web-1                              1/1     Running   0              4m     10.244.85.242   k8s-node01   <none>           <none>
[root@k8s-master01 statefulset]# echo web-test-0 > /data/nfs_pro/default-www-web-0-pvc-54ce83ca-698d-4c32-a0a2-1350f8717941/index.html
[root@k8s-master01 statefulset]# echo web-test-1 > /data/nfs_pro/default-www-web-1-pvc-35c5949e-0227-4d8e-bdbb-02c1ba9ce488/index.html
[root@k8s-master01 statefulset]# curl 10.244.58.204
web-test-0
[root@k8s-master01 statefulset]# curl 10.244.85.242
web-test-1
# 测试成功,pod分别使用不同卷

[root@k8s-master01 statefulset]# kubectl run busybox --image docker.io/library/busybox:1.28  --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
If you don't see a command prompt, try pressing enter.
/ # nslookup nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      nginx
Address 1: 10.244.58.204 web-0.nginx.default.svc.cluster.local
Address 2: 10.244.85.242 web-1.nginx.default.svc.cluster.local
/ # exit
pod "busybox" deleted
# 因为ClusterIP设置为了None,所以解析出来是两个pod的地址

[root@k8s-master01 statefulset]# kubectl delete -f statefulset.yaml 
service "nginx" deleted
statefulset.apps "web" deleted
# 删除service以及statefulset

[root@k8s-master01 statefulset]# cat statefulset.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  selector:
    app: nginx  
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx    
  serviceName: nginx
  template: 
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates: 
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: nfs
      resources:
        requests:
          storage: 1Gi
[root@k8s-master01 statefulset]# kubectl apply -f statefulset.yaml 
service/nginx created
statefulset.apps/web created
# 删除clusterIP: None,也就是给一个ip给service看看会怎么样
[root@k8s-master01 statefulset]# kubectl run busybox --image docker.io/library/busybox:1.28  --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
If you don't see a command prompt, try pressing enter.
/ # nslookup nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      nginx
Address 1: 10.96.165.5 nginx.default.svc.cluster.local
/ # exit
pod "busybox" deleted
[root@k8s-master01 statefulset]# kubectl get svc -owide -l app=nginx
NAME    TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE   SELECTOR
nginx   ClusterIP   10.96.165.5   <none>        80/TCP    48s   app=nginx
# 可以看到解析出来是service的ip
StatefulSet总结:

1、Statefulset管理的pod,pod名字是有序的,由statefulset的名字-0、1、2这种格式组成

2、创建statefulset资源的时候,必须事先创建好一个service,如果创建的service没有ip,那对这个service做dns解析,会找到它所关联的pod ip,如果创建的service有ip,那对这个service做dns解析,会解析到service本身ip。

3、statefulset管理的pod,删除pod,新创建的pod名字跟删除的pod名字是一样的

4、statefulset具有volumeclaimtemplate这个字段,这个是卷申请模板,会自动创建pv,pvc也会自动生成,跟pv进行绑定,那如果创建的statefulset使用了volumeclaimtemplate这个字段,那创建pod,数据目录是独享的

5、ststefulset创建的pod,是域名的(域名组成:pod-name.svc-name.svc-namespace.svc.cluster.local)

StatefulSet管理pod-扩缩容和更新
[root@k8s-master01 statefulset]# cat statefulset.yaml |grep replicas:
  replicas: 3
[root@k8s-master01 statefulset]# kubectl apply -f statefulset.yaml 
service/nginx unchanged
statefulset.apps/web configured
[root@k8s-master01 statefulset]# kubectl get pods -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          43m
web-1   1/1     Running   0          43m
web-2   0/1     Pending   0          0s
web-2   0/1     Pending   0          0s
web-2   0/1     Pending   0          1s
web-2   0/1     ContainerCreating   0          1s
web-2   0/1     ContainerCreating   0          1s
web-2   1/1     Running             0          2s
# 直接修改yaml文件实现pod扩容

[root@k8s-master01 statefulset]# cat statefulset.yaml |grep replicas:
  replicas: 2
[root@k8s-master01 statefulset]# kubectl apply -f statefulset.yaml 
service/nginx unchanged
statefulset.apps/web configured
[root@k8s-master01 statefulset]# kubectl get pods -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          44m
web-1   1/1     Running   0          44m
web-2   1/1     Running   0          5s
web-2   1/1     Terminating   0          13s
web-2   1/1     Terminating   0          13s
web-2   0/1     Terminating   0          14s
web-2   0/1     Terminating   0          14s
web-2   0/1     Terminating   0          14s
^C[root@k8s-master01 statefulset]# kubectl get pods -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          45m
web-1   1/1     Running   0          45m
# 实现pod缩容
更新
[root@k8s-master01 statefulset]# kubectl explain statefulset.spec.updateStrategy.
# 查看帮助

[root@k8s-master01 statefulset]# cat statefulset.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  selector:
    app: nginx  
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  replicas: 3
  updateStrategy:
    rollingUpdate: 
      partition: 1
      # 意为只更新序号大于等于1的pod
      maxUnavailable: 0
      # 最多不可用pod数为0
  selector:
    matchLabels:
      app: nginx    
  serviceName: nginx
  template: 
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates: 
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: nfs
      resources:
        requests:
          storage: 1Gi
[root@k8s-master01 statefulset]# kubectl apply -f statefulset.yaml 
service/nginx unchanged
statefulset.apps/web configured
[root@k8s-master01 statefulset]# kubectl get pods -l app=nginx -w
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          17s
web-1   1/1     Running   0          15s
web-2   1/1     Running   0          14s
web-2   1/1     Terminating   0          24s
web-2   1/1     Terminating   0          24s
web-2   0/1     Terminating   0          25s
web-2   0/1     Terminating   0          25s
web-2   0/1     Terminating   0          25s
web-2   0/1     Pending       0          0s
web-2   0/1     Pending       0          0s
web-2   0/1     ContainerCreating   0          0s
web-2   0/1     ContainerCreating   0          0s
web-2   1/1     Running             0          1s
web-1   1/1     Terminating         0          27s
web-1   0/1     Terminating         0          28s
web-1   0/1     Terminating         0          28s
web-1   0/1     Terminating         0          28s
web-1   0/1     Pending             0          0s
web-1   0/1     Pending             0          0s
web-1   0/1     ContainerCreating   0          0s
web-1   0/1     ContainerCreating   0          0s
web-1   1/1     Running             0          2s
# 先从大的开始删(只测过一次,不确定)

需要注意rollingUpdate下的partition字段,整数类型,
如果是1,就代表只更新序号大于等于1的pod

测试OnDelete类型
[root@k8s-master01 statefulset]# cat statefulset.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  selector:
    app: nginx  
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  replicas: 3
  updateStrategy:
    type: OnDelete
  selector:
    matchLabels:
      app: nginx    
  serviceName: nginx
  template: 
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v2
        imagePullPolicy: IfNotPresent
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates: 
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: nfs
      resources:
        requests:
          storage: 1Gi
[root@k8s-master01 statefulset]# kubectl apply -f statefulset.yaml 
service/nginx unchanged
statefulset.apps/web configured
[root@k8s-master01 statefulset]# kubectl get pods -l app=nginx -w
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          2m30s
web-1   1/1     Running   0          2m
web-2   1/1     Running   0          2m2s
# 没有更新
[root@k8s-master01 statefulset]# kubectl delete pod web-0
pod "web-0" deleted
[root@k8s-master01 statefulset]# kubectl delete pod web-1
pod "web-1" deleted
[root@k8s-master01 statefulset]# kubectl delete pod web-2
pod "web-2" deleted
[root@k8s-master01 statefulset]# kubectl get pods -l app=nginx 
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          10s
web-1   1/1     Running   0          8s
web-2   1/1     Running   0          5s
# OnDelete类型必须要手动删除pod才会更新

[root@k8s-master01 statefulset]# kubectl delete -f statefulset.yaml 
service "nginx" deleted
statefulset.apps "web" deleted
# 清除环境

K8S控制器DaemonSet入门到企业实战应用

Daemonset控制器基本介绍

DaemonSet概述

DaemonSet控制器能够确保k8s集群所有的节点都运行一个相同的pod副本,当向k8s集群中增加node节点时,这个node节点也会自动创建一个pod副本,当node节点从集群移除,这些pod也会自动删除;删除Daemonset也会删除它们创建的pod

DaemonSet工作原理:如何管理Pod?

daemonset的控制器会监听kuberntes的daemonset对象、pod对象、node对象,这些被监听的对象之变动,就会触发syncLoop循环让kubernetes集群朝着daemonset对象描述的状态进行演进。

Daemonset具有实战应用场景分析

在集群的每个节点上运行存储,比如:glusterd 或 ceph。
在每个节点上运行日志收集组件,比如:flunentd 、 logstash、filebeat等。
在每个节点上运行监控组件,比如:Prometheus、 Node Exporter 、collectd等。

通过YAML文件创建Daemonset资源技巧
[root@k8s-master01 ~]# kubectl explain ds.
# 查看帮助
Daemonset实战: 部署收集日志组件
ctr -n k8s.io images import fluentd_2_5_1.tar.gz
# 所有节点导入镜像

[root@k8s-master01 ~]# kubectl describe node k8s-master01 |grep -i taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule
# 查看master节点污点
[root@k8s-master01 ~]# mkdir daemonset
[root@k8s-master01 ~]# cd daemonset/
# 创建工作目录

[root@k8s-master01 daemonset]# cat daemonset.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: xianchao/fluentd:v2.5.1
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
          limits:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          readOnly: true
        - name: varlibcontainerdiocontainerdgrpcv1cricontainers
          mountPath: /var/lib/containerd/io.containerd.grpc.v1.cri/containers
          readOnly: true
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibcontainerdiocontainerdgrpcv1cricontainers
        hostPath:
          path: /var/lib/containerd/io.containerd.grpc.v1.cri/containers
          # 这个目录自己琢磨了一下,应该存放的是containerd的运行中容器状态
[root@k8s-master01 daemonset]# kubectl apply -f daemonset.yaml 
daemonset.apps/fluentd-elasticsearch created

[root@k8s-master01 daemonset]# kubectl get ds -n kube-system -l k8s-app=fluentd-logging
NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluentd-elasticsearch   3         3         3       3            3           <none>          94s
[root@k8s-master01 daemonset]# kubectl get pods -n kube-system -l name=fluentd-elasticsearch -owide
NAME                          READY   STATUS    RESTARTS   AGE     IP              NODE           NOMINATED NODE   READINESS GATES
fluentd-elasticsearch-482h6   1/1     Running   0          3m18s   10.244.85.255   k8s-node01     <none>           <none>
fluentd-elasticsearch-5hscz   1/1     Running   0          3m17s   10.244.58.217   k8s-node02     <none>           <none>
fluentd-elasticsearch-jjf8w   1/1     Running   0          3m17s   10.244.32.161   k8s-master01   <none>           <none>
# 可以看到已经部署成功
Daemonset管理Pod: 动态更新和回滚
[root@k8s-master01 statefulset]# kubectl explain ds.spec.updateStrategy.rollingUpdate.
# 查看帮助

[root@k8s-master01 daemonset]# kubectl set image daemonsets fluentd-elasticsearch fluentd-elasticsearch=ikubernetes/filebeat:5.6.6-alpine -n kube-system
daemonset.apps/fluentd-elasticsearch image updated
# 这个镜像启动pod会有问题,主要是演示daemonset如何在命令行更新pod

[root@k8s-master01 daemonset]# kubectl rollout history daemonset fluentd-elasticsearch -n kube-system
daemonset.apps/fluentd-elasticsearch 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

[root@k8s-master01 daemonset]# kubectl -n kube-system rollout undo daemonset fluentd-elasticsearch --to-revision=1
daemonset.apps/fluentd-elasticsearch rolled back
# 回滚
[root@k8s-master01 daemonset]# kubectl get pods -n kube-system -l name=fluentd-elasticsearch -owide
NAME                          READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
fluentd-elasticsearch-cm55l   1/1     Running   0          16m   10.244.58.214   k8s-node02     <none>           <none>
fluentd-elasticsearch-lxmd8   1/1     Running   0          13s   10.244.32.164   k8s-master01   <none>           <none>
fluentd-elasticsearch-x5jrc   1/1     Running   0          16m   10.244.85.193   k8s-node01     <none>           <none>
# 状态正常

[root@k8s-master01 daemonset]# kubectl delete -f daemonset.yaml 
daemonset.apps "fluentd-elasticsearch" deleted
# 清除环境

K8S配置管理中心ConfigMap实现微服务配置管理

配置管理中心Configmap基本介绍

Configmap是k8s中的资源对象,用于保存非机密性的配置的,数据可以用key/value键值对的形式保存,也可通过文件的形式保存。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. configmap是k8s的资源,相当于配置文件,可以有一个或者多个configmap;
  2. configmap可以做成volume,k8s pod启动后,通过volume挂载到容器内部指定目录;
  3. 容器内部应用按照原有方式读取特定目录上的配置文件;
  4. 在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入.
Configmap具体实战应用场景分析

集群跑着服务,像nginx,tomcat,mysql,突然资源不够用了,需要加机器,加机器的话又要更新配置,一个一个修改很麻烦,这时候就有configmap,可以把配置信息之类的存在configmap,通过volume卷挂载进去

Configmap注入方式有两种: 一种是将configmap作为存储卷,一种是将configmap通过env中configMapKeyRef注入到容器中

使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中心单独一份配置的话,那么更新配置很麻烦,使用configmap可以友好的进行配置共享

configmap局限性

configmap设计上不是用来保存大量数据的,保存在configmap中的数据不能超过1MiB,如果你需要保存超过此尺寸限制的数据,可以考虑挂载存储卷或者使用独立数据库或文件服务

创建configmap的第一种方案: 指定参数
[root@k8s-master01 ~]# kubectl create cm --help
[root@k8s-master01 ~]# kubectl create cm --help |grep '\-\-from\-literal=\[]' -A1
    --from-literal=[]:
	Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)
# 查看帮助

[root@k8s-master01 ~]# kubectl create cm tomcat-config --from-literal=tomcat-port=8080 --from-literal=tomcat-server_name=myapp.tomcat.com
configmap/tomcat-config created
[root@k8s-master01 ~]# kubectl describe cm tomcat-config
Name:         tomcat-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
tomcat-server_name:
----
myapp.tomcat.com
tomcat-port:
----
8080

BinaryData
====

Events:  <none>
# 创建一个名为tomcat-config的cm
创建configmap的第二种方案: 指定文件
[root@k8s-master01 ~]# kubectl create cm www-nginx --from-file=www=./nginx.conf 
configmap/www-nginx created
[root@k8s-master01 ~]# kubectl describe cm www-nginx
Name:         www-nginx
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
www:
# 这里是--from-file后面那个参数定义的
----
server {
  server_name www.nginx.com;
  listen 80;
  root /home/nginx/www/
}


BinaryData
====

Events:  <none>
[root@k8s-master01 ~]# kubectl describe cm www-nginx-1
Name:         www-nginx-1
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx.conf:
# 如果不写的话就是文件名
----
server {
  server_name www.nginx.com;
  listen 80;
  root /home/nginx/www/
}


BinaryData
====

Events:  <none>
创建configmap的第三种方案: 指定文件夹
[root@k8s-master01 ~]# mkdir configmap
[root@k8s-master01 ~]# cd configmap/
[root@k8s-master01 configmap]# mv ../nginx.conf ./
[root@k8s-master01 configmap]# mkdir test-a
[root@k8s-master01 configmap]# cd test-a/
[root@k8s-master01 test-a]# echo server-id=1 > my-server.cnf 
[root@k8s-master01 test-a]# echo server-id=2 > my-slave.cnf
[root@k8s-master01 test-a]# kubectl create cm mysql-config --from-file=/root/configmap/test-a/
configmap/mysql-config created
# 通过目录创建configmap
[root@k8s-master01 test-a]# kubectl describe cm mysql-config 
Name:         mysql-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
my-server.cnf:
----
server-id=1

my-slave.cnf:
----
server-id=2


BinaryData
====

Events:  <none>
通过YAML文件创建configmap技巧
[root@k8s-master01 test-a]# cd ..
[root@k8s-master01 configmap]# kubectl explain cm.
# 查看帮助

[root@k8s-master01 configmap]# cat mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  master.cnf: |
    [mysqld]
    log-bin
    log_bin_trust_function_creators=1
    lower_case_table_names=1
  slave.cnf: |
    [mysqld]
    super-read-only
    log_bin_trust_function_creators=1
# 对于多行数据|必须要加,这代表多行字符串保留为单个字符串
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 
configmap/mysql created
[root@k8s-master01 configmap]# kubectl describe cm mysql
Name:         mysql
Namespace:    default
Labels:       app=mysql
Annotations:  <none>

Data
====
master.cnf:
----
[mysqld]
log-bin
log_bin_trust_function_creators=1
lower_case_table_names=1

slave.cnf:
----
[mysqld]
super-read-only
log_bin_trust_function_creators=1


BinaryData
====

Events:  <none>
[root@k8s-master01 configmap]# kubectl delete -f mysql-configmap.yaml 
configmap "mysql" deleted
# 删除cm

注意:

多行数据必须要加 “|”

使用cm第一种方式: ConfigMapKeyRef
[root@k8s-master01 configmap]# cat mysql-configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 
configmap/mysql created
# 创建cm

[root@k8s-master01 configmap]# cat mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
spec:
  containers:
  - name: mysql
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 3600"]
    env:
    - name: log-bin
    # 指定环境变量名字
      valueFrom:
        configMapKeyRef:
          name: mysql
          # 指定cm的名字
          key: log
          # 指定cm中的key
    - name: lower
      valueFrom:
        configMapKeyRef:
          name: mysql
          key: lower
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod.yaml
pod/mysql-pod created

[root@k8s-master01 configmap]# kubectl exec -it mysql-pod -c mysql -- /bin/sh
/ # printenv 
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=mysql-pod
SHLVL=1
HOME=/root
NGINX_PORT_80_TCP=tcp://10.100.169.159:80
TERM=xterm
lower=1
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_SERVICE_HOST=10.100.169.159
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
NGINX_SERVICE_PORT=80
NGINX_PORT=tcp://10.100.169.159:80
log-bin=1
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
NGINX_SERVICE_PORT_WEB=80
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
NGINX_PORT_80_TCP_ADDR=10.100.169.159
NGINX_PORT_80_TCP_PORT=80
NGINX_PORT_80_TCP_PROTO=tcp
/ # exit
# 查看环境变量

[root@k8s-master01 configmap]# kubectl delete -f mysql-pod.yaml 
pod "mysql-pod" deleted
# 清除环境
使用configmap第二种方式: envFrom
[root@k8s-master01 configmap]# cat mysql-pod-envfrom.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-envfrom
spec:
  containers:
  - name: mysql
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 3600"]
    envFrom:
    - configMapRef: 
        name: mysql
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-envfrom.yaml 
pod/mysql-pod-envfrom created
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-envfrom -c mysql -- /bin/sh
/ # printenv 
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=mysql-pod-envfrom
SHLVL=1
HOME=/root
TERM=xterm
lower=1
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
log=1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
/ # exit
# 查看环境变量

[root@k8s-master01 configmap]# kubectl delete -f mysql-pod-envfrom.yaml 
pod "mysql-pod-envfrom" deleted
# 清除环境
使用configmap第三种方式: volume
[root@k8s-master01 configmap]# cat mysql-configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"
  my.cnf: |
    [mysqld]
    Welcome=yuhang
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 
configmap/mysql configured
# 更新cm

[root@k8s-master01 configmap]# cat mysql-pod-volume.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-volume
spec:
  containers:
  - name: mysql
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 3600"]
    volumeMounts:
    - name: mysql-config
      mountPath: /tmp/config
  volumes:
  - name: mysql-config
    configMap:
      name: mysql
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-volume.yaml 
pod/mysql-pod-volume created
# 创建pod

[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -c mysql -- /bin/sh
/ # cd /tmp/config/
/tmp/config # ls
log     lower   my.cnf
/tmp/config # cat log
1/tmp/config # cat lower
1/tmp/config # cat my.cnf
[mysqld]
Welcome=yuhang
/tmp/config # exit
# 查看挂载目录下文件内容
Configmap热加载: 自动更新配置
[root@k8s-master01 configmap]# kubectl edit cm mysql
data:
  log: "2"
  # 修改log值为2
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -c mysql -- /bin/sh
/ # cd /tmp/config/
/tmp/config # cat log
2/tmp/config # exit
# 有时候没改过来可能是还在改,过一会再看看

[root@k8s-master01 configmap]# kubectl delete -f mysql-pod-volume.yaml 
pod "mysql-pod-volume" deleted
# 清除环境

nfigmap]# kubectl delete -f mysql-pod-envfrom.yaml
pod “mysql-pod-envfrom” deleted

清除环境


#### 使用configmap第三种方式: volume

```shell
[root@k8s-master01 configmap]# cat mysql-configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"
  my.cnf: |
    [mysqld]
    Welcome=yuhang
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 
configmap/mysql configured
# 更新cm

[root@k8s-master01 configmap]# cat mysql-pod-volume.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-volume
spec:
  containers:
  - name: mysql
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 3600"]
    volumeMounts:
    - name: mysql-config
      mountPath: /tmp/config
  volumes:
  - name: mysql-config
    configMap:
      name: mysql
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-volume.yaml 
pod/mysql-pod-volume created
# 创建pod

[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -c mysql -- /bin/sh
/ # cd /tmp/config/
/tmp/config # ls
log     lower   my.cnf
/tmp/config # cat log
1/tmp/config # cat lower
1/tmp/config # cat my.cnf
[mysqld]
Welcome=yuhang
/tmp/config # exit
# 查看挂载目录下文件内容
Configmap热加载: 自动更新配置
[root@k8s-master01 configmap]# kubectl edit cm mysql
data:
  log: "2"
  # 修改log值为2
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -c mysql -- /bin/sh
/ # cd /tmp/config/
/tmp/config # cat log
2/tmp/config # exit
# 有时候没改过来可能是还在改,过一会再看看

[root@k8s-master01 configmap]# kubectl delete -f mysql-pod-volume.yaml 
pod "mysql-pod-volume" deleted
# 清除环境

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

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

相关文章

从0到0.01入门React | 005.精选 React 面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

快速批量去除文件夹名称中多余重复文字!一键轻松优化文件夹命名!

您是否曾经因为文件夹名称中多余重复文字而烦恼&#xff1f;是否因为文件夹重命名而浪费大量时间&#xff1f;现在&#xff0c;我们为您推荐一款全新的文件夹批量改名工具——快速批量去除文件夹名称中多余重复文字&#xff0c;轻松实现文件夹改名优化&#xff0c;让您的整理效…

企业微信后台通过小程序给员工发送文字信息附带超链接实现(加上A标签:<a href=“网址“> </a>)

如下&#xff0c;在编辑文本消息的时候&#xff0c;添加上HTML的A标签 <a href"www.baidu"> </a>即可实现点击直接跳转

移远EC600U-CN开发板 day04

控件探索-滑杆&#xff08;lv.slider&#xff09; 1. 显示一个简单的滑杆 def slider_event_cb(evt): slider evt.get_target()# 修改label的值label.set_text(str(slider.get_value()))slider lv.slider(scr) #创建滑杆组件 slider.set_width(200) #设置滑杆宽…

上门洗衣洗鞋app小程序

上门洗衣洗鞋app小程序作为专业的帮助用户洗衣服务的软件,许多朋友都使用过。在这里,小编就帮助大家收集一些非常不错的洗衣洗鞋软件。 不知道大家是否还在为洗衣而烦恼,而怕麻烦,现在大家都在用网上的洗衣洗鞋小程序来洗衣服,用户只需要打开手机软件,发起订单,门店即可收到订单…

Flink SQL --命令行的使用(02)

1、窗口函数&#xff1a; 1、创建表&#xff1a; -- 创建kafka 表 CREATE TABLE bid (bidtime TIMESTAMP(3),price DECIMAL(10, 2) ,item STRING,WATERMARK FOR bidtime AS bidtime ) WITH (connector kafka,topic bid, -- 数据的topicproperties.bootstrap.servers m…

产品速递 | 璞华采云端,打造降本增效的企业采购订单协同平台

为应对快速变化的市场环境&#xff0c;企业需要建立起更加敏捷、灵活的采购体系&#xff0c;利用数字化手段提高工作效率、降低潜在风险&#xff0c;将是企业构筑新时代竞争壁垒的关键要素。 而控制采购成本对一个企业的经营业绩至关重要。采购成本下降不仅体现在企业现金流出的…

正交试验DOE

它原本是日本学者为了质量管理而设计的试验。后来被用在算法的参数设计上&#xff0c;可以利用部分的试验确定出最合理的参数组合。 举个例子&#xff0c;比如遗传算法中的种群数pop&#xff0c;交叉概率pr&#xff0c;变异概率pm&#xff0c;以及迭代次数N&#xff0c;每个参…

字符串和内存函数(1)

文章目录 目录1. 前言2. 函数介绍2.1 strlen2.2 strcpy2.3 strcat2.4 strcmp2.5 strncpy2.6 strncat2.7 strncmp2.8 strstr2.9 strtok2.10 strerror2.11 字符分类函数2.12 字符转换函数 目录 求字符串长度函数长度不受限制的字符串函数长度受限制的字符串函数字符串查找函数错…

1.0.0 IGP高级特性简要介绍(OSPF-下篇)

二、OSPF_精细的路由控制 1.OSPF数据库上限 简介 ​ OSPF技术要求同一个区域内的路由器保存着相同的LSDB信息。 ​ 但随着网络上路由数量不断增加&#xff0c;一些路由器由于系统资源有限&#xff0c;不能再承载如此多的路由信息&#xff0c;这种状态就被称为数据库超限&am…

蓝桥杯每日一题2023.11.13

题目描述 蓝桥杯大赛历届真题 - C 语言 B 组 - 蓝桥云课 (lanqiao.cn) 题目分析 由于每次吹灭的蜡烛与年龄相同故我们想到使用前缀和可以让我们求出各个区间的和&#xff0c;我们将每个区间都枚举一遍&#xff0c;如果符合要求就输出区间开始的位置&#xff08;答案&#xff…

基于GoogleNet深度学习网络的花朵类型识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. GoogleNet网络结构 4.2. 基于GoogleNet的花朵类型识别 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .............................…

sql查询查看数据库空间使用情况

SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)", D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)", TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),990.99) || % "使…

Ansys Electronics Desktop仿真——HFSS线圈寄生电阻,电感

利用ANSYS Electronics Desktop&#xff0c;可在综合全面、易于使用的设计平台中集成严格的电磁场分析和系统电路仿真。按需求解器技术让您能集成电磁场仿真器和电路及系统级仿真&#xff0c;以探索完整的系统性能。 HFSS&#xff08;High Frequency Structure Simulator&#…

如何使用软路由R4S+iStoreOS实现远程访问内网电脑桌面

软路由R4SiStoreOS实现公网远程桌面局域网内电脑 文章目录 软路由R4SiStoreOS实现公网远程桌面局域网内电脑简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 上篇教程我们介绍了如何在iStoreOS中安装Cpolar&#xff0…

RE切入点:选择SLI,设定SLO

还是先来复习下上节课讲的“系统可用性”的两种计算方式&#xff0c;一种是从故障角度出发&#xff0c;以时长维度对系统进行稳定性评估&#xff1b;另一种是从成功请求占比角度出发&#xff0c;以请求维度对系统进行稳定性评估。同时&#xff0c;我们还讲到&#xff0c;在 SRE…

Layer 2 真的为以太坊扩容了吗?

构建一个安全、对用户友好的去中心化网络的愿景&#xff0c;依赖于关键基础设施的发展。这个愿景由一个共享的经济框架支持&#xff0c;得到了亿万人的拥护。Layer 2 的扩展解决方案在构建这一基础和增强以太坊的能力方面起着至关重要的作用。这些项目相互协作&#xff0c;形成…

cpcd 使用

cpcd 是支持多协议融合的一种解决方案&#xff0c;应用场景是一个无线模块支持大于一种协议栈&#xff0c;通过cpcd 可以分发不同协议&#xff0c;使用说明主要查看readme.md 文件说明 编译 使用cpcd 4.3.2 提示需要安装mbedtls 编译成功了 运行 关闭加密&#xff0c;通信…

STM32GPIO——上拉、下拉电阻

如上两个图所示&#xff0c;标号2都为上拉、下拉电阻部分&#xff0c;阻值约为30k~50k欧&#xff0c;通过对应开关进行控制&#xff0c;开关由寄存器控制。 当引脚外部的器件没有干扰引脚的电压时&#xff0c;即没有外部的上、下拉电压&#xff0c;引脚的电平由引脚内部上、下…
最新文章