🌑

Mocha's Blog

目录
  1. k8s 是什么
    1. k8s 的特点
    2. k8s 架构
  2. k8s 资源清单
    1. Pod
      1. 声明一个 Pod
      2. 相关命令
    2. 常用控制器 - Deployment
      1. 声明一个 Deployment
      2. 相关命令
    3. Service - SVC
      1. 声明一个 Service
      2. EndPoints
      3. 对外提供服务
    4. Ingress
      1. 声明一个 Ingress

前端工程师的k8s入门课

发布时间:2022年10月12日

k8s 是什么

Kubernetes 是一个开源容器编排平台(也可以叫做分布式资源管理框架),用于调度以及自动部署、管理和扩展容器化应用,消除了容器化应用程序在部署、伸缩时涉及到的许多手动操作。
一般简称为 k8s ,官方文档:Kubernetes 文档 | Kubernetes

k8s 的特点

  • 轻量级,底层采用 GO 语言开发
  • 开源,背靠 Google
  • 支持弹性伸缩、负载均衡

k8s 架构

image.png

架构中的一些概念

  • APISERVER:所有服务访问统一入口,包括对 Pod 的调度、服务的对外暴露等
  • ControllerManager:维持副本期望数目
  • Scheduler:负责进行任务的调度,选择合适的节点进行分配任务,通过轮询根据不同节点的处理器、内存情况实现负载均衡
  • ETCD:键值对数据库 ,持久化储存K8S集群所有重要信息,比如配置的 YAML 文件
  • Kubelet:直接跟容器引擎交互实现容器的生命周期管理
  • Kube-proxy:负责写入规则至 IPTABLES、IPVS 实现服务映射访问的
  • CoreDNS:可以为集群中的 SVC 创建一个域名 IP 的对应关系解析
  • DashBoard:给 K8S 集群提供一个 B/S 结构访问体系
  • Ingress Controller:官方只能实现四层代理,INGRESS 可以实现七层代理

k8s 资源清单

在 k8s 中,集群管理的一切内容均称之为资源,包括:集群节点、应用、存储卷等,我们一般通过创建对应 YAML 文件的方式声明式的创建我们想要的资源清单类型。
作为 k8s 集群的使用方,我们只需要关注在编排应用中可能用到的资源类型即可,从资源对应能力角度,我们可以将其分为以下几类:

  • 网关/请求分发:Ingress
  • 服务暴露:Service,简称 svc
  • 服务管控:Deployment / StatefulSet / DaemonSet / Job / CronJob
  • 服务提供:Pod
  • 存储卷挂载:PersitentVolumeClaim / PersistentVolume

以上几种资源组合起来就可以形成一个下图中的完整应用

image.png

下面我们就按照从内到外的顺序,介绍一下这些资源各自的能力

Pod

  • Pod是Kubernetes中能够创建和部署的最小单元,是Kubernetes集群中的一个应用实例,总是部署在某一个集群节点上。
  • Pod中包含了一个或多个容器,各个容器之间可以共享以下资源:
    • 存储:Pod挂载的资源,当前Pod 中的容器均可访问
    • 网络:同一个Pod 中的容器可以通过 localhost:Port 的方式相互访问
  • Pod支持多种容器环境,Docker则是最流行的容器环境。
  • Pod可以分为两种:自主式 Pod、控制器管理的 Pod

声明一个 Pod

apiVersion: v1
kind: Pod
metadata:
  name: show-default-pod
  namespace: mocha
spec:
  containers:
   - name: default-nginx
      image: docker.io/nginx:latest
      ports:
       - containerPort: 80
          name: "http-server"

然后执行 kubectl apply -f pod.yaml

相关命令

# 删除pod
kubectl dele pod ${pod-name}

# 修改 Pod 镜像版本
kubectl set image pod ${pod-name} ${container-name}=${image-name}

常用控制器 - Deployment

在 k8s 中,Deployment 是最常用的用来编排 Pod 的资源清单,通过使用 Deployment 来控制 Pod,我们可以轻松的实现如 滚动更新、应用回滚、自动负载均衡/扩缩容功能。

除 Deployment 外,StatefulSet、ReplicaSet、DaemonSet、Job、CronJob 都、也可以用来编排 Pod。

值得一提的是,Deployment 并不直接负责 Pod 的创建。当我们创建/更新一个 Deployment 时,其都会创建一个对应版本的 ReplicaSet,并由 RS 完成对应 Pod 的创建。
三者的关系可以从下图中看出

image.png

通过这个特性,我们可以实现滚动更新、应用回滚的功能。
当 Deployment 更新时,其会创建一个新版本的 RS,此时新的 RS 会创建对应版本的 Pod,在新的 Pod 尚未完全启动前,所有对该应用的访问都会调度到老版本的应用中。当 Deployment 配置了多个副本时,k8s 会遵循启动一个销毁一个的逻辑实现应用的更新。
有了上面的设计,实现应用的回滚也很简单,我们在回滚 Deployment 的更新时,Deploy 会将回滚目标版本对应的 RS 重新激活,然后就是与应用更新相同的过程,启动一个新 Pod 销毁一个当前 Pod,直至回滚完成。

声明一个 Deployment

