天坑

忍一时风平浪静,退一步越想越气……
——调到半夜而愤怒的nofyso

集群内DNS解析的问题

在我试图在Pod里使用域名来连接Redis服务的时候,发现了一个很奇怪的问题,就是Pod居然解析不到Redis的Service域名的IP……
然后,我使用了以下命令创建了一个临时测试Pod:

1
kubectl -n kube-system run dns-debug --rm -it --image=ghcr.io/nicolaka/netshoot:latest -- sh

这个命令可以创建一个临时的用于网络测试的Pod,然后我在这个Pod的命令行内使用了nslookup和dig,之后,我发现一件匪夷所思的现象:
无论我nslookup test-release-redis-master还是nslookup test-release-redis-master.dev-test.svc.cluster.local,结果始终返回NXDOMAIN,但是nslookup cn.bing.com类似的命令又可以跑通……
接下来就是各种求助AI,排查了业务Pod的/etc/resolv.conf/etc/nsswitch.conf发现没有问题;查看了core-dns的配置,也没有问题;检查了Endpoint的配置,同样没有问题……
这时候我都快疯了
直到我尝试性的关掉了宿主机上V2Ray的TUN模式,发现所有的DNS都解析的通了……
仔细想想好像还真是——为了对抗DNS污染,TUN模式说不定把我集群内的DNS流量全部劫走并转发到外部DNS解析了,在外部DNS下,显然无法解析出集群内部域名的IP,但是解析出一些外部域名反而轻而易举……
解决方法?不用TUN模式就可以了……

更多更多的组件!

呼……终于可以继续推进了吗……

helm,组装!

是时候给我们的helm包添加更多的依赖了,先从数据库开始吧!
首先,在我们的Chart.yaml里添加上依赖:

1
2
3
4
5
6
7
dependencies:
- name: redis
version: 23.x.x
repository: https://charts.bitnami.com/bitnami
- name: postgresql
version: 18.x.x
repository: https://charts.bitnami.com/bitnami

哦对了,确定好版本之后,记得把23.x.x的版本号改为具体的版本!
然后拉取依赖

1
helm dependency update

这样,我们应该可以在charts/目录下看到下载下来的包
接着修改我们的配置文件values.yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
redis:
auth:
enabled: false # 为了调试方便,先把auth关掉
master:
persistence:
enabled: false # 我们的工作队列不需要持久化,所以把持久化关掉
replica:
replicaCount: 0 # 为了方便,我们暂时不需要replica来保证高可用

postgresql:
auth: # 在这里设置账号密码和数据库名字,懒得用Secret了
username: appuser
password: apppass
database: appdb
primary:
persistence:
enabled: true # 这个可得持久化
# storageClass: local-storage # 至于这个是啥,我们之后说
# size: 10Gi

诶诶??

然后,我们使用helm install ...这种命令来将我们的helm包部署上去
之后,你很快就会发现Redis成功拉起来了,但是PostgreSQL失败了
原因很简单,因为我们想让PostgreSQL具有持久化,但是我们根本没有提供让它持久化的地方,也就是PV
为了方便(以及你知道的我们现在还是单节点集群),我们先创建一个LocalPV给我们的PostgreSQL解解馋:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-local-pv
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage # 这里可以随便写,保证记得住就可以了
local:
path: /mnt/k8s/postgres # 别忘了创建对应的目录并修改权限!
# 为了增加那么一丁点的兼容性,我们配置一个节点亲和来防止数据库漂走了
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node # 这里改成node的具体名称

这个时候,我们再修改values.yaml下postgresql底下原本注释掉的那两行,将其改成对应的值,然后更新release就可以了
哦对了,你可能还发现了,PostgreSQL的Pod下连着一个PVC,如果操作正确的话,它的Status会变成Bound才对……

与此同时,另一边……

而这时我们的业务Pod小可爱还根本不知道我们的Redis和PostgreSQL到底在哪里,所以最后一步就是将这些参数注入给Pod啦~
修改deployment.yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "cuscuta.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "cuscuta.name" . }}
template:
metadata:
labels:
app: {{ include "cuscuta.name" . }}
spec:
containers:
- name: app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8080
env:
- name: BASE_PATH
value: {{ .Values.ingress.path }}
# 这里这里~ 加上对应的环境变量吧!
- name: POSTGRES_HOST
value: '{{ tpl .Values.deps.postgresql.host . }}'
- name: POSTGRES_PORT
value: {{ .Values.deps.postgresql.port | quote }}
- name: REDIS_HOST
value: '{{ tpl .Values.deps.redis.host . }}'
- name: REDIS_PORT
value: {{ .Values.deps.redis.port | quote }}
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace

然后再修改values.yaml,加上:

1
2
3
4
5
6
7
8
# 如果你使用了 fullnameOverride,请同步修改 deps.postgresql.host
deps:
postgresql:
host: "{{ .Release.Name }}-postgresql"
port: 5432
redis:
host: "{{ .Release.Name }}-redis-master"
port: 6379

为了防止用户nameOverride或者fullnameOverride,我们配置了类似{{ tpl .Values.deps.postgresql.host . }}的配置,这样,如果用户配置了这些重写参数,他们就可以更改values的这些值来适配他的更改