Kubernetes:入门案例

一. 简介

Kubernetes 里“最小”的 API 对象是 Pod。Pod 可以等价为一个应用,所以,Pod 可以由多个紧密协作的容器组成。在 Kubernetes 中,我们经常会看到它通过一种 API 对象来管理另一种 API 对象,比如 Deployment 和 Pod 之间的关系,而由于 Pod 是“最小”的对象,所以它往往都是被其他对象控制的。
这种组合方式,正是 Kubernetes 进行容器编排的重要模式。

二. 流程

关于如何演示kubectl apply 如何使用,下面讲创造一个这样的场景:

运行一个3个副本的nginx应用,并且nginx指定版本为1.7.9,同时对外暴露80端口。

本篇文章相关代码,已在GitHub此链接:demo-deployment.yaml

2.1 编写YAML

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

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

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

2.2 分析YAML

针对如上的yaml,细节参数含义如下:

  • apiVersion:Api版本
  • kind:指定当前Api type为Deployment
  • spec.selector.mathcLabels:标签,作为过滤筛选使用
  • spec.replicas:当前定义的Pod的数量,也就是期望值,Kubernetes会一直保证期望值=实际值
  • spec.containers.image:容器的具体镜像名称+版本号
  • spec.containers:容器相关配置

Labels这个字段也是上面的重点。这样的每一个 API 对象都有一个叫作 Metadata 的字段,这个字段就是 API 对象的“标识”,即元数据,它也是我们从 Kubernetes 里找到这个对象的主要依据。这其中最主要使用到的字段是 Labels。换句话说,Labels 就是一组 key-value 格式的标签。

而像 Deployment 这样的控制器对象,就可以通过这个 Labels 字段从 Kubernetes 中过滤出它所关心的被控制对象。

比如,在上面这个YAML文件中,Deployment 会把所有正在运行的、携带“app: nginx”标签的 Pod 识别为被管理的对象,并确保这些 Pod 的总数严格等于三个。而这个过滤规则的定义,是在 Deployment 的“spec.selector.matchLabels”字段。我们一般称之为:Label Selector。

一个 Kubernetes 的 API 对象的定义,大多可以分为 Metadata 和 Spec 两个部分。

  • Metadata
    Metadata存放的是这个对象的元数据,对所有 API 对象来说,这部分的字段和格式基本上是一样的。
  • Spec
    Spec存放的是属于这个对象独有的定义,用来描述它所要表达的功能。

2.3 运行YAML

指令如下:

kubectl apply -f demo-deployment.yaml (推荐)
# kubectl create -f demo-deployment.yaml

成功后,如下图:


success

2.4 检查Pods

通过kubectl get命令检查这个YAML运行的运行结果是否与期望一致:

kubectl get pods -l app=nginx

NAME                               READY   STATUS    RESTARTS   AGE
demo-deployment-5d59d67564-6dxnv   1/1     Running   0          2m23s
demo-deployment-5d59d67564-lgxzx   1/1     Running   0          2m23s
demo-deployment-5d59d67564-pcdk5   1/1     Running   0          2m23s

看到如下的状态,我们可以看到现在有3个 Pod 处于 Running 状态,也就意味着我们这个 Deployment 所管理的 Pod 都处于预期的状态。


3 pods

kubectl get指令的作用,就是从 Kubernetes 里面获取(GET)指定的 API 对象。可以看到,在这里还加上了一个-l参数,即获取所有匹配 app: nginx标签的 Pod。
一个细节问题:在命令行中,所有 key-value格式的参数,都使用“=”而非“:”表示。

2.5 kubectl describe

我们从上面的Pod Name中挑选一个Pod,使用kubectl describe进入查看。

kubectl describe pod demo-deployment-5d59d67564-6dxnv

Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  8m     default-scheduler  Successfully assigned default/demo-deployment-5d59d67564-6dxnv to docker-desktop
  Normal  Pulled     7m59s  kubelet            Container image "nginx:1.7.9" already present on machine
  Normal  Created    7m59s  kubelet            Created container nginx
  Normal  Started    7m58s  kubelet            Started container nginx

kubectl describe命令返回的结果中,可以清楚地看到这个 Pod 的详细信息,比如它的 IP 地址等等。

