service
service存在的意义
1 防止pod失去联系(服务发现)
2 定义一组pod的访问策略(负载均衡)
通过label-selector相关联(标签关联)
通过service实现pod的负载均衡(tcp/UDP/只能支持4层)
service只支持4层负载均衡
4层: OSI中的传输层, TCP/UDP协议 只负责数据包的转发
7层: OSI中的应用层 http fTP 可以拿到这些协议头部信息 可以实现基于协议层面的处理
service的三种常用的类型
ClusterIP 集群内部使用
clusterIP 默认分配一个稳定的IP 即VIP 只能在集群内部访问 (同Namespace内的pod)
NOdePort 对外部暴露应用
NoPort访问流程
[ USER > 域名 > node ip+port > iptables/ipvs > pod]
LoadBalancer 对外暴露应用 适合公有云
LoadBalancer访问流程
[user > 域名 > 公有云的slb (自动配置端口) > node:ip:port > pod]
userspace 自己用户实现的转发
iptables 阻止ip通信 端口映射 跟踪包状态 数据包的修改
ipvs LVS 就是基于ipvs模块做的4层负载均衡器
kube-proxy
1:实现数据包的转发
2:将service相关的规则落地现实
iptables规则:
Nodeport -> KUBE-SVC-RRHDV4CFXHW7RWV3 -> KUBE-SEP-XE5XFBDN7LLHNVMO -> -j DNAT --to-destination 10.244.2.2:80
clusterip -> KUBE-SVC-RRHDV4CFXHW7RWV3 -> KUBE-SEP-XE5XFBDN7LLHNVMO -> -j DNAT --to-destination 10.244.2.2:80
-A KUBE-SVC-RRHDV4CFXHW7RWV3 -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-BGV4R4Y32WAZO4AD
-A KUBE-SVC-RRHDV4CFXHW7RWV3 -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XE5XFBDN7LLHNVMO
-A KUBE-SVC-RRHDV4CFXHW7RWV3 -j KUBE-SEP-CYUFO3BNAYR2R5O3
上面是转发到3个pod规则。
轮训
ip_vs启动
lsmod|grep ip_vs 查看ip_vs是否启动
modprobe ip_v 启动ipvs
启动模块 ip_vs
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack_ipv4
在每一个机器上面执行一遍 把这些启动的模块加入到 [etc/rc.local]里面开机启动
通过 kubectl get cm -n kube-system 查看kube-porxy
通过 kubectl edit cm kube-porxy -n kube-system 修改启动ipvs mode"ipvs"
lvs 虚拟服务器 真实服务器
TCP 10.96.0.1:443 rr
-> 192.168.195.110:6443 Masq 1 0 0
TCP 10.96.0.10:53 rr
-> 10.244.1.6:53 Masq 1 0 0
-> 10.244.1.7:53 Masq 1 0 0
TCP 10.96.0.10:9153 rr
-> 10.244.1.6:9153 Masq 1 0 0
-> 10.244.1.7:9153 Masq 1 0 0
UDP 10.96.0.10:53 rr
-> 10.244.1.6:53 Masq 1 0 0
-> 10.244.1.7:53 Masq 1 0
ipvs 通过 虚拟的vip 流量首先会到ipvs的虚拟服务器 在通过虚拟服务器 转发给真实服务器
通过 yum install ipvsadm -y 安装ipvs的用户端看见当前状态和转发规则
iptables
灵活强大 规则遍历匹配和更新慢 呈线性时延
ipvs
工作在内核 有更好的性能
调度算法丰富 rr wrr lc wlc ip hash
ipvs 在部署 pod多的时候 客园切换因为调度快规则匹配少
有ipvs以后iptables的规则不要清空因为 ipvs还是需要通过iptables转发流量到ipvs
service DNS
程序比写死ip更好的方式
1. dns解析
2. 绑定hosts
coreDNS pod -> 获取server (apiserver 获取) -> 更新到本地
kubelet 运行pod > pod 默认走> coreDNS pod >
[1. 采用Nodeport 对外暴露应用 前面加一个LB实现统一访问入口]
[2. 优秀使用IPVS 代理模式]
[3. 集群内部采用dns名称访问]、
web.default.svc.cluster.local 名称.命名空间.svc.默认域
ingress
[nodeporet存在的不足
一个端口只能一个服务去使用 端口需要提前规划
只支持4层负载均衡]
pod与ingress的关系
[通过 service相联
通过ingress Controll现实pod的负载均衡
支持tcp/udp4层和http7层]
ingress访问流程
user > 域名 >
node: ip:80/443 > ingress controller > 域名分流 > pod
ingress
基于URL路由到多个服务类式nginx的反向代理
[apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: url-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foobar.ctnrs.com
http:
paths:
- path: /foo
backend:
serviceName: service1
servicePort: 80
- host: foobar.ctnrs.com
http:
paths:
- path: /bar
backend:
serviceName: service2
servicePort: 80]
ingress 基于虚拟机主机
配置两个域名 主机就可以了
[apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.ctnrs.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: bar.ctnrs.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80]
Annotations对Ingress个性化配置
+超时时间
[apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: "nginx“
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
rules:
- host: example.ctnrs.com
http:
paths:
- path: /
backend:
serviceName: web
servicePort: 80]
ingress controller pod -> 获取service(apiserver)-> 应用到本地nginx
1、控制器获取service关联的pod应用到nginx
2、nginx 提供七层负载均衡
ingress controller 高可用方案
1. 使用 Daemonset+nodeselector
固定ingress到两个nodes上
访问逻辑
user > 域名解析到 > vip (keepalived) ha功能 > pod
2.
固定ingress到N个nodes上 因并发定
user > 域名 > LB (nginx lvs haproxy) > ingress controller > pod
360 调度流程
lvs(定制开发的lvs控制器 对接lvs的api) > pod
应用程序管理配置
secret
加密数据并存放在ETCD中 让pod容器以挂载volume的方式 去访问
应用场景 凭据
pod使用 secret的两种方式
变量注入
挂载
secret的应用场景
1. ingress https证书
2. secret 存放docker registry认证信息
3. 存放文件内容或者是字符串
configmap 主要是使用文件传入 和secret的使用场景不一样
[参数
docker-registry 创建一个给 Docker registry 使用的 secret
generic 从本地 file, directory 或者 literal value 创建一个 secret
tls 创建一个 TLS secret
用法
kubectl create secret [flags] [options]]
---
用户名 密码这些必须通过base64转过 因为这样子比较安全
echo -n 'admin' | base64
---
创建一个secret
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
----
引入secret变量
[apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx
env:
- name: secret_user
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: secret_passwd
valueFrom:
secretKeyRef:
name: mysecret
key: password]
~
-------------------------------------
secret通过挂载的方式
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
~
----------------------------
应用程序如何动态更新配置
1. 重新构建pod
2. 应用程序本身实现监听本地配置文件 如果发生变化触发配置热更新
3. 使用 sidecal容器是否触发更新 如果发生变化触发 socket http 通知应用程序热更新
采用配置中心的 例如 nacos apollo
------------------------------