7.2 Kubernetes 实践


文章目录

  • 1.kubernetes概述
  • 2.RC(ReplicationController)控制器
    • 2.1 通过部署文件手动启动kubia容器
    • 2.2 控制器的标签
    • 2.3 容器扩容缩容
    • 2.4 修改控制器标签
    • 2.5 修改控制器部署文件
    • 2.6 删除控制器
  • 3.pod容器
    • 3.1 创建部署文件
    • 3.2 使用部署文件手动创建pod
    • 3.3 Pod相关查询命令
    • 3.4 pod 标签
      • 3.4.1 创建pod时指定标签
      • 3.4.2 使用部署文件创建资源
      • 3.4.3 查看pod的标签
    • 3.5 pod的标签的增删改查
      • 3.5.1 pod的标签的修改
      • 3.5.2 使用标签来查询 pod
      • 3.5.3 删除标签
    • 3.6 把pod部署到指定的节点服务器
      • 3.6.1 创建节点服务器部署文件
      • 3.6.2 为服务器添加标签
      • 3.6.3 查看部署结果
    • 3.7 pod 注解
    • 3.8 pod端口转发
  • 4.namespace
    • 4.1 查看命名空间
    • 4.2 创建命名空间
    • 4.3 将pod部署到指定的命名空间中
  • 5.相关资源的删除
  • 6.存活探针
    • 6.1 创建部署文件
    • 6.2 创建 pod
    • 6.3 查看 pod 日志
    • 6.4 查看pod描述
    • 6.5 设置延迟时间
  • 7.Dashboard 仪表盘
    • 7.1 查看 Dashboard 部署信息
    • 7.2 证书验证访问(了解)
    • 7.3 令牌
    • 7.4 使用控制台创建RC控制器
  • 8.RS(ReplicaSet)控制器
    • 8.1 使用部署文件创建ReplicaSet控制器
    • 8.2 更改部署文件内容
  • 9.其它特殊场景控制器
    • 9.1 DaemonSet控制器
    • 9.2 Job控制器
    • 9.3 Cronjob控制器
  • 10.Service
    • 10.1 Service创建
    • 10.2 会话亲和性
    • 10.3 endpoint
      • 10.3.1 查看kubia服务的endpoint
      • 10.3.2 创建没有选择器的 Service,不会创建Endpoint
      • 10.3.3 通过`完全限定域名`访问外部服务
      • 10.3.4 在容器内部调用
    • 10.4 服务暴露给客户端
    • 10.5 NodePort方式对外暴露端口
  • 11.磁盘挂载到容器
    • 11.1 emptyDir方式临时存储数据
    • 8.2 NFS 共享文件系统
    • 8.3 持久化存储(PersistentVolume)
    • 8.4 持久卷声明(Persistent Volume Claim )
  • 12.配置启动参数
    • 12.1 docker 的命令行参数
    • 12.2 `k8s`中覆盖docker的`ENTRYPOINT`和`CMD`
    • 12.3 环境变量
    • 12.4 ConfigMap
      • 12.4.1 创建
      • 12.4.2 使用部署文件添加配置
      • 12.4.3 从控制台添加配置
    • 12.5 config-map–>env–>arg
  • 13.Deployment
    • 13.1 创建 Deployment
    • 13.2 升级 Deployment
    • 13.3 触发滚动升级
    • 13.4 自动回滚 Deployment
    • 13.5 控制滚动升级速率
    • 13.6 暂停滚动升级
    • 10.8 自动阻止出错版本升级
  • 14.常用命令总结


1.kubernetes概述

kubectl run 命令是最简单的部署引用的方式,它自动创建必要组件,这样,我们就先不必深入了解每个组件的结构;

了解kubernetes,首先要了解其重要的三个概念:

  • podpod是k8s的容器,用来封装Docker或其它容器的对象,它具有自己的虚拟环境(端口, 环境变量等),一个Pod可以封装多个Docker或其它容器.,在pod容器中会启动运行docker容器;其主要作用是完成容器化技术的解耦,通过这个媒介可以随时使用dockerContainerd等多种其他容器;
  • RC控制器:控制器是用来自动控制容器部署、销毁的工具,k8s通过控制器来完成自动部署及销毁的相关操作;我们只需要告诉其需要启动多少个什么服务,其就会帮你在所有工作服务器上自动的部署启动相关服务;
  • Service:Service对容器提供了一个不变的访问地址,我们经常会新启动很多容器或者删除很多容器,容器会变来变去,此时当客户端去调用这些容器时,Service 就会统一其访问地址,客户端通过service可以访问这些变来变去的容器,保证其地址不会一直变动;

目前 Docker 官方维护了一个公共仓库 Docker Hub,其中已经包括了数量超过 2,650,000 的镜像。大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。

我们此次使用 作者 Lukas 所提供的一些测试使用的镜像:
7.2 Kubernetes 实践_第1张图片

2.RC(ReplicationController)控制器

Pod是用来封装Docker容器的对象,它具有自己的虚拟环境(端口, 环境变量等),一个Pod可以封装多个Docker容器.

RC是用来自动控制Pod部署的工具,它可以自动启停Pod,对Pod进行自动伸缩.

下面我们用命令部署一个RC控制器;
7.2 Kubernetes 实践_第2张图片

2.1 通过部署文件手动启动kubia容器

RC可以自动化维护多个pod,只需指定pod副本的数量,就可以轻松实现自动扩容缩容的操作;当一个pod宕机,RC可以自动关闭pod,并启动一个新的pod替代它来保证集群的高可用;

我们下载 作者Lukas 所提供Kubia镜像,通过Kubia镜像帮助我们启动3个容器,所启动容器是3个Pod容器,Pod容器中封装着docker容器;

下面是一个RC的部署文件,通过部署启动文件启动三个kubia容器:
cat命令向kubia-rc.yml文件中输出后续的内容,以作为开始标志,以EOF作为结束标志;

cat <<EOF > kubia-rc.yml
apiVersion: v1
kind: ReplicationController        # 创建的控制器类型
metadata:   
  name: kubia                      # 为RC控制器命名
spec:
  replicas: 3                      # 启动的pod副本的数量
  selector:                        # 选择器,用来选择RC管理的pod
    app: kubia                     # 选择标签'app=kubia'的pod,由当前RC进行管理
  template:                        # pod模板,用来创建新的pod
    metadata:
      labels:
        app: kubia                 # 指定pod的标签
    spec:
      containers:                  # 容器配置
      - name: kubia                # 容器名
        image: luksa/kubia         # 镜像
        imagePullPolicy: Never
        ports:
        - containerPort: 8080      # 容器暴露的端口
EOF
  • template:通过template设置容器模板,控制器启动容器时,将使用这个模板启动容器;
  • --image=luksa/kubia:使用的镜像名称,表明从luksa/kubia运行启动容器;
  • replicas:3 :表明启动3个RC控制器自动创建的Pod容器(Pod容器中封装着docker容器)
  • --port=8080RC控制器 对外暴露的端口
  • --generator=run/v1 kubia:创建一个ReplicationController
    7.2 Kubernetes 实践_第3张图片

RC控制器创建后,会根据配置文件中指定的pod数量3,自动创建3个pod:

  • -f命令为指定文件名;

使用create 命令创建控制器后,控制器会帮我们自动创建容器;

k create -f kubia-rc.yml

# 查看控制器
k get rc

# 查看容器
k get po -o wide

7.2 Kubernetes 实践_第4张图片

2.2 控制器的标签

控制器的部署文件中,除了我们 2.1 中介绍的参数外,还包括标签相关的参数;RC控制器也是通过指定的标签app=kubia对匹配的pod进行管理的,包括:

  • 贴标签的设置:app=kubia,自定义标签,可以根据我们的部署情况自己定义,部署文件中我们会从 luksa/kubia 镜像中启动3个容器,启动容器时,会在容器中贴上设置的这个标签;
  • 标签选择器:我们这里设置的也是app=kubia,通过此标签选择容器,用来控制有此标签的容器;

允许在pod上添加任何其他标签,而不会影响pod与RC的关联关系

k label pod kubia-vh46q type=special

k get po --show-labels

7.2 Kubernetes 实践_第5张图片

但是,如果改变pod的app标签的值,就会使这个pod脱离RC的管理,这样RC会认为这里少了一个pod,那么它会立即创建一个新的pod,来满足我们设置的3个pod的要求

k label pod kubia-qrx8r app=foo --overwrite

k get pods -L app

7.2 Kubernetes 实践_第6张图片

2.3 容器扩容缩容

某些特殊时间节点会需要更大运算能力,此时就需要我们创建更多的容器,例如十一活动,各个电商平台均需要租赁服务器,临时进行容器的扩容;

k8s对应用部署节点的扩容缩容能力非常强,只需要指定需要运行多少个pod,k8s就可以完成pod的自动伸缩;

我们使用scale 命令进行容器的扩容缩容,通过指定具体的控制器名字并给定容器数量参数及值即可进行相应的扩容缩容:

# 将pod数量缩容为1个
k scale rc kubia --replicas=1

# 将pod数量扩容为3个
k scale rc kubia --replicas=3

7.2 Kubernetes 实践_第7张图片

2.4 修改控制器标签

我们使用命令k label po kubia-qcmps type=special 来给通过控制器自动创建的三个Pod容器中的其中一个容器添加一个标签:

