资源-控制器
SharedInformer 作为控制器的代理,可以缓解入口压力
一,控制器作用
管理pod对象
使用标签与pod关联
控制器实现了pod运维,例如滚动更新、伸缩副本管理,维护pod状态等
二,控制器类型
2.1,Deployment:无状态应用部署
功能:管理pod和replicas
应用场景: 网站、API、微服务
2.2,DaemonSet:确保所有Node运行同一个pod
功能:在每一个node上运行一个pod
新加入的node也同样会自动运行一个pod
应用场景:网络插件(kube-proxy、calico)、其他agent应用
2.3,StatefulSet:有状态应用部署
结合headless service使用
功能特性:
- 稳定的、唯一的网络标识符
- 稳定的、持久化的存储
- 有序的、优雅的部署和伸缩
- 有序的、优雅的删除和终止
- 有序的、自动滚动更新
Headless Service 特性:
未配置 ClusterIP,不通过 SVC 分配的 VIP 负载均衡访问 Pod
直接以 DNS 记录方式解析到 Pod 对应的IP地址
应用场景:
- 稳定的持久化存储,即 Pod 重新调度后,还能够访问到相同的持久化数据,基于PVC来实现
- 稳定的网络标识,即 Pod 重新调度后其 PodName 和 HostName 不变,基于 Headless Service (即没有Cluster IP的Service)来实现
- 有序部署、有序扩展,即Pod是有序的,在部署和扩展时,要按照定义的顺序依次进行 (即从 0 到N - 1, 在下一个Pod 运行前,所有 Pod 必须是 Running 和 Ready 状态),基于 Init Containers 来实现
- 有序收缩、有序删除(即从 N-1 到 0)
2.4,Job:一次性任务
功能:一次性执行
应用场景:离线数据处理
2.5,CronJob:定时任务
功能:定时任务
应用场景:通知、备份类任务
2.6,pod
Kubernetes应用程序的最小化部署和管理单元。
可以是一个容器也可以是多个容器组成
2.7,service
2.8,replicaset
维持一组pod副本的运行,保证运行数量
监听pod运行状态,pod增加或者故障减少时维持副本数量
2.9,endpoints
代理集群外部服务到kubernetes内部访问
三,控制器yaml应用
3.1,Deployment
Deployment进行pod升级时,采用滚动更新方式
更新策略:
-
maxSurge:滚动更新过程中最大pod副本数,确保在更新时启动的pod数量比期望(replicas)pod数量最大多出25%
-
maxUnavailable:滚动更新过程中最大不可用pod副本数,确保在更新时最大25%pod数量不可用,即确保75%pod是可用状态
yaml例:
apiVersion: apps/v1 ##版本
kind: Deployment ##类型
metadata: ##Deployment的元数据
name: httpd ##Deployment的名字
labels: ##标签
app: httpd ##标签app=httpd
spec: ##Pod的信息
replicas: 3 ##Pod的副本数
selector: ##标签选择器
matchLabels: ##查找匹配的标签
app: httpd ##app=httpd
template: ##Pod的模板信息,根据模板信息来创建Pod
metadata: ##Pod的元数据
labels: ##Pod的标签
app: httpd ##标签app=httpd
spec: ##容器的信息
containers: ##容器
- name: httpd ##容器名
image: httpd ##容器所需的镜像
ports: ##端口
- containerPort: 80 ##容器暴露的端口
3.2,DaemonSet
yaml 例:
apiVersion: apps/v1
kind: DaemonSet
...
3.3,StatefulSet
管理策略:spec.podManagementPolicy
- OrderedReady:按顺序性就绪,默认
- Parallel:并行就绪/终止
更新策略:.spec.updateStrategy.type
- OnDelete: 只有手动删除旧的 Pod 才会创建新的 Pod
- RollingUpdate:自动删除旧的 Pod 并创建新的Pod,如果更新发生了错误,这次“滚动更新”就会停止
dns域名命名规则
myservice.mynamespace.svc.cluster.local
解析podIP地址
nslookup -query=A demodb-0.demodb
demodb-0.demodb.default.svc.cluster.local
域名解析
kubectl create deployment dnsutils --image=tutum/dnsutils -- sleep infinity
#kubectl exec dnsutils-77ccd77fb6-czfd2 -- nslookup redis-cluster-master.default.svc.cluster.local
kubectl exec dnsutils-77ccd77fb6-czfd2 -- nslookup redis-cluster-master
yaml例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
serviceName: mysql
replicas: 3
template:
metadata:
labels:
app: mysql
spec:
initContainers:
- name: init-mysql
image: mysql:5.7
command:
- bash
- "-c"
- |
set -ex
# Generate mysql server-id from pod ordinal index.
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1 #过滤第一个pod名mysql,其中hostname表示容器内pod名字
ordinal=${BASH_REMATCH[1]} #表示拿取第一个数字0
echo [mysqld] > /mnt/conf.d/server-id.cnf #创建一个server-id.cnf 文件,往里面写mysqld表示这个文件里的配置针对server生效
# Add an offset to avoid reserved server-id=0 value.
echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf #往server-id.conf 追加一条server-id=100+上面取到的数字
# Copy appropriate conf.d files from config-map to emptyDir. 拷贝conf.d 文件到空卷
if [[ $ordinal -eq 0 ]]; then #如果取到的数字为0
cp /mnt/config-map/master.cnf /mnt/conf.d/ #拷贝master
else
cp /mnt/config-map/slave.cnf /mnt/conf.d/ #否则拷贝slave
fi
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
- name: config-map
mountPath: /mnt/config-map
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "1"
ports:
- name: mysql
containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql #挂在点里创建一个子目录
- name: conf
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: 500m
memory: 1Gi
livenessProbe:
exec:
command: ["mysqladmin", "ping"]
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
# Check we can execute queries over TCP (skip-networking is off).
command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
initialDelaySeconds: 5
periodSeconds: 2
timeoutSeconds: 1
volumes:
- name: conf
emptyDir: {}
- name: config-map
configMap:
name: mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "managed-nfs-storage"
resources:
requests:
storage: 5Gi
3.4,Job
重启策略使用Never
例:
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
3.5,Crontab
每次运行会启动一个pod,但是停止后不占用资源
重启策略使用OnFailure
例:
apiVersion: batch/v1
kind: CronJob
metadata:
name: crontab
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: crontab
image: busybox
args:
- /bin/sh
- -c
- date; echo hello world
restartPolicy: OnFailure
查看kubectl get CronJob
删除kubectl delete CronJob crontab
6,endpoints
apiVersion: v1
kind: Endpoints
metadata:
name: mysql
subsets:
- addresses:
- ip: 10.98.4.200
ports:
- port: 3306
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: 10.0.0.200
ports:
- port: 3306
targetPort: 3306
protocol: TCP
3.6 pod
3.7,Service控制器
service存在的意义
- 服务发现:防止pod失联,找到提供同一个服务的pod
- 负载均衡:定义一组pod的访问策略
pod和service的关系
- 资源类型中的标签选择器和pod模板中的标签是一致的,service通过它们关联一组pod
- service为一组pod提供负载均衡能力
headless service
- Headless服务就是一组Pod组成的只供集群内访问(没有ClusterIP)的Service,一般结合StatefulSet用于部署有状态应用的场景。
- 在某些场景中,无需对外提供访问能力,只需要在内部找到自己想找到的Pod资源时,可以通过Headless Service来实现。
- 这种不具有ClusterIP的Service资源就是Headless Service,该 Service 的请求流量不需要
kube-proxy 处理,也不会有负载均衡和路由规则,而是由ClusterDNS的域名解析机制直接去访问固定的Pod资源。
3.7.1,service三种常用类型
- ClusterIP:集群内部使用(pod)
默认,只分配一个稳定的IP地址,即VIP,只能在集群内部访问
yaml使用:
spec:
type:ClusterIP
可访问对象:
集群中其他应用
集群中其他应用的外部机器
-
NodePort:对外暴露应用(浏览器)
一个端口只能一个服务使用,如果指定端口需要提前规划
只支持四层负载均衡
在每个节点启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址
访问地址:任意nodeIP:NodePort
默认NodePort端口范围:30000-32767
yaml例:
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30009
selector:
app: web
- LoadBalancer:对外暴露应用,适用公有云
与NodePort相似,在每个节点上启用一个端口来暴露服务。除此之外,kubernetes会请求底层云平台(例如阿里云、腾讯云,AWS等)上的负载均衡器,将每个Node的服务([NodeIP]:[NodePort])作为后端添加进去
3.7.2,service代理模式实现方式
- iptables 默认使用此方式
特点:
灵活、功能强大
规则遍历匹配和更新,呈线性时延
适合小规模流量
- ipvs
特点:
工作在内核态,有更好性能
调度算法丰富:rr、wrr、lc、wlc、ip hash等
适合大规模流量
修改方式
-
kubeadm集群
kubectl edit cm kube-proxy -n kube-system mode: "ipvs"/mod
-
二进制集群
vim k8s根目录/cfg/kube-proxy-config.yml
kind: KubeProxyConfiguration
mode: "ipvs"
3.7.3,Service DNS名称
CoreDNS:一个DNS服务器,kubernetes默认采用,以pod部署在集群中
CoreDNS服务监视kubernetes API,为每一个Service创建DNS记录用于域名解析
3.7.4,service负载均衡策略
- k8s service 负载均衡策略
在Kubernetes中,Service资源是用来提供一种方式,使得一组Pod能够被统一的方式访问。Service定义了如何访问它的Pod,通过分配一个集群内独一无二的IP地址。Service的负载均衡功能是基于内核的虚拟服务器(IPVS)或者iptables来实现的。 Kubernetes Service的负载均衡策略主要有以下几种:
轮询(RoundRobin):每个新的连接由轮询方式分配到下一个Pod
会话保持(SessionAffinity):来自同一个客户端的请求被定向到同一个Pod。
最少连接(LeastConnections):负载均衡器选择连接数最少的Pod。
请求最少(Shortest Expected Delay):负载均衡器选择预期等待时间最短的Pod。
随机(Random):负载均衡器随机选择一个Pod。
默认情况下,Kubernetes使用的是轮询策略。在Service的配置中设置spec.sessionAffinity为ClientIP,以启用会话保持。
会话保持策略:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
sessionAffinity: ClientIP
type: ClusterIP
在这个配置中,sessionAffinity: ClientIP 表示启用了基于客户端IP的会话保持。type: ClusterIP 表示Service类型为集群内部的服务,它会分配一个集群内部的IP地址。
请注意,Kubernetes默认的负载均衡器实现不支持最少连接或请求最少的策略。这些高级功能可能需要第三方的负载均衡器或Ingress控制器来实现。
3.8,endpoints
apiVersion: v1
kind: Endpoints
metadata:
name: mysql
subsets:
- addresses:
- ip: 10.98.4.200
ports:
- port: 3306
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: 10.0.0.200
ports:
- port: 3306
targetPort: 3306
protocol: TCP