1、Pod简介
Pod是k8s系统中能够建立和管理的最小单元,是资源对象模型中由用户建立或部署的最小资源对象模型,也是在k8s上运行容器化应用的资源对象,其余的资源对象都是用来支撑或者扩展Pod对象功能的,好比控制器对象是用来管控Pod对象的,Service或者Ingress资源对象是用来暴露Pod引用对象的,PersistentVolume资源对象是用来为Pod提供存储等等,k8s不会直接处理容器,而是Pod,Pod是由一个或者多个container组成的。php
每一个Pod都是运行应用的单个实例,若是须要水平扩展应用(例如,运行多个实例),则应该使用多个Pods,每一个实例一个Pod。在Kubernetes中,这样一般称为Replication。Replication的Pod一般由Controller建立和管理。html
1.一、为何须要pod
咱们先谈谈为何k8s会使用pod这个最小单元,而不是使用docker的容器,k8s既然使用了pod,固然有它的理由。前端
一、更利于扩展
k8s不只仅支持Docker容器,也支持rkt甚至用户自定义容器,为何会有这么多不一样的容器呢,由于容器并非真正的虚拟机,docker的一些概念和误区总结,此外,Kubernetes不依赖于底层某一种具体的规则去实现容器技术,而是经过CRI这个抽象层操做容器,这样就会须要pod这样一个东西,pod内部再管理多个业务上紧密相关的用户业务容器,就会更有利用业务扩展pod而不是扩展容器。
node
二、更容易定义一组容器的状态nginx
若是咱们没有使用pod,而是直接使用一组容器去跑一个业务呢,那么当其中一个或者若干个容器出现问题呢,咱们如何去定义这一组容器的状态呢,经过pod这个概念,这个问题就能够很好的解决,一组业务容器跑在一个k8s的pod中,这个pod中会有一个pause容器,这个容器与其余的业务容器都没有关系,以这个pause容器的状态来表明这个pod的状态.git
三、利于容器间文件共享,以及通讯。
pod里的多个业务容器共享pause容器的ip和存储卷Volume,pod中的其余容器共享pause容器的ip地址和存储,这样就作到了文件共享和互信。
web
1.2 Pod 特性:
1 资源共享:IP和Volume
一个Pod里的多个容器能够共享存储和网络IP,能够看做一个逻辑的主机。共享的如 namespace,cgroups或者其余的隔离资源。redis
多个容器共享同一个network namespace,由此在一个Pod里的多个容器共享Pod的IP和端口namespace,因此一个Pod内的多个容器之间能够经过localhost来进行通讯,所须要注意的是不一样容器要注意不要有端口冲突便可。不一样的Pod有不一样的IP,不一样Pod内的多个容器以前通讯,不可使用IPC(若是没有特殊指定的话)通讯,一般状况下使用Pod的IP进行通讯。算法
k8s要求底层网络支持集群内任意两个pod直接的TCP/IP直接通讯,这一般才有虚拟二层网络技术来实现,例如Flannel,Openswitch等。spring
一个Pod里的多个容器能够共享存储卷,这个存储卷会被定义为Pod的一部分,而且能够挂载到该Pod里的全部容器的文件系统上。
2 生命周期短暂
Pod属于生命周期比较短暂的组件,好比,当Pod所在节点发生故障,那么该节点上的Pod会被调度到其余节点,但须要注意的是,被从新调度的Pod是一个全新的Pod,跟以前的Pod没有半毛钱关系。
3 平坦的网络
K8s集群中的全部Pod都在同一个共享网络地址空间中,也就是说每一个Pod均可以经过其余Pod的IP地址来实现访问。
1.3 Pod使用和管理
一、核心原则是:将多个应用分散到多个Pod中
缘由:基于资源的合理应用;扩缩容,不一样应用应该有不一样的扩缩容策略等。
若是容器之间不是必须运行在一块儿的话,那么就放到不一样的Pod里
若是容器以前是相互独立的组件,那么就放到不一样的Pod里
若是容器以前扩缩容策略不同,那么就放到不一样的Pod里
结论:单Pod单容器应用,除非特殊缘由。
你不多会直接在kubernetes中建立单个Pod。由于Pod的生命周期是短暂的,用后即焚的实体。当Pod被建立后(不管是由你直接建立仍是被其余Controller),都会被Kubernetes调度到集群的Node上。直到Pod的进程终止、被删掉、由于缺乏资源而被驱逐、或者Node故障以前这个Pod都会一直保持在那个Node上。
注意:重启Pod中的容器跟重启Pod不是一回事。Pod只提供容器的运行环境并保持容器的运行状态,重启容器不会形成Pod重启。
Pod不会自愈。若是Pod运行的Node故障,或者是调度器自己故障,这个Pod就会被删除。一样的,若是Pod所在Node缺乏资源或者Pod处于维护状态,Pod也会被驱逐。Kubernetes使用更高级的称为Controller的抽象层,来管理Pod实例。虽然能够直接使用Pod,可是在Kubernetes中一般是使用Controller来管理Pod的。
1.四、Pod和Controller
Controller能够建立和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,若是一个Node故障,Controller就能自动将该节点上的Pod调度到其余健康的Node上。
包含一个或者多个Pod的Controller示例:
一般,Controller会用你提供的Pod Template来建立相应的Pod。
在用户定义范围内,若是pod增多,则ReplicationController会终止额外的pod,若是减小,RC会建立新的pod,始终保持在定义范围。例如,RC会在Pod维护(例如内核升级)后在节点上从新建立新Pod。
2、Pod定义
对Pod的定义能够经过Yaml或Json格式的配置文件来完成。关于Yaml或Json中都能写哪些参数,参考官网http://kubernetes.io/docs/user-guide/pods/multi-container/
Pod的yaml总体文件内容及功能注解以下:
# yaml格式的pod定义文件完整内容:
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #必选,Pod所属的命名空间
labels: #自定义标签
- name: string #自定义标签名字
annotations: #自定义注释列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,不然下载镜像,Nerver表示仅使用本地镜像
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工做目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #须要暴露的端口库号列表
- name: string #端口号名称
containerPort: int #容器须要监听的端口号
hostPort: int #容器所在主机须要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位能够为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存清楚,容器启动的初始可用数量
livenessProbe: #对Pod内个容器健康检查的设置,当探测无响应几回后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法便可
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式须要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,须要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的按期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged:false
restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦无论以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示再也不重启该Pod
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork:false #是否使用主机网络模式,默认为false,若是设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有不少种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预约义的configMap对象到容器内部
name: string
items:
- key: string
path: string
3、Pod使用
在使用docker时,咱们可使用docker run命令建立并启动一个容器,而在Kubernetes系统中对长时间运行的容器要求是:其主程序须要一直在前台运行。若是咱们建立的docker镜像的启动命令是后台执行程序,例如Linux脚本:
nohup ./startup.sh &
则kubelet建立包含这个容器的pod后运行完该命令,即认为Pod执行结束,以后根据RC中定义的pod的replicas副本数量生产一个新的pod,而一旦建立出新的pod,将在执行完命令后陷入无限循环的过程当中,这就是Kubernetes须要咱们建立的docker镜像以一个前台命令做为启动命令的缘由。
对于没法改造为前台执行的应用,也可使用开源工具supervisor辅助进行前台运行的功能。
Pod能够由一个或多个容器组合而成
场景1:单个应用多个容器
spring boot web:
apiVersion:v1
kind: Pod
metadata:
name: springbootweb
label:
name: test
spec:
containers:
- name: springbootweb
image: registry.tuling123.com/springboot:latest
ports:
- containerPort: 9081
kubectl create -f springboot-deployment.yml
[root@k8s-master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
springbootweb 0/1 Pending 0 1m
kubectl get pods -o wide
# 加入 –o wide参数 查看额外信息:包括node和ip
pod处于pending的缘由:经过kubectl describe pods springbootweb进一步查找问题。
能够看到pod的镜像信息写错了:
先删除pod,而后再建立:kubectl delete pod springbootweb
因为建立的端口号是9081,能够直接访问:curl 10.0.86.2:9081
# curl 10.0.86.2:9081
Hello world
场景2:Pod不一样应用多个容器组合而成
例如:两个容器应用的前端frontend和redis为紧耦合的关系,应该组合成一个总体对外提供服务,则应该将这两个打包为一个pod.
配置文件frontend-localredis-pod.yaml以下:
apiVersion:v1
kind: Pod
metadata:
name: redis-php
label:
name: redis-php
spec:
containers:
- name: frontend
image: kubeguide/guestbook-php-frontend:localredis
ports:
- containersPort: 80
- name: redis-php
image:kubeguide/redis-master
ports:
- containersPort: 6379
属于一个Pod的多个容器应用之间相互访问只须要经过localhost就能够通讯,这一组容器被绑定在一个环境中。
使用kubectl create建立该Pod后,get Pod信息能够看到以下图:
#kubectl get gods
NAME READY STATUS RESTATS AGE
redis-php 2
/2
Running 0 10m
能够看到READY信息为2/2,表示Pod中的两个容器都成功运行了.
2.3 集群外部访问Pod
上面的例子,在k8s集群的安装有kube-proxy的node节点上,能够直接经过curl 10.0.86.2:9081 访问集群的pod。但在集群外的客户端系统没法经过Pod的IP地址或者Service的虚拟IP地址和虚拟端口号访问到它们。为了让外部客户端能够访问这些服务,能够将Pod或Service的端口号映射到宿主机,以使得客户端应用可以经过物理机访问容器应用。
一、将容器应用的端口号映射到物理机
apiVersion:v1
kind: Pod
metadata:
name: springbootweb
label:
name: test
spec:
containers:
- name: springbootweb
image: registry.tuling123.com/springboot:latest
ports:
- containerPort:9081
hostPort: 9082
(2)经过设置Pod级别的hostNetwork-true,该Pod中全部容器的端口号都将被直接映射到物理机上。设置hostNetwork-true时须要注意,在容器的ports定义部分若是不指定hostPort,则默认hostPort等于containerPort,若是指定了hostPort,则hostPort必须等于containerPort的值。
apiVersion:v1
kind: Pod
metadata:
name: springbootweb
label:
name: test
spec:
hostNetwork: true
containers:
- name: springbootweb
image: registry.tuling123.com/springboot:latest
ports:
- containerPort:9081
4、静态Pod
静态pod是由kubelet进行管理的仅存在于特定Node的Pod上,他们不能经过API Server进行管理,没法与ReplicationController、Deployment或者DaemonSet进行关联,而且kubelet没法对他们进行健康检查。静态Pod老是由kubelet进行建立,而且老是在kubelet所在的Node上运行。
建立静态Pod有两种方式:配置文件或者HTTP方式
1)配置文件方式
首先,须要设置kubelet的启动参数"--config",指定kubelet须要监控的配置文件所在的目录,kubelet会按期扫描该目录,冰根据目录中的 .yaml或 .json文件进行建立操做
假设配置目录为/etc/kubelet.d/配置启动参数:--config=/etc/kubelet.d/,而后重启kubelet服务后,再宿主机受用docker ps或者在Kubernetes Master上均可以看到指定的容器在列表中
因为静态pod没法经过API Server直接管理,因此在master节点尝试删除该pod,会将其变为pending状态,也不会被删除
#kubetctl delete pod static-web-node1
pod
"static-web-node1"
deleted
#kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-node1 0
/1
Pending 0 1s
要删除该pod的操做只能在其所在的Node上操做,将其定义的.yaml文件从/etc/kubelet.d/目录下删除
#rm -f /etc/kubelet.d/static-web.yaml
#docker ps
5、Pod容器共享Volume
Volume类型包括:emtyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、gitRepo、secret、nfs、scsi、glusterfs、persistentVolumeClaim、rbd、flexVolume、cinder、cephfs、flocker、downwardAPI、fc、azureFile、configMap、vsphereVolume等等,能够定义多个Volume,每一个Volume的name保持惟一。在同一个pod中的多个容器可以共享pod级别的存储卷Volume。Volume能够定义为各类类型,多个容器各自进行挂载操做,讲一个Volume挂载为容器内须要的目录。
以下图:
如上图中的Pod中包含两个容器:tomcat和busybox,在pod级别设置Volume “app-logs”,用于tomcat想其中写日志文件,busybox读日志文件。
配置文件以下:
apiVersion:v1
kind: Pod
metadata:
name: redis-php
label:
name: volume-pod
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containersPort: 8080
volumeMounts:
- name: app-logs
mountPath:/usr/local/tomcat/logs
- name: busybox
image:busybox
command: ["sh","-C","tail -f /logs/catalina*.log"]
volumes:
- name: app-logs
emptyDir:{}
busybox容器能够经过kubectl logs查看输出内容
#kubectl logs volume-pod -c busybox
tomcat容器生成的日志文件能够登陆容器查看
#kubectl exec -ti volume-pod -c tomcat -- ls /usr/local/tomcat/logs
六.Pod的配置管理
应用部署的一个最佳实践是将应用所需的配置信息于程序进行分离,这样可使得应用程序被更好的复用,经过不用配置文件也能实现更灵活的功能。将应用打包为容器镜像后,能够经过环境变量或外挂文件的方式在建立容器时进行配置注入。ConfigMap是Kubernetes v1.2版本开始提供的一种统一集群配置管理方案。
6.1 ConfigMap:容器应用的配置管理
容器使用ConfigMap的典型用法以下:
(1)生产为容器的环境变量。
(2)设置容器启动命令的启动参数(需设置为环境变量)。
(3)以Volume的形式挂载为容器内部的文件或目录。
ConfigMap以一个或多个key:value的形式保存在Kubernetes系统中共应用使用,既能够用于表示一个变量的值,也能够表示一个完整的配置文件内容。
经过yuaml配置文件或者直接使用kubelet create configmap 命令的方式来建立ConfigMap
6.2 ConfigMap的建立
举个小例子cm-appvars.yaml来描述将几个应用所需的变量定义为ConfigMap的用法:
# vim cm-appvars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
apploglevel: info
appdatadir:/var/data
执行kubectl create命令建立该ConfigMap
#kubectl create -f cm-appvars.yaml
configmap
"cm-appvars.yaml"
created
查看创建好的ConfigMap:
#kubectl get configmap
kubectl describe configmap cm-appvars
kubectl get configmap cm-appvars -o yaml
另:建立一个cm-appconfigfile.yaml描述将两个配置文件server.xml和logging.properties定义为configmap的用法,设置key为配置文件的别名,value则是配置文件的文本内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
key-serverxml:
<?xml Version='1.0'encoding='utf-8'?>
<Server port="8005"shutdown="SHUTDOWN">
.....
</service>
</Server>
key-loggingproperties:
"handlers=lcatalina.org.apache.juli.FileHandler,
...."
在pod "cm-test-app"定义中,将configmap "cm-appconfigfile"中的内容以文件形式mount到容器内部configfiles目录中。
Pod配置文件cm-test-app.yaml内容以下:
#vim cm-test-app.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-test-app
spec:
containers:
- name: cm-test-app
image: tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml #引用volume名
mountPath:/configfiles #挂载到容器内部目录
configMap:
name: cm-test-appconfigfile #使用configmap定义的的cm-appconfigfile
items:
- key: key-serverxml #将key=key-serverxml
path: server.xml #value将server.xml文件名进行挂载
- key: key-loggingproperties #将key=key-loggingproperties
path: logging.properties #value将logging.properties文件名进行挂载
建立该Pod:
#kubectl create -f cm-test-app.yaml
Pod "cm-test-app"created
登陆容器查看configfiles目录下的server.xml和logging.properties文件,他们的内容就是configmap “cm-appconfigfile”中定义的两个key的内容
#kubectl exec -ti cm-test-app -- bash
root@cm-rest-app:/# cat /configfiles/server.xml
root@cm-rest-app:/# cat /configfiles/logging.properties
6.3使用ConfigMap的条件限制
使用configmap的限制条件以下:
- configmap必须在pod之间建立
- configmap也能够定义为属于某个Namespace,只有处于相同namespaces中的pod能够引用
- configmap中配额管理还未能实现
- kubelet只支持被api server管理的pod使用configmap,静态pod没法引用
- 在pod对configmap进行挂载操做时,容器内部职能挂载为目录,没法挂载文件。
7、Pod生命周期和重启策略
Pod在整个生命周期过程当中被定义为各类状态,熟悉Pod的各类状态有助于理解如何设置Pod的调度策略、重启策略
Pod的状态包含如下几种,如图:
Pod的重启策略(RestartPolicy)应用于Pod内全部的容器,而且仅在Pod所处的Node上由kubelet进行判断和重启操做。当某哥容器异常退出或者健康检查石柏师,kubelet将根据RestartPolicy的设置进行相应的操做
Pod的重启策略包括Always、OnFailure及Nerver,默认值为Always。
kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如一、二、四、8倍等,最长延时5分钟,而且成功重启后的10分钟后重置该事件。
Pod的重启策略和控制方式息息相关,当前可用于管理Pod的控制器宝库ReplicationController、Job、DaemonSet及直接经过kubelet管理(静态Pod),每种控制器对Pod的重启策略要求以下:
- RC和DaemonSet:必须设置为Always,须要保证该容器持续运行
- Job:OnFailure或Nerver,确保容器执行完成后再也不重启
- kubelet:在Pod失效时重启他,不论RestartPolicy设置什么值,而且也不会对Pod进行健康检查
8、Pod健康检查
对Pod的健康检查能够经过两类探针来检查:LivenessProbe和ReadinessProbe
- LivenessProbe探针:用于判断容器是否存活(running状态),若是LivenessProbe探针探测到容器不健康,则kubelet杀掉该容器,并根据容器的重启策略作响应处理
- ReadinessProbe探针:用于判断容器是否启动完成(ready状态),能够接受请求。若是ReadinessProbe探针探测失败,则Pod的状态被修改。Endpoint Controller将从service的Endpoint中删除包含该容器所在的Pod的Endpoint。
kubelet定制执行LivenessProbe探针来诊断容器的健康情况。LivenessProbe有三种事项方式。
1)ExecAction:在容器内部执行一个命令,若是该命令的返回值为0,则表示容器健康。例:
apiVersion:v1
kind: Pod
metadata:
name: liveness-exec
label:
name: liveness
spec:
containers:
- name: tomcat
image: grc.io/google_containers/tomcat
args:
-/bin/sh
- -c
-echo ok >/tmp.health;sleep10; rm -fr /tmp/health;sleep600
livenessProbe:
exec:
command:
-cat
-/tmp/health
initianDelaySeconds:15
timeoutSeconds:1
(2)TCPSocketAction:经过容器ip地址和端口号执行TCP检查,若是可以创建tcp链接代表容器健康。例:
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
livenessProbe:
tcpSocket:
port: 80
initianDelaySeconds:30
timeoutSeconds:1
3)HTTPGetAction:经过容器Ip地址、端口号及路径调用http get方法,若是响应的状态吗大于200且小于400,则认为容器健康。例:
apiVersion:v1
kind: Pod
metadata:
name: pod-with-healthcheck
spec:
containers:
- name: nginx
image: nginx
livenessProbe:
httpGet:
path:/_status/healthz
port: 80
initianDelaySeconds:30
timeoutSeconds:1
对于每种探针方式,都须要设置initialDelaySeconds和timeoutSeconds两个参数,它们含义以下:
- initialDelaySeconds:启动容器后首次监控检查的等待时间,单位秒
- timeouSeconds:健康检查发送请求后等待响应的超时时间,单位秒。当发生超时就被认为容器没法提供服务无,该容器将被重启
九.玩转Pod调度
在Kubernetes系统中,Pod在大部分场景下都只是容器的载体而已,一般须要经过RC、Deployment、DaemonSet、Job等对象来完成Pod的调度和自动控制功能。
9.1 RC、Deployment:全自动调度
RC的主要功能之一就是自动部署容器应用的多份副本,以及持续监控副本的数量,在集群内始终维护用户指定的副本数量。
在调度策略上,除了使用系统内置的调度算法选择合适的Node进行调度,也能够在Pod的定义中使用NodeSelector或NodeAffinity来指定知足条件的Node进行调度。
1)NodeSelector:定向调度
Kubernetes Master上的scheduler服务(kube-Scheduler进程)负责实现Pod的调度,整个过程经过一系列复杂的算法,最终为每一个Pod计算出一个最佳的目标节点,一般咱们没法知道Pod最终会被调度到哪一个节点上。实际状况中,咱们须要将Pod调度到咱们指定的节点上,能够经过Node的标签和pod的nodeSelector属性相匹配来达到目的。
(1)首先经过kubectl label命令给目标Node打上标签
kubectl label nodes <node-name> <label-key>=<label-value>
例:#kubectllabel nodes k8s-node-1 zonenorth
(2)而后在Pod定义中加上nodeSelector的设置,例:
apiVersion:v1
kind: Pod
metadata:
name: redis-master
label:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: redis-master
images: kubeguide/redis-master
ports:
- containerPort: 6379
nodeSelector:
zone: north
运行kubectl create -f命令建立Pod,scheduler就会将该Pod调度到拥有zone=north标签的Node上。
若是多个Node拥有该标签,则会根据调度算法在该组Node上选一个可用的进行Pod调度。
须要注意的是:若是集群中没有拥有该标签的Node,则这个Pod也没法被成功调度。
2)NodeAffinity:亲和性调度
该调度策略是未来替换NodeSelector的新一代调度策略。因为NodeSelector经过Node的Label进行精确匹配,全部NodeAffinity增长了In、NotIn、Exists、DoesNotexist、Gt、Lt等操做符来选择Node。调度侧露更加灵活。
9.2 DaemonSet:特定场景调度
DaemonSet用于管理集群中每一个Node上仅运行一份Pod的副本实例,如图:
这种用法适合一些有下列需求的应用:
- 在每一个Node上运行个以GlusterFS存储或者ceph存储的daemon进程
- 在每一个Node上运行一个日志采集程序,例如fluentd或者logstach
- 在每一个Node上运行一个健康程序,采集Node的性能数据。
DaemonSet的Pod调度策略相似于RC,除了使用系统内置的算法在每台Node上进行调度,也能够在Pod的定义中使用NodeSelector或NodeAffinity来指定知足条件的Node范围来进行调度。
十.Pod的扩容和缩容
在实际生产环境中,咱们常常遇到某个服务须要扩容的场景,也有可能由于资源精确须要缩减资源而须要减小服务实例数量,此时咱们能够Kubernetes中RC提供scale机制来完成这些工做。
以redis-slave RC为例,已定义的最初副本数量为2,经过kubectl scale命令能够将Pod副本数量从新调整
#kubectl scale rc redis-slave --replicas=3
ReplicationController"redis-slave" scaled
#kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-slave-1sf23 1/1Running 0 1h
redis-slave-54wfk 1/1Running 0 1h
redis-slave-3da5y 1/1Running 0 1h
除了能够手工经过kubectl scale命令完成Pod的扩容和缩容操做之外,新版本新增长了Horizontal Podautoscaler(HPA)的控制器,用于实现基于CPU使用路进行启动Pod扩容缩容的功能。该控制器基于Mastger的kube-controller-manager服务启动参数 --horizontal-pod-autoscler-sync-period定义的时长(默认30秒),周期性监控目标Pod的Cpu使用率并在知足条件时对ReplicationController或Deployment中的Pod副本数量进行调整,以符合用户定义的平均Pod Cpu使用率,Pod Cpu使用率来源于heapster组件,因此需预先安装好heapster。
十一.Pod的滚动升级
当集群中的某个服务须要升级时,咱们须要中止目前与该服务相关的全部Pod,而后从新拉取镜像并启动。若是集群规模较大,因服务所有中止后升级的方式将致使长时间的服务不可用。由此,Kubernetes提供了rolling-update(滚动升级)功能来解决该问题。
滚动升级经过执行kubectl rolling-update命令一键完成,该命令建立一个新的RC,而后自动控制旧版本的Pod数量逐渐减小到0,同时新的RC中的Pod副本数量从0逐步增长到目标值,最终实现Pod的升级。须要注意的是,系统要求新的RC须要与旧的RC在相同的Namespace内,即不能把别人的资产转到到自家名下。
例:将redis-master从1.0版本升级到2.0:
apiVersion: v1
kind: replicationController
metadata:
name: redis-master-v2
labels:
name: redis-master
Version: v2
spec:
replicas: 1
selector:
name: redis-master
Version: v2
template:
labels:
name: redis-master
Version: v2
spec:
containers:
- name: master
images: kubeguide/redis-master:2.0
ports:
- containerPort: 6379
须要注意的点:
(1)RC的name不能与旧的RC名字相同
(2)在sele中应至少有一个label与旧的RC的label不一样,以标识为新的RC。本例中新增了一个名为version的label与旧的RC区分
运行kubectl rolling-update来完成Pod的滚动升级:
#kubectl rolling-update redis-master -f redis-master-controller-v2.yaml
另外一种方法就是不使用配置文件,直接用kubectl rolling-update加上--image参数指定新版镜像名来完成Pod的滚动升级
#kubectl rolling-update redis-master --image=redis-master:2.0
与使用配置文件的方式不一样的是,执行的结果是旧的RC被删除,新的RC仍然使用就的RC的名字。
若是在更新过程总发现配置有误,则用户能够中断更新操做,并经过执行kubectl rolling-update-rollback完成Pod版本的回滚。
问题
一、在建立pod的时候发现报了这个错误:
Error from server (ServerTimeout): error when creating "busybox.yaml": No API token found for
service account "default", retry after the token is automatically created and added to the service
account
分析
根据报错信息能够初步看出是service account没有设置API token引发的。
解决
解决方式有两种:
方式一:禁用ServiceAccount
编辑/etc/kubenetes/apiserver:
将如下这行中的ServiceAccount删除便可
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
改成:
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
这种方式比较粗暴,可能会遇到必需要用ServiceAccount的状况。
方式二:配置ServiceAccount
一、首先生成密钥:
openssl genrsa -out /etc/kubernetes/serviceaccount.key 2048
二、编辑/etc/kubenetes/apiserver
添加如下内容:
KUBE_API_ARGS="--service_account_key_file=/etc/kubernetes/serviceaccount.key"
三、再编辑/etc/kubernetes/controller-manager
添加如下内容:
KUBE_CONTROLLER_MANAGER_ARGS="--service_account_private_key_file=/etc/kubernetes/serviceaccount.key"
最后不管是哪一种解决方式都须要再重启kubernetes服务: systemctl restart etcd kube-apiserver kube-controller-manager kube-scheduler