【K8S】K8S-网络模型、PODRCSVCYAML语法官方文档

【K8S】K8S-网络模型、PODRCSVCYAML语法官方文档

2023年7月6日发(作者:)

【K8S】K8S-⽹络模型、PODRCSVCYAML语法官⽅⽂档K8S-⽹络模型、POD/RC/SVC YAML 语法官⽅⽂档

⼀、部署组合型的应⽤

1、使⽤配置⽂件启动replicas集合

k8s通过Replication Controller来创建和管理各个不同的重复容器集合(实际上是重复的pods)。

Replication Controller会确保pod的数量在运⾏的时候会⼀直保持在⼀个特殊的数字,即replicas的设置。这个功能类似于Google GCE的实例组管理和AWS的弹性伸缩。

在快速开始中,通过kubectl run以下的YAML⽂件创建了⼀个rc运⾏着nginx:

apiVersion: v1kind: ReplicationControllermetadata: name: my-nginxspec: replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80

和定义⼀个pod的YAML⽂件相⽐,不同的只是kind的值为ReplicationController,replicas的值需要制定,pod的相关定义在template中,pod的名字不需要显式地指定,因为它们会在rc中创建并赋予名字,点击查看完整的rc定义字段列表:

rc可以通过create命令像创建pod⼀样来创建:

$ kubectl create -f ./plicationcontrollers/my-nginx

和直接创建pod不⼀样,rc将会替换因为任何原因⽽被删除或者停⽌运⾏的Pod,⽐如说pod依赖的节点挂了。所以我们推荐使⽤rc来创建和管理复杂应⽤,即使你的应⽤只要使⽤到⼀个pod,在配置⽂件中忽略replicas字段的设置即可。

2、查看Replication Controller的状态

可以通过get命令来查看你创建的rc:

$ kubectl get rcCONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICASmy-nginx nginx nginx app=nginx 2

这个状态表⽰,你创建的rc将会确保你⼀直有两个nginx的副本。

也可以和直接创pPod⼀样查看创建的Pod状态信息:

$ kubectl get podsNAME READY STATUS RESTARTS AGEmy-nginx-065jq 1/1 Running 0 51smy-nginx-buaiq 1/1 Running 0 51s

3、删除Replication Controller

当你想停⽌你的应⽤,删除你的rc,可以使⽤:

$ kubectl delete rc my-nginxreplicationcontrollers/my-nginx 默认的,这将会删除所有被这个rc管理的pod,如果pod的数量很⼤,将会花⼀些时间来完成整个删除动作,如果你想使这些pod停⽌运⾏,请指定--cascade=false。如果你在删除rc之前尝试删除pod,rc将会⽴即启动新的pod来替换被删除的pod,就像它承诺要做的⼀样。

4、Labels

k8s使⽤⽤户⾃定义的key-value键值对来区分和标识资源集合(就像rc、pod等资源),这种键值对称为label。在上⾯的例⼦中,定义pod的template字段包含了⼀个简单定义的label,key的值为app,value的值为nginx。所有被创建的pod都会卸载这个label,可以通过-L参数来查看:

$ kubectl get rc my-nginx -L appCONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS APPmy-nginx nginx nginx app=nginx 2 nginx

默认情况下,pod的label会复制到rc的label,同样地,k8s中的所有资源都⽀持携带label。

更重要的是,pod的label会被⽤来创建⼀个selector,⽤来匹配过滤携带这些label的pods。你可以通过kubectl get请求这样⼀个字段来查看template的格式化输出:

$ kubectl get rc my-nginx -o template --template="{{.or}}"map[app:nginx]你也可以直接指定selector,⽐如你想在pod template中指明那些不想选中的label,但是你应该确保selector将会匹配这些从pod template中创建的pod的label,并且它将不会匹配其他rc创建的pod。

确保后者最简单的⽅法是为rc创建⼀个唯⼀的label值,然后在pod template的label和selector中都指定这个label。

⼆、连接应⽤到⽹络中

1、k8s中连接容器的模型

现在,你已经有了组合的、多份副本的应⽤,你可以将它连接到⼀个⽹络上。在讨论k8s联⽹的⽅式之前,有必要和Docker中连接⽹络的普通⽅式进⾏⼀下⽐较。

默认情况下,Docker使⽤主机私有⽹络,所以容器之间可以互相交互,只要它们在同⼀台机器上。为了让Docker容器可以进⾏跨节点的交流,必须在主机的IP地址上为容器分配端⼝号,之后通过主机IP和端⼝将信息转发到容器中。这样⼀来,很明显地,容器之间必须谨慎地使⽤和协调端⼝号的分配,或者动态分配端⼝号。

