K8s暴露端口与代理方式

K8s暴露端口与代理方式

kubernetes暴露端口的方式

方式1:clusterIP
此类型会提供一个集群内部的虚拟IP(与pod不在同一网段),以供集群内部的pod之间通信使用。clusterIP也是kubernetes service的默认类型
主要需要以下几个组件的协同工作
apiservice:在创建service时,apiserver接收到请求以后将数据存储到etcd中。
kube-proxy:k8s的每个节点中都有该进程,负责实现service功能,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables中
iptables:使用NAT等技术奖virtuallp的流量转至endpoint中

方式2:NodePort
NodePort模式除了使用cluster ip外,也将service的port映射到每个node的一个指定内部的port上,映射的每个node的内部port都一样。为每个节点暴露一个端口,通过nodeIP+nodeport可以访问你这个服务,同时服务依然会有cluster类型的ip+port。内部通过clusterip方式访问,外部通过nodeport方式访问

方式3:loadbalancer
loadbalancer在nodeport基础上,k8s可以请求底层云平台创建一个负载均衡器,将每个node作为后端,进行服务分发,该模式需要底层云平台(例如GCE)支持

方式4:lngress
lngress,是一种http方式的路由转发机制由lngress controller和http代理服务器组合而成,lngress controller实例监控kubernetes api,实时更新http代理服务器的转发规则。http代理服务器有GCE load-balancer、haproxy、nginx等开源方案

​ service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务.举个例子一个a服务运行3个pod,b服务怎么访问a服务的pod,pod的ip都不是持久化的重启之后就会有变化。这时候b服务可以访问跟a服务绑定的service,service信息是固定的提前告诉b就行了,service通过Label Selector跟a服务的pod绑定,无论a的pod如何变化对b来说都是透明的.

kubernetes代理方式

​ k8s群集中的每个节点都运行一个kube-proxy的组件,kube-proxy其实是一个代理层负责实现service.kube-proxy代理模式有两种:

代理模式:userspace

​ 客户端访问ServiceIP(clusterIP)请求会先从用户空间到内核中的iptables,然后回到用户空间kube-proxy,kube-proxy负责代理工作。具体细节:
​ 每个service都会由kube-proxy在node节点上起一个随机的代理端口,iptables会捕捉clusterIP上的端口(targetPort)流量重定向代理端口,访问代理端口的任何连接都会被代理到service后端的某一个pod,默认情况下对后端pod的选择是轮询

图片1

代理模式:iptables

​ 客户端访问ServiceIP(clusterIP)请求会由iptables直接重定向到后端,具体细节:每个service都会由kube-proxy生成一组iptables规则,iptables会捕捉clusterIP上的端口(targetPort)流量重定向后端某一个pod,默认对pod的选择是随机的

图片2

​ Kubernetes v1.2之前默认是userspace之后是iptables模式,iptables模式性能和可靠性更好,但是iptables模式依赖健康检查,在没有健康检查的情况下如果一个pod不响应,iptables模式不会切换另一个pod上.

service的类型

  • ClusterIP 默认模式,只能在集群内部访问
  • NodePort 在每个节点上都监听一个同样的端口号(30000-32767),ClusterIP和路由规则会自动创建。
  • LoadBalancer 使用外部负载均衡。其实也是NodePort,只不过会把:自动添加到公有云的负载均衡当中
  • ExternalName 创建一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用
实践操作

1、创建一个deployment副本数3,然后滚动更新镜像版本,并记录这个更新记录,最后再回滚到上一个版本

[root@master kubenetres]# vim test.yml 
[root@master kubenetres]# cat test.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test01
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test01
  template:
    metadata:
      labels:
        app: test01
    spec:
      containers:
      - image: 1225514226/httpd
        name: test
        
#创建deployment类型的pod
[root@master kubenetres]# kubectl apply -f test.yml 
deployment.apps/test created

