Kubernetes 学习笔记(一):基础概念

我的笔记,仅本人查阅使用。html

零、微服务

微服务架构专一于应用解耦合,经过将应用完全地组件化和服务化,每一个微服务只包含一个很是小的功能,好比权限管理、日志收集等等。由这一组微服务组合起来,提供一个应用的完整功能。前端

这样的好处是:node

  1. 开发更方便了。各微服务再也不须要关注其余服务内的细节,直接调用 API 就行。
  2. 方便持续集成。升级只须要从新部署更新了的微服务,不须要更新整个应用。
  3. 方便拓展。遇到性能瓶颈时,只须要拓展瓶颈所在的微服务,不须要拓展整个应用。

固然,这也带来了一些难点:nginx

  1. 业务型微服务,要尽可能无状态化。由于只有无状态微服务,才能够方便地作拓展,而不会致使状态不一致。
    • 注:而数据层服务,尽可能使用云平台提供的服务,而不是本身搭建。(这样数据层的负载均衡,数据一致性,就均可以甩锅了。)
  2. 成百上千个微服务,须要相互协做。这对运维提出了更高的要求。
  3. bug 追踪更难了,出现 bug 可能很难定位到缘由。

因而,kubernetes 应运而生。曾经还有个比 k8s 简单不少的 mesos 与它竞争,可是如今 k8s 已经一统天下了,mesos 将很快中止维护。。git

1、基础概念

1. kubernetes 中的对象与资源

Kubernetes 包含若干抽象用来表示系统状态,这些抽象被称做 kubernetes 对象。github

而对象(Objects)的实例(Instances),被称作资源(Resources)数据库

对象被用于表示已部署的容器化应用和负载、与它们相关的网络和磁盘资源以及有关集群正在运行的其余操做的信息。编程

基本的 kubernetes 对象包括:后端

1). Pod 容器组

Pod 是 k8s 管理的最小的可执行单元,它可包含多个容器,可是一般只有一个。api

Pod 封装了应用程序的容器(组)、存储资源、惟一的网络 IP,以及一些容器运行的参数。

同一个 Pod 中的容器,就好像是跑在同一个虚拟机上的应用同样,他们:

  1. 能够经过 localhost 发现对方(即共享网络)
  2. 也共享同一个 Service(也是共享网络)
  3. 也能够共享存储资源

所以,若是一个多容器的应用须要如上三个特性之一,那这个应用以多容器Pod的形式来部署。好比 nginx 静态文件服务器和 nginx_upload 文件上传服务两个容器,一个负责对外提供文件访问,一个服务将文件上传到 nginx 存储空间中。他们显然就须要共享同一个存储资源。

2). Service 服务:用于为 pod 提供稳定的网络 ip

Service 是一种抽象方式,它将在一组Pod上运行的应用程序公开为网络服务。
若是一个客户端须要使用一项特定的服务,它只须要使用该服务的名称就能找到对应的服务提供者(Pod)。
客户端不须要关心该服务后面的 Pod 有多少个,运行在哪些节点上,ip 是多少等等。

只要你在 kubernetes 为这一组 Pod 定义了一个【服务】,kubernetes 就保证客户端可以经过该服务找到对应的 Pod,不论这些 Pod 如今运行在哪些节点上。

从概念上说, Service 其实就是负载均衡,或者说反向代理。
传统的负载均衡方式,就是用一台 Nginx 服务器作反向代理。
可是这种方式下,虽而后端是负载均衡了,可是 Nginx 服务器却只有一台,它一出问题,系统就挂了。
kubernetes 的 Service 则不一样,它在每一个节点(Node)上都部署了一个 Proxy,全部对集群服务的访问,都会被节点上的这个 Proxy 转换成对服务(Service)后端容器组(Pod)的访问。

