一个计算机技术爱好者与学习者

0%

好好学K8S:使用client-go在K8S集群发布项目

1. 问题简述

怎样在K8S集群中发布一个新的项目?怎样判断一个项目是发布成功了还是失败了?怎样访问一个项目?怎样实现灰度发布?怎样实现发布过程中的并发度控制、暂停、继续、取消?怎样实现回滚?

本文中,会努力寻求这些问题的答案。

参考文档:

2. 准备镜像

首先准备两个镜像,分别是nginx:v1.0和nginx:v2.0。

1、启动并进入容器

1
2
docker run --name nginx -d -p 80:80 voidking/nginx:latest
docker exec -it nginx /bin/bash

有些小伙伴会有疑问,为什么不使用docker run启动并进入容器?
docker run -it voidking/nginx:latest /bin/bash

因为如果使用这种方式进入容器,修改内容后commit镜像,那么镜像无法正常启动。

docker ps -a --no-trunc
使用该命令可以看到,voidking/nginx:latest的默认启动命令为:
nginx -g 'daemon off;'
而commit后的镜像,默认启动命令被修改为:
/bin/bash
看到这里就知道,因为自定义的启动命令覆盖掉了原有的启动命令,所以镜像无法正常启动。为什么会覆盖呢?因为CMD指令允许用户指定容器的默认的执行命令,此命令会在容器启动且docker run没有指定其他命令时运行。当docker run指定其他命令时,则会覆盖默认的执行命令。更多内容参考Dockerfile RUN,CMD,ENTRYPOINT命令区别

2、修改index.html

1
2
3
4
cd /usr/share/nginx/html
sed 's/nginx!/nginx!v1.0/' index.html
sed -i 's/nginx!/nginx!v1.0/' index.html
cat index.html

3、commit/push镜像

1
2
3
4
docker ps -l
docker commit 6efcd878d0d1 voidking/nginx:v1.0
docker login
docker push voidking/nginx:v1.0

3. kubectl

在使用go-client之前,我们先来学习一下使用kubectl怎样发布项目、获取状态、访问项目、更新项目。

3.1. 发布项目

以发布一个nginx项目为例。

1、准备deployment yaml文件nginx.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: voidking/nginx:v1.0
ports:
- containerPort: 80
imagePullPolicy: Always

2、发布项目

1
kubectl apply -f nginx.yaml

3.2. 获取状态

1
2
3
4
5
6
kubectl get deployments nginx
kubectl get deployments nginx -o json
kubectl get pods -l app=nginx
kubectl get pods -l app=nginx -o json
kubectl describe deployments nginx
kubectl describe pods -l app=nginx

根据获取到的信息,判断发布成功还是失败。

3.3. 访问项目

1、准备service yaml文件nginx-svc.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: NodePort
#type: LoadBalancer

2、查看服务IP和端口

1
kubectl get svc nginx

3、访问项目

1
minikube service nginx

执行上面的命令后,会自动打开浏览器。
或者使用curl命令访问:curl http://192.168.99.100:32329/

4、从容器内部访问项目(三种方式)

1
2
3
4
5
6
7
kubectl get pods
kubectl exec -it hello-node-6747d458b6-d757m /bin/bash
# wget -O- 10.97.151.28
curl 10.97.151.28
curl nginx.default
env | grep NGINX
curl $NGINX_SERVICE_HOST:$NGINX_SERVICE_PORT

如果env命令没有显示出nginx service信息,那么可以重建pod:

1
kubectl get pod hello-node-6747d458b6-d757m -n default -o yaml | kubectl replace --force -f -

PS:使用kubectl进入容器的方法

1
2
3
kubectl get pods
kubectl exec -it pod-name /bin/bash
kubectl exec -it pod-name -c container-name /bin/bash

3.4. 更新发布

1、修改nginx.yaml中的配置,升级镜像为voidking/nginx:2.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: voidking/nginx:v2.0
ports:
- containerPort: 80
imagePullPolicy: Always

2、更新发布

1
kubectl apply -f nginx.yaml

3、访问项目

1
curl http://192.168.99.100:32329/

4. client-go

《使用client-go操作K8S》一文中,配置好了k8s-client-go项目,可以使用这个项目对k8s集群进行一些基本操作。在此基础上,本节会实现一些更高阶的操作。

4.1. 判断发布状态

根据deployment和pod的状态,怎样判断一次发布成功还是失败?首先,要知道deployment和pod都有哪些状态。

1、通过kubectl命令获取发布数据

1
2
3
4
kubectl get deployments hello-node -o json
kubectl get deployments nginx -o json
kubectl get pods -l app=hello-node -o json
kubectl get pods -l app=nginx -o json

2、获取到的发布数据
发布成功的json数据:hello-node.json
发布失败的json数据:nginx.json

3、具体可用状态有哪些

1
2
3
4
5
6
7
8
9
10
11
12
13
# deployment部分
deployment.generation
deployment.spec.replicas
deployment.status.observedGeneration
deployment.status.replicas
deployment.status.readyReplicas/unavailableReplicas
deployment.status.updatedReplicas
deployment.status.conditions[*].type{Available,Progressing} && deployment.status.conditions[*].status{True,False}

# pod部分
pod.status.phase{Pending,Running}
pod.status.conditions[*].type{Initialized,Ready,ContainersReady,PodScheduled} && pod.status.conditions[*].status{True,False}
pod.status.containerStatuses[*].state.{waiting,running}

4、判断条件组合
参考k8s-client-go/common/deployment.go文件的GetDeploymentStatus函数。

4.2. 灰度发布

常见的发布方案包括蓝绿发布、滚动发布和灰度发布(金丝雀发布),更多内容参考微服务部署:蓝绿部署、滚动部署、灰度发布、金丝雀发布
参考Spinnaker第四节-对接k8s基于 Spinnaker 的 K8S 灰度发布灰度发布/蓝绿发布,使用Ingress,可以很好地实现灰度发布。但是,在没有Ingress的情况下,该怎样实现灰度发布?

最简单的方案是发布一个新的deployment,把service的流量分流到新的deployment
,测试通过后删除老的deployment,流量就全部到了新的deployment。具体实现参考k8s-client-go/common/deploy.go文件的GrayDeploy和UpdateDeploy函数。

但是,如果只允许维护一个deployment,该怎么处理?创建灰度的deployment,测试通过后删除灰度的deployment,然后正常更新原有的deployment。具体实现参考k8s-client-go/common/deploy.go文件的GrayDeploy2和UpdateDeploy2函数。

5. 后记

并发度控制、暂停、继续、取消、回滚等等功能,未完待续。。。