前言
通过linux基于cgroup,ns,及rootfs的学习,我们了解了基于容器技术原理。在大规模情况下,单单容器技术完全不够,k8s的出现就是解决
在大规模集群中存在各种各样的任务,任务之间又有着各样的关系。对于这些关系要如何处理优雅得体才是作业编排与系统管理的痛点所在
k8s架构
k8s架构由Master和Node两种节点组成,而这两种角色分别对应控制节点和计算节点。
Master结点
master节点,由3个紧密协作的独立组件组合而成
- kube-apiserver 负责API服务
- kube-shceduler 负责任务调度
- kube-controller-manager 负责容器编排
整个集群的持久化数据,则由kube-apiserver处理后保存在etcd中
Node结点
- 核心:kubelet,负责与容器运行时(Docker)交互。这种交互所依赖的是一个称作CRI(Container Runtime Interface),远程调用接口。其定义了容器运行时核心操作(比如:启动容器所需的参数)。
这里通过CRI层,来实现k8s与容器层的解耦,我并不关心你使用的是什么容器技术,只要能运行标准镜像,就可以接入到Kubernetes中。 - 除此之外,kubelet还通过gRPC与叫作Device Plugin插件交互。这个插件是用于管理GPU等宿主机的物理设备。是使用K8s进行机器学习,高性能作业,必须关注的插件。
kubelet 另一个重要功能 调用网络插件配置容器网络与存储插件提供容器的持久化存储。这两插件与kubelet 交互接口分别是 CNI(Container Networking)与CSI(Container Storage Interface)。
k8s的设计思想
声明式API是k8s最核心的设计理念。
- k8s定义了编排对象,比如Pod,Job, CronJob等。
- 又定义了运维能力对象,比如Service,Ingress, Horizontal Pod Autoscaler(自动水平扩展器)等。
开发者,可以根据自己应用的需求,选用不同的编排对象和服务对象。这种使用方式就是所谓的“声明式API”。
如上,我们从容器这个最基础的概念出发,首先遇到了容器间 “紧密协作” 关系的难题,于是就有了 Pod;有了 Pod 之后,我们希望能一次启动或收缩多个应用的实例,这样就需要 Deployment 这个 Pod 的多实例管理器;有一组相同的 Pod之后,我们又需要通过固定的IP地址和端口以负载均衡方式访问它,这个时候就有了 Service。
可是,如果现在两个不同pod之间不仅有访问关系,还要求在发起时加上授权信息。最典型的盒子就是Web 访问数据库时肯定时需要密码信息。
Kubernetes 提供了一个加 Secret 服务,它把键值对的数据保存在 Etcd 中,我们使用这个密码信息时,就要用到 Secret 里的数据以 Volume 的方式挂载到容器里。
除了应用与应用之间的关系,应用的运行的形态是影响“如何容器化这个应用”的第二个重要因素
为此,k8s定义了新的,基于Pod改进的对象。
- job,用来描述一次性运行的Pod(大数据任务)
- DaemonSet, 用来描述每个宿主机上必须且只能运行一个副本的守护进程服务
- CronJob, 用来描述定时任务
什么是Pod
上术介绍可以了解到 Pod在k8s 的地位是在最中心,所有的服务都是为 Pod 提供服务或者管理 Pod。 要理解Pod,则需要明白他和容器的关系
kubernetes 中最小的编排单位是Pod ,而非容器。将这个设计落实到API对象上,Container 就成了Pod属性里的一个普通字段。
要彻底理解Pod与容器的关系,就要牢记一个结论:Pod扮演的是传统部署环境中的“虚拟机”的角色,容器则是“虚拟机”中运行的“用户进程”。
即如果后期用户想配置“调度”,“网络”,“存储”,“安全”的相关属性,基本上在Pod上。
k8s的安装
2017年,在志愿者的推动下,一个独立的部署工具誔生,名叫kubeadm.
# 创建一个Master节点
$ kubeadm init
# 将一个Node 节点加入当前集群
$ kubeadm join <Master 节点的IP 和端口>
kubeadm的部署思路: 直接在宿主柚子上运行kubelet,然后使用容器部署其它的Kubernetes组件
为什么不是全部用容器技术布署?
kubelet是用来操作容器运行时的核心组件。除了跟容器运行时打交道,kubelet在配置容器网络,管理容器volume时,都需要直接操作宿主机。如果kubelet以容器运行,直接操作宿主机,就会变的很麻烦。
官网提供了几种安装方式《安装工具
》
初学者:还是直接使用docker desktop 提供的功能来部署《m1 mac安装docker、k8s(成功案例)》
第一个k8s程序
创建一个简单的nginx应用
apiVersion: v1
kind: Pod
metadata:
name: nginx
# 指定 label,便于检索
labels:
app: nginx
spec:
containers:
- name: nginx
# 指定镜像
image: nginx:alpine
# 指定暴露端口
ports:
- containerPort: 80
---
# 创建网络服务
apiVersion: v1
kind: Service
metadata:
name: kube-node-service
labels:
name: kube-node-service
spec:
type: NodePort #这里代表是NodePort类型的
ports:
- port: 80 #这里的端口和clusterIP(10.97.114.36)对应,即10.97.114.36:80,供内部访问。
targetPort: 80 #端口一定要和container暴露出来的端口对应,nodejs暴露出来的端口是8081,所以这里也应是8081
protocol: TCP
nodePort: 32143 # 所有的节点都会开放此端口,此端口供外部调用。
selector:
app: nginx #这里选择器一定要选择容器的标签,之前写name:kube-node是错的。
通过以下命令进行操作
## 通过配置文件创建服务
sudo kubectl create -f nginx.yaml
## 如果有修改可使用
sudo kubectl apply -f nginx.yaml
## 移除服务
sudo kubectl delete -f nginx.yaml
## 查看服务
sudo kubectl get service
## 查看
sudo kubectl get pod
## 通过浏览器访问了
http://<nodeIP> : 32143
主要参考
《深入剖析Kubernates》
《m1 mac安装docker、k8s(成功案例)》
《第一个 k8s应用》
《理解现代云原生时代的引擎》