在整个pod内容体里面,我们可以关注一下Events的内容。在 Kubernetes 执行的过程中,对 API 对象的所有重要操作,都会被记录在这个对象的 Events 里,并且显示在kubectl describe指令返回的结果中。

这个Events从上向下看即可,对于当前这个 Pod,我们可以看到它被创建之后,被调度器调度(Successfully assigned)到了 docker-desktop,拉取了指定的镜像(本地)(Container image),然后启动了 Pod 里定义的容器(Started container)

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

2.6 更新YAML(patch功能)

如果我们要对这个 Nginx 服务进行升级,把它的镜像版本从 1.7.9 升级为 1.8,那么操作还是很简单。

  1. 只需要变动YAML的nginx版本即可
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.8.0 # 这里被从1.7.9修改为1.8
          ports:
            - containerPort: 80
  1. 执行kubectl apply指令
kubectl apply -f demo-deployment.yaml (推荐)
# kubectl replace -f demo-deployment.yaml(不推荐)
  1. 查看Pods状态
kubectl get pods -l app=nginx
NAME                               READY   STATUS    RESTARTS   AGE
demo-deployment-64c9d67564-9m64m   1/1     Running   0          39s
demo-deployment-64c9d67564-m7l8w   1/1     Running   0          37s
demo-deployment-64c9d67564-rv5vs   1/1     Running   0          82s

是否觉得同一条指令kubectl apply可以进行增改操作很神奇?这就是 Kubernetes“声明式 API”所推荐的使用方法。
执行的命令始终是 kubectl apply,而 Kubernetes 则会根据 YAML 文件的内容变化,自动进行具体的处理。而这个流程的好处是,它有助于帮助开发和运维人员,围绕着可以版本化管理的 YAML 文件,而不是“行踪不定”的命令行进行协作,从而大大降低开发人员和运维人员之间的沟通成本。

2.7 删除demo-deployment

Kubernetes会自动删除YAML所相关的所有程序,这也是自动化与自描述带来的好处。
执行如下指令即可:

kubectl delete -f demo-deployment.yaml

三. Volume

3.1 Volume基础类型

这儿的Volume是Kubernetes里面,而非docker,但是本质上出别不大。具体为如下俩种:

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

  • hostPath
    与上面相反,就是显式的 Volume 定义。

3.2 案例

  1. emptyDir类型
    参考项目项目中的V2版本,使用的是emptyDir类型。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: "/usr/share/nginx/html"
              name: nginx-volume
      volumes:
        - name: nginx-volume
          emptyDir: {}

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

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

  1. hostPath类型
    参考项目项目中的V3版本,使用的是hostPath类型。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: "/usr/share/nginx/html"
              name: nginx-volume
      volumes:
        - name: nginx-volume
          hostPath:
            path: "/var/tmp"

这个和上面类型原理同等,只是容器 Volume 挂载的宿主机目录,就变成了 /var/tmp

3.4 kubectl exec

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

kubectl exec -it demo-deployment-5846465d4d-vpkb2 -- /bin/bash
# ls /usr/share/nginx/html/

四. 总结

关于Kubernetes与Docker的组合,我们已经可以按照如下步骤进行落地编写了:

  1. 在本地通过 Docker 测试代码,制作镜像
  2. 选择合适的 Kubernetes API 对象,编写对应 YAML 文件(比如,Pod,Deployment)
  3. 在 Kubernetes 上部署这个 YAML 文件。

我们会发现Kubernetes与Docker很多指令很相同,但是以后我们还是少用Docker指令,毕竟Docker只是整个云原生中很小的一个实现类而已,Kubernetes才是中枢系统。
本篇文章,我讲了一个最常见的Deployment落地的全生命周期操作流程,关于每个细节其实还有很多其他内容,这也是后面细分方向文章的重点。

最后,欢迎关注我的博客:https://blog.wyatt.plus

Reference

https://kubernetes.io/docs/setup/
https://medium.com/google-cloud/kubernetes-101-pods-nodes-containers-and-clusters-c1509e409e16
https://time.geekbang.org/column/article/40008?utm_campaign=guanwang&utm_source=baidu-ad&utm_medium=ppzq-pc&utm_content=title&utm_term=baidu-ad-ppzq-title

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容