详细聊聊K8s容器内nginx带变量的域名解析

如果 nginx 的 proxy_pass 指令带有变量名的话:

server {
	server_name ~^(\w+)\.example\.com$;
	location / {
		proxy_pass http://svc-$1;
	}
}

不配置 resolver 是不能使用的(虽然可以成功加载配置):

$ curl --resolve 'a.example.com:80:127.0.0.1' a.example.com
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>

nginx 的错误日志:

[error] 615#615: *1 no resolver defined to resolve svc-a

查看当前的 resolve 配置:

$ cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.152.183.10
options ndots:5

尝试把它添加到 nginx 的配置里面:

server {
	server_name ~^(\w+)\.example\.com$;
	location / {
		resolver 10.152.183.10;
		proxy_pass http://svc-$1;
	}
}

结果是仍然不能可用:

[error] 3817#3817: *10 svc-a could not be resolved (3: Host not found)

nginx 要求配置 resolver 指令,那么可以猜测,它没有使用系统的 resolve.conf 文件,也就是:不走系统那一套来解析域名。 所以现在的差异就在于下面 search 这一行了:

search default.svc.cluster.local svc.cluster.local cluster.local

search 指令的用途:当名字无法解析时,加上这些后缀再尝试解析。

根据 K8s 的 Service 的 DNS 文章所言可以推测:

  • cluster.local 是 K8s 的 cluster_domain
  • default.svc.cluster.local 是名字空间的域名( default 是我的名字空间)

而服务的域名则是:<服务>.<名字空间域名>。

所以当我 curl svc-a 的时候,实际上返回的是 svc-a.default.svc.cluster.local 的结果:

$ host svc-a
svc-a.default.svc.cluster.local has address 10.152.183.160

$ host svc-a.default
svc-a.default.svc.cluster.local has address 10.152.183.160

$ host svc-a.default.svc
svc-a.default.svc.cluster.local has address 10.152.183.160

$ host svc-a.default.svc.cluster.local
svc-a.default.svc.cluster.local has address 10.152.183.160

看出来了吗?以上命令省略的恰好是 search 指令列出来的部分。

但是,nginx 的 resolver 不支持 search,所以应该写完整的域名。

server {
	server_name ~^(\w+)\.example\.com$;
	location / {
		resolver 10.152.183.10;
		proxy_pass http://svc-$1.default.svc.cluster.local;
	}
}

以上这样配置就没有问题了。 但是,hardcode 了一个 resolver,不好,得去掉,用服务名的方式找到 K8s DNS 的域名。 我的 K8s 的域名是 kube-dns 服务提供的,名字空间是 kube-system,所以完整的 resolver 是: kube-dns.kube-system.svc.cluster.local。

$ host kube-dns.kube-system.svc.cluster.local
kube-dns.kube-system.svc.cluster.local has address 10.152.183.10

最终的 nginx 配置:

server {
	server_name ~^(\w+)\.example\.com$;
	location / {
		resolver kube-dns.kube-system.svc.cluster.local;
		proxy_pass http://svc-$1.default.svc.cluster.local;
	}
}

其中的变量,应该按你的场景来修改:

  • kube-dns 是我的集群使用的 DNS 服务
  • kube-system 是我的 DNS 服务所在的名字空间
  • default 是我的名字空间
  • cluster.local 是集群域名(cluster_domain)

    有至少两种方式可以拿到这个集群域名:

    • /etc/resolv.conf 文件的 search 指令。
    • 这是 kubelet 的一个启动参数,可以找到你的集群启动参数来获取到。 我这里用的是 microk8s 搭建的测试集群,其中就有一个集群域名参数的值。
      $ ps aux|grep kubelet
      root      728595 16.0 11.1 3549776 872556 ?      Ssl  02:25   9:44 /snap/microk8s/2870/kubelite --scheduler-args-file=/var/snap/microk8s/2870/args/kube-scheduler --controller-manager-args-file=/var/snap/microk8s/2870/args/kube-controller-manager --proxy-args-file=/var/snap/microk8s/2870/args/kube-proxy --kubelet-args-file=/var/snap/microk8s/2870/args/kubelet --apiserver-args-file=/var/snap/microk8s/2870/args/kube-apiserver --kubeconfig-file=/var/snap/microk8s/2870/credentials/client.config --start-control-plane=true
      
      $ cat /var/snap/microk8s/2870/args/kubelet
      ...
      --cluster-domain=cluster.local
      ...
      

    由于集群域名不是变化的量,所以每次从文件里面读取并无必要(第一种方式),所以推荐第二种。

总结 

