Pod IP仅仅是集群内可见的虚拟IP,外部无法访问。
Pod IP会随着Pod的销毁而消失,当ReplicaSet对Pod进行动态伸缩时,Pod IP可能随时随地都会变化,这样对于我们访问这个服务带来了难度。
因此,Kubernetes中的Service对象就是解决以上问题的实现服务发现核心关键。
在Serivce定义时,我们需要指定spec.type字段,这个字段拥有四个选项:
● ClusterIP:默认值。给这个Service分配一个Cluster IP,它是Kubernetes系统自动分配的虚拟IP,因此只能在集群内部访问。
● NodePort:将Service通过指定的Node上的端口暴露给外部。通过此方法,访问任意一个NodeIP:nodePort都将路由到ClusterIP,从而成功获得该服务。
● LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort。此模式只能在云服务器(AWS等)上使用。
● ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。需要 kube-dns 版本在 1.7 以上。
● userspace 代理模式
● iptables 代理模式
● ipvs 代理模式:
这种模式,kube-proxy 会监视 Kubernetes Service 对象和 Endpoints ,调用 netlink 接口以相应地创建 ipvs 规则并定期与 Kubernetes Service 对象和Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一 致。访问服务时,流量将被重定向到其中一个后端 Pod 。与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意 味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:
rr :轮询调度
lc :最小连接数
dh :目标哈希
sh :源哈希
sed :最短期望延迟
nq : 不排队调度
ingress controller
将新加入的Ingress转化成Nginx的配置文件并使之生效
ingress服务
将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可
1.ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,
2.然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,
3.再写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,
4.然后reload一下使配置生效。以此达到域名分配置和动态更新的问题。
官网:https://kubernetes.github.io/ingress-nginx/deploy/#quick-start
github:https://github.com/kubernetes/ingress-nginx/tree/nginx-0.30.0/deploy
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
$ ll
总用量 12
-rw-r--r-- 1 root root 6637 9月 16 23:46 mandatory.yaml
-rw-r--r-- 1 root root 471 9月 16 23:36 service-nodeport.yaml
#修改mandatory.yaml修改kind为daemonset,ingress-controller镜像地址修改为阿里云地址,添加imagePullPolicy策略,并指定hostPort,将宿主机的80、443映射到容器的80与443
........
apiVersion: apps/v1
kind: DaemonSet
.............
spec:
#replicas: 1
........
- name: nginx-ingress-controller
image: registry.aliyuncs.com/google_containers/nginx-ingress-controller:0.30.0
imagePullPolicy: IfNotPresent
........
ports:
- name: http
containerPort: 80
protocol: TCP
hostPort: 80
- name: https
containerPort: 443
protocol: TCP
hostPort: 443
............
$ cat nginx-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: registry.sudytech.com:35000/library/nginx:1.15.9
ports:
- containerPort: 80
#创建ingress服务
$ cat ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
spec:
rules:
- host: www.aaa.com
http:
paths:
- backend:
serviceName: nginx-service
servicePort: 80
path: /
#serviceName对应nginx-deployment.yaml文件中Service的标签
#做本地测试即可
#自签发证书,可以使用下面的语句,也可以阅读自制https的博客
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/O=aaa/CN=*.aaa.com"
$ ll
总用量 8
-rw-r--r-- 1 root root 1131 9月 19 16:30 tls.crt
-rw-r--r-- 1 root root 1704 9月 19 16:30 tls.key
#导入证书文件到k8s secret(注意这边的nginx-test要和下面ingress.yaml文件中tls相对应)
$ kubectl create secret tls nginx-test --cert=tls.crt --key=tls.key
$ kubectl get secret
NAME TYPE DATA AGE
nginx-test kubernetes.io/tls 2 53m
#创建https的ingrss.yaml文件
$ cat ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false" #是否开启强制跳转,true/false,默认开启
spec:
tls:
- hosts:
- www.aaa.com
secretName: nginx-test
#- hosts: 多域名配置
# - www.bbb.com
# secretName: nginx-bbb
rules:
- host: www.aaa.com
http:
paths:
- backend:
serviceName: nginx-service
servicePort: 80
path: /
# - host: www.bbb.com
# http:
# paths:
# - backend:
# serviceName: nginx-service
# servicePort: 80
# path: /
Ingress-nginx与Service之间通过匹配serviceName绑定
Service相当于给外界提供访问pod的端口,如果不采用ingress-nginx,那么是由kube-proxy实现4层代理,只能通过ip访问,所以由NodePort的类型将端口暴露。如果采用ingress-nginx相当于在Service前面加了一层代理,访问会先经过ingress-nginx,这样Service的类型就不需要变更为NodePort,
两者之间通过标签关联,spec.template.metadata.labels为pod打上名为mediaplus-main的标签,Service的spec.selector需要与spec.template.metadata.labels值一致
apiVersion: v1
kind: Service
metadata:
name: mediaplus-main
labels:
app: mediaplus-main
spec:
..............
selector:
app: mediaplus-main
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mediaplus-main
spec:
replicas: 1
selector:
matchLabels:
app: mediaplus-main
template:
metadata:
labels:
app: mediaplus-main
spec:
containers:
- name: mediaplus-main
Service只能实现四层代理 传输层,基于IP和端口
Ingress可以实现七层代理 应用层,基于应用协议转发,例如http协议
Ingress与Service之间通过匹配serviceName绑定,metadata.labels为Service打上mediaplus-main的标签,spec.rules.backend.serviceName的值需要与mediaplus-main保持一致
apiVersion: v1
kind: Service
metadata:
name: mediaplus-main
labels:
app: mediaplus-main
spec:
..............
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
tls:
- secretName: sign-secret
rules:
.........
- backend:
serviceName: mediaplus-main
servicePort: 3000
path: /