Kubernetes基础

本文目录结构

虚拟机与容器的区别

虚拟机(Virtual Machine, VM)和容器(Container)是两种不同的虚拟化技术,它们在资源隔离、部署和扩展、操作系统支持等方面有着各自的特点和优劣。

  • 资源隔离: 虚拟机通过在物理硬件上创建完整的虚拟操作系统环境,使得每个虚拟机拥有独立的操作系统和应用程序,彼此之间资源隔离。而容器技术通过将应用程序及其运行环境打包成容器,容器之间共享同一个操作系统内核,使得容器之间资源相互隔离。
  • 部署和扩展: 虚拟机需要安装和配置相应的操作系统,部署和扩展相对繁琐。容器只需将应用程序及其运行环境打包成一个容器镜像,然后通过容器引擎在集群中部署和扩展。这使得容器在部署和扩展方面更加轻量级和灵活。
  • 操作系统支持: 虚拟机通过虚拟化技术提供完整的操作系统环境,可以运行任何支持的操作系统。容器技术通常支持一个或多个应用程序及其运行环境,只能运行在特定的操作系统上。
  • 资源占用: 虚拟机需要为每个虚拟机分配独立的操作系统资源,因此资源占用较高。容器共享同一个操作系统内核,资源占用相对较低。
  • 安全性: 虚拟机之间通过虚拟化层隔离,安全性较高;容器之间通过操作系统内核隔离,安全性相对较低。
  • 应用场景: 虚拟机适用于需要运行不同操作系统或对资源隔离要求较高的场景,如数据库、Web服务器等。容器适用于微服务架构下的应用程序开发、部署和扩展,以及轻量级、需要快速启动的场景,如Web应用程序、API服务等。

容器技术

容器技术是指将应用程序及其依赖项打包在一起,形成一个独立的单元,可以在任何支持容器运行时环境的操作系统上运行。容器技术的主要优点包括易于移植、可扩展、易于管理、易于组合和隔离。常见的容器技术包括Docker、rkt、containerd等。以Docker为例本质由命名空间cgroup镜像三块组成。

Kubernetes

什么是Kubernetes

Kubernetes,简称K8s,是用8代替名字中间的8个字符“ubernete”而成的缩写,它是一种容器集群管理技术,由Google开发并开源。k8s由Master和Node组成,工作流和各组件如下:

Master组件 Node组件
kube-apiserver
ETCD
kube-controller-manager
cloud-controller-manager
kube-scheduler
插件 addons
DNS
用户界面
容器资源监测
Cluster-level Logging
kubelet
kube-proxy
docker
RKT
supervisord
fluentd

Kubernetes 重要概念

pod

  • pod是k8s中的基本的部署单元,在worker nodes之间进行调度。
  • 可以把pod看作一个独立的机器,一个pod中可以运行一个或者多个容器,这些容器之间共享相同的ip和port空间。
  • 一个pod的所有容器都运行在同一个woker node中,一个pod不会跨越两个worker node。
  • 由于大多数容器的文件系统来自于容器镜像,所以每个容器的文件系统与其他容器是完全隔离的,但是可以试用Volume在容器间共享文件目录。
  • pod是短暂的, 他们随时的会启动或者关闭。也就是这如果某个pod被销毁之后,重新创建的pod的IP可能会变化。

如何创建一个pod。将以下保存到pod.yaml中然后执行kubectl apply -f pod.yaml。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}

配置文件相关解释:

  • apiVersion记录K8S的API Server版本,现在看到的都是v1,用户不用管。

  • kind记录该yaml的对象,比如这是一份Pod的yaml配置文件,那么值内容就是Pod。

  • metadata记录了Pod自身的元数据,比如这个Pod的名字、这个Pod属于哪个namespace(命名空间的概念,后文会详述,暂时理解为“同一个命名空间内的对象互相可见”)。

  • spec记录了Pod内部所有的资源的详细信息,看懂这个很重要:

    • containers记录了Pod内的容器信息,containers包括了:name容器名,image容器的镜像地址,resources容器需要的CPU、内存、GPU等资源,command容器的入口命令,args容器的入口参数,volumeMounts容器要挂载的Pod数据卷等。可以看到,上述这些信息都是启动容器的必要和必需的信息。
    • volumes记录了Pod内的数据卷信息,后文会详细介绍Pod的数据卷。

注:如果使用服务的vim编辑工具推荐以下vim配置,编辑vim ~.vimrc,并保存一下内容:

1
2
3
4
5
6
7
set paste
set encoding=utf8
set ts=4
set expandtab
set number
set showmode
set t_Co=256

执行 source ~.vimrc 实时生效文件的中的配置。

k8s控制器

在kubernetes中,有很多类型的pod控制器,每个都有自己的适合的场景,常见的有下面这些:

  • ReplicaSet:保证指定数量的pod运行,并支持pod数量变更,镜像版本变更
  • Deployment:通过空值ReplicaSet来空值pod,并支持滚动升级,版本回退。管控它们运行在用户期望的状态。
  • Horizontal Pod Autoscaler:可以根据集群负载自动调整pod的数量,实现消峰填谷
  • DaemonSet:在集群中的指定Node上都运行一个副本,一般用于守护进行类的任务
  • Job:它创建出来的pod只要完成任务就立即退出,用于执行一次性任务
  • Cronjob:它创建的pod会周期性的执行,用于执行周期性任务
  • StatefulSet:管理有状态应用,如数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1   #版本号
kind: ReplicaSet #类型
metadata: #元数据
name: pc-replicaset #rs名称
namespace: dev #所属命名空间
labels: #标签
controller: rs
spec: #详情
replicas: 3 #副本数量3
selector: #选择器,通过它指定该控制器管理哪些pod
matchLabels: #labels匹配规则,用于匹配template
app: nginx-pod
template: #模板,当副本数量不足时,会根据模板创建pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1

Service和Ingress

Service

在Kubernetes中,Pod是应用程序的载体,我们可以通过Pod的IP来访问应用程序,但是Pod的IP地址不是固定的,这也就意味着不方便直接采用Pod的IP对服务进行访问。
为了解决这个问题,Kubernetes提供了Service资源,Service会对提供同一个服务的多个Pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的Pod服务
Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的Service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。

services案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kind: Service # 资源类型
apiVersion: v1 # 资源版本
metadata: # 元数据
name: service # 资源名称
namespace: dev # 命名空间
spec: # 描述
selector: # 标签选择器,用于确定当前service代理哪些pod
app: nginx
type: # Service类型,指定service的访问方式
clusterIP: # 虚拟服务的ip地址
sessionAffinity: # session亲和性,支持ClientIP、None两个选项
ports: # 端口信息
- protocol: TCP
port: 3017 # service端口
targetPort: 5003 # pod端口
nodePort: 31122 # 主机端口
  • ClusterIP:默认值,它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问
  • NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务
  • LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持
  • ExternalName: 把集群外部的服务引入集群内部,直接使用

Ingress

Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点:

  • NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显
  • LB方式的缺点是每个service需要一个LB,并且需要Kubernetes之外设备的支持

本文参考
https://blog.csdn.net/qq_40378034/article/details/123297408