7.2 Kubernetes 实践_第8张图片

此时我们的控制器与容器之间的关联关系没有任何影响,然后我们再次选择一个Pod容器修改其标签app值为foo
7.2 Kubernetes 实践_第9张图片

此时我们可以看到控制器自动创建了一个新的标签,被修改标签的容器因为没有标签可以和控制器进行匹配,被认为是没有控制器管理的一个独立的容器,而控制器被创建时指定了自动创建的容器数量为3,而此时只剩了2台容器,所以其会自动新建一个新的容器;

2.5 修改控制器部署文件

我们通过命令修改控制器的部署文件,更改其默认创建容器数量为4,并添加一个新的标签foo: far,保存退出后查看我们的容器变化:

k edit rc kubia

7.2 Kubernetes 实践_第10张图片

要注意的是,修改控制器部署文件时,不允许使用tab键,tab键在这里是制表符,会导致文件保存失败,只能使用空格键进行命令行缩进;并且标签的冒号后续,也要使用空格键空一格;
7.2 Kubernetes 实践_第11张图片

这时我们可以观察到,修改文件之前创建的容器并没有任何变化,而因为我们修改了默认创建的容器数量,所以此时控制器自动又新增了一个容器,使数量符合要求,并且新增的容器的标签已经按照我们修改后的部署文件内容进行配置了;

2.6 删除控制器

最后,我们这里使用命令删除控制器,但是不关联控制器创建的容器,使容器依然保留并处于脱管状态:

k delete rc kubia --cascade=orphan

为了后续操作的方便性,建议可以简单查看 10.Service 的相关内容,并且执行 10.5 NodePort方式对外暴露端口 的相关操作;

3.pod容器

3.1 创建部署文件

在第2节的内容中,我们通过创建控制器,从而使用控制器自动帮助我们构建了3个容器,这里我们将不适用控制器,而是通过手动创建的方式创建容器,首先,我们创建kubia-manual.yml部署文件:

cat <<EOF > kubia-manual.yml 
apiVersion: v1               # k8s api版本
kind: Pod                    # 该部署文件用来创建pod资源
metadata:                
  name: kubia-manual         # pod名称前缀,后面会追加随机字符串
spec:
  containers:                # 对pod中容器的配置
  - image: luksa/kubia       # 镜像名
    imagePullPolicy: Never
    name: kubia              # 容器名
    ports:
    - containerPort: 8080    # 容器暴露的端口
      protocol: TCP
EOF
  • image是这里的核心参数,指定从哪个镜像中构建我们的Pod容器;
  • ports端口可以不配置,做自动端口映射时才需要使用,当使用手动映射时则不需要此配置;
  • imagePullPolicy是指镜像的拉取策略,默认是镜像不存在时自动拉取,我们这里设置为Never,从不拉取;
  • name是给Pod中的docker容器的配置取名,Pod容器中可以包含多个docker容器,为了区分我们可以对其进行取名;
    7.2 Kubernetes 实践_第12张图片

3.2 使用部署文件手动创建pod

k create -f kubia-manual.yml

k get po

7.2 Kubernetes 实践_第13张图片

3.3 Pod相关查询命令

  • 查看pod的部署文件的详细信息

    k get po kubia-manual -o yaml
    
  • 查看pod日志

    k logs kubia-manual
    
  • 查看容器部署节点服务器信息

    k get po -o wide
    

    在这里插入图片描述 我们可以看到,我们Pod中的docker容器部署到了 192.168.64.192 节点;

3.4 pod 标签

部署容器时,我们可以为对应容器生成不同的标签,控制器在控制容器时,可以通过对标签的选择从而控制对应的容器,这很好的解决了我们有大量容器时的分组管理难题;

我们也可以为 pod 指定自定义标签,通过标签可以对 pod 进行分组管理;

ReplicationController,ReplicationSet,Service中,都可以通过 Label 来分组管理 pod

3.4.1 创建pod时指定标签

通过kubia-manual-with-labels.yml部署文件部署pod时,我们可以在部署文件中设置标签的键值对内容;

例如下方的部署文件中为pod设置了两个自定义标签:creation_methodenv,另外还有- image:的值比较重要,表明其从哪个镜像启动docker容器;

cat <<EOF > kubia-manual-with-labels.yml
apiVersion: v1                  # api版本
kind: Pod                       # 部署的资源类型
metadata:
  name: kubia-manual-v2         # pod名
  labels:                       # 标签设置,键值对形式
    creation_method: manual     
    env: prod
spec:
  containers:                   # 容器设置
  - image: luksa/kubia          # 镜像
    name: kubia                 # 容器命名
    imagePullPolicy: Never
    ports:                      # 容器暴露的端口
    - containerPort: 8080
      protocol: TCP
EOF

3.4.2 使用部署文件创建资源

创建部署文件后,通过手动创建的方式创建容器:

k create -f kubia-manual-with-labels.yml

7.2 Kubernetes 实践_第14张图片

3.4.3 查看pod的标签

创建容器后,我们通过下方的命令列出所有的pod,并显示pod的标签

k get po --show-labels

7.2 Kubernetes 实践_第15张图片

以列的形式列出pod的标签

k get po -L creation_method,env

7.2 Kubernetes 实践_第16张图片

3.5 pod的标签的增删改查

3.5.1 pod的标签的修改

接下来我们做一些对已存在标签增删改查的一些操作;

pod kubia-manual-v2 的env标签值是prod, 我们把这个标签的值修改为 debug

修改一个标签的值时,必须指定 --overwrite 参数,目的是防止误修改,需要明确的表明就是要修改相关内容,避免因新增标签时不知道已存在此标签导致的误修改;

k label po kubia-manual-v2 env=debug --overwrite

7.2 Kubernetes 实践_第17张图片

为pod kubia-manual 设置标签

k label po kubia-manual creation_method=manual env=debug

为pod kubia-5rz9h 设置标签```bash
k label po kubia-5rz9h env=debug
k label po kubia-2cfd9 env=debug
k label po kubia-94vtb env=prob


查看标签设置的结果

```bash
k get po -L creation_method,env

7.2 Kubernetes 实践_第18张图片

3.5.2 使用标签来查询 pod

查询 creation_method=manual 的pod,使用-l来进行条件过滤,使用逗号可以分割多个条件,同时使用多个条件查询,需要注意的是!表示排查,这种特殊字符需要使用引号将其引起来;

其他查询举例:

  • creation_method!=manual :表示不等,表明查询不包含manual 的其它标签
  • env in (prod,debug):in表示匹配多个值
  • env notin (prod,debug):notin表示匹配不包含的多个值
# -l 查询creation_method=manual的Pdod
k get po -l creation_method=manual -L creation_method,env

7.2 Kubernetes 实践_第19张图片

查询有 env 标签的 pod:

# -l 查询
k get po -l env -L creation_method,env

7.2 Kubernetes 实践_第20张图片

查询 creation_method=manual 并且 env=debug 的 pod:

# -l 查询
k get po -l creation_method=manual,env=debug -L creation_method,env

7.2 Kubernetes 实践_第21张图片

查询不存在 creation_method 标签的 pod

# -l 查询
k get po -l '!creation_method' -L creation_method,env

7.2 Kubernetes 实践_第22张图片

3.5.3 删除标签

删除标签时在标签名后边跟上一个-来表示删除一个标签:

k label po kubia-94vtb env-

7.2 Kubernetes 实践_第23张图片

3.6 把pod部署到指定的节点服务器

我们不能通过直接指定服务器的地址来约束pod部署的节点,例如我们有2个工作节点,在部署时,Pod会随机选择一个节点进行部署,这是不可控的;

但是在实际业务中,我们需要的运算单元是需要指定部署到固定的单元,此时就需要通过为node设置标签,在部署pod时,使用节点选择器,来选择把pod部署到匹配的节点服务器;

3.6.1 创建节点服务器部署文件

部署文件,其中节点选择器nodeSelector设置了通过标签gpu=true来选择节点

cat <<EOF > kubia-gpu.yml
apiVersion: v1
kind: Pod
metadata:
  name: kubia-gpu          # pod名
spec:
  nodeSelector:            # 节点选择器,把pod部署到匹配的节点
    gpu: "true"            # 通过标签 gpu=true 来选择匹配的节点
  containers:              # 容器配置
  - image: luksa/kubia     # 镜像
    name: kubia            # 容器名
    imagePullPolicy: Never
EOF

创建pod kubia-gpu,并查看pod的部署节点

k create -f kubia-gpu.yml

k get po -o wide

我们可以看到此时REDAY的值为0/1,因为Pod中要包含docker容器,但是因为此时我们docker容器还没有部署,所以其状态为Pending;

7.2 Kubernetes 实践_第24张图片

3.6.2 为服务器添加标签

下面为名称为192.168.64.193的节点服务器,添加标签gpu=true

k label node 192.168.64.193 gpu=true

k get node -l gpu=true -L gpu

7.2 Kubernetes 实践_第25张图片

创建部署文件以及完成节点服务器的标签设置后,Pod会马上启动容器,并自动进行节点服务器注册;

3.6.3 查看部署结果

此时我们再次查看并查看pod的部署节点

k get po -o wide

可以看到此时已经变为了运行状态:
7.2 Kubernetes 实践_第26张图片

查看pod kubia-gpu的描述

k describe po kubia-gpu

7.2 Kubernetes 实践_第27张图片

