k8s阶段02 namespace,pod资源及命令, pod资源配置(应用监控,资源需求和限制), 多容器pod(初始容器), k8s卷基础

namespace

Namespace: 
    名称空间,命名空间
        资源对象名称隔离

        www.google.com, www.magedu.com

    资源类型:
        名称空间级别:必须属于某个名称空间
            -n NAMESPACE_NAME  
            --namespace NAMESPACE_NAME
        集群级别:不属于任何名称名称      

    命令:  kubectl get 
        kubectl get TYPE [name, ...] 
            -o {json|yaml|wide|jsonpath|name} #显示类型
            
        kubectl get TYPE1,TYPE2,...     #显示多种资源类型
            all:代表所有类型

        kubectl get TYPE name1 name2 ...
        kubectl get TYPE1/NAME TYPE2/NAME2 ...

        TYPE:     #支持3种格式,单数,复数,简写(适用于get delete方法,create不支持)
            namespaces, namespace, ns
            
        kubectl get -f /PATH/TO/MANIFEST_FILE        
#例:
#获取所有名称空间
~]#kubectl get namespace
#获取指定名称空间
~]#kubectl get namespace blog
#以json格式展示
~]#kubectl get namespace blog -o json
#只显示json中的metadata.name字段
~]#kubectl get namespace blog -o jsonpath={.metadata.name}
#显示名字
~]#kubectl get namespace -o name
#列出多种资源对象, get all表示显示所有资源类型
~]#kubectl get service,pods -n blog
#显示指定资源类型
~]#kubectl get service/mysql -n blog


    命令: kubectl create 
        方法一:指令式命令
            kubectl create TYPE NAME OPTIONS

        方法二:指令式对象配置
            kubectl create -f /PATH/TO/MANIFEST_FILE
            -f选项可重复使用多次;
            -f /PATH/TO/DIR/:加载目录下的所有以.yaml, .yml, .json结尾的文件;
            -f URL: 加载URL位置上的配置文件
            
            单个配置文件,可以存在多个资源对象:#通过---进行隔开
                apiVersion
                kind 
                ...
                ---
                apiVersion
                kind 
                ....
                ---
#例:
#创建名称空间
[root@master01 ~]#kubectl create namespace dev
#存入yaml文件并做修改
~]#kubectl get namespace dev -o yaml > prod-namespace.yaml
~]#vim prod-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: prod
spec:    #namespace可以不用定义
  finalizers:    #终结器,表示删除时谁来删除
  - kubernetes
#创建名称空间
[root@master01 ~]#kubectl create -f prod-namespace.yaml

#--dry-run=client表示以客户端形式做测试,并不真正运行
[root@master01 ~]#kubectl create namespace stage --dry-run=client -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: stage
spec: {}
status: {}
~]#kubectl create namespace stage --dry-run=client -o yaml > stage-namespace.yaml
[root@master01 ~]#kubectl create -f stage-namespace.yaml
#可以通过配置文件查看资源类型
[root@master01 ~]#kubectl get -f stage-namespace.yaml 
NAME    STATUS   AGE
stage   Active   22s


    命令: kubectl delete 
        命令格式类似于kubectl get,删除某类型下的所有资源对象时,要使用“--all”选项;
#例:
[root@master01 ~]#kubectl delete namespace prod stage dev
~]#kubectl delete -f stage-namespace.yaml

    命令:kubectl edit 
        kubectl edit TYPE NAME 
#例:
[root@master01 ~]#kubectl edit service wordpress -n blog
#如果修改修改有语法错误会不让保存

管理名称空间

Kubernetes的名称空间可以划分为两种类型
  系统级名称空间:由Kubernetes集群默认创建,主要用来隔离系统级的资源对象
  自定义名称空间:由用户按需创建
  
系统级名称空间
  default:默认的名称空间,为任何名称空间级别的资源提供的默认设定
  kube-system:Kubernetes集群自身组件及其它系统级组件使用的名称空间,Kubernetes自身的关键组件均部署在该名称空间中
  kube-public:公众开放的名称空间,所有用户(包括Anonymous)都可以读取内部的资源
  kube-node-lease:节点租约资源所用的名称空间
    分布式系统通常使用“租约(Lease)”机制来锁定共享资源并协调集群成员之间的活动
    Kubernetes上的租约概念由API群组coordination.k8s.io群组下的Lease资源所承载,以支撑系统级别的功能需求,例如节点心跳(node heartbeats)和组件级的领导选举等
    Kubernetes集群的每个节点,在该名称空间下都有一个与节点名称同名的Lease资源对象
      ~# kubectl -n kube-node-lease get lease
      
