内容简介:Kubernetes 中的大部分概念如 Node、 Pod、 ReplicationController、 Service 等都可以看作一种“资源对象”, 几乎所有的资源对象都可以通过 Kubernetes 提供的 kubectl 工具(或者 API 编程调用) 执行 增、 删、 改、 查 等操作并将其保存 在 etcd 中持久化存储。几乎所有的控制命令都是发给 Master 的,一般来说 Master 会单独部署在一个虚拟机或 X86服务器上Master 的进程包括:
Kubernetes 中的大部分概念如 Node、 Pod、 ReplicationController、 Service 等都可以看作一种“资源对象”, 几乎所有的资源对象都可以通过 Kubernetes 提供的 kubectl 工具(或者 API 编程调用) 执行 增、 删、 改、 查 等操作并将其保存 在 etcd 中持久化存储。
Master
几乎所有的控制命令都是发给 Master 的,一般来说 Master 会单独部署在一个虚拟机或 X86服务器上
Master 的进程包括:
- Kubernetes API Server( kube- apiserver), 提供了 HTTP Rest 接口的关键服务进程, 是 Kubernetes 里所有资源的增、删、改、查等操作的唯一 入口,也是集群控制 的入口进程。
- Kubernetes Controller Manager( kube- controller- manager), Kubernetes 里所有资源对象的自动化控制中心, 可以理解为资源对象的“大总管”。
- Kubernetes Scheduler( kube- scheduler), 负责资源调度(Pod 调度)的程, 相当于公交公司的“ 调度室”。
其实 Master 节点上往往还启动了一个 etcd Server 进程, 因为 Kubernetes 里 的 所有 资源 对象 的 数据 全部 是 保存 在 etcd 中的。
Node
除了 Master,Kubernetes 集群中的其他机器被称为 Node 节点.
每个 Node 节点上都运行着以下一组关键进程。
- kubelet: 负责Pod 的创建 删除 启动 停止, 同时与 Master 节点密切协作, 实现集群管理的基本功能。
- kube- proxy: 实现 Kubernetes Service 的通信与负载均衡机制的重要组件。
- Docker Engine( dockerDocker 引擎, 负责本机的容器创建和管理工作。
查看节点
[root@centos ~]# kubectl get node NAME STATUS AGE 127.0.0.1 Ready 2d
查看节点详细信息,包括磁盘状态
[root@centos ~]# kubectl describe node 127.0.0.1 Name: 127.0.0.1 # 节点名称 Role: Labels: beta.kubernetes.io/arch=amd64 # 节点标签 beta.kubernetes.io/os=linux kubernetes.io/hostname=127.0.0.1 Taints: <none> CreationTimestamp: Fri, 02 Mar 2018 21:59:52 +0800 # 创建时间 Phase: Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- OutOfDisk False Mon, 05 Mar 2018 10:24:15 +0800 Fri, 02 Mar 2018 21:59:52 +0800 KubeletHasSufficientDisk kubelet has sufficient disk space available # 磁盘信息 True 表示磁盘满了. MemoryPressure False Mon, 05 Mar 2018 10:24:15 +0800 Fri, 02 Mar 2018 21:59:52 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure False Mon, 05 Mar 2018 10:24:15 +0800 Fri, 02 Mar 2018 21:59:52 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure Ready True Mon, 05 Mar 2018 10:24:15 +0800 Sat, 03 Mar 2018 10:50:27 +0800 KubeletReady kubelet is posting ready status Addresses: 127.0.0.1,127.0.0.1,127.0.0.1 Capacity: alpha.kubernetes.io/nvidia-gpu: 0 cpu: 4 memory: 8002252Ki pods: 110 Allocatable: alpha.kubernetes.io/nvidia-gpu: 0 cpu: 4 memory: 8002252Ki pods: 110 System Info: Machine ID: 3ce150b846d1364ca00934cb4b7425e7 System UUID: 6648964A-8A37-49F8-AE2E-CD51D601E0A4 Boot ID: 6c79106a-2825-43e5-a49a-ce1837fed475 Kernel Version: 3.10.0-693.el7.x86_64 OS Image: CentOS Linux 7 (Core) Operating System: linux Architecture: amd64 Container Runtime Version: docker://1.12.6 Kubelet Version: v1.5.2 Kube-Proxy Version: v1.5.2 ExternalID: 127.0.0.1 Non-terminated Pods: (6 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits --------- ---- ------------ ---------- --------------- ------------- default mysql-j6vpx 0 (0%) 0 (0%) 0 (0%) 0 (0%) default myweb-cwhhl 0 (0%) 0 (0%) 0 (0%) 0 (0%) default myweb-ljwtl 0 (0%) 0 (0%) 0 (0%) 0 (0%) default myweb-n0vrj 0 (0%) 0 (0%) 0 (0%) 0 (0%) default myweb-rnjq9 0 (0%) 0 (0%) 0 (0%) 0 (0%) default myweb-sgfhs 0 (0%) 0 (0%) 0 (0%) 0 (0%) Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted. CPU Requests CPU Limits Memory Requests Memory Limits ------------ ---------- --------------- ------------- 0 (0%) 0 (0%) 0 (0%) 0 (0%) No events.
Pod
Pod 是 kubernetes 中 最基本的单位,每个 Pod 都有一个根容器叫 Pause
为什么需要根容器?
- 一组容器作为一个 Pod,无法对整体进行简单的判断并作出行动,比如一个容器死了是整体都死了吗?因此需要一个无关的根容器来代表整个容器的状态.
- Pod 的多个业务容器共享 Pause 的 IP, 并共享容器挂载的卷,既解决了通信问题又解决了共享问题
kubernetes 中,每个Pod都分配了一个唯一的 IP, 称之为 Pod-IP, 不同 Pod 和其他 pod 是可以通信的
在 Kubernetes 里, 一个计算资源进行配额限定需要设定以下两个参数。
- Requests: 该资源的最小申请量,系统必须满足要求。
- Limits: 该资源最大允许使用的量, 不能被突破, 当容器试图使用超过这个量的资源时, 可能会被 Kubernetes Kill 并重启。
通常来说我们会把 Requests 的值设置为一个比较小的数值,符合容器平时的工作负载情况下的资源需求,而 Limit 设置为峰值负载情况下资源占用的最大量,比如下面这段,表明 MYSQL 容器申请至少0.25个 CPU 一级64MiB 内存,在运行过程中容器所使用的资源配额为0.5个 CPU 以及128MiB 内存:
spec: containers: - name: db image: mysql resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
Label
一个 Label 是一个 key=value 的键值对,由用户自主设定, Label 可以附加到各种资源对象上,例如 Node、Pod、Service、RC 等,一个资源对象可以定义任意数量的 Label,同一个 Label 也可以被添加到任意数量的资源对象上去,Label 通常在资源对象定义时确定,也可以在对象创建后动态添加或删除。
Label 定义后,可以通过 Label Selector 查询和筛选拥有某些 Label 的资源对象。查询类似 SQL 的 where 查询条件:
- name = redis-slave 匹配name等于 redis-slave 的资源对象。
- env != production 匹配不具有标签 env=production 的资源对象, 比如 env=test 就满足此条件。
- name in (redis-slave,redis-master) 匹配所有包含 redis-slave 和 redis-master 的资源对象。
- name notin (php-frontend),匹配所有不具有标签 name=php-frontend 的资源对象
多个表达式可以组合实现,需要用”,” 分割,几个条件之间是 “AND” 的关系
name= redis- slave, env!= production name notin (php- frontend), env!= production
Label 选择器的使用场景:
- kube-controller 进程通过资源对象 RC 定义标签来筛选要监控的副本数量,实现自动控制流程。
- kube-proxy 进程通过 service 的标签选择器来选择对应的 Pod,自动建立每个 service 到对应 Pod的请求转发路由表,从而实现 service 的智能负载均衡机制。
- 通过对某些 Node 定义特定标签,并且在 Pod 定义文件中使用 NodeSelector 这种标签调度策略,kube-scheduler 进程可实现 Pod“定向调度”的特性。
多 label
RC
RC 定义了一个期望的场景,即声明某种 Pod 的副本数在任何时候都符合预期,其包括:
- 副本数
- 用于筛选的 Pod 和 标签选择器
- 当 Pod 副本数小于预期数量时,用于创建新 Pod 的模板
RC 提交到集群–Master Controller Manager 组件收到通知,定期巡检当前存活的目标 Pod,并确保目标 Pod 实力数量刚好等于此 RC 的预期值,如果多于 Pod 副本,就会停掉一些,否则会创建一些 Pod。
动态缩放rc
[root@centos ~]# kubectl get rc NAME DESIRED CURRENT READY AGE mysql 1 1 1 2d myweb 5 5 5 1d [root@centos ~]# kubectl scale rc mysql --replicas=3 replicationcontroller "mysql" scaled [root@centos ~]# kubectl get rc NAME DESIRED CURRENT READY AGE mysql 3 3 1 2d myweb 5 5 5 1d [root@centos ~]#
删除 RC 并不会影响通过该 RC 已经创建好的 Pod,为了删除所有 Pod,可以设置 replicas=0 然后更新该 RC,另外可以使用 stop 或 delete 删除 RC 和 RC 控制的全部 Pod。
Deployment
从 k8s 1.2引入的新概念, 与RC 相似度90%,目的是为了更好的解决 Pod 的编排问题。Deployment 在内部使用了 Replica Set 来实现目的。
Deployment 相对于 RC 的一个最大的升级就是随时知道当前 Pod “部署”的进度
Deployment 的场景:
- 创建一个 DP 对象来生成对应的 Replica Set 并完成 Pod 副本的创建过程。
- 检查 DP 的状态来看部署动作是否完成。
- 更新 DP 以创建新的 Pod(比如镜像升级)。
- 如果当前 DP 不稳定,回滚到一个早先的 DP 版本。
- 挂起或恢复一个 DP
例子,tomcat-deployment.yaml
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend spec: replicas: 1 selector: matchLabels: tier: frontend matchExpressions: - {key: tier,operator: In,values: [frontend]} template: metadata: labels: app: app-demo tier: frontend spec: containers: - name: tomcat-demo image: tomcat imagePullPolicy: IfNotPresent ports: - containerPort: 8080
然后在集群中创建 deployment
[root@centos ~]# kubectl create -f tomcat-dp.yaml deployment "frontend" created
然后查看
[root@centos ~]# kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE frontend 1 1 1 1 2m
其中
- DESIRED 为 Pod 副本数量的期望值,即定义的 Replica。
- CURRENT 为当前的 Replica 值,它会不断变化直到达到 DESIRED 值,表明整个部署过程完成。
- UP-TO-DATA 最新版本的 Pod 的副本数量,在滚动升级过程中,有多少个 Pod 副本已经升级成功了。
- AVAILABLE 当前集群中可用的 Pod 副本数量。
查看对应的 Replica Set
[root@centos ~]# kubectl get rs NAME DESIRED CURRENT READY AGE frontend-141477217 1 1 1 11m
查看 pods
[root@centos ~]# kubectl get pods NAME READY STATUS RESTARTS AGE frontend-141477217-jcckp 1/1 Running 0 12m
HPA
HPA = Horizontal Pod Autoscaler 意思是横向自动扩容。
通过手工执行 kubectl scale 效率低,不符合自动化、智能化的定位。HPA 通过追踪分析 RC 控制的所有目标 Pod 的负载变化情况,来确定是否需要针对性的调整目标 Pod 的副本数,这是 HPA 的实现原理。
HPA 的Pod 负载度量指标:
- CPUutilizationPercentage,目标 Pod 所有副本自身 CPU 利用率的平均值。
- 引用程序自定义的度量指标,比如服务在每秒内的请求数(TPS 或 QPS)
例子
apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name:php-apache namespace: default spec: maxReplicas: 10 minReplicas: 1 scaleTargetRef: kind: Deployment name: php-apache targetCPUUtilizationPercentage: 90
命令方式实现
kubectl autoscale deployment php- apache --cpu- percent= 90 --min= 1 --max= 10
Service
之前的 Pod RC 都是为服务做“嫁衣”的
k8s 定义了一个服务的访问入口地址,前端通过这个入口访问其背后的一组由 Pod 副本组成的集群,service 与后端 Pod 通过 label selector 来实现对接。 而 RC 的作用是保证 service 的服务能能力和服务质量能够始终处于预期的标准。
每个 Pod 都会被分配一个单独的 IP 地址,而且每个 Pod 都提供一个独立的 endpoint 以被客户端访问,现在多个 Pod 组成的集群提供服务,一般是需要部署一个负载均衡器实现转发。在 k8s 中,node 上的 kube-proxy 就是一个软件负载均衡器,它负责把对 service 的请求转发到后端的某个 Pod 实例上,部署实现服务的负载均衡与会话保持机制,每个 service 分配一个全局唯一的虚拟 IP 地址,这个虚拟 IP 被称为 cluster IP,其在 service 的整个生命周期内是不变的。
apiVersion: v1 kind: Service metadata: name: tomcat-service spec: ports: - port: 8080 selector: tier: frontend
这里的标签与之前创建的 Tomcat 对应,查看暴露的地址和端口
[root@centos ~]# kubectl get endpoints NAME ENDPOINTS AGE kubernetes 192.168.10.115:6443 2d mysql 172.17.0.3:3306 3m tomcat-service 172.17.0.2:8080 37s
查看 service 的 cluster IP:
[root@centos ~]# kubectl get svc tomcat-service -o yaml
得到如下内容
apiVersion: v1 kind: Service metadata: creationTimestamp: 2018-03-05T06:46:41Z name: tomcat-service namespace: default resourceVersion: "256242" selfLink: /api/v1/namespaces/default/services/tomcat-service uid: f6544c3e-2040-11e8-b481-fa163eee21c2 spec: clusterIP: 10.254.1.165 ports: - port: 8080 protocol: TCP targetPort: 8080 selector: tier: frontend sessionAffinity: None type: ClusterIP status: loadBalancer: {}
其中 targetPort 属性用来确定提供该服务的容器暴露(EXPOSE)的端口,而 port 则定义 service 的虚拟端口,因为前面 Tomcat 没有指定 targetport,则默认与 port 相同。
多端口问题
其样例:
apiVersion: v1 kind: Service metadata: name: tomcat-service spec: ports: - port: 8080 name: service-port - port: 8005 name: shutdown-port selector: tier: frontend
为什么要给多端口命名,这就需要涉及 k8s 的服务发现了。
服务发现
首先,每个 k8s 中的 service 都有一个唯一的 cluster IP 以及唯一的名字,而名字是由开发者自定义的,部署的时候也没必要改变,所以完全可以固定在配置中。
早期 k8s 采用 linux 环境变量的方式解决问题。
这种方式不太方便,后来 k8s 通过 ADD-On 增值包的方式引入了 DNS 系统,把服务名作为 DNS 域名。
外部系统访问 service 的问题
采用nodeport 访问最为直接,但是 nodeport 无法解决例如负载均衡的问题,需要有一个 load balancer
Volume (存储卷)
k8s 的 volume 是 Pod 中能够给多容器访问的共享目录,与 docker 的 volume 类似,但不等价。首先,k8s 的 volume 定义在 Pod 上,然后被一个 Pod 里的多个容器挂载到具体的文件目录下,其次,k8s 的 volume 与 Pod 的生命周期相同,但是与容器的生命周期不相关。最后,k8s 支持多种类型的 volume,例如 ceph 等分布式文件系统。
k8s 的 volume 类型有:emptyDir(初始为空的,用来存放一些临时文件)、hostPath(主机文件或目录,存放日子等需要永久保存的文件)、gcePersistentDisk(谷歌公有云的永久磁盘,数据不会被删除,但是有限制条件)、awsElasticBlockStore(与前者类似)、NFS、其他类型的(iscsi等)。
Persistent volume
简称 PV,可以理解为 k8s 集群中的某个网络存储中对应的一块存储:
- PV 只能是网络存储,不属于任何 Node,但是可以在 Node 上访问。
- PV 并不是定义在 Pod 上,而是独立在 Pod 之外。
- PV 目前的类型有 GCE NFS RBD iSCSCI aswElasticBlockStore GlusterFS
Namespace
中文名命令空间,可以实现多租户的资源隔离,通过将集群内部的资源对象分配到不同的 namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同分组在共享使用整个集群的资源的同时还能被分别管理。
默认会有一个 default 的 namespace。
[root@centos ~]# kubectl get namespaces NAME STATUS AGE default Active 2d kube-system Active 2d
如果不特别指明,则创建的 Pod RC service 都会被分配到 default 中。
定义 namespace,创建一个 namespace-demo.yaml 的文件
apiVersion: v1 kind: Namespace metadata: name: development
然后创建查看 namespace
[root@centos ~]# kubectl create -f namespace-demo.yaml namespace "development" created [root@centos ~]# kubectl get namespaces NAME STATUS AGE default Active 2d development Active 4s kube-system Active 2d
添加一个pod 的配置,直到其 namespace 为 development
apiVersion: v1 kind: Pod metadata: name: busybox namespace: development spec: containers: - image: busybox command: - sleep - "36000" name: busybox
创建
[root@centos ~]# kubectl create -f busybox.yaml pod "busybox" created
查看
[root@centos ~]# kubectl get pods NAME READY STATUS RESTARTS AGE frontend-141477217-jcckp 1/1 Running 0 1h mysql-7p27m 1/1 Running 0 42m myweb-0n7b9 1/1 Running 0 42m myweb-5dcff 1/1 Running 0 42m myweb-mbxk4 1/1 Running 0 42m myweb-md64b 1/1 Running 0 42m myweb-rkql9 1/1 Running 0 42m
直接查看不显示,需要加参数
[root@centos ~]# kubectl get pods --namespace=development NAME READY STATUS RESTARTS AGE busybox 1/1 Running 0 57s
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
How to Solve It
Zbigniew Michalewicz、David B. Fogel / Springer / 2004-03-01 / USD 59.95
This book is the only source that provides comprehensive, current, and detailed information on problem solving using modern heuristics. It covers classic methods of optimization, including dynamic pro......一起来看看 《How to Solve It》 这本书的介绍吧!