3.7 pod 注解

可以为资源添加注解,注解不能被选择器使用

# 注解
k annotate pod kubia-manual tedu.cn/shuoming="foo bar"

k describe po kubia-manual

3.8 pod端口转发

使用 kubectl port-forward 命令设置端口转发,对外暴露pod.

使用服务器的 8888 端口,映射到 pod 的 8080 端口

k port-forward kubia-manual --address localhost,192.168.64.191 8888:8080

# 或在所有网卡上暴露8888端口
k port-forward kubia-manual --address 0.0.0.0 8888:8080

在浏览器中访问 http://192.168.64.191:8888/

4.namespace

可以使用命名空间对资源进行组织管理,我们可以创建多个命名空间,在命名空间下可以创建多个容器,多个命名空间内的容器互不影响;

但不同命名空间的资源并不完全隔离,它们之间可以通过网络互相访问

4.1 查看命名空间

# namespace 写全拼或简写均可
k get ns

k get po --namespace kube-system
k get po -n kube-system

4.2 创建命名空间

新建部署文件custom-namespace.yml,创建命名空间,命名为custom-namespace

cat <<EOF > custom-namespace.yml
apiVersion: v1
kind: Namespace
metadata:
  name: custom-namespace
EOF
# 创建命名空间
k create -f custom-namespace.yml 

7.2 Kubernetes 实践_第28张图片

4.3 将pod部署到指定的命名空间中

创建pod,并将其部署到命名空间custom-namespace

# 创建 Pod 时指定命名空间
k create -f kubia-manual.yml -n custom-namespace

# 默认访问default命名空间,默认命名空间中存在我们此前创建的kubia-manual
k get po kubia-manual

# 访问custom-namespace命名空间中的pod
k get po kubia-manual -n custom-namespace

7.2 Kubernetes 实践_第29张图片

5.相关资源的删除

  • 按名称删除, 可以指定多个名称,例如: k delete po po1 po2 po3;在删除时会首先停止关闭容器,然后再进行删除操作,所以会比较慢
k delete po kubia-gpu
  • 按标签删除,使用-l进行过滤删除
k delete po -l creation_method=manual
  • 删除命名空间和其中所有的pod
k delete ns custom-namespace
  • 删除当前命名空间中所有pod
k delete po --all

# 由于有ReplicationController,所以会自动创建新的pod
[root@master1 ~]# k get po
NAME          READY   STATUS    RESTARTS   AGE
kubia-m6k4d   1/1     Running   0          2m20s
kubia-rkm58   1/1     Running   0          2m15s
kubia-v4cmh   1/1     Running   0          2m15s
  • 删除工作空间中所有类型中的所有资源,这个操作会删除一个系统Service kubernetes,它被删除后会立即被自动重建
k delete all --all
  • 删除节点服务器中的标签
k label no 192.168.64.193 gpu- 

6.存活探针

存活探针可以自动检测容器是否正常,会每隔一段时间进行容器状态的检测,如果连续3此检测到容器异常,会自动重启容器使其恢复,并且在重启时,会自动记录重启次数;

有三种存活探针:

  • HTTP GET
    • 返回 2xx 或 3xx 响应码则认为探测成功
  • TCP
    • 与指定端口建立 TCP 连接,连接成功则为成功,一般不会使用
  • Exec
    • 在容器内执行任意的指定命令,并检查命令的退出码,退出码为0则为探测成功,一般不会使用

我们这里将介绍HTTP GET 存活探针;

6.1 创建部署文件

luksa/kubia-unhealthy 镜像是一个封装好的不健康镜像,在kubia-unhealthy镜像中,前5次请求均为正常: 从第6次请求开始会返回500异常报错;

在部署文件中,我们使用kubia-unhealthy镜像来创建容器,并且我们添加探针,来探测容器的健康状态.

探针默认每10秒探测一次,连续三次探测失败后重启容器,在启动容器时,就会自动进行第一次探测;

cat <<EOF > kubia-liveness-probe.yml
apiVersion: v1
kind: Pod
metadata:
  name: kubia-liveness               # pod名称
spec:
  containers:
  - image: luksa/kubia-unhealthy     # 镜像
    name: kubia                      # 容器名
    imagePullPolicy: Never
    livenessProbe:                   # 存活探针配置
      httpGet:                       # HTTP GET 类型的存活探针
        path: /                      # 探测路径
        port: 8080                   # 探测端口
EOF

6.2 创建 pod

k create -f kubia-liveness-probe.yml

查看创建的 kubia-liveness 容器

k get po kubia-liveness

7.2 Kubernetes 实践_第30张图片

pod的RESTARTS属性,每重启一次就会加1;

6.3 查看 pod 日志

查看pod的日志,每次探测请求时,都会打印一个日志,前5次探测是正确状态,后面3次探测是失败的,则该pod会被删除,然后进行重启,重启后日志将又会从第一次探测日志开始打印,而此时RESTARTS属性就会加1;

k logs kubia-liveness --previous
-----------------------------------------
Kubia server starting...
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1
Received request from ::ffff:172.20.3.1

6.4 查看pod描述

k describe po kubia-liveness
---------------------------------
......
    Restart Count:  6
    Liveness:       http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
......
  • delay 0表示容器启动后立即开始探测
  • timeout 1表示必须在1秒内响应,否则视为探测失败
  • period 10s表示每10秒探测一次
  • failure 3表示连续3次失败后重启容器

6.5 设置延迟时间

我们上边介绍了,在容器启动时,存活探针就会自动进行第一次探测,而某些复杂的运行启动时间可能会比较长,启动过程中可能会导致探测失败,多次失败的情况下,会导致运用再次重启;

通过设置 delay 延迟时间,可以避免在容器内应用没有完全启动的情况下就开始探测, delay 延迟时间的设定可以在部署文件中通过initialDelaySeconds参数进行设定;

cat <<EOF > kubia-liveness-probe-initial-delay.yml
apiVersion: v1
kind: Pod
metadata:
  name: kubia-liveness
spec:
  containers:
  - image: luksa/kubia-unhealthy
    name: kubia
    imagePullPolicy: Never
    livenessProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 15        # 第一次探测的延迟时间
EOF

重新设置部署文件后,可以直接使用新的部署文件重新创建容器,创建后自行测试是否符合延迟探测的预期即可;

7.Dashboard 仪表盘

Kubernetes 提供了一个控制台管理工具,可以在浏览器界面上做一些简单的管理操作,功能比较有限,其使用 Dashboard 容器进行运行管理控制台,这个容器提供了一个service 并在服务器上打开了一个端口映射,我们通过访问这个service的端口映射从而访问 Dashboard 容器;

7.1 查看 Dashboard 部署信息

我们可以使用 k get pod -n kube-system 命令查看 kube-system 所提供的一些容器,里边有一个 dashboard 容器,或者也可以直接使用 k get pod -n kube-system | grep dashboard 进行查找:
7.2 Kubernetes 实践_第31张图片

我们可以使用 k get svc -n kube-system 命令查看 dashboard 容器所提供的 service 暴露的端口信息,或者也可以直接使用 k get svc -n kube-system | grep dashboard 进行查找:
7.2 Kubernetes 实践_第32张图片

我们可以看到 https 默认的端口443映射到了一个随机的30456端口;

# 查看集群信息
k cluster-info | grep dashboard

7.2 Kubernetes 实践_第33张图片

根据上面信息可以看到 dashboard 的访问地址:
https://192.168.64.191:30456/

现在访问 dashboard 由于安全设置的原因无法访问
7.2 Kubernetes 实践_第34张图片

我们这里点击高级–继续前往;
7.2 Kubernetes 实践_第35张图片

7.2 证书验证访问(了解)

使用集群CA 生成客户端证书,该证书拥有所有权限:

cd /etc/kubernetes/ssl

# 导出证书文件
openssl pkcs12 -export -in admin.pem -inkey admin-key.pem -out kube-admin.p12

下载 /etc/kubernetes/ssl/kube-admin.p12 证书文件, 在浏览器中导入:

7.2 Kubernetes 实践_第36张图片

访问 dashboard 会提示登录, 这里我们用令牌的方式访问 :https://192.168.64.191:30456/

7.2 Kubernetes 实践_第37张图片

7.3 令牌

我们这里使用更简便的令牌方式进行权限获取:

# 获取 Bearer Token,复制输出中 ‘token:’ 开头那一行
k -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

7.2 Kubernetes 实践_第38张图片

输入获取的令牌即可进入管理后台:
7.2 Kubernetes 实践_第39张图片

7.2 Kubernetes 实践_第40张图片

7.4 使用控制台创建RC控制器

我们上一章介绍了Kubernetes 的控制台,现在我们使用控制台来创建控制器,我们复制创建控制台的部署文件,然后去掉 cat命令相关内容,只保留yml配置内容:
7.2 Kubernetes 实践_第41张图片

即可在工作台中查看我们创建的Pod容器:
7.2 Kubernetes 实践_第42张图片

8.RS(ReplicaSet)控制器

RC控制器是一个旧版本的控制器,RS是一个新版本的控制器,RS控制器是用来替代RC控制器的,俩者唯一的却别就是RS提供了增强选择器,比RC控制器只能使用标签选择器选择容器要更方便,还可以使用表达式来选择容器;

8.1 使用部署文件创建ReplicaSet控制器