所有的系统级名称空间均不能进行删除操作,而且除default外,其它三个也不应该用作业务应用的部署目标

关于Pod

什么是Pod?
  一个或多个容器的集合,因而也可称为容器集,但却是Kubernetes调度、部署和运行应用的原子单元
  另外封装的内容:可被该组容器共享的存储资源、网络协议栈及容器的运行控制策略等
  依赖于pause容器事先创建出可被各应用容器共享的基础环境,它默认共享Network、IPC和UTS名称空间给各容器,PID名称空间也可以共享,但需要用户显式定义

Pod的组成形式有两种
  单容器Pod:仅含有单个容器
  多容器Pod:含有多个具有“超亲密”关系的容器
    同一Pod内的所有容器都将运行于由Scheduler选定的同一个节点上

Pod资源规范的基础框架

一个极简的Pod定义,仅需要为其指定一个要运行的容器即可
    给出该容器的名称和使用的Image
#例:
~]#vim pod-demoapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demoapp # Pod的标识名,在名称空间中必须惟一;
  namespace: default # 该Pod所属的名称空间,省略时使用默认名称空间default;
spec:
  containers: # 定义容器,它是一个列表对象,可包括多个容器的定义,至少得有一个;
  - name: demoapp # 容器名称,必选字段,在当前Pod中必须惟一;
    image: ikubernetes/demoapp:v1.0 # 创建容器时使用的镜像;
 
#创建pod  
~]#kubectl apply -f pod-demoapp.yaml
#kubectl create是命令式操作,若资源已经存在会报错
#kubectl apply是声明式操作,若资源不存着就创建;若资源存在,比较现有资源配置差异,不同就更新,相同就不操作

    pause容器无需定义

    命令:kubectl explain 
        TYPE NAME
        显示指定资源类型的内建文档
        --api-version=GROUP_NAME/VERSION 
#例:查看pods配置怎么写
~]#kubectl explain pods
~]#kubectl explain pods.metadata    #查看其中的metadata字段

    命令:kubectl api-versions
        打印k8s上的所有的资源群组及其版本号
    查看一个组下所有资源
        kubectl api-resources --api-group=apps

了解Pod的运行状况

打印Pod完整的资源规范,通过status字段了解
  kubectl get TYPE NAME -o yaml|json
  #例如
    kubectl get pods demoapp -o yaml
    kubectl get pods demoapp -o json
    
打印Pod资源的详细状态
  kubectl describe TYPE NAME
  #例如
    kubectl describe pods demoapp
    
获取Pod中容器应用的日志
  kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]
        --all-containers    #显示所有容器
        --tail=N       #显示多少行
  #例如
    kubectl logs demoapp -c demoapp    #多容器指定哪个容器
    kubectl logs demoapp    #单容器,不用指定哪个容器(如果多容器,会显示第一个容器)


    命令:kubectl exec 
        kubectl exec (POD | TYPE/NAME) [-c CONTAINER] [flags] -- COMMAND [args...] [options]
        -it:打开交互式接口时使用
  #例如
#容器内部执行netstat -tnl命令, 有多个容器加上-c
[root@master01 ~]#kubectl exec demoapp -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
#进入容器内部,指定运行sh
[root@master01 ~]#kubectl exec -it demoapp -- /bin/sh
[root@demoapp /]# ifconfig

镜像下载策略

    镜像下载策略:
        imagePullPolicy:
            Always #永远下载
            IfNotPresent    #如果没有就下载
            Never #永远不下载,等用户手动下载

        默认:IfNotPresent
        例外:Image Tag为latest时,在Always或IfNotPresent策略下,都会重新下载;

#
~]#vim pod-demoapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demoapp # Pod的标识名,在名称空间中必须惟一;
  namespace: default # 该Pod所属的名称空间,省略时使用默认名称空间default;
spec:
  containers: # 定义容器,它是一个列表对象,可包括多个容器的定义,至少得有一个;
  - name: demoapp # 容器名称,必选字段,在当前Pod中必须惟一;
    image: ikubernetes/demoapp:v1.0 # 创建容器时使用的镜像;
    imagePullPolicy: IfNotPresent    #镜像拉取策略

