Kubernetes 入门总结

栏目: 编程工具 · 发布时间: 4年前

内容简介:Kubernetes 简称 k8s,是 google 在 2014 年发布的一个开源项目。Kubernetes 解决了哪些问题?真实的生产环境应用会包含多个容器,而这些容器还很可能会跨越多个服务器主机部署。Kubernetes 提供了为那些工作负载大规模部署容器的编排与管理能力。Kubernetes 编排让你能够构建多容器的应用服务,在集群上调度或伸缩这些容器,以及管理它们随时间变化的健康状态。

Kubernetes 简称 k8s,是 google 在 2014 年发布的一个开源项目。

Kubernetes 解决了哪些问题?

真实的生产环境应用会包含多个容器,而这些容器还很可能会跨越多个服务器主机部署。Kubernetes 提供了为那些工作负载大规模部署容器的编排与管理能力。Kubernetes 编排让你能够构建多容器的应用服务,在集群上调度或伸缩这些容器,以及管理它们随时间变化的健康状态。

  • kubernetes 基础
  • kubernetes 优化
  • kubernetes 实战

k8s 中有几个重要概念。

概念 介绍
cluster 一个 k8s 集群
master 集群中的一台机器,是集群的核心,负责整个集群的管理和控制
node 集群中的一台机器,是集群中的工作负载节点
pod k8s 最小调度单位,每个 pod 包含一个或多个容器
controller kubernetes 通过 controller 来管理 pod
service 将服务内容与具体的 pod 分离,负责自动将请求分发到正确的 pod 处
namespace 将 cluster 逻辑上划分成多个虚拟 cluster,每个 cluster 就是一个 namespace

Cluster 是计算、存储和网络资源的集合,kubernetes 利用这些资源运行各种基于容器的应用。

Master 是 cluster 的大脑,运行着的 Daemon(一直运行的服务端程序,又称为守护进程)服务包括 kube-apiserver、kube-scheduler、kube-controller-manager、etcd 和 pod 网络。

  • kube-apiserver
    • 提供 restful api,即 kubernetes api。apiserver 是 kubernetes cluster 的前端接口,各种客户端 工具 以及 kubernetes 其他组件。可以通过它管理 cluster 的各种资源。
  • kube-scheduler
    • 负责决定将 pod 放在哪个 node 上运行,scheduler 在调度时会充分考虑 cluster 中各个节点的负载,以及应用对高可用、性能、数据亲和性的需求。
  • kube-controller-manager
    • 负责管理 cluster 各种资源,保证资源处理预期状态。controller-manager 由多种 controller 组成,包括 replication controller,endpoint controller,namespace controller,serviceaccount controller 等。
    • 不同的 controller 管理不同的资源,例如:replication controller 管理 deployment ,statefulset,damonset 的生命周期,namespace controller 资源管理 namespace 资源。
  • etcd(分布式 key-value 存储库)
    • 负责保存 cluster 的配置信息和各种资源的状态信息。当数据发生变化时,etcd 会快速地通知 kubernetes 相关组件。
  • pod 网络
    • pod 要能够通信,cluster 必须部署 pod 网络,flannel 是其中一个可选方案。

Node 节点 是 pod 运行的地方。node 节点上运行的 k8s 组件有 kubelet、kube-proxy 和 pod 网络。

  • kubelet
    • kubelet 是 node 节点的代理,当 master 节点中 kube-scheduler 确定在某个 node 节点上运行 pod 后,会将 pod 的具体配置信息发送给该节点的 kubelet,kubelet 根据这些信息创建和运行容器,并向 master 节点报告运行状态。
  • kube-proxy
    • 每个 node 节点都会运行 kube-proxy 服务,它负责将访问 service 的请求转发到后端的容器。如果有多个副本,kube-proxy 会实现负载均衡。
  • pod 网络
    • pod 要能够相互通信,k8s cluster 必须部署 pod 网络,flannel 是其中一个可选方案。

每一个 pod 包含一个或多个 container,pod 中的容器作为一个整体被 master 调度到 node 节点上运行。

  • 为什么 k8s 使用 pod 管理容器,而不是直接操作容器?

答:因为有些容器天生就是需要紧密的联系,放在一个 pod 中方便管理。同时 pod 中的所有容器使用同一个网络,即相同的 ip 地址和 port 空间,方便进行数据共享。

  • 什么时候需要在 pod 中定义多个容器?

答:这些容器联系非常紧密,而且需要直接共享资源,例如一个爬虫程序,和一个 web server 程序。web server 强烈依赖爬虫程序提供数据支持。

