Kubernetes 技术分享
Summary: Author: 张亚飞 | Read Time: 8 minute read | Published: 2020-10-12
Filed under
—
Categories:
MarkDown
—
Tags:
Tag,
Kubernetes: 容器调度与编排管理平台
Kubernetes
被设计作为构建组件和工具的生态系统平台,提供了很多的功能,以便更轻松地部署、扩展和管理应用程序,有较强的自动化能力.它可以简化应用程序的工作流,加快开发速度.
传统开发运维常见问题
各服务器部署环境不一致,开发环境测试通过后上线运行报错.系统环境需要单独维护和升级,增加运维的工作量;
微服务架构的优点
- 单体式架构
各业务使用相同的技术栈,难以快速迭代应用新技术; 通常采用分层架构模式,按不同技术维度分层,例如数据持久化层、业务逻辑层、UI表示层; 对任何功能的修改都要整个系统部署维护,运维成本高;(牵一发而动全身) 系统出现一个问题,整个系统受影响; 系统应用负载高,难以分段水平扩展;
- 微服务架构
相对于单体式架构,微服务更轻量,它将复杂的应用拆分到不同的独立自治的服务单元,服务与服务之间采用松耦合的形式交互,有很好的扩展性和复用性;
微服务平台
Kubernetes
是谷歌开源的容器调度与编排管理系统,正迅速成为在分布式系统中部署工作负载的事实标准;
主要功能包括:
- 跨机器和跨地区的集群调度
- 集群内负载均衡和服务发现
- 适合灰度发布
- 基于容器的应用部署、维护和滚动升级
- 支持弹性伸缩
- 故障隔离
- 服务熔断
- 健康检查
其它容器管理框架Swarm
和Rancher
,Rancher
定位k8s
上层可以管理k8s
集群的编排工具
开放接口
Kubernetes
作为云原生应用的的基础调度平台,相当于云原生的操作系统,为了便于系统的扩展,Kubernetes
中开放的以下接口,可以分别对接不同的后端,来实现自己的业务逻辑:
- CRI(Container Runtime Interface):容器运行时接口,提供计算资源
- CNI(Container Network Interface):容器网络接口,提供网络资源
- CSI(Container Storage Interface):容器存储接口,提供存储资源
核心组件
- kube-apiserver
模块之间的数据交互和通信的枢纽:提供集群管理的 REST API 接口,提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;
- kube-scheduler
负责资源的调度,它监听 kube-apiserver
,按照预定的调度策略将 Pod
调度到相应的机器上;
- kube-controller-manager
是 Kubernetes 的大脑,它通过 apiserver
监控整个集群的状态,负责维护集群的状态,比如故障检测、自动扩展、滚动更新等,并确保集群处于预期的工作状态;
- Kubelet
每个 Node
节点上都运行一个 Kubelet
服务进程,在 API Server
上注册所在Node节点的信息,定期向 Master
节点汇报该节点的资源使用情况,
接收并执行 Master
发来的指令,管理 Pod
及 Pod
中的容器,并监控节点和容器的资源.
- kube-proxy
每台机器上都运行一个 kube-proxy
服务,它监听 API server
中 service
和 endpoint
的变化情况,并通过 iptables
等来为服务配置负载均衡.
负责为 Service
提供 cluster
内部的服务发现和负载均衡;
- kube-dns
提供集群中的 dns
服务,可以解析 service
到 cluster ip
,实现服务发现
- etcd
分部式数据库,保存了整个集群的配置及状态;
常用组件
- Namespace
通过命名空间,为集群中的部分资源或不同的环境关联鉴权,配置资源限额,有助于不同的项目、团队共享 Kubernetes
集群.
- Pod
Kubernetes 使用 Pod
来管理容器,每个 Pod
可以包含一个或多个紧密关联的容器.
- Deployment
Deployment
通过 ReplicaSet
管理创建 Pod
,可以实现指定 Pod
副本数量,滚动更新,扩容 Pod
- DaemonSet
在每个节点都需要运行的 Pod
,例如 filebeat
日志采集服务
- StatefulSet
有状态服务,部署、扩展、更新、删除都要有顺序,每个 Pod 都有自己存储和状态
- Service
集群内负载均衡与服务发现
- Ingress
定义反向代理规则,用来规定 HTTP/S
请求应该被转发到哪个 Service
上,比如根据请求中不同的 Host
和 url
路径让请求落到不同的 Service
上,暴露集群内部 Service
服务
- Job
一次性任务
- CronJob
定时任务
- PersistentVolume
持久化存储卷,作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息
- PersistentVolumeClaim
持久化卷声明
- StorageClass
使用模板动态创建 PV
和 PVC
,适用于有状态服务 StatefulSet
- Label
Label
是识别 Kubernetes
对象的标签,作为服务资源绑定
其它
- Secret
- LoadBalancer
- ConfigMap
常用命令及操作
可以通过官方提供的工具 kubectl
对集群资源进行管理
kubectl describe namespaces
kubectl get node,pod
kubectl logs pod test-xxx
kubectl create -f xxx.yaml
使用命令创建一个 Deployment
kubectl create deployment --image nginx:1.10 test-web-deployment
也可以使用声明式的配置,以下等价
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-web-deployment
spec:
selector:
matchLabels:
app: test-web-deployment
replicas: 1
template:
metadata:
labels:
app: test-web-deployment
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
创建 Service
服务发现
kubectl expose deployment test-web-deployment --port=80 --type=LoadBalancer
以下配置等价
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: LoadBalancer
ports:
- name: http
targetPort: 80
protocol: TCP
selector:
app: test-web-deployment
测试
http HEAD http://ms.iirii.com:30066
调整副本集数量
kubectl scale deployment --replicas 2 test-web-deployment
修改容器镜像
kubectl set image deployment/test-web-deployment nginx=nginx:1.11
删除 Deployment
kubectl delete deployment test-web-deployment
功能演示
- 创建节点并加入集群
cargo run tcs create -i t.cs.11
cargo run tcs drop -i t.cs.11
- 创建
Deployment
服务容器
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-web-deployment
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: test-web-deployment
replicas: 10
template:
metadata:
labels:
app: test-web-deployment
spec:
containers:
- name: test-web
image: nginx:1.10
ports:
- containerPort: 80
- 创建服务
apiVersion: v1
kind: Service
metadata:
name: test-web-svc
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 80
nodePort: 30044
selector:
app: test-web-deployment
测试
curl -s -I http://ms.iirii.com:30044
- 滚动更新
升级 nginx
版本号
kubectl apply -f k8s.run.yaml --record
循环验证
while sleep 0.2;do curl -s -I http://ms.iirii.com:30044 | grep server;done
- 回滚
查看历史版本
kubectl rollout history deployment test-web-deployment
执行回滚
kubectl rollout undo deployment test-web-deployment
kubectl rollout undo deployment test-web-deployment --to-revision=1
循环验证
while sleep 0.2;do curl -s -I http://ms.iirii.com:30044 | grep server;done
- 水平伸缩
HPA
创建 HorizontalPodAutoscaler
对象或使用 kubectl autoscale
子命令都可以配置 HPA
控制器,以管理工作负载
创建一个服务
- Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-scale-deployment
spec:
selector:
matchLabels:
app: test-scale-deployment
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 1
template:
metadata:
labels:
app: test-scale-deployment
spec:
containers:
- name: test-scale
image: registry.ioros.com/coam/test.web:0.0.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 50Mi
- Service
apiVersion: v1
kind: Service
metadata:
name: test-scale-svc
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 80
nodePort: 30077
selector:
app: test-scale-deployment
- HorizontalPodAutoscaler
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: test-scale-hpa
namespace: default
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: test-scale-deployment
targetCPUUtilizationPercentage: 30
监控 Pod
资源占用
watch -n 1 kubectl top pod
watch -n 1 kubectl get hpa
模拟并发请求
while true; do wget -q -O- http://ms.iirii.com:30077; done
- 健康检查
- 执行命令检查
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
labels:
test: liveness
spec:
containers:
- name: liveness
image: registry.ioros.com/docker.io/busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- echo Exec-Started:$(date '+%d/%m/%Y %H:%M:%S'); touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
我们使用存活探针 livenessProbe
每隔 3 秒执行一次上面的 cat /tmp/healthy
命令
httpGet
请求检测
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
labels:
test: liveness
spec:
containers:
- name: liveness
image: registry.ioros.com/docker.io/busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- echo Exec-Started:$(date '+%d/%m/%Y %H:%M:%S'); touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
httpGet:
host: w.nocs.cn
path: /pi.php
port: 443
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 3
我们使用存活探针 livenessProbe
每隔 3 秒请求一次 https://w.nocs.cn:443/pi.php
服务网格 Istio
- 开启自动注入
kubectl label namespace default istio-injection=enabled
准备环境
部署两个版本的应用 flask(v1,v2)
istio/flask.istio.yaml
apiVersion: v1
kind: Service
metadata:
name: flaskapp
labels:
app: flaskapp
spec:
selector:
app: flaskapp
ports:
- name: http
port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: flaskapp-v1
spec:
selector:
matchLabels:
app: flaskapp
version: v1
replicas: 1
template:
metadata:
labels:
app: flaskapp
version: v1
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: flaskapp
image: registry.ioros.com/docker.io/dustise/flaskapp
imagePullPolicy: IfNotPresent
env:
- name: version
value: v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: flaskapp-v2
spec:
selector:
matchLabels:
app: flaskapp
version: v2
replicas: 1
template:
metadata:
labels:
app: flaskapp
version: v2
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: flaskapp
image: registry.ioros.com/docker.io/dustise/flaskapp
imagePullPolicy: IfNotPresent
env:
- name: version
value: v2
部署客户端应用 sleep
istio/sleep.istio.yaml
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
spec:
selector:
app: sleep
ports:
- name: ssh
port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
selector:
matchLabels:
app: sleep
replicas: 1
template:
metadata:
labels:
app: sleep
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: sleep
image: registry.ioros.com/docker.io/dustise/sleep
imagePullPolicy: IfNotPresent
测试,v1,v2
交替出现
sleep
for i in `seq 100`;do http --body http://flaskapp/env/version;done
- 蓝绿发布
两套环境,蓝色验证,绿色线上
设置目标规则,根据应用 label: version
分别设置2个子集 v1,v2
flaskapp-destinationrule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: flaskapp
spec:
host: flaskapp.default.svc.cluster.local
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
默认路由: 定义一个 VirtualService
对象,负责接管 flaskapp
流量,并将请求发送到 v2
的子集
flaskapp-virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: flaskapp
spec:
hosts:
- flaskapp.default.svc.cluster.local
http:
- route:
- destination:
host: flaskapp.default.svc.cluster.local
subset: v1
测试,仅 v1
版本
for i in `seq 100`;do http --body http://flaskapp/env/version;done
- 流量拆分与迁移
修改权重比率
flaskapp-virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: flaskapp
spec:
hosts:
- flaskapp.default.svc.cluster.local
http:
- route:
- destination:
host: flaskapp.default.svc.cluster.local
subset: v1
weight: 70
- destination:
host: flaskapp.default.svc.cluster.local
subset: v2
weight: 30
验证
for i in `seq 100`;do http --body http://flaskapp/env/version;done
for i in `seq 100`;do http --body http://flaskapp/env/version;done | awk -F"v1" '{print NF-1}'
- 金丝雀部署(灰度发布)
可以添加 match
根据 header
、scheme
等信息分流
flaskapp-virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: flaskapp
spec:
hosts:
- flaskapp.default.svc.cluster.local
http:
- match:
- headers:
lab:
exact: canary
route:
- destination:
host: flaskapp.default.svc.cluster.local
subset: v2
- route:
- destination:
host: flaskapp.default.svc.cluster.local
subset: v1
测试
http --body http://flaskapp.default.svc.cluster.local/env/version
http --body http://flaskapp.default.svc.cluster.local/env/version lab:canary
http --body url=http://flaskapp.default.svc.cluster.local/env/version lab:other
- 流量复制
flaskapp-virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: flaskapp
spec:
hosts:
- flaskapp.default.svc.cluster.local
http:
- match:
- headers:
lab:
exact: canary
route:
- destination:
host: flaskapp.default.svc.cluster.local
subset: v2
mirror:
host: flaskapp.default.svc.cluster.local
subset: v1
- route:
- destination:
host: flaskapp.default.svc.cluster.local
subset: v1
测试
kube logs flaskapp-v1
kube logs flaskapp-v2
http --body http://flaskapp/env/version
- 服务熔断
部署测试环境
httpbin.yaml
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
selector:
matchLabels:
app: httpbin
version: v1
replicas: 1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
containers:
- image: registry.ioros.com/docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
httpbin.virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin.default.svc.cluster.local
http:
- route:
- destination:
host: httpbin.default.svc.cluster.local
测试
http http://httpbin:8000/get
wrk -c 3 -t 3 http://httpbin:8000/ip
配置熔断规则
httpbin.destinationrule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin.default.svc.cluster.local
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
测试
wrk -c 3 -t 3 http://httpbin.default.svc.cluster.local:8000/ip
其它
Traefik: Ingress Controller 反向代理及负载均衡 RBAC: 鉴权 Prometheus: 监控
结论
重构目的
微服务设计是一个趋势,Kubernetes
又是大公司必备的微服务治理Pass
平台,后期可以根据具体的业务发展需要进行有益的尝试,梳理精简代码,调整技术架构方案
重构方向
前后的分离,独立部署,采用REST API
的方式交互
将一些可复用的业务拆分出来,例如用户帐号,支付渠道,帐号交易
独立的业务也可以拆出来,如不同产品线,网校、直播、点播、BRTC
故障重试
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin.default.svc.cluster.local
http:
- route:
- destination:
host: httpbin.default.svc.cluster.local
retries:
attempts: 3
retryOn: 5xx
测试
http http://httpbin:8000/status/5000
kubectl logs -f httpbin-77bfc6b755-xvcmx -c istio-proxy
故障注入
超时控制
httpbin.virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin.default.svc.cluster.local
http:
- route:
- destination:
host: httpbin.default.svc.cluster.local
测试
延迟2秒正常,延迟5秒失败
http --body http://httpbin:8000/delay/2
http --body http://httpbin:8000/delay/5
安装 metrics-server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml
开启 8 线程,每秒并发 500 发起请求
fortio load -a -c 8 -qps 500 -t 60s "http://ms.iirii.com:30077"
微服务的定义和优缺点 Kubernetes面试之Deployment和Statefulset区别 通俗理解Kubernetes中Service、Ingress与Ingress Controller的作用与关系
相关镜像
docker tag kennethreitz/httpbin:latest registry.ioros.com/docker.io/kennethreitz/httpbin:latest
docker image push registry.ioros.com/docker.io/kennethreitz/httpbin:latest
docker tag busybox:latest registry.ioros.com/docker.io/busybox:latest
docker image push registry.ioros.com/docker.io/busybox:latest
docker tag dustise/flaskapp:latest registry.ioros.com/docker.io/dustise/flaskapp:latest
docker image push registry.ioros.com/docker.io/dustise/flaskapp:latest
docker tag dustise/sleep:latest registry.ioros.com/docker.io/dustise/sleep:latest
docker image push registry.ioros.com/docker.io/dustise/sleep:latest
docker tag coam/test.web:0.0.1 registry.ioros.com/coam/test.web:0.0.1
docker image push registry.ioros.com/coam/test.web:0.0.1
Comments