Kubernetes 学习笔记(一):基础概念
个人笔记,仅本人查阅使用,不保证正确。
零、微服务
微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理、日志收集等等。由这一组微服务组合起来,提供一个应用的完整功能。
这样的好处是:
- 开发更方便了。各微服务不再需要关注其他服务内的细节,直接调用 API 就行。
- 方便持续集成。升级只需要重新部署更新了的微服务,不需要更新整个应用。
- 方便拓展。遇到性能瓶颈时,只需要拓展瓶颈所在的微服务,不需要拓展整个应用。
当然,这也带来了一些难点:
- 业务型微服务,要尽量无状态化。因为只有无状态微服务,才可以方便地做拓展,而不会导致状态不一致。
- 注:而数据层服务,尽量使用云平台提供的服务,而不是自己搭建。(这样数据层的负载均衡,数据一致性,就都可以甩锅了。)
- 成百上千个微服务,需要相互协作。这对运维提出了更高的要求。
- bug 追踪更难了,出现 bug 可能很难定位到原因。
于是,kubernetes 应运而生。曾经还有个比 k8s 简单很多的 mesos 与它竞争,但是现在 k8s 已经几乎一统天下了。。
一、基础概念
1. kubernetes 中的对象与资源
Kubernetes 包含若干抽象用来表示系统状态,这些抽象被称作 kubernetes 对象。
而对象(Objects)的实例(Instances),被称做资源(Resources)
对象被用于表示已部署的容器化应用和负载、与它们相关的网络和磁盘资源以及有关集群正在运行的其他操作的信息。
基本的 kubernetes 对象包括:
1). Pod 容器组
Pod 是 k8s 管理的最小的可执行单元,它可包含多个容器,但是通常只有一个。
Pod 封装了应用程序的容器(组)、存储资源、唯一的网络 IP,以及一些容器运行的参数。
同一个 Pod 中的容器,就好像是跑在同一个虚拟机上的应用一样,他们:
- 可以通过 localhost 发现对方(即共享网络)
- 也共享同一个 Service(也是共享网络)
- 也可以共享存储资源
因此,如果一个多容器的应用需要如上三个特性之一,那这个应用以多容器Pod的形式来部署。比如 nginx 静态文件服务器和 nginx_upload 文件上传服务两个容器,一个负责对外提供文件访问,一个服务将文件上传到 nginx 存储空间中。他们显然就需要共享同一个存储资源。
P.S. 生产环境尽量不要直接创建 Pod,应该通过 Deployment 来管理 Pod.
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:
- ClusterIP: (默认使用的类型)集群内部 ip,仅用于集群内部 Pods 的通信。
- NodePort: 在每个节点上暴露出一个静态 ip。这样可以通过
<节点ip>:<port>
来访问指定节点上的 Service - LoadBalancer: 使用云提供商(所以本地集群用不了)的 Load Balancer 创建 Service,这会为服务提供一个静态的外网 ip。
- ExternalName: 将服务 xxx 映射到一个外部域名上,如
myapp.xxx.me
。这样在集群内部访问xxx.<namespace>.svc.cluster.local
,实际上就是访问了外部的myapp.xxx.me
- 这种方式隐藏了外部服务的具体服务名称和 pod 的位置。你甚至可以随时将它迁移到别的集群中,或者再将它重新变回 ClusterIP
要将一个 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 之间共享数据/持久化数据
4). Namespace 名字空间
名字空间使我们能够在一个物理集群上部署多个虚拟集群,这样的一个虚拟集群,就被称做一个名字空间。
5). Ingress 集群入口网关
Ingress 是一种将进入集群的流量集中管理的资源,目前只支持 http/websocket 这两种协议(不同的 Ingress-controller 实现,对协议的支持也会有差别)。
Ingress 本身只相当于一份配置,它依赖下层的 Ingress-Controller 提供实际的功能。
比如说你本地运行了一个 Ingress Controller,它使用 NodePort 的方式监听所有节点的 80 和 443 端口。
- 你修改本地的
/etc/hosts
或C:\Windows\System32\drivers\etc\hosts
文件,将nginx.mykubernetes.io
解析到127.0.0.1
(解析到你的节点 ip) - 然后你通过浏览器访问
http://nginx.mykubernetes.io
- 这时 ingress-controller 就会受理你的 http 请求,它会将你的请求域名
nginx.mykubernetes.io
已经 http/ws 路径/
和所有的 Ingress 规则进行匹配,匹配成功,就将请求转发到规则中所定义的 Service.
所以说 Ingress 就是一个基于域名和路径进行请求转发的代理(第七层应用层转发)。相比 Service 的好处是:
- 所有流量都集中从这一个入口进入了,不再需要每个对外服务都暴露一个 NodePort。
- 通过域名和路径来匹配对应的服务,很直观。
- 因为流量集中了,就可以对流量做更多的管控。比如灰度发布。
P.S. 既然有入口网关,自然就有出口网关。出口网关可对集群的对外请求进行限制,比如域名白名单。
K8s 本身没有实现出口网关的功能,但是 Istio 提供了这项功能。
控制器
另外,Kubernetes 包含大量的被称作控制器(controllers) 的高级抽象。控制器基于基本对象构建并提供额外的功能和方便使用的特性。具体包括:
1). ReplicaSet 副本集
副本集的目的是为了在任何时候,都能有一组稳定的副本 Pods 能够正常运行。这通常都是为了保证一组特定的 Pod 一直可用。
- 如果一个 Pod 状态为 failed(通常是由于磁盘压力等导致 pod 启动失败),replicaset 会重新创建一个新 pod。(failed 的 pod 不会被自动删除)
- 如果一个 Pod 没通过 readiness/liveness 探针,它会被不断重启。
我们通常也不会直接创建 ReplicaSet,而是通过 Deployment 来管理 ReplicaSet 和 Pod
1). Deployment 部署控制器
最常用的资源之一!
Deployment 控制器为 Pod 和 ReplicaSets. 提供声明式的更新。
你为一个 Pod 声明一个你希望达到的状态,然后 Deployment 控制器就会尽力使该 Pod 迁移到这个状态去。
比如说你希望它始终有三个副本正常运行。正常情况下,如果你修改了 Deployment 的 ReplicaSet 模板,Deployment 会立即新建一个 ReplicaSet,然后将流量慢慢切到新的 ReplicaSet 上,慢慢缩容老的 ReplicaSet,最终完全删除掉老的 ReplicaSet。实现平滑更新。
而如果更新后发现问题,也可以随时回退到以前的版本。
3). StatefulSet 有状态副本集
Pod 有两种:
- 一种是无状态的,可以通过 Deployment/ReplicaSet 管理,因为它们可以随时被替换,不同的副本之间没有任何区别,请求可以被由任一副本处理。
- 而另一种,是有状态 Pod,这类 Pod 需要挂载数据卷,并且保证 Pod 的重启、更新、移动,不会导致数据(状态)的丢失。
但是 Pod 不会自愈,我们需要类似 Deployment 这样的控制器来声明式地管理有状态的 Pod。
那么有状态的 Pod,能不能用 ReplicaSet 管理呢?可当然是可以,但是这只适合单节点的有状态应用。对于数据库集群等分布式应用,它就无能为力了。
为此 k8s 提供了 StatefulSet,它解决的问题有:
- 为每个 Pod 提供固定的、唯一的 dns 解析(其实就是通过使用递增整数替代 hash 做 pod 后缀实现的),固定的集群 ip 地址。(注意是每个 Pod,不是通过 Service)
- 顺序性 - StatefulSet 中 pod 的启动、更新、销毁默认都是按顺序进行的。而且一次只变更一个 Pod,不会并发!
- 唯一的、稳定的持久化存储 - 不同的 Pod 可以使用不同的存储卷,而且当 pod 被重新调度后,仍然能挂载原有的 PersistentVolume,保证了数据的完整性和一致性。
但是 StatefulSet 真用起来还是很复杂,需要考虑很多东西。所以 CoreOS 又出了个 kubernetes operator 来部署这类复杂应用,后续可以了解下。
另外不缺钱的话,存储还是尽量买云服务吧。。
4). DaemonSet 守护进程集
守护进程集会保证每个 Node 上有运行着属于该集合的 Pod 的一个副本,并且它会自动管理这些 Pod 的增删。当节点被添加或删除时,DaemonSet 会自动处理 Pod 的增删以确保每个节点上都有该 Pod 的一个副本。
DaemonSet 常被用于运行每个节点都需要的服务,如日志收集(Fluentd/logstash)、存储(ceph/glusterd)、节点监控(Promethus)等,并且经常会通过 hostPath 类型的数据卷读写节点上的数据。
5). Job 任务
Job 就是一次性的任务,跑完就结束。Job 会确保这个任务正常地终止,否则 Job 会被重新启动。任务成功结束后,会留下一条记录在 kubernetes 中,记录的存留时间是可设定的。
此外还有 CronJob,顾名思义,就是定时自动执行的周期性 Job。
2. kubernetes 控制面
2.1. 节点
kubernetes 是一个“集群操作系统”,既然是集群,自然是会包含多种多样的节点。kubernetes 有两种节点:
- 主节点(master):主节点是集群的控制中心,它上面运行了如下几个组件:
- kube-apiserver:集群控制层的前端,我们使用
kubectl
时就是一直在与它打交道。 - etcd:存放集群数据的键值数据库。(确保该数据有备份)
- kube-scheduler:调度器,负责把新建的 pod 选择找个坑(node)“埋”好,它会考虑到各种因素。
- kube-controller-manager:控制器都由它运行。
- cloud-controller-manager:负责管理与下层的云服务提供商交互的控制器。(实验特性)
- kube-apiserver:集群控制层的前端,我们使用
- 工作节点(Node):提供 kubernetes 运行环境,所有的 pods 都运行在工作节点上。它包含如下几个组件:
- kubelet:在每个节点上运行的代理,它确保容器在 pod 中运行。
- kube-proxy:它通过维护一组主机上的网络规则和连接转发,实现了 kubernetes 的网络抽象。
- 容器运行时:Docker
2.2. 附加组件(Addons)
附加组件使用 kubernetes 的资源来实现一些特性。
- CoreDNS:通过 DNS 解析使服务之间能方便地互相发现。
- Kubernetes Dashboard:kubernetes 的 Web UI,方便直观地了解集群的状态,并进行一些简单的操作。
- Ingress Controller: 集群的流量入口,是 Ingress 的底层支持组件。比较流行的有官方的 Nignx-Controller、Kong 还有 Trafik。
二、基本使用
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>
访问该服务
参考
- Kubernetes 基础概念
- 面向 Kubernetes 编程:Kubernetes 是下一代操作系统
- K8S从懵圈到熟练 – 集群服务的三个要点和一种实现
- 你闺女也能看懂的插画版Kubernetes指南
问题
Kubernetes 学习笔记(一):基础概念的更多相关文章
- Docker:学习笔记(1)——基础概念
Docker:学习笔记(1)——基础概念 Docker是什么 软件开发后,我们需要在测试电脑.客户电脑.服务器安装运行,用户计算机的环境各不相同,所以需要进行各自的环境配置,耗时耗力.为了解决这个问题 ...
- OpenFlow Switch学习笔记(一)——基础概念
OpenFlow Switch v1.4.0规范是在2013年10月14号发布,规范涵盖了OpenFlow Switch各个组件的功能定义.Controller与Switch之间的通信协议Open F ...
- Elasticserach学习笔记-01基础概念
本文系本人根据官方文档的翻译,能力有限.水平一般,如果对想学习Elasticsearch的朋友有帮助,将是本人的莫大荣幸. 原文出处:https://www.elastic.co/guide/en/e ...
- 【miscellaneous】 GStreamer应用开发手册学习笔记之基础概念介绍
第3章. 基础概念介绍 本章将介绍GStreamer的基本概念. 理解这些概念对于你后续的学习非常重要,因为后续深入的讲解我们都假定你已经完全理解了这些概念. 3.1. 元件(Elements) 元件 ...
- Kubernetes 学习2 k8s基础概念
一.架构描述 1.基本架构 2.pod ,有两类 a.自主式pod 自我管理的,创建之后,任然是需要提交给API Server,API Server接受之后然后由调度器调度到指定的 node节点,由n ...
- Centos7安装gitlab11 学习笔记之基础概念、部署安装、权限管理、issue管理
一.基础介绍 1.简介 一个基于GIT的源码托管解决方案 基于rubyonrails开发 集成了nginx postgreSQL redis sidekiq等组件 2.安装要求 2g内存以上,有点占内 ...
- JAVA学习笔记之基础概念(一)
一.Java 简介: Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称. 由 James Gosling和同 ...
- C#学习笔记(基础知识回顾)之值类型和引用类型
一:C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存 ...
- Quartz学习笔记:基础知识
Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...
随机推荐
- 随机森林算法OOB_SCORE最佳特征选择
RandomForest算法(有监督学习),可以根据输入数据,选择最佳特征组合,减少特征冗余:原理:由于随机决策树生成过程采用的Boostrap,所以在一棵树的生成过程并不会使用所有的样本,未使用的样 ...
- * resolve_conffiles: Existing conffile /etc/config/dhcp is different from the conffile in the new package. The new conffile will be placed at /etc/config/dhcp-opkg.
* resolve_conffiles: Existing conffile /etc/config/dhcp is different from the conffile in the new pa ...
- Confluence 实现公司wiki【转】
Confluence是一个企业级的Wiki软件,可用于在企业.部门.团队内部进行信息共享和协同编辑一.安装过程1 安装并配置mysql [root@vm1 ~]# /etc/my.cnf charac ...
- mycat启动报Unable to start JVM: No such file or directory (2)【转】
mycat启动失败,查看日志 /mycat/logs/wrapper.log发现如下信息 1 STATUS | wrapper | 2017/11/22 16:15:17 | --> Wra ...
- JS构造函数中有return
function foo(name) { this.name = name; return name } console.log(new foo('光何')) function bar(name) { ...
- Spring Boot TImer Schedule Quartz
Spring Boot 2.X(十二):定时任务-云栖社区-阿里云https://yq.aliyun.com/articles/723876?spm=a2c4e.11155472.0.0.2f8b3a ...
- ISO/IEC 9899:2011 条款6.8.3——表达式与空语句
6.8.3 表达式与空语句 语法 1.expression-statement: expressionopt ; 语义 2.在一条表达式语句中的表达式被计算为一个void表达式作为其副作用.[注 ...
- Oracle 自动生成的视图VM_NSO_1
作者:Jerry 有时候优化sql的时候,在执行计划中看到有VM_NSO_X的视图,在Oracle定义中,可以吧NSO理解为nested subquery optimizing,功能就是把in转换为j ...
- Spring Cloud API网关服务 5.2
为什么需要API网关 通过前面内容的学习,我们已经可以构建一个简单的微服务架构系统.这个系统可以使用Spring Boot实现微服务的开发,使用Spring Cloud Eureka实现注册中心以及服 ...
- LeetCode_303. Range Sum Query - Immutable
303. Range Sum Query - Immutable Easy Given an integer array nums, find the sum of the elements betw ...