目录

一、Kubernetes基本知识要点

1.Kubernetes简介

 2.Kubernetes特性

3.集群架构与组件

4.创建pod流程

二、Kubernetes Pod

1.pod基本概念

 2.命名空间

三、yaml文件编写

1.YAML文件 语法特点(语法结构)

 2.yaml编写自主式pod资源

 3.yaml文件使用

 4.pod资源编写格式说明


一、Kubernetes基本知识要点

1.Kubernetes简介

• Kubernetes 是一个全新的基于容器技术的分布式架构解决方案,是 Google 开源的一个容器集群管理系统,Kubernetes 简称 K8S。

• Kubernetes 是一个一站式的完备的分布式系统开发和支撑平台,更是一个开放平台,对现有的编程语言、编程框架、中间件没有任何侵入性。

• Kubernetes 提供了完善的管理工具,这些工具涵盖了开发、部署测试、运维监控在内的各个环节。

• Kubernetes 具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制、多粒度的资源配额管理能力。

• Kubernetes 官方文档:Kubernetes

 2.Kubernetes特性

 

① 自我修复

在节点故障时,重新启动失败的容器,替换和重新部署,保证预期的副本数量;杀死健康检查失败的容器,并且在未准备好之前不会处理用户的请求,确保线上服务不中断。

② 弹性伸缩

使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例,保证应用业务高峰并发时的高可用性;业务低峰时回收资源,以最小成本运行服务。

③ 自动部署和回滚

K8S采用滚动更新策略更新应用,一次更新一个Pod,而不是同时删除所有Pod,如果更新过程中出现问题,将回滚更改,确保升级不影响业务。

④ 服务发现和负载均衡

K8S为多个容器提供一个统一访问入口(内部IP地址和一个DNS名称),并且负载均衡关联的所有容器,使得用户无需考虑容器IP问题。

⑤ 机密和配置管理

管理机密数据和应用程序配置,而不需要把敏感数据暴露在镜像里,提高敏感数据安全性。并可以将一些常用的配置存储在K8S中,方便应用程序使用。

⑥ 存储编排

挂载外部存储系统,无论是来自本地存储,公有云,还是网络存储,都作为集群资源的一部分使用,极大提高存储使用灵活性。

⑦ 批处理

提供一次性任务,定时任务;满足批量数据处理和分析的场景。

3.集群架构与组件

3.1 Master

Master 是 K8S 的集群控制节点,每个 K8S 集群里需要有一个 Master 节点来负责整个集群的管理和控制,基本上 K8S 所有的控制命令都是发给它,它来负责具体的执行过程。Master 节点通常会占据一个独立的服务器,因为它太重要了,如果它不可用,那么所有的控制命令都将失效。

Master 节点上运行着以下关键组件:

① kube-API server

集群的统一入口,各组件协调者,以 HTTP Rest 提供接口服务,所有对象资源的增、删、改、查和监听操作都交给 API server 处理后再提交给 Etcd 存储。

② kube-controller-manager

K8S 里所有资源对象的自动化控制中心,处理集群中常规后台任务,一个资源对应一个控制器,而 controller-manager 就是负责管理这些控制器的。

③ kube-scheduler

根据调度算法为新创建的 Pod 选择一个 Node 节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。

④ etcd

是一个分布式的数据库,一致的 key-value 存储(非关系型),主要用途是共享配置和服务发现,保存集群状态数据,比如 Pod、Service 等对象信息。

3.2 Node

除了 Master,K8S 集群中的其它机器被称为 Node 节点,Node 节点是 K8S 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载,当某个 Node 宕机时,其上的工作负载会被 Master 自动转移到其它节点上去。

每个 Node 节点上都运行着以下关键组件:

① kubelet

kubelet 是 Master 在 Node 节点上的 Agent(代理),与 Master 密切协作,管理本机运行容器的生命周期,负责 Pod 对应的容器的创建、启停等任务,实现集群管理的基本功能。

② kube-proxy

在 Node 节点上实现 Pod 网络代理,实现 Kubernetes Service 的通信,维护网络规则和四层负载均衡工作。

③ docker engine

Docker 引擎,负责本机的容器创建和管理工作。

