• Pod的扩容和缩容

  在实际生产系统中,我们经常会遇到某个服务需要扩容的场景,也可能遇到由于资源紧张或者负载降低而需要减少服务实例数量的场景。此时我们可以利用RCscale机制来完成这些工作。

  以《从一个例子开始认识Kubernetes》中myweb的RC为例,已定义的最初副本数量为2,通过kubectl scale 命令可以将其控制的Pod数量从2变为3,也可以从3变成1。

1 [root@localhost ~]# kubectl get po
 2 NAME          READY     STATUS    RESTARTS   AGE
 3 mysql-px9th   1/1       Running   0          1d
 4 myweb-fxq9s   1/1       Running   0          1d
 5 myweb-tt5sd   1/1       Running   0          1d
 6 [root@localhost ~]# kubectl scale rc myweb --replicas=3
 7 replicationcontroller "myweb" scaled
 8 [root@localhost ~]# kubectl get po
 9 NAME          READY     STATUS    RESTARTS   AGE
10 mysql-px9th   1/1       Running   0          1d
11 myweb-fxq9s   1/1       Running   0          1d
12 myweb-rkg9m   1/1       Running   0          33s
13 myweb-tt5sd   1/1       Running   0          1d
14 [root@localhost ~]# kubectl scale rc myweb --replicas=1
15 replicationcontroller "myweb" scaled
16 [root@localhost ~]# kubectl get po
17 NAME          READY     STATUS    RESTARTS   AGE
18 mysql-px9th   1/1       Running   0          1d
19 myweb-tt5sd   1/1       Running   0          1d

    Horizontal Pod Autoscaler(HPA)

  对于Kubernetes中的Pod集群来说,HPA可以实现很多自动化功能,比如当Pod中业务负载上升的时候,可以创建新的Pod来保证业务系统稳定运行,当Pod中业务负载下降的时候,可以销毁Pod来提高资源利用率。HPA控制器默认每隔30秒就会运行一次。 如果要修改间隔时间,可以设置horizontal-pod-autoscaler-sync-period参数。HPA的操作对象是RC、RS或Deployment对应的Pod 根据观察到的CPU等实际使用量与用户的期望值进行比对,做出是否需要增减实例数量的决策。

  在Kubernetes v1.1中首次引入了hpa特性。hpa第一个版本基于观察到的CPU利用率,后续版本支持基于内存使用。 在Kubernetes 1.6中引入了一个新的API自定义指标API,它允许HPA访问任意指标。 Kubernetes 1.7引入了聚合层,允许第三方应用程序通过注册为API附加组件来扩展Kubernetes API。自定义指标API以及聚合层使得像Prometheus这样的监控系统可以向HPA控制器公开特定于应用程序的指标。

 直接通过kubectl autoscale直接创建

1 ]# docker pull siriuszg/hpa-example 
2 ]# kubectl get pod,deployment,svc
3 ]# kubectl run php-apache --image=siriuszg/hpa-example --requests=cpu=50m --expose --port=80 
4 ]# kubectl autoscale deployment php-apache --cpu-percent=10 --min=1 --max=3
通过yaml文件创建
 创建RC
1 apiVersion: v1
 2 kind: ReplicationController
 3 metadata:
 4   name: php-apache
 5 spec:
 6   replicas: 1
 7   template:
 8     metadata:
 9       name: php-apache
10       labels:
11         app: php-apache
12     spec:
13       containers:
14       - name: php-apache
15         image: gcr.io/google_containers/hpa-example:latest
16         imagePullPolicy: IfNotPresent
17         resources:
18           requests:
19             cpu: 200m
20         ports:
21         - containerPort: 80

创建SVC

1 apiVersion: v1
 2 kind: Service
 3 metadata:
 4   name: php-apache
 5   labels:
 6     k8s-app: php-apache
 7 spec:
 8   ports:
 9     # The port that this service should serve on.
10     - port: 80
11   # Label keys and values that must match in order to receive traffic for this service.
12   selector:
13     app: php-apache

创建HPA

1 apiVersion: autoscaling/v1
 2 kind: HorizontalPodAutoscaler
 3 metadata:
 4   name: php-apache
 5   namespace: default
 6 spec:
 7   scaleTargetRef:
 8     apiVersion: v1
 9     kind: ReplicationController
10     name: php-apache
11   minReplicas: 1
12   maxReplicas: 10
13   targetCPUUtilizationPercentage: 50

使用kubectl create创建yaml文件

1 ]# kubectl create -f php-rc.yaml
2 ]# kubectl create -f php-svc.yaml
3 ]# kubectl create -f hpa-example.yaml

进行压力测试

1 kubectl run -i --tty load-generator --image=busybox:latest /bin/sh #进入容器后执行一下命令
2 while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

压测几分钟后查看hpa状态,如果cpu压力超过了设置的阈值,可以停止压测。
查看hpa状态已经超过了阈值,此时查看pod,pod的数量已经增加了。
当停止压力测试之后,过一段时间,Pod数量又会恢复到1。

  • Pod的滚动升级

  当集群中的某个服务需要升级时,我们需要停止目前与该服务相关的所有Pod,然后重新拉取镜像并启动。如果集群规模比较大,则这样操作就比较困难,Kubernetes提供了rolling-update功能来解决这个困难。

  滚动升级通过执行命令kubectl rolling-update命令一键完成,改命令会创建一个新的RC,然后控制旧的RC中的Pod数量逐渐减少到0,同时新的RC中的Pod数量逐渐增加到目标值,最终实现Pod升级。(注:新旧RC需在同一个Namespace中)

1 示例:
2 // 更新frontend-v1的pod到frontend-v2
3 $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
4 // 更新frontend的pods,不更改replication controller的名称
5 $ kubectl rolling-update frontend --image=image:v2

例如运行一个1.7.9版本的nginx

1 apiVersion: v1
 2 kind: ReplicationController
 3 metadata:
 4   name: my-nginx
 5 spec:
 6   replicas: 5
 7   template:
 8     metadata:
 9       labels:
10         app: nginx
11     spec:
12       containers:
13       - name: nginx
14         image: nginx:1.7.9
15         ports:
16         - containerPort: 80

更新到1.9.1版本

1 ]# kubectl rolling-update my-nginx --image=nginx:1.9.1

更新过程如图:

Operator通过扩展Kubernetes定义Custom Controller kubernetes扩容缩容_php

  如果遇到问题可以使用--rollback 回滚。

  如果你不仅仅是需要更新镜像,(例如,更新命令参数,环境变量等),你可以创建一个新的replication controller配置文件,包含一个新的名称和不同的标签值,例如:

1 apiVersion: v1
 2 kind: ReplicationController
 3 metadata:
 4   name: my-nginx-v4
 5 spec:
 6   replicas: 5
 7   selector:
 8     app: nginx
 9     deployment: v4
10   template:
11     metadata:
12       labels:
13         app: nginx
14         deployment: v4
15     spec:
16       containers:
17       - name: nginx
18         image: nginx:1.9.2
19         args: ["nginx", "-T"]
20         ports:
21         - containerPort: 80
1 ]# kubectl rolling-update my-nginx -f ./nginx-rc.yaml

注:

如果更新过程中,达到超时时长timeout后还没更新完成,则更新会失败。这时,一些pod会属于新的replication controller,一些会属于旧的。

如果更新失败,可以尝试使用同样的命令来继续更新过程。

在尝试更新之前如果需要回滚到之前的状态,可在之前的命令后面添加--rollback=true参数,这将回退所有的更改。