在众多开发者之间协调端⼝号的分配是⼗分困难的,会将集群级别之外的复杂问题暴露给⽤户来处理。

在k8s中,假设Pod之间可以互相交流,⽆论它们是在哪个宿主机上。我们赋予每个Pod⾃⼰的集群私有IP,如此⼀来你就不需要明确地在Pod之间创建连接,或者将容器的端⼝映射到主机的端⼝中。这意味着,Pod中的容器可以在主机上使⽤任意彼此的端⼝,⽽且集群中的Pods可以在不使⽤NAT的⽅式下连接到其他Pod。

本章将会详细描述如何通过这样⼀个⽹络连接模型来运⾏稳定的Services。

本指南使⽤⼀个简单的nginx服务来验证以上的概念,在有对相同概念的更加详细的说明。

2、在集群上将Pod连接到⽹络

我们之前做过这个例⼦,但是让我们以⽹络连接的⾓度来重新做⼀次。创建⼀个nginx Pod,注意,这个Pod有⼀个容器端⼝的说明:

$ cat iVersion: v1kind: ReplicationControllermetadata: name: my-nginxspec: replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80

这使它可以进⼊集群上的任意节点,检查节点上运⾏的Pod:

$ kubectl create -f ./$ kubectl get pods -l app=nginx -o widemy-nginx-6isf4 1/1 Running 0 2h e2e-test-beeps-minion-93lymy-nginx-t26zt 1/1 Running 0 2h e2e-test-beeps-minion-93ly

检查你的Pod的IPs:

$ kubectl get pods -l app=nginx -o json | grep podIP "podIP": "10.245.0.15", "podIP": "10.245.0.14",

这时,你应该能够通过ssh登录任意节点然后使⽤curl来连接任⼀IP(如果节点之间没有处于同⼀个⼦⽹段,⽆法使⽤私有IP进⾏连接的话,就只能在对应节点上使⽤对应的IP进⾏连接测试)。注意,容器并不是真的在节点上使⽤80端⼝,也没有任何的NAT规则来路由流量到Pod中。这意味着你可以在同样的节点上使⽤同样的containerPort来运⾏多个nginx Pod,并且可以在集群上的任何Pod或者节点通过这个IP来连接它们。和Docker⼀样,端⼝仍然可以发布到宿主机的接⼝上,但是因为这个⽹络连接模型,这个需求就变得很少了。

如果你好奇的话,可以通过这⾥查看我们是如何做到的:

3、创建Service

现在,在集群上我们有了⼀个运⾏着niginx并且有分配IP地址空间的的Pod。理论上,你可以直接和这些Pod进⾏交互,但是当节点挂掉之后会发⽣什么?这些Pod会跟着节点挂掉,然后RC会在另外⼀个健康的节点上重新创建新的Pod来代替,⽽这些Pod分配的IP地址都会发⽣变化,对于Service类型的服务来说这是⼀个难题。

k8s上的Service是抽象的,其定义了⼀组运⾏在集群之上的Pod的逻辑集合,这些Pod是重复的,复制出来的,所以提供相同的功能。当Service被创建,会被分配⼀个唯⼀的IP地址(也称为集群IP)。这个地址和Service的⽣命周期相关联,并且当Service是运⾏的时候,这个IP不会发⽣改变。Pods进⾏配置来和这个Service进⾏交互,之后Service将会⾃动做负载均衡到Service中的Pod。

你可以通过以下的YAML⽂件来为你的两个nginx容器副本创建⼀个Service:

$ cat iVersion: v1kind: Servicemetadata: name: nginxsvc labels: app: nginxspec: ports: - port: 80 protocol: TCP selector: app: nginx

这个YAML定义创建创建⼀个Service,带有Label为app=nginx的Pod都将会开放80端⼝,并将其关联到⼀个抽象的Service端⼝。(targetPort字段是指容器内开放的端⼝Service通过这个端⼝连接Pod,port字段是指抽象Service的端⼝,nodePort为节点上暴露的端⼝号,不指定的话为随机。)点击这⾥查看完整的Service字段列表:

现在查看你创建的Service:

