k8s实践(k8s实践指南)

k8s实践这种用法仅用于在公有云服务提供商的云平台上设置Service的场景。在下面的例子中, status.loadBalancer.ingress.ip设置的146.148.47.155为云服务商提供的负载均衡器的IP地址。对该Serv

该用法仅适用于在公有云服务商的云平台上搭建服务的场景。在下面的示例中,status.loadBalancer.ingress.ip 中设置的146.148.47.155 是云服务提供商提供的负载均衡器的IP 地址。访问Service 的请求通过LoadBalancer 转发到后端Pod。实现负载均衡依赖于您的云服务提供商提供的LoadBalancer实现机制。

kind:服务

api版本: v1

元数据:

name: 我的服务

规格:

选择器:

app: 我的应用程序

端口:

– 协议: TCP

端口: 80

目标端口: 9376

节点端口: 19376

集群IP: 10.0.171.239

负载平衡器IP: 78.11.24.19

:型负载均衡器

状态:

负载平衡器:

入口:

-ip: 146.148.47.155

k8s 具有三种类型的IP 地址。

节点IP:节点的节点IP地址。这是集群中每个节点的物理网卡的IP地址。

Pod IP:Pod 的IP 地址。由Docker引擎根据docker0网桥的IP地址段分配。这通常是虚拟第2 层网络。

集群IP:服务的IP地址。这也是一个虚拟IP,但它缺少实体网络对象,因此无法响应ping命令,因此它类似于“假”IP地址。它只能与服务端口组合形成特定的通信服务端口。集群IP 本身并不能提供TCP/IP 通信的基础。在k8s 集群内,节点IP 网络、Pod IP 网络和集群IP 网络之间的通信使用k8s 本身设计和实现的特殊路由规则,这些规则不同于一般的IP 路由实现。

该模式提供集群内的虚拟IP(与Pod不在同一网段),用于集群内Pod之间的通信。

headlessservice 要求将spec.clusterIP 设置为None。

由于没有ClusterIP,kube-proxy 将不会处理此类服务。由于没有负载均衡或代理配置,因此访问服务时会返回所有后端Pod IP 地址。主要由开发人员用来执行负载平衡。基于Pod 的开发(选择器集)。

三、Service 服务的VIP 和 Service 网络代理

1、Service 服务的VIP

在Kubernetes 集群中,每个节点都运行一个kube-proxy 进程。每个节点上运行的kube-proxy 进程实际上是一个智能软件负载均衡器,它将服务请求转发到后端pod 实例,并在内部实现服务负载均衡和会话保留机制。

服务不是共享负载均衡器IP,而是分配一个全局唯一的虚拟IP 地址(称为集群IP)。在整个服务生命周期中,其集群IP不会发生变化。

kube-proxy 负责实现服务的VIP(虚拟IP)形式,而不是外部名称形式。

在Kubernetes v1.0 中,代理完全位于用户空间。

Kubernetes v1.1 添加了iptables 代理,但这不是默认的操作模式。

从Kubernetes v1.2 开始,默认使用iptables 代理。

在Kubernetes v1.0 中,服务是“第4 层”(基于IP 的TCP/UDP)概念。 Kubernetes v1.1 添加了Ingress API(测试版),它代表“第7 层”(HTTP)服务。

每当您在k8s 集群中创建服务时,k8s 集群都会为service-cluster-ip-range 内的服务分配一个集群IP,如下所示:

您可以使用kubectl get ep 查看相应的端点信息,即代理的pod。

此外,您还可以以服务的形式将现有服务添加到Kubernetes 集群中。创建服务时不需要指定标签选择器,只需在创建服务后手动添加端点即可。

2、service网络代理模式:

代理模式共有三种:userspace、iptables 和ipvs。

现在默认使用iptables,并从1.8 版本开始添加了ipvs 功能。

1)早期 userspace 代理模式

客户端首先请求一个serviceip 并通过iptables 将其转发到kube-proxy,然后由kube-proxy 将其转发到pod。这种方法效率相对较低。

在这种模式下,kube-proxy 监控Kubernetes master 添加和删除Service 和Endpoints 对象。 在本地节点上为每个服务打开一个端口(随机选择)。连接到“代理端口”的任何请求都将被代理到服务的backendPod 之一(如端点所报告的)。 使用哪个backendPod 根据服务的SessionAffinity 来确定。 最后,安装一条iptables规则,捕获到达服务的clusterIP(虚拟IP)和端口的请求,将其重定向到代理端口,代理端口将请求代理到backendPod。