Pod的phase和重启策略

Pod的相位

Pending:没有任何节点满足调度条件,或能运行该pod时,导致scheduler调度无法完成
如果是作业类应用,执行完任务会出现成功,失败两种状态
服务类应用也可能处于失败状态,所有任务都启动不起来(一直重启,但都失败了)
Unknown:apiserver接收不到kubectl的报告,kubectl维护的pod信息变为未知
#kubectl有自愈能力,任何pod中的容器启动失败都会通过重启解决问题

容器的状态

 Pod的重启策略:决定了容器终止后是否应该重启

◼ Always:无论何种exit code,都要重启容器
◼ OnFailure:仅在exit code为非0值(即错误退出)时才重启容器
◼ Never:无论何种exit code,都不重启容器
#默认是Always

#
[root@master01 ~]#vim pod-demoapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demoapp # Pod的标识名,在名称空间中必须惟一;
  namespace: default # 该Pod所属的名称空间,省略时使用默认名称空间default;
spec:
  containers: # 定义容器,它是一个列表对象,可包括多个容器的定义,至少得有一个;
  - name: demoapp # 容器名称,必选字段,在当前Pod中必须惟一;
    image: ikubernetes/demoapp:v1.0 # 创建容器时使用的镜像;
    imagePullPolicy: IfNotPresent    #镜像拉取策略
  restartPolicy: Always
  
#注意:有些字段创建后不允许修改,有些字段创建后允许时时修改
[root@master01 ~]#kubectl apply -f pod-demoapp.yaml
pod/demoapp configured

通过环境变量向容器传递参数

容器配置参数:
    环境变量:
        1、启动容器时,自定义要运行的命令及选项、参数;
            Dockerfile, CMD, ENTRYPOINT
        2、通过环境进行配置;
            Dockerfile, entrypoint.sh脚本来代理预处理环境变量
        3、将配置焙进Image,重制Image;
        4、将配置文件放置在卷上,由容器通过卷加载;
            卷:ConfigMap/Secret  
            
        命令:kubectl run 
            创建并运行Pod 
            #--dry-run=client以client形式做测试,不执行,以yaml格式输出
            kubectl run mydb --image=mysql:8.0 --dry-run=client -o yaml
            kubectl run wordpress --image=wordpress:6.4-apache -n default --dry-run=client -o yaml
            
        主机端口:
            将Pod所在的主机的某个端口与容器的端口建立映射关系#外部不能访问pod端口,通过映射就能访问
               External Client --> hostIP:hostPort --> podIP:containerPort
           #例如:yaml格式如下
            containers:
            - name: 
              ...
              ports:
              - name: NAME
                containerPort: ...    #容器端口
                #映射到节点的端口(调度器scheduler找一个不占用该端口的节点)
                hostPort: ...    
#
]#vim pod-demo-with-cmd-and-args.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo-with-cmd-and-args
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    command: ['/bin/sh','-c'] #自定义命令
    args: ['python3 /usr/local/bin/demo.py -p 8080'] #自定义传给命令的参数
]#kubectl apply -f pod-demo-with-cmd-and-args.yaml

#定义mysql容器环境变量
]#vim pod-mydb.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mydb
  namespace: default
spec:
  containers:
  - name: mydb
    image: mysql:8.0
    env:    #把密码写在这里不安全,这里只是做演示
    - name: MYSQL_RANDOM_ROOT_PASSWORD #超级用户账号
      value: 1
    - name: MYSQL_DATABASE
      value: wpdb
    - name: MYSQL_USER
      value: wpuser
    - name: MYSQL_PASSWORD
      value: magedu.com
]#kubectl apply -f pod-mydb.yaml

]#vim wordpress.yaml
apiVersion: v1
kind: Pod
metadata:
  name: wordpress
  namespace: default