$ kubectl get svcNAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGEkubernetes 10.179.240.1 443/TCP 8dnginxsvc 10.179.252.126 122.222.183.144 80/TCP,81/TCP,82/TCP run=nginx2 11m 和之前提到的⼀样,Service是以⼀组Pod为基础的。这些Pod通过endpoints字段开放出来。Service的selector将会不断地进⾏Pod的Label匹配,结果将会通知⼀个Endpoints Object,这⾥创建的也叫做nginxsvc。当Pod挂掉之后,将会⾃动从Endpoints中移除,当有新的Pod被Service的selector匹配到之后将会⾃动加⼊这个Endpoints。你可以查看这个Endpoint,注意,这些IP和第⼀步中创建Pods的时候是⼀样的:

$ kubectl describe svc nginxsvcName: nginxsvcNamespace: defaultLabels: app=nginxSelector: app=nginxType: ClusterIPIP: 10.0.116.146Port: 80/TCPEndpoints: 10.245.0.14:80,10.245.0.15:80Session Affinity: NoneNo events.$ kubectl get epNAME ENDPOINTSnginxsvc 10.245.0.14:80,10.245.0.15:80

你现在应该可以通过10.0.116.146:80这个IP从集群上的任何⼀个节点使⽤curl命令来连接到nginx的Service。注意,Service的IP是完全虚拟的,如果你想知道它是怎么⼯作的,请点击:

4、Pod发现并加⼊到Service中

k8s提供了两种基本的⽅式来发现Service:环境变量和DNS。环境变量是⽴即可以使⽤的,DNS则需要kube-dns集群插件。

5、环境变量

当Pod运⾏在⼀个节点上,kubelet将会为每个激活的Service添加⼀系列的环境变量。为你的nginx Pod检查⼀下环境:$ kubectl exec my-nginx-6isf4 -- printenv | grep SERVICEKUBERNETES_SERVICE_HOST=10.0.0.1KUBERNETES_SERVICE_PORT=443

注意,这⾥没有显⽰和Service相关的东西,因为这个Pod是在Service之前创建的,这种做法另外⼀个缺点是,Scheduler可能会将两个Pod都在同⼀个机器上启动,这样⼀来,当节点挂掉之后整个Service也会挂掉。

这⾥正确的做法是杀死两个Pod,等待RC重新启动新的Pod来代替。这样⼀来,Service就在那些副本之前存在,并将环境变量设置到所有的Pod中。正确的环境变量应为:

$ kubectl scale rc my-nginx --replicas=0; kubectl scale rc my-nginx --replicas=2;$ kubectl get pods -l app=nginx -o wideNAME READY STATUS RESTARTS AGE NODEmy-nginx-5j8ok 1/1 Running 0 2m node1my-nginx-90vaf 1/1 Running 0 2m node2$ kubectl exec my-nginx-5j8ok -- printenv | grep SERVICEKUBERNETES_SERVICE_PORT=443NGINXSVC_SERVICE_HOST=10.0.116.146KUBERNETES_SERVICE_HOST=10.0.0.1NGINXSVC_SERVICE_PORT=80

6、DNS

k8s提供了⼀个DNS集群服务插件,使⽤skydns来⾃动分配DNS给其他的Service。如果你的集群上有运⾏的话,你可以查看它的状态:

$ kubectl get services kube-dns --namespace=kube-systemNAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGEkube-dns 10.179.240.10 53/UDP,53/TCP k8s-app=kube-dns 8d如果集群上没有运⾏,那么你可以启⽤它:

本节剩下的内容是在假设你拥有⼀个长时间可以使⽤IP的Service(nginxsvc)并且DNS域名已经通过dns服务(DNS集群服务插件)分配给这个IP的前提下。所以你可以在集群上的任⼀节点中使⽤标准的请求⽅法来连接Service,现在来创建另外⼀个Pod进⾏测试: $ cat iVersion: v1kind: Podmetadata: name: curlpodspec: containers: - image: radial/busyboxplus:curl command: - sleep - "3600" imagePullPolicy: IfNotPresent name: curlcontainer restartPolicy: Always执⾏查找nginx Service:

$ kubectl create -f ./fault/curlpod$ kubectl get pods curlpodNAME READY STATUS RESTARTS AGEcurlpod 1/1 Running 0 18s$ kubectl exec curlpod -- nslookup nginxsvcServer: 10.0.0.10Address 1: 10.0.0.10Name: nginxsvcAddress 1: 10.0.116.1467、使⽤加密连接的Service

到⽬前为⽌,我们仅仅是在集群中连接了nginx服务,在将服务开放到Internet上之前,你需要确认双⽅交流的通道是安全的。你将会需要以下的东西来确保安全性:

HTTPS⾃签名证书(或者你已经有了⼀个证书)⼀个nginx服务配置好了使⽤这个证书⼀个加密措施使得证书在Pod之间交流使⽤