从网络返回的结果是,到达服务的IP: 端口的任何请求都将被代理到适当的后端,而客户端不知道有关Kubernetes、服务或Pod 的任何信息。

默认策略是通过循环算法选择backendPod。 要实现基于客户端IP 的会话关联,请将service.spec.sessionAffinity 的值设置为“ClientIP”(默认值为“None”)。

2) 当前iptables 代理模式

当客户端请求serviceip 时,服务IP 会直接转发到pod。这种模式下的性能要高得多。 kube-proxy 在节点iptables 规则中生成pod 地址。

在这种模式下,kube-proxy 监控Kubernetes master 添加和删除Service 和Endpoints 对象。 对于每个服务,安装iptables 规则以捕获到达服务的集群IP(虚拟IP)和端口的请求,并将请求重定向到服务的一组后端之一。对于每个Endpoints 对象,还安装一条选择backendPod 的iptables 规则。

默认策略是随机选择一个后端。 要实现基于客户端IP 的会话关联,请将service.spec.sessionAffinity 的值设置为“ClientIP”(默认值为“None”)。

与用户空间代理类似,从网络返回的结果是,到达服务的IP: 端口的任何请求都会被代理到适当的后端,而客户端无需了解有关Kubernetes、服务或Pod 的任何信息。 这比用户空间代理更快、更可靠。然而,与用户空间代理不同的是,iptables 代理依赖于就绪探针,因为如果第一个选定的Pod 变得无响应,它可以自动重试另一个Pod。

3)、ipvs代理方式

该方法通过内核模块ipvs实现转发,效率更高。

3、多端口 Service

许多服务需要公开多个端口。针对这种情况,Kubernetes 支持在Service 对象上定义多个端口。 如果使用多个端口,则必须指定所有端口名称以避免端点上出现歧义。例如:

kind:服务

api版本: v1

元数据:

name: 我的服务

规格:

选择器:

app: 我的应用程序

端口:

– name: http

协议: TCP

端口: 80

目标端口: 9376

– name: https

协议: TCP

端口: 443

目标端口: 9377

4、 选择自己的 IP 地址

您的服务发出的请求可以通过设置spec.clusterIP字段来指定您自己的集群IP地址。 例如,如果您想要替换现有的DNS 条目,或者您的旧系统配置有固定IP 并且难以重新配置。 用户选择的IP地址必须有效,并且在API服务器标识符指定的service-cluster-ip-rangeCIDR范围内。如果IP 地址无效,API 服务器将返回HTTP 状态代码422,指示该值无效。

service为何使用vip而不是不使用 round-robin DNS?

有时我被问到的一个问题是为什么使用VIP 而不是标准的循环DNS。有几个原因。

长期以来,DNS 库并没有认真对待DNS TTL 和缓存域名查询结果。许多应用程序仅查询DNS 一次并缓存结果,即使应用程序或库能够成功查询和解析它,重复重播也会产生负载。 – 解析每个客户端是非常困难的。

我们尽最大努力阻止我们的用户做对他们没有好处的事情,如果很多人问这个问题,我们可能会选择实现它。

四、服务发现和DNS

Kubernetes 支持两种基本的服务发现模式:—— 环境变量和DNS。

1、环境变量

当pod 在节点上运行时,kubelet 会向每个活动服务添加一组环境变量。 它还支持Docker 链接兼容变量(请参阅makeLinkVariables)以及简单的{SVCNAME}_SERVICE_HOST 和{SVCNAME}_SERVICE_PORT 变量。这里的服务名必须大写,横线转为下划线。

例如,名为“redis-master”的服务公开TCP 端口6379 并分配集群IP 地址10.0.0.11。该服务生成以下环境变量:

REDIS_MASTER_SERVICE_HOST=10.0.0.11

REDIS_MASTER_SERVICE_PORT=6379

REDIS_MASTER_PORT=tcp://10.0.0.11:6379

REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379

REDIS_MASTER_PORT_6379_TCP_PROTO=tcp

REDIS_MASTER_PORT_6379_TCP_PORT=6379

REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

这意味着存在一个顺序要求,即—— pod 想要访问的服务必须在pod 本身之前创建。否则,不会给这些环境变量赋值。 DNS 没有这个限制。

2、DNS

