【云原生 | 从零开始学Kubernetes】十八、Kubernetes核心技术Service实战 ...

打印 上一主题 下一主题

主题 801|帖子 801|积分 2403

该篇文章已经被专栏《从零开始学k8s》收录
上一篇文章:k8s核心技术service 点击跳转
  


  
创建 Service 资源

  1. #查看定义 Service 资源需要的字段有哪些?
  2. [root@k8smaster node]# kubectl explain service
  3. KIND:     Service
  4. VERSION:  v1
  5. DESCRIPTION:
  6.      Service is a named abstraction of software service (for example, mysql)
  7.      consisting of local port (for example 3306) that the proxy listens on, and
  8.      the selector that determines which pods will answer requests sent through
  9.      the proxy.
  10. FIELDS:
  11.    apiVersion        <string>        #service 资源使用的 api 组
  12.    kind        <string>                        #创建的资源类型
  13.    metadata        <Object>                #定义元数据
  14.    spec        <Object>
  15.    status        <Object>
  16. #查看 service 的 spec 字段如何定义?
  17. [root@k8smaster node]# kubectl explain service.spec
  18. KIND:     Service
  19. VERSION:  v1
  20. RESOURCE: spec <Object>
  21. DESCRIPTION:
  22.      Spec defines the behavior of a service.
  23.      https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
  24.      ServiceSpec describes the attributes that a user creates on a service.
  25. FIELDS:
  26. clusterIP <string>         #动态分配的地址,也可以自己在创建的时候指定,创建之后就改不了了
  27. externalIPs <[]string>
  28. externalName <string>
  29. externalTrafficPolicy <string>
  30. healthCheckNodePort <integer>
  31. ipFamilies <[]string>
  32. ipFamilyPolicy <string>
  33. loadBalancerIP <string>
  34. loadBalancerSourceRanges <[]string>
  35. ports <[]Object>                 #定义 service 端口,用来和后端 pod 建立联系
  36. publishNotReadyAddresses <boolean>
  37. selector <map[string]string> #通过标签选择器选择关联的 pod 有哪些
  38. sessionAffinity <string>
  39. sessionAffinityConfig <Object>        
  40. #service 在实现负载均衡的时候还支持 sessionAffinity,sessionAffinity 什么意思?会话联系,默认是 none,随机调度的(基于 iptables 规则调度的);如果我们定义 sessionAffinity 的 client ip,那就表示把来自同一客户端的 IP 请求调度到同一个 pod 上
  41. topologyKeys <[]string>
  42. type <string> #定义 service 的类型
复制代码
Service 的四种范例

  1. #查看定义 Service.spec.type 需要的字段有哪些?
  2. [root@k8smaster node]# kubectl explain service.spec.type
  3. KIND:     Service
  4. VERSION:  v1
  5. FIELD:    type <string>
  6. DESCRIPTION:
  7.      type determines how the Service is exposed. Defaults to ClusterIP. Valid
  8.      options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
  9.      "ExternalName" maps to the specified externalName. "ClusterIP" allocates a
  10.      cluster-internal IP address for load-balancing to endpoints. Endpoints are
  11.      determined by the selector or if that is not specified, by manual
  12.      construction of an Endpoints object. If clusterIP is "None", no virtual IP
  13.      is allocated and the endpoints are published as a set of endpoints rather
  14.      than a stable IP. "NodePort" builds on ClusterIP and allocates a port on
  15.      every node which routes to the clusterIP. "LoadBalancer" builds on NodePort
  16.      and creates an external load-balancer (if supported in the current cloud)
  17.      which routes to the clusterIP. More info:
  18.      https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
  19. 1、ExternalName:
  20. 适用于 k8s 集群内部容器访问外部资源,它没有 selector,也没有定义任何的端口和 Endpoint。
  21. 以下 Service 定义的是将 prod 名称空间中的 my-service 服务映射到 my.database.example.com
  22. kind: Service
  23. apiVersion: v1
  24. metadata:
  25.   name: my-service
  26.   namespace: prod
  27. spec:
  28.   type: ExternalName
  29.   externalName: my.database.example.com
  30. 当查询主机 my-service.prod.svc.cluster.local 时,群集 DNS 将返回值为 my.database.example.com 的 CNAME 记录。
  31. service 的 FQDN(带有主机名的域名) 是: <service_name>.<namespace>.svc.cluster.local
  32. my-service.prod.svc.cluster.local        #访问这个域名就相当于解析my.database.example.com域名对应的服务(这是个数据库)
  33. #k8s内部的pod都可以用这个域名,用这个域名都可以访问k8s内部的pod。
  34. 2、ClusterIP:
  35. 通过 k8s 集群内部 IP 暴露服务,选择该值,服务只能够在集群内部访问,这也是默认的 ServiceType。
  36. 3、NodePort:
  37. 通过每个 Node 节点上的 IP 和静态端口暴露 k8s 集群内部的服务。
  38. 通过请求<NodeIP>:<NodePort>可以把请求代理到内部的 pod,每个service端口都会在物理机映射一个端口,访问物理机的端口会代理到service内部的ip和端口,然后代理到与service关联的podip与pod里容器(pod里容器和pod共享ip)的ip。
  39. Client----->NodeIP:NodePort----->ServiceIp:ServicePort----->PodIP:ContainerPort。
  40. 4、LoadBalancer:
  41. 使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
