k8s系列之五通过Service访问Pod

1.0变更

因本地原因,k8s系列之二集群环境搭建以及插件安装 中的虚拟机更换为以下3个节点,后续文章均在此三个节点上实践:

节点ip
k8s-master192.168.200.128
k8s-node1192.168.200.129
k8s-node2192.168.200.130

假设Pod中的容器很可能因为各种原因发生故障而死掉。Deployment等Controller会通过动态创建和销毁Pod来保证应用整体的健壮性。换句话说,Pod是脆弱的,但应用是健壮的。

每个Pod都有自己的IP地址。当Controller用新Pod替代发生故障的Pod时,新Pod会分配到新的IP地址。这样就产生了⼀个问题:如果⼀组Pod对外提供服务(比如HTTP),它们的IP很有可能发⽣变化,那么客户端如何找到并访问这个服务呢?Kubernetes给出的解决方案是Service。

1.1 Service是什么

由于Pod的动态性,Service解决了一个重要问题:如果一组Pod(称为“后端”)为其他Pod(称为“前端”)提供服务,前端如何找到并连接到后端的IP地址。Kubernetes中的Service为此提供了解决方案,通过提供稳定的虚拟IP和DNS,使服务发现变得简单而可靠。

1.2 Service的几种类型

(1)ClusterIP
ClusterIP 服务是 Kubernetes 的默认服务。它给你一个集群内的服务,集群内的其它应用都可以访问该服务,但是集群外部无法访问它。
(2)NodePort
除了只在内部访问的服务,我们总有很多是需要暴露出来公开访问的服务吧。在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过:NodePort来访问这些服务。
(3)LoadBalancer
LoadBalancer 服务是暴露服务到 internet 的标准方式,它借助Cloud Provider创建一个外部的负载均衡器,并将请求转发到:NodePort(向节点导流)。

1.3 ClusterIP

先创建Deployment。
vi httpd.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
spec:
  replicas: 3
  selector:  # 添加这一行,定义标签选择器
    matchLabels:
      run: httpd
  template:
    metadata:
      labels:
        run: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
        ports:
        - containerPort: 80

我们启动了三个Pod,运行httpd镜像,label是run: httpd,Service将会用这个label来挑选Pod。

kubectl get pod -o wide

Pod分配了各自的IP,这些IP只能被KubernetesCluster中的容器和节点访问,如图所示。

[root@k8s-master ~]# kubectl get pod -o wide
NAME                                READY   STATUS      RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
httpd-ff8d77b9b-dpp79               1/1     Running     1          43h   10.244.2.104   k8s-node2   <none>           <none>
httpd-ff8d77b9b-n5w6x               1/1     Running     1          43h   10.244.2.103   k8s-node2   <none>           <none>
httpd-ff8d77b9b-t6jhg               1/1     Running     1          43h   10.244.2.105   
[root@k8s-master ~]# curl 10.244.2.103
<html><body><h1>It works!</h1></body></html>
[root@k8s-master ~]# curl 10.244.2.104
<html><body><h1>It works!</h1></body></html>
[root@k8s-master ~]# curl 10.244.2.105
<html><body><h1>It works!</h1></body></html>

接下来创建Service,其配置文件如下。
vi httpdservice.yaml

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  selector:
    run: httpd
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80

执⾏kubectl apply创建Service httpd-svc,查看service

kubectl get service
[root@k8s-master ~]# kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
httpd-svc    ClusterIP   10.1.216.8   <none>        8080/TCP   43h
kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP    10d

httpd-svc分配到⼀个CLUSTER-IP 10.1.216.8。可以通过该IP访问后端的httpd Pod,如图。

[root@k8s-master ~]# curl 10.1.216.8:8080
<html><body><h1>It works!</h1></body></html>

通过kubectl describe可以查看httpd-svc与Pod的对应关系,如图

[root@k8s-master ~]# kubectl describe service httpd-svc
Name:              httpd-svc
Namespace:         default
Labels:            <none>
Annotations:       Selector:  run=httpd
Type:              ClusterIP
IP:                10.1.216.8
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.103:80,10.244.2.104:80,10.244.2.105:80
Session Affinity:  None
Events:            <none>

Endpoints罗列了三个Pod的IP和端口。我们知道Pod的IP是在容器中配置的,那么Service的Cluster IP又是配置在哪⾥的呢?CLUSTER-IP又是如何映射到Pod IP的呢?
答案是iptables。