DNS 服务器是一个可选(但强烈推荐)的集群插件。 DNS 服务器监视Kubernetes API 以创建新服务,从而为每个服务创建一组DNS 记录。 如果集群范围内的DNS 始终启用,则所有Pod 都应该能够使用服务自动解析名称。

例如:

该服务是webapp,命名空间是“my-ns”。在Kubernetes 集群中为“webapp.my-ns”创建DNS 记录。

1) 同一集群中的Pod(在名为“my-ns”的命名空间中)必须能够仅通过名称查询找到“webapp”。

2) 另一个命名空间中的Pod 必须使用名称“webapp.my-ns”进行限定。 这些名称查询的结果是集群IP。

Kubernetes 还支持端口名称的DNS SRV(服务)记录。如果名为“webapp.my-ns”的服务具有名为“http”的TCP 端口,则可以对“_http._tcp.webapp.my-ns”执行DNS SRV 查询,即可获取端口号。

Kubernetes DNS 服务器是访问外部名称类型服务的唯一方式。 更多信息请参见https://guisu.blog.csdn.net/article/details/93501650。

五、集群外部访问服务

k8s集群外部访问集群内服务的主要方式有hostPort或hostNetwork、NodePort、Ingress。

1、hostPort或hostNetwork

hostPort 和hostNetwork 放在第一位是因为它们很容易被忽视。这允许从集群外部访问集群内的应用程序。

hostNetwork用法:

apiVersion: 应用程序/v1

部署kind:

元数据:

标签:

app:nginx

name: nginx-部署

规格:

复制品: 1

选择器:

匹配标签:

app: nginx

模板:

元数据:

标签:

app: nginx

规格:

nodeSelector: # 节点节点选择器

role: Master # Node 节点标签(Label)

hostNetwork: true # 使用node节点网络

集装箱:

– image: nginx

imagePullPolicy: 如果不存在

name: nginx

端口:

– 集装箱港口: 8080

重点是与容器同级的hostNetwork: true,表示pod应该使用宿主机网络,配合nodeSelector在固定节点上实例化pod。如上,为主节点添加标签role: master。通过.nodeSelector,nginx在master节点上实例化,因此可以通过master节点的ip和8080端口访问它。

hostPort用法:

apiVersion: 应用程序/v1

部署kind:

元数据:

标签:

app: nginx

name: nginx-部署

规格:

复制品: 1

选择器:

匹配标签:

app: nginx

模板:

元数据:

标签:

app: nginx

规格:

nodeSelector: # 节点节点选择器

role: Master # Node 节点标签(Label)

集装箱:

– image: nginx

imagePullPolicy: 如果不存在

name: nginx

端口:

– 集装箱港口: 8080

hostPort: 80 #要点

与hostNetwork相比,它具有更多的映射功能。当然,HostPort需要一个节点选择器来修改节点。否则每次创建节点都会不同。 IP将会改变。

如何访问:用nodeSelector选择的节点ip:hostPort:role=Master Label节点ip:80如上

2、NodePort

NodePorts 是提供集群外部访问的最常见方法之一。该方法使用Service来提供集群外部的访问。

设置物理机映射的nodePort,服务类型设置为NodePort:

kind:服务

api版本: v1

元数据:

name: 我的服务

规格:

type:节点端口

选择器:

app: 我的应用程序

端口:

– 协议: TCP

端口: 80

目标端口: 9376

节点端口:30376

如何访问:将集群中任意节点的IP添加到上面分配给nodePort的端口号中。集群中任何节点上的ip:30376都可以访问该服务。

使用节点端口的缺点:

每个端口只能提供一项服务,端口范围只有30000-32767,并且与节点的IP地址紧密耦合。

nodePort 在本机上可访问,但在其他服务器上不可访问。例如,curl 172.16.1.23:30018 在节点172.16.1.23 上可访问,但在服务器172.16.1.21 上不可访问。

解决办法是:

cat /etc/sysctl.d//etc/sysctl.conf EOF

net.ipv4.ip_forward=1

结束后

系统控制-p

具体原因:Vendor libnetwork @1861587 by sanimej · Pull Request #28257 · moby/moby · GitHub

如果Docker 设置了net.ipv4.ip_forward=1 参数,则iptables FORWARD 将设置为DORP 策略。如果用户设置了net.ipv4.ip_forward=1参数,则用户可能需要对ACCEPT策略进行FORWARD。此时,Docker 不会改变FORWARD 策略。

3、LoadBalancer

通过配置云服务提供商提供的LoadBalancer地址来映射LoadBalancer。

