在一切皆容器的时代,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/
其中,service/
如果可以连接,则说明设置正确。如果不能,则很可能配置了标签,或者端口不匹配。
服务和入口连接
应用程序发布的最后一个一步是配置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)相匹配。