#查看
[root@master kubenetres]# kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
test-c9dcccb69-tz8zj   1/1     Running   0          2m54s
test-c9dcccb69-v9jjw   1/1     Running   0          2m54s
test-c9dcccb69-xf4gl   1/1     Running   0          2m54s

#升级(kubectl set image deployment.apps/{deployment名称} {镜像名称}:={镜像名称}:{版本})
[root@master kubenetres]# kubectl set image deploy/test test=nginx:v0.1 
deployment.apps/test image updated

#查看是否在升级
[root@master kubenetres]# kubectl get pod
NAME                    READY   STATUS              RESTARTS   AGE
test-7b9f664684-ddllz   1/1     Running             0          107s
test-7b9f664684-hcfqp   0/1     ContainerCreating   0          10s
test-c9dcccb69-4clhj    1/1     Terminating         0          9m
test-c9dcccb69-dqlg2    1/1     Running             0          9m
test-c9dcccb69-w8q7c    1/1     Running             0          9m

[root@master kubenetres]# kubectl get deployment
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
test   3/3     2            3           10m

#回滚
#默认情况下, Deployment 的上线记录都会保留在系统中,以便可以随时回滚,查看 Deployment 的上线历史记录:
[root@master kubenetres]# kubectl rollout history deployment test
deployment.apps/test 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

#查看一个版本
[root@master kubenetres]# kubectl rollout history deployment test --revision=2
deployment.apps/test with revision #2
Pod Template:
  Labels:       app=test01
        pod-template-hash=7b9f664684
  Containers:
   test:
    Image:      best2001/httpd:v0.1
    Port:       <none>
    Host Port:  <none>
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>
  
#回滚到上一个版本
[root@master kubenetres]# kubectl rollout undo deployment test --to-revision=1
deployment.apps/test rolled back
[root@master kubenetres]# kubectl rollout history deployment test
deployment.apps/test 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

2、给一个应用扩容副本数为3

[root@master kubenetres]# kubectl scale deploy/test --replicas=3
[root@master kubenetres]# kubectl get pod
NAME                   READY   STATUS        RESTARTS   AGE
test-c9dcccb69-9zvc9   1/1     Running       0          8m3s
test-c9dcccb69-gd94h   1/1     Running       0          7m44s
test-c9dcccb69-jdmhl   1/1     Running       0          7m38s
test-c9dcccb69-l6wg5   1/1     Terminating   0          119s
test-c9dcccb69-wqjfk   1/1     Terminating   0          119s

3、创建一个pod,其中运行着nginx、redis、memcached 3个容器

[root@master kubenetres]# vim test.yml 
[root@master kubenetres]# cat test.yml 
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: test01
spec:
  containers:
  - image: nginx
    name: nginx
  - image: redis
    name: redis
  - image: memcached
    name: memcached
[root@master kubenetres]# kubectl apply -f test.yml 
pod/test created
[root@master kubenetres]# kubectl get pod
NAME   READY   STATUS    RESTARTS   AGE
test   3/3     Running   0          47s

4、给一个pod创建service,并可以通过ClusterlP/NodePort访问

[root@master kubenetres]# vim test.yml 
[root@master kubenetres]# cat test.yml 
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: test01
spec:
  containers:
  - image: 1225514226/nginx:v0.3 
    name: nginx

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: test01
  type: NodePort
  
[root@master kubenetres]# kubectl apply -f test.yml 
pod/test created
service/nginx created
[root@master kubenetres]# kubectl get pod,svc
NAME       READY   STATUS    RESTARTS   AGE
pod/test   1/1     Running   0          16s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/nginx        NodePort    10.100.135.23   <none>        80:31762/TCP   16s

#ClusterIP访问
[root@master kubenetres]# curl 10.100.135.23
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
···省略部分····

#NodePort访问
[root@master kubenetres]# curl 192.168.240.30:31762
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
···省略部分····

5、创建deployment和service,使用busybox容器nslookup解析service