该用法仅适用于在公有云服务商的云平台上搭建服务的场景。在下面的示例中,status.loadBalancer.ingress.ip 中设置的146.148.47.155 是云服务提供商提供的负载均衡器的IP 地址。访问Service 的请求通过LoadBalancer 转发到后端Pod。实现负载均衡依赖于您的云服务提供商提供的LoadBalancer实现机制。

kind:服务

api版本: v1

元数据:

name: 我的服务

规格:

选择器:

app: 我的应用程序

端口:

– 协议: TCP

端口: 80

目标端口: 9376

节点端口: 19376

集群IP: 10.0.171.239

负载平衡器IP: 78.11.24.19

:型负载均衡器

状态:

负载平衡器:

入口:

-ip: 146.148.47.155

4、Ingress

这可以理解为简单的部署一个nginx服务。 nginx服务使用hostNetwork或hostPort提供集群外部的访问,并根据配置的路由规则路由集群内部的各种服务。

根据上述使用服务的步骤,一个服务以IP:Port的形式表示,而对于基于HTTP的服务,不同的URL地址往往对应不同的后端服务或虚拟服务器。这些应用层传输机制只能通过Kubernetes Service机制来实现。 kubernetes V1.1中新增的Ingress将不同URL的访问请求转发到不同的后端服务,并实现了HTTP层业务路由机制。在kubernetes 集群中,Ingress 实现必须与Ingress 和Ingress 控制器定义相结合,才能形成完整的HTTP 负载均衡功能。

1)、创建Ingress Controller

使用Nginx 实现Ingress 控制器时,需要实现的基本逻辑是:

a) 监控您的API 服务器并获取所有入口定义。

b) 根据ingress定义生成Nginx所需的配置文件/etc/nginx/nginx.conf。

c) 运行nginx -s relaod 命令重新加载nginx.conf 文件并创建脚本。

直接下载Google提供的nginx-ingress镜像来创建Ingress控制器。

文件nginx-ingress-rc.yaml

api版本: v1

kind:复制控制器

元数据:

name: nginx-ingress

标签:

app: nginx 入口

规格:

复制品: 1

选择器:

app: nginx 入口

模板:

元数据:

标签:

app: nginx 入口

规格:

集装箱:

– image: gcr.io/google_containers/nginx-ingress:0.1

姓名:

nginx
        ports:
        – containerPort: 80
          hostPort: 80
这里,Nginx应用配置设置了hostPort,即它将容器应用监听的80端口号映射到物理机,以使得客户端应用可以通过URL地址“http://物理机IP:80”来访问该Ingress Controller
#kubectl create -f nginx-ingress-rc.yaml
#kubectl get pods

2)、定义Ingress

为mywebsite.com定义Ingress,设置到后端Service的转发规则:
apiVersion: extensions/vlbeta1
kind: Ingress
metadata:
  name: mywebsite-ingress
spec:
  rules:
  – host: mywebsite.com
    http:
      paths:
      – path: /web
        backend:
          serviceName: webapp
          servicePort: 80

这个Ingress的定义说明对目标http://mywebsite.com/web的访问将被转发到kubernetes的一个Service上 webapp:80

创建该Ingress
#kubectl create -f Ingress.yaml

#kubectl get ingress
NAME |Hosts |Address |Ports |Age
mywebsite-ingress |mywebsite.com |80 |17s

创建后登陆nginx-ingress Pod,查看自动生成的nginx.conf内容

3)访问http://mywebsite.com/web
我们可以通过其他的物理机对其进行访问。通过curl –resolve进行指定
#curl –resolve mywebsite.com:80:192.169.18.3 mywebsite.com/web

3)、使用Ingress 场景

Ingress 可能是暴露服务的最强大方式,但同时也是最复杂的。Ingress 控制器有各种类型,包括 Google Cloud Load Balancer, Nginx,Contour,Istio,等等。它还有各种插件,比如 cert-manager,它可以为你的服务自动提供 SSL 证书。
如果你想要使用同一个 IP 暴露多个服务,这些服务都是使用相同的七层协议(典型如 HTTP),那么Ingress 就是最有用的。如果你使用本地的 GCP 集成,你只需要为一个负载均衡器付费,且由于 Ingress是“智能”的,你还可以获取各种开箱即用的特性(比如 SSL,认证,路由,等等)。

5、总结各方式利弊

hostPort和hostNetwork直接使用节点网络,部署时节点需固定,访问ip也固定(也可以用host),端口为正常端口

