Kubernetes 201 学习笔记
Kubernetes 201 - Labels, Replication Controllers, Services and Health Checking
Kubernetes and Docker
Kubernetes 201 涵盖了 Kubernetes 101 未涉及的领域和更高级的话题,如应用生产化,部署和扩展。
大致的知识树如下:
- Kubernetes 201 - Labels, Replication Controllers, Services and Health Checking
- Labels
- Replication Controllers
- Replication Controller Management
- Services
- Service Management
- Health Checking
- Process Health Checking
- Application Health Checking
Labels
了解 Pods 概念并会创建后,你一定想创建原来越多的 pod。 加油干吧!
但是你逐渐会需要一个体系来组织这些 pod,做好分组。
Kubernetes 中实现这一目的的系统是 Labels。
Labels 是 key-value 对,附属于 Kubernetes 中每一个对象。
可以使用 RESTful 的 list
操作做 Label 选择,发送到 api 服务器,获取满足 label 选择条件的对象列表。
增加一个 label,只要在 pod 定义的元数据部分以下写 labels 即可:
labels:
app: nginx
以下是一个 nginx pod 定义示例,包含了 label:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
创建一个有 label 的 pod:
$ kubectl create -f docs/user-guide/walkthrough/pod-nginx-with-label.yaml
列出所有具有 label app=nginx
的 pod:
$ kubectl get pods -l app=nginx
Label 是 Kubernetes 构建链上两个部分(Replication Controllers 和 Services)的核心概念。
Replication Controllers
OK,你知道如何构建超棒的、多容器、有标签的 pod, 想用他们构建应用程序, 也许已经开始建立了一堆独立的 pod, 但如果你这么做了, 一系列操作问题会出现。
比如:如何向上或向下扩展 pod 的数量,如何保证所有 pod 同质同源?
Replication controller (副本控制器)回答了这一问题。 Replicatin controller 将 pod 创建的模版和所需副本数,结合到单一的 Kubernetes 对象里。 它还包含一个标签选择器,表示副本控制器管理的对象集合。
副本控制器持续测量对象集合大小与所需大小的差异,采取行动创建或删除 pod。
例如,一个副本控制器,初始化两个 nginx pod:
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-controller
spec:
replicas: 2
# selector identifies the set of Pods that this
# replication controller is responsible for managing
selector:
app: nginx
# podTemplate defines the 'cookie cutter' used for creating
# new pods when necessary
template:
metadata:
labels:
# Important: these labels need to match the selector above
# The api server enforces this constraint.
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Replication Controller Management
创建一个副本控制器:
$ kubectl create -f docs/user-guide/walkthrough/replication-controller.yaml
列出所有副本控制器:
$ kubectl get rc
通过名字删除副本控制器:
$ kubectl delete rc nginx-controller
Services
一旦有一套 pod 的副本,就需要一个抽象层,使应用的各层之间联系起来。 例如,如果有复制控制器管理后台任务,就不希望每次后端扩展后都需要重现配置前端程序。 同样,如果后台任务被计划调度到不同机器上,也不应该被要求重新配置前端程序。
在 Kubernetes 里,Service(服务)实现这些目标。
Service 提供了通过静态 ip 指向一组(用 label 选择出来的) pod 的方式。 如果提供商支持,也可以提供负载均衡。
例如,基于前文 nginx 副本控制器例子创建的 pod,这个 service 提供了负载均衡:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- port: 8000 # the port that this service should serve on
# the container on each pod to connect to, can be a name
# (e.g. 'www') or a number (e.g. 80)
targetPort: 80
protocol: TCP
# just like the selector in the replication controller,
# but this time it identifies the set of pods to load balance
# traffic to.
selector:
app: nginx
Service Management
创建一个 nginx 服务:
$ kubectl create -f docs/user-guide/walkthrough/service.yaml
列出所有服务:
$ kubectl get services
大多数提供商的服务 IP 无法从外部访问。 测试服务工作的最简单方式是创建一个 busybox pod,通过它执行命令。
服务 IP 可用时,能够用 curl 在 80 端口访问:
$ export SERVICE_IP=$(kubectl get service nginx-service -o=template -t={{.spec.clusterIP}})
$ export SERVICE_PORT=$(kubectl get service nginx-service -o=template '-t={{(index .spec.ports 0).port}}')
$ curl http://${SERVICE_IP}:${SERVICE_PORT}
通过名字删除服务:
$ kubectl delete service nginx-controller
每个服务创建时,都分配了唯一的 IP 地址。 这个地址绑定在 Service 的整个生命周期,并且不回改变。
Pod 可以配置与 Service 进行通讯,与 Service 的数据交换会自动负载均衡到 Service 选择条件所选择出来的一个成员 pod 上。
Health Checking
我写的代码永远不会崩溃,是吗? 可悲的是 Kubernetes 邮件列表里显示正好相反……
与其试图写出无 bug 的代码,不如使用一个管理工具来定期做健康检查并修复。 由一个应用外部的系统负责监视应用程序和采取修复措施。 在外部做检查很重要,因为如果健康检查是应用的一部分,应用程序失效时它也可能也失效,而你并不知晓。
在 Kubernetes 中,健康监控程序是 Kubelet 客服端。
Process Health Checking
监控检查最简单的形式是进程级别的监控检查。 Kubelet 持续向 Docker 服务询问容器进程是否在运行,如果失败,容器进程被重新启动。
目前我们所运行的 Kubernetes 例子中,健康检查都已经启用。 Kubernetes 中每一个容器,健康检查都是开启的状态。
Application Health Checking
然而,许多情况下,这种低级别的健康检查是不够的。
考虑下面的代码:
lockOne := sync.Mutex{}
lockTwo := sync.Mutex{}
go func() {
lockOne.Lock();
lockTwo.Lock();
...
}()
lockTwo.Lock();
lockOne.Lock();
这是计算机科学经典问题“死锁”的例子。 从 Docker 的角度来看进程仍然在运行,但是从应用程序的角度代码被死锁,永远不会再正确响应。
为解决这个问题,Kubernetes 支持应用层次的健康检查。 这些检查由 Kubelet 执行,确保应用程序运行的“正确性”。
目前有三种类型的应用健康检查可供选择:
- HTTP 健康检查 - Kubelet 调用 web hook。如果返回 200-399 之间的状态码,则认为成功。反之则失败。
- Container Exec - Kubelet 在容器内执行命令。如果退出状态码为 0 则认为成功。
- TCP Socket - Kubelet 尝试向容器建立一个 socket。如果能建立成功,则任务是健康的,否则认为失败。
任何情况,只要 Kubelet 发现容器故障,都会重启它。
容器健康检查在容器配置文件的 livenessProbe
部分配置。
还可以指定 initialDelaySeconds
,即服务启动最初的一个宽限期,使容器执行必要的初始化后才执行健康检查。
以下是包含 HTTP 健康检查的示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
# defines the health checking
livenessProbe:
# an http probe
httpGet:
path: /_status/healthz
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80