[root@master kubenetres]# kubectl run test1  --image=busybox:1.28.4 -- sleep 24h
pod/test1 created
[root@master kubenetres]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
test    1/1     Running   0          10m

[root@master kubenetres]# kubectl exec -it test1 -- /bin/sh
/ # nslookup kubernetes
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local

[root@master kubenetres]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        3d21h
### ### Kubernetes 中的网络暴露方式 Kubernetes 提供了多种方式用于将服务暴露给集群外部或内部的客户端,主要包括以下几种类型: #### #### 1. ClusterIP ClusterIP 是默认的 Service 类型,它为服务分配一个内部 IP 地址,仅在集群内部可访问。这种类型适用于仅在集群内部通信的场景。 ```yaml apiVersion: v1 kind: Service metadata: name: my-clusterip-service spec: type: ClusterIP selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 8080 ``` #### #### 2. NodePort NodePort 类型通过在每个节点的 IP 上开放一个特定端口,将流量转发到后端 Pod。外部客户端可以通过 `<节点IP>:<NodePort>` 访问服务。NodePort 的端口范围通常为 30000-32767,但也可以手动指定。 ```yaml apiVersion: v1 kind: Service metadata: name: my-nodeport-service spec: type: NodePort selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 8080 nodePort: 30007 ``` 这种方式适用于需要直接暴露服务到外部网络的场景,但缺乏灵活的路由规则[^5]。 #### #### 3. LoadBalancer LoadBalancer 类型通常用于云服务商环境,它在 NodePort 的基础上自动创建一个外部负载均衡器,并将流量分发到各个节点的 NodePort 上。该方式为服务分配一个外部 IP。 ```yaml apiVersion: v1 kind: Service metadata: name: my-loadbalancer-service spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 8080 ``` 这种方式适用于需要高可用和自动负载均衡的生产环境[^2]。 #### #### 4. Ingress Ingress 提供基于 HTTP/HTTPS 的路由规则,可以将外部流量路由到集群内部的多个 Service。Ingress 控制器(如 Nginx、Traefik 等)负责处理请求并进行转发。 ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: rules: - http: paths: - path: /app1 pathType: Prefix backend: service: name: app1-service port: number: 80 - http: paths: - path: /app2 pathType: Prefix backend: service: name: app2-service port: number: 80 ``` Ingress 支持路径和子域名的路由规则,适用于多服务的统一入口管理。 #### #### 5. ExternalName ExternalName 类型用于将集群外部的服务通过 DNS 别名的方式暴露给集群内部。该方式不会创建任何代理或转发规则,而是直接通过 DNS 解析到外部服务地址。 ```yaml apiVersion: v1 kind: Service metadata: name: my-externalname-service spec: type: ExternalName externalName: example.com ports: - port: 80 ``` 这种方式适用于需要将外部服务集成到集群内部 DNS 体系的场景。 #### #### 6. HostPort 和 HostNetwork HostPort 允许容器直接绑定到宿主机的端口上,使得服务可以通过 `<节点IP>:<HostPort>` 直接访问。而 HostNetwork 模式则允许容器共享宿主机的网络命名空间,从而直接使用主机网络。 ```yaml apiVersion: v1 kind: Pod metadata: name: my-hostport-pod spec: containers: - name: my-container image: nginx ports: - containerPort: 80 hostPort: 8080 ``` 这种方式适用于需要高性能或直接暴露到主机网络的特殊场景,但可能带来安全和端口冲突问题。 --- ### ### 总结 Kubernetes 提供了多种网络暴露方式,每种方式适用于不同的使用场景: - ClusterIP 适用于集群内部通信; - NodePort 和 LoadBalancer 适用于直接暴露服务到外部; - Ingress 适用于统一管理多个服务的 HTTP/HTTPS 路由; - ExternalName 用于集成外部服务; - HostPort 和 HostNetwork 适用于需要直接绑定主机端口或网络的场景。 通过合理选择这些方式,可以根据业务需求构建灵活、安全、高效的网络架构。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值