在部署文件中,我们选择创建3个pod副本,如果现在标签匹配的,实际存在的副本数量要大于3的话,那么它会随机杀掉超过数量的Pod容器;

cat <<EOF > kubia-replicaset.yml
apiVersion: apps/v1              # RS 是 apps/v1中提供的资源类型
kind: ReplicaSet                 # 资源类型
metadata:
  name: kubia                    # RS 命名为 kubia
spec:
  replicas: 3                    # pod 副本数量
  selector:
    matchLabels:                 # 使用 label 选择器
      app: kubia                 # 选取标签是 "app=kubia" 的pod
  template:
    metadata:
      labels:
        app: kubia               # 为创建的pod添加标签 "app=kubia"
    spec:
      containers:
      - name: kubia              # 容器名
        image: luksa/kubia       # 镜像
        imagePullPolicy: Never
EOF

创建 ReplicaSet

k create -f kubia-replicaset.yml

# 之前脱离管理的pod被RS管理
# 设置的pod数量是3,多出的pod会被关闭
k get rs
----------------------------------------
NAME    DESIRED   CURRENT   READY   AGE
kubia   3         3         3       4s

# 多出的3个pod会被关闭
k get pods --show-labels
----------------------------------------------------------------------
NAME             READY   STATUS        RESTARTS   AGE     LABELS
kubia-8d9jj      1/1     Pending       0          2m23s   app=kubia,foo=bar
kubia-lc5qv      1/1     Terminating   0          3d5h    app=kubia
kubia-lhj4q      1/1     Terminating   0          2d22h   app=kubia
kubia-pjs9n      1/1     Running       0          3d5h    app=kubia
kubia-wb8sv      1/1     Pending       0          2m17s   app=kubia,foo=bar
kubia-xp4jv      1/1     Terminating   0          2m17s   app=kubia,foo=bar

# 查看RS描述, 与RC几乎相同
k describe rs kubia

我们可以在控制台看到目前的容器列表,其中有一个容器处于Terminating状态:
7.2 Kubernetes 实践_第43张图片

8.2 更改部署文件内容

我们先删除现有的RS控制器,并保留容器:

k delete rs kubia --cascade=orphan

然后重新使用新的部署文件内容,使用表达式的标签选择器,并修改启动容器数量为4:

cat <<EOF > kubia-replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: kubia
spec:
  replicas: 4
  selector:
    matchExpressions:       # 表达式匹配选择器
      - key: app            # label 名是 app
        operator: In        # in 运算符
        values:             # label 值列表
          - kubia
          - foo
  template:
    metadata:
      labels:
        app: kubia
    spec:
      containers:
      - name: kubia
        image: luksa/kubia
        imagePullPolicy: Never
EOF

然后创建新的RS控制器:

k create -f kubia-replicaset.yml

# 查看rs
k get rs
# 查看pod
k get po --show-labels

7.2 Kubernetes 实践_第44张图片

可使用的运算符:

  • In: label与其中一个值匹配
  • NotIn: label与任何一个值都不匹配
  • Exists: 包含指定label名称(值任意)
  • DoesNotExists: 不包含指定的label

测试完成后我们清理一下环境,方便后续测试的继续进行:

k delete all --all

k get rs
k get po

7.2 Kubernetes 实践_第45张图片

9.其它特殊场景控制器

除了RC控制器,RS控制器这种每个场景都可以使用的控制器外,还有3中特殊场景使用的控制器,我们这里做一些简单的介绍;

9.1 DaemonSet控制器

DS控制器最适合的场景就是监控场景的部署,它可以在每个节点上运行一个 pod,例如资源监控,kube-proxy等;

DaemonSet不需要指定pod数量,它会在每个节点上部署一个pod,十分适合部署监控场景的使用;下面我们来模拟部署一个监控工具,进行某一环境的监控;

cat <<EOF > ssd-monitor-daemonset.yml
apiVersion: apps/v1
kind: DaemonSet                       # 资源类型
metadata:
  name: ssd-monitor                   # DS资源命名
spec:
  selector:
    matchLabels:                      # 标签匹配器
      app: ssd-monitor                # 匹配的标签
  template:
    metadata:
      labels:
        app: ssd-monitor              # 创建pod时,添加标签
    spec:
      containers:                     # 容器配置
        - name: main                  # 容器命名
          image: luksa/ssd-monitor    # 镜像
          imagePullPolicy: Never
EOF

创建 DS

k create -f ssd-monitor-daemonset.yml

DS 创建后,会在所有节点上创建pod,包括master,我们这里一共有3台服务器,所以其部署了3个容器:

k get po -o wide

7.2 Kubernetes 实践_第46张图片

并且我们可以通过节点的label来选择节点,在所有选定的节点上部署pod:

cat <<EOF > ssd-monitor-daemonset.yml
apiVersion: apps/v1
kind: DaemonSet                       
metadata:
  name: ssd-monitor                   
spec:
  selector:
    matchLabels:                      
      app: ssd-monitor                
  template:
    metadata:
      labels:
        app: ssd-monitor              
    spec:
      nodeSelector:                   # 节点选择器
        disk: ssd                     # 选择具有标签'disk=ssd'的节点
      containers:                     
        - name: main                  
          image: luksa/ssd-monitor   
          imagePullPolicy: Never
EOF

部署文件创建后需要先清理环境,再创建控制器:

# 先清理
k delete ds ssd-monitor

# 再重新创建
k create -f ssd-monitor-daemonset.yml

查看 DS控制器 和 pod容器, 看到并没有创建pod,这是因为不存在具有disk=ssd标签的节点

k get ds

k get po

为节点’192.168.64.192’设置标签 disk=ssd,这样 DS 会在该节点上立即创建 pod

k label node 192.168.64.192 disk=ssd

k get ds

k get po -o wide

7.2 Kubernetes 实践_第47张图片

同样,进一步测试,为节点’192.168.64.193’设置标签 disk=ssd

k label node 192.168.64.193 disk=ssd
k get ds
k get po -o wide

7.2 Kubernetes 实践_第48张图片

删除’192.168.64.193’节点上的disk标签,那么该节点中部署的pod会被立即销毁

# 注意删除格式: disk-
k label node 192.168.64.193 disk-
k get ds
k get po -o wide

7.2 Kubernetes 实践_第49张图片

测试完成后,我们清理环境

k delete all --all

9.2 Job控制器

Job控制器是用来运行单个任务的,任务结束后pod控制器不再重启容器,使容器关闭退出;这种单次任务容器的运行使用控制器主要作用是为了避免容器在运行过程中的出错和意外关闭;

cat <<EOF > exporter.yml
apiVersion: batch/v1                 # Job资源在batch/v1版本中提供
kind: Job                            # 资源类型
metadata: 
  name: batch-job                    # 资源命名
spec:
  template: 
    metadata:
      labels:
        app: batch-job               # pod容器标签
    spec:
      restartPolicy: OnFailure       # 任务失败时重启
      containers:
        - name: main                 # 容器名
          image: luksa/batch-job     # 镜像
          imagePullPolicy: Never
EOF

创建 job

镜像 batch-job 中的进程,运行120秒后会自动退出

k create -f exporter.yml

k get job
-----------------------------------------
NAME        COMPLETIONS   DURATION   AGE
batch-job   0/1                      7s

k get po
-------------------------------------------------------------
NAME              READY   STATUS              RESTARTS   AGE
batch-job-q97zf   0/1     ContainerCreating   0          7s

等待两分钟后,pod中执行的任务退出,再查看job和pod

k get job
-----------------------------------------
NAME        COMPLETIONS   DURATION   AGE
batch-job   1/1           2m5s       2m16s


k get po
-----------------------------------------------------
NAME              READY   STATUS      RESTARTS   AGE
batch-job-q97zf   0/1     Completed   0          2m20s

我们也可以使用Job让pod连续运行5次,因为其默认每次只会启动一个容器进行运行,所以我们设置启动5个容器的话,会先创建第一个pod,等第一个完成后后,再创建第二个pod,以此类推,共顺序完成5个pod;

cat <<EOF > multi-completion-batch-job.yml
apiVersion: batch/v1
kind: Job
metadata: 
  name: multi-completion-batch-job
spec:
  completions: 5                    # 指定完整的数量
  template: 
    metadata:
      labels:
        app: batch-job
    spec:
      restartPolicy: OnFailure
      containers:
        - name: main
          image: luksa/batch-job
          imagePullPolicy: Never
EOF
k create -f multi-completion-batch-job.yml 

并且还可以设置并发的运行,每次运行2个容器,共完成5个容器的运行:

cat <<EOF > multi-completion-parallel-batch-job.yml
apiVersion: batch/v1
kind: Job
metadata: 
  name: multi-completion-parallel-batch-job
spec:
  completions: 5                    # 共完成5个
  parallelism: 2                    # 可以有两个pod同时执行
  template: 
    metadata:
      labels:
        app: batch-job
    spec:
      restartPolicy: OnFailure
      containers:
        - name: main
          image: luksa/batch-job
          imagePullPolicy: Never
EOF
k create -f multi-completion-parallel-batch-job.yml

9.3 Cronjob控制器

Cronjob控制器用来执行定时和重复的计划任务,例如备份,临时数据的清理等;cron时间表格式为:"几分 几点 几号 几月 周几"