spec:
  containers:
  - name: wordpress
    image: wordpress:6.4-apache
    env:
    - name: WORDPRESS_DB_HOST
      value: '10.244.3.8'
    - name: WORDPRESS_DB_NAME
      value: wpdb
    - name: WORDPRESS_DB_USER
      value: wpuser
    - name: WORDPRESS_DB_PASSWORD
      value: magedu.com
    #pod地址只在集群上可达,集群外访问不到,这里通过节点和pod端口做映射
    ports: #把容器的80端口映射到节点的8080端口,这样外部可以访问(正常应该通过service实现)
    - name: http
      containerPort: 80
      hostPort: 8080
]#kubectl apply -f wordpress.yaml
#查找对应wordpress节点在哪  kubectl get pods -o wide
#浏览器输入节点ip:8080即可访问wordpress


#删除节点
]#kubectl delete -f wordpress.yaml

应用监控

Container Probe (探测): 周期性向容器发起探测请求
     StartupProbe: 应对启动过程较长的应用而提供,探针成功后退出
     LivenessProbe:存活状态,用于判定容器进程是否健康运行;
         影响:判定为不健康的Pod,会被kubelet根据重启策略进行处理,重启;
     ReadinessProbe:就绪状态,用于判定容器进程是否已经初始化完成,并可向用户提供服务;
         影响:判定为未就绪的Pod,以该Pod为后端端点的Service,不予调度流量给该Pod;
            
     成功阈值:1
         failure状态下,满足连续success的次数之后,即被判定为成功;
     失败阈值:3
          success状态下,满足连续failure的次数之后,即被判定为失败;
          
Startup Probe和Liveness Probe
◼ Startup探针主要是为了应对启动过程较长的应用而提供
◼ Startup探针成功后将退出,并切换为使用Liveness探针
#如果一直成功,突然失败,超过阈值将会重启容器,再次启用Startup探针

探针配置参数    #每种探针都支持下面几种参数
◼ initialDelaySeconds:首次探测的延迟时长
◼ periodSeconds:探测周期时长
◼ timeoutSeconds:单次探测的超时时长
◼ successThreshold:成功阈值
◼ failureThreshold:失败阈值
以Liveness Probe为例来看上面几个参数的意义

探测的方式:
      tcpSocket
      httpGet
      exec:运行此处自定义的命令,根据命令的退出码,来判定其健康状态;
      
#例:(了解)
]#vim startup-exec-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: startup-exec-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    startupProbe: #启动探针(成功就退出)一个容器可以也应该同时存在多种探针(就绪和存活都有)
      exec:    #探针类型,下面为执行的命令
        command: ['/bin/sh', '-c', '[ "$(/usr/bin/curl -s http://127.0.0.1/livez)" == "OK" ]']
      initialDelaySeconds: 0    #首次探测延迟0s
      failureThreshold: 3    #失败阈值3
      periodSeconds: 5    #每隔5s探测一次

#例: 使用exec探测
]#vim liveness-exec-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    livenessProbe:    #一般一个容apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcpsocket-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
    livenessProbe:
      tcpSocket:
        port: http
      periodSeconds: 5
      initialDelaySeconds: 5器同时存在多种探针
      exec:
        #command: ['/bin/sh', '-c', '[ "$(curl -s 127.0.0.1/livez)" == "OK" ]']
        command: ['/bin/sh', '-c', '[ "$(/usr/bin/curl -s http://127.0.0.1/livez)" == "OK" ]']
      initialDelaySeconds: 5    #首次探测延迟5s
      timeoutSeconds: 1    #超时时长1s
      periodSeconds: 5    #每隔5s探测一次

]#kubectl apply -f liveness-exec-demo.yaml
#查看探针状态,重启计数
]#kubectl describe pods liveness-exec-demo
#查看重启计数
]#kubectl get pods -o wide

#例: 使用tcp探测
]#vim liveness-tcpsocket-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcpsocket-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    ports:
    - name: http    #被引用
      containerPort: 80
    securityContext: #安全上下文,赋予容器内部特权能力(可以看iptables)
      capabilities:
        add:
        - NET_ADMIN
    livenessProbe:
      tcpSocket: #发tcp请求第一次,只要对方返回就算成功
        port: http    #应用上面的http端口80
      periodSeconds: 5
      initialDelaySeconds: 5    #首次探测延迟5s

#例: 七层探测
]#vim liveness-httpget-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    livenessProbe:
      httpGet:    #请求如果是200就是成功的
        path: '/livez'    #向本机路径
        port: 80
        scheme: HTTP    #使用http协议
      initialDelaySeconds: 5