k8s 通常不会直接创建 pod,而是通过 controller 来管理 pod。controller 中定义了 pod 的部署特性,比如有几个副本,在什么样的 node 上运行等。为了满足不同的业务场景,k8s 提供了多种类型的 controller。

  • Deployment
    • 最常使用,可以管理 pod 多个副本,并确保 pod 按照期望的状态运行,底层调用 ReplicaSet。
  • ReplicaSet
    • 实现 pod 的多副本管理,通常使用 Deployment 就够了。
  • DaemonSet
    • 用于每个 node 最多只运行一个 pod 副本的场景。
    • 使用场景
      • 在集群的每个节点上运行存储 Daemon,比如 glusterd 或 ceph。
      • 在每个节点上运行日志搜集 Daemon,比如 flunentd 或 logstash。
      • 在每个节点上运行监控,比如 Prometheus Node Exporter 或 collected。
  • StatefuleSet
    • 能够保证 pod 的每个副本在整个生命周期中名称是不变的,而其他 controller 不提供这个功能。
  • Job
    • 用于运行结束就删除的应用,而其他 controller 中的 pod 通常是长期持续运行。

提示

使用 deployment controller 创建的用例,如果出现有 pod 挂掉的情况,会自动新建一个 pod,来满足内部定义的 replicas 字段要求。

容器按照持续运行时间可分为两类:服务类容器和工作类容器。

服务类容器通常持续提供服务,需要一直运行,比如 http server。工作类容器则是一次性任务,比如批处理程序,完成后容器就退出。

Controller 中 deployment、replicaSet 和 daemonSet 类型都用于管理服务类容器,对于工作类容器,我们使用 job。

Service 是可以访问一组 pod 的策略 —— 通常称为微服务。 具体访问哪一组 pod 通常是通过 label 进行选择的。service 为 pod 提供了负载均衡,原理是使用 iptables。

为什么要用 service ?

  • pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结束。而 pod 在一个 k8s 集群中可能经常性的创建,销毁,每一次重建都会产生一个新的 ip 地址。
  • service 从逻辑上代表了一组 pod,具体是哪些 pod 是由 label 来挑选的。service 有自己的 ip,而且这个 ip 是不变的,客户端只需要访问 service 的 ip,k8s 则负责建立和维护 service 与 pod 的映射关系,无论 pod 如何变化,对客户端不会有任何影响,因为 service 没有变。

外网如何访问 service?

nodeip:nodeport

如果有多个用户使用同一个 k8s cluster,如何将他们创建的 controller,pod 等资源分开呢?

答:使用 namespace。

如果将物理的 cluster 逻辑上划分成多个虚拟 cluster,每个 cluster 就是一个 namespace,不同 namespace 里的资源是完全隔离的。

k8s 默认创建了两个 namespace。

  • default 创建资源时如果不指定,将会放到这个 namespace 中。
  • kube-system 存放 k8s 自己创建的系统资源。
  • 健康检查
  • 数据管理
  • 密码管理
  • 集群监控

强大的自愈能力是 k8s 这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。除此之外,用户还可以利用 liveness 和 readiness 探测机制设置更精细的健康检查,进而实现如下需求:

  • 零停机部署
  • 避免部署无效的镜像
  • 更加安全的滚动升级

默认情况下,只有容器进程返回值非零,k8s 才会认为容器发生了故障,需要重启。如果我们想更加细粒度的控制容器重启,可以使用 liveness 和 readiness。

liveness 和 readiness 的原理是定期检查 /tmp/healthy 文件是否存在,如果存在即认为程序没有出故障,如果文件不存在,则会采取相应的措施来进行反馈。

liveness 采取的策略是重启容器,而 readiness 采取的策略是将容器设置为不可用。

案例

如果需要在特定情况下重启容器,可以使用 liveness。

如果需要保证容器一直可以对外提供服务,可以使用 readiness。

我们可以将 liveness 和 readiness 配合使用,使用 liveness 判断容器是否需要重启,用 readiness 判断容器是否已经准备好对外提供服务。

上文说道,pod 可能会被频繁地销毁和创建,当容器销毁时,保存在容器内部文件系统中的数据都会被清除。为了持久化保存容器的数据,可以使用 k8s volume。

Volume 的生命周期独立于容器,pod 中的容器可能被销毁和重建,但 volume 会被保留。实质上 vloume 是一个目录,当 volume 被 mount 到 pod,pod 中的所有容器都可以访问到这个 volume。

Volume 支持多种类型。

  • emptyDir
    • 数据存放在 pod 中,对 pod 中的容器来说,是持久的,只要 pod 还在数据就还在。
  • hostPath
    • 数据存在主机上,主机在数据就在。
  • AWS Elastic Block Store
    • 数据存在云服务器上。
  • Persistent Volume
    • 自定义一块外部存储空间 Persistent Volume,然后在创建 pod 时使用 PersistentVolumeClaim(PVC)去申请空间,并进行存储。