Node 节点可以在运行期间动态增加到 K8S 集群中,前提是这个节点上已经正确安装、配置和启动了上述关键组件。在默认情况下 kubelet 会向 Master 注册自己,一旦 Node 被纳入集群管理范围,kubelet 就会定时向 Master 节点汇报自身的情况,例如操作系统、Docker 版本、机器的 CPU 和内存情况,以及之前有哪些 Pod 在运行等,这样 Master 可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略。而某个 Node 超过指定时间不上报信息时,会被 Master 判定为“失联”,Node 的状态被标记为不可用(Not Ready),随后 Master 会触发“工作负载大转移”的自动流程。

4.创建pod流程

master节点:kubectl -> kube-api -> kubelet -> CRI容器环境初始化

• 第一步:

客户端提交创建Pod的请求,可以通过调用API Server的Rest API接口,也可以通过kubectl命令行工具。如kubectl apply -f filename.yaml(资源清单文件)

• 第二步:

◇ apiserver接收到pod创建请求后,会将yaml中的属性信息(metadata)写入etcd。

• 第三步:

apiserver触发watch机制(类似监听)准备创建pod,信息转发给调度器scheduler,调度器使用调度算法选择node,调度器将node信息给apiserver,apiserver将绑定的node信息写入etcd

◇ 调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。

• 第四步:

apiserver又通过watch机制,调用kubelet,指定pod信息,调用Docker API创建并启动pod内的容器。

• 第五步:

◇ 创建完成之后反馈给kubelet, kubelet又将pod的状态信息给apiserver,

◇ apiserver又将pod的状态信息写入etcd。

二、Kubernetes Pod

1.pod基本概念

        Pod是Kubernetes中的最小调度单元,k8s是通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定一个镜像,这样就可以用来运行具体的服务。一个Pod封装一个或多个容器,Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

 

1.1 Pod网络

Pod是有IP地址的,每个pod都被分配唯一的IP地址(通过网络插件calico、flannel、weave等分配),POD中的容器共享网络名称空间,包括IP地址和网络端口。 Pod内部的容器可以使用localhost相互通信。 Pod中的容器也可以通过网络插件calico与其他节点的Pod通信。

1.2Pod存储

创建Pod的时候可以指定挂载的存储卷。 POD中的所有容器都可以访问共享卷,允许这些容器共享数据。 Pod只要挂载持久化数据卷,Pod重启之后数据依旧存在。若不进行挂载,Pod重启后数据消失。

 1.3Pod工作方式

在K8s中,所有的资源都可以使用一个yaml文件来创建,创建Pod也可以使用yaml配置文件。或者使用kubectl run在命令行创建Pod(不常用)。

1.4.pod控制相关

◇ 帮助信息:kubectl explain 资源名称[.字段名]

◇ 创建pod:kubectl create -f ymal文件

◇ 查看pod:kubectl get pod [-n 名称空间]

                    -o wide 查看详细信息

◇ 更新pod:kubectl apply -f yaml文件

◇ 删除pod:kubectl delete pod pod名称

◇ 进入pod:kubectl exec -it pod名称 -- /shellName

◇ 进入pod中的指定容器:kubectl exec -it pod名称  -c  容器名称 -- /bin/bash

◇ 查看pod日志:kubectl logs pod-first

◇ 查看pod中指定容器日志:kubectl logs pod名称 -c 容器名

◇ 通过kubectl run创建Pod(一般不用):kubectl run pod-run --image=tomcat:8.5-jre8-alpine  --image-pull-policy='IfNotPresent'  --port=8080

 2.命名空间

2.1 命名空间简介

• Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。这些虚拟集群被称为命名空间。

• 命名空间namespace是k8s集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命名空间,例如,可以为test、devlopment、production环境分别创建各自的命名空间。

2.2 namespace应用场景

命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本不需要创建或考虑命名空间。

2.3 namespace相关控制命令

下述命令中,namespace可缩写为ns(如:kubectl get ns)

        1) 查看名称空间及其资源对象

        ◇ 查看namespace资源:kubectl get namespace

        ◇ 查看特定名称空间的详细信息:kubectl describe namespace $NAME

        ◇ k8s集群默认提供了几个名称空间用于特定目的,例如,kube-system主要用于运行系统级资源,存放k8s一些组件的。而default则为那些未指定名称空间的资源操作提供一个默认值。

        2) 管理namespace资源

        ◇ 创建命名空间:kubectl create namespace 空间名称

        ◇ namespace资源的名称仅能由字母、数字、下划线、连接线等字符组成。删除namespace资源会级联删除其包含的所有其他资源对象。