#例: readiness探针
]#vim readiness-httpget-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-demo
  namespace: default
  labels:
    name: readiness-httpget-demo
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        path: '/readyz'
        port: 80
        scheme: HTTP
      initialDelaySeconds: 5
      timeoutSeconds: 2
      periodSeconds: 5
      failureThreshold: 5
  restartPolicy: Always
#启动对应service,当探针异常就不调度请求给该Pod,service会摘掉该节点
#当探针异常恢复后,service会把该节点加入

Security Context

Pod及容器的安全上下文
  一组用来决定容器是如何创建和运行的约束条件,这些条件代表创建和运行容器时使用的运行时参数
  给了用户为Pod或容器定义特权和访问控制机制
Pod和容器的安全上下文设置主要包括以下几个方面
  自主访问控制DAC
  容器进程运行身份及资源访问权限
  Linux Capabilities
  seccomp
  AppArmor
  SELinux
  Privileged Mode
  Privilege Escalation

#常用
  Pod级别:
      runAsUser        #以指定用户身份
      runAsGroup    #以指定组运行
      runAsNonRoot    #以非管理员身份运行
      sysctls        #运行时改pod内的内核参数
      
  容器级别:
      runAsUser
      runAsGroup
      runAsNonRoot
      readOnlyRootFilesystem    #限制根文件系统为只读
      privileged <boolean>    #容器运行成特权模式
      capabilities  <Capabilities> #开放特定的内核特权给当前容器
              NET_ADMIN
              CHOWN        #改变文件属主属组的权限(默认具有CHOWN)
              SYS_ADMIN    #仅次于管理员的身份
              ...  
#例:
]#vim securitycontext-capabilities-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: securitycontext-capabilities-demo
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c"]
    args: ["/sbin/iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80 && /usr/bin/python3 /usr/local/bin/demo.py"]
    securityContext:
      capabilities:
        add: ['NET_ADMIN']
        #drop: ['CHOWN']    #移除特权

资源需求(requests)和限制(limits)

资源需求和资源限制
  资源需求(requests)
    定义需要系统预留给该容器使用的资源最小可用值
    容器运行时可能用不到这些额度的资源,但用到时必须确保有相应数量的资源可用
    资源需求的定义会影响调度器的决策
  资源限制(limits)
    定义该容器可以申请使用的资源最大可用值,超出该额度的资源使用请求将被拒绝
    该限制需要大于等于requests的值,但系统在其某项资源紧张时,会从容器那里回收其使用的超出其requests值的那部
分
#cpu可用要回来,但是被使用的内部不能要回来(会导致程序崩溃)。所以建议资源需求和资源限制保持一致
#如果什么都不设定,那么任务优先级是最低的

requests和limits定义在容器级别,主要围绕cpu、memory、hugepages和ephemeral-storage四种资源

Extended resources
  所有那些不属于kubernetes.io域的资源,即为扩展资源,例如“nvidia.com/gpu”
  又存在节点级别和集群级别两个不同级别的扩展资源


Pod的QoS类别:
    BestEffort: 最低(只要空闲就让你运行)
        未定义requests和limits
    Burstable
    Garanteed:最高
        cpu.requests == cpu.limits    #需求等于限制
        memory.ruquests == memroy.limits 
        
    CPU资源单位:
        1 == 1000m
            100m <= 总体上单个核心的10% (可以分散到各个cpu上)
    内存资源单位:
        Ki, Mi, Gi, ...
#例:
apiVersion: v1
kind: Pod
metadata:
  name: stress-pod
spec:
  containers:
  - name: stress
    image: ikubernetes/stress-ng    #压测镜像
    command: ["/usr/bin/stress-ng", "-c 1", "-m 1", "--metrics-brief"]
    resources:
      requests: #需求,要预留的
        memory: "128Mi"
        cpu: "200m"
      limits:
        memory: "512Mi"
        cpu: "400m"

 

3 Pod设计模式

多容器Pod: 
    containers:
    - name: ...
      image: ...
    - name: ...
      image: ...
      
