我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Kubernetes服务的介绍以及如何创建

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Kubernetes服务的介绍以及如何创建

Kubernetes服务的介绍以及如何创建,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

前言

上文介绍了Kubernetes副本机制,正是因为副本机制你的部署能自动保待运行,并且保持健康,无须任何手动干预;本文继续介绍kubernetes的另一个强大的功能服务,在客户端和pod之间提供一个服务层,提供了单一的接入点,更加方便客户端使用pod。

服务

Kubernetes服务是一种为一组功能相同的pod提供单一不变的接入点的资源;当服务存在时,它的IP地址和端口不会改变,客户端通过IP地址和端口号建立连接,这些连接会被路由到提供该服务的任意一个pod上;

1.创建服务

服务的连接对所有的后端pod是负载均衡的,至于哪些pod被属于哪个服务,通过在定义服务的时候设置标签选择器;

[d:\k8s]$ kubectl create -f kubia-rc.yamlreplicationcontroller/kubia created[d:\k8s]$ kubectl get podNAME          READY   STATUS              RESTARTS   AGEkubia-6dxn7   0/1     ContainerCreating   0          4skubia-fhxht   0/1     ContainerCreating   0          4skubia-fpvc7   0/1     ContainerCreating   0          4s

使用之前的yaml文件创建pod,模版中设置的标签为app: kubia,所以创建服务的yaml(还有之前介绍的kubectl expose方式也可以创建服务)中也需要指定相同的标签:

apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  ports:  - port: 80targetPort: 8080  selector:app: kubia

首先指定的资源类型为Service,然后指定了两个端口分别:port服务提供的端口,targetPort指定pod中进程监听的端口,最后指定标签选择器,相同标签的pod被当前服务管理;

