Kubernetes:必须通信的多个容器+;暴露节点端口
在我的设置中,有一组容器最初构建为使用Kubernetes:必须通信的多个容器+;暴露节点端口,kubernetes,Kubernetes,在我的设置中,有一组容器最初构建为使用docker compose运行。搬到Kubernetes后,我面临以下挑战: docker compose设法提供某种类型的内部DNS,允许按容器名称对其进行寻址。如何在Kubernetes中创建这样的网络?到目前为止,我发现: 它们都可以是一个pod的一部分,因此可以通过本地主机进行通信 它们都可以有一个带有匹配键:值对和服务的公共标签,但如何处理端口呢 我需要向某个NodePort公开一个内部端口,因为它必须公开。这样的服务配置是什么样子的?到目前
docker compose
运行。搬到Kubernetes后,我面临以下挑战:
docker compose
设法提供某种类型的内部DNS,允许按容器名称对其进行寻址。如何在Kubernetes中创建这样的网络?到目前为止,我发现:
- 它们都可以是一个pod的一部分,因此可以通过本地主机进行通信
- 它们都可以有一个带有匹配键:值对和服务的公共标签,但如何处理端口呢
- 大概是这样的:
apiVersion: v1 kind: Service metadata: labels: app: frontend name: frontend-nodeport spec: type: NodePort ports: - name: "3000-30001" port: 3000 nodePort: 30001 selector: app: frontend status: loadBalancer: {}`
- 如果要将容器一起缩放,则将它们放在同一个pod中,并通过本地主机通过单独的端口进行通信。这种情况不太可能发生,因为当容器化应用程序更类似于一个物理机箱上的进程而不是单独的服务/服务器时,这种方法更合适
- 如果您的容器要单独缩放,这更可能是您的情况,请使用服务。对于服务,如果跨名称空间访问服务,您可以使用服务名称(如果POD位于同一名称空间中)或FQDN(servicename.namespace.svc.cluster.local)来代替localhost(在上一点中)。与上一点不同,您的容器必须有不同的端口(因为您要寻址localhost),在这种情况下,您可以跨多个服务拥有相同的端口,因为service:port必须是唯一的。此外,使用该服务,您也可以从容器重新映射端口,如果您希望这样做的话
- 服务解决方案从吊舱/集装箱的角度出发。要测试它,您实际上需要执行到实际的容器(或来自主机的代理)中,这是常见的混淆点。为了安全起见,测试服务:实际容器中的端口可访问性,而不是来自主容器
- 最后,为了模拟容器间网络的docker compose设置,您不需要公开NodePort或其他内容。kubernetes中的服务层将负责DNS处理。NodePort有不同的意图
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
selector:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
编辑:您能否提供一个示例,说明如果容器单独缩放,service.yaml的外观如何
- 第一个是,比如说,api服务器,我们将其称为
,它将使用标记为svc my api
的pod,并与pod的端口80通信,其他pod(在同一名称空间中)可以访问主机:app:my api
和端口:svc my api
8080
apiVersion: v1 kind: Service metadata: name: svc-my-api labels: app: my-api spec: selector: app: my-api ports: - protocol: TCP port: 8080 targetPort: 80
- 第二个是mysql服务器,我们称之为
。假设来自api吊舱(由以前的服务覆盖)的容器想要访问数据库,它们将使用主机:svc my database
和端口:svc my database
3306
apiVersion: v1 kind: Service metadata: name: svc-my-database labels: app: my-database spec: selector: app: my-database ports: - name: http protocol: TCP port: 3306 targetPort: 3306
...
spec:
hostname: foo-{1..4} #keep in mind this line
subdomain: bar #and this line
containers:
- image: busybox
...
注意:假设您刚刚创建了4个pod,主机名分别为foo-1、foo-2、foo-3和foo-4。这些是分开的豆荚。你不能做foo-{1..4}。所以这只是为了演示的目的
如果您现在创建一个与子域同名的服务,则可以通过主机名、服务名、命名空间、svc.cluster.local
从集群中的任何位置访问pod
例如:
apiVersion: v1
kind: Service
metadata:
name: bar #my subdomain is called "bar", so is this service
spec:
selector:
app: my-app
ports:
- name: foo
port: 1234
targetPort: 1234
现在,假设我的pod中有标签app:my-app
,那么服务的目标就是正确的
此时,看看发生了什么(从集群内的任何pod):
2.-你问题的第二部分几乎是正确的。这是一个节点端口服务:
apiVersion: v1
kind: Service
metadata:
name: svc-nodeport
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: my-app
type: NodePort
此服务在端口80上运行,因此可以从群集中的端口80上访问它。它会将端口映射到节点上30000个以上的随机端口。现在,来自外部世界的节点的端口30001(例如)上也提供了相同的服务。最后,它会将请求转发到容器的8080端口。1-pod的概念是运行多个相互依赖的容器,如果其中一个容器失败,则整个应用程序将失败,如果您的容器是这样的,则将它们包含在同一个pod中。通信可以是本地主机或共享卷。2-您可以创建nodeport服务,并且您将能够访问POD(带有标签),其中只有一个POD存在于使用clusterIP进行通信的节点中,否则请求将被丢弃。分开你的问题,明确你需要什么。非常感谢。到目前为止,选择器位于.spec.selector。这和你使用.selector的方法有什么区别?你能提供一个例子,说明如果容器单独缩放,service.yaml会是什么样子吗?关于selector很好的理解。坦率地说,我并没有注意到选择器在规范之外,因为我只是按照原样记录了所提供链接的相关定义(而不是只留下可能过时的链接)。据我在Kubernetes的理解,它打算在规范内使用选择器(根据API和k8s)
apiVersion: v1
kind: Service
metadata:
name: svc-nodeport
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: my-app
type: NodePort