kubernetes k8s一文入门

云原生的定义

云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API 。

这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。

云原生计算基金会( CNCF )致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。

云原生为用户指定了一条低心智负担的、敏捷的、能够以可扩展、可复制的方式最大化地利用云的能力、发挥云的价值的最佳路径.因此,云原生其实是一套指导进行软件架构设计的思想。按照这样的思想而设计出来的软件:首先,天然就 “ 生在云上,长在云上 ” ;其次,能够最大化地发挥云的能力,使得我们开发的软件和 “ 云 ” 能够天然地集成在一起,发挥出 “ 云 ” 的最大价值。

所以,云原生的最大价值和愿景,就是认为未来的软件,会从诞生起就生长在云上,并且遵循一种新的软件开发、发布和运维模式,从而使得软件能够最大化地发挥云的能力。说到了这里,大家可以思考一下为什么容器技术具有革命性?其实,容器技术和集装箱技术的革命性非常类似,即:容器技术使得应用具有了一种 “ 自包含 ”的定义方式。所以,这样的应用才能以敏捷的、以可扩展可复制的方式发布在云上,发挥出云的能力。这也就是容器技术对云发挥出的革命性影响所在,所以说,容器技术正是云原生技术的核心底盘.

官方给出的 Cloud Native 的 Trail Map ,主要涵盖了云原生技术在十个个领域的简介和典型项目举
例。
Containerization ,容器化,比如镜像的制作
CI/CD ,持续集成和部署
Orchestration & Application Definition ,应用的编排与管理
Observability & Analysis ,监控和可以观测行,比如如何进行监控、日志收集、 Tracing 等。
Service Proxy, Discovery & Mesh ,服务发现和服务网格
Networking & Plolicy ,网络
Distributed Database & Storage ,分布式数据存储
Streaming & Messaging ,消息系统
Container Registry & Runtime ,容器镜像仓库和容器运行时
Software Distribution ,软件发布

Kubernetes 是什么?

Kubernetes 一个开源的系统,用于容器化应用的自动化部署、扩缩容和管理。Kubernetes 将多个容器组成一个逻辑单元便于管理。 Kubernetes 是基于 Google 内部的 15 年调度经验设计出来的系统,参考了业界的智慧。

这里面提到的 Google 内部 15 年调度经验 就是业界有名的 Borg 系统,而 逻辑单元 实际上就是 Pod ,可以认为是 Kubernetes 的精髓设计了。

我们把 Kubernetes 的定义分解一下:
容器化应用: Kubernetes 管理的应用都是容器化的,可以是 Docker 容器,也可以是其他容器,比如 Kata 安全容器。容器的好处是应用之间资源隔离,便于管理。

自动化部署: Kubernetes 可以将容器组织成应用自动化部署到集群中。

扩缩容:扩缩容对应的是应用的副本数可以根据需要进行 scale-up 或者 scale-down 。

管理:对容器化应用的管理,比如说容器之间的依赖关系,编排关系等。

Kubernetes 的核心功能

服务发现和负载均衡:不需要修改应用程序去适配一些服务发现的机制。在 Kubernetes 里面可以给应用的每个 Pod 分配一个 IP 地址,然后这些 Pod 前面挂一个 DNS 就可以实现负载均衡了。最重要的是,这些在Kubernetes 里面实现起来非常的简单。

自动装箱( Automatic bin packing ):可以根据容器的描述定义(资源需求和限制,比如 CPU 、内存、存储等)将容器自动打包成一个调度单元,并通过特定的调度算法,将其调度到集群的某一台机器上运行。

自动修复( Self-healing ): Kubernetes 会帮助我们做一系列的 failover 的处理工作,以达到自动恢复的目的。比如当容器 fail 的时候进行重启, nodes (也就是主机节点)挂掉的时候将其上面的容器重新调度到其他 node上,当容器不影响预先定义的健康检测时重启容器。

存储编排( Storage orchestration ): Kubernetes 支持多种存储,比如本地存储、云产商( GCP 或者 AWS )提供的云存储或者远端存储( NFS , Ceph 等)。我们只需要在配置文件中指定存储类型, Kubernetes 就会自动帮助我们做存储的编排,并保证存储和应用的生命周期一致。

应用自动发布和回滚( Automated rollouts and rollbacks ): Kubernetes 提供了应用自动发布和回滚的机制。回滚的版本可以支持保存多个版本。