nodeport方式部署时不要求固定节点,可通过集群内任一ip进行访问,就是端口为30000以上,很多时候由于公司安全策略导致不能访问。

LoadBalancer依赖于云服务商提供的LoadBalancer的实现机制。

ingress需要额外安装ingress模块,配置路由规则,且仅能通过所配置域名访问,配置好域名后,可以直接对外提供服务,和传统的nginx作用类似

六、Headless Service

**1、定义:**有时不需要或不想要负载均衡,以及单独的Service IP。遇到这种情况,可以通过指定Cluster IP(spec.clusterIP)的值为“None”来创建Headless Service。

2、和普通Service相比:

对这类Headless Service并不会分配Cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由。

它会给一个集群内部的每个成员提供一个唯一的DNS域名来作为每个成员的网络标识,集群内部成员之间使用域名通信。

3、无头服务管理的域名是如下的格式:$(service_name).$(k8s_namespace).svc.cluster.local。其中的\”cluster.local\”是集群的域名,除非做了配置,否则集群域名默认就是cluster.local。

因此选项spec.clusterIP允许开发人员自由的寻找他们自己的方式,从而降低与Kubernetes系统的耦合性。应用仍然可以使用一种自注册的模式和适配器,对其他需要发现机制的系统能够很容易的基于这个API来构建。

因为没有load balancing或 proxy 代理设置,在访问服务的时候回返回后端的全部的Pods IP地址,主要用于开发者自己根据pods进行负载均衡器的开发(设置了selector)。

DNS如何实现自动配置,依赖于Service时候定义了selector。

(1)编写headless service配置清单

vim myapp-svc-headless.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: “None” #headless的clusterIP值为None
  ports:
  – port: 80
    targetPort: 80

(2)创建headless service

kubectl apply -f myapp-svc-headless.yaml

[root@k8s-master mainfests]# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes       ClusterIP   10.96.0.1                443/TCP        36d
myapp            NodePort    10.101.245.119           80:30080/TCP   1h
myapp-headless   ClusterIP   None                     80/TCP         5s
redis            ClusterIP   10.107.238.182           6379/TCP       2h

(3)使用coredns进行解析验证
[root@k8s-master mainfests]# dig -t A myapp-headless.default.svc.cluster.local. @10.96.0.10

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A myapp-headless.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62028
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-headless.default.svc.cluster.local. IN A

;; ANSWER SECTION:
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.1.18
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.1.19
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.2.15
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.2.16
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.2.17

;; Query time: 4 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Thu Sep 27 04:27:15 EDT 2018
;; MSG SIZE  rcvd: 349

[root@k8s-master mainfests]# kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   10.96.0.10           53/UDP,53/TCP   36d

[root@k8s-master mainfests]# kubectl get pods -o wide -l app=myapp
NAME                            READY     STATUS    RESTARTS   AGE       IP            NODE
myapp-deploy-69b47bc96d-4hxxw   1/1       Running   0          1h        10.244.1.18   k8s-node01
myapp-deploy-69b47bc96d-95bc4   1/1       Running   0          1h        10.244.2.16   k8s-node02
myapp-deploy-69b47bc96d-hwbzt   1/1       Running   0          1h        10.244.1.19   k8s-node01
myapp-deploy-69b47bc96d-pjv74   1/1       Running   0          1h        10.244.2.15   k8s-node02
myapp-deploy-69b47bc96d-rf7bs   1/1       Running   0          1h        10.244.2.17   k8s-node02

(4)对比含有ClusterIP的service解析
[root@k8s-master mainfests]# dig -t A myapp.default.svc.cluster.local. @10.96.0.10

; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A myapp.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50445
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp.default.svc.cluster.local. IN    A

;; ANSWER SECTION:
myapp.default.svc.cluster.local. 5 IN    A    10.101.245.119

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

给大家整理的电子书资料:

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

-t A myapp.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50445
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp.default.svc.cluster.local. IN    A

;; ANSWER SECTION:
myapp.default.svc.cluster.local. 5 IN    A    10.101.245.119

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

[外链图片转存中…(img-bcC3h1Am-1719212063577)]

给大家整理的电子书资料:

[外链图片转存中…(img-ItIrxC68-1719212063578)]

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

#以上关于k8s实践的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92017.html

(0)
CSDN's avatarCSDN
上一篇 2024年6月24日 下午3:09
下一篇 2024年6月24日 下午3:09

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注