zoukankan      html  css  js  c++  java
  • 深入剖析Kubernetes学习笔记:Kubernetes集群搭建与实践(11)

    一、什么才是 Kubernetes 项目能“认识”的方式呢?

    1、这就是使用 Kubernetes 的必备技能:编写配置文件。

    备注:这些配置文件可以是 YAML 或者 JSON 格式的。为方便阅读与理解,在后面的讲解中,我会统一使用 YAML 文件来指代它们。

    Kubernetes 跟 Docker 等很多项目最大的不同,就在于它不推荐你使用命令行的方式直接运行容器(虽然 Kubernetes 项目也支持这种方式,比如:kubectl run),而是希望你用 YAML 文件的方式,即:把容器的定义、参数、配置,统统记录在一个 YAML 文件中,然后用这样一句指令把它运行起来:

    kubectl create -f 我的配置文件

    这么做最直接的好处是,你会有一个文件能记录下 Kubernetes 到底“run”了什么

    像这样的一个 YAML 文件,对应到 Kubernetes 中,就是一个 API Object(API 对象)。当你为这个对象的各个字段填好值并提交给 Kubernetes 之后,Kubernetes 就会负责创建出这些对象所定义的容器或者其他类型的 API 资源。

    2、Deployment

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      selector:
        matchLabels:
          app: nginx
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.7.9
            ports:
            - containerPort: 80

    可以看到,这个 YAML 文件中的 Kind 字段,指定了这个 API 对象的类型(Type),是一个 Deployment。

    所谓 Deployment,是一个定义多副本应用(即多个副本 Pod)的对象,我在前面的文章中(也是第 9 篇文章《从容器到容器云:谈谈 Kubernetes 的本质》)曾经简单提到过它的用法。

    此外,Deployment 还负责在 Pod 定义发生变化时,对每个副本进行滚动更新(Rolling Update)。

    在上面这个 YAML 文件中,我给它定义的 Pod 副本个数 (spec.replicas) 是:2。

    二、常用命令和应用发布

    1、kubectl get 获取(GET)指定的 API 对象

    $ kubectl get pods -l app=nginx
    NAME                                READY     STATUS    RESTARTS   AGE
    nginx-deployment-67594d6bf6-9gdvr   1/1       Running   0          10m
    nginx-deployment-67594d6bf6-v6j7w   1/1       Running   0          10m

    kubectl get 指令的作用,就是从 Kubernetes 里面获取(GET)指定的 API 对象。可以看到,在这里我还加上了一个 -l 参数,即获取所有匹配 app: nginx 标签的 Pod。

    需要注意的是,在命令行中,所有 key-value 格式的参数,都使用“=”而非“:”表示。

    2、kubectl describe 查看一个 API 对象的细节

    $ kubectl describe pod nginx-deployment-67594d6bf6-9gdvr
    Name:               nginx-deployment-67594d6bf6-9gdvr
    Namespace:          default
    Priority:           0
    PriorityClassName:  <none>
    Node:               node-1/10.168.0.3
    Start Time:         Thu, 16 Aug 2018 08:48:42 +0000
    Labels:             app=nginx
                        pod-template-hash=2315082692
    Annotations:        <none>
    Status:             Running
    IP:                 10.32.0.23
    Controlled By:      ReplicaSet/nginx-deployment-67594d6bf6
    ...
    Events:
     
      Type     Reason                  Age                From               Message
     
      ----     ------                  ----               ----               -------
      
      Normal   Scheduled               1m                 default-scheduler  Successfully assigned default/nginx-deployment-67594d6bf6-9gdvr to node-1
      Normal   Pulling                 25s                kubelet, node-1    pulling image "nginx:1.7.9"
      Normal   Pulled                  17s                kubelet, node-1    Successfully pulled image "nginx:1.7.9"
      Normal   Created                 17s                kubelet, node-1    Created container
      Normal   Started                 17s                kubelet, node-1    Started container

    在 kubectl describe 命令返回的结果中,你可以清楚地看到这个 Pod 的详细信息,比如它的 IP 地址等等。其中,有一个部分值得你特别关注,它就是Events(事件)。

    在 Kubernetes 执行的过程中,对 API 对象的所有重要操作,都会被记录在这个对象的 Events 里,并且显示在 kubectl describe 指令返回的结果中。

    比如,对于这个 Pod,我们可以看到它被创建之后,被调度器调度(Successfully assigned)到了 node-1,拉取了指定的镜像(pulling image),然后启动了 Pod 里定义的容器(Started container)。

    所以,这个部分正是我们将来进行 Debug 的重要依据。如果有异常发生,你一定要第一时间查看这些 Events,往往可以看到非常详细的错误信息。

    3、kubectl replace 变更更新

     $ kubectl replace -f nginx-deployment.yaml

    不推荐使用

    4、kubectl apply Kubernetes 对象的创建和更新操作

    $ kubectl apply -f nginx-deployment.yaml
    # 修改 nginx-deployment.yaml 的内容
    $ kubectl apply -f nginx-deployment.yaml

    这样的操作方法,是 Kubernetes“声明式 API”所推荐的使用方法。也就是说,作为用户,你不必关心当前的操作是创建,还是更新,你执行的命令始终是 kubectl apply,而 Kubernetes 则会根据 YAML 文件的内容变化,自动进行具体的处理。

    5、而这个流程的好处是:

    它有助于帮助开发和运维人员,围绕着可以版本化管理的 YAML 文件,而不是“行踪不定”的命令行进行协作,从而大大降低开发人员和运维人员之间的沟通成本。

    举个例子,一位开发人员开发好一个应用,制作好了容器镜像。那么他就可以在应用的发布目录里附带上一个 Deployment 的 YAML 文件。

    而运维人员,拿到这个应用的发布目录后,就可以直接用这个 YAML 文件执行 kubectl apply 操作把它运行起来。

    这时候,如果开发人员修改了应用,生成了新的发布内容,那么这个 YAML 文件,也就需要被修改,并且成为这次变更的一部分。

    而接下来,运维人员可以使用 git diff 命令查看到这个 YAML 文件本身的变化,然后继续用 kubectl apply 命令更新这个应用。

    所以说,如果通过容器镜像,我们能够保证应用本身在开发与部署环境里的一致性的话,那么现在,Kubernetes 项目通过这些 YAML 文件,就保证了应用的“部署参数”在开发与部署环境中的一致性。

    而当应用本身发生变化时,开发人员和运维人员可以依靠容器镜像来进行同步;当应用部署参数发生变化时,这些 YAML 文件就是他们相互沟通和信任的媒介。

    三、Volume

    在 Kubernetes 中,Volume 是属于 Pod 对象的一部分。所以,我们就需要修改这个 YAML 文件里的 template.spec 字段,如下所示:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      selector:
        matchLabels:
          app: nginx
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.8
            ports:
            - containerPort: 80
            volumeMounts:
            - mountPath: "/usr/share/nginx/html"
              name: nginx-vol
          volumes:
          - name: nginx-vol
            emptyDir: {}

    可以看到,我们在 Deployment 的 Pod 模板部分添加了一个 volumes 字段,定义了这个 Pod 声明的所有 Volume。它的名字叫作 nginx-vol,类型是 emptyDir

    1、那什么是 emptyDir 类型呢?

    它其实就等同于我们之前讲过的 Docker 的隐式 Volume 参数,即:不显式声明宿主机目录的 Volume。所以,Kubernetes 也会在宿主机上创建一个临时目录,这个目录将来就会被绑定挂载到容器所声明的 Volume 目录上。

    备注:不难看到,Kubernetes 的 emptyDir 类型,只是把 Kubernetes 创建的临时目录作为 Volume 的宿主机目录,交给了 Docker。这么做的原因,是 Kubernetes 不想依赖 Docker 自己创建的那个 _data 目录。

    而 Pod 中的容器,使用的是 volumeMounts 字段来声明自己要挂载哪个 Volume,并通过 mountPath 字段来定义容器内的 Volume 目录,比如:/usr/share/nginx/html。

    当然,Kubernetes 也提供了显式的 Volume 定义,它叫做 hostPath。比如下面的这个 YAML 文件:

    这样,容器 Volume 挂载的宿主机目录,就变成了 /var/data。

    在上述修改完成后,我们还是使用 kubectl apply 指令,更新这个 Deployment:

    $ kubectl apply -f nginx-deployment.yaml

    接下来,你可以通过 kubectl get 指令,查看两个 Pod 被逐一更新的过程:

    $ kubectl get pods
    NAME                                READY     STATUS              RESTARTS   AGE
    nginx-deployment-5c678cfb6d-v5dlh   0/1       ContainerCreating   0          4s
    nginx-deployment-67594d6bf6-9gdvr   1/1       Running             0          10m
    nginx-deployment-67594d6bf6-v6j7w   1/1       Running             0          10m
    $ kubectl get pods
    NAME                                READY     STATUS    RESTARTS   AGE
    nginx-deployment-5c678cfb6d-lg9lw   1/1       Running   0          8s
    nginx-deployment-5c678cfb6d-v5dlh   1/1       Running   0          19s

    从返回结果中,我们可以看到,新旧两个 Pod,被交替创建、删除,最后剩下的就是新版本的 Pod。

    然后,你可以使用 kubectl describe 查看一下最新的 Pod,就会发现 Volume 的信息已经出现在了 Container 描述部分:

    ...
    Containers:
      nginx:
        Container ID:   docker://07b4f89248791c2aa47787e3da3cc94b48576cd173018356a6ec8db2b6041343
        Image:          nginx:1.8
        ...
        Environment:    <none>
        Mounts:
          /usr/share/nginx/html from nginx-vol (rw)
    ...
    Volumes:
      nginx-vol:
        Type:    EmptyDir (a temporary directory that shares a pod's lifetime)

    备注:作为一个完整的容器化平台项目,Kubernetes 为我们提供的 Volume 类型远远不止这些,在容器存储章节里,我将会为你详细介绍这部分内容

    最后,你还可以使用 kubectl exec 指令,进入到这个 Pod 当中(即容器的 Namespace 中)查看这个 Volume 目录:

    $ kubectl exec -it nginx-deployment-5c678cfb6d-lg9lw -- /bin/bash
    # ls /usr/share/nginx/html

    此外,你想要从 Kubernetes 集群中删除这个 Nginx Deployment 的话,直接执行:

    $ kubectl delete -f nginx-deployment.yaml

    四、如果你想要快速熟悉 Kubernetes,请按照下面的流程进行练习:

    所以,如果你想要快速熟悉 Kubernetes,请按照下面的流程进行练习:

    首先,在本地通过 Docker 测试代码,制作镜像;
    然后,选择合适的 Kubernetes API 对象,编写对应 YAML 文件(比如,Pod,Deployment);
    最后,在 Kubernetes 上部署这个 YAML 文件。
    更重要的是,在部署到 Kubernetes 之后,接下来的所有操作,要么通过 kubectl 来执行,要么通过修改 YAML 文件来实现,就尽量不要再碰 Docker 的命令行了

  • 相关阅读:
    nohup 运行后台程序
    配置了yum本地源
    rhel 6.7 离线安装docker
    java timer 执行任务
    遇到的sql关键字
    mysql事务和锁
    Mysql命令大全
    mysql keepalived
    mysql主从复制
    mysql从binlog恢复数据
  • 原文地址:https://www.cnblogs.com/luoahong/p/12335304.html
Copyright © 2011-2022 走看看