其含义分别为:

  • 几分:例如0,15,30,45的设置,表明其每15分钟执行1次,第一次从0分开始执行
  • 几点 :例如3,4的设置,在每天的凌晨的3点和4点各执行4次;
  • 几号 :例如设置 * 号,表明每天的凌晨的3点和4点各执行4次;
  • 几月 :例如设置 * 号,表明每月的每一天的凌晨的3点和4点各执行4次;
  • 周几:例如设置 * 号,表明每周的每一天的凌晨的3点和4点各执行4次;
cat <<EOF > cronjob.yml
apiVersion: batch/v1beta1                # api版本
kind: CronJob                            # 资源类型
metadata:
  name: batch-job-every-fifteen-minutes
spec:
  # 0,15,30,45  - 分钟
  # 第一个*  -  每个小时
  # 第二个*  -  每月的每一天
  # 第三个*  -  每月
  # 第四个*  -  每一周中的每一天
  schedule: "0,15,30,45 * * * *"
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: periodic-batch-job
        spec:
          restartPolicy: OnFailure
          containers: 
          - name: main
            image: luksa/batch-job
            imagePullPolicy: Never
EOF

在设置时间格式中,每个字段之间使用空格分隔,单个字段多个值的,使用逗号进行分隔;上面部署文件中,设置了 每天每个小时的0,15,30,45 分执行任务,只为分钟设置了具体的数值值,其它值均设置为 * 号;

创建cronjob

k create -f cronjob.yml

# 立即查看 cronjob,此时还没有执行任务创建pod
k get cj
----------------------------------------------------------------------------------------------
NAME                              SCHEDULE             SUSPEND   ACTIVE   LAST SCHEDULE   AGE
batch-job-every-fifteen-minutes   0,15,30,45 * * * *   False     1        27s             2m17s


# 到0,15,30,45分钟时,会创建一个pod
k get po
--------------------------------------------------------------------------------------
NAME                                               READY   STATUS      RESTARTS   AGE
batch-job-every-fifteen-minutes-1567649700-vlmdw   1/1     Running     0          36s

10.Service

Service类似于一个注册中心,k8s中使用的注册中心是etcd,通过Service资源,在注册中心发现注册的所有可以访问的容器,客户端调用时调用Service,通过Service转发调用指令,找到对应注册的容器,从而避免因容器的创建销毁导致的注册地址变化无法找到容器:
7.2 Kubernetes 实践_第50张图片

在Service 帮助客户端进行调用转发时,首先Service自己要打开一个端口,以供注册中心、客户端等进行连接;

10.1 Service创建

上面我们创建了对外暴露的端口的信息,其可以使外部设备直接访问Service,但在实际项目中,我们的容器是不断变化的,经常性的会出现大批量的扩容缩容,因此我们使用Service主要还是控制器通过其统一管理容器;

在service帮我们调用容器时,会首先从注册中心得到地址,并且service自己也要打开一个端口对外暴露,方便控制器访问Service,然后再通过标签选择相应容器进行统一的调用管理;

接下来我们创建内部使用的Service 服务:

cat <<EOF > kubia-svc.yml
apiVersion: v1
kind: Service                # 资源类型
metadata:
  name: kubia                # 资源命名
spec:
  ports:
  - port: 80                 # Service向外暴露的端口
    targetPort: 8080         # 容器的端口
  selector:
    app: kubia               # 通过标签,选择名为kubia的所有pod
EOF

核心参数就是对外暴露的端口以及选择具有哪些标签的容器和容器的端口;

k create -f kubia-svc.yml

#查看service服务,也可以使用 k get service 命令
k get svc

7.2 Kubernetes 实践_第51张图片

如果没有pod具有app:kubia标签,可以创建前面的ReplicaSet资源,并让RS自动创建pod:

k create -f kubia-replicaset.yml

Kubernetes 会创建一个虚拟网络,这个虚拟网络是可以跨服务器的,我们创建的容器、Service都可以连接虚拟网络,并可以通过虚拟网络进行跨服务器的互相连接;

但是因为我们现在创建的service服务并没有向外暴露端口,暂时还不能在服务器外部访问service服务,但是我们可以使用服务器集群进行访问,通过执行curl http://10.68.123.147来从内部的虚拟网络访问Service,多次执行时我们可以看到,Service会在多个pod中轮训发送请求
7.2 Kubernetes 实践_第52张图片

当 Service 选中容器后会自动创建 EndPoint 断点对象,其本质就是一个地址列表(数组/集合),EndPoint 和 Service 会绑定到一起,存放Service获取的容器地址列表,俩者之间通过名称进行关联,也就是说它俩是同名的,或者说只要同名的俩个EndPoint 和 Service 服务就会被绑定在一起;我们可以通过 k get ep 命令查看 EndPoint 相关信息:
7.2 Kubernetes 实践_第53张图片

或者也可以通过查看 Service详情查看关联的 EndPoint 对象信息:
7.2 Kubernetes 实践_第54张图片

进行后续操作时,需要保证 9.1 使用部署文件创建ReplicaSet控制器 中的相关操作均已执行,已正确创建RS控制器集群,我们后续的操作将依托RS控制器集群进行操作;

10.2 会话亲和性

我们通过Service访容器时,可能会产生一些数据,但是后续如果再次调用时,可能调用的是其它容器,此时就无法访问此前长生的数据了,为了使Service调用的总是同一个容器,我们要使用 会话亲和性 的概念,一般使用客户端的IP地址进行关联,如果使用这个IP进行访问,只要IP不变,就访问同一个容器;

也就是说来自同一个客户端的请求,总是发给同一个pod,通过在Service的部署文件中添加 sessionAffinity 参数来进行设置:

cat <<EOF > kubia-svc-clientip.yml
apiVersion: v1
kind: Service
metadata:
  name: kubia-clientip
spec:
  sessionAffinity: ClientIP        # 回话亲和性使用ClientIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: kubia
EOF
k create -f kubia-svc-clientip.yml

k get svc

7.2 Kubernetes 实践_第55张图片

此时我们再次进入kubia-5zm2q容器,向Service发送请求,执行多次会看到,每次请求的都是同一个pod
7.2 Kubernetes 实践_第56张图片

10.3 endpoint

前边在创建Service服务时,已经简单了解了endpoint,endpoint是在Service和pod之间的一种资源,用来存储容器的地址;一个endpoint资源,包含一组pod的地址列表;

并且endpoint也可以手动创建,手动创建endpoint一般都是为了调用外部系统,比如集成地图导航时,我们调用百度地图的服务时,需要访问其外部的服务器;

10.3.1 查看kubia服务的endpoint

k describe svc kubia

7.2 Kubernetes 实践_第57张图片

查看所有endpoint:

k get ep

7.2 Kubernetes 实践_第58张图片

查看名为kubia的endpoint:

k get ep kubia

7.2 Kubernetes 实践_第59张图片

并且,endpoint虽然会自动创建,但是其必须在包含pod选择器的服务被创建时才会自动被创建,但是我们在调用外部服务时,并不会设置选择器,所以不含pod选择器的服务,不会创建 endpoint,此时就需要我们手动创建endpoint来调用外部服务了;

cat <<EOF > external-service.yml
apiVersion: v1
kind: Service
metadata:
  name: external-service        #  Service命名
spec:
  ports:
  - port: 80
EOF

10.3.2 创建没有选择器的 Service,不会创建Endpoint

k create -f external-service.yml

# 查看Service
k get svc

# 通过内部网络ip访问Service,没有Endpoint地址列表,会拒绝连接
curl http://10.68.27.124

7.2 Kubernetes 实践_第60张图片

创建endpoint关联到Service,它的名字必须与Service同名

cat <<EOF > external-service-endpoints.yml
apiVersion: v1
kind: Endpoints                 # 资源类型
metadata:
  name: external-service        # 名称要与Service名相匹配
subsets:
- addresses:                    # 包含的地址列表
  - ip: 153.3.238.110           # 百度的ip地址
  - ip: 58.20.196.140           # 搜狐的ip地址
  ports:
  - port: 80                    # 目标服务的的端口
EOF

也可以设置你自己喜欢的地址,复制官网网页连接,然后使用工具ping即可获取地址信息:
在这里插入图片描述

# 创建Endpoint
k create -f external-service-endpoints.yml
# 访问 external-service
# 多次访问,会在endpoints地址列表中轮训请求
curl http://10.68.27.124

7.2 Kubernetes 实践_第61张图片

10.3.3 通过完全限定域名访问外部服务

这种方式不需要使用 NodePort 对象添加地址链表,通过指定一个域名来直接访问,这种方式只能设置一个固定的域名;

cat <<EOF > external-service-externalname.yml
apiVersion: v1
kind: Service
metadata:
  name: external-service-externalname
spec:
  type: ExternalName
  externalName: www.baidu.com     # 域名
  ports:
  - port: 80
EOF

通过部署文件创建服务:

k create -f external-service-externalname.yml

# 访问 external-service-externalname
curl www.chinaunicom.com.cn

7.2 Kubernetes 实践_第62张图片

10.3.4 在容器内部调用

上述操作都是通过集群的IP去进行调用操作的,那么没有集群的情况怎么办呢,其实我们也可以在容器内部直接使用这些 Service 的名称去进行调用;

# 进入Pod容器
k exec -it kubia-8dpqn bash

# 通过Service名称直接访问服务
curl http://external-service-externalname

7.2 Kubernetes 实践_第63张图片