1.4 Cluster IP底层实现

ClusterIP是⼀个虚拟IP,是由Kubernetes节点上的iptables规则管理的。可以通过iptables-save命令打印出当前节点的iptables规则,因为输出较多,这里只截取与httpd-svcClusterIP10.1.216.8相关的信息,如下。

-A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.1.216.8/32 -p tcp -m comment --comment "default/httpd-svc: cluster IP" -m tcp --dport 808       0 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.1.216.8/32 -p tcp -m comment --comment "default/httpd-svc: cluster IP" -m tcp --dport 8080 -j KUBE-SVC-RL3JAE4GN7VOGDGP

这两条规则的含义是:
(1)如果Cluster内的Pod(源地址来⾃10.244.0.0/16)要访问
httpd-svc,则允许。
(2)其他源地址访问httpd-svc,跳转到规则KUBE-SVC-
RL3JAE4GN7VOGDGP。KUBE-SVC-RL3JAE4GN7VOGDGP规则如下。

-A KUBE-SVC-RL3JAE4GN7VOGDGP -m comment --comment "default/httpd-svc:" -m statistic --mode random --probability 0.33333333349 -j KU       BE-SEP-EQHMOIHNIUPMH73P
-A KUBE-SVC-RL3JAE4GN7VOGDGP -m comment --comment "default/httpd-svc:" -m statistic --mode random --probability 0.50000000000 -j KU       BE-SEP-7VYTM2IXTFTHGXZQ
-A KUBE-SVC-RL3JAE4GN7VOGDGP -m comment --comment "default/httpd-svc:" -j KUBE-SEP-6OZMKNJKUPLE2HZF

(1)1/3的概率跳转到规则KUBE-SEP-EQHMOIHNIUPMH73P。
(2)1/3的概率(剩下2/3的⼀半)跳转到规则KUBE-SEP-7VYTM2IXTFTHGXZQ。
(3)1/3的概率跳转到规则KUBE-SEP-6OZMKNJKUPLE2HZF。

-A KUBE-SEP-EQHMOIHNIUPMH73P -s 10.244.2.106/32 -m comment --comment "default/httpd-svc:" -j KUBE-MARK-MASQ
-A KUBE-SEP-EQHMOIHNIUPMH73P -p tcp -m comment --comment "default/httpd-svc:" -m tcp -j DNAT --to-destination 10.244.2.106:80

-A KUBE-SEP-7VYTM2IXTFTHGXZQ -s 10.244.2.107/32 -m comment --comment "default/httpd-svc:" -j KUBE-MARK-MASQ
-A KUBE-SEP-7VYTM2IXTFTHGXZQ -p tcp -m comment --comment "default/httpd-svc:" -m tcp -j DNAT --to-destination 10.244.2.107:80

-A KUBE-SEP-6OZMKNJKUPLE2HZF -s 10.244.2.108/32 -m comment --comment "default/httpd-svc:" -j KUBE-MARK-MASQ
-A KUBE-SEP-6OZMKNJKUPLE2HZF -p tcp -m comment --comment "default/httpd-svc:" -m tcp -j DNAT --to-destination 10.244.2.108:80

可以看到是将请求分别转发到后端的三个Pod。
通过上面的分析,我们得到结论:iptables将访问Service的流量转发到后端Pod,而且使用类似轮询的负载均衡策略。

1.5 DNS访问Service

kubeadm部署时会默认安装kube-dns组件。

[root@k8s-master ~]#  kubectl get deployment --namespace=kube-system
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
coredns          2/2     2            2           12d
metrics-server   1/1     1            1           12d

kube-dns是⼀个DNS服务器。每当有新的Service被创建,kube-dns会添加该Service的DNS记录。Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>访问Service。比如可以用httpd-svc.default访问Servicehttpd-svc。

[root@k8s-master ~]# kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # curl httpd-svc.default:8080
/bin/sh: curl: not found
/ # wget httpd-svc.default:8080
Connecting to httpd-svc.default:8080 (10.1.216.8:8080)
saving to 'index.html'
index.html           100% |******************************************************************************************|    45  0:00:00 ETA
'index.html' saved

如果要访问其他namespace中的Service,就必须带上namesapce了。在kube-public中部署Service httpd2-svc。
vi httpd2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd2
  namespace: kube-public
