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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
网络型负载均衡 NLB,每月750个小时 15LCU
简介: service实战

service实战



创建 Service 资源


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


Service 的四种类型


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


Service 的端口


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


创建Service:type类型是ClusterIP


1、创建 Pod 
node1,2都下载nginx
[root@k8smaster node]# mkdir service
[root@k8smaster node]# cd service/
[root@k8smaster service]# kubectl delete deploy myapp-v1
deployment.apps "myapp-v1" deleted
[root@k8smaster service]# vim pod_test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80 #pod 中的容器需要暴露的端口 
#更新资源清单文件 
[root@k8smaster service]# kubectl apply -f pod_test.yaml 
deployment.apps/my-nginx created
#查看刚才创建的 Pod ip 地址 
[root@k8smaster service]# kubectl get pods -l run=my-nginx -o wide 
NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE  
my-nginx-5898cf8d98-kgwbg   1/1     Running   0          58s   10.244.1.35   k8snode2   <none>          
my-nginx-5898cf8d98-tgpst   1/1     Running   0          8s    10.244.1.36   k8snode2   <none>          
#请求 pod ip 地址,查看结果 
[root@k8smaster service]# curl 10.244.1.35 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[root@k8smaster service]# curl 10.244.1.36
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
[root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-kgwbg -- /bin/bash 
root@my-nginx-5898cf8d98-kgwbg:/# curl 10.244.1.36
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
root@my-nginx-5898cf8d98-kgwbg:/# exit
exit
需要注意的是,pod 虽然定义了容器端口,但是不会使用调度到该节点上的 80 端口,也不会使用任何特定的 NAT 规则去路由流量到 Pod 上。 这意味着可以在同一个节点上运行多个 Pod,使用相同的容器端口,并且可以从集群中任何其他的 Pod 或节点上使用 IP 的方式访问到它们。 
误删除其中一个 Pod: 
[root@k8smaster service]# kubectl delete pods my-nginx-5898cf8d98-kgwbg
pod "my-nginx-5898cf8d98-kgwbg" deleted
[root@k8smaster service]# kubectl get pods -l run=my-nginx -o wide 
NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   
my-nginx-5898cf8d98-cjzs4   1/1     Running   0          6s      10.244.2.36   k8snode    <none>           
my-nginx-5898cf8d98-tgpst   1/1     Running   0          2m50s   10.244.1.36   k8snode2   <none>           
通过上面可以看到重新生成了一个 pod my-nginx-5898cf8d98-cjzs4,ip 是 10.244.2.36,在 k8s 中创建 pod,如果 pod 被删除了,重新生成的 pod ip 地址会发生变化,所以需要在 pod 前端加一个固定接入层。接下来创建 service.
查看 pod 标签: 
[root@k8smaster service]# kubectl get pods --show-labels 
NAME                        READY   STATUS    RESTARTS   AGE     LABELS
my-nginx-5898cf8d98-cjzs4   1/1     Running   0          5m29s   pod-template-hash=5898cf8d98,run=my-nginx
my-nginx-5898cf8d98-tgpst   1/1     Running   0          8m13s   pod-template-hash=5898cf8d98,run=my-nginx
2、创建 Service 
[root@xianchaomaster1 service]# vim service_test.yaml 
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: ClusterIP
  ports:
  - port: 80  #service 的端口,暴露给 k8s 集群内部服务访问 
    protocol: TCP
    targetPort: 80  #pod 容器中定义的端口 
  selector:
    run: my-nginx #选择拥有 run=my-nginx 标签的 pod 
上述 yaml 文件将创建一个 Service,具有标签 run=my-nginx 的 Pod,目标 TCP 端口 80,并且在一个抽象的 Service 端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod 访问该 Service 的端口)上暴露。 
[root@k8smaster service]# kubectl apply -f service_test.yaml 
service/my-nginx created
[root@k8smaster service]# kubectl get svc -l run=my-nginx
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.110.254.82   <none>        80/TCP    61s
[root@k8smaster service]# kubectl get endpoints
NAME         ENDPOINTS                       AGE
my-nginx     10.244.1.36:80,10.244.2.36:80   2m4s
#可以看到关联了两个pod的ip和端口
#在 k8s 控制节点访问 service 的 ip:端口就可以把请求代理到后端 pod 
[root@k8smaster service]# curl 10.110.254.82:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
#通过上面可以看到请求 service IP:port 跟直接访问 pod ip:port 看到的结果一样,这就说明 service 可以把请求代理到它所关联的后端 pod
注意:上面的 10.99.198.177:80 地址只能是在 k8s 集群内部可以访问,在外部无法访问,比方说我们想要通过浏览器访问,那么是访问不通的,如果想要在 k8s 集群之外访问,是需要把 service type 类型改成 nodePort 的 
#查看 service 详细信息 
[root@k8smaster service]# kubectl describe svc my-nginx
Name:              my-nginx
Namespace:         default
Labels:            run=my-nginx
Annotations:       Selector:  run=my-nginx
Type:              ClusterIP
IP:                10.110.254.82
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.36:80,10.244.2.36:80
Session Affinity:  None
Events:            <none>
[root@k8smaster service]# kubectl get ep my-nginx 
NAME       ENDPOINTS                       AGE
my-nginx   10.244.1.36:80,10.244.2.36:80   11m
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。 
service 只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群 dns 中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是: 
SVC_NAME.NS_NAME.DOMAIN.LTD. 服务名.命名空间.域名后缀 集群默认的域名后缀是 svc.cluster.local
就像我们上面创建的 my-nginx 这个服务,它的完整名称解析就是 my-nginx.default.svc.cluster.local
[root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-tgpst -- /bin/bash 
root@my-nginx-5898cf8d98-tgpst:/# curl my-nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title> 
#想让主机访问域名要配置hosts和resolv
[root@k8smaster service]# vim /etc/hosts
加一行10.110.254.82 my-nginx.default.svc.cluster.local
[root@k8smaster service]# kubectl exec -it my-nginx-5898cf8d98-tgpst -- /bin/bash 
root@my-nginx-5898cf8d98-tgpst:/# cat /etc/host
cat: /etc/host: No such file or directory
root@my-nginx-5898cf8d98-tgpst:/# cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.244.1.36 my-nginx-5898cf8d98-tgpst
root@my-nginx-5898cf8d98-tgpst:/# cat /etc/resolv.conf    
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
#然后要修改resolv,搜索的时候会在这个文件搜索。
[root@k8smaster service]# vim /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local localdomain      #搜索的域名
[root@k8smaster service]# curl my-nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
#nameserver要把之前的注释掉,只写coredns的,然后可以在物理机访问,但是如果这么写,物理机一些dns访问会有问题,所以还是要把这个恢复原样.
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
27天前
|
Cloud Native 持续交付 开发者
云原生技术在现代企业中的应用与实践####
本文深入探讨了云原生技术的核心概念及其在现代企业IT架构转型中的关键作用,通过具体案例分析展示了云原生如何促进企业的敏捷开发、高效运维及成本优化。不同于传统摘要仅概述内容,本部分旨在激发读者对云原生领域的兴趣,强调其在加速数字化转型过程中的不可或缺性,为后续详细论述奠定基础。 ####
|
10天前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
71 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
|
2天前
|
运维 Cloud Native Serverless
Serverless Argo Workflows大规模计算工作流平台荣获信通院“云原生技术创新标杆案例”
2024年12月24日,阿里云Serverless Argo Workflows大规模计算工作流平台荣获由中国信息通信研究院颁发的「云原生技术创新案例」奖。
|
2天前
|
人工智能 Cloud Native 大数据
DataWorks深度技术解读:构建开放的云原生数据开发平台
Dateworks是一款阿里云推出的云原生数据处理产品,旨在解决数据治理和数仓管理中的挑战。它强调数据的准确性与一致性,确保商业决策的有效性。然而,严格的治理模式限制了开发者的灵活性,尤其是在面对多模态数据和AI应用时。为应对这些挑战,Dateworks进行了重大革新,包括云原生化、开放性增强及面向开发者的改进。通过Kubernetes作为资源底座,Dateworks实现了更灵活的任务调度和容器化支持,连接更多云产品,并提供开源Flowspec和Open API,提升用户体验。
|
16天前
|
Cloud Native
邀您参加云原生高可用技术沙龙丨云上高可用体系构建:从理论到实践
云原生高可用技术专场,邀您从理论到实践一起交流,探索云上高可用体系构建!
|
27天前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####
|
29天前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
27天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
2月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
45 3
|
2月前
|
Cloud Native 持续交付 云计算
云原生架构的演进与挑战
随着云计算技术的不断发展,云原生架构已成为企业数字化转型的重要支撑。本文深入探讨了云原生架构的概念、发展历程、核心技术以及面临的挑战,旨在为读者提供一个全面了解云原生架构的视角。通过分析Kubernetes、Docker等关键技术的应用,以及微服务、持续集成/持续部署(CI/CD)等实践案例,本文揭示了云原生架构在提高应用开发效率、降低运维成本、增强系统可扩展性等方面的显著优势。同时,也指出了云原生架构在安全性、复杂性管理等方面所面临的挑战,并提出了相应的解决策略。