Volume 提供了对各种类型的存放方式,但容器在使用 volume 读写数据时,不需要关心数据到底是存放在本地节点的系统中还是云硬盘上。对容器来说,所有类型的 volume 都只是一个目录。

应用程序在启动过程中可能需要一些敏感信息,比如访问数据库的用户名和密码。将这些信息直接保存在容器镜像中显然不妥,k8s 提供的解决方案是 secret。

secret 会以密文的方式存储数据,避免直接在配置文件中保存敏感信息。secret 会以 volume 的形式被 mount 到 pod,容器可通过文件的方式使用 secret 中的敏感数据,此外容器也可以按环境变量的形式使用这些数据。

使用配置文件创建 mysecret.yaml:

apiVersion: v1
kind Secret
metadata:
  name:mysecret
data:
  username:admin
  password:123

1

2

3

4

5

6

7

保存配置文件后,然后执行 kubectl apply -f mysecret.yaml 进行创建。

在 pod 中使用创建好的 secret:

# mypod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mypod
      image: yhlben/notepad
  volumeMounts:
    - name: foo
      mountPath: 'etc/foo'
      readOnly: true
  volumes:
    - name: foo
      secret:
        secretName: mysecret

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

执行 kubectl apply -f mypod.yaml 创建 pod,并使用 secret。创建完成后,secret 保存在容器内 /etc/foo/username ,/etc/foo/password 目录下。

创建 k8s 集群并部署容器化应用只是第一步。一旦集群运行起来,我们需要确保集群一切都是正常的,这就需要对集群进行监控。

常用的可视化监控工具如下。

  • Weave Scope
  • Heapster
  • Prometheus Operator

具体的使用步骤就直接看文档了,这里不详细说明。

通过集群监控我们能够及时发现集群出现的问题,但为了方便进一步排查问题,我们还需要进行进行日志记录。

常用的日志管理工具如下。

  • Elasticsearch 负责存储日志并提供查询接口。
  • Fluentd 负责从 k8s 搜集日志并发送给 Elasticsearch。
  • Kibana 提供一个可视化页面,用户可以浏览和搜索日志。

我们来实战部署一个 k8s 记事本项目,项目使用 yhlben/notepad 镜像进行构建,该镜像在部署后会在 8083 端口上提供一个 web 服务,访问该服务,即可打开一个 记事本网站

为了避免安装 k8s 出现的各种坑,这里使用 Play with Kubernetes 进行演示。

首先在 Play with Kubernetes 上创建 2 台服务器,node1 作为 master 节点,node2 作为工作节点。接下来进行以下操作;

  • 创建一个集群 cluster
  • 加入 node 节点
  • 初始化 cluster 网络
  • 创建 controller
  • 创建 service
  • 执行部署

创建一个集群 cluster

使用 kubeadm init 即可创建一个集群。

kubeadm init --apiserver-advertise-address $(hostname -i)

1

执行完成后会生成 token,这样其他节点就可以凭借这个 token 加入该集群。

Kubernetes 入门总结

在 node2 机器上,执行以下命令。

kubeadm join 192.168.0.8:6443 --token nfs9d0.z7ibv3xokif1mnmv \
    --discovery-token-ca-cert-hash sha256:6587f474ae1543b38954b0e560832ff5b7c67f79e1d464e7f59e33b0fefd6548

1

2

命令执行完毕后,即可看到 node2 已经加入成功。

Kubernetes 入门总结

在 master 节点上,执行以下命令。

kubectl get node

1

Kubernetes 入门总结

可以看到,集群中存在两个节点,node1 和 node2,但这两个节点的都是 NotReady 状态,为什么?

答:因为没有创建集群网络。

执行以下代码创建集群网络。

kubectl apply -n kube-system -f \
    "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 |tr -d '\n')"

1

2

执行命令后,稍等一下,然后查看 node 状态,可以看到,集群中的两个节点都是 Ready 状态了。

Kubernetes 入门总结

我们通过配置文件来创建 deployment,新建 deployment.yaml 文件,内容如下:

# 配置文件格式的版本
apiVersion: apps/v1
# 创建的资源类型
kind: Deployment
# 资源的元数据
metadata:
  name: notepad
  # 创建 label 方便 service 匹配
  labels:
    app: mytest
# 规格说明
spec:
  # 定义 pod 数量
  replicas: 3
  # 通过 label 方便 deployment 找到对应的 pod
  selector:
    matchLabels:
      app: mytest
  # 定义 pod 的模板
  template:
    # pod 的元数据
    metadata:
      labels:
        app: mytest
    # 描述 pod 的规格
    spec:
      containers:
        - name: notepad
          image: yhlben/notepad
          ports:
            - containerPort: 8083

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

