云原生技术与应用-Kubernetes高级调度01
一,初始化容器initContainerInitcontainer 是 Kubernetes 的初始化容器(也可称之为 Init 容器),它是一种特殊的容器,在Pod 内的应用容器启动之前运行,可以包括一些应用镜像中不存在的使用工具和安装脚本,用以在程序启动时进行初始化,比如创建文件、修改内核参数、等待依赖程序启动等。
·
一,初始化容器initContainer
Initcontainer 是 Kubernetes 的初始化容器(也可称之为 Init 容器),它是一种特殊的容器,在Pod 内的应用容器启动之前运行,可以包括一些应用镜像中不存在的使用工具和安装脚本,用以在程序启动时进行初始化,比如创建文件、修改内核参数、等待依赖程序启动等。
每个 Pod 中可以包含多个容器,同时 Pod 也可以有一个或多个先于应用程序启动的 Init 容器,在 Pod定义中和 container 同级,按顺序逐个执行,当所有的 Init 容器运行完成时,Kubernetes 才会启动 Pod内的普通容器。
1,示例1——延迟指定时间后启动
编写yaml文件并指定初始化容器需要休眠15秒后启动
[root@k8s-master ~]# vim init01.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: initc01
name: initc01
spec:
terminationGracePeriodSeconds: 0
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: n1
resources: {}
initContainers:
- name: initc01
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 15"]
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
创建该pod
[root@k8s-master ~]# ku create -f init01.yml
pod/initc01 created
查看pod启动状态
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 0/1 Init:0/1 0 3s
等待15秒后查看pod状态
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
initc01 1/1 Running 0 26s
2,示例2——使用初始化容器最该内核参数
在容器里修改内核参数,实际上修改的就是物理机的内核参数,为了安全性,一般不允许在容器里修改内核参数。
编写一个pod,指定修改swappiness的内核参数
[root@k8s-master ~]# vim init02.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: initc02
name: initc02
spec:
terminationGracePeriodSeconds: 0
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: n1
resources: {}
initContainers:
- name: initc02
image: alpine
imagePullPolicy: IfNotPresent
command: ["sh","-c","/sbin/sysctl -w vm.swappiness=0"] ##swappiness默认值为30,修改为0
securityContext:
privileged: true
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
创建该pod
[root@k8s-master ~]# ku create -f init02.yml
pod/initc02 created
查看pod运行在那个node上
[root@k8s-master ~]# ku get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
initc02 1/1 Running 0 24s 10.244.169.133 k8s-node2 <none> <none>
##可以看到运行在node2节点上
在node2节点查看swappines参数是否修改
[root@k8s-node2 ~]# cat /proc/sys/vm/swappiness
0 ##修改已经生效
3,示例3——依赖服务启动
有时某些服务需要依赖其他组件才能启动,比如后端应用需要数据库启动之后,应用才能正常启动,此时需要检测数据库实例是否正常,等待数据库可以正常使用时,在启动后端应用,此时可以使用初始化容器进行控制。
创建pod,该 Pod 内要依赖两个条件才能启动,一个是利用 busybox 容器检测 redis-service 服务是否生成第二个是检测 mysql-server 服务是否生成。
[root@k8s-master ~]# vim myapp.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
initContainers:
- name: init-redis
image: busybox:1.28
command: ['sh', '-c', 'until nslookup redis-service; do echo waiting for nginx01; sleep 2; done;']
- name: init-mysql
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mysql-service; do echo waiting for nginx02; sleep 2; done;’]
## command: ['sh', '-c', 'until nslookup redis-service; do echo waiting for nginx01; sleep 2; done;']使用until语句检测容器是否已经启动,如果指定容器未启动则会一直循环,反之会停止
创建容器并观察状态
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
nginx 0/1 Init:0/2 0 2s
##容器状态处于未启动的状态,需要两个依赖服务才会启动
创建第一个依赖的service
[root@k8s-master ~]# vim redis-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: redis
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis:5.0
imagePullPolicy: IfNotPresent
name: redis
---
apiVersion: v1
kind: Service
metadata:
labels:
app: redis
name: redis-service
spec:
ports:
- port: 6379
protocol: TCP
targetPort: 6379
selector:
创建的二个依赖的service
[root@k8s-master ~]# vim mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mysql
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- env:
- name: MYSQL_ROOT_PASSWORD
value: 'moonfdd'
image: 'mysql:8.0'
imagePullPolicy: IfNotPresent
name: mysql
volumeMounts:
- mountPath: /var/lib/mysql
name: volv
volumes:
- hostPath:
path: /root/k8s/moonfdd/mysql/var/lib/mysql
type: DirectoryOrCreate
name: volv
---
apiVersion: v1
kind: Service
metadata:
labels:
app: mysql
name: mysql-service
spec:
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mysql
type: NodePort
创建两个服务
[root@k8s-master ~]# ku create -f mysql-deployment.yaml
[root@k8s-master ~]# ku create -f redis-deployment.yaml
查看service
[root@k8s-master ~]# ku get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 127d
mysql-service NodePort 10.103.206.118 <none> 3306:32199/TCP 9s
redis-service NodePort 10.107.25.58 <none> 6379:31854/TCP 3s
再次查看nginx服务状态
[root@k8s-master ~]# ku get pod
NAME READY STATUS RESTARTS AGE
mysql-7f5d669b6c-6727r 1/1 Running 0 2m28s
nginx 1/1 Running 0 5m
redis-56bcf55554-rhqnr 1/1 Running 0 2m22s
二,临时容器Ephemeral Containers
临时容器与其他容器的不同之处在于,临时容器是被临时添加到 Pod 上,用于在线调试应用的,他永远不会自动重启,因此不适用与构建应用程序,临时容器的声明和普通容器类似,但是临时容器没有端口配置,因此不能使用像 ports、livenessprobe、readnessProbe、resources 这样的字段,当然,临时容器只是用来调试程序的,它的状态不会影响其他正常容器,所以它并不需要这些字段配置。
临时容器使用 API 中一种特殊的 Ephemeral containers 处理器进行创建,而不是直接添加到pod.spec 字段,因此无法使用 kubectl edit 来添加临时容器,与常规容器一样,将临时容器添加到 Pod后,将不能更改或删除临时容器,但是当添加了临时容器的 Pod 重启后,临时容器就会被销毁
因为临时容器是为了调试程序而设计的,所以在添加临时容器时,最好使用一个包含所有常用工具的镜像进行创建。当业务容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 不可用时,临时容器对于交互故障排査和在线 Debug 很有用。尤其是在使用像不包含任何 shel1 和其他工具的 destroless 镜像作为基础镜像时,虽然可以减少攻击面和漏洞,但对于问题的排査会变得尤为棘手,此时临时容器就可以发挥很大的作用,带来诸多便利性。
1,配置临时容器
创建一个nginx的资源清单
[root@k8s-master ~]# vim pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
name: tomcat-test
namespace: default
labels:
app: tomcat
spec:
containers:
- name: tomcat-java
ports:
- containerPort: 8080
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
创建pod
[root@k8s-master ~]# ku create -f pod-tomcat.yaml
pod/tomcat-test created
为pod创建临时容器
##进入到临时容器,可以看到nginx的进程
[root@k8s-master images]# ku debug -it tomcat-test --image=busybox:1.28 --target=tomcat-java
Targeting container "tomcat-java". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-47zbr.
/ # ps
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx -g daemon off;
7 101 0:00 nginx: worker process
8 root 0:00 sh
14 root 0:00 ps
查看tomcat-test这个pod是否已经又临时容器
[root@k8s-master images]# ku describe pods tomcat-test
......../省略部分内容
Ephemeral Containers: ##此部分就是该pod的临时容器
debugger-zj4lw:
Container ID:
Image: budybox:1.28
Image ID:
Port: <none>
Host Port: <none>
State: Waiting
Reason: ErrImagePull
Ready: False
Restart Count: 0
Environment: <none>
Mounts: <none>
......../省略部分内容
三,自动扩容缩容HPA
在集群安装的过程中,我们可以安装一个叫 Metrics Server 的组件,该组件在集群中负责采集 Pod和 Node 的度量值指标,比如 Pod 的 CPU、内存使用率和节点的内存、CPU 使用率,而且安装的 Dashboard可以展示 CPU、内存信息也是依靠 Metrics server 的。当然,该组件不仅仅是用来展示数据的,还可以使用 Metrics Server 提供的数据结合 Kubernetes 的 HPA 功能实现 Pod 的自动扩缩容。
1,什么是HPA
HPA(Horizontal Pod Autoscaler,水平 Pod 自动伸缩器)可以根据观察到的 CPU、内存使用率或自定义度量标准来自动扩展或缩容 Pod 的数量。注意 HPA 不适用于无法缩放的对象,比如 DaemonSet,HPA 控制器会定期调整 RC或 Deployment 的副本数,以使观察到的平均 CPU 利用率与用户指定的目标相匹配。
2,HPA的工作原理
HPA 根据观察到的 CPU、内存使用率或自定义度量标准来自动扩展或缩容 Pod 的数量。
HPA 控制器会定期调整 RC(Replication controller)或 Deployment 的副本数,以使观察到的平均 CPU 利用率(或其他度量标准)与用户指定的目标相匹配。
HPA 需要 Metrics Server 获取度量指标,Metrics Server 负责采集 Pod 和 Node 的度量值指标,如 CPU、内存使用率等。
3,HPA的工作流程
配置 HPA:使用 kubectl autoscale 命令为Deployment、Replicaset 或 statefulset 等资源创建 HPA 对象,并指定目标 CPU 利用率、最小副本数和最大副本数。
度量指标采集:Metrics server 定期采集 Pod 和 Node 的度量值指标,并将这些数据提供给 HPA控制器。
伸缩决策:HPA 控制器根据当前 Pod 的度量指标和目标利用率进行比较,如果当前利用率高于目标利用率,则增加 Pod 副本数;如果当前利用率低于目标利用率,则减少 Pod 副本数(在最小副本数和最大副本数之间调整)
Pod 伸缩:Kubernetes 根据 HPA 控制器的决策自动调整 Pod 的副本数,以实现自动扩缩容。
4,HPA的应用场景
应对流量波动:在 web服务中,流量可能会随时间变化而波动。HPA可以根据流量变化自动调整Pod 副本数,以确保服务的稳定性和响应速度。
资源优化:通过自动扩缩容,HPA可以在保证服务质量的同时最大化资源利用率,降低运营成本。
5,配置web实现服务器的自动扩容缩容
编写一个使用deployment启动一个nginx服务
[root@k8s-master ~]# vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server
labels:
name: nginx-server
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
resources:
requests:
cpu: 10m
image: nginx:1.7.9
ports:
- name: nginx
containerPort: 80
创建该pod
[root@k8s-master ~]# ku create -f nginx-deployment.yaml
deployment.apps/nginx-server created
配置该pod的service
[root@k8s-master ~]# ku expose deployment nginx-server --port=80
service/nginx-server exposed
创建HPA
[root@k8s-master ~]# ku autoscale deployment nginx-server --cpu-percent=10 --min=1 --max=10
查看HPA状态
[root@k8s-master ~]# ku get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 0%/10% 1 10 2 118s##为发送任何请求,所有当前cpu使用为0%
查看该service的IP地址
[root@k8s-master ~]# ku get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-server ClusterIP 10.110.68.83 <none> 80/TCP 2m25s
打开一个新的终端进行压力测试
[root@k8s-node2 images]# while true;do wget -q -O- http://10.110.68.83 >/dev/null;
再次HPA查看使用情况
[root@k8s-master ~]# ku get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server Deployment/nginx-server 35%/10% 1 10 10 4m21s
##可以看到已经CPU已经升高
查看pod副本是否增加
[root@k8s-master ~]# ku get pod ##由于我们设置了10个所以增加到10个就会停止
NAME READY STATUS RESTARTS AGE
nginx-server-6ddcfd4c8f-5bvls 1/1 Running 0 2m34s
nginx-server-6ddcfd4c8f-9b8xh 1/1 Running 0 2m34s
nginx-server-6ddcfd4c8f-b76wd 1/1 Running 0 2m19s
nginx-server-6ddcfd4c8f-ffmjx 1/1 Running 0 2m49s
nginx-server-6ddcfd4c8f-ghddp 1/1 Running 0 2m49s
nginx-server-6ddcfd4c8f-kz6gr 1/1 Running 0 2m34s
nginx-server-6ddcfd4c8f-qg255 1/1 Running 0 2m19s
nginx-server-6ddcfd4c8f-tlsdt 1/1 Running 0 6m25s
nginx-server-6ddcfd4c8f-xr7x5 1/1 Running 0 2m34s
nginx-server-6ddcfd4c8f-zxmfl 1/1 Running 0 6m25s
##关闭测试会回到最小值为1
更多推荐


所有评论(0)