1 Pod
很少在 Kubernetes 中直接创建一个Pod,甚至是单实例(Singleton)的 Pod。 这是因为 Pod 被设计成了相对临时性的、用后即抛的一次性实体,不支持高可用。一般使用工作负载资源来创建和管理多个 Pod。 资源的控制器能够处理副本的管理、上线,并在 Pod 失效时提供自愈能力。
能够管理一个或者多个 Pod 的工作负载资源有:
- Deployment
- ReplicaSet
- DaemonSet
- ReplicationController
1.1 Pod中的内容
Pod 类似于共享namesapce、cgroup、文件系统卷的一组 Docker 容器。创建Pod时,除了会创建1个或多个工作容器外,还会额外在Pod中创建Pod容器,Pod容器用于实现k8s的各种功能。
1.2 Pod模板
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 这里是 Pod 模版
spec:
containers:
- name: hello
image: busybox
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
1.3 Pod基本操作
1.3.1 创建
kubectl create 或 apply -f XXX.yaml
1.3.2 查询
查询基础信息
kubectl get pods|pod名字
kubectl get pods -o wide
查询详细信息
kubectl describe pod pod名字
查询Pod的标签
kubectl describe pod pod名字 --show-labels
1.3.3 删除
kubectl delete pod pod名字
kubectl delete pod --all
1.3.4 更新
kubectl apply -f XXX.yaml
2 ReplicationController
ReplicationController 确保在任何时候都有特定数量的 Pod 副本处于运行状态。 换句话说,ReplicationController 确保一个 Pod 或一组同类的 Pod 总是可用的。
RC会根据spec.selector将当前已经运行的Pod加入RC,当 Pod 数量过多时,ReplicationController 会终止多余的 Pod。当 Pod 数量太少时,ReplicationController 将会启动新的 Pod。
ReplicationController在新版本中被ReplicaSet所取代,通常使用Deployment来部署ReplicaSet,而不是直接使用ReplicaSet。
2.1 RC模板
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
#参数解释
spec.replicas: 副本数
spec.selector: 选择器,根据选择的条件筛选Pod的labels,将符合的Pod加入RC
spec.template: Pod的模板
spec.template.metadata: Pod的元数据
spec.template.spec: Pod的具体属性信息
2.2 RC基本操作
2.2.1 创建
kubectl create 或 apply -f XXX.yaml
2.2.2 查询
查询基础信息
kubectl get rc
kubectl get rc -o wide
查询详细信息
kubectl describe rc rc名字
2.2.3 删除
kubectl delete rc rc名字
kubectl delete rc --all
2.2.4 调整副本数
kubectl scale rc rc名字 --replicas=num
3 Service
3.1 Service概述
问题:
Pod创建完成后,如何访问Pod呢?直接访问Pod会有如下几个问题:
- Pod会随时被Deployment这样的控制器删除重建,那访问Pod的结果就会变得不可预知。
- Pod的IP地址是在Pod启动后才被分配,在启动前并不知道Pod的IP地址。
- 应用往往都是由多个运行相同镜像的一组Pod组成,逐个访问Pod也变得不现实
解决方法:
Kubernetes中的Service对象就是用来解决上述Pod访问问题的。Service有一个固定IP地址Cluster IP,Service将访问它的流量转发给Pod,具体转发给哪些Pod通过Label来选择,而且Service可以给这些Pod做负载均衡。
3.2 K8s中的3种IP地址
3.2.1 Node IP
Node物理节点的IP地址
3.2.2 Cluster IP
Service的IP地址,此为虚拟IP地址。外部网络无法ping通,只有kubernetes集群内部访问使用。
- Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址
- Cluster IP无法被ping,他没有一个“实体网络对象”来响应
- Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。
- 在不同Service下的pod节点在集群间相互访问可以通过Cluster IP
3.2.3 Pod IP
每个Pod的IP地址
- 同Service下的pod可以直接根据PodIP相互通信
- 不同Service下的pod在集群间pod通信要借助于 cluster ip
- pod和集群外通信,要借助于node ip
3.2.4 3种IP的访问关系
Cluster地址和pod地址在不同网段,Cluster地址为虚拟地址,不配在pod上或主机上,外部访问时,先到Node节点网络(所有Node开放同一个端口号),再转到service网络,最后代理给pod网络。
3.3 Service的类型
Service的类型决定了如何向外暴露Service
3.3.1 ClusterIP
通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认的 ServiceType。
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx-clusterip
spec:
ports:
- name: service0
port: 8080 # 访问Service的端口
protocol: TCP # 访问Service的协议,支持TCP和UDP
targetPort: 80 # Service访问目标容器的端口,此端口与容器中运行的应用强相关,如本例中nginx镜像默认使用80端口
selector: # 标签选择器,Service通过标签选择Pod,将访问Service的流量转发给Pod,此处选择带有 app:nginx 标签的Pod
app: nginx
type: ClusterIP # Service的类型,ClusterIP表示在集群内访问
clusterIP: IP Address # 指定Service使用的ClusterIP,默认为随机分配
3.3.2 NodePort
通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 NodePort 服务会路由到自动创建的 ClusterIP 服务。 通过请求 <Node节点 IP>:<节点端口>,你可以从集群的外部访问一个 NodePort 服务。
NodePort的端口范围默认是30000-32767,可以修改
/etc/kubernetes/manifests/kube-apiserver.yaml文件从而修改端口范围。
NodePort类型的Service例子:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: MyApp
ports:
- port: 80
targetPort: 80
nodePort: 30007
参数解释:
spec.ports[*].port: Cluster IP的端口
spec.ports[*].targetPort: Pod IP的端口
spec.ports[*].nodePort: Node IP的端口
spec.selector: 选择器,根据Pod的labels,将Pod加入到Service
3.3.3 LoadBalancer
3.3.4 ExternalName
3.4 负载均衡模式
Service默认的负载均衡模式是RR轮询模式,可以通过修改spec.sessionAffinity为ClientIP来实现源地址会话保持。可以设置会话保持的超时时间(默认时间是10800s),设置spec.sessionAffinityConfig.clientIP.timeoutSeconds 的值。
apiVersion: v1
kind: Service
metadata:
...
spec:
...
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10
type: NodePort
4 Deployments
4.1 Deployments概述
Deployment 管理 ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能,
- 创建 Deployment 以将 ReplicaSet 上线。 ReplicaSet 在后台创建 Pods。 检查 ReplicaSet 的上线状态,查看其是否成功。
- 通过更新 Deployment 的 PodTemplateSpec,声明 Pod 的新状态。 新的 ReplicaSet 会被创建,Deployment 以受控速率将 Pod 从旧 ReplicaSet 迁移到新 ReplicaSet。 每个新的 ReplicaSet 都会更新 Deployment 的修订版本。
- 如果 Deployment 的当前状态不稳定,回滚到较早的 Deployment 版本。 每次回滚都会更新 Deployment 的修订版本。
- 扩大 Deployment 规模以承担更多负载。
- 暂停 Deployment以应用对 PodTemplateSpec 所作的多项修改, 然后恢复其执行以启动新的上线版本。
- 使用 Deployment 状态来判定上线过程是否出现停滞。
- 清理较旧的不再需要的 ReplicaSet。
4.2 Deployments模板
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
#参数解释
spec.replicas: 副本数
spec.selector: 选择器,根据选择的条件筛选Pod的labels,将符合的Pod加入deployment
spec.template: Pod的模板
spec.template.metadata: Pod的元数据
spec.template.spec: Pod的具体属性信息
4.3 Deployments创建流程
首先根据文件创建deployment,加入--record参数来记录历史,方便在回滚时查看针对每个 Deployment 修订版本所执行过的命令。
kubectl apply -f nginx/nginx-deployment.yaml --record
Deployment会创建ReplicaSet,ReplicaSet负责启动Pods。ReplicaSet 的名称始终被格式化为[Deployment名称]-[随机字符串]。 其中的随机字符串是使用 pod-template-hash 作为种子随机生成的。
Pod-template-hash 标签
Deployment 控制器将pod-template-hash标签添加到 Deployment 所创建或收留的每个ReplicaSet 。
此标签可确保 Deployment 的子 ReplicaSets 不重叠。 标签是通过对 ReplicaSet 的PodTemplate进行哈希处理。 所生成的哈希值被添加到ReplicaSet 选择算符、Pod 模板标签,并存在于在 ReplicaSet 可能拥有的任何现有 Pod 中。![]()
4.4 Deployments升级流程
仅当 Deployment Pod 模板(即
.spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
Deployment 控制器每次注意到新的 Deployment 时,都会创建一个 ReplicaSet 以启动所需的 Pods。 如果更新了 Deployment,则控制标签匹配 .spec.selector 但模板不匹配 .spec.template 的 Pods 的现有 ReplicaSet 被缩容。最终,新的 ReplicaSet 缩放为 .spec.replicas 个副本, 所有旧 ReplicaSets 缩放为 0 个副本。
当 Deployment 正在上线时被更新,Deployment 会针对更新创建一个新的 ReplicaSet 并开始对其扩容,之前正在被扩容的 ReplicaSet 会被翻转,添加到旧 ReplicaSets 列表 并开始缩容。
例如,假定你在创建一个 Deployment 以生成 nginx:1.14.2 的 5 个副本,但接下来 更新 Deployment 以创建 5 个 nginx:1.16.1 的副本,而此时只有 3 个nginx:1.14.2 副本已创建。在这种情况下,Deployment 会立即开始杀死 3 个 nginx:1.14.2 Pods, 并开始创建 nginx:1.16.1 Pods。它不会等待 nginx:1.14.2 的 5 个副本都创建完成 后才开始执行变更动作。
升级操作,两种方式:
- 直接使用命令行更新镜像版本
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
- 使用edit在线编辑
kubectl edit deployment.v1.apps/nginx-deployment
Deployment可以通过
maxSurge和maxUnavailable两个参数控制升级过程中同时重新创建Pod的比例,这在很多时候是非常有用,配置如下所示。
spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
- maxSurge:与Deployment中spec.replicas相比,可以有多少个Pod存在,默认值是25%,比如spec.replicas为 4,那升级过程中就不能超过5个Pod存在,即按1个的步伐升级,实际升级过程中会换算成数字,且换算会向上取整。这个值也可以直接设置成数字。
- maxUnavailable:与Deployment中spec.replicas相比,可以有多少个Pod失效,也就是删除的比例,默认值是25%,比如spec.replicas为4,那升级过程中就至少有3个Pod存在,即删除Pod的步伐是1。同样这个值也可以设置成数字。
4.5 Deployments回滚流程
Deployment之所以能如此容易的做到回滚,是因为Deployment是通过ReplicaSet控制Pod的,升级后之前ReplicaSet都一直存在,Deployment回滚做的就是使用之前的ReplicaSet再次把Pod创建出来。Deployment中保存ReplicaSet的数量可以使用revisionHistoryLimit参数限制,默认值为10。
查看Deployment 修订历史
kubectl rollout history deployment nginx-deployment
输出
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=nginx/nginx-deployment.yaml --record=true
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
查看第n次的修订历史
kubectl rollout history deployment nginx-deployment --revision=n
输出
deployment.apps/nginx-deployment with revision #2
Pod Template:
Labels: app=nginx
pod-template-hash=559d658b74
Annotations: kubernetes.io/change-cause: kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
回滚到之前的修订版本
kubectl rollout undo deployment nginx-deployment --to-revision=1
回滚后,Deployment 修订历史发生变化,revision 1变为revision 3
[root@centos7-wht ~]$ kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
3 kubectl apply --filename=nginx/nginx-deployment.yaml --record=true
4.6 Deployments缩放
kubectl scale deployment deployment名字 --replicas=个数
4.7 暂停、恢复 Deployment
可以在触发一个或多个更新之前暂停 Deployment,然后再恢复其执行。 这样做使得你能够在暂停和恢复执行之间应用多个修补程序,而不会触发不必要的上线操作。
暂停
kubectl rollout pause deployment nginx-deployment
恢复
kubectl rollout resume deployment nginx-deployment
处于暂停状态的 Deployment不能回滚,除非先恢复其执行状态。
4.8 Deployments进度监视
kubectl rollout status deployment deploy名字
5 Liveness Probe
通过检测容器响应是否正常来决定是否重启Pod,Kubernetes支持如下三种探测机制:
- HTTP GET:向容器发送HTTP GET请求,如果Probe收到2xx或3xx,说明容器是健康的。
- TCP Socket:尝试与容器指定端口建立TCP连接,如果连接成功建立,说明容器是健康的。
- Exec:Probe执行容器中的命令并检查命令退出的状态码,如果状态码为
0则说明容器是健康的。
Liveness Probe在containers字段中定义
5.1 HTTP GET
为Deployment中的Pod配置Liveness Probe,Probe往容器的80端口发送HTTP GET请求,如果请求不成功,Kubernetes会重启容器。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
livenessProbe: # liveness probe部分
httpGet: # HTTP GET定义
path: /
port: 80
ports:
- containerPort: 80
5.2 TCP Socket
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
livenessProbe: # liveness probe部分
tcpSocket:
port: 80
ports:
- containerPort: 80
5.3 Exec
在容器中执行cat /tmp/healthy命令,如果成功执行并返回0,则说明容器是健康的。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
livenessProbe: # liveness probe
exec: # Exec定义
command:
- cat
- /tmp/healthy
ports:
- containerPort: 80














网友评论