[d:\k8s]$ kubectl create -f kubia-svc.yamlservice/kubia created[d:\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   6d15hkubia        ClusterIP   10.96.191.193   <none>        80/TCP    4s[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.191.193You've hit kubia-fhxht[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.191.193You've hit kubia-fpvc7

创建完服务之后,可以发现给kubia分配了CLUSTER-IP,这是一个内部ip;至于如何测试可以使用kubectl exec命令远程地在一个已经存在的pod容器上执行任何命令;pod名称可以随意指定三个中的任何一个,接收到crul命令的pod,会转发给Service,由Service来决定将请求交给哪个pod处理,所以可以看到多次执行,发现每次处理的pod都不一样;如果希望特定客户端产生的所有请求每次都指向同一个pod, 可以设置服务的sessionAffinity属性为ClientIP;

1.1配置会话黏性
apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  sessionAffinity: ClientIP  ports:  - port: 80targetPort: 8080  selector:app: kubia

除了添加了sessionAffinity: ClientIP,其他都一样

[d:\k8s]$ kubectl delete svc kubiaservice "kubia" deleted[d:\k8s]$ kubectl create -f kubia-svc-client-ip-session-affinity.yamlservice/kubia created[d:\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1     <none>        443/TCP   6d15hkubia        ClusterIP   10.96.51.99   <none>        80/TCP    25s[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.51.99You've hit kubia-fhxht[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.51.99You've hit kubia-fhxht
1.2 同一个服务暴露多个端口

如果pod监听了两个或者多个端口,那么服务同样可以暴露多个端口:

apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  ports:  - name: httpport: 80targetPort: 8080  - name: httpsport: 443targetPort: 8080  selector:app: kubia

因为Node.js只监听了8080一个端口,所以这里在Service里面配置两个端口都指向同一个目标端口,看是否都能访问:

[d:\k8s]$ kubectl create -f kubia-svc-named-ports.yamlservice/kubia created[d:\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGEkubernetes   ClusterIP   10.96.0.1      <none>        443/TCP          6d18hkubia        ClusterIP   10.96.13.178   <none>        80/TCP,443/TCP   7s[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.13.178You've hit kubia-fpvc7[d:\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.13.178:443You've hit kubia-fpvc7

可以发现使用两个端口都可以访问;

1.3 使用命名的端口

在Service中指定了端口为8080,如果目标端口变了这里也需要改变,可以在定义pod的模版中给端口命名,在Service中可以直接指定名称:

apiVersion: v1kind: ReplicationControllermetadata:    name: kubiaspec:    replicas: 3   selector:       app: kubia   template:      metadata:          labels:app: kubia      spec:          containers:          - name: kubia           image: ksfzhaohui/kubia           ports:            - name: http             containerPort: 8080

在之前的ReplicationController中稍作修改,在port是中指定了名称,Service的yaml文件同样做修改,直接使用名称:

apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  ports:  - port: 80targetPort: http  selector:app: kubia

targetPort直接使用了名称http:

[d:\k8s]$ kubectl create -f kubia-rc2.yamlreplicationcontroller/kubia created[d:\k8s]$ kubectl get podNAME          READY   STATUS    RESTARTS   AGEkubia-4m9nv   1/1     Running   0          66skubia-bm6rx   1/1     Running   0          66skubia-dh87r   1/1     Running   0          66s[d:\k8s]$ kubectl create -f kubia-svc2.yamlservice/kubia created[d:\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   7dkubia        ClusterIP   10.96.106.37   <none>        80/TCP    10s[d:\k8s]$ kubectl exec kubia-4m9nv -- curl -s http://10.96.106.37You've hit kubia-dh87r

2.服务发现

服务给我们提供了一个单一不变的ip去访问pod,那是否每次都要先创建服务,然后找到服务的CLUSTER-IP,再给其他pod去使用;这样就太麻烦了,Kubernets还提供了其他方式去访问服务;

2.1 通过环境变量发现服务

在pod开始运行的时候,Kubernets会初始化一系列的环境变量指向现在存在的服务;如果创建的服务早于客户端pod的创建,pod上的进程可以根据环境变量获得服务的IP地址和端口号;

[d:\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   7d14hkubia        ClusterIP   10.96.106.37   <none>        80/TCP    14h[d:\k8s]$ kubectl get podNAME          READY   STATUS    RESTARTS   AGEkubia-4m9nv   1/1     Running   0          14hkubia-bm6rx   1/1     Running   0          14hkubia-dh87r   1/1     Running   0          14h[d:\k8s]$ kubectl exec kubia-4m9nv envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=kubia-4m9nvKUBERNETES_SERVICE_PORT_HTTPS=443KUBERNETES_PORT=tcp://10.96.0.1:443KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443KUBERNETES_PORT_443_TCP_PROTO=tcpKUBERNETES_PORT_443_TCP_PORT=443KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1KUBERNETES_SERVICE_HOST=10.96.0.1KUBERNETES_SERVICE_PORT=443NPM_CONFIG_LOGLEVEL=infoNODE_VERSION=7.10.1YARN_VERSION=0.24.4HOME=/root

因为这里的pod早于服务的创建,所有没有相关服务的相关信息:

[d:\k8s]$ kubectl delete po --allpod "kubia-4m9nv" deletedpod "kubia-bm6rx" deletedpod "kubia-dh87r" deleted[d:\k8s]$ kubectl get podNAME          READY   STATUS    RESTARTS   AGEkubia-599v9   1/1     Running   0          48skubia-8s8j4   1/1     Running   0          48skubia-dm6kr   1/1     Running   0          48s[d:\k8s]$ kubectl exec kubia-599v9 envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=kubia-599v9...KUBIA_SERVICE_HOST=10.96.106.37KUBIA_SERVICE_PORT=80...

如果删除pod重新创建新的pod,这样服务就在创建pod之前了,再次获取环境变量可以发现有KUBIA_SERVICE_HOST和KUBIA_SERVICE_PORT,分别代表了kubia服务的IP地址和端口号;这样就可以通过环境变量去获取IP和端口了;

2.2 通过DNS发现服务

命名空间kube-system下有一个默认的服务kube-dns,其后端是一个coredns的pod:

[d:\k8s]$ kubectl get svc --namespace kube-systemNAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGEkube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   9d[d:\k8s]$ kubectl get po -o wide --namespace kube-systemNAME                               READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATEScoredns-7f9c544f75-h3cwn           1/1     Running   0          9d    172.17.0.3       minikube   <none>           <none>coredns-7f9c544f75-x2ttk           1/1     Running   0          9d    172.17.0.2       minikube   <none>           <none>

运行在pod上的进程DNS查询都会被Kubernets自身的DNS服务器响应,该服务器知道系统中运行的所有服务;客户端的pod在知道服务名称的情况下可以通过全限定域名(FQDN)来访问

[d:\k8s]$ kubectl exec kubia-599v9 -- curl -s http://kubia.default.svc.cluster.localYou've hit kubia-8s8j4

kubia对应服务名称,default为服务所在的命名空间,svc.cluster.local是在所有集群本地服务名称中使用的可配置集群域后缀;如果两个pod在同一个命名空间下,可以省略svc.cluster.local和default,使用服务名即可:

[d:\k8s]$ kubectl exec kubia-599v9 -- curl -s http://kubia.defaultYou've hit kubia-dm6kr[d:\k8s]$ kubectl exec kubia-599v9 -- curl -s http://kubiaYou've hit kubia-dm6kr
2.3 在pod中运行shell
d:\k8s>winpty kubectl exec -it kubia-599v9 -- sh# curl -s http://kubiaYou've hit kubia-dm6kr# exit

通过kubectl exec命令在一个pod容器上运行bash,这样就无须为每个要运行的命令执行kubectl exec命令;因为在windows环境下使用了winpty工具;

连接集群外部的服务

以上介绍的后端是集群中运行的一个或多个pod的服务;但也存在希望通过Kubernetes服务特性暴露外部服务的情况,可以通过Endpoint方式和外部服务别名的方式;

1.Endpoint

服务并不是和pod直接相连的;有一种资源介于两者之间:它就是Endpoint资源

[d:\k8s]$ kubectl describe svc kubiaName:              kubiaNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          app=kubiaType:              ClusterIPIP:                10.96.106.37Port:              <unset>  80/TCPTargetPort:        http/TCPEndpoints:         172.17.0.10:8080,172.17.0.11:8080,172.17.0.9:8080Session Affinity:  NoneEvents:            <none>[d:\k8s]$ kubectl get pod -o wideNAME          READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATESkubia-599v9   1/1     Running   0          3h61m   172.17.0.10   minikube   <none>           <none>kubia-8s8j4   1/1     Running   0          3h61m   172.17.0.11   minikube   <none>           <none>kubia-dm6kr   1/1     Running   0          3h61m   172.17.0.9    minikube   <none>           <none>

可以看到Endpoints对应其实就是pod的IP和端口;当客户端连接到服务时,服务代理选择这些IP和端口对中的一个,并将传入连接重定向到在该位置监听的服务器;

2.手动配置服务的endpoint(内部)

如果创建了不包含pod选择器的服务,Kubernetes将不会创建Endpoint资源;这样就需要创建Endpoint资源来指定该服务的Endpoint列表;

apiVersion: v1kind: Servicemetadata:  name: external-servicespec:  ports:  - port: 80

如上定义没有指定selector选择器:

[d:\k8s]$ kubectl create -f external-service.yamlservice/external-service created[d:\k8s]$ kubectl get svc external-serviceNAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGEexternal-service   ClusterIP   10.96.241.116   <none>        80/TCP    74s[d:\k8s]$ kubectl describe svc external-serviceName:              external-serviceNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          <none>Type:              ClusterIPIP:                10.96.241.116Port:              <unset>  80/TCPTargetPort:        80/TCPEndpoints:         <none>Session Affinity:  NoneEvents:            <none>

可以发现因为没有指定selector选择器,external-service的Endpoints为none,这种情况可以手动配置服务的Endpoint;

apiVersion: v1kind: Endpointsmetadata:  name: external-servicesubsets:  - addresses:    - ip: 172.17.0.9- ip: 172.17.0.10ports:    - port: 8080

Endpoint对象需要与服务具有相同的名称,并包含该服务的目标IP地址和端口列表:

[d:\k8s]$ kubectl create -f external-service-endpoints.yamlendpoints/external-service created[d:\k8s]$ kubectl describe svc external-serviceName:              external-serviceNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          <none>Type:              ClusterIPIP:                10.96.241.116Port:              <unset>  80/TCPTargetPort:        80/TCPEndpoints:         172.17.0.10:8080,172.17.0.9:8080Session Affinity:  NoneEvents:            <none>[d:\k8s]$ kubectl exec kubia-599v9 -- curl -s http://external-serviceYou've hit kubia-dm6kr

可以发现再创建完Endpoints之后,服务external-service的Endpoints中多了pod的ip地址和端口,同样也可以通过kubectl exec执行请求;

3.手动配置服务的endpoint(外部)

以上在endpoint配置的是kubernetes内部的ip端口,同样也可以配置外部的ip端口,在kubernetes外部启动一个服务:

apiVersion: v1kind: Endpointsmetadata:  name: external-servicesubsets:  - addresses:    - ip: 10.13.82.21ports:    - port: 8080

以上配置的10.13.82.21:8080就是一个普通的tomcat服务,在本机启动即可

[d:\k8s]$ kubectl create -f external-service-endpoints2.yamlendpoints/external-service created[d:\k8s]$ kubectl create -f external-service.yamlservice/external-service created[d:\k8s]$ kubectl exec kubia-599v9 -- curl -s http://external-serviceok

经测试可以返回外部服务的响应

4.创建外部服务别名

除了手动配置服务的Endpoint来代替公开外部服务方法,还可以通过给外部服务指定一个别名,比如给10.13.82.21指定一个域名:api.ksfzhaohui.com

apiVersion: v1kind: Servicemetadata:  name: external-servicespec:  type: ExternalName  externalName: api.ksfzhaohui.com  ports:  - port: 80

要创建一个具有别名的外部服务的服务时,要将创建服务资源的一个type字段设置为ExternalName;在externalName中指定外服服务的域名:

[d:\k8s]$ kubectl create -f external-service-externalname.yamlservice/external-service created[d:\k8s]$ kubectl exec kubia-599v9 -- curl -s http://external-service:8080ok

经测试可以返回外部服务的响应

将服务暴露给外部客户端

向外部公开某些服务,kubernetes提供了三种方式:NodePort服务,LoadBalance服务以及Ingress资源方式,下面分别介绍及实战;

1.NodePort类型的服务

创建一个服务并将其类型设置为NodePort,通过创建NodePort服务,可以让kubernetes在其所有节点上保留一个端口(所有节点上都使用相同的端口号),然后将传入的连接转发给pod;

apiVersion: v1kind: Servicemetadata:  name: kubia-nodeportspec:  type: NodePort  ports:  - port: 80targetPort: 8080nodePort: 30123  selector:app: kubia

指定服务类型为NodePort,节点端口为30123;

d:\k8s]$ kubectl create -f kubia-svc-nodeport.yamlservice/kubia-nodeport created[d:\k8s]$ kubectl get svcNAME             TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGEkubernetes       ClusterIP   10.96.0.1     <none>        443/TCP        31dkubia-nodeport   NodePort    10.96.59.16   <none>        80:30123/TCP   3s[d:\k8s]$ kubectl exec kubia-7fs6m -- curl -s http://10.96.59.16You've hit kubia-m487j

要外部可以访问内部pod服务,需要知道节点的IP,我们这里使用的节点为minikube,因为这里的minikube是安装在本地windows系统下,可以直接使用minikube的内部ip进行访问

d:\k8s]$ kubectl get nodes -o wideNAME       STATUS   ROLES    AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE              KERNEL-VERSION   CONTAINER-RUNTIMEminikube   Ready    master   34d   v1.17.0   192.168.99.108   <none>        Buildroot 2019.02.7   4.19.81          docker://19.3.5

Kubernetes服务的介绍以及如何创建

2.LoadBalance类型服务

相比NodePort方式可以通过任何节点的30312端口访问内部的pod,LoadBalance方式拥有自己独一无二的可公开访问的IP地址;LoadBalance其实是NodePort的一种扩展,使得服务可以通过一个专用的负载均衡器来访问;

apiVersion: v1kind: Servicemetadata:  name: kubia-loadbalancerspec:  type: LoadBalancer  ports:  - port: 80targetPort: 8080  selector:app: kubia

指定服务类型为LoadBalancer,无需指定节点端口;

d:\k8s]$ kubectl create -f kubia-svc-loadbalancer.yamlservice/kubia-loadbalancer created[d:\k8s]$ kubectl get svcNAME                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGEkubernetes           ClusterIP      10.96.0.1       <none>        443/TCP        31dkubia-loadbalancer   LoadBalancer   10.96.207.113   <pending>     80:30038/TCP   7skubia-nodeport       NodePort       10.96.59.16     <none>        80:30123/TCP   32m

可以看到虽然我们没有指定节点端口,但是创建完之后自动启动了30038节点端口
Kubernetes服务的介绍以及如何创建
所以可以发现同样能通过使用NodePort的方式来访问服务(节点IP+节点端口);同时也可以通过EXTERNAL-IP来访问,但是使用Minikube,就不会有外部IP地址,外部IP地址将会一直是pending状态;

3.了解并防止不必要的网络跳数

当外部客户端通过节点端口连接到服务时,随机选择的pod并不一定在接收连接的同一节点上运行;可以通过将服务配置为仅将外部通信重定向到接收连接的节点上运行的pod来阻止此额外跳数;

apiVersion: v1kind: Servicemetadata:  name: kubia-nodeport-onlylocalspec:  type: NodePort  externalTrafficPolicy: Local  ports:  - port: 80targetPort: 8080nodePort: 30124  selector:app: kubia

通过在服务的spec部分中设置externalTrafficPolicy字段来完成;

4.Ingress类型服务

每个LoadBalancer服务都需要自己的负载均衡器,以及独有的公有IP地址;而Ingress 只需要一个公网IP就能为许多服务提供访问;当客户端向Ingress发送HTTP请求时,Ingress会根据请求的主机名和路径转发到对应的服务;

4.1 Ingress控制器

只有Ingress控制器在集群中运行,Ingress资源才能正常工作;不同的Kubernetes环境使用不同的控制器实现,但有些并不提供默认控制器;我这里使用的Minikube需要启用附加组件才可以使用控制器;

[d:\Program Files\Kubernetes\Minikube]$ minikube addons list- addon-manager: enabled- dashboard: enabled- default-storageclass: enabled- efk: disabled- freshpod: disabled- gvisor: disabled- helm-tiller: disabled- ingress: disabled- ingress-dns: disabled- logviewer: disabled- metrics-server: disabled- nvidia-driver-installer: disabled- nvidia-gpu-device-plugin: disabled- registry: disabled- registry-creds: disabled- storage-provisioner: enabled- storage-provisioner-gluster: disabled

列出所有的附件组件,可以看到ingress是不可用的,所以需要开启

[d:\Program Files\Kubernetes\Minikube]$ minikube addons enable ingress* ingress was successfully enabled

启动之后可以查看kube-system命名空间下的pod

[d:\k8s]$ kubectl get pods -n kube-systemNAME                                        READY   STATUS              RESTARTS   AGEcoredns-7f9c544f75-h3cwn                    1/1     Running             0          55dcoredns-7f9c544f75-x2ttk                    1/1     Running             0          55detcd-minikube                               1/1     Running             0          55dkube-addon-manager-minikube                 1/1     Running             0          55dkube-apiserver-minikube                     1/1     Running             0          55dkube-controller-manager-minikube            1/1     Running             2          55dkube-proxy-xtbc4                            1/1     Running             0          55dkube-scheduler-minikube                     1/1     Running             2          55dnginx-ingress-controller-6fc5bcc8c9-nvcb5   0/1     ContainerCreating   0          8sstorage-provisioner                         1/1     Running             0          55d

可以发现正在创建一个名称为nginx-ingress-controller的pod,会一直停留在拉取镜像状态,并显示如下错误:

Failed to pull image "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1": rpc error: code = Unknown desc = context canceled

这是因为国内无法下载quay.io下面的镜像,可以使用阿里云镜像:

image: registry.aliyuncs.com/google_containers/nginx-ingress-controller:0.26.1

可以从ingress-nginx下的deploy/static/mandatory.yaml文件修改其中的镜像为阿里云镜像,然后重新创建即可:

[d:\k8s]$ kubectl create -f mandatory.yamlnamespace/ingress-nginx createdconfigmap/nginx-configuration createdconfigmap/tcp-services createdconfigmap/udp-services createdserviceaccount/nginx-ingress-serviceaccount createdclusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole createdrole.rbac.authorization.k8s.io/nginx-ingress-role createdrolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding createdclusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding createddeployment.apps/nginx-ingress-controller created

再次查看kube-system命名空间下的pod

[d:\k8s]$ kubectl get pods -n kube-systemNAME                                        READY   STATUS    RESTARTS   AGEcoredns-7f9c544f75-h3cwn                    1/1     Running   0          56dcoredns-7f9c544f75-x2ttk                    1/1     Running   0          56detcd-minikube                               1/1     Running   0          56dkube-addon-manager-minikube                 1/1     Running   0          56dkube-apiserver-minikube                     1/1     Running   0          56dkube-controller-manager-minikube            1/1     Running   2          56dkube-proxy-xtbc4                            1/1     Running   0          56dkube-scheduler-minikube                     1/1     Running   2          56dnginx-ingress-controller-6fc5bcc8c9-nvcb5   1/1     Running   0          10mstorage-provisioner                         1/1     Running   0          56d

nginx-ingress-controller已经为Running状态,下面就可以使用Ingress资源了;

4.2 Ingress资源

Ingress控制器启动之后,就可以创建Ingress资源了

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubiaspec:  rules:  - host: kubia.example.comhttp:      paths:      - path: /backend:          serviceName: kubia-nodeport          servicePort: 80

指定资源类型为Ingress,定一个单一规则,所有发送kubia.example.com的请求都会被转发给端口为80的kubia-nodeport服务上;

[d:\k8s]$ kubectl get svcNAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGEkubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        53dkubia-nodeport   NodePort    10.96.204.104   <none>        80:30123/TCP   21h[d:\k8s]$ kubectl create -f kubia-ingress.yamlingress.extensions/kubia created[d:\k8s]$ kubectl get ingressNAME    HOSTS               ADDRESS          PORTS   AGEkubia   kubia.example.com   192.168.99.108   80      6m4s

需要把域名映射到ADDRESS:192.168.99.108,修改hosts文件即可,下面就可以直接用域名访问了,最终请求会被转发到kubia-nodeport服务
Kubernetes服务的介绍以及如何创建

大致请求流程如下:浏览器中请求域名首先会查询域名服务器,然后DNS返回了控制器的IP地址;客户端向控制器发送请求并在头部指定了kubia.example.com;然后控制器根据头部信息确定客户端需要访问哪个服务;然后通过服务关联的Endpoint对象查看pod IP,并将请求转发给其中一个;

4.3 Ingress暴露多个服务

rules和paths是数组,可以配置多个

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubia2spec:  rules:  - host: kubia.example.comhttp:      paths:      - path: /v1backend:          serviceName: kubia-nodeport          servicePort: 80  - path: /v2backend:          serviceName: kubia-nodeport          servicePort: 80  - host: kubia2.example.comhttp:      paths:      - path: /backend:          serviceName: kubia-nodeport          servicePort: 80

配置了多个host和path,这里为了方便映射了同样服务;

[d:\k8s]$ kubectl create -f kubia-ingress2.yamlingress.extensions/kubia2 created[d:\k8s]$ kubectl get ingressNAME     HOSTS                                  ADDRESS          PORTS   AGEkubia    kubia.example.com                      192.168.99.108   80      41mkubia2   kubia.example.com,kubia2.example.com   192.168.99.108   80      15m

同样需要配置host文件,测试如下:
Kubernetes服务的介绍以及如何创建

Kubernetes服务的介绍以及如何创建

Kubernetes服务的介绍以及如何创建

4.4 配置Ingress处理TLS传输

以上介绍的消息都是基于Http协议,Https协议需要配置相关证书;客户端创建到Ingress控制器的TLS连接时,控制器将终止TLS连接;客户端与Ingress控制器之间是加密的,而Ingress控制器和pod之间没有加密;要使控制器可以这样,需要将证书和私钥附加到Ingress中;

[root@localhost batck-job]# openssl genrsa -out tls.key 2048Generating RSA private key, 2048 bit long modulus..................................................................+++........................+++e is 65537 (0x10001)[root@localhost batck-job]# openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com[root@localhost batck-job]# ll-rw-r--r--. 1 root root 1115 Feb 11 01:20 tls.cert-rw-r--r--. 1 root root 1679 Feb 11 01:20 tls.key

生成的两个文件创建secret

[d:\k8s]$ kubectl create secret tls tls-secret --cert=tls.cert --key=tls.keysecret/tls-secret created

现在可以更新Ingress对象,以便它也接收kubia.example.com的HTTPS请求;

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubiaspec:  tls:  - hosts:     - kubia.example.comsecretName: tls-secret  rules:  - host: kubia.example.comhttp:      paths:      - path: /backend:          serviceName: kubia-nodeport          servicePort: 80

tls中指定相关证书

[d:\k8s]$ kubectl apply -f kubia-ingress-tls.yamlWarning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl applyingress.extensions/kubia configured

通过浏览器访问https协议,如下图所示
Kubernetes服务的介绍以及如何创建

Pod就绪信号

只要pod的标签和服务的pod选择器想匹配,pod就可以作为服务的后端,但是如果pod没有准备好,是不能处理请求的,这时候就需要就绪探针了,用来检查pod是否已经准备好了,如果检查成功就可以作为服务的后端处理消息了;

1.就绪探针类型

就绪探针有三种类型分别:

  • Exec探针:执行进程的地方,容器的状态由进程的退出状态代码确认;

  • Http get探针:向容器发送HTTP GET请求,通过响应的HTTP状态代码判断容器是否准备好;

  • Tcp socket探针:它打开一个TCP连接到容器的指定端口,如果连接己建立,则认为容器己准备就绪。

kubernetes会周期性地调用探针,并根据就绪探针的结果采取行动。如果某个pod报告它尚未准备就绪,则会从该服务中删除该pod。如果pod再次准备就绪,则重新添加pod;

2.向pod添加就行探针

编辑ReplicationController,修改pod模版添加就绪探针

[d:\k8s]$ kubectl edit rc kubialibpng warning: iCCP: known incorrect sRGB profilereplicationcontroller/kubia edited[d:\k8s]$ kubectl get podsNAME          READY   STATUS    RESTARTS   AGEkubia-7fs6m   1/1     Running   0          22dkubia-m487j   1/1     Running   0          22dkubia-q6z5w   1/1     Running   0          22d

编辑ReplicationController如下所示,添加readinessProbe

apiVersion: v1kind: ReplicationControllermetadata:    name: kubiaspec:    replicas: 3   selector:       app: kubia   template:      metadata:          labels:app: kubia      spec:          containers:          - name: kubia           image: ksfzhaohui/kubia           ports:            - containerPort: 8080   readinessProbe:           exec:command:            - ls            - /var/ready

就绪探针将定期在容器内执行ls/var/ready命令。如果文件存在,则ls命令返回退出码 0, 否则返回非零的退出码;如果文件存在,则就绪探针将成功,否则失败;
我们编辑完ReplicationController还没有产生新的pod所以可以发现以上pod的READY都为1,表示已经准备好可以处理消息;

[d:\k8s]$ kubectl delete pod kubia-m487jpod "kubia-m487j" deleted[d:\k8s]$ kubectl get podsNAME          READY   STATUS    RESTARTS   AGEkubia-7fs6m   1/1     Running   0          22dkubia-cxz5v   0/1     Running   0          114skubia-q6z5w   1/1     Running   0          22d

删除一个pod,马上会创建一个带有就绪探针的pod,可以发现长时间READY为0;

本文首先介绍了服务的基本知识,如何创建服务发现服务;然后介绍了服务和pod直接的关联器endpoint;最后重点介绍了将服务暴露给外部客户端的三种方式。

看完上述内容,你们掌握Kubernetes服务的介绍以及如何创建的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网行业资讯频道,感谢各位的阅读!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Kubernetes服务的介绍以及如何创建

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Kubernetes服务的介绍以及如何创建

Kubernetes服务的介绍以及如何创建,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。前言上文介绍了Kubernetes副本机制,正是因为副本机制你的部署能自动保待运行,并且
2023-06-19

windows8中存储池如何创建及存储池的功能介绍

这个名为“存储空间”的新功能将利用一个物理存储设施组成数据池。这个数据池将使用SATA、USB和SAS硬盘创建,并且能够使用额外的硬件扩展。这些称作“空间”的虚拟硬盘能够把4TB存储空间扩大到
2022-06-04

如何搭建私有GitLab服务器?方法介绍

随着互联网的快速发展和普及,越来越多的开发者开始使用git作为版本控制工具,在此基础上又出现了一款基于git的代码托管平台GitLab。随着GitLab的不断发展壮大,越来越多的团队使用GitLab来管理和托管自己的代码库,而搭建私有Git
2023-10-22

CentOS下常见的系统服务以及相关的关闭方法介绍

这篇文章主要介绍“CentOS下常见的系统服务以及相关的关闭方法介绍”,在日常操作中,相信很多人在CentOS下常见的系统服务以及相关的关闭方法介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”CentOS下
2023-06-10

如何在阿里云搭建ecs服务器?详细介绍

在数字化时代,搭建一个可靠的服务器对于企业或个人来说非常重要。阿里云作为国内最大的云计算平台,拥有丰富的服务器资源,让搭建服务器变得非常简单。本文将详细介绍如何在阿里云搭建ecs服务器。一、登录阿里云账号首先,你需要在阿里云官网上注册一个账号。注册完成后,登录你的阿里云账号。二、购买ecs服务器在阿里云控制台,选
如何在阿里云搭建ecs服务器?详细介绍
2023-11-06

如何在Windows7系统下创建宽带连接的图文方法介绍

WIN7 宽带连接创建图文教程 满足那些刚刚接触WIN7系统的朋友。打开开始菜单,点击“控制面板”。VdYiQifB点击“网络和Internet”。点击“网络和共享中心&rdquo
2023-05-29

如何购买Vultr VPS主机及创建服务器

这篇文章主要介绍“如何购买Vultr VPS主机及创建服务器”,在日常操作中,相信很多人在如何购买Vultr VPS主机及创建服务器问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何购买Vultr VPS主机
2023-06-10

亚马逊的服务器如何创建

步骤1:登录AWS账户。使用AWSEC2登录到AWSAccount,然后在EC2中输入您的AWSElasticContainerKey。如果您使用的是AWSEC2云服务,请使用EC2Connect或EC2Connect-to-EC2EdgeEdgeKey登录到AWSEC2账户。步骤2:创建AWS服务器。在AWS账户登录后,在AWSEC2中输入要创建的AWS服务器的ElasticContainerKey,然后输入您的主机名和端口号,并指定要分配给该服务器的云服务的主机名...
2023-10-27

linux如何创建一个包含了 'file1', 'file2' 以及 'dir1'的档案文件

Linux中创建和管理存档文件在Linux系统中创建、修改和解压包含多个文件的存档文件。本指南介绍使用tar命令创建存档文件、添加文件、排除文件、创建压缩存档和解压存档内容。还包括高级选项,例如排除模式、增量备份和验证存档完整性。
linux如何创建一个包含了 'file1', 'file2' 以及 'dir1'的档案文件
2024-04-10

Java如何创建多线程的服务器

这篇“Java如何创建多线程的服务器”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java如何创建多线程的服务器”文章吧。回
2023-06-03

win8系统中的宽带连接在哪以及如何创建宽带连接

随着微软新一代Win8系统逐渐成为主流,不少新购买的电脑用户普遍用上了Win8,不过近期很多小白朋友在Win8中找不到宽带连接,不知道Win8宽带连接在哪里,从而不知道如何拨号上网。针对不少Win8用户遇到的问题,下面编程网与大家做个详细的
2022-06-04

亚马逊的服务器如何创建账户

登录到您的亚马逊账户。在登录页面,您可能需要点击“注册”或“创建账户”来进入到此页面。找到“AmazonWebServices”页面。在此页面上,您将看到一个“创建AWSAccount”的链接。点击该链接。输入您的基本信息,例如您的公司名称、您的联系人姓名和您的电邮地址。这可以是您已经拥有的所有联系信息。在“AWSAccount”页面上,您将看到一个表格,其中包含您的所有联系信息和可用余
2023-10-27

如何用python创建最简单的服务器

今天就跟大家聊聊有关如何用python创建最简单的服务器,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。  本文使用socket实现,  使用python访问  下面,我们开始讲解实现
2023-06-02

C#如何创建Windows服务与服务的安装、卸载

这篇文章主要介绍C#如何创建Windows服务与服务的安装、卸载,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录