文件创建之后,执行命令:

kubectl apply -f ./deployment.yaml

1

创建 service 和 deployment 类似,新建 service.yaml 文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app: mytest
spec:
  # 在节点上暴露端口,访问服务,端口随机
  type: NodePort
  ports:
    - port: 8083
  # 匹配 pod
  selector:
    app: mytest

1

2

3

4

5

6

7

8

9

10

11

12

13

14

文件创建之后,执行命令:

kubectl apply -f ./service.yaml

1

使用 kubectl get deployment 和 kubectl get service 查看创建结果。

Kubernetes 入门总结

可以看到,deployment 和 service 均创建成功,并且已知 service 暴露的 ip 地址为:10.107.22.212,端口号为 8083。

我们没有指定 service 的 NodePort,系统就自动分配了一个 32494 端口。这样就能通过 master 节点的 ip:32494 来进行访问了。

在 node1 或者 node2 上,我们可以通过 service 暴露的 ip 来访问网站。

curl 10.107.22.212:8083

1

Kubernetes 入门总结

到这里,已经算部署成功了,大家肯定有疑问,部署一个如此简单的 web 应用就这么麻烦,到底 k8s 好在哪里?

项目已经部署,接下来我们来实战一个运维。

公司要做双 11 活动,需要至少 100 个容器才能满足用户要求,应该怎么做?

首先,应该尽可能利用当前拥有的服务器资源,创建更多的容器来参与负载均衡,通过 docker stats 可以查看容器占用的系统资源情况。如果充分利用后仍然不能满足需求,就根据剩余需要的容器,计算出需要购买多少机器,实现资源的合理利用。

  • 购买服务器,将服务器作为 node 节点,join 到集群中。
  • 执行扩容命令。

执行以下命令就能将容器扩展到 100 个。

kubectl scale deployments/notepad --replicas=100

1

也可以通过修改 deployment.yaml 中的 replicas 字段,执行 kubectl apply -f deployment.yaml 去执行扩展。如果活动结束了,只需要将多余的服务器删除,缩减容器数量即可还原到之前的效果。

双 11 活动很火爆,但出现了一个 bug,需要紧急修复,如果实现滚动更新?

滚动更新就是在不宕机的情况下,实现代码更新。执行以下命令,修改 image 即可。

kubectl set image deployments/notepad notepad=yhlben/notepad:v1

1

或者也可以通过修改 deployment.yaml 中的 image 字段,执行 kubectl apply -f deployment.yaml 去执行升级。

如果更新出了问题,k8s 内置了一键还原上个版本的命令:

kubectl rollout undo deployments/notepad

1

通过这两个案例,感觉到 k8s 非常适合管理项目的部署与运维,再也不用担心线上代码挂掉了。

本文的目的就是入门 k8s,通过一个简单的集群来实现这一点,但其中也踩了好多坑,具体如下:

  • 使用 minikube 搭建项目
    • 本想在本地使用 minikube 搭建一套 k8s 集群,没想到很多包装不上,全局代理也不行。
  • 使用 google clould 上的服务器
    • 由于是新服务器,需要各种安装环境,docker,kubeadm,kubectl 等,安装过程可能会遇到报错。
    • 不知道哪天手滑了一下,试用账号变成了付费账号,赠金 $300 就这样没了 :sob:。
    • 不过在 gogole clould 上,解决了网络问题,依赖包都能装上。
  • 使用 play with kubernetes
    • 上周使用 play with kubernetes 刚新建完一个实例,就被踢下线,简直恶心,不过最近可以正常使用。
    • 无法验证公网访问情况。

最后,推荐一下《每天 5 分钟玩转 Kubernetes》这本书,一本非常适合新手入门 k8s 的实战书。书中通过大量的简单实战,从易到难,让我真正理解了 k8s,本文中的大量理论知识也都来自这本书。


以上所述就是小编给大家介绍的《Kubernetes 入门总结》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

信息学奥林匹克教程·提高篇

信息学奥林匹克教程·提高篇

吴耀斌 / 湖南师范大学出版社 / 2003-1 / 24.00元

《信息学奥林匹克教程》(提高篇)既有各个算法设计基本思路的讲解及对求解问题的分析,注重了算法引导分析与不同算法的比较,又给出了具体的编程思路与参考程序,程序采用信息学竞赛流行的Turbo Pascal7.0语言编写,并注重结构化与可读性。一起来看看 《信息学奥林匹克教程·提高篇》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器