寻找利用Kubernetes进行开发的最佳实践
这篇文章是关于Recruit Lifestyle Advent Calendar 2017的第9篇文章。
在CET项目中,我负责AB测试的提案、分析和开发等工作。晚上好,我是@mihirat。
AWS也推出了托管服务,Kubernetes的热潮正在兴起。顺便说一句,我去年写的入门文章即将获得200个赞,这让我感到惊讶。现在回过头来看,里面有一些有点可疑的解释…
我想总结一下我们团队目前正在使用的k8s的临时最佳实践。
前提 – qian2 ti2 (premise, condition)
-
- GKEでの話
- 弊社の某サービスの一部ページのwebサーバーをk8sで運用してます
形成
组成图

关于构成
虽然K8s中有Ingress,为什么要使用GCP的负载均衡器呢?原因有几个。
-
- 想要使用GCS进行静态内容的传递。在考虑使用CDN静态内容传递服务时,发现可以将GCS作为Load Balancer的后端bucket来使用。但如果选择使用Ingress,则无法使用这个功能,所以我选择使用LB。(后备方案将在后文提及)
为了确保服务的可用性,并在多个区域中设置集群,我希望使用k8s的Federation进行验证。然而,经过验证后得出了目前还不适合在生产环境中使用的结论。作为替代方案,我们将k8s集群挂载在Load Balancer的后面。
关于开发周围的各种各样事情
除了 LB、GCS、全局地址和防火墙规则等k8s资源之外,我们使用Terraform管理其他GCP资源。与k8s相关的其他资源,如Docker和yaml系列都集中在一个仓库里。恕我打广告,但我们参考了解决方案架构师提供的GKE最佳实践进行配置。
部署
在部署过程中,我们基本上使用kubectl从CI执行所有操作。我们使用Drone作为我们的CI工具。
流程如下:
1. 构建 Docker
2. 对 Docker 镜像进行 serverspec 或单元测试
3. 如果测试通过,将镜像推送到 Google Container Registry(GCR)
4. 使用 GCR 的镜像指定参数,执行 kubectl apply -f
一旦部署完成后,会在有关人员的slack频道中通知部署的结果。另外,我们还准备了rollback.sh等用于紧急回退的工具,以便任何T的人都可以进行处理。
各种YAML配置
使用kubectl apply -f命令更新部署时,我们可以在此过程中进行一些滚动更新的设置调整。
考虑到在某些时刻,可用的pod数量可能会极端减少,从而可能影响服务的响应能力,我们需要进行一些配置以防止这种情况的发生。
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 10% # maximum number of Pods that can be created above the desired number of Pods
maxUnavailable: 0% # maximum number of Pods that can be unavailable during the update process.
如果在策略部分进行这样的设置,首先将创建一个具有新的docker image的pod,并在该pod可用后删除现有的pod。
如果新创建的docker image存在问题或者创建pod时出现任何障碍,现有的pod数量不会减少,流量仍将流向现有的pod,这样可以放心。
(虽然有漏洞就没意义了,我要教训自己…)
通过将 maxSurge 设置为较小值,可以控制每次替换的数量。如果设置过大,当 nodes 的计算资源刚好满负荷时,无法创建新的 pod。
通过在创建集群时指定 –enable-autoscaling,可以避免这种情况并且可以增减 nodes 的数量,尽管可能需要一些时间。
考试
由于找不到关于k8s测试的好信息,所以我们根据需要采取了相应的措施。
首先,通过使用Dockerspec,您可以对创建的镜像运行Serverspec测试。这样就可以针对每个镜像进行测试。
作为进一步的通信测试,dockerspec可以在内部使用docker-compose,因此可以在多个容器启动的情况下运行测试。
假设有这样一个nginx例子。
# pseudo code
upstream backend1 {
server backend1:80;
}
upstream backend2 {
server backend2:80;
}
server {
location /be1/ {
proxy_pass http://backend1/;
}
location /be2/ {
proxy_pass http://backend2/;
}
}
准备一个这样的docker-compose文件
version: '2'
services:
frontend:
image: asia.gcr.io/__GOOGLE_PROJECT__/frontend:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
links:
- backend1
- backend2
ports:
- 38080:80
backend1:
image: backend1:latest
expose:
- 80
backend2:
image: backend2:latest
expose:
- 80
我可以做这样的测试。
describe docker_compose("#{ENV['COMPOSE_FILE']}", wait: 5) do
its_container(:frontend) do
describe 'access to backend 1' do
subject do
command("curl http://127.0.0.1/be1/ -v")
end
its(:stderr) { should match /HTTP\/1.1 200 OK/ }
end
describe 'access to backend 2' do
subject do
command("curl http://127.0.0.1/be2/ -v")
end
its(:stderr) { should match /HTTP\/1.1 200 OK/ }
end
end
end
因为这只是一个模拟的通信测试,所以我认为本来应该在k8s集群上进行测试。我正在探索在CI上使用minikube等更好的测试方法。
监视
基本上,看起来Prometheus是首选。它有针对k8s的官方yaml文件,也有很多实际应用案例。它还可以对每个pod进行资源监控,对于需要详细信息的情况似乎很有用。
现在,T不再使用Prometheus,所有日志都通过stdout发送给Stackdriver,并直接流向BigQuery。
在Google BigQuery上创建一个Redash来连接,并定期从Redash中查询nginx访问日志等数据,以创建包括服务器响应时间等信息的仪表盘。
此外,如果检测到500等错误,会通过Slack与开发人员进行通知,以便能够立即通知开发人员。
未来(正在考虑中)
目前我们正在以这样的形式进行开发,但在一些结构上正在讨论改进的建议。目前的结构中,terraform和k8s的分解点有些困难,k8s的可变性部分还没有得到充分利用。
-
- 使用Fuse在Kubernetes上挂载GCS
-
- 在上述配置中,我想要使用后端存储桶和云CDN,但是有一种将云存储作为Kubernetes的卷进行挂载的功能。
-
- https://karlstoney.com/2017/03/01/fuse-mount-in-kubernetes/
-
- 利用Ingress
- 与使用terraform创建L7 LB相比,我仍然希望使用Kubernetes独有的Ingress。要么放弃多区域,要么使用Federation来使用改进的Federated Ingress。
最后 | 综上所述 | 总之 | 总结
k8s的最佳实践,特别是关于测试、配置和运维等方面的信息很难找到,并且我们在摸索中陷入了这种情况。
Istio等新技术层出不穷,我们希望能够不断采纳并追求最佳实践。
期待您在评论中能够给出更好的配置建议!