在一切皆容器的时代, Kubernetes 无疑是一个时代宠儿. 越来越多的企业和个人开始使用 Kubernetes 来虚拟化自己的业务, 管理自己的容器. 那么如何在 Kubernetes 部署应用, 以及对运行中的集群出现故障如何排查就成了大家日益关注的问题了. 本文虫虫给大家以直观图示方式介绍如何在 Kubernetes 中部署一个应用以及如何排查 Kubernetes 的故障(下一篇, 请等待).
概述
当希望在 Kubernetes 中部署应用程序时, 通常要定义三个组件:
部署(Deployment): 这是创建 Pod 应用程序副本的方法
服务(Service): 将流量调度到 Pods 的内部负载平衡器
入口(Ingress): 描述流量如何从群集外部流到服务.
直观图示
首先, 在 Kubernetes 中, 应用程序应该通过两层负载均衡对外公开: 内部负载均衡器和外部负载均衡器.
其次, 内部的负载均衡器又被称为服务, 而外部的负载均衡器称为入口.
最后: Pods 不会直接部署. 相反, Deployment 会在其上创建 Pods 和观察者.
应用 YAML 示例
一个简单的 Hello World 应用程序为例, 该应用程序的 YAML 如下所示:
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: my-deployment
- labels:
- track: canary
- spec:
- selector:
- matchLabels:
- any-name: my-App
- template:
- metadata:
- labels:
- any-name: my-App
- spec:
- containers:
- - name: cont1
- image: learnk8s/App:1.0.0
- ports:
- - containerPort: 8080
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: my-service
- spec:
- ports:
- - port: 80
- targetPort: 8080
- selector:
- name: App
- ---
- apiVersion: networking.k8s.io/v1beta1
- kind: Ingress
- metadata:
- name: my-ingress
- spec:
- rules:
- - http:
- paths:
- - backend:
- serviceName: App
- servicePort: 80
- path: /
该定义很长, 不好发现组件之间的相互联系.
比如下这些问题:
什么时候应该使用端口 80, 什么时候应该使用端口 8080?
为了避免冲突, 是否应要为每个服务都创建一个新端口?
标签名称重要吗? 各处命名是否都应该一致?
要回答这些问题, 请接着往下看:
连接部署和服务
实际上服务和部署没有直接连接, 服务跳过部署直接指向 Pod. 因此, 要注意的实际上是 Pod 和服务之间的相互关系.
关键点
他们关系中要注意:
服务选择器应至少与 Pod 的一个标签匹配;
服务的目标端口 (targetPort) 应该与 Pod 内容器的容器端口 (containerPort) 匹配;
服务端口可以是任何数字. 多个服务也可以使用同一端口, 因为它们分配了不同的 IP 地址.
直观图示
1. 考虑服务下 Pod 公开的端口
2. 创建 Pod 时, 应为 Pod 中的每个容器定义端口 containerPort.
3. 创建服务时, 可以定义端口和目标端口. 但是只能用目标端口连接容器
4. 目标端口和容器端口应该匹配.
5. 如果容器公开了端口 3000, 则 targetPort 应该与该数字匹配.
如果查看 YAML, 则标签和 ports/targetPor 应该匹配:
常见问题
那么部署顶部 track: canary 标签是干什么的?
需要应该匹配吗?
部署的 track: canary 标签属于部署, 服务选择器没有使用它来做流量调度. 所以这个标签完全可以删除, 或者为它分配其他值.
matchLabels 选择器呢?
它必须与 Pod 标签匹配, 部署用它来跟踪 Pod.
Pod 配置修改, 如何测试?
我们可以使用以下命令检查 Pod 的标签是否正确:
kubectl get pods --show-labels
对于属于多个应用程序的 Pod 使用:
kubectl get pods --selector any-name=my-App --show-labels
其中 any-name = my-App 表示标签 any-name:my-App.
或者可以直接连接到 Pod: 可以使用 kubectl port-forward 命令连接到服务并测试连接.
kubectl port-forward service/3000:80
其中, service / 是服务的名称, 比如示例中为 "my-service";3000 是希望在计算机上打开的端口; 80 是 "服务" 在 "端口" 字段中公开的端口.
如果可以连接, 则说明设置正确. 如果不能, 则很可能配置了标签, 或者端口不匹配.
服务和入口连接
应用程序发布的最后一个一步是配置 Ingress 入口.
关键点
入口必须知道如何检索服务, 然后检索 Pod 并将流量调度到它们. 入口按名称和公开的端口来检索服务.
在入口和服务中应该匹配两件事:
Ingress 的 servicePort 应该与 Service 的端口匹配
Ingress 的 serviceName 应该与 Service 的名称匹配
直观图示
首先, 已经该服务发布了一个端口.
其次, 入口中有一个名为服务端口 (servicePort) 的字段.
在次, 服务端口和入口服务端口应始终匹配.
最后, 如果为服务分配了端口 80, 也应将其 servicePort 更改为 80.
先示例配置要注意的字段:
常见问题
如何测试入口的功能?
可以对 kubectl port-forward 使用与之前相同的策略, 但是应该连接到 Ingress 控制器, 而不是连接到服务.
首先, 使用以下命令检索 Ingress 控制器的 Pod 名称:
kubectl get pods --all-namespaces
对确认的 Ingress Pod(可能在不同的命名空间中)执行下面命令:
kubectl describe pod nginx-ingress-controller-6fc5bcc --namespace kube-system|grep Ports
用得到端口连接到 Pod:
kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system
这样访问计算机上的端口 3000 时, 请求都会被转发到 Ingress 控制器 Pod 上的端口 80. 你访问 localhost:3000, 就能看到发布的应用程序.
总结
最后, 我们总结回顾一下哪些端口和标签应该匹配点:
服务选择器应与 Pod 的标签匹配;
服务目标端口 (targetPort) 应该与 Pod 内的容器的容器端口 (containerPort) 相匹配;
服务端口可以是任何数字. 多个服务可以使用同一端口, 因为它们分配了不同的 IP 地址;
入口的服务端口 servicePort 应该与服务中的端口相匹配;
服务的名称应与入口中的字段服务名 (serviceName) 相匹配.
来源: http://developer.51cto.com/art/201912/607370.htm