配置管理( Secret and configuration managerment ): secret 是 kubernetes 中提供的用于管理敏感信息的一种 API 对象,我们可以将容器的配置保存为这种配置对象,从而和镜像进行解耦。

批任务执行( Batch execution ): Kubernetes 诞生之初对于 Long-running 的服务支持良好,后来慢慢提供对批任务执行的支持,在 Kubernetes 中这种对象叫 Job 。

弹性伸缩( Horizontal Scaling ): Kubernetes 可以对应用进行弹性伸缩,包括手动和自动的方式

Kubernetes 的核心概念

Pod

Pod 是 Kubernetes 中的最小调度单元,一个 Pod 可以由多个容器组成,同一个 Pod 内的容器之间没有进行隔离。容器和 Pod 的关系可以类比进程和进程组的关系,这个也是 Kubernetes 借鉴于 Google 内部调度系统 Borg的设计

Pod 内的每个容器可以定义自己需要的资源大小,比如 CPU 、内存,同时 Pod 内可以包含一些其他的资源,比如说 Volume 数据卷等。

Pod 是 Kubernetes 的精髓所在,在没有 Pod 之前,如果我们要将两个有依赖关系的容器调度到同一个节点上需要调度器做很多复杂的工作。使用 Pod 之后,我们只需要将 Pod 作为一个单元进行调度就可以了。

Deployment

我们的应用会启动在一个 Pod 里面,有时候为了系统的高可用或者应对大流量的时候,需要启动多个应用实例,也就是启动多个相同的 Pod 。这个时候就需要 Deployment 了, Deployment 可以理解为一组 Pod 的管理器。可以通过 Deployment 定义 Pod 的一些元信息,比如资源使用限制等,还可以定义一组 Pod 的副本数量。

实际上我们真正的应用管理都是通过 Deployment 来做的,这样应用不管有几个副本我们都只需要管理一个
Deployment 对象即可。 Deployment 管理 Pod 在 Kubernetes 里面是通过控制器的方式管理的,控制器会不断的检测 Pod 的状态,比如 Pod 的健康检测是否正常,副本数是否正常,一旦出现异常情况, Deployment 就会通过控制器去做一些操作,比如重启 Pod ,以达到期望的状态。

通过 Deployment 我们还可以对应用做到滚动升级、版本回滚等发布运维相关的操作。

Service

我们前面说到 Kubernetes 的核心功能的时候提到服务发现和负载均衡就是通过 Service 来做的。举个例子,在Kubernetes 中,我们通过 Deployment 管理多个 Pod ,每个 Pod 对应一个应用实例,比如 Web 服务。每个 Pod都有一个 IP ,但是我们并不希望用户直接去访问 Pod 的 IP ,一是这样用户需要自己管理 Pod 的 IP 列表,并实现自己的负载均衡策略;二是 Pod 可能重启,重启之后 Pod 的 IP 会发生变化。对于这种情况就可以通过 Service 来处理。

在 Kubernetes 中 Service 也是一个对象, Service 后面可以关联一组 Pod 。 Service 对象创建成功之后会映射到一个域名和固定的 IP ,这样这个 IP 相当于一个 VIP ,用户只需要访问这个固定的 IP 就可以访问的后端的 Pod 中运行的应用了.

Kubernetes 中的 Service 有多种实现,比如 ClusterIP 、 NodePort 、 LoadBalancer 和 Ingress 等

Configmap

一个正规的开发流程中会包括多个环境,比如开发环境、预发环境和线上生产环境。这些不同环境中使用的代码还是同一套,区别在于配置不同。使用同一套代码保证了我们的 Pod 中使用的镜像是同一个,对于配置,在Kubernetes 中可以通过一个叫 Configmap 的对象来管理和创建。这样就将配置和应用进行了解耦

Namespace

Namespace 这个词在很多地方都有使用,比如编程语言中的命名空间。在 Kubernetes 中, Namespace 可以理解为一个资源的逻辑空间,包括鉴权( rbac )、资源管理等。 Kubernetes 中的每个资源,比如刚才 Pod 、Deployment 、 Service 等都有一个 Namespace 属主,不同 Namespace 的资源不能跨 Namespace 访问。另外一个Namespace 内的资源要求命名具有唯一性。

资源隔离: Namespace 剖析