10.4 服务暴露给客户端

将Service 端口直接暴露到服务器上,映射到服务器上,这样的话我们就可以通过服务器直接访问Service端口,然后通过Service进行访问请求的转发;

10.5 NodePort方式对外暴露端口

前面创建的Service只能在集群内部网络中访问,那么怎么让客户端来访问Service呢? 共有三种方式进行Service的访问:

  • NodePort
    • 每个节点都开放一个端口
  • LoadBalance
    • NodePort的一种扩展,负载均衡器需要云基础设施来提供,需要购买云服务
  • Ingress
    • 通过 k8s 提供的一个插件来实现对外保留端口方式

今天我们只介绍 NodePort 节点端口方式对外暴露端口;

Service在暴露端口时,可以使用NodePort方式在每个服务器中都暴露相同的一个端口,每个节点(包括master),都开放这个相同的端口,可以通过任意节点的端口来访问Service;

cat <<EOF > kubia-svc-nodeport.yml
apiVersion: v1
kind: Service
metadata:
  name: kubia-nodeport
spec:
  type: NodePort           # 在每个节点上开放访问端口
  ports:
  - port: 80               # 集群内部访问该服务的端口
    targetPort: 8080       # 容器的端口
    nodePort: 30123        # 外部访问端口
  selector:
    app: kubia
EOF

创建并查看 Service:

k create -f kubia-svc-nodeport.yml

k get svc kubia-nodeport

在这里插入图片描述

可以通过任意节点的30123端口来访问 Service

  • http://192.168.64.191:30123
  • http://192.168.64.192:30123
  • http://192.168.64.193:30123
    7.2 Kubernetes 实践_第64张图片

并且可以通过外部浏览器来访问 Service:
7.2 Kubernetes 实践_第65张图片

我们通过访问可以看到,当访问不同节点时可能会由相同的容器返回相应信息,但是当连续访问同一个节点时,将会在三个容器中切换返回容器信息;

但是浏览器不会一直去切换访问,这是因为现在浏览器与服务器建立了连接缓存,只有断开后,重新建立连接,才会访问其它服务,不会浏览器连接只会存在几十秒,每隔几十秒刷新一次,还是能观察到服务切换的状态;

或者我们也可以使用命令直接 使用 service 对外暴露 pod

7.2 Kubernetes 实践_第66张图片

k expose \
    rc kubia \
    --type=NodePort \
    --name kubia-http

k get svc

这里创建了一个 service 组件,用来对外暴露pod访问,在所有节点服务器上,暴露了20916端口,通过此端口,可以访问指定pod的8080端口

访问以下节点服务器的30123端口,都可以访问该应用

注意: 要把端口修改成你生成的随机端口

  • http://192.168.64.191:30123/
  • http://192.168.64.192:30123/
  • http://192.168.64.193:30123/

11.磁盘挂载到容器

如果容器被删除,那么容器中的数据也将丢失,为了数据永久保存,需要进行容器挂载操作,那么k8s是怎么进行容器挂载的呢?

k8s中数据卷的类型分为:

  • emptyDir: 简单的空目录,是临时的一个数据存储方式,当容器被删除时,emptyDir中存储的数据也会被删除;
  • hostPath: 工作节点中的磁盘路径
  • gitRepo: 从git克隆的本地仓库
  • nfs: nfs共享文件系统

接下来我们开始尝试各种方式的数据挂载;

11.1 emptyDir方式临时存储数据

创建包含两个docker容器的pod, 它们共享同一个卷,其中一个docker运行一个应用,每10秒生成1个 index.html 文件,每隔10秒产生新的随机内容,覆盖之前的内容;

另一个docker部署Nginx服务,使用Nginx作为一个web应用服务器,去访问 index.html 文件;这样我们就可以观察到,每隔10秒生成的文件内容都会改变;

最后将其挂载到 emptyDir 中,用来验证其存储文件的策略;

cat <<EOF > fortune-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:
  - image: luksa/fortune                 # 镜像名
    name: html-genrator                  # 容器名
    imagePullPolicy: Never
    volumeMounts:
    - name: html                         # 卷名为 html
      mountPath: /var/htdocs             # 容器中的挂载路径
  - image: nginx:alpine                  # 第二个镜像名
    name: web-server                     # 第二个容器名
    imagePullPolicy: Never
    volumeMounts:
    - name: html                         # 相同的卷 html
      mountPath: /usr/share/nginx/html   # 在第二个容器中的挂载路径
      readOnly: true                     # 设置为只读
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:                               # 卷
  - name: html                           # 为卷命名
    emptyDir: {}                         # emptyDir类型的卷
EOF

部署文件中的 containers 中设置了俩个docker容器,并设置了数据卷的挂载位置,volumes 中设置了数据卷为 emptyDir;

# 清理此前创建的所有内容
k delete all --all

# 创建Pod容器
k create -f fortune-pod.yml

# 查看创建的Pod容器
k get po

7.2 Kubernetes 实践_第67张图片

此时我们已经可以使用命令查看生成的 html文件内容了,并且内容是每10秒重新生成的:
7.2 Kubernetes 实践_第68张图片

此时我们可以到部署的服务器中查看具体部署的容器:
7.2 Kubernetes 实践_第69张图片

并且可以使用 docker inspect c035 命令查看挂载详情,我们切换到挂载的目录可以查看我们生成的文件:
7.2 Kubernetes 实践_第70张图片

7.2 Kubernetes 实践_第71张图片

此时我们保持在html目录下,直接执行删除命令 kubectl delete po fortune 删除我们刚刚创建的容器,然后切换目录我们就可以看到,实际的目录已经被同步删除了:
7.2 Kubernetes 实践_第72张图片

创建Service, 通过这个Service访问pod的80端口

cat <<EOF > fortune-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: fortune
spec:
  type: NodePort
  ports:
  - port: 8088
    targetPort: 80
    nodePort: 32088
  selector:
    app: fortune
EOF
# 创建Service
k create -f fortune-svc.yml

# 查看创建的Service
k get svc

用浏览器访问 http://172.20.2.22:32088/

8.2 NFS 共享文件系统

emptyDir方式依赖于自身本身的服务器,当服务器被删除后,挂载的文件夹目录也会被删除,还是会导致数据丢失;

那么,我们是否可以单独创建一个服务器,只用作数据卷的挂载呢?这样当其它服务被删除时,并不会影响到我们用于挂载数据卷的服务器,那么这样的话,数据卷中数据的存储就需要使用网络在各个服务器之间进行存取;

centos虚拟机使用NFS系统需要先安装其系统,下面我们在191,192,193这三台服务器上安装 nfs:

# centos8使用此命令
dnf install nfs-utils

# centos7使用此命令
yum install nfs-utils

7.2 Kubernetes 实践_第73张图片

安装完成之后我们就可以共享文件夹了,首先我们在 master 节点 192.168.64.191 上创建 nfs 目录 /etc/nfs_data 用作共享文件夹,并允许 1921.68.64 网段的主机共享访问这个目录

# 创建文件夹
mkdir /etc/nfs_data

在exports文件夹中写入配置dnf install nfs-utils -bash,并设置no_root_squash:表示服务器端使用root权限访问时不进行身份降级,rw 表示读写权限, asyn 表示异步操作;并且在虚拟机中,有很多的虚拟网络,我们这里设置共享到 192.168.64.0 这个虚拟网段;

cat <<EOF > /etc/exports
/etc/nfs_data    192.168.64.0/24(rw,async,no_root_squash)
EOF

最后启动相关服务:

systemctl enable nfs-server
systemctl enable rpcbind
systemctl start nfs-server
systemctl start rpcbind

尝试在客户端主机上,例如在192.168.64.192 服务器上进行下列操作挂载远程的nfs目录:

# 新建挂载目录
mkdir /etc/web_dir/

# 在客户端, 挂载服务器的 nfs 目录
mount -t nfs 192.168.64.191:/etc/nfs_data /etc/web_dir/

8.3 持久化存储(PersistentVolume)

上一小节我们创建了共享文件夹来进行数据卷的挂载,通过网络将数据存储到另一台服务器上从而避免因服务器的变动而导致数据丢失的情况,但这样又会引起另一个问题,如果服务器的存储位置发生变化,那么俩台服务器之间的配置、部署都需要重新设置,这将是十分麻烦的事情;

所以这里引入了 PersistentVolume 对象,用于设置存储位置,存储条件和访问模式,通过PersistentVolume对象来实现服务器之间的解耦;

创建 PersistentVolume - 持久卷资源部署文件:

cat <<EOF > mongodb-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: mongodb-pv
spec:
  capacity:
    storage: 1Gi                          # 定义持久卷大小
  accessModes:
    - ReadWriteOnce                       # 只允许被一个客户端挂载为读写模式
    - ReadOnlyMany                        # 可以被多个客户端挂载为只读模式
  persistentVolumeReclaimPolicy: Retain   # 当声明被释放,持久卷将被保留
  nfs:                                    # nfs远程目录定义
    path: /etc/nfs_data
    server: 192.168.64.191
EOF
# 创建持久卷
k create -f mongodb-pv.yml

# 查看持久卷
k get pv

7.2 Kubernetes 实践_第74张图片

8.4 持久卷声明(Persistent Volume Claim )