你可以通过这⾥来获得完整的配置⽅式,简要地说,⽅式如下:

$ make keys secret KEY=/tmp/ CERT=/tmp/ SECRET=/tmp/$ kubectl create -f /tmp/crets/nginxsecret$ kubectl get secretsNAME TYPE DATAdefault-token-il9rc 1nginxsecret Opaque 2

现在修改你的nginx副本来启动⼀个使⽤这个证书的HTTPS服务和Service,并且都开放80和443端⼝:

$ cat iVersion: v1kind: Servicemetadata: name: nginxsvc labels: app: nginxspec: type: NodePort ports: - port: 8080 targetPort: 80 protocol: TCP name: http - port: 443 protocol: TCP name: https selector: app: nginx---apiVersion: v1kind: ReplicationControllermetadata: name: my-nginxspec: replicas: 1 template: metadata: labels: app: nginx spec: volumes: - name: secret-volume secret: secretName: nginxsecret containers: - name: nginxhttps image: bprashanth/nginxhttps:1.0 ports: - containerPort: 443 - containerPort: 80 volumeMounts: - mountPath: /etc/nginx/ssl name: secret-volume

nginx-app中值得注意的点有:

其包括了RC和SVC的定义在同⼀个⽂件中nginx服务的HTTP通过80端⼝,HTTPS通过443端⼝每个容器都通过挂载在/etc/nginx/ssl卷中的keys来连接。这步是在nginx服务启动之前完成的

$ kubectl delete rc,svc -l app=nginx; kubectl create -f ./plicationcontrollers/my-nginxservices/nginxsvcservices/nginxsvcreplicationcontrollers/my-nginx此时,你可以在任意节点上访问nginx服务

$ kubectl get pods -o json | grep -i podip "podIP": "10.1.0.80",node $ curl -k

...

Welcome to nginx!

注意在最后⼀步中,我们是如何使⽤-k这个参数的,因为我们不知道任何有关nginx服务运⾏的Pod的证书⽣成时刻,所以我们要告诉curl忽略别名不匹配。通过创建⼀个Service,在Pod发现Service的时候我们将证书中使⽤的别名和真实地DNS域名关联起来,让我们通过⼀个Pod来测试(这⾥会重⽤这个证书,Pod连接Service只需要):

$ cat piVersion: v1kind: ReplicationControllermetadata: name: curlrcspec: replicas: 1 template: metadata: labels: app: curlpod spec: volumes: - name: secret-volume secret: secretName: nginxsecret containers: - name: curlpod command: - sh - -c - while true; do sleep 1; done image: radial/busyboxplus:curl volumeMounts: - mountPath: /etc/nginx/ssl name: secret-volume$ kubectl create -f ./$ kubectl get podsNAME READY STATUS RESTARTS AGEcurlpod 1/1 Running 0 2mmy-nginx-7006w 1/1 Running 0 24m$ kubectl exec curlpod -- curl --cacert /etc/nginx/ssl/...Welcome to nginx!...

8、开放Service

在你的应⽤中可能需要将其开放到⼀个外部的IP中。k8s提供了两种⽅式:NodePorts和LoadBalancers。在上⾯的最后⼀部分中,我们已经通过NodePorts⽅式创建了Service,所以如果你有公⽹IP,你的nginx https副本就可以在Internet上开放了。

$ kubectl get svc nginxsvc -o json | grep -i nodeport -C 5 { "name": "http", "protocol": "TCP", "port": 80, "targetPort": 80, "nodePort": 32188 }, { "name": "https", "protocol": "TCP", "port": 443, "targetPort": 443, "nodePort": 30645 }

$ kubectl get nodes -o json | grep ExternalIP -C 2 { "type": "ExternalIP", "address": "104.197.63.17" }-- }, { "type": "ExternalIP", "address": "104.154.89.170" }$ curl -k...

Welcome to nginx!

现在,我们将通过负载均衡器重新创建⼀个Service,只需要将⽂件中的type字段从NodePort改为LoadBalancer即可:

$ kubectl delete rc, svc -l app=nginx$ kubectl create -f ./$ kubectl get svc nginxsvcNAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGEnginxsvc 10.179.252.126 162.222.184.144 80/TCP,81/TCP,82/TCP run=nginx2 13m$ curl -k...Welcome to nginx!

EXTERNAL_IP这列的IP即是可以在公⽹上访问的IP,CLUSTER_IP只能在⾃⼰的集群上访问到。

发布者:admin,转转请注明出处:http://www.yc00.com/news/1688594409a153210.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信