到此这篇关于K8s容器内nginx带变量域名解析的文章就介绍到这了,更多相关K8s容器内nginx域名解析内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • k8s部署ingress-nginx的方法步骤

    目录 前言 一.部署配置Ingress 二.使用https 前言 k8s集群服务部署好之后,需要对外提域名访问,这时候就需要ingress-nginx了,今天来给大家分享一下 一.部署配置Ingress 1.获取配置文件 #文件已下载到本地 https://github.com/kubernetes/ingress-nginx/tree/nginx-0.20.0/deploy 2.准备镜像 unzip ingress-nginx-nginx-0.20.0.zip cd ingress-nginx

  • 详细聊聊K8s容器内nginx带变量的域名解析

    如果 nginx 的 proxy_pass 指令带有变量名的话: server { server_name ~^(\w+)\.example\.com$; location / { proxy_pass http://svc-$1; } } 不配置 resolver 是不能使用的(虽然可以成功加载配置): $ curl --resolve 'a.example.com:80:127.0.0.1' a.example.com <html> <head><title>502

  • Kubernetes(K8S)容器集群管理环境完整部署详细教程-中篇

    本文系列: Kubernetes(K8S)容器集群管理环境完整部署详细教程-上篇 Kubernetes(K8S)容器集群管理环境完整部署详细教程-中篇 Kubernetes(K8S)容器集群管理环境完整部署详细教程-下篇 接着Kubernetes(K8S)容器集群管理环境完整部署详细教程-上篇继续往下部署: 八.部署master节点 master节点的kube-apiserver.kube-scheduler 和 kube-controller-manager 均以多实例模式运行:kube-sc

  • Kubernetes(K8S)容器集群管理环境完整部署详细教程-上篇

    Kubernetes(通常称为"K8S")是Google开源的容器集群管理系统.其设计目标是在主机集群之间提供一个能够自动化部署.可拓展.应用容器可运营的平台.Kubernetes通常结合docker容器工具工作,并且整合多个运行着docker容器的主机集群,Kubernetes不仅仅支持Docker,还支持Rocket,这是另一种容器技术.Kubernetes是一个用于容器集群的自动化部署.扩容以及运维的开源平台. 本文系列: Kubernetes(K8S)容器集群管理环境完整部署详

  • Kubernetes(K8S)容器集群管理环境完整部署详细教程-下篇

    本文系列: Kubernetes(K8S)容器集群管理环境完整部署详细教程-上篇 Kubernetes(K8S)容器集群管理环境完整部署详细教程-中篇 Kubernetes(K8S)容器集群管理环境完整部署详细教程-下篇 在前一篇文章中详细介绍了Kubernetes(K8S)容器集群管理环境完整部署详细教程-中篇,这里继续记录下Kubernetes集群插件等部署过程: 十一.Kubernetes集群插件 插件是Kubernetes集群的附件组件,丰富和完善了集群的功能,这里分别介绍的插件有cor

  • nginx自定义变量与内置预定义变量的使用

    总览 nginx可以使用变量简化配置与提高配置的灵活性,所有的变量值都可以通过这种方式引用: $变量名 而nginx中的变量分为两种,自定义变量与内置预定义变量 内置变量 声明 可以在sever,http,location等标签中使用set命令(非唯一)声明变量,语法如下 set $变量名 变量值 注意nginx中的变量必须都以$开头. 可见性 nginx的配置文件中所有使用的变量都必须是声明过的,否则nginx会无法启动并打印相关异常日志 nginx变量的一个有趣的特性就是nginx中没一个变

  • Docker容器配置Nginx实例分享

    作为目前最火的应用,Docker 确实存在着其独到之处,无论是程序猿还是运维都应该听说过 Docker 的大名,Docker 已经走过了许多的坑,目前最新版本是 v1.11.0 版本,应该说是完全能承载开发使用和运维监控,这款工具能帮助我们高效的打包.发布和运行承载着应用程序的容器系统.而且收集日志.帮助 App 的快速开发都有很大作用. 容器和虚拟机,经常是被拿出来对比的两款产品,实际上两者有着根本的差别,虚拟机是完全模拟了一台真实计算机,在上面运行的系统可能或者不可能知道自己运行在虚拟化环境

  • 把数据库部署在docker容器内有哪些缺陷

    前言 近2年Docker非常的火热,各位开发者恨不得把所有的应用.软件都部署在Docker容器中,但是您确定也要把数据库也部署的容器中吗? 这个问题不是子虚乌有,因为在网上能够找到很多各种操作手册和视频教程,小编整理了一些数据库不适合容器化的原因供大家参考,同时也希望大家在使用时能够谨慎一点. 目前为止将数据库容器化是非常不合理的,但是容器化的优点相信各位开发者都尝到了甜头,希望随着技术的发展能够更加完美的解决方案出现. Docker不适合部署数据库的7大原因 1.数据安全问题 不要将数据储存在

  • 有关perl的内置特殊变量介绍

    一.正则表达式特殊变量 1.$n :包含上次模式匹配的第n个子串2.$& :前一次成功模式匹配的字符串3.$` :前次匹配成功的子串之前的内容4.$' :前次匹配成功的子串之后的内容5.$+ :前一次使用括号的模式匹配的字符串. 二.文件句柄特殊变量 1.$| :如果设置为零,在每次调用函数write或print后,自动调用函数fflush,将所写内容写回文件2.$% :当前输出页号3.$= :当前每页长度4.$- :当前页剩余的行数5.$~ :当前报表输出格式的名称.默认值是文件句柄名.6.$

  • Perl内置特殊变量总结

    [ 文件句柄 ] $| 如果非零, 则在对当前选定的文件执行写或打印操作后强制清除缓冲区$% 当前选中文件句柄的当前页码$= 当前选中文件句柄的当前页面长度$- 当前选中文件句柄的页面剩余长度$~ 当前选中文件句柄的报表格式名称$^ 当前选中文件句柄的当前页眉格式名 [ 全局变量 ] $_ 默认的输入和模式搜索空间$@ 上一个 eval.do 或 require 函数产生的错误消息$/ 输入记录的分隔符, 默认为换行符(类似于 awk 中的 RS)$\ 打印函数的输入记录分隔符. 除非设置了 $

  • Docker容器内应用服务自启动的方法示例

    如果想把Docker容器内的应用服务随着容器开启时自启动.只需要将服务启动的脚本写在Dockerfile里,然后用Dockerfile重构镜像即可实现: 编写应用服务自启动脚本 编写Dockerfile 重构镜像 开启容器 编写服务自启动脚本(dockerd) (tomcat为例) #!/bin/bash # # # # chkconfig: 345 98 30 # description: tomcat program. # processname: tomcat # Source funct

随机推荐