复制代码
Service 的端口

  1. #查看 service 的 spec.ports 字段如何定义?
  2. [root@k8smaster node]# kubectl explain service.spec.ports
  3. KIND:     Service
  4. VERSION:  v1
  5. RESOURCE: ports <[]Object>
  6. DESCRIPTION:
  7.      The list of ports that are exposed by this service. More info:
  8.      https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
  9.      ServicePort contains information on service's port.
  10. FIELDS:
  11.    appProtocol        <string>
  12.    name        <string>                #定义端口的名字
  13.    nodePort        <integer>       
  14.    #宿主机上映射的端口,比如一个Web应用需要被k8s集群之外的其他用户访问,那么需要配置type=NodePort,比如nodePort=30001,那么其他机器就可以通过浏览器访问scheme://k8s集群中的任何一个节点ip:30001即可访问到该服务。
  15. #例如:http://192.168.11.139:30001。如果在 k8s 中部署 MySQL 数据库,MySQL 可能不需要被外界访问,只需被内部服务访问,那么就不需要设置 NodePort
  16.    port        <integer> -required-        #service 的端口,这个是 k8s 集群内部服务可访问的端口
  17.    protocol        <string>                        #端口协议
  18.    targetPort        <string>                #service关联的目标pod具体容器的端口,是pod上的端口,从port和nodePort上来的流量,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。与制作容器时暴露的端口一致(使用DockerFile中的EXPOSE)例如官方的 nginx 暴露 80 端口,在target写80,他就会找到所关联的pod里关联80端口的容器,然后代理。
