一:Docker与k8s简介
在正式开始分享之前,给大家先分享一个相关的小故事:老王的叩问
老王是一家公司的工程师,精通各种技术栈,平常最重要的工作就是开发,上线和线上服务维护。
- 星期一,在一台服务器上部署一个nodejs应用,登录服务器后安装node,nginx,部署代码,安装依赖
- 星期二,部署nodejs应用的那台服务器因为某些原因挂掉了,待服务器重启后重启服务并检查是否正常
- 星期三,在某台服务器上部署一个web前端项目,登录服务器后部署代码,打包
- 星期四,node应用因访问量激增,在5台服务器上各自部署了1套,并用nginx实现了负载均衡
- 星期五,访问高峰过去了,停掉3套node服务,并对nginx做对应修改
每天的上线和维护消耗了老王大量的时间,夜深人静,老王不禁发出灵魂的叩问:啥时候是个头儿?
为了拯救老王,引入下面的词汇:容器,docker和kubernetes
1.1:容器
容器是一个标准化的软件单元,它将代码及其所有依赖关系打包,以便应用程序从一个计算环境可靠快速地运行到另一个计算环境。
1.2:docker
Docker 是一个开源的、轻量级的容器引擎,主要运行于 Linux 和 Windows,用于创建、管理和编排容器。
1.2.1 docker的口号
- build,ship and run,也就是搭建、发送和运行。
- build once, run anywher,搭建一次,到处能用
1.2.2 相关概念
- 镜像:一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器 (包含程序、库、资源、配置等)
- 容器:基于镜像创建的运行实例
- 仓库:保存各种镜像
一句话:
有了docker,老王同志的上线工作变得轻松,只要编写标准的Dockerfile就行。但服务规模扩大以后容器的部署,伸缩和管理依然很麻烦。
1.3:kubernetes
大服务集群上容器的部署,伸缩和管理的各种问题,衍生出来了容器编排引擎,比较著名的有 Mesos, DockerSwarm, Kubernetes。
Kubernetes名字太长了,叫起来有点麻烦,而Kubernetes首字母与结尾字母之间有8个字母,因此被称作K8S。
1.3.1:发展历史
- 2003-2004: Borg 是一个大规模的内部集群管理系统,它运行着来自数千个不同应用程序的数十万个作业,跨越许多集群,而每个集群拥有多达数万台计算机。
- 2013:从Borg到Omega。继 Borg 之后,Google 推出了 Omega 集群管理系统,这是一种适用于大型计算集群的灵活、可扩展的调度程序
- 2014:Google推出Borg的开源版本kubernetes。微软、RedHat、IBM、Docker 加入 Kubernetes 社区
- 2017年10月,Docker宣布将在新版本中加入对Kubernetes的原生支持。至此,容器编排引擎领域的三足鼎立时代结束,Kubernetes赢得全面胜利
有了kubernetes,老王同志的服务管理工作终于轻松了一些,对着终端敲敲命令就行。
二:一个demo
kubernetes官网提供了最小可用系统,kubernetes.io开发了一个交互式教程,通过Web浏览器就能使用预先部署好的一个Kubernetes集群,快速体验Kubernetes的功能和应用场景:
https://kubernetes.io/docs/tutorials/kubernetes-basics/
PS:这个交互式教程,应该是类似文档+终端+命令复制粘贴这样实现的
2.1:创建Kubernetes集群
相关命令:
- minikube start
- kubectl cluster-info
- kubectl get nodes
2.2:部署应用
[图片上传失败...(image-c1fb57-1625644415633)]
相关命令:
- kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
- kubectl get pods
2.3:访问应用
默认情况下,所有Pod只能在集群内部访问。对于上面这个例子,要访问应用只能直接访问容器的8080端口。为了能够从外部访问应用,我们需要将容器的8080端口映射到节点的端口
[图片上传失败...(image-c9eb10-1625644415633)]
相关命令:
- kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
2.4:扩缩应用(Scale)
默认情况下应用只会运行一个副本,可以通过命令增减副本
[图片上传失败...(image-3e707c-1625644415633)]
通过curl访问应用,可以看到每次请求有可能发送到不同的Pod
2.5:更新应用
相关命令:
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
三:k8s概念及架构
3.1:概念
3.1.1:Cluster
Cluster是计算、存储和网络资源的集合,Kubernetes利用这些资源运行各种基于容器的应用
3.1.2:master
Master是Cluster的大脑,它的主要职责是调度,即决定将应用放在哪里运行。Master运行Linux操作系统,可以是物理机或者虚拟机。为了实现高可用,可以运行多个Master
3.1.3:node
Node的职责是运行容器应用。Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期。Node运行在Linux操作系统上,可以是物理机或者是虚拟机。
在官网的交互式教程中,我们创建的Cluster只有一个主机,它既是Master也是Node。
3.1.4:pod
Pod是Kubernetes的最小工作单元。每个Pod包含一个或多个容器。Pod中的容器会作为一个整体被Master调度到一个Node上运行。同一个pod管理的多个容器之间可以通信和资源共享。
3.1.5:Controller
Kubernetes通常不会直接创建Pod,而是通过Controller来管理Pod的。Controller中定义了Pod的部署特性,比如有几个副本、在什么样的Node上运行等。为了满足不同的业务场景,Kubernetes提供了多种Controller,包括Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等
3.1.6:Service
Kubernetes Service定义了外界访问一组特定Pod的方式。Service有自己的IP和端口,Service为Pod提供了负载均衡。
Kubernetes运行容器(Pod)与访问容器(Pod)这两项任务分别由Controller和Service执行。
3.1.7:Namespace
Namespace可以将一个物理的Cluster逻辑上划分成多个虚拟Cluster,每个Cluster就是一个Namespace。不同Namespace里的资源是完全隔离的
3.2:架构
3.2.1: master节点
master是kubernetes cluster的大脑
- API Server:提供HTTP/HTTPS RESTful API,即Kubernetes API。API Server是Kubernetes Cluster的前端接口,各种客户端工具(CLI或UI)以及Kubernetes其他组件可以通过它管理Cluster的各种资源
- Scheduler:负责决定将Pod放在哪个Node上运行。Scheduler在调度时会充分考虑Cluster的拓扑结构,当前各个节点的负载,以及应用对高可用、性能、数据亲和性的需求。
- Controller Manager:负责管理Cluster各种资源,保证资源处于预期的状态。Controller Manager由多种controller组成,包括replicationcontroller、endpoints controller、namespace controller、serviceaccountscontroller等。不同的controller管理不同的资源。例如,replication controller管理Deployment、StatefulSet、DaemonSet的生命周期,namespacecontroller管理Namespace资源
- etcd:负责保存Kubernetes Cluster的配置信息和各种资源的状态信息。当数据发生变化时,etcd会快速地通知Kubernetes相关组件
- Pod网络:Pod要能够相互通信,Kubernetes Cluster必须部署Pod网络,flannel是其中一个可选方案
- kubelet和kube-proxy见node节点的结构(master同时也是一个node,可以运行应用)
3.2.2: node节点
node是pod运行的地方。
- kubelet:kubelet是Node的agent,当Scheduler确定在某个Node上运行Pod后,会将Pod的具体配置信息(image、volume等)发送给该节点的kubelet,kubelet根据这些信息创建和运行容器,并向Master报告运行状态。
- kube-proxy:kube-proxy负责将访问service的TCP/UPD数据流转发到后端的容器。如果有多个副本,kube-proxy会实现负载均衡
- pod网络:同上
3.2.3:单master架构
3.3:组件间的协作
kubectl run httpd-app --image=httpd --replicas=2 发生了什么?
- kubectl发送部署请求到API Server
- API Server通知Controller Manager创建一个deployment资源
- Scheduler执行调度任务,将两个副本Pod分发到k8s-node1和k8s-node2
- k8s-node1和k8s-node2上的kubectl在各自的节点上创建并运行Pod
四:kubectl命令
kubectl的语法:kubectl [command] [TYPE] [NAME] [flags]
- command:指定要对一个或多个资源执行的操作,例如 create、get、describe、delete
- type:指定资源类型。资源类型不区分大小写, 可以指定单数、复数或缩写形式
- name:指定资源的名称。名称区分大小写。 如果省略名称,则显示所有资源的详细信息,如 kubectl get pods
- flags:指定可选的参数。例如,可以使用 -s 或 -server 参数指定 Kubernetes API 服务器的地址和端口
常用命令示例:
- kubectl get pods
- kubectl get nodes
- kubectl create -f nginx-deployment.yaml
- kubectl delete po rc-nginx-btv4j
- kubectl scale rc rc-nginx-3 —replicas=4
- kubectl logs mysql-478535978-1dnm2
- kubectl expose rc nginx --port=80 --target-port=8000(为RC的nginx创建service,并通过Service的80端口转发至容器的8000端口上)
- kubecl run xxxxx 创建并运行一个或多个容器镜像
其他内容,如:数据管理,dashboard,包管理、集群监控、集群日志管理等,感兴趣的同学可以通过下方的参考或链接了解。
五:更加简便的方式
老王还是觉得麻烦,因为自己要敲命令,怎么办?腾讯云TKE,阿里云ACK等都在kubernetes的基础上做了再一次的开发,相当简便。老王连命令都不用敲了,登录控制台点按钮,配参数就行。
本文参考
- 《每天五分钟玩转Kubernetes》
- 《深入浅出Docker》
- kubernetes官方交互式教程:https://kubernetes.io/docs/tutorials/kubernetes-basics/
- kubectl命令文档:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create
- kubectl中文文档:http://docs.kubernetes.org.cn/475.html