运行核心业务程序的容器:主容器, main container 
其它容器:辅助容器
    Sidecar #其他各种类型,例流量统计,所有请求都先经过它
    Ambassador#大使容器,代主容器去访问外部环境(主容器没有访问外部对应功能时,直接访问大使容器)
    Adpater #适配器容器,适配器不兼容外部请求,通过Adpater来接受请求,再请求主容器


    Init Container模式    #初始化容器
        为定义在containers字段中的容器,执行初始化任务,因此,初始化容器成功运行并退出后,常规容器才能启动、运行;而且,如果存在多个初始化容器,那么他们将以串行方式运行,且全部都成功退出,常规容器才能启动;
        任何一个初始化容器启动失败,那么整个pod就失败了
    #格式:
    initContainers:    #允许多个(如果多个,串行运行),和container同一级别
    - name: ...
      image: ...
    - name: ...
      image: ...
    container:    #常规容器
    - name: ...
      image: ...
    - name: ...
      image: ...

#例:
]#vim init-container-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: init-container-demo
  namespace: default
spec:
  initContainers:
  - name: iptables-init
    image: ikubernetes/admin-box:latest
    imagePullPolicy: IfNotPresent
    command: ['/bin/sh','-c']    #pod内核添加规则,访问8080都跳转至80端口
    args: ['iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80']
    securityContext:
      capabilities:
        add:
        - NET_ADMIN    #给予网络管理员权限
  containers:    #常规容器
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
#apply -f运行后,kubectl get pods会看到init:0/1表示初始化阶段,初始化容器1个,完成后运行常规容器

 

4 Pod的创建和终止(了解)

创建

 终止

 

5 Pod状态及常见异常问题

 

存储卷

1存储卷基础

从概念上讲,存储卷是可供Pod中的所有容器访问的目录
  Pod规范中声明的存储卷来源决定了目录的创建方式、使用的存储介质以及目录的初始内容
    存储卷插件(存储驱动)决定了支持的后端存储介质或存储服务,例如hostPath插件使用宿主机文件系统,而nfs插件则对接指定的NFS存储服务等
    kubelet内置支持多种存储卷插件
  Pod在规范中需要指定其包含的卷以及这些卷在容器中的挂载路径

存储卷对象并非Kubernetes系统一等公民
  它定义在Pod上,因而生命周期与Pod相同,这意味着
    Pod中的所有卷都是在创建Pod时一并被创建
    删除Pod时,其上的所有卷(定义)亦会同时被删除
  另一方面,其后端的存储及相关数据的生命周期通常要取决于存储介质

存储卷类型和相应的插件

In-Tree存储卷插件
  临时存储卷 #删掉pod,数据也会被删掉.通常在pod所在节点的内存上或者磁盘上
    emptyDir
  节点本地存储卷 #无法跨节点被访问
    hostPath, local
  网络存储卷
    文件系统:NFS、GlusterFS、CephFS和Cinder
    块设备:iSCSI、FC、RBD和vSphereVolume
    存储平台:Quobyte、PortworxVolume、StorageOS和ScaleIO
    云存储:awsElasticBlockStore、gcePersistentDisk、azureDisk和azureFile
  特殊存储卷
    Secret、ConfigMap、DownwardAPI和Projected
  扩展接口
    CSI和FlexVolume

Out-of-Tree存储卷插件 #要部署才能使用
◼ 经由CSI或FlexVolume接口扩展出的存储系统称为Out-of-Tree类的存储插件

存储卷资源规范

spec:
  volumes:
  - name <string> 
    # 卷名称标识,仅可使用DNS标签格式的字符,在当前Pod中必须惟一;
    VOL_TYPE <Object> 
# 存储卷插件及具体的目标存储供给方的相关配置;
containers:
- name: …
  image: …
  volumeMounts:
  - name <string> 
    # 要挂载的存储卷的名称,必须匹配存储卷列表中某项的定义;
    mountPath <string> 
    # 容器文件系统上的挂载点路径;
    readOnly <boolean> 
    # 是否挂载为只读模式,默认为否;
    subPath <string> 
    # 挂载存储卷上的一个子目录至指定的挂载点;
    subPathExpr <string> 
    # 挂载由指定的模式匹配到的存储卷的文件或目录至挂载点;
    mountPropagation <string> 
    # 挂载卷的传播模式;

emptyDir存储卷

#通常只能用于某些特殊场景中
  同一Pod内的多个容器间文件共享
  作为容器数据的临时存储目录用于数据缓存系统

配置参数
  medium:此目录所在的存储介质的类型,可用值为“default”或“Memory”
  sizeLimit:当前存储卷的空间限额,默认值为nil,表示不限制