spec:
  replicas: 1
  selector:
    matchLabels:
      run: httpd2
  template:
    metadata:
      labels:
        run: httpd2
    spec:
      containers:
      - name: httpd2
        image: httpd
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: httpd2-svc
  namespace: kube-public
spec:
  selector:
    run: httpd2
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80

通过namespace:kube-public指定资源所属的namespace。多个资源可以在⼀个YAML⽂件中定义,⽤“—”分割。执⾏kubectlapply创建资源。

[root@k8s-master ~]#  kubectl apply -f httpd2.yaml
deployment.apps/httpd2 created
service/httpd2-svc unchanged
[root@k8s-master ~]# kubectl get service --namespace=kube-public
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
httpd2-svc   ClusterIP   10.1.19.55   <none>        8080/TCP   9m15s
[root@k8s-master ~]# kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget httpd2-svc.kube-public:8080
Connecting to httpd2-svc.kube-public:8080 (10.1.19.55:8080)
saving to 'index.html'
index.html           100% |******************************************************************************************|    45  0:00:00 ETA
'index.html' saved

1.5 NodePort

Service通过Cluster节点的静态端口对外提供服务。Cluster外部可以通过:访问Service。
下面我们来实践NodePort,Service httpd-svc的配置文件修改。
vi httpdservice.yaml

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  type: NodePort
  selector:
    run: httpd
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80

添加type: NodePort,重新创建httpd-svc

[root@k8s-master ~]# vi httpdservice.yaml
[root@k8s-master ~]#  kubectl apply -f httpdservice.yaml
service/httpd-svc configured
[root@k8s-master ~]# kubectl get service httpd-svc
NAME        TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
httpd-svc   NodePort   10.1.216.8   <none>        8080:30560/TCP   2d23h

Kubernetes依然会为httpd-svc分配⼀个ClusterIP,不同的是:
(1)EXTERNAL-IP为nodes,表示可通过Cluster每个节点自身的IP访问Service。
(2)PORT(S)为8080:30560。8080是ClusterIP监听的端口,30560则是节点上监听的端口。Kubernetes会从30000〜32767中分配⼀个可用的端口,每个节点都会监听此端⼝并将请求转发给Service。

测试NodePort是否正常工作,通过三个节点IP+30560端口都能够访问httpd-svc。:

[root@k8s-master ~]# curl 192.168.200.128:30560
<html><body><h1>It works!</h1></body></html>
[root@k8s-master ~]# curl 192.168.200.129:30560
<html><body><h1>It works!</h1></body></html>
[root@k8s-master ~]# curl 192.168.200.130:30560
<html><body><h1>It works!</h1></body></html>

Kubernetes是如何将:映射到Pod的呢?执行iptables-save
与ClusterIP⼀样,也是借助了iptables。与ClusterIP相比,每个节点的iptables中都增加了下面两条规则。

-A KUBE-NODEPORTS -p tcp -m comment --comment "default/httpd-svc:" -m tcp --dport 30560 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/httpd-svc:" -m tcp --dport 30560 -j KUBE-SVC-RL3JAE4GN7VOGDGP

规则的含义是:访问当前节点32312端口的请求会应用规则KUBE-
SVC-RL3JAE4GN7VOGDGP,内容如下

-A KUBE-SVC-RL3JAE4GN7VOGDGP -m comment --comment "default/httpd-svc:" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-EQHMOIHNIUPMH73P
-A KUBE-SVC-RL3JAE4GN7VOGDGP -m comment --comment "default/httpd-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-7VYTM2IXTFTHGXZQ
-A KUBE-SVC-RL3JAE4GN7VOGDGP -m comment --comment "default/httpd-svc:" -j KUBE-SEP-6OZMKNJKUPLE2HZF

其作用就是负载均衡到每⼀个Pod。

NodePort默认的是随机选择,不过我们可以用nodePort指定某个特定端口。
vi httpdservice.yaml

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  type: NodePort
  selector:
    run: httpd
  ports:
    - protocol: TCP 
      nodePort: 31000
      port: 8080
      targetPort: 80

现在配置文件中就有三个Port了:

  • nodePort是节点上监听的端口。
  • port是ClusterIP上监听的端口。
  • targetPort是Pod监听的端口。