声明一个最简单的 Deployment 所需要配置的 YAML 文件如下

apiVersion: apps/v1
kind: Deployment // 声明类型
metadata:
	name: nginx-deployment // deployment的名字
spec:
	selector: // 定义选择器,用于控制创建的pod
		matchLabels: // Deployment管理的 Pod Label
			app: nginx // 与要管理的 Pod 的 label 相同
	replicas: 2 // 创建几个副本
	revisionHistoryLimit: 3 // 保存的历史版本数
	template: // 创建的Pod的模板属性
		metadata:
			labels: // 创建的Pod的label属性,需要与 Selector 中一致,否则无法管理
				app: nginx // Pod的Label  key:value 允许任意定义
		spec: // 与pod定义中的spec相同
			containers:
			- name: anyname // 这个容器的名字无所谓随便取
			  image: docker.io/nginx:latest
			  ports:
			 - containerPort: 80

然后手动创建该 Deploy

kubectl apply -f deployment.yaml

创建结果如下图:

image.png

当所有 Pod 创建完成后可以通过 k get po -n namespace 命令查看 Pod

image.png

为了查看是否我们的前端应用是否启动完成,可以直接在对应 Pod 中执行 curl 127.0.0.1 命令来查看 nginx 服务是否返回了正常页面

相关命令

# 修改镜像
kubectl set image deploy ${deployment-name} ${container-name}=${image-name}

# 伸缩副本
kubectl scale deploy ${deployment-name} --replicas=${replicas-number}

# 回滚升级
kubectl rollout undo deploy ${deployment-name}

# 查看历史版本
kubectl rollout history deploy ${deployment-name}

# 回滚到指定版本
kubectl rollout undo deploy ${deploy-name} --to-revision=${visionId}

# 重启Deploy控制的所有Pod
kubectl rollout restart deploy ${deployment-name}

Service - SVC

在 k8s 集群中,Pod 是无法直接对外提供服务的,原因有两个:

  1. Pod 无法将其应用挂载到主机的指定端口中,外部无法直接访问
  2. Pod 可能会存在重启的情况,每次新建都会分配一个新的 IP,所以内部通过 IP + 端口 的方式互相访问也是不可靠的
    Service 便是用来解决这类问题的。
    Service 是 Kubernetes 里最核心的资源对象之一,Service 定义了一个服务的访问入口地址,通过访问 Service 的地址,可以实现访问其关联的一系列 Pod 的能力。
    与 Deployment - Pod 关联关系相同,Service与其后端Pod副本集群之间也是通过Label Selector来实现关联的。

声明一个 Service

apiVersion: v1
kind: Service
metadata:
  name: share-svc
  namespace: mocha
spec:
  selector:
    app: share-nginx-pod
  ports:
 - port: 80 # svc 监听的端口,互相之间可以重复,一般与TargetPort相同
    protocol: TCP # 协议
    targetPort: 80 # svc 关联 Pod 中服务的监听端口
  type: ClusterIP # 集群IP,不直接对外提供访问

EndPoints

与 Deployment - ReplicaSet - Pod 类似,Service - Pod 之间也存在一个中间角色:EndPoints,简写为 ep。
当我们声明一个 svc 后,集群会自动创建一个相对应的 ep,同时收集与 selector 相匹配的 Pod 的信息并记录在 ep 内,当 svc 收到网络请求时,会根据 ep 中记录的信息将请求转发给具体的 Pod。

image.png

对外提供服务

Service 根据类型可以分为:CluserIP、NodePort 两种模式:

  • ClusterIP:只分配内部 IP 和端口,无法直接对外提供访问,依赖于 Ingress 的流量分发或集群内部应用间的互相访问
  • NodePort:在 ClusterIP 类型基础上,会将 svc 挂载到所在节点(真实服务器)的随机端口上,外部可以通过 {cluster-master-node-ip}:{svc-port} 的方式访问其背后的应用

此外,针对每一个 svc,k8s 集群都为其创建了一个供集群内部访问的地址,组成方式为 {svc-name}.{namespace}.svc.cluster.local。
如果集群内部的 Pod 之间存在相互调用,可以通过内部地址来请求,k8s 会自动将其转换成对应 svc 的地址并分发到具体的应用中

原理:创建 svc 时,k8s 将 svc 信息写入自己的 dns 服务,并使用 etcd 持久化存储,当集群内通过 svc 地址请求时,利用 iptables 将其请求重定向

Ingress

通常情况下,service 和 pod 仅可在集群内部网络中通过 IP 地址访问。此时所有访问集群的流量都会被丢弃或转发到其他地方,也就是说 service 通常不直接对外提供服务,而 Ingress 便是流量与 service 的连接器。
具体来说,Ingress 是流量与服务对应关系的规则集合,是从 Kubernetes 集群外部访问集群内部服务的入口,我们可以在 Ingress 中配置 域名/Path 与 svc的关系、配置 SSL 连接、负载均衡等

声明一个 Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: default-ingress
  namespace: default
spec:
  rules:
 - host: mdks.top
    http:
      paths:
     - backend:
          service:
            name: mdks-svc
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
 - hosts:
   - mdks.top
    secretName: mdks-tls

Powered By Hexo.js Hexo and Minima. Support By Oracle & Docker-Compose.