复制代码
创建Service:type范例是ClusterIP

  1. 1、创建 Pod
  2. node1,2都下载nginx
  3. [root@k8smaster node]# mkdir service
  4. [root@k8smaster node]# cd service/
  5. [root@k8smaster service]# kubectl delete deploy myapp-v1
  6. deployment.apps "myapp-v1" deleted
  7. [root@k8smaster service]# vim pod_test.yaml
  8. apiVersion: apps/v1
  9. kind: Deployment
  10. metadata:
  11.   name: my-nginx
  12. spec:
  13.   selector:
  14.     matchLabels:
  15.       run: my-nginx
  16.   replicas: 2
  17.   template:
  18.     metadata:
  19.       labels:
  20.         run: my-nginx
  21.     spec:
  22.       containers:
  23.       - name: my-nginx
  24.         image: nginx
  25.         imagePullPolicy: IfNotPresent
  26.         ports:
  27.         - containerPort: 80 #pod 中的容器需要暴露的端口
  28. #更新资源清单文件
  29. [root@k8smaster service]# kubectl apply -f pod_test.yaml
  30. deployment.apps/my-nginx created
  31. #查看刚才创建的 Pod ip 地址
  32. [root@k8smaster service]# kubectl get pods -l run=my-nginx -o wide
  33. NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE  
  34. my-nginx-5898cf8d98-kgwbg   1/1     Running   0          58s   10.244.1.35   k8snode2   <none>         
  35. my-nginx-5898cf8d98-tgpst   1/1     Running   0          8s    10.244.1.36   k8snode2   <none>         
  36. #请求 pod ip 地址,查看结果
  37. [root@k8smaster service]# curl 10.244.1.35
  38. <!DOCTYPE html>
  39. <html>
  40. <head>
  41. <title>Welcome to nginx!</title>
  42. [root@k8smaster service]# curl 10.244.1.36
  43. <!DOCTYPE html>
  44. <html>
  45. <head>
  46. <title>Welcome to nginx!</title>
  47. [root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-kgwbg -- /bin/bash
  48. root@my-nginx-5898cf8d98-kgwbg:/# curl 10.244.1.36
  49. <!DOCTYPE html>
  50. <html>
  51. <head>
  52. <title>Welcome to nginx!</title>
  53. root@my-nginx-5898cf8d98-kgwbg:/# exit
  54. exit
  55. 需要注意的是,pod 虽然定义了容器端口,但是不会使用调度到该节点上的 80 端口,也不会使用任何特定的 NAT 规则去路由流量到 Pod 上。 这意味着可以在同一个节点上运行多个 Pod,使用相同的容器端口,并且可以从集群中任何其他的 Pod 或节点上使用 IP 的方式访问到它们。
  56. 误删除其中一个 Pod:
  57. [root@k8smaster service]# kubectl delete pods my-nginx-5898cf8d98-kgwbg
  58. pod "my-nginx-5898cf8d98-kgwbg" deleted
  59. [root@k8smaster service]# kubectl get pods -l run=my-nginx -o wide
  60. NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   
  61. my-nginx-5898cf8d98-cjzs4   1/1     Running   0          6s      10.244.2.36   k8snode    <none>           
  62. my-nginx-5898cf8d98-tgpst   1/1     Running   0          2m50s   10.244.1.36   k8snode2   <none>           
  63. 通过上面可以看到重新生成了一个 pod my-nginx-5898cf8d98-cjzs4,ip 是 10.244.2.36,在 k8s 中创建 pod,如果 pod 被删除了,重新生成的 pod ip 地址会发生变化,所以需要在 pod 前端加一个固定接入层。接下来创建 service.
  64. 查看 pod 标签:
  65. [root@k8smaster service]# kubectl get pods --show-labels
  66. NAME                        READY   STATUS    RESTARTS   AGE     LABELS
  67. my-nginx-5898cf8d98-cjzs4   1/1     Running   0          5m29s   pod-template-hash=5898cf8d98,run=my-nginx
  68. my-nginx-5898cf8d98-tgpst   1/1     Running   0          8m13s   pod-template-hash=5898cf8d98,run=my-nginx
  69. 2、创建 Service
  70. [root@xianchaomaster1 service]# vim service_test.yaml
  71. apiVersion: v1
  72. kind: Service
  73. metadata:
  74.   name: my-nginx
  75.   labels:
  76.     run: my-nginx
  77. spec:
  78.   type: ClusterIP
  79.   ports:
  80.   - port: 80        #service 的端口,暴露给 k8s 集群内部服务访问
  81.     protocol: TCP
  82.     targetPort: 80        #pod 容器中定义的端口
  83.   selector:
  84.     run: my-nginx        #选择拥有 run=my-nginx 标签的 pod
  85. 上述 yaml 文件将创建一个 Service,具有标签 run=my-nginx 的 Pod,目标 TCP 端口 80,并且在一个抽象的 Service 端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod 访问该 Service 的端口)上暴露。
  86. [root@k8smaster service]# kubectl apply -f service_test.yaml
  87. service/my-nginx created
  88. [root@k8smaster service]# kubectl get svc -l run=my-nginx
  89. NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
  90. my-nginx   ClusterIP   10.110.254.82   <none>        80/TCP    61s
  91. [root@k8smaster service]# kubectl get endpoints
  92. NAME         ENDPOINTS                       AGE
  93. my-nginx     10.244.1.36:80,10.244.2.36:80   2m4s
  94. #可以看到关联了两个pod的ip和端口
  95. #在 k8s 控制节点访问 service 的 ip:端口就可以把请求代理到后端 pod
  96. [root@k8smaster service]# curl 10.110.254.82:80
  97. <!DOCTYPE html>
  98. <html>
  99. <head>
  100. <title>Welcome to nginx!</title>
  101. #通过上面可以看到请求 service IP:port 跟直接访问 pod ip:port 看到的结果一样,这就说明 service 可以把请求代理到它所关联的后端 pod
  102. 注意:上面的 10.99.198.177:80 地址只能是在 k8s 集群内部可以访问,在外部无法访问,比方说我们想要通过浏览器访问,那么是访问不通的,如果想要在 k8s 集群之外访问,是需要把 service type 类型改成 nodePort 的
  103. #查看 service 详细信息
  104. [root@k8smaster service]# kubectl describe svc my-nginx
  105. Name:              my-nginx
  106. Namespace:         default
  107. Labels:            run=my-nginx
  108. Annotations:       Selector:  run=my-nginx
  109. Type:              ClusterIP
  110. IP:                10.110.254.82
  111. Port:              <unset>  80/TCP
  112. TargetPort:        80/TCP
  113. Endpoints:         10.244.1.36:80,10.244.2.36:80
  114. Session Affinity:  None
  115. Events:            <none>
  116. [root@k8smaster service]# kubectl get ep my-nginx
  117. NAME       ENDPOINTS                       AGE
  118. my-nginx   10.244.1.36:80,10.244.2.36:80   11m
  119. service 可以对外提供统一固定的 ip 地址,并将请求重定向至集群中的 pod。其中“将请求重定向至集群中的 pod”就是通过 endpoint 与 selector 协同工作实现。selector 是用于选择 pod,由selector 选择出来的 pod 的 ip 地址和端口号,将会被记录在 endpoint 中。endpoint 便记录了所有 pod的 ip 地址和端口号。当一个请求访问到 service 的 ip 地址时,就会从 endpoint 中选择出一个 ip 地址和端口号,然后将请求重定向至 pod 中。具体把请求代理到哪个 pod,需要的就是 kube-proxy 的轮询实现的。service 不会直接到 pod,service 是直接到 endpoint 资源,就是地址加端口,再由 endpoint 再关联到 pod。
  120. service 只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群 dns 中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:
  121. SVC_NAME.NS_NAME.DOMAIN.LTD. 服务名.命名空间.域名后缀 集群默认的域名后缀是 svc.cluster.local
  122. 就像我们上面创建的 my-nginx 这个服务,它的完整名称解析就是 my-nginx.default.svc.cluster.local
  123. [root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-tgpst -- /bin/bash
  124. root@my-nginx-5898cf8d98-tgpst:/# curl my-nginx.default.svc.cluster.local
  125. <!DOCTYPE html>
  126. <html>
  127. <head>
  128. <title>Welcome to nginx!</title>
  129. #想让主机访问域名要配置hosts和resolv
  130. [root@k8smaster service]# vim /etc/hosts
  131. 加一行10.110.254.82 my-nginx.default.svc.cluster.local
  132. [root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-tgpst -- /bin/bash
  133. root@my-nginx-5898cf8d98-tgpst:/# cat /etc/host
  134. cat: /etc/host: No such file or directory
  135. root@my-nginx-5898cf8d98-tgpst:/# cat /etc/hosts
  136. # Kubernetes-managed hosts file.
  137. 127.0.0.1        localhost
  138. ::1        localhost ip6-localhost ip6-loopback
  139. fe00::0        ip6-localnet
  140. fe00::0        ip6-mcastprefix
  141. fe00::1        ip6-allnodes
  142. fe00::2        ip6-allrouters
  143. 10.244.1.36        my-nginx-5898cf8d98-tgpst
  144. root@my-nginx-5898cf8d98-tgpst:/# cat /etc/resolv.conf               
  145. nameserver 10.96.0.10
  146. search default.svc.cluster.local svc.cluster.local cluster.local localdomain
  147. options ndots:5
  148. #然后要修改resolv,搜索的时候会在这个文件搜索。
  149. [root@k8smaster service]# vim /etc/resolv.conf
  150. nameserver 10.96.0.10
  151. search default.svc.cluster.local svc.cluster.local cluster.local localdomain                        #搜索的域名
  152. [root@k8smaster service]# curl my-nginx.default.svc.cluster.local
  153. <!DOCTYPE html>
  154. <html>
  155. <head>
  156. <title>Welcome to nginx!</title>
  157. #nameserver要把之前的注释掉,只写coredns的,然后可以在物理机访问,但是如果这么写,物理机一些dns访问会有问题,所以还是要把这个恢复原样.
复制代码
写在末了

创作不易,如果觉得内容对你有帮助,麻烦给个三连关注支持一下我!如果有错误,请在批评区指出,我会及时更改!
目前正在更新的系列:从零开始学k8s
感谢各位的观看,文章掺杂个人理解,如有错误请接洽我指出~


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表