现在你对 Kubernetes 的控制面板的工作机制是否有了深入的了解呢?是否对如何构建一个优雅的云上应用有了深刻的认识,那么接下来用最近学过的知识把你之前编写的 http 以优雅的方式部署起来吧,你可能需要审视之前代码是否能满足优雅上云的需求。作业要求:编写 Kubernetes 部署脚本将 httpserver 部署到 Kubernetes 集群,以下是你可以思考的维度。
- 优雅启动
- 优雅终止
- 资源需求和 QoS 保证
- 探活
- 日常运维需求,日志等级
- 配置和代码分离
完整 YAML 配置
apiVersion: apps/v1 kind: Deployment metadata: name: httpserver spec: # 副本数 replicas: 2 selector: matchLabels: app: httpserver # 更新策略 strategy: rollingUpdate: maxSurge: 50% maxUnavailable: 50% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: httpserver spec: containers: - name: httpserver image: registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1 imagePullPolicy: IfNotPresent # 资源需求和 QoS 保证 resources: limits: memory: 1Gi cpu: 1 requests: memory: 1Gi cpu: 1 # 探活 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 8888 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 # 优雅启动,就绪状态检查 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 8888 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 # grace peroid 定义30秒后,发送SIGKILL terminationGracePeriodSeconds: 30
作业步骤
优雅启动
探活能力,通常服务流出 healthz 的端口来做探活,那么如何将探活暴露给 k8s spec 中,让 k8s 帮我们探活
spec: containers: - name: httpserver image: registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1 imagePullPolicy: Never readinessProbe: httpGet: path: /healthz port: 8888 initialDelaySeconds: 30 periodSeconds: 5 successThreshold: 2
优雅终止
相关方案:preStop Hook;应用进程处理 SIGTERM 的信号量(Go 语言如何处理 SIGTERM 信号量);
# grace peroid 定义30秒后,发送SIGKILL terminationGracePeriodSeconds: 30
资源需求和 QoS 保证
配置 limits 和 requests
- requests:kube-scheduler 只会按照 requests 的值进行计算。
- limits:kubelet 则会按照 limits 的值来进行设置 Cgroups 限制.
Qos
- Guaranteed: 同时设置 requests 和 limits,并且 requests 和 limit 值相等。优势一是在资源不足 Eviction 发生时,最后被删除;并且删除的是 Pod 资源用量超过 limits 时才会被删除;优势二是该模型与 docker cpuset 的方式绑定 CPU 核,避免频繁的上下午文切换,性能会得到大幅提升。
- Burstable:不满足 Guaranteed 条件, 但至少有一个 Container 设置了 requests
- BestEffort:没有设置 requests 和 limits。
spec: containers: - name: httpserver image: registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1 imagePullPolicy: IfNotPresent resources: limits: memory: 1Gi cpu: 1 requests: memory: 1Gi cpu: 1
探活
# 探活 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 8888 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 5 successThreshold: 2 timeoutSeconds: 1
日常运维需求,日志等级:日志输出到哪里
log 推荐输出到标准输出,然后由统一的日志采集文件上报到监控系统。
配置和代码分离
传入方式
- Environment Variables 环境变量配置
- Volume Mount 当作文件挂载
数据来源
- ConfigMap
- Secret
- Downward API
构建 httpserver 容器镜像
FROM golang:1.17 AS build WORKDIR /httpserver/ COPY . . ENV CGO_ENABLED=0 ENV GO111MODULE=on ENV GOPROXY=https://goproxy.cn,direct RUN GOOS=linux go build -installsuffix cgo -o httpserver main.go FROM busybox COPY --from=build /httpserver/httpserver /httpserver/httpserver EXPOSE 8888 ENV ENV local WORKDIR /httpserver/ ENTRYPOINT ["./httpserver"]
容器启动测试
docker build -t httpserver . docker run -p 8888:8888 --name httpserver -d httpserver docker logs httpserver curl --location --request GET 'http://127.0.0.1:8888' curl -X 'GET' 'http://127.0.0.1:8888/' curl -X 'GET' 'http://127.0.0.1:8888/healthz'
镜像推送阿里云
阿里容器镜像服务
https://www.aliyun.com/product/acr
https://cr.console.aliyun.com/cn-beijing/instances
无法登录 docker 时,执行如下命令
sudo apt install gnupg2 pass
https://stackoverflow.com/questions/50151833/cannot-login-to-docker-account
提交新的镜像
docker login --username=xxx@gmail.com registry.cn-hangzhou.aliyuncs.com docker tag 26c5cfe317bb registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1 docker push registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1
下载镜像
docker pull registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1
K8S 使用阿里云镜像仓库
- 使用 docker login 阿里云的私有仓库,需要在 master 上生成 secret 秘钥
kubectl create secret docker-registry httpserver --docker-server=registry.cn-hangzhou.aliyuncs.com --docker-username=xxx@gmail.com --docker-password='pass' --docker-email=xxx@gmail.com
- 将 ImagePullSecrets 添加到 default
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "httpserver"}]}'
- 运行测试
kubectl run httpserver --image=registry.cn-hangzhou.aliyuncs.com/jjnnzb/httpserver:0.0.1
kubectl describe pods httpserver -n default
kubectl apply -f httpserver.yaml kubectl delete -f httpserver.yaml