2.4 namespace资源限额

• 可以对命名空间资源做个限制,防止该命名空间部署的资源超过限制。

• 资源限额设置:

[root@hd1.com~]# vim namespace-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-quota
  namespace: test
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 2Gi
    limits.cpu: "4"
    limits.memory: 4Gi

        yaml文件说明:创建的ResourceQuota对象将在test名字空间中添加以下限制,每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。

◇ 所有容器的内存请求总额不得超过2 GiB。

◇ 所有容器的内存限额总额不得超过4 GiB。

◇ 所有容器的CPU请求总额不得超过2 CPU。

◇ 所有容器的CPU限额总额不得超过4 CPU。

• 应用配额文件并查看命名空间是否收到了限制

[root@hd1 ~]# kubectl  apply -f namespace-quota.yaml
[root@hd1 ~]# kubectl describe ns test
Name:         test
Resource Quotas
 Name:            mem-cpu-quota
 Resource         Used  Hard
 --------         ---   ---
 limits.cpu       0     4
 limits.memory    0     4Gi
 requests.cpu     0     2
 requests.memory  0     2Gi

三、yaml文件编写

1.YAML文件 语法特点(语法结构)

• YAML大小写敏感。

• 使用缩进表示层级关系。

• 缩进只能使用空格,不能使用TAB,不要求空格个数,但相同层级应当左对齐。

• 使用符号“#”表示注释,YAML中只有行注释。

• 字符串可以不用引号标注。

• 每个“:”与它后面所跟的参数之间都需要有一个空格。

• YAML文件可以由一或多个文档组成,并用“---”符号分隔。

• 部分关键字有驼峰式写法

 2.yaml编写自主式pod资源

[root@hd1.com ~]# vim pod-tomcat.yaml
apiVersion: v1  #api版本
kind: Pod       #创建的资源
metadata:   
  name: tomcat-test  #Pod的名字
  namespace: default   #Pod所在的名称空间
  labels:
    app:  tomcat     #Pod具有的标签
spec:
  containers:
  - name:  tomcat-java   #Pod里容器的名字
    ports:
    - containerPort: 8080  #容器暴露的端口
      nodeport: 30010  #外部port调用
    image: tomcat-8.5-jre8:v1  #容器使用的镜像
  imagePullPolicy: IfNotPresent    #镜像拉取策略

#更新资源清单文件
[root@hd1.com ~]# kubectl apply -f pod-tomcat.yaml

①containerPort为容器内暴露端口,nodeport为外部port调用端口,后者范围30000~32767

②imagePullPolicy是描述镜像的拉取策略:

◇ Always 总是拉取镜像

◇ IfNotPresent 本地有则使用本地镜像不拉取,无则拉取

◇ Never 只使用本地镜像,从不拉取,即使本地没有

◇ 如果省略imagePullPolicy,  策略为always 

③如果字段后面跟着的是列表的话,后面一定是要加“-”,如果以xxxxs结尾,要重视起来,有可能要跟“-”

 3.yaml文件使用

#导入镜像并查看镜像
[root@hd2 ~]# docker images |grep tomcat
tomcat                                                            8.5-jre8-alpine
[root@hd3 ~]# docker images|grep tomcat
tomcat                                                            8.5-jre8-alpine

#更新资源清单文件
[root@hd1.com ~]# kubectl apply -f pod-tomcat.yaml

#查看pod是否创建成功
[root@hd1.com ~]# kubectl get pods -o wide -l app=tomcat
NAME          READY   STATUS       IP              NODE           
tomcat-test      1/1        Running   10.244.121.45   hd2.com  

#但是自主式Pod是存在一个问题的,假如我们不小心删除了pod:
[root@hd1.com ~]# kubectl delete pods tomcat-test

#查看pod是否还在
[root@hd1.com ~]# kubectl get pods -l app=tomcat
#结果是空,说明pod已经被删除了

        通过上面可以看到,如果直接定义一个Pod资源,那Pod被删除,就彻底被删除了,不会再创建一个新的Pod,这在生产环境还是具有非常大风险的,所以今后我们接触的Pod,都是控制器管理的。

 4.pod资源编写格式说明

        基本格式查看:

