第7章:深入理解常用控制器
7.1 Pod与controller的关系
-
controllers:在集群上管理和运行容器的对象。有时也称为工作负载(workload)
-
通过label-selector相关联,如下图所示。
-
Pod通过控制器实现应用的运维,如伸缩,滚动升级等
7.2 无状态应用部署控制器 Deployment
Deployment功能:
-
部署无状态应用(无状态应用简单来讲,就是Pod可以漂移任意节点,而不用考虑数据和IP变化)
-
管理Pod和ReplicaSet(副本数量管理控制器)
-
具有上线部署、副本设定、滚动升级、回滚等功能
-
提供声明式更新,例如只更新一个新的Image
应用场景:Web服务,微服务
下图是Deployment 标准YAML,通过标签与Pod关联。
使用YAML部署一个java应用:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3 # 设置3个副本
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: lizhenliang/java-demo
name: java
将这个java应用暴露到集群外部访问:
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80 # 集群内容访问应用端口
protocol: TCP
targetPort: 8080 # 容器镜像端口
nodePort: 30008 # 对外暴露的端口
selector:
app: web
type: NodePort
查看资源:
kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/web-7f9c858899-dcqwb 1/1 Running 0 18s
pod/web-7f9c858899-q26bj 1/1 Running 0 18s
pod/web-7f9c858899-wg287 1/1 Running 0 48s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 5m55s
service/web NodePort 10.1.157.27 <none> 80:30008/TCP 48s
浏览器输入:http://NodeIP:30008 即可访问到该应用。
升级项目,即更新最新镜像版本,这里换一个nginx镜像为例:
kubectl set image deployment/web nginx=nginx:1.15
kubectl rollout status deployment/web # 查看升级状态
如果该版本发布失败想回滚到上一个版本可以执行:
kubectl rollout undo deployment/web # 回滚最新版本
也可以回滚到指定发布记录:
kubectl rollout history deployment/web # 查看发布记录
kubectl rollout undo deployment/web --revision=2 # 回滚指定版本
扩容/缩容:
kubectl scale deployment nginx-deployment --replicas=5
--replicas设置比现在值大就是扩容,反之就是缩容。
kubectl set image 会触发滚动更新,即分批升级Pod。
滚动更新原理其实很简单,利用新旧两个replicaset,例如副本是3个,首先Scale Up增加新RS副本数量为1,准备就绪后,Scale Down减少旧RS副本数量为2,以此类推,逐渐替代,最终旧RS副本数量为0,新RS副本数量为3,完成本次更新。这个过程可通过kubectl describe deployment web看到。
7.3 守护进程控制器 DaemonSet
DaemonSet功能:
-
在每一个Node上运行一个Pod
-
新加入的Node也同样会自动运行一个Pod
应用场景:Agent,例如监控采集工具,日志采集工具
7.4 批处理 Job & CronJob
Job:一次性执行
应用场景:离线数据处理,视频解码等业务
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never # 作业失败后会不再尝试创建新的Pod
backoffLimit: 4 # .spec.backoffLimit字段限制重试次数。默认情况下,这个字段默认值是6。
上述示例中将π计算到2000个位置并将其打印出来。完成大约需要10秒。
查看任务:
kubectl get pods,job
CronJob:定时任务,像Linux的Crontab一样。
应用场景:通知,备份
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure # 作业失败并返回状态码非0时,尝试创建新的Pod运行任务
上述示例中将每分钟打印一次Hello。
查看任务:
kubectl get pods,cronjob
第8章:深入理解Service
8.1 Service存在的意义
-
防止Pod失联(服务发现)依靠pod的ip通讯不可靠, service把一组pod关联起来
-
定义一组Pod的访问策略(负载均衡)为一组pod提供负载均衡
8.2 Pod与Service的关系
-
通过label-selector相关联
-
通过Service实现Pod的负载均衡( TCP/UDP 4层)
8.2 Service三种常用类型
-
ClusterIP:集群内部使用,默认**,**分配一个稳定的IP地址,即VIP,只能在集群内部访问(同Namespace内的Pod)。
-
NodePort:对外暴露应用。在每个节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。访问地址::
-
LoadBalancer:对外暴露应用,适用公有云、与NodePort类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes会请求底层云平台上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去, NodePort的增强版,主要用于公有云,对接公有云的负载均衡。
[root@k8s-master ~]# kubectl delete $(kubectl get pods -o name) "批量删除pod资源"
[root@k8s-master ~]# kubectl delete $(kubectl get job -o name) "批量删除job"
[root@k8s-master ~]# kubectl delete $(kubectl get cronjob -o name)
[root@k8s-master ~]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: nginxweb
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
[root@k8s-master ~]# kubectl apply -f deployment.yaml
deployment.apps/nginxweb created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginxweb-5dcb957ccc-54b92 1/1 Running 0 61s
nginxweb-5dcb957ccc-dkcvq 1/1 Running 0 61s
nginxweb-5dcb957ccc-qlst5 1/1 Running 0 61s
[root@k8s-master ~]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 192.168.100.110:6443 45h
tomcat <none> 18h
nginxweb 10.244.0.172:80,10.244.0.173:80,10.244.1.20:80 7h37m
[root@k8s-master ~]# curl 10.244.0.173
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
.....
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 45h
tomcat NodePort 10.0.0.26 <none> 8080:32120/TCP 18h
web NodePort 10.0.0.46 <none> 80:30000/TCP 7h38m
[root@k8s-master ~]# curl 10.0.0.46
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[root@k8s-node1 ~]# curl 10.0.0.46
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
[root@k8s-node2 data]# curl 10.0.0.46
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
//集群内部用service 的clouderip 10.0.0.46进行内部通讯
kubectl expose deployment web --port=80 --terget=8080 --type-port=NodePort -name=web --dry-run -o yaml > service.yaml
--port=80 service管理的端口
--terget=8080 容器里跑的服务的端口
kubectl get ep 查看service关联的pod
[root@k8s-master ~]# vim service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: apacheweb
name: apacheweb
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30008 "指定对外暴露的端口"
selector:
app: apacheweb
type: NodePort
[root@k8s-master ~]# kubectl apply -f service.yaml
service/apacheweb created
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apacheweb NodePort 10.0.0.144 <none> 80:30008/TCP 8s
[root@k8s-node2 ~]# netstat -ntap | grep 30008
tcp 0 0 0.0.0.0:30008 0.0.0.0:* LISTEN 24827/kube-proxy
[root@k8s-node1 ~]# netstat -ntap | grep 30008
tcp 0 0 0.0.0.0:30008 0.0.0.0:* LISTEN 24845/kube-proxy
[root@k8s-master ~]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: apacheweb "与service的selecter标签一致"
name: apache
spec:
replicas: 3
selector:
matchLabels:
app: apacheweb "与service的selecter标签一致"
strategy: {}
template:
metadata:
labels:
app: apacheweb "与service的selecter标签一致"
spec:
containers:
- image: httpd
name: httpd
resources: {}
[root@k8s-master ~]# kubectl apply -f deployment.yaml
deployment.apps/apache created
[root@k8s-master ~]# vim deployment.yaml
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
apache-774c5dd967-7ftpz 1/1 Running 0 14s
apache-774c5dd967-dqmvv 1/1 Running 0 14s
apache-774c5dd967-zqh55 1/1 Running 0 14s
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apacheweb NodePort 10.0.0.144 <none> 80:30008/TCP 5m32s
[root@k8s-master ~]# kubectl get ep "查看service与pod的对应关系"
NAME ENDPOINTS AGE
apacheweb 10.244.0.188:80,10.244.0.189:80,10.244.1.28:80 5m43s
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
apache-774c5dd967-7ftpz 1/1 Running 0 50s 10.244.1.28 k8s-node1 <none> <none>
apache-774c5dd967-dqmvv 1/1 Running 0 50s 10.244.0.188 k8s-node2 <none> <none>
apache-774c5dd967-zqh55 1/1 Running 0 50s 10.244.0.189 k8s-node2 <none> <none>
8.3 Service代理模式
Iptables:
- 灵活,功能强大
- 默认的转发规则
- 规则遍历匹配和更新,呈线性时延
IPVS:
-
工作在内核态,有更好的性能
-
调度算法丰富:rr,wrr,lc,wlc,ip hash…
-
查看是否启用: lsmod|grep ip_vs
启用ip_vs: modprobe ip_vs
//iptables示例
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apacheweb NodePort 10.0.0.144 <none> 80:30008/TCP 3h8m
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 2d2h
tomweb NodePort 10.0.0.171 <none> 8080:30191/TCP 3h33m
web NodePort 10.0.0.59 <none> 80:32689/TCP 3h41m
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
apache-774c5dd967-7ftpz 1/1 Running 0 3h3m
apache-774c5dd967-dqmvv 1/1 Running 0 3h3m
apache-774c5dd967-zqh55 1/1 Running 0 3h3m
tomcat-779675bcd7-mn64n 1/1 Running 0 22s
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
apache-774c5dd967-7ftpz 1/1 Running 0 3h3m 10.244.1.28 k8s-node1 <none> <none>
apache-774c5dd967-dqmvv 1/1 Running 0 3h3m 10.244.0.188 k8s-node2 <none> <none>
apache-774c5dd967-zqh55 1/1 Running 0 3h3m 10.244.0.189 k8s-node2 <non