为了知足各种需求,kubernetes 提供了四种类型的 service:

  1. ClusterIP: (默认使用的类型)集群内部 ip,仅用于集群内部 Pods 的通讯。
  2. NodePort: 在每一个节点上暴露出一个静态 ip。这样能够经过<节点ip>:<port>来访问指定节点上的 Service
  3. LoadBalancer: 使用云提供商(因此本地集群用不了)的 Load Balancer 建立 Service,这会为服务提供一个静态的外网 ip。
  4. ExternalName: 将服务映射到一个域名上,如myapp.xxx.me(新出的功能)

要将一个 Pod 暴露出去,可使用 ClusterIP 以外的另外三种 Service Type。

此外,也可使用 Ingress,和 Service 不一样的是,Ingress 提供了一个集中式的集群网络入口。
客户从外网访问 Ingress Controller,而后 Ingress Controller 根据 Ingress 规则,将请求转发到对应的 Service 上。
集群对外只暴露 Ingress Controller(以 NodePort 或 LoadBalancer 的方式),外部请求经过 Ingress Controller 转发到内部对应的 Service 上。
这样集群就只有一个公网 IP,就是 Ingress Controller 的公网 IP,其余全部服务都只能通在内网访问。
Ingress 也能够添加 TLS/SSL 协议,做为一个 SSL/TLS Proxy.

3). Volume 数据卷:持久化数据,使数据与 Pod 分离

将动态数据映射到数据卷,这样数据就与 Pod 分离了,Pod 的 crash/recreate 就不会形成数据的丢失。

Docker 提供的 Volume 功能比较有限,Kubernetes 提供的数据卷功能更丰富,数据卷具备明确的生命周期:与使用它的 Pod 一致。
数据卷存在于 Pod 中的任何容器以外,只要 Pod 一直存在,那 Volume 就不会被清理。Pod 的重启也不会致使 Volume 中的数据丢失。

另外,kubernetes 有不少类型的数据卷,Pod 能够同时挂载多个数据卷使用。

可是要注意的是,Pod 删除后,大部分类型的 Volume 也会被清理掉。
所以 Volume 不是全部的类型的 Volume 都能用于持久化数据的!要建立一个有状态的应用,咱们须要使用持久化数据卷(Persistent Volume)来映射数据。

4). Namespace 名字空间

名字空间使咱们可以在一个物理集群上部署多个虚拟集群,这样的一个虚拟集群,就被称作一个名字空间。

另外,Kubernetes 包含大量的被称做控制器(controllers) 的高级抽象。控制器基于基本对象构建并提供额外的功能和方便使用的特性。具体包括:

1). ReplicaSet 副本集

副本集的目的是为了在任什么时候候,都能有一组稳定的副本 Pods 可以正常运行。这一般都是为了保证一组特定的 Pod 一直可用。

1). Deployment 部署控制器

Deployment 控制器为 Pod 和 ReplicaSets. 提供声明式的更新。
你为一个 Pod 声明一个你但愿达到的状态,而后 Deployment 控制器就会尽力使该 Pod 迁移到这个状态去。(好比说你但愿它正常运行)

3). StatefulSet 有状态副本集

这个应该是最难的概念之一,有状态副本集用于管理有状态应用。StatefulSet 必须有本身的存储标识,以保证数据能跨 Pod 地使用。

P.S. 据说 StatefulSet 用起来坑不少,因此存储仍是尽可能买云服务或者本身搭建存储集群吧。。

4). DaemonSet 守护进程集

守护进程集会保证每一个 Node 上有运行着属于该集合的 Pod 的一个副本,而且它会自动管理这些 Pod 的增删。当节点被添加或删除时,DaemonSet 会自动处理 Pod 的增删以确保每一个节点上都有该 Pod 的一个副本。

DaemonSet 常被用于运行每一个节点都须要的服务,如日志收集(Fluentd/logstash)、存储(ceph/glusterd)、节点监控(Promethus)等。

5). Job 任务

Job 就是一次性的任务,跑完就结束。Job 会确保这个任务正常地终止,不然 Job 会被从新启动。

此外还有 CronJob,定时执行的 Job

2. kubernetes 控制面

2.1. 节点

