【kubernetes】Deployment中的pod如何进行域名解析
背景假设一个名为ws的无状态服务,在业务代码中,服务需要根据hostname解析本机ip,并绑定端口启动监听进程, 例如:import socketdef get_hostname():with open("/etc/hostname") as f:return f.read().strip()ip = socket.gethostbyname(get_hostname())server = so
背景
假设一个名为ws的无状态服务,在业务代码中,服务需要根据hostname解析本机ip,并绑定端口启动监听进程, 例如:
import socket
def get_hostname():
with open("/etc/hostname") as f:
return f.read().strip()
ip = socket.gethostbyname(get_hostname())
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, 9999))
server.listen(10)
在上面的代码中, 只在‘ip’这一个地址上进行监听。 开启监听后,会将 <主机名>.mgmt.pix.yun.com:9999注册到zk, 使其他服务从zk中取得, 作为目标进行访问。容器化部署该服务需要满足:
- socket.gethostbyname能根据容器中的hostname获得容器正确的ip地址
- 集群中的其他服务能通过<容器中的主机名>.mgmt.pix.yun.com解析到ws服务的ip地址(在解析外部域名一文中已解决了能将mgmt.pix.yun.com转换为default.svc.cluster.local的问题, 因此该条件等同于集群中的其他服务能通过<容器中的主机名>。default.svc.cluster.local解析到ws服务的ip地址)
分析与方案
按照通常的思路,一个无状态的服务,用kubernetes来部署的话,只需要使用svc + deployment的方式便足够, 但是,却不能满足上面描述的需求, 例如一个pod的名称为‘ws-777779bd59-ftn4j’, 则其注册到zk中的信息为:
ws-777779bd59-ftn4j.mgmt.pix.yun.com:9999
kubernetes集群无法通过该域名解析到ip地址,根据参考文档的介绍, 可以使用headless svc + subdomain的方式,使deployment中的pod也能像statefulset的pod一样,通过类似<pod名>.<svc名>.default.svc.cluster.local的域名被解析
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ws
labels:
app: w
spec:
replicas: 2
selector:
matchLabels:
app: ws
template:
metadata:
labels:
app: ws
spec:
subdomain: ws
containers:
- name: ws
image: webservice
imagePullPolicy: Always
ports:
- containerPort: 8880
---
apiVersion: v1
kind: Service
metadata:
name: ws
spec:
clusterIP: None
selector:
app: ws
ports:
- name: nginx
protocol: TCP
port: 8880
targetPort: 8880
如上进行设置, 则在ws的pod内部就能通过<主机名>.ws.default.svc.cluster.local 解析到各自的ip地址了
# 容器内部查看本机的ip地址
root@ws-777779bd59-ftn4j:/$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP group default
link/ether 6a:7d:2d:d4:2e:ef brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.36.0.1/12 brd 10.47.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 用python检验域名解析是否能获取到本机的ip
root@ws-777779bd59-ftn4j:/$ python
Python 2.7.12 (default, Nov 12 2018, 14:36:49)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> socket.gethostbyname("ws-777779bd59-ftn4j.ws.default.svc.cluster.local")
'10.36.0.1'
>>> socket.gethostbyname("ws-777779bd59-ftn4j.ws.mgmt.pix.yun.com")
'10.36.0.1'
在deployment的另一个容器内查看:
root@ws-777779bd59-nnppt:/$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
114: eth0@if115: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP group default
link/ether 2e:23:56:a4:2f:e9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.32.0.5/12 brd 10.47.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 用python检验域名解析是否能获取到本机的ip
root@ws-777779bd59-nnppt:/$ python
Python 2.7.12 (default, Nov 12 2018, 14:36:49)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> socket.gethostbyname("ws-777779bd59-nnppt.ws.default.svc.cluster.local")
'10.36.0.5'
>>> socket.gethostbyname("ws-777779bd59-nnppt.ws.mgmt.pix.yun.com")
'10.36.0.5'
因此, 只需要把/etc/hostname中的主机名加上后缀‘.ws’即可, 可以在容器的启动脚本内添加
echo $HOSTNAME.ws > /etc/hostname
更多推荐
所有评论(0)