kubernetes 提供了 service 的概念可以通过 VIP 访问 pod 提供的服务,但是在使用的时候还有一个问题:怎么知道某个应用的 VIP?比如我们有两个应用,一个 app,一个 是 db,每个应用使用 deploy 进行管理,并通过 service 暴露出端口提供服务。app 需要连接到 db 应用,我们只知道 db 应用的名称,但是并不知道它的 VIP 地址。
最简单的办法是从 kubernetes 提供的 API 查询。但这是一个糟糕的做法,首先每个应用都要在启动的时候编写查询依赖服务的逻辑,这本身就是重复和增加应用的复杂度;其次这也导致应用需要依赖 kubernetes,不能够单独部署和运行(当然如果通过增加配置选项也是可以做到的,但这又是增加负责度)。
开始的时候,kubernetes 采用了 docker 使用过的方法——环境变量。每个 pod 启动时候,会把通过环境变量设置所有服务的 IP 和 port 信息,这样 pod 中的应用可以通过读取环境变量来获取依赖服务的地址信息。这种方式服务和环境变量的匹配关系有一定的规范,使用起来也相对简单,但是有个很大的问题:需要先创建svc后创建pod,否则pod中无法注入这些变量信息。
更理想的方案是:应用能够直接使用服务的名字,不需要关心它实际的 ip 地址,中间的转换能够自动完成。名字和 ip 之间的转换就是 DNS 系统的功能,因此 kubernetes 也提供了 DNS 方法来解决这个问题。
DNS 服务不是独立的系统服务,而是一种 addon ,作为插件来安装的,不是 kubernetes 集群必须的(但是非常推荐安装)。可以把它看做运行在集群上的应用,只不过这个应用比较特殊而已。
DNS 有两种配置方式,在 1.3 之前使用 etcd + kube2sky + skydns 的方式,在 1.3 之后可以使用 kubedns + dnsmasq 的方式。
不管以什么方式启动,对外的效果是一样的。要想使用 DNS 功能,还需要修改 kubelet
的启动配置项,告诉 kubelet,给每个启动的 pod 设置对应的 DNS 信息,一共有两个参数:--cluster_dns=10.10.10.10 --cluster_domain=cluster.local
,分别是 DNS 在集群中的 vip 和域名后缀,要和 DNS rs 中保持一致。
下面是这种方式的部署配置文件:
apiVersion: v1
kind: ReplicationController
metadata:
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
name: kube-dns
namespace: kube-system
spec:
replicas: 1
selector:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: etcd
command:
- /usr/local/bin/etcd
- "-listen-client-urls"
- "http://127.0.0.1:2379,http://127.0.0.1:4001"
- "-advertise-client-urls"
- "http://127.0.0.1:2379,http://127.0.0.1:4001"
- "-initial-cluster-token"
- skydns-etcd
image: "gcr.io/google_containers/etcd:2.0.9"
resources:
limits:
cpu: 100m
memory: 50Mi
- name: kube2sky
args:
- "-domain=cluster.local"
- "-kube_master_url=http://10.7.114.81:8080"
image: "gcr.io/google_containers/kube2sky:1.11"
resources:
limits:
cpu: 100m
memory: 50Mi
- name: skydns
args:
- "-machines=http://localhost:4001"
- "-addr=0.0.0.0:53"
- "-domain=cluster.local"
image: "gcr.io/google_containers/skydns:2015-03-11-001"
livenessProbe:
exec:
command:
- /bin/sh
- "-c"
- "nslookup kubernetes.default.svc.cluster.local localhost >/dev/null"
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
resources:
limits:
cpu: 100m
memory: 50Mi
dnsPolicy: Default
这里有两个需要根据实际情况配置的地方:
kube_master_url
: kube2sky 会用到 kubernetes master API,它会读取里面的 service 信息domain
:域名后缀,默认是 cluster.local
,你可以根据实际需要修改成任何合法的值然后是 Service 的配置文件:
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.10.10.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
这里需要注意的是 clusterIP: 10.10.10.10
这一行手动指定了 DNS service 的 IP 地址,这个地址必须在预留的 vip 网段。手动指定的原因是为了固定这个 ip,这样启动 kubelet 的时候配置 --cluster_dns=10.10.10.10
比较方便,不需要再动态获取 DNS 的 vip 地址。
有了这两个文件,直接创建对象就行:
$ kubectl create -f ./skydns-rc.yml
$ kubectl create -f ./skydns-svc.yml
[root@localhost ~]# kubectl get svc,rc,pod --namespace=kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/kube-dns 10.10.10.10 <none> 53/UDP 1d
NAME DESIRED CURRENT READY AGE
rc/kube-dns 1 1 1 41m
NAME READY STATUS RESTARTS AGE
po/kube-dns-twl0q 3/3 Running 0 41m
在 kubernetes 1.3 版本之后,kubernetes 改变了 DNS 的部署方式,变成了 kubeDNS + dnsmasq
,没有了 etcd
。在这种模式下,kubeDNS 是原来 kube2sky + skyDNS + etcd
,只不过它把数据都保存到自己的内存,而不是 kv store 中;dnsmasq
的引进是为了提高解析的速度,因为它可以配置 DNS 缓存。
这种部署方式的完整配置文件这里就不贴出来了,我放到了 github gist 上面,有兴趣可以查看。创建方法也是一样 kubectl create -f ./skydns-rc.yml
不管那种部署很是,kubernetes 对外提供的 DNS 服务是一致的。每个 service 都会有对应的 DNS 记录,kubernetes 保存 DNS 记录的格式如下:
<service_name>.<namespace>.svc.<domain>
每个部分的字段意思:
cluster.local
在 pod 中可以通过 service_name.namespace.svc.domain
来访问任何的服务,也可以使用缩写 service_name.namespace
,如果 pod 和 service 在同一个 namespace,甚至可以直接使用 service_name
。
NOTE:正常的 service 域名会被解析成 service vip,而 headless service 域名会被直接解析成背后的 pods ip。
虽然不会经常用到,但是 pod 也会有对应的 DNS 记录,格式是 pod-ip-address.
,其中 pod-ip-address
为 pod ip 地址的用 -
符号隔开的格式,比如 pod ip 地址是 1.2.3.4
,那么对应的域名就是 1-2-3-4.default.pod.cluster.local
。
我们运行一个 busybox
来验证 DNS 服务能够正常工作:
[root@master01 yaml]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.254.0.1 443/TCP 21d nginx-service NodePort 10.254.218.227 80:30680/TCP 5d4h [root@master01 yaml]# kubectl exec -it busybox ping nginx-service PING nginx-service (10.254.218.227): 56 data bytes 64 bytes from 10.254.218.227: seq=0 ttl=64 time=0.130 ms ^C --- nginx-service ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.130/0.130/0.130 ms [root@master01 yaml]# kubectl exec -it busybox ping kubernetes PING kubernetes (10.254.0.1): 56 data bytes 64 bytes from 10.254.0.1: seq=0 ttl=64 time=0.123 ms ^C --- kubernetes ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.123/0.123/0.123 ms
测试kube-system这个ns里边的svc:
[root@master01 yaml]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE heapster ClusterIP 10.254.231.183 80/TCP 4d3h kube-dns ClusterIP 10.254.0.2 53/UDP,53/TCP 52m kubernetes-dashboard NodePort 10.254.16.128 443:31552/TCP 6d2h monitoring-grafana ClusterIP 10.254.166.125 80/TCP 4d3h monitoring-influxdb ClusterIP 10.254.80.98 8086/TCP 4d3h [root@master01 yaml]# kubectl exec -it busybox ping kube-dns.kube-system PING kube-dns.kube-system (10.254.0.2): 56 data bytes 64 bytes from 10.254.0.2: seq=0 ttl=64 time=0.123 ms 64 bytes from 10.254.0.2: seq=1 ttl=64 time=0.159 ms ^C --- kube-dns.kube-system ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.123/0.141/0.159 ms [root@master01 yaml]# kubectl exec -it busybox ping kubernetes-dashboard.kube-system PING kubernetes-dashboard.kube-system (10.254.16.128): 56 data bytes 64 bytes from 10.254.16.128: seq=0 ttl=64 time=0.163 ms 64 bytes from 10.254.16.128: seq=1 ttl=64 time=0.186 ms ^C --- kubernetes-dashboard.kube-system ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.163/0.174/0.186 ms
我们前面介绍了两种不同 DNS 部署方式,这部分讲讲它们内部的原理。
这种模式下主要有三个容器在运行:
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
919cbc006da2 172.16.1.41:5000/google_containers/kube2sky:1.12 "/kube2sky /kube2sky " About an hour ago Up About an hour k8s_kube2sky.80a41edc_kube-dns-twl0q_kube-system_ea1f5f4d-15cf-11e7-bece-080027c09e5b_1bd3fdb4
73dd11cac057 172.16.1.41:5000/jenkins/etcd:live "etcd -data-dir=/var/" About an hour ago Up About an hour k8s_etcd.4040370_kube-dns-twl0q_kube-system_ea1f5f4d-15cf-11e7-bece-080027c09e5b_b0e5a99f
0b10ae639989 172.16.1.41:5000/jenkins/skydns:20150703-113305 "bootstrap.sh" About an hour ago Up About an hour k8s_skydns.73baf3b1_kube-dns-twl0q_kube-system_ea1f5f4d-15cf-11e7-bece-080027c09e5b_2860aa6d
这三个容器的作用分别是:
这种模式下,kubeDNS
容器替代了原来的三个容器的功能,它会监听 apiserver 并把所有 service 和 endpoints 的结果在内存中用合适的数据结构保存起来,并对外提供 DNS 查询服务。
每种模式都可以运行额外的 exec-healthz
容器对外提供 health check 功能,证明当前 DNS 服务是正常的。
/healthz
结果推荐使用 kubeDNS 的模式来部署,因为它有着以下的好处:
http://cizixs.com/2017/04/11/kubernetes-intro-kube-dns
http://jingyan.baidu.com/article/72ee561a6e2460e16138dff7.html
源码分析 http://blog.csdn.net/u010278923/article/details/70173635
文章转载于https://www.cnblogs.com/allcloud/p/7614123.html ,比自己写的好。
转载请注明:云速博客www.ysidc.top» k8s入门系列之service 服务发现进阶以及dns部署方式
https://www.ysidc.top 云速博客,数据库,云速,虚拟主机,域名注册,域名,云服务器,云主机,云建站,ysidc.top