[root@hd1.com ~]# kubectl explain pod
FIELDS:
   apiVersion    <string>
#APIVersion定义了对象,代表了一个版本。
   kind  <string>
#Kind是字符串类型的值,代表了要创建的资源。服务器可以从客户端提交的请求推断出这个资源。
   metadata  <Object>
#metadata是对象,定义元数据属性信息的
   spec  <Object>
#spec制定了定义Pod的规格,里面包含容器的信息
   status    <Object>
#status表示状态,这个不可以修改,定义pod的时候也不需要定义这个字段

        查看pod.metadata字段如何定义:

[root@hd1.com ~]# kubectl explain pod.metadata
# metadata是对象<Object>,下面可以有多个字段
FIELDS:
   labels    <map[string]string> #创建的资源具有的标签
   name  <string>           #创建的资源的名字
   namespace <string>      #创建的资源所属的名称空间
# namespaces划分了一个空间,在同一个namesace下的资源名字是唯一的,默认的名称空间是default。

        查看pod.spec字段如何定义:

[root@hd1.com ~]# kubectl explain pod.spec
#Pod的spec字段是用来描述Pod的
FIELDS:
   activeDeadlineSeconds <integer>
#表示Pod可以运行的最长时间,达到设置的值后,Pod会自动停止。
affinity <Object>
  #定义亲和性的
   containers    <[]Object> -required-
#containers是对象列表,用来定义容器的,是必须字段。对象列表 表示下面有很多对象,对象列表下面的内容用 - 连接。
   dnsConfig <Object>
   dnsPolicy <string>
   enableServiceLinks    <boolean>
   ephemeralContainers   <[]Object>
   hostAliases   <[]Object>
   hostIPC   <boolean>
   hostNetwork   <boolean>
   hostPID   <boolean>
   hostname  <string>
   imagePullSecrets  <[]Object>
   initContainers    <[]Object>
   nodeName  <string>
   nodeSelector  <map[string]string>
   overhead  <map[string]string>
   preemptionPolicy  <string>
   priority  <integer>
   priorityClassName <string>
   readinessGates    <[]Object>
   restartPolicy <string>
   runtimeClassName  <string>
   schedulerName <string>
   securityContext   <Object>
   serviceAccount    <string>
   serviceAccountName    <string>
   setHostnameAsFQDN <boolean>
   shareProcessNamespace <boolean>
   subdomain <string>
   terminationGracePeriodSeconds<integer>
   tolerations   <[]Object>
   topologySpreadConstraints<[]Object>
   volumes   <[]Object>

        查看pod.spec.containers字段如何定义:

[root@hd1.com ~]# kubectl explain pod.spec.containers
FIELDS:
   args  <[]string>
   command   <[]string>
   env   <[]Object>
   envFrom   <[]Object>
   image <string>
#image是用来指定容器需要的镜像的
   imagePullPolicy   <string>
#镜像拉取策略,pod是要调度到node节点的,那pod启动需要镜像,可以根据这个字段设置镜像拉取策略,支持如下三种:
Always:不管本地是否存在镜像,都要重新拉取镜像
Never: 从不拉取镜像
IfNotPresent:如果本地存在,使用本地的镜像,本地不存在,从官方拉取镜像
   name <string> -required-
#name是必须字段,用来指定容器名字的
   ports <[]Object>
#port是端口,属于对象列表

        查看pod.spec.container.ports字段如何定义:

[root@hd1.com ~]# kubectl explain pod.spec.containers.ports
FIELDS:
   containerPort <integer> -required-
     Number of port to expose on the pod`s IP address. This must be a valid port
     number, 0 < x < 65536.
#containerPort是必须字段, pod中的容器需要暴露的端口。
   hostIP    <string>
     What host IP to bind the external port to.
#将容器中的服务暴露到宿主机的端口上时,可以指定绑定的宿主机 IP,30000-32 767
   hostPort  <integer>
     Number of port to expose on the host. If specified, this must be a valid
     port number, 0 < x < 65536. If HostNetwork is specified, this must match
     ContainerPort. Most containers do not need this.
#容器中的服务在宿主机上映射的端口
   name  <string>
     If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
     named port in a pod must have a unique name. Name for the port that can be
     referred to by services.
#端口的名字
   protocol  <string>
     Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP".

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