kubernetes 是一个“集群操做系统”,既然是集群,天然是会包含多种多样的节点。kubernetes 有两种节点:

  1. 主节点(master):主节点是集群的控制中心,它上面运行了以下几个组件:
    1. kube-apiserver:集群控制层的前端,咱们使用 kubectl 时就是一直在与它打交道。
    2. etcd:存放集群数据的键值数据库。(确保该数据有备份)
    3. kube-scheduler:调度器,负责把新建的 pod 选择找个坑(node)“埋”好,它会考虑到各类因素。
    4. kube-controller-manager:控制器都由它运行。
    5. cloud-controller-manager:负责管理与下层的云服务提供商交互的控制器。(实验特性)
  2. 工做节点(Node):提供 kubernetes 运行环境,全部的 pods 都运行在工做节点上。它包含以下几个组件:
    1. kubelet:在每一个节点上运行的代理,它确保容器在 pod 中运行。
    2. kube-proxy:它经过维护一组主机上的网络规则和链接转发,实现了 kubernetes 的网络抽象。
    3. 容器运行时:Docker

2.2. 附加组件(Addons)

附加组件使用 kubernetes 的资源来实现一些特性。

  1. CoreDNS
  2. Kubernetes Dashboard(Web UI)
  3. Ingress Controller: 提供网关同样的集群入口。

2、基本使用

0. 安装阿里版的 minikube: AliyunContainerService/minikube

学了些理论,到底仍是要实际使用过才能真正理解。这就须要一个可用的 kubernetes 集群。

安装一个 k8s 的入门学习环境,最好最简单的选择,官方的 minikube 是其中之一。

minikube 是一个官方推出的单节点 k8s 集群,适用于本地学习/开发。

可是因为某种你们都晓得的缘由,官方的 minikube 在国内是访问不到的,因此建议你们安装阿里版的 minikube: AliyunContainerService/minikube,阿里官方的教程就很详细。

1. 在 kubernetes 上运行一个 nginx 应用

minikube 是一个 k8s 集群,前面介绍过,k8s 集群是经过一个 apiserver 提供对集群的操控功能的。

要对一个 k8s 集群进行操做,就须要去访问这个 apiserver,官方提供了一个命令行工具:kubectl,这个工具将 restful api 包装成了方便易用的命令行工具。

下面就来学习一下 kubectl 的基本使用。

P.S. 既然是 restful api,固然就能够经过任何实现了 http 协议的工具访问。kubernetes 官方提供了各类语言的客户端包供使用:https://github.com/kubernetes-client

1.1 kubectl run

首先使用 kubectl run 在集群上运行指定的镜像。

kubectl run nginx --image=nginx:1.10.0

上面这条命令会从 nginx 镜像建立一个容器(单容器的 Pod),而后再建立一个 Deployment 来管理这个 Pod.

1.2 查看 Pods

接下来就能够经过 kubectl get pods 查看到 kubectl run 建立的 Pod 了。

kubectl get pods

1.3 从外部访问集群的 Pods

如今 nginx 已经跑起来了,可是咱们不知道它跑在集群的哪一个节点上,并且咱们也没为它指定任何端口映射,咱们没办法访问到它。

为了访问 nginx,咱们须要给它分配一个固定的地址,不论它跑在哪一个 k8s 节点上,咱们都应该能经过这个地址访问到它。k8s 经过 service 提供了这个功能。

能够经过 kubectl expose 命令,为刚刚建立好的 Pod/Depolyment 建立一个 Service,这样就能访问到它了。

kubectl expose deployments nginx --port=80 --type LoadBalancer

若是是在阿里云上跑这个命令,Service 会被分配到一个公网 ip。但 minikube 是本地单节点集群,它的 LoadBalancer 只能分配一个局域网 ip。
并且不能直接经过 kubectl get service 看到局域网的 ip 地址。须要经过 minikube service <schema>:<service-name>:<port> 访问该服务

参考

问题

相关文章
相关标签/搜索