虽然使用PersistentVolume进行了服务器之间的解耦,但通常被认为这样的解耦是不彻底的,所以又引入了 Persistent Volume Claim 对象,用于服务器与 PersistentVolume 对象之间的解耦,Persistent Volume Claim对象只设置了数据卷的存储条件和访问模式,并没有设置具体的存储路径,这样就使得如果在多台Persistent Volume对象存在的情况下,可以不必关心存储条件的设置;

可以简单理解为 Persistent Volume Claim 为一个声明,而 PersistentVolume 是一个具体实现,它们俩者之间是通过存储条件和访问模式的相似度进行匹配的,会自动关联相似度较高的俩个对象;

使用持久卷声明,使应用与底层存储技术解耦,这里只设置存储条件:

cat <<EOF > mongodb-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata: 
  name: mongodb-pvc
spec:
  resources:
    requests:
      storage: 1Gi           # 申请1GiB存储空间
  accessModes:
    - ReadWriteOnce          # 允许单个客户端读写
  storageClassName: ""       # 参考动态配置章节
EOF
k create -f mongodb-pvc.yml

k get pvc

7.2 Kubernetes 实践_第75张图片

然后我们创建一个mongodb服务

cat <<EOF > mongodb-pod-pvc.yml
apiVersion: v1
kind: Pod
metadata:
  name: mongodb
spec:
  containers:
  - image: mongo
    name: mongodb
    imagePullPolicy: Never
    securityContext:
      runAsUser: 0
    volumeMounts:
    - name: mongodb-data
      mountPath: /data/db
    ports:
    - containerPort: 27017
      protocol: TCP
  volumes:
  - name: mongodb-data
    persistentVolumeClaim:
      claimName: mongodb-pvc     # 引用之前创建的"持久卷声明"
EOF

验证 pod 中加挂载了 nfs 远程目录作为持久卷

k create -f mongodb-pod-pvc.yml

k exec -it mongodb -- mongo

use mystore
db.foo.insert({name:'foo'})
db.foo.find()

7.2 Kubernetes 实践_第76张图片

查看在 nfs 远程目录中的文件

cd /etc/nfs_data
ls

在这里插入图片描述

12.配置启动参数

一个复杂的容器是需要设置启动命令和启动参数的,某些在启动时需要设置环境不变量和环境参数,这时就需要我们自己配置启动参数了

12.1 docker 的命令行参数

在docker 中使用 ENTRYPOINT 来设置启动命令,使用CMD来对启动命令中的参数进行设置;

Dockerfile中定义命令和参数的指令:

  • ENTRYPOINT 启动容器时,在容器内执行的命令
  • CMD 对启动命令传递的参数

其中CMD可以在docker run命令中进行覆盖

例如:

......
ENTRYPOINT ["java", "-jar", "/opt/sp05-eureka-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=eureka1"]

启动容器时,可以执行:

docker run <image>

或者启动容器时覆盖CMD

docker run <image> --spring.profiles.active=eureka2

12.2 k8s中覆盖docker的ENTRYPOINTCMD

  • command 可以覆盖ENTRYPOINT
  • args 可以覆盖CMD

在镜像luksa/fortune:args中,设置了自动生成内容的间隔时间参数为10秒
7.2 Kubernetes 实践_第77张图片

可以通过k8s的args来覆盖docker的CMD,将自动生成内容的间隔时间参数设置为2秒;

cat <<EOF > fortune-pod-args.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:args
    args: ["2"]                  # docker镜像中配置的CMD是10,这里用args把这个值覆盖成2
    name: html-genrator
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    name: web-server
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
EOF
k create -f fortune-pod-args.yml

# 查看pod
k get po -o wide

7.2 Kubernetes 实践_第78张图片

重复地执行curl命令,访问该pod,会看到数据每2秒刷新一次

注意要修改成你的pod的ip

curl http://172.20.2.55

7.2 Kubernetes 实践_第79张图片

在控制台我们页可以看到所启动容器的覆盖时间参数:
7.2 Kubernetes 实践_第80张图片

12.3 环境变量

在镜像luksa/fortune:env中通过环境变量INTERVAL来指定内容生成的间隔时间

下面配置中,通过env配置,在容器中设置了环境变量INTERVAL的值,使用命令行执行的话就是 docker run -e interval=5

cat <<EOF > fortune-pod-env.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:env
    env:                        # 设置环境变量 INTERVAL=5
    - name: INTERVAL
      value: "5"
    name: html-genrator
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    name: web-server
    imagePullPolicy: Never
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
EOF
k delete po --all
k create -f fortune-pod-env.yml 

# 查看pod
k get po -o wide

# 进入pod
k exec -it fortune bash
# 查看pod的环境变量
env
------------
INTERVAL=5
......

# 从pod推出,回到宿主机
exit

在这里插入图片描述

重复地执行curl命令,访问该pod,会看到数据每5秒刷新一次

注意要修改成你的pod的ip

curl http://172.20.2.56

7.2 Kubernetes 实践_第81张图片

12.4 ConfigMap

12.4.1 创建

通过ConfigMap资源,可以从pod中把环境变量配置分离出来,使环境变量配置与pod解耦;其类似于配置中心的作用,将这些参数集中存放,从而在修改配置时不需要改变容器的相关配置,只需要动Map即可;

可以从命令行创建ConfigMap资源:

# 直接命令行创建
k create configmap fortune-config --from-literal=sleep-interval=20

或者从部署文件创建ConfigMap:

# 或从文件创建
cat <<EOF > fortune-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: fortune-config
data:
  sleep-interval: "10"
EOF

并且在这一个文件中可以设置多个值,供多个容器使用,只需要使用键去对应获取值即可;

# 创建ConfigMap
k create -f fortune-config.yml

# 查看ConfigMap的配置
k get cm fortune-config -o yaml

12.4.2 使用部署文件添加配置

我们可以使用部署文件添加12.4.1中创建的配置文件,从ConfigMap获取配置数据,设置为pod的环境变量

cat <<EOF > fortune-pod-env-configmap.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:env
    imagePullPolicy: Never
    env:
    - name: INTERVAL              # 环境变量名
      valueFrom:
        configMapKeyRef:          # 环境变量的值从ConfigMap获取
          name: fortune-config    # 使用的ConfigMap名称
          key: sleep-interval     # 用指定的键从ConfigMap取数据
    name: html-genrator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    imagePullPolicy: Never
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
EOF

12.4.3 从控制台添加配置

执行步骤 12.4.1后,我们也可以选择从控制台添加具体的配置文件,点击进入配置文件内按照键值对匹配的方式进行添加即可;
7.2 Kubernetes 实践_第82张图片

12.5 config-map–>env–>arg

配置环境变量后,可以在启动参数中使用环境变量

cat <<EOF > fortune-pod-args.yml
apiVersion: v1
kind: Pod
metadata:
  name: fortune
  labels:
    app: fortune
spec:
  containers:

  - image: luksa/fortune:args
    imagePullPolicy: Never
    env:
    - name: INTERVAL
      valueFrom:
        configMapKeyRef:
          name: fortune-config
          key: sleep-interval
    args: ["\$(INTERVAL)"]        # 启动参数中使用环境变量
    name: html-genrator
    volumeMounts:
    - name: html
      mountPath: /var/htdocs

  - image: nginx:alpine
    imagePullPolicy: Never 
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP

  volumes:
  - name: html
    emptyDir: {}
EOF

先删除之前创建的ComfigMap后,从磁盘文件创建 ConfigMap

d delete cm fortune-config

创建一个文件夹,存放配置文件

cd ~/
mkdir configmap-files
cd configmap

创建nginx的配置文件,启用对文本文件和xml文件的压缩

cat <<EOF > my-nginx-config.conf
server {
    listen           80;
    server_name      www.kubia-example.com;
    
    gzip             on;
    gzip_types       text/plain application/xml;
    
    location / {
        root         /ur/share/nginx/html;
        index        index.html index.htm;
    }
}
EOF

添加sleep-interval文件,写入值25

cat <<EOF > sleep-interval
25
EOF

从configmap-files文件夹创建ConfigMap

cd ~/

k create configmap fortune-config \
--from-file=configmap-files 

13.Deployment

常见的系统升级有俩种,一种是直接杀掉所有旧版本,然后启动新版本,一般称为停机升级,这种升级方式的缺点就是在停机过程中会造成系统不可用,影响用户体验;

另一种是逐步替换,杀掉一个旧版本,启动一个新版本,一直到所有旧版本杀掉,新版本启动,这种升级一般称为滚动升级,缺点就是用户在使用中,有些请求会请求到旧版本,有些请求会请求到新版本,并且对于版本之间的耦合兼容要求较高,新版本和旧版本之间必须要相互兼容;

相对来说,停机升级会比较简单,而滚动升级就会比较麻烦,而Deployment 就是是一种自动实现滚动升级的资源,用于部署升级应用;

13.1 创建 Deployment

创建Deployment时,ReplicaSet资源会随之创建,实际Pod是由ReplicaSet创建和管理,而不是由Deployment直接管理

Deployment可以在应用滚动升级过程中, 引入另一个RepliaSet, 并协调两个ReplicaSet,与RepliaSet的配置设计基本一致;

cat <<EOF > kubia-deployment-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: kubia
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        imagePullPolicy: Never
        name: nodejs
EOF
k create -f kubia-deployment-v1.yml --record

k get deploy

k get rs

k get po

k rollout status deploy kubia