Kubernetes 集群里面也有一个类似资源队列的角色,叫 namespace 。在生产实践中我们可以为不同的部门设置不同的 namespace ,另外 namespace 支持资源限制,我们可以按需为不同的部门设置不同的资源限制.

namespace 适用于跨团队、跨项目的多用户使用场景。如果 Kubernetes 集群的使用者很少,那么
不需要考虑 namespace

Namespace 为资源提供了一个界限,同一个 namespace 内的资源必须保证名字唯一,不同 namespace 内的资源可以名字相同。这里的资源包括 Pod , Deployment , Service 等。 namespace 不支持嵌套结构,即一个namespace 下包含子 namespace 。这里值得注意的是:命名空间资源本身不受限于一个 namespace 内,像一些底层资源,比如 nodes 和持久化卷也不属于任何 namespace .

Namespace 可以通过 resource quota 设置资源配额,这样我们就可以为不同用户群体划分资源了。

在 Kubernetes 的未来版本,同一个 namespace 下的对象都将使用相同的访问控制。

值得注意的是,不要滥用 namespace ,比如不要因为资源存在微小的差异(比如版本不同),就将这些资源划分的不同的 namespace 。对于这种情况,可以使用 label 去区分.

Namespace 使用

查看 namespace

和其他 kubernetes 的资源一样,我们可以通过命令 kubectl get namespace 或者 kubectl get ns 来获取集群中的namespace 情况,下面是我的 kubernetes 集群中的 namespace 情况。

? ~ kubectl get namespace
NAME STATUS AGE
default Active 148d
ieeemooc Active 57m
kube-node-lease Active 148d
kube-public Active 148d
kube-system Active 148d

这其中有三个资源是由 kubernetes 自动创建的:

default :创建对象时没有指定特定 namespace 的对象都会被置于 default namespace 下。
kube-system : Kubernetes 系统创建对象所使用的命名空间,比如 kube-proxy 、 kube-scheduler 等
kube-public :这个命名空间是自动创建的,所有用户(包括未经过身份验证的用户)都可以读取它。这个命名空间主要用于集群使用,以防某些资源在整个集群中应该是可见和可读的。这个命名空间的公共方面只是一种约定,而不是要求。

为请求设置 namespace
这里说的请求,包括创建、获取、删除特定的资源对象等,可以通过 --namespace= 或者 -n 来指定特定的 namespace 。

kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>

设置 namespace 首选项

如果觉得每个 kubectl 命令后面都添加 --namespace 参数过于繁琐,则可以通弄过 kubectl config 为当前 session设置 namespace 参数,则之后的 kubectl 命令都将使用这个特定的 namespace .

kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Validate it
kubectl config view | grep namespace:

Namespace 和 DNS

当我们创建一个 Service 对象时, Kubernetes 为了在集群内部可以访问到该 Service 对象的域名,会自动创建一个DNS 条目,形式为 ..svc.cluster.local ,也就是说如果容器只使用 ,它将被解析到本地命名空间的服务。这对于跨多个命名空间(如开发、分级和生产)使用相同的配置非常有用。如果您希望跨命名空间访问,则需要使用完全限定域名( FQDN )。

为 Namespace 设置资源配额

Namespace 机制的一个目标就是通过 namespace 将集群资源划分给不同的业务方使用,这一小节我们就来看一下如何限制一个 namespace 的资源配额。

在 Kubernetes 中,资源配额是通过一个叫 ResourceQuota 的对象来定义的。通过 ResourceQuota 我们可以限制namespace 中的对象数量,以及可以使用的计算资源总量。

Resource Quota 默认是支持的,如果发现你的 kubernetes 不支持的话,可以检查参数 --enable-admission-plugins= 的值里面有没有 ResourceQuota

ResourceQuota 提供的资源配额支持包括:

计算资源配置

Resource Description
limits.memory 所有非终结态的 Pod 的 memory limits 的和不能超过这个值
limits.cpu 所有非终结态的 Pod 的 cpu limits 的和不能超过这个值
requests.cpu 所有非终结态的 Pod 的 cpu requests 的和不能超过这个值
requests.memory 所有非终结态的 Pod 的 memory requests 的和不能超过这个值

存储资源配额

Resource Description
Requests.storage 所有 PVC 的存储请求总和不能超过这个值
persistentvolumeclaims namespace 中的 pvc 数量
.storageclass.storage.k8s.io/requests.storage 指定 storage-calss-name 的所有 pvc 的存储请求的上限值
.storageclass.storage.k8s.io/persistentvolumeclaims 指定 storage-calss-name 的 pvc 数量

