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的选择是轮询
代理模式:iptables
客户端访问ServiceIP(clusterIP)请求会由iptables直接重定向到后端,具体细节:每个service都会由kube-proxy生成一组iptables规则,iptables会捕捉clusterIP上的端口(targetPort)流量重定向后端某一个pod,默认对pod的选择是随机的
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: best2001/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: best2001/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