十、IPVS模型分析
1、会在每个节点上创建一个名为kube-ipvs0的虚拟接口,并将集群所有Service对象的ClusterIP都配置在该接口:2、Kube-Proxy将每个Service生成一个虚拟服务器VirtualServer的定义;
注意:ipvs仅需要借助极少量的iptables规则完成源地址转换、源端口转换等;
1、设置集群为IPVS模式
1.1 修改ipvs模式
kubectl edit configmaps kube-proxy -n kube-system
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
strictARP: false
syncPeriod: 0s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: "ipvs" #指定ipvs规则
1.2、删除kube-proxy的pod,重启kube-proxy
kubectl delete pod $(kubectl get pod -n kube-system | grep proxy | awk '{print $1}') -n kube-system
kubectl delete pod $(kubectl get pod -l k8s-app=kube-proxy -n kube-system | awk 'NR>1 {print $1}') -n kube-system
# 只删除第2和第三个pod
kubectl delete pod $(kubectl get pod -l k8s-app=kube-proxy -n kube-system | awk 'NR==3 || NR==4 {print $1}') -n kube-system
1.3 IPVS 规则查看
## 全部规则查看
ipvsadm -L -n
## IPVS的映射网卡查看
ip a s ## 查看网卡
kubect get svc ## 查看svc
如图所示,正式映射关系
十一、服务发现
当Pod需要访问Service时,通过Service提供的ClusterIP就可以实现了,但是有几个问题;
1、Service的IP不稳定,删除重建会发生变化;
2、ServiceIP难以记忆,如果能通过一个固定的名称访问就好了;
为了解决这样的问题,Kubernetes引入了环境变量和DNS两种方案来解决这样的问题;
1、环境变量方式:通过特定的名称将环境变量注入到Pod内部;
2、DNS方式:通过APIServer来监视Service变动,而后动态创建对应Service名称与ServiceIP的域名解析记录;
1、环境变量
每个 Pod 启动的时候,会通过环境变量的方式将Service的IP以及Port信息注入进去,这样 Pod 中的应用可以通过读取环境变量来获取对应Service服务的地址信息,这种方法使用起来相对简单,但是也存在一定的问题。就是Pod所依赖的Service必须优Pod启动,否则无法注入到环境变量中。
kubectl run tools --image=registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
kubectl exec -it tools -- /bin/bash
env | grep -i demoapp_svc
ping ${DEMOAPP\_SVC\_SERVICE\_HOST}
在创建一个svc。pod就无法获取到svc的环境变量
apiVersion: v1
kind: Service
metadata:
name: env-svc
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
pod无法获取新创建的svc的环境变量信息
但是再新创建一个pod就会能或者svc的变量信息
重新创建一个pod,能够或者两个svc的环境变量,这就是环境变量的作用
2、CoreDNS
在安装Kubernetes集群时,CoreDNS作为附加组件,用来为Pod提供DNS域名解析。CoreDNS监视 Kubernetes API 中的新Service,并为每个Service名称创建一组 DNS 记录。这样我们就可以通过固定的Service名称来转换出不固定的ServiceIP
了解CoreDNS的配置
[root@master service]# kubectl get configmap -n kube-system ## 查看所有的配置信息
NAME DATA AGE
coredns 1 97d
extension-apiserver-authentication 6 97d
kube-flannel-cfg 2 97d
kube-proxy 2 97d
kube-root-ca.crt 1 97d
kubeadm-config 1 97d
kubelet-config-1.23 1 97d
[root@master service]# kubectl get configmaps coredns -n kube-system -o yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors ## 错误记录
health { ## 监控检查
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa { ## 用于解析kubernetes集群内域名
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153 ## 监控端口
forward . /etc/resolv.conf { # 如果请求非Kubernetes域名,则由节点的resolv.conf中dns解析
max\_concurrent 1000
}
cache 30 # 缓存所有内容
loop
reload # 支持热更新
loadbalance # 负载均衡,默认轮询
}
kind: ConfigMap
metadata:
creationTimestamp: "2023-12-15T16:08:05Z"
name: coredns
namespace: kube-system
resourceVersion: "233"
uid: 6fe29dab-17db-45f6-a7eb-70a08724337b
默认的域名解析配置
解析svc域名
总结:可以解析到对应的svcIP
总结:删除svc时,svc的ip就会发生变化,但是重新对svc的域名进行解析,仍然能够解析到svc的ip。只要service的名称不发生变化,就可以正常解析,所有可以将这个注入到pod的中,就可以解析svc的配置。这个DNS是通过cordDNS进行转发解析的。
十二、CordDNS策略
DNS策略可以单独对Pod进行设定,在创建Pod时可以为其指定DNS的策略,最终配置会落在Pod的/etc/resolv.conf文件中,可以通过pod.spec.dnsPolicy字段设置DNS的策略
1、ClusterFirst(默认DNS策略)
表示Pod内的DNS使用集群中配置的DNS服务,简单来说就是使用Kubernetes 中的 coredns 服务进行域名解析。如果解析不成功,会使用当前Pod所在的宿主机 DNS 进行解析。
apiVersion: v1
kind: Pod
metadata:
name: pod-example-1
spec:
dnsPolicy: ClusterFirst
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
ports:
- containerPort: 8899
查看pod的DNS的策略
总结: 使用默认DNS解析
2、ClusterFirstWithHostNet
在某些场景下,我们的 Pod 是用 HostNetwork 模式启动的,一旦使用 HostNetwork 模式,那该Pod则会使用当前宿主机的/etc/resolv.conf来进行 DNS 查询,但如果任然想继续使用Kubernetes的DNS服务,那就将 dnsPolicy设置为ClusterFirstWithHostNet
- 为了方便验证,将三个node的主机域名解析都缓存不一样的的
vim /etc/resolv.conf
### node1
nameserver 233.5.5.5
### node2
nameserver 233.6.6.6
### node3
nameserver 114.114.114.114
apiVersion: v1
kind: Pod
metadata:
name: pod-example-2
spec:
hostNetwork: true ## 与主机共享网络
dnsPolicy: ClusterFirst
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8899
- 通过指定node标签,让pod创建到指定的node上
kubectl get node --show-labels
apiVersion: v1
kind: Pod
metadata:
name: pod-example-2
spec:
hostNetwork: true
dnsPolicy: ClusterFirst
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8899
nodeSelector:
kubernetes.io/hostname: node2
通过指定不的node便签进行创建pod,可以看到共享不同pod主机域名解析
pod无法通过svc进行解析,可以dnsPolicy规则改为ClusterFirstWithHostNet
apiVersion: v1
kind: Pod
metadata:
name: pod-example-2
spec:
hostNetwork: true ## 共享主机网络
dnsPolicy: ClusterFirstWithHostNet ## 如果配置了首要配置kubernetes的域名解析
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8899
nodeSelector:
kubernetes.io/hostname: node3
- 这个ClusterFirstWithHostNet策略也适用deployment
- 编写deployment的资源清单
apiVersion: apps/v1
kind: Deployment
metadata:
name: demoapp
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
hostNetwork: true
dnsPolicy: ClusterFirst
containers:
- name: webservers
image: oldxu3957/demoapp:v1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: demoapp-svc
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 32000
域名解析能解析到node3的主机 /etc/resolv.conf
3、default
默认使用宿主机的 /etc/resolv.conf但可以使用 kubelet 的 --resolv-conf=/etc/resolv.conf 来指定 DNS 解析文件地址。
- 使用默认主机的 /etc/resolv.conf
apiVersion: v1
kind: Pod
metadata:
name: pod-example-3
spec:
dnsPolicy: Default
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
ports:
- containerPort: 8899
nodeSelector:
kubernetes.io/hostname: node3
使用了node3的 /etc/resolv.conf 的默认主机名认证
- 使用node节点的指定路径的域名解析的文件,使用主机挂载方式
apiVersion: v1
kind: Pod
metadata:
name: pod-example-6
spec:
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: resolv-conf
mountPath: /etc/resolv.conf
readOnly: true
dnsPolicy: Default
dnsConfig:
options:
- name: ndots
value: "2"
volumes:
- name: resolv-conf
hostPath:
path: /root/resolv.conf
nodeSelector:
kubernetes.io/hostname: node3
- 将域名添加到,并执行域名解析的ip,我特定的域名地址
apiVersion: v1
kind: Pod
metadata:
name: pod-example-4
spec:
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
dnsPolicy: Default
dnsConfig:
nameservers:
- 10.0.0.1
- 10.0.0.2
searches:
- /etc/resolv.conf
- otherdomain.svc.cluster.local
nodeSelector:
kubernetes.io/hostname: node2
4、Node
空的DNS设置,这种方式一般用于自定义 DNS 配置的场景,往往需要和dnsConfig一起使用才可以达到自定义DNS的目的。
apiVersion: v1
kind: Pod
metadata:
name: pod-example-7
spec:
containers:
- name: tools
image: registry.cn-hangzhou.aliyuncs.com/mokeyking/k8s-oldxu:tools-latest
imagePullPolicy: IfNotPresent
dnsPolicy: None
dnsConfig:
nameservers:
- 233.5.5.5
- 233.6.6.6
searches:
- mydomain.com
- otherdomain.svc.cluster.local
- king.net
nodeSelector:
kubernetes.io/hostname: node1
十三、HeadLess Service
1、什么是HeadLess
HeadlessService也叫无头服务,就是创建的Service没有ClusterIP,而是为Service所匹配的每个Pod都创建一条DNS的解析记录,这样每个Pod都有一个唯一的DNS名称标识身份,访问的格式如下
2、HeadLess的作用
像 elasticsearch,mongodb,kafka 等分布式服务,在做集群初始化时,配置文件中要写上集群中所有节点的IP(或是域名)但Pod是没有固定IP的,所以配置文件里写DNS名称是最合适的。
那为什么不用Service,因为 Service 作为 Pod 前置的负载均衡一般是为一组相同的后端 Pod 提供访问入口,而且 Service的selector也没有办法区分同一组Pod的不同身份。
但是我们可以使用 Statefulset控制器,它在创建每个Pod的时候,能为每个 Pod 做一个编号,就是为了能区分这一组Pod的不同角色,各个节点的角色不会变得混乱,然后再创建 headless service 资源,集群内的节点通过Pod名称+序号.Service名称,来进行彼此间通信的只要序号不变,访问就不会出错。
当statefulSet.spec.serviceName 配置与headless service相同时,可以通过 {hostName}.fheadless service}.{namespace}.svc.cluster.local 解析出节点IP。hostName 由{statefulSet name}-{编号}组成。
{statefulSet name}-{编号}.{headless service}{namespace}.svc.cluster.local
# 放在当前es中,对应的DNS子域名分别是
es-0.elastic.default.svc.cluster.local
es-1.elastic.default.svc.cluster.local
es-2.elastic.default.svc.cluster.local
3、HeadLess示例
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
clusterIP: "None"
selector:
app: nginx
ports:
- port: 80
targetPort: 80
- 编写pod资源
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "myapp"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: xx
image: nginx:1.16
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- 使用tools 进行验证测试
kubectl exec -it tools -- /bin/bash
- ping myapp.default.svc.cluster.local 可以轮询到不同的pod上。
- ping web-1.myapp.default.svc.cluster.local 使用这个可以解析到指定的pod上
4、HeadLess测试
总结: 通过删除pod。依旧可以通过域名的方式进行解析
十四、guestBook案例实践
guestBook官网示例
guestBook的GitHub地址
1、场景描述
- 1、启动 Redis、领导 者(Leader)
- 2、启动两个 Redis 跟随者(Follower)
- 3、启动并公开 GuestBook 服务,数据写入Redis Leader节点数据读取统一写入Redis Slave节点
- 3.1 如果 GET HOSTS_FROM 设置为 env,则需要手动传递Redis Master、以及Slave的 Service名称;
REDIS LEADER SERVICE HOST # 传递Leader节点的Service名称或IP
REDIS FOLLOWER_SERVICE_HOST # 传递 Follower节点Service的名称或IP - 3.2 如果 GET HOSTS_FROM 设置为 dns,则站点会自动初始化两个变量,这就要求创建service时的名称得固定;
$host =‘redis-leader’;
$host =‘redis-follower’;
2、部署Redis-Leader
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-leader # Deployment Pod的名称
spec:
replicas: 1
selector:
matchLabels:
app: redis-master
template:
metadata:
labels:
app: redis-master
spec:
containers:
- name: redis-container
image: redis
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-leader
spec:
type: ClusterIP
selector:
app: redis-master
ports:
- port: 6379
targetPort: 6379
3、部署redis-follower
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-follower
spec:
replicas: 2
selector:
matchLabels:
app: redis-slave
template:
metadata:
labels:
app: redis-slave
spec:
containers:
- name: redis-slave
image: redis
command: ["redis-server"]
args:
- --port 6379
- --slaveof redis-leader 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-follower
spec:
type: ClusterIP
selector:
app: redis-slave
ports:
- port: 6379
targetPort: 6379
4、部署guestbooks的deploy和service
apiVersion: apps/v1
kind: Deployment
metadata:
name: guestbooks
spec:
replicas: 3
selector:
matchLabels:
app: books
template:
metadata:
labels:
app: books
spec:
containers:
- name: books-container
# image: oldxu3957/guestbook:v5
image: uhub.service.ucloud.cn/oldxu/guestbook:v7
env:
- name: GET_HOSTS_FROM
value: "env"
- name: REDIS_LEADER_SERVICE_HOST
value: "redis-leader"
- name: REDIS_FOLLOWER_SERVICE_HOST
value: "redis-follower"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: guestbook-svc
spec:
type: NodePort
selector:
app: books
ports:
- name: http
port: 80
targetPort: 80
nodePort: 32002
将redis的server的环境变量注册到Guesbook的环境变量中
登陆redis从库查看数据
5、使用Ingress部署guestbooks
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: books-ingress
spec:
ingressClassName: "nginx"
rules:
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Linux运维工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/2b2c236a4f0f56463361a00c0e9ab5c1.png)
![img](https://img-blog.csdnimg.cn/img_convert/8aa2b9b95ecaac7dd974ed87c5ead87a.png)
![img](https://img-blog.csdnimg.cn/img_convert/420c13de5bcd657dec4149a22b2e0348.png)
![img](https://img-blog.csdnimg.cn/img_convert/fc91a80cb868c186479fcb8e6161b4b7.png)
![img](https://img-blog.csdnimg.cn/img_convert/96bccf15c34149ff11d2acf95403123b.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Linux运维知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加VX:vip1024b (备注Linux运维获取)**
![img](https://img-blog.csdnimg.cn/img_convert/7946a56113569a21ab7d90b22a39bbf0.jpeg)
### 最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
### 资料预览
给大家整理的视频资料:
![](https://img-blog.csdnimg.cn/img_convert/1481cc5cbeaf7e5caccb4a802063482e.png)
给大家整理的电子书资料:
![](https://img-blog.csdnimg.cn/img_convert/1c75dc6d44af8e17642974d7be0bb660.png)
**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
![img](https://img-blog.csdnimg.cn/img_convert/07ea451fc03978bf58310dc900f41ebc.jpeg)
望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中...(img-meuM9DrC-1712504049894)]
[外链图片转存中...(img-sa25HJVl-1712504049895)]
[外链图片转存中...(img-QtQtm7cD-1712504049896)]
[外链图片转存中...(img-5jVGMOSg-1712504049896)]
[外链图片转存中...(img-llPZN8K0-1712504049897)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Linux运维知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加VX:vip1024b (备注Linux运维获取)**
[外链图片转存中...(img-XtLxi8RB-1712504049897)]
### 最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
### 资料预览
给大家整理的视频资料:
[外链图片转存中...(img-DhR8xThF-1712504049897)]
给大家整理的电子书资料:
[外链图片转存中...(img-4cd1P0XS-1712504049898)]
**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
[外链图片转存中...(img-G6UqZtFR-1712504049898)]