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 AGE127.0.0.1 Ready 2d
查看节点详细信息,包括磁盘状态
[root@centos ~ ]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 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 ~] NAME DESIRED CURRENT READY AGE mysql 1 1 1 2d myweb 5 5 5 1d [root@centos ~] replicationcontroller "mysql" scaled [root@centos ~] 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: Deploymentmetadata: name: frontendspec: 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 deploymentsNAME DESIRED CURRENT UP-TO -DATE AVAILABLE AGE frontend 1 1 1 1 2 m
其中
DESIRED 为 Pod 副本数量的期望值,即定义的 Replica。
CURRENT 为当前的 Replica 值,它会不断变化直到达到 DESIRED 值,表明整个部署过程完成。
UP-TO-DATA 最新版本的 Pod 的副本数量,在滚动升级过程中,有多少个 Pod 副本已经升级成功了。
AVAILABLE 当前集群中可用的 Pod 副本数量。
查看对应的 Replica Set
[root@centos ~] 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 12 m
HPA HPA = Horizontal Pod Autoscaler 意思是横向自动扩容。
通过手工执行 kubectl scale 效率低,不符合自动化、智能化的定位。HPA 通过追踪分析 RC 控制的所有目标 Pod 的负载变化情况,来确定是否需要针对性的调整目标 Pod 的副本数,这是 HPA 的实现原理。
HPA 的Pod 负载度量指标:
CPUutilizationPercentage,目标 Pod 所有副本自身 CPU 利用率的平均值。
引用程序自定义的度量指标,比如服务在每秒内的请求数(TPS 或 QPS)
例子
apiVersion: autoscaling/v1kind: HorizontalPodAutoscalermetadata: name: php-apache namespace: defaultspec: 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 37 s
查看 service 的 cluster IP:
得到如下内容
apiVersion: v1kind: Servicemetadata: creationTimestamp: 2018 -03 -05 T06:46 :41 Z name: tomcat-service namespace: default resourceVersion: "256242" selfLink: /api/ v1/namespaces/ default/services/ tomcat-service uid: f6544c3e-2040 -11e8 -b481-fa163eee21c2spec: clusterIP: 10.254 .1 .165 ports: - port: 8080 protocol: TCP targetPort: 8080 selector: tier: frontend sessionAffinity: None type: ClusterIPstatus: 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 AGEdefault Active 2 d kube- system Active 2 d
如果不特别指明,则创建的 Pod RC service 都会被分配到 default 中。
定义 namespace,创建一个 namespace-demo.yaml 的文件
apiVersion: v1kind: Namespacemetadata: name: development
然后创建查看 namespace
[root@centos ~]# kubectl create -f namespace -demo.yamlnamespace "development" created [root@centos ~]# kubectl get namespaces NAME STATUS AGEdefault Active 2 d development Active 4 s kube-system Active 2 d
添加一个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 1 h mysql-7 p27m 1 / 1 Running 0 42 m myweb-0 n7b9 1 / 1 Running 0 42 m myweb-5 dcff 1 / 1 Running 0 42 m myweb- mbxk4 1 / 1 Running 0 42 m myweb- md64b 1 / 1 Running 0 42 m myweb- rkql9 1 / 1 Running 0 42 m
直接查看不显示,需要加参数
[root@centos ~] # kubectl get pods --namespace =development NAME READY STATUS RESTARTS AGE busybox 1 /1 Running 0 57s
文章作者: 阿文
版权声明: 本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0 许可协议。转载请注明来自
阿文的博客 !