zoukankan      html  css  js  c++  java
  • kubernetes之PV及PVC案例

    kubernetes之PV及PVC案例

    概念

    默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题,第一:当容器挂掉kubelet将重启启动它时,文件将会丢失;第二:当Pod中同时运行多个容器,容器之间需要共享文件时,Kubernetes的Volume解决了这两个问题

    官方文档
    https://kubernetes.io/zh/docs/concepts/storage/

    PersistentVolume(PV)是集群中已由管理员配置的一段网络存储,集群中的存储资源就像一个node节点是一个集群资源,PV是诸如卷之类的卷插件,但是具有独立于使用PV的任何单个pod的生命周期, 该API对象捕获存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统,PV是由管理员添加的的一个存储的描述,是一个全局资源即不隶属于任何namespace,包含存储的类型,存储的大小和访问模式等,它的生命周期独立于Pod,例如当使用它的Pod销毁时对PV没有影响。
    
    PersistentVolumeClaim(PVC)是用户存储的请求,它类似于pod,Pod消耗节点资源,PVC消耗存储资源, 就像pod可以请求特定级别的资源(CPU和内存),PVC是namespace中的资源,可以设置特定的空间大小和访问模式。
    
    kubernetes 从1.0版本开始支持PersistentVolume和PersistentVolumeClaim。
    
    PV是对底层网络存储的抽象,即将网络存储定义为一种存储资源,将一个整体的存储资源拆分成多份后给不同的业务使用。
    
    PVC是对PV资源的申请调用,就像POD消费node节点资源一样,pod是通过PVC将数据保存至PV,PV在保存至存储。
    

    PersistentVolume参数

    # kubectl explain PersistentVolume
    
    Capacity: #当前PV空间大小,kubectl explain PersistentVolume.spec.capacity
    
    accessModes :访问模式,#kubectl explain PersistentVolume.spec.accessModes
        ReadWriteOnce – PV只能被单个节点以读写权限挂载,RWO
        ReadOnlyMany – PV以可以被多个节点挂载但是权限是只读的,ROX
        ReadWriteMany – PV可以被多个节点是读写方式挂载使用,RWX
    
    persistentVolumeReclaimPolicy #删除机制即删除存储卷时候,已经创建好的存储卷由以下删除操作:
    #kubectl explain PersistentVolume.spec.persistentVolumeReclaimPolicy
        Retain – 删除PV后保持原装,最后需要管理员手动删除
        Recycle – 空间回收,及删除存储卷上的所有数据(包括目录和隐藏文件),目前仅支持NFS和hostPath
        Delete – 自动删除存储卷
    
    volumeMode #卷类型,kubectl explain PersistentVolume.spec.volumeMode
        定义存储卷使用的文件系统是块设备还是文件系统,默认为文件系统
    
    mountOptions #附加的挂载选项列表,实现更精细的权限控制
        ro #等
    

    官方提供的基于各后端存储创建的PV支持的访问模式
    https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options

    PersistentVolume参数

    #kubectl explain PersistentVolumeClaim.
    
    accessModes :PVC 访问模式,#kubectl explain PersistentVolumeClaim.spec.volumeMode
        ReadWriteOnce – PVC只能被单个节点以读写权限挂载,RWO
        ReadOnlyMany – PVC以可以被多个节点挂载但是权限是只读的,ROX
        ReadWriteMany – PVC可以被多个节点是读写方式挂载使用,RWX
    
    resources: #定义PVC创建存储卷的空间大小
    
    selector: #标签选择器,选择要绑定的PV
        matchLabels #匹配标签名称
        matchExpressions #基于正则表达式匹配
    
    volumeName #要绑定的PV名称
    
    volumeMode #卷类型
        定义PVC使用的文件系统是块设备还是文件系统,默认为文件系统
    

    运行java应用Jenkins

    基于java命令,运行java war包或jar包,本次以jenkins.war 包部署方式为例,且要求jenkins的数据保存至外部存储(NFS或者PVC),其他java应用看实际需求是否需要将数据保存至外部存储

    下载Jenkins War包

    https://www.jenkins.io/download/

    root@master1:/opt/data/dockerfile/web/jevon/jenkins# ls
    Dockerfile  jenkins-2.222.1.war
    

    镜像目录文件

    root@master1:/opt/data/dockerfile/web/jevon/jenkins# tree
    .
    ├── build-command.sh
    ├── Dockerfile
    ├── jenkins-2.222.1.war
    └── run_jenkins.sh
    
    0 directories, 4 files
    

    Dockerfile

    root@master1:/opt/data/dockerfile/web/jevon/jenkins# cat Dockerfile 
    FROM harbor.linux.com/webimages/jdk-base:v8.212
    
    MAINTAINER Jevonwei jevonran@163.com
    
    RUN mkdir /apps/jenkins -p
    ADD jenkins-2.222.1.war /apps/jenkings/
    ADD run_jenkins.sh /usr/bin/
    
    EXPOSE 8080
    
    CMD ["/usr/bin/run_jenkins.sh"]
    

    run_jenkins.sh

    root@master1:/opt/data/dockerfile/web/jevon/jenkins# cat run_jenkins.sh 
    #! /bin/bash
    cd /apps/jenkins && java -server -Xms1024m -Xmx1024m -Xss512K -jar jenkins-2.222.1.war --webroot=/apps/jenkins/jenkins-data --httpPort=8080
    
    root@master1:/opt/data/dockerfile/web/pub-images/jenkins# chmod a+x run_jenkins.sh
    

    build-command.sh

    root@master1:/opt/data/dockerfile/web/jevon/jenkins# cat build-command.sh 
    #!/bin/bash
    docker build -t harbor.linux.com/danran/jenkins:v2.222.1 .
    sleep 1
    docker push harbor.linux.com/danran/jenkins:v2.222.1
    

    构建镜像

    root@master1:/opt/data/dockerfile/web/jevon/jenkins# bash build-command.sh 
    Sending build context to Docker daemon  66.29MB
    Step 1/7 : FROM harbor.linux.com/webimages/jdk-base:v8.212
     ---> b2a21bae10f4
    Step 2/7 : MAINTAINER Jevonwei jevonran@163.com
     ---> Running in b58233826de9
    Removing intermediate container b58233826de9
     ---> 56998928e055
    Step 3/7 : RUN mkdir /apps/jenkins -p
     ---> Running in 7d61ce262f02
    Removing intermediate container 7d61ce262f02
     ---> f3ac8e57dde0
    Step 4/7 : ADD jenkins-2.222.1.war /apps/jenkins/
     ---> 0ef8fb2eeb92
    Step 5/7 : ADD run_jenkins.sh /usr/bin/
     ---> 29cb2aa6ca79
    Step 6/7 : EXPOSE 8080
     ---> Running in 26d431e39c5a
    Removing intermediate container 26d431e39c5a
     ---> 3a6a89c04f46
    Step 7/7 : CMD ["/usr/bin/run_jenkins.sh"]
     ---> Running in 8f05103b2a30
    Removing intermediate container 8f05103b2a30
     ---> 5e0134545cb2
    Successfully built 5e0134545cb2
    Successfully tagged harbor.linux.com/danran/jenkins:v2.222.1
    The push refers to repository [harbor.linux.com/danran/jenkins]
    a8612df0a8b6: Pushed 
    b9bfd2cf304d: Pushed 
    cc45b9ed58cf: Pushed 
    9f96344cfb8b: Mounted from danran/tomcat-app1 
    519b1d12005c: Mounted from danran/tomcat-app1 
    1d12abb2850e: Mounted from danran/tomcat-app1 
    23a3090b0538: Mounted from danran/nginx-web1 
    45d27d00345a: Mounted from danran/nginx-web1 
    6f12928590f2: Mounted from danran/nginx-web1 
    25cbc4e383db: Mounted from danran/tomcat-app1 
    9dd0e608b4ce: Mounted from danran/tomcat-app1 
    6d161c41a7f7: Mounted from danran/nginx-web1 
    034f282942cd: Mounted from danran/nginx-web1 
    v2.222.1: digest: sha256:bec9583ffc5be0a4b142dba67b6f43bec319a0781012bb172d13b28d34b13e52 size: 3041
    
    验证jenkins镜像
    root@master1:~# docker run -it --rm -p 8081:8080 harbor.linux.com/danran/jenkins:v2.222.1
    

    创建PV/PVC

    需要两个PVC,一个保存jenkins的数据,一个保存.jenkins的数据

    PV使用NFS存储挂载,请提前确保/data/k8sdata/danran NFS共享目录可挂载

    root@master1:~# showmount -e 10.203.104.30
    Export list for 10.203.104.30:
    /data/k8sdata       *
    
    PV

    jenkins-persistentvolume.yaml

    root@master1:/opt/data/yaml/danran/jenkins# cat jenkins-persistentvolume.yaml 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: jenkins-datadir-pv
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/jenkins-data
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: jenkins-root-datadir-pv
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/zookeeper-root-data
    

    创建PV

    root@master1:/opt/data/yaml/danran/jenkins# kubectl apply -f jenkins-persistentvolume.yaml 
    persistentvolume/jenkins-datadir-pv created
    persistentvolume/jenkins-root-datadir-pv created
    

    验证PV

    root@master1:/opt/data/yaml/danran/jenkins# kubectl get pv
    NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                            STORAGECLASS   REASON   AGE
    jenkins-datadir-pv           20Gi       RWO            Retain           Available                                                            43s
    jenkins-root-datadir-pv   20Gi       RWO            Retain           Available                                                            43
    
    PVC

    jenkins-persistentvolumeclaim.yaml

    root@master1:/opt/data/yaml/danran/jenkins# cat jenkins-persistentvolumeclaim.yaml 
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: jenkins-datadir-pvc
      namespace: danran
    spec:
      accessModes:
        - ReadWriteOnce
      volumeName: jenkins-datadir-pv
      resources: 
        requests:
          storage: 10Gi
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: jenkins-root-data-pvc
      namespace: danran
    spec:
      accessModes:
        - ReadWriteOnce
      volumeName: jenkins-root-datadir-pv
      resources: 
        requests:
          storage: 10Gi
    

    创建PVC

    root@master1:/opt/data/yaml/danran/jenkins# kubectl apply -f jenkins-persistentvolumeclaim.yaml 
    persistentvolumeclaim/jenkins-datadir-pvc created
    persistentvolumeclaim/jenkins-root-data-pvc created
    

    验证PVC

    root@master1:/opt/data/yaml/danran/jenkins# kubectl get pv
    NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                            STORAGECLASS   REASON   AGE
    jenkins-datadir-pv           20Gi       RWO            Retain           Bound    danran/jenkins-datadir-pvc                               6m13s
    jenkins-root-datadir-pv   20Gi       RWO            Retain           Bound    danran/jenkins-root-data-pvc                             6m13s
    
    root@master1:/opt/data/yaml/danran/jenkins# kubectl get pvc -n danran
    NAME                      STATUS   VOLUME                    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    jenkins-datadir-pvc         Bound    jenkins-datadir-pv          20Gi       RWO                           2m28s
    jenkins-root-data-pvc     Bound    jenkins-root-datadir-pv   20Gi       RWO                           2m28s
    

    yaml文件

    root@master1:/opt/data/yaml/danran/jenkins# cat jenkins.yaml 
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        app: danran-jenkins
      name: danran-jenkins-deployment 
      namespace: danran
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: danran-jenkins
      template:
        metadata:
          labels:
            app: danran-jenkins
        spec:
          containers:
          - name: danran-jenkins-container
            image: harbor.linux.com/danran/jenkins:v2.222.1
            #imagePullPolicy: IfNotPresent
            imagePullPolicy: Always
            ports:
            - containerPort: 8080
              protocol: TCP
              name: http
            volumeMounts:
              - mountPath: "/apps/jenkins/jenkins-data/"
                name: jenkins-datadir-danran
              - mountPath: "/root/.jenkins"
                name: jenkins-root-datadir
          volumes:
          - name: jenkins-datadir-danran
            persistentVolumeClaim:
              claimName: jenkins-datadir-pvc
          - name: jenkins-root-datadir
            persistentVolumeClaim:
              claimName: jenkins-root-data-pvc
    
    ---
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: danran-jenkins
      name: danran-nginx-service
      namespace: danran
    spec:
      type: NodePort
      ports:
      - name: http
        port: 80
        protocol: TCP
        targetPort: 8080
        nodePort: 38080
      selector:
        app: danran-jenkins
    

    创建Pod

    root@master1:/opt/data/yaml/danran/jenkins# kubectl apply -f jenkins.yaml 
    deployment.apps/danran-jenkins-deployment created
    service/danran-nginx-service created
    

    验证Pod

    root@master1:~# kubectl get pod -n danran
    NAME                                                                                READY    STATUS    RESTARTS   AGE
    danran-jenkins-deployment-788fd6d64f-n86cz             1/1          Running   0                 12s
    

    web 登录测试

    http://10.203.104.28:38080/

    在pod中查看AdminPassword

    [root@danran-jenkins-deployment-788fd6d64f-n86cz /]# cat /root/.jenkins/secrets/initialAdminPassword
    30a2d1a3a59a4d3dbf9e3ab598cfd099
    

    将AdminPassword填入web,登录

    实战案例之Redis 服务

    http://download.redis.io/releases/redis-4.0.14.tar.gz

    构建redis镜像

    镜像文件结构
    root@master1:/opt/data/dockerfile/web/jevon/redis# tree
    .
    ├── build-command.sh
    ├── Dockerfile
    ├── redis-4.0.14.tar.gz
    ├── redis.conf
    └── run_redis.sh
    
    0 directories, 5 files
    
    Dockerfile
    root@master1:/opt/data/dockerfile/web/jevon/redis# cat Dockerfile 
    FROM harbor.linux.com/baseimages/centos-jevon-base:7.7.1908
    
    MAINTAINER JevonWei "jevonran@163.com"
    
    ADD redis-4.0.14.tar.gz /usr/local/src/
    RUN ln -sv /usr/local/src/redis-4.0.14 /usr/local/redis && cd /usr/local/redis && make && cp src/redis-cli /usr/sbin/ && cp src/redis-server /usr/sbin/ && mkdir -pv /data/redis-data && mkdir -pv /var/log/redis/
    ADD redis.conf /usr/local/redis/redis.conf
    ADD run_redis.sh /usr/local/redis/run_redis.sh
    
    EXPOSE 6379
    
    CMD ["/usr/local/redis/run_redis.sh"]
    
    编辑redis.conf
    修改redis.conf配置文件的以下选项 
    root@master1:/opt/data/dockerfile/web/jevon/redis# cat redis.conf
    bind 0.0.0.0
    save 900 1
    save 5 1
    save 300 10
    
    dir /data/redis-data
    requirepass danran
    
    run_redis.sh
    root@master1:/opt/data/dockerfile/web/jevon/redis# cat run_redis.sh 
    #!/bin/bash
    
    /usr/sbin/redis-server /usr/local/redis/redis.conf
    tail -f /etc/hosts
    
    build-command.sh
    root@master1:/opt/data/dockerfile/web/jevon/redis# cat build-command.sh 
    #!/bin/bash
    TAG=$1
    docker build -t harbor.linux.com/danran/redis:${TAG} .
    sleep 1
    docker push  harbor.linux.com/danran/redis:${TAG}
    
    构建镜像
    root@master1:/opt/data/dockerfile/web/jevon/redis# bash build-command.sh v1
    

    运行redis服务

    创建PV与PVC
    PV

    jenkins-persistentvolume.yaml

    root@master1:/opt/data/yaml/danran/redis# cat redis-persistentvolume.yaml 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: redis-datadir-pv-1
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/redis-datadir
    

    创建PV

    root@master1:/opt/data/yaml/danran/redis# kubectl apply -f redis-persistentvolume.yaml 
    persistentvolume/redis-datadir-pv created
    
    PVC

    redis-persistentvolumeclaim.yaml

    root@master1:/opt/data/yaml/danran/redis# cat redis-persistentvolumeclaim.yaml 
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: redis-datadir-pvc
      namespace: danran
    spec:
      accessModes:
        - ReadWriteOnce
      volumeName: redis-datadir-pv-1
      resources: 
        requests:
          storage: 10Gi
    

    创建PVC

    root@master1:/opt/data/yaml/danran/redis# kubectl apply -f redis-persistentvolumeclaim.yaml 
    persistentvolumeclaim/redis-datadir-pvc created
    
    验证PV/PVC
    root@master1:/opt/data/yaml/danran/redis# kubectl get pv
        NAME                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                            STORAGECLASS   REASON   AGE
    redis-datadir-pv-1        20Gi       RWO            Retain           Bound    danran/redis-datadir-pvc                                 5m36s
    
    root@master1:/opt/data/yaml/danran/redis# kubectl get pvc -n danran
    NAME                            STATUS   VOLUME                    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    redis-datadir-pvc         Bound    redis-datadir-pv-1        20Gi       RWO                           11m
    
    yaml文件
    root@master1:/opt/data/yaml/danran/redis# cat redis.yaml 
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        app: devops-redis
      name: deploy-devops-redis
      namespace: danran
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: devops-redis
      template:
        metadata:
          labels:
            app: devops-redis
        spec:
          containers:
          - name: redis-container
            image: harbor.linux.com/danran/redis:v1
            #imagePullPolicy: IfNotPresent
            imagePullPolicy: Always
            volumeMounts:
              - mountPath: "/data/redis-data"
                name: redis-datadir
          volumes:
          - name: redis-datadir
            persistentVolumeClaim:
              claimName: redis-datadir-pvc
    
    ---
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: devops-redis
      name: srv-devops-redis
      namespace: danran
    spec:
      type: NodePort
      ports:
      - name: http
        port: 6379
        targetPort: 6379
        nodePort: 36379
      selector:
        app: devops-redis
      sessionAffinity: ClientIP
      sessionAffinityConfig:
        clientIP:
          timeoutSeconds: 10800
    
    构建pod
    root@master1:/opt/data/yaml/danran/redis# kubectl apply -f redis.yaml 
    deployment.apps/deploy-devops-redis unchanged
    service/srv-devops-redis created
    
    查看srv-devops-redis service
    root@master1:~# kubectl get svc -n danran
    NAME                         TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
    danran-nginx-service         NodePort   172.28.129.39    <none>        80:38080/TCP                 3h25m
    danran-nginx-spec            NodePort   172.28.111.204   <none>        80:40002/TCP,443:40043/TCP   3d14h
    danran-tomcat-app1-service   NodePort   172.28.134.178   <none>        80:40004/TCP                 2d15h
    srv-devops-redis             NodePort   172.28.158.139   <none>        6379:36379/TCP               5m26s
    
    外部客户端访问redis
    root@master1:~# redis-cli -h 10.203.104.26 -p 36379 -a danran
    

    实战案例之MySQL 主从架构

    https://kubernetes.io/zh/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/
    https://kubernetes.io/zh/docs/tasks/run-application/run-replicated-stateful-application/
    https://www.kubernetes.org.cn/statefulset

    基于StatefulSet实现

    Pod调度运行时,如果应用不需要任何稳定的标示、有序的部署、删除和扩展,则应该使用一组无状态副本的控制器来部署应用,例如 Deployment 或 ReplicaSet更适合无状态服务需求,而StatefulSet适合管理所有有状态的服务,比如MySQL、MongoDB集群等。
    

    基于StatefulSet 实现的MySQL 一主多从架构

    StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。
    
    在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headlessservice,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
    
    StatefulSet 特点:
        -> 给每个pdo分配固定且唯一的网络标识符
        -> 给每个pod分配固定且持久化的外部存储
        -> 对pod进行有序的部署和扩展
        -> 对pod进有序的删除和终止
        -> 对pod进有序的自动滚动更新
    

    StatefulSet的组成部分

    Headless Service:用来定义Pod网络标识( DNS domain)。
    StatefulSet:定义具体应用,有多少个Pod副本,并为每个Pod定义了一个域名。
    volumeClaimTemplates: 存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应。
    

    镜像准备

    https://github.com/docker-library/ #github 下载地址

    准备xtrabackup镜像
    root@master1:~# docker pull registry.cn-hangzhou.aliyuncs.com/hxpdocker/xtrabackup:1.0
    root@master1:~/package# docker tag registry.cn-hangzhou.aliyuncs.com/hxpdocker/xtrabackup:1.0 harbor.linux.com/danran/xtrabackup:1.0
    root@master1:~/package# docker push harbor.linux.com/danran/xtrabackup:1.0
    
    准备mysql 镜像
    root@master1:~# docker pull mysql:5.7
    root@master1:~/package# docker tag mysql:5.7.29 harbor.linux.com/danran/mysql:5.7.29
    root@master1:~/package# docker push harbor.linux.com/danran/mysql:5.7.29
    

    创建PV

    创建五个PV,每个pod挂载一个pv

    mysql-persistentvolume.yaml
    root@master1:/opt/data/yaml/danran/mysql# cat mysql-persistentvolume.yaml 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-datadir-1
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/mysql-datadir-1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-datadir-2
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/mysql-datadir-2
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-datadir-3
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/mysql-datadir-3
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-datadir-4
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/mysql-datadir-4
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-datadir-5
      namespace: danran
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      nfs:
        server: 10.203.104.30
        path: /data/k8sdata/danran/mysql-datadir-5
    
    创建PV
    root@master1:/opt/data/yaml/danran/mysql# kubectl apply -f mysql-persistentvolume.yaml 
    persistentvolume/mysql-datadir-1 created
    persistentvolume/mysql-datadir-2 created
    persistentvolume/mysql-datadir-3 created
    persistentvolume/mysql-datadir-4 created
    persistentvolume/mysql-datadir-5 created
    
    root@master1:/opt/data/yaml/danran/mysql# kubectl get pv
    NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                            STORAGECLASS   REASON   AGE
    mysql-datadir-1           20Gi       RWO            Retain           Available                                                            118s
    mysql-datadir-2           20Gi       RWO            Retain           Available                                                            118s
    mysql-datadir-3           20Gi       RWO            Retain           Available                                                            118s
    mysql-datadir-4           20Gi       RWO            Retain           Available                                                            118s
    mysql-datadir-5           20Gi       RWO            Retain           Available                                                            118s
    

    部署Mysql

    部署 MySQL 示例,包含一个 ConfigMap,两个 Services,与一个 StatefulSet。

    文件结构
    root@master1:/opt/data/yaml/danran/mysql# tree
    .
    ├── mysql-configmap.yaml
    ├── mysql-persistentvolume.yaml
    ├── mysql-services.yaml
    └── mysql-statefulset.yaml
    
    0 directories, 4 files
    
    ConfigMap
    root@master1:/opt/data/yaml/danran/mysql# cat mysql-configmap.yaml 
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql
      labels:
        app: mysql
    data:
      master.cnf: |
        # Apply this config only on the master.
        [mysqld]
        log-bin
        log_bin_trust_function_creators=1
        lower_case_table_names=1
      slave.cnf: |
        # Apply this config only on slaves.
        [mysqld]
        super-read-only
        log_bin_trust_function_creators=1
    
    Services

    以下 YAML 配置文件创建服务

    root@master1:/opt/data/yaml/danran/mysql# cat mysql-services.yaml 
    # Headless service for stable DNS entries of StatefulSet members.
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
      labels:
        app: mysql
    spec:
      ports:
      - name: mysql
        port: 3306
      clusterIP: None
      selector:
        app: mysql
    ---
    # Client service for connecting to any MySQL instance for reads.
    # For writes, you must instead connect to the master: mysql-0.mysql.
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql-read
      labels:
        app: mysql
    spec:
      ports:
      - name: mysql
        port: 3306
      selector:
        app: mysql
    
    StatefulSet

    拷贝https://kubernetes.io/zh/docs/tasks/run-application/run-replicated-stateful-application/的StatefulSet中的配置,并将image修改为harbor的镜像

    创建pod
    root@master1:/opt/data/yaml/danran/mysql# kubectl apply -f .
    configmap/mysql created
    service/mysql created
    service/mysql-read created
    statefulset.apps/mysql created
    
    验证mysql pod
    root@master1:/opt/data/yaml/danran/mysql# kubectl get pod -A | grep mysql
    default                mysql-0                                                2/2     Running   0          115s
    default                mysql-1                                                2/2     Running   1          87s
    default                mysql-2                                                2/2     Running   1          59s
    
    NFS中验证mysql数据

    三个mysql 随机绑定了三个pv

    root@ha1:~# ls /data/k8sdata/danran/mysql-datadir-1/
    mysql
    root@ha1:~# ls /data/k8sdata/danran/mysql-datadir-2/
    mysql
    root@ha1:~# ls /data/k8sdata/danran/mysql-datadir-3/
    root@ha1:~# ls /data/k8sdata/danran/mysql-datadir-4/
    root@ha1:~# ls /data/k8sdata/danran/mysql-datadir-5/
    mysql
    

    验证

    在mysql-0 master中创建数据库danran

    root@master1:~# kubectl exec -it mysql-0 bash
    root@mysql-0:/# mysql
    mysql> create database danran;
    Query OK, 1 row affected (0.00 sec)
    

    在mysql-1中查看新建的danran数据库是否存在

    root@master1:~# kubectl exec -it mysql-1 bash
    Defaulting container name to mysql.
    Use 'kubectl describe pod/mysql-1 -n default' to see all of the containers in this pod.
    root@mysql-1:/# mysql    
    mysql> show databases;
    +------------------------+
    | Database               |
    +------------------------+
    | information_schema     |
    | danran                 |
    | mysql                  |
    | performance_schema     |
    | sys                    |
    | xtrabackup_backupfiles |
    +------------------------+ 
    6 rows in set (0.00 sec)
    

    k8s 示例之WordPress

    https://cn.wordpress.org/
    https://cn.wordpress.org/download/releases/
    

    LNMP案例之基于Nginx+PHP实现WordPress博客站点,要求Nginx+PHP运行在同一个Pod的不同容器,MySQL运行与default的namespace并可以通过service name增删改查数据库

    PHP代码通过NFS共享挂载到每个容器的的代码目录中

    PHP镜像

    官方PHP镜像

    https://hub.docker.com/

     root@master1:~# docker pull php:5.6.40-fpm
    root@master1:~# docker tag php:5.6.40-fpm harbor.linux.com/danran/php:5.6.40-fpm
    root@master1:~# docker push harbor.linux.com/danran/php:5.6.40-fpm
    
    准备PHP镜像
    目录结构
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/php# tree
    .
    ├── build-command.sh
    ├── Dockerfile
    ├── run_php.sh
    └── www.conf
    
    0 directories, 4 files
    
    Dockerfile
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/php# cat Dockerfile 
    #PHP Base Image
    FROM harbor.linux.com/baseimages/centos-jevon-base:7.7.1908
    MAINTAINER jevonran@163.com
    RUN yum install -y https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm && yum install -y php56-php-fpm php56-php-mysql -y
    ADD www.conf /opt/remi/php56/root/etc/php-fpm.d/www.conf
    ADD run_php.sh /usr/local/bin/run_php.sh
    EXPOSE 9000
    
    CMD ["/usr/local/bin/run_php.sh]
    
    run_php.sh
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/php# cat run_php.sh 
    #!/bin/bash
    /opt/remi/php56/root/usr/sbin/php-fpm
    taif -f /etc/hosts
    
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/php# chmod +x run_php.sh
    
    build-command.sh
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/php# cat build-command.sh 
    #!/bin/bash
    TAG=$1
    docker build -t harbor.linux.com/danran/wordpress-php:${TAG} .
    sleep 1
    docker push  harbor.linux.com/danran/wordpress-php:${TAG}
    
    构建镜像
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/php# bash build-command.sh v1
    

    准备wordpress Nginx 基础镜像

    目录结构
    root@master1:/opt/data/dockerfile/web/pub-images/nginx-base-wordpress# tree
    .
    ├── build-command.sh
    ├── Dockerfile
    └── nginx-1.14.2.tar.gz
    
    0 directories, 3 files
    
    Dockerfile
    root@master1:/opt/data/dockerfile/web/pub-images/nginx-base-wordpress# cat Dockerfile 
    #Nginx Base Image
    FROM harbor.linux.com/baseimages/centos-jevon-base:7.7.1908
    MAINTAINER jevonran@163.com
    RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlibdevel openssl openssl-devel iproute net-tools iotop
    ADD nginx-1.14.2.tar.gz /usr/local/src/
    RUN cd /usr/local/src/nginx-1.14.2 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/sbin/nginx && rm -rf /usr/local/src/nginx-1.14.2.tar.gz
    
    build-command.sh
    root@master1:/opt/data/dockerfile/web/pub-images/nginx-base-wordpress# cat build-command.sh 
    #!/bin/bash
    docker build -t harbor.linux.com/webimages/nginx-base-wordpress:v1.14.2 .
    sleep 1
    docker push harbor.linux.com/webimages/nginx-base-wordpress:v1.14.2
    
    构建镜像
    root@master1:/opt/data/dockerfile/web/pub-images/nginx-base-wordpress# bash build-command.sh
    

    准备wordpress PHP+Nginx镜像

    目录结构
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/nginx# tree
    .
    ├── build-command.sh
    ├── Dockerfile
    ├── index.html
    ├── nginx.conf
    └── run_nginx.sh
    
    0 directories, 5 files
    
    Dockerfile
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/nginx# cat Dockerfile 
    #Nginx Base Image
    FROM harbor.linux.com/webimages/nginx-base-wordpress:v1.14.2
    
    ADD nginx.conf /apps/nginx/conf/nginx.conf
    ADD run_nginx.sh /apps/nginx/sbin/run_nginx.sh
    RUN mkdir -pv /home/nginx/wordpress
    RUN chown nginx:nginx /home/nginx/wordpress/ -R
    
    EXPOSE 80 443
    CMD ["/apps/nginx/sbin/run_nginx.sh"]
    
    nginx.conf
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/nginx# cat nginx.conf 
    user nginx nginx;
    worker_processes auto;
    
    events {
        worker_connections 1024;
        # multi_accept on;
    }
    http {
        sendfile on;      
        keepalive_timeout 65;
        client_max_body_size 10M;
        client_body_buffer_size 16K;
        client_body_temp_path /apps/nginx/tmp/ 1 2 2;
        
        include 	mime.types;
        default_type 	application/octet-stream;
        
        gzip on;
        
        server {
            listen 		80;
            server_name	localhost;
    
        # Add index.php to the list if you are using PHP
            index index.html index.htm index.nginx-debian.html;
            location / {
                root 	/home/nginx/wordpress;
                index	index.php index.html index.htm;
            }
        # pass PHP scripts to FastCGI server
        #
            location ~ .php$ {
                root 	/home/nginx/wordpress;
                fastcgi_index	index.php;
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_param	SCRIPT_FILENAME	$document_root$fastcgi_script_name;
                include 	fastcgi_params;
    
            }
           
            error_page	500 502 503 504 /50x.html;
            location = /50x.html {
                root	html;	
            }
       
        }
    }
    
    run_nginx.sh
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/nginx# cat run_nginx.sh 
    #!/bin/bash
    /apps/nginx/sbin/nginx
    tail -f /etc/hosts
    
    build-command.sh
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/nginx# cat build-command.sh 
    #!/bin/bash
    TAG=$1
    docker build -t harbor.linux.com/danran/wordpress-nginx:${TAG} .
    sleep 1
    docker push  harbor.linux.com/danran/wordpress-nginx:${TAG}
    
    构建nginx镜像
    root@master1:/opt/data/dockerfile/web/jevon/wordpress/nginx# bash build-command.sh v1
    

    运行WordPress站点

    使用官方PHP镜像运行PHP环境,WordPress页面文件保存在后端存储NFS服务器

    yaml
    root@master1:/opt/data/yaml/danran/wordpress# cat wordpress.yaml 
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        app: wordpress-app 
      name: wordpress-app-deployment
      namespace: danran
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: wordpress-app
      template:
        metadata:
          labels:
            app: wordpress-app
        spec:
          containers:
          - name: wordpress-app-nginx
            image: harbor.linux.com/danran/wordpress-nginx:v1
            #imagePullPolicy: IfNotPresent
            imagePullPolicy: Always
            ports:
            - containerPort: 80
              protocol: TCP
              name: http
            - containerPort: 443
              protocol: TCP
              name: https
            volumeMounts:
              - name: wordpress
                mountPath: /home/nginx/wordpress
                readOnly: false
    
          - name: wordpress-app-php
            image: harbor.linux.com/danran/php:5.6.40-fpm
            #imagePullPolicy: IfNotPresent
            imagePullPolicy: Always
            ports:
            - containerPort: 9000
              protocol: TCP
              name: http
            volumeMounts:
              - name: wordpress
                mountPath: /home/nginx/wordpress
                readOnly: false
          volumes:
          - name: wordpress
            nfs:
              server: 10.203.104.30
              path: /data/k8sdata/danran/wordpress
    ---
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: wordpress-app
      name: wordpress-app-spec
      namespace: danran
    spec:
      type: NodePort
      ports:
      - name: http
        port: 80
        protocol: TCP
        targetPort: 80
        nodePort: 30031
      - name: https
        port: 443
        protocol: TCP
        targetPort: 443
        nodePort: 30443
      selector:
        app: wordpress-app
    
    运行wordpress
    root@master1:/opt/data/yaml/danran/wordpress# kubectl apply -f wordpress.yaml 
    deployment.apps/wordpress-app-deployment created
    service/wordpress-app-spec created
    
    验证pod
    root@master1:~# kubectl get pods -n danran
    NAME                                                                                     READY    STATUS    RESTARTS   AGE
    wordpress-app-deployment-55bb954d5f-hmxn8              2/2          Running   0                  33s
    

    在pod中确认nginx及php是否启用,确认nfs共享目录是否挂载

    测试Nginx访问

    在NFS 共享目录中创建一个index.html测试页,并将该共享目录的权限设置nginx的启动账号nginx可读,Pod中nginx的UID为2020

    root@ha1:~# cd /data/k8sdata/danran/
    root@ha1:/data/k8sdata/danran# chown 2020.2020 wordpress/ -R
    root@ha1:/data/k8sdata/danran# cat wordpress/index.html 
    Nginx Web Page
    

    浏览器中访问Node节点的nginx暴露端口30031(http://10.203.104.27:30031/index.html)

    测试PHP访问

    在NFS 共享目录中创建一个PHP测试页,并将该测试页的权限设置nginx的启动账号nginx可读,Pod中nginx的UID为2020

    root@ha1:/data/k8sdata/danran# cat wordpress/index.php
    <?php
        phpinfo()
    ?>
    
    root@ha1:/data/k8sdata/danran/wordpress# chown 2020.2020 index.php
    

    浏览器中访问php测试页(http://10.203.104.27:30031/index.php)

    将WordPress保存至NFS的共享目录

    root@ha1:/data/k8sdata/danran/wordpress# ls
    wordpress  wordpress-5.2.5.tar.gz
    root@ha1:/data/k8sdata/danran/wordpress# tar zxvf wordpress-5.2.5.tar.gz
    
    
    将wordpress解压后的数据移动到/data/k8sdata/danran/wordpress目录下
    root@ha1:/data/k8sdata/danran/wordpress# mv wordpress/* .
    root@ha1:/data/k8sdata/danran/wordpress# rmdir wordpress/
    root@ha1:/data/k8sdata/danran/wordpress# ls
    index.php    readme.html             wp-activate.php  wp-blog-header.php    wp-config-sample.php  wp-cron.php  wp-links-opml.php  wp-login.php  wp-settings.php  wp-trackback.php
    license.txt  wordpress-5.2.5.tar.gz  wp-admin         wp-comments-post.php  wp-content            wp-includes  wp-load.php        wp-mail.php   wp-signup.php    xmlrpc.php
    
    将该共享目录的权限设置nginx的启动账号nginx可读,Pod中nginx的UID为2020 
    root@ha1:/data/k8sdata/danran/wordpress# chown 2020.2020 ./* -R
    root@ha1:/data/k8sdata/danran/wordpress# ll
    

    在浏览器访问http://10.203.104.27:30031/wp-admin/setup-config.php测试

    HA中设置wordpress的负载均衡地址

    root@ha1:~# cat /etc/haproxy/haproxy.cfg
    listen danran-nginx-80
            bind 10.203.104.213:80
            mode tcp
            server master1 10.203.104.26:30031 check inter 3s fall 3 rise 5	
            server master2 10.203.104.27:30031 check inter 3s fall 3 rise 5	
            server master3 10.203.104.28:30031 check inter 3s fall 3 rise 5	
    
    root@ha1:~# systemctl restart haproxy.service    
    

    浏览器访问VIP地址测试(http://10.203.104.213/)

    在本地hosts或DNS中添加VIP的主机名解析

    10.203.104.213 www.linux.blog.com
    

    测试主机访问wordpress(http://www.linux.blog.com/)

    初始化WordPress站点

    使用k8s中运行的mysql服务,作为mysql服务器,mysql服务器最好跟wordpress在同一NameSpace空间下

    在mysql中创建wordpress数据库,并授权给wordpress用户
    root@master1:~# kubectl get pod
    NAME                        READY   STATUS    RESTARTS   AGE
    mysql-0                     2/2     Running   0          23h
    mysql-1                     2/2     Running   1          23h
    mysql-2                     2/2     Running   1          23h
     
    root@master1:~# kubectl exec -it mysql-0 bash
    Defaulting container name to mysql.
    Use 'kubectl describe pod/mysql-0 -n default' to see all of the containers in this pod.
    root@mysql-0:/# mysql
    Welcome to the MySQL monitor.  Commands end with ; or g.
    Your MySQL connection id is 50586
    Server version: 5.7.29-log MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    
    mysql> CREATE DATABASE wordpress;
    Query OK, 1 row affected (0.01 sec)
    mysql> GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"%" IDENTIFIED BY "wordpress";
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    mysql> exit
    Bye
    
    k8s中测试MySQL连接

    web界面初始化

    mysql所在的NameSpace为Default,mysql的mysql-services.yaml文件中写了连接数据库需使用mysql-0.mysql,故mysql的全域名为mysql-0.mysql.default.svc.danran.com

    Database Host 添加Mysql的主机地址(如果mysql pod不在同一个namespace,那么就写对方services全称,以实现跨namespace的解析和访问)

    验证k8s中mysql 数据

    分别验证k8s中MySQL主库和从库是否数据

  • 相关阅读:
    菜鸟笔记 -- Chapter 6.2.6 内部类
    菜鸟笔记 -- Chapter 6 面向对象
    菜鸟笔记 -- Chapter 6.1 面向对象概述
    菜鸟笔记 -- Chapter 4.7 代码注释与编码规范
    菜鸟笔记 -- Chapter 4 Java语言基础
    小白袍 -- Chapter 1.4.1.1 URL编码的理论解读
    小白袍 -- Chapter 1.1 避不开的编解码
    小白袍 -- Chapter 1 Java中的Encode与Decode
    菜鸟崛起 Ajax
    软件测试
  • 原文地址:https://www.cnblogs.com/JevonWei/p/13187031.html
Copyright © 2011-2022 走看看