#
apiVersion: v1
kind: Pod
metadata:
  name: pods-with-emptydir-vol
spec:
  containers:
  - image: ikubernetes/admin-box:v1.2
    name: admin
    command: ["/bin/sh", "-c"]
    args: ["sleep 99999"]
    resources: {}
    volumeMounts:#卷挂载在/data下
    - name: data
      mountPath: /data
  - image: nginx:alpine
    name: nginx
    resources: {}
    volumeMounts:#卷挂载在/var/www/html下
    - name: data
      mountPath: /usr/share/nginx/html/
volumes:    #
- name: data
  emptyDir:
    medium: Memory
    sizeLimit: 16Mi
    
#创建完成后,即可在admin容器的/data目录生成测试数据,而后在nginx容器中,通过挂载点/usr/share/nginx/html/进行测试访问

hostPath存储卷

hostPath卷
◼ 将Pod所在节点上的文件系统的某目录用作存储卷
◼ 数据的生命周期与节点相同
配置参数
◼ path:指定工作节点上的路径,必选字段
◼ type:指定节点之上存储类型

#
apiVersion: v1
kind: Pod
metadata:
  name: volumes-hostpath-demo
spec:
  containers:
  - name: redis
    image: redis:alpine
    volumeMounts:
    - mountPath: /data
      name: redisdata
volumes:
  - name: redisdata
  hostPath:
    path: /appsdata/redis/ #宿主机上的路径
    type: DirectoryOrCreate #不存在就创建
    
#如果当前pod被删,下次还想部署到相同节点,使用同一卷,可以指定spec下追加nodename
apiVersion: v1
kind: Pod
metadata:
  name: volumes-hostpath-demo
spec:
  nodename: 节点主机名    #追加该行
  ...

type种类如下图

 NFS存储

NFS Server的目录导出方法:
    /data/nfs/ 172.29.0.0/16(rw,async,no_subtree_check,no_root_squash)

Server:
    nfs-kernel-server #安装包

Worker Nodes:
    nfs-common #安装包

#准备一台机器,安装nfs服务器(ubuntu上程序包叫nfs-kernel-server)
[root@ubuntu ~]#apt update && apt install nfs-kernel-server -y
[root@ubuntu ~]#mkdir -pv /data/nfs
#把该路径作为导出目录
[root@ubuntu ~]#vim /etc/exports
#NFS Server的目录导出方法:(给10.0.0.0/16地址使用)
/data/nfs/ 10.0.0.0/16(rw,async,no_subtree_check,no_root_squash)
#查看状态
[root@ubuntu ~]#systemctl status nfs-server.service
#重新导出下,让配置生效
[root@ubuntu ~]#exportfs -arv
exporting 10.0.0.0/16:/data/nfs

#每个节点安装包,来挂载nfs服务
[root@node03 ~]#apt install -y nfs-common
#一台机器挂载测试
[root@node03 ~]#mount 10.0.0.155:/data/nfs /mnt
#不需要手动挂,卸载掉
[root@node03 /]#umount /mnt

#
[root@master01 volumes]#vim pod-with-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-nfs-vol
spec:
  containers:
  - name: redis
    image: redis:7-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: redisdata
      mountPath: /data
  volumes:
  - name: redisdata
    nfs:
      server: 10.0.0.155 #nfs服务器地址
      path: /data/nfs #真正文件系统导出来的路径
      
[root@master01 volumes]#kubectl apply -f pod-with-nfs-vol.yaml
#进入容器
[root@master01 volumes]#kubectl exec -it redis-nfs-vol -- /bin/sh
/data # redis-cli
127.0.0.1:6379> SET hi "Hi from MageEdu"
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> exit
/data # ls
dump.rdb

#nfs服务器上查看是否有对应文件
[root@ubuntu ~]#ls /data/nfs
dump.rdb
#删除对应pod
[root@master01 volumes]#kubectl delete pods redis-nfs-vol
#修改yaml文件,创建到其他节点上
[root@master01 volumes]#vim pod-with-nfs-vol.yaml
...
spec:
  nodeName: node02
...
[root@master01 volumes]#kubectl apply -f pod-with-nfs-vol.yaml
#进入容器查看redis里面数据是否和node3上创建的相同

 

posted @ 2024-11-19 23:30  战斗小人  阅读(0)  评论(0编辑  收藏  举报