对象数量配额

Name Description
congfigmaps namespace 中可以存在的配置映射的总数。
persistentvolumeclaims namespace 中可以存在的 PVC 总数。
podsnamespace 中可以存在的非终止态的 pod 总数。如果一个 pod 的 status.phase 是 Failed, Succeeded , 则该 pod 处于终止态。
replicationcontrollers namespace 中可以存在的 rc 总数。
resourcequotas namespace 中可以存在的资源配额( resource quotas )总数。
services namespace 中可以存在的服务总数量。
services.loadbalancers namespace 中可以存在的服务的负载均衡的总数量。
services.nodeports namespace 中可以存在的服务的主机接口的总数量。
secrets namespace 中可以存在的 secrets 的总数量。

我们下面来演示一下 Resource Quota 如何使用。首先定义个 resource quota 的资源文件,我们这里使用一个 List对象,下面可以连接多个 Resource Quota 对象。

apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: quota
spec:
hard:
configmaps: "20"
limits.cpu: "4"
limits.memory: 10Gi
persistentvolumeclaims: "10"
pods: "30"
requests.storage: 10Ti
secrets: "60"
services: "40"
services.loadbalancers: "50

后使用 kubectl apply 将这个 ResourceQuota 对象应用到指定的 namespace 中

kubectl apply -f resourcequota.yaml -n imooc

最后我们再通过 kubectl describe 看一下这个 namespace ,可以看到其中的 Resource Quotas 部分。

? k8s kubectl describe ns imooc
Name: imooc
Labels: <none>
Annotations: <none>
Status: Active
Resource Quotas
Name: quota
Resource Used Hard
-------- --- ---
configmaps 0 20
limits.cpu 700m 4
limits.memory 900Mi 10Gi
persistentvolumeclaims 0 10
pods 1 30
requests.storage 0 10Ti
secrets 1 60
services 0 40
services.loadbalancers 0 50
Resource Limits
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory 99Mi 1Gi 111Mi 900Mi -
Container cpu 100m 800m 110m 700m -

为 Namespace 设置资源限制

在 Kubernetes 集群中,容器可以使用的资源默认没有上限。为了避免单个容器或者 Pod 用光 node 上的所有可用资源, Kubernetes 提供了一种可以给 namespace 设置资源限制的方式,叫 LimitRange 。 LimitRange 提供的限制包括:

限制每个 Pod 或者容器可以使用的最少和最多计算资源
限制每个 PVC ( PersistentVolumeClaim )可以使用的最少和最多存储
限制资源的 request 和 limit 比例
设置容器默认的 request/limit 的资源大小

下面我们定一个一个 LimitRange 资源对象。

apiVersion: v1
kind: LimitRange
metadata:
name: limit-mem-cpu-per-container
spec:
limits:
- max:
cpu: "800m"
memory: "1Gi"
min:
cpu: "100m"
memory: "99Mi"
default:
cpu: "700m"
memory: "900Mi"
defaultRequest:
cpu: "110m"
memory: "111Mi"
type: Containe

然后我们将这个 LimitRange 对象应用到其中一个 namespace 中。

kubectl apply -f limitrange.yaml -n imoo

我们通过 kubectl describe 查看一下 imooc 这个 namespace 的一些描述信息。

k8s kubectl describe namespace imooc
Name: imooc
Labels: <none>
Annotations: <none>
Status: Active
No resource quota.
Resource Limits
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 100m 800m 110m 700m -
Container memory 99Mi 1Gi 111Mi 900Mi -

我们将 namespace 的描述信息和 LimitRange 资源对象联合起来一起看,可以得出一些结论:

spec.limits.type 表示限制资源的类型,可以是 Container 或者 Pod
spec.limits.max 表示计算资源限制的最大值,可以包含 cpu 或者 memory
spec.limits.min 表示计算资源限制的最小值,可以包含 cpu 或者 memory
spec.limit.defaultRequest 表示计算资源的默认 request 值,可以包含 cpu 或者 memomry
spec.limit.default 表示计算资源的默认 limit 值,可以包含 cpu 或者 memory

Kubernetes 核心概念解析: Pod (一)

那么我们首先来看看为什么要设计 Pod 这个概念呢?直接使用容器有什么问题

你可能感兴趣的:(Docker,入门,云原生,容器,docker,kubernetes)