[root@k8s-master ~]# vi httpdservice.yaml
[root@k8s-master ~]#  kubectl apply -f httpdservice.yaml
service/httpd-svc configured
[root@k8s-master ~]# curl 192.168.200.130:31000
<html><body><h1>It works!</h1></body></html>
[root@k8s-master ~]# curl 192.168.200.128:31000
<html><body><h1>It works!</h1></body></html>
[root@k8s-master ~]# curl 192.168.200.129:31000
<html><body><h1>It works!</h1></body></html>

最终,Node和ClusterIP在各自端口上接收到的请求都会通过 iptables转发到Pod的targetPort。

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
k8s全自动离线部署(高可用),百度下载连接(永久有效,且免费) 当前可选安装版本----------------------------------------------------------------------------------------------------------------------------------------- Kubernetes 1.16.2  -->Docker版本18.09.7-3、18.09.8-3、18.09.9-3、19.03.0-3、19.03.1-3、19.03.2-3、19.03.3-3、19.03.4-3 Kubernetes 1.15.4  -->Docker版本18.09.7-3、18.09.8-3、18.09.9-3、19.03.0-3、19.03.1-3、19.03.2-3、19.03.3-3、19.03.4-3 Kubernetes 1.15.3  -->Docker版本18.09.7-3、18.09.8-3、18.09.9-3、19.03.0-3、19.03.1-3、19.03.2-3、19.03.3-3、19.03.4-3 当前---------------------------------------------------------------------------------------------------------------------------------------------------- 版本:kubernetes(k8s)离线自动化安装系统-v2.6(基于CentOS7.4/7.5/7.6/7.7版本) 升级内容: 1、增加多master集群节点部署功能,即配置文件configs/k8shostlist.ini支持多master节点集群加入 2、增加etcd集群分离部署支持,通过systemctl进行管理,即配置文件configs/etcdhostlist.ini支持多master节点集群加入。 3、经过测试,所有master、node节点依次注入停机故障进行测试,所有业务pod实现100%正常漂移,漂移过程中,出现业务服务响应延时增加现象,但无业务响应异常发生。 4、此版本实现100%一键安装,安装前,整理好配置文件,上传安装包到初始安装主机,直接执行安装脚本,无需任何其他手动处理,即可完成etcd、k8s集群环境搭建。 5、此版本实现了除dockerhub外,所有关键模块,无单点的解决方案。 6、此版本高可用解决方案,对于apiServer的endpoint(k8s.master.com:6443),通过配置/etc/hosts(域名:IP,1:n)模拟VIP, 生产环境下,可以给集群内所有master节点分配一个VIP(k8s.master.com),以避免软负载的流量风暴影响运行稳定性 历史---------------------------------------------------------------------------------------------------------------------------------------------------- 版本:kubernetes(k8s)离线自动化安装系统-v2.5(基于CentOS7.4/7.5/7.6/7.7版本) 升级内容: 1、增加traefik部署以及相关资源创建,除master节点外,其余node节点默认开启服务访问权限 2、demo同时支持ingress和NodePort两种服务发布模式。分别通过虚拟域名+path和NodePort端口即可方案demo服务 3、实现k8s已发布service自动发现和适配能力,在线看板实时动态显示 4、主要模块开机自启动脚本优化,以确保集群所有节点重启后,所有服务运行正常 历史---------------------------------------------------------------------------------------------------------------------------------------------------- 版本:K8s离线自动化安装系统-v2.4(基于CentOS7.4及以上版本) 升级内容: 1、私服镜像仓库搭建支撑harbor、docker-registry 2、安装配置,增加私服镜像仓库端口配置,harbor的admin用户密码配置 3、安装进度条,Ctrl+C支持强制退出,支持保持安装进度和卸载 4、安装帮助文档、使用帮助文档更新 历史---------------------------------------------------------------------------------------------------------------------------------------------------- 版本:K8s离线自动化安装系统-v2.3(基于CentOS7.4及以上版本) 升级内容: 1、增加监控模块heapster部署和配置 2、部署kubernetesui/dashboard最新版 3、授权serviceAccount:dashboard账户获取最大访问权限,满足dashboardUI操作需要 4、安装完成界面,增加dashboard访问URL提示,以及登录dashboard门户的账户token 历史----------------------------------------------------------------------------------------------------------------------------------------------------

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值