7.2 Kubernetes 实践_第83张图片

我们可以看到Deployment对象帮我们创建了3个RS控制器对象,而RS控制器对象帮我们创建了3个容器对象;

其中RS控制对象的名字继承了Deployment对象的名字,并且RS控制对象的名字对镜像名进行了hash运行产生了hash值加到了名字后面;

同样的,容器对象的名字也继承了RS控制对象的名字,并且容器对象的名字对RS控制对象的镜像名也进行了hash运行产生了hash值加到了名字后面;

7.2 Kubernetes 实践_第84张图片

接下来我们创建一个Service服务的Node方式对外暴露的断开,执行 10.5 NodePort方式对外暴露端口 小节的内容,便于我们使用Service观察访问的情况;
7.2 Kubernetes 实践_第85张图片

13.2 升级 Deployment

只需要在 pod 模板中修改镜像的 Tag, Deployment 就可以自动完成升级过程

Deployment的升级策略

  • 滚动升级 Rolling Update - 渐进的删除旧的pod, 同时创建新的pod, 这是默认的升级策略
  • 重建 Recreate - 一次删除所有旧的pod, 再重新创建新的pod

minReadySeconds设置为10秒, 减慢滚动升级速度, 便于我们观察升级的过程.

k patch deploy kubia -p '{"spec": {"minReadySeconds": 10}}'

13.3 触发滚动升级

修改 Deployment 中 pod 模板使用的镜像就可以触发滚动升级

为了便于观察, 我们新打开一个标签,在另一个191终端页面中执行循环, 通过 service 来访问pod,循坏调用服务:

while true; do curl http://192.168.64.191:30123; sleep 0.5s; done

7.2 Kubernetes 实践_第86张图片

可以看到目前访问的都是V1版本的内容,接下来我们修改镜像将其改为V2版本:

k set image deploy kubia nodejs=luksa/kubia:v2

7.2 Kubernetes 实践_第87张图片

我们看到已经开始启动V2版本了,通过不断的杀掉V1启动V2的方式来将版本更新完成,我们可以通过不同的命令来了解升级的过程和原理

# 查看升级滚动状态
k rollout status deploy kubia

# 查看控制器
k get rs

# 查看容器
k get po --show-labels

# 查看控制器详情,可以查看单独设置的hash值标签
k describe rs kubia-577cffc4f5

7.2 Kubernetes 实践_第88张图片

在升级过程中,Deployment对象会创建多个RS对象,分别控制新版本和旧版本,因为RS控制器是通过标签来选择创建的容器的,而这时同一个控制器会选择新版本也会控制旧版本,这是怎么做到的呢?

这是因为在创建容器是会给容器设置一个额外的hash值标签,通过此标签来分别进行选择,控制新版本的RS控制器是一个,控制旧版本的RS控制器是另一个;

13.4 自动回滚 Deployment

我们再设置一个V3版本,v3 镜像中的应用模拟一个 bug, 从第5次请求开始, 会出现 500 错误:

k set image deploy kubia nodejs=luksa/kubia:v3

出错后,我们执行回滚命令,使其回退到此前的可用版本V2版本:

k rollout undo deploy kubia

我们观察Service连接的变化情况,由V2替换V3时的报错逐渐增多,再到V3回退到V2的报错逐渐减少:
7.2 Kubernetes 实践_第89张图片

13.5 控制滚动升级速率

滚动升级时是先创建新版本pod,再销毁旧版本pod的,我们可以通过参数设置来控制滚动升级中的新建容器数量和销毁容器数量;

  • 新建容器时允许超出的新建容器数量:maxSurge - 默认25%
    • 允许超出的 pod 数量.
    • 如果实际pod数量是4, 滚动升级期间, 最多只允许实际有5个 pod,也就是说每次只允许新建一个新容器;
  • 销毁容器时,允许不可用的容器数量:maxUnavailable - 默认 25%
    • 允许有多少 pod 处于不可用状态.
    • 如果实际pod数量是4, 滚动升级期间, 最多只允许 1 个 pod 不可用, 也就是说任何时间都要保持至少有 3 个可用的pod.

容器数量可以使用百分比表示,也可以使用整数直接表示数量;

# 查看升级速率参数
k get deploy -o yaml

7.2 Kubernetes 实践_第90张图片

13.6 暂停滚动升级

接下来我们尝试将 image 升级到 v4 版本,在触发更新后立即暂停更新.

这时会有一个新版本的 pod 启动, 可以暂停更新过程, 让少量用户可以访问到新版本, 并观察其运行是否正常.

根据新版本的运行情况, 可以继续完成更新, 或回滚到旧版本.

k set image deploy kubia nodejs=luksa/kubia:v4

# 暂停
k rollout pause deploy kubia

# 继续
k rollout resume deploy kubia

10.8 自动阻止出错版本升级

在升级过程中,我们可以设置 minReadySeconds 参数来自动控制出错版本是否继续升级,其会在升级中等待容器就绪后倒计时一段时间(默认为10秒),然后才会下一步继续的升级;

minReadySeconds

  • 新创建的pod成功运行多久后才,继续升级过程
  • 在该时间段内, 如果容器的就绪探针返回失败, 升级过程将被阻止

最后还需要添加一个就绪探针,通过 minReadySeconds 参数设置倒计时参数,在倒计时开始时开始探测容器的就绪状态,探测成功则容器为就绪状态,探测失败则设置容器状态为未就绪状态,在倒计时结束后,如果获取容器还是未就绪状态,则认为升级失败,从而停止升级状态;

cat <<EOF > kubia-deployment-v3-with-readinesscheck.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: kubia
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v3
        name: nodejs
        imagePullPolicy: Never
        readinessProbe:
          periodSeconds: 1
          httpGet:
            path: /
            port: 8080
EOF

当然也可以在控制台中,完整的替换部署策略:
7.2 Kubernetes 实践_第91张图片

我们这里设置探测时间为1秒探测1测,并且只要探测成功,立即变为就绪状态,并且设置了滚动升级的策略,升级为V3。同样模拟第5次开始升级状态为V3:

k apply -f kubia-deployment-v3-with-readinesscheck.yml

就绪探针探测间隔设置成了 1 秒, 第5次请求开始每次请求都返回500错, 容器会处于未就绪状态. minReadySeconds被设置成了10秒, 只有pod就绪10秒后, 升级过程才会继续.所以这是滚动升级过程会被阻塞, 不会继续进行.
7.2 Kubernetes 实践_第92张图片

我们可以看到,在升级过程中会有报错的提醒,并且新建的容器中有一个容器状态是未就绪,此时有未就绪状态的容器,那么就不会开始倒计时,升级也就不会继续进行下去:
7.2 Kubernetes 实践_第93张图片

默认升级过程被阻塞10分钟后, 升级过程会被视为失败, Deployment描述中会显示超时(ProgressDeadlineExceeded),这时升级也就不会再继续进行了:

k describe deploy kubia
-----------------------------
......
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    False   ProgressDeadlineExceeded
......

这是只能通过手动执行 rollout undo 命令进行回滚

k rollout undo deploy kubia

14.常用命令总结

  • kubectl get cs:查看集群系统服务基础信息(正常为Healthy健康状态)
  • kubectl get no:查看节点服务器基础信息(正常为Ready就绪状态)
  • kubectl get rc:查看RC控制器基础信息
  • kubectl get po:查看创建的容器基础信息(正常为Running状态)
  • kubectl get svc:svc是service缩写,这里写全写也可以,获取service信息,也可以查询指定service信息,例如k get svc kubia-nodeport
  • kubectl get po kubia-manual -o yaml:查看Pod中部署的容器的详细信息;
  • kubectl get po kubia-manual -o yaml:查看pod日志
  • kubectl get po -o wide:查看容器部署节点服务器信息
  • kubectl get po --show-labels:列出所有的pod,并显示pod的标签
  • kubectl get po -L creation_method,env:以列的形式所有的pod,并显示pod的标签
  • kubectl create -f xxx.yml:使用部署配置文件创建Pod,-f参数后跟yml配置文件
  • kubectl label po kubia-manual-v2 env=debug:为Pod容器新增标签
  • kubectl label po kubia-manual-v2 env=debug --overwrite: 修改Pod容器的标签
  • kubectl label po kubia-94vtb env-:删除Pod容器
  • kubectl get po -L creation_method,env:查看Pod容器的标签
  • kubectl get po -l creation_method=manual -L creation_method,env:使用标签查询匹配的Pod容器
  • kubectl label node 192.168.64.193 gpu=true:为指定节点的服务器添加标签
  • kubectl get node -l gpu=true -L gpu :查看节点服务器的标签信息
  • kubectl describe po kubia-gpu:查看Pod服务器的详细描述信息
  • kubectl get ns:查看系统中存在的命名空间
  • kubectl get po -n xxx : xxx为命名空间名,查看此命名空间内有哪些服务
  • kubectl delete rc kubia --cascade=orphan :删除控制器,但保留容器
  • kubectl edit rc kubia:修改部署文件,后续跟文件类型参数(rc/pod),文件名
  • kubectl delete cj -all:删除所有计划任务,,其中 -all也可以替换为集体的任务名
  • kubectl get pv :查看PersistentVolume对象
  • kubectl get pvc :查看Persistent Volume Claim 对象

你可能感兴趣的:(零基础入门到就业--JAVA篇,kubernetes,容器,云原生)