WHY Service
kubectl expose ...
apiVersion: v1kind: Servicemetadata: name: kubiaspec: selector: # 该服务管理 app=kubia 的 Pod app: kubia ports: - port: 80 # 服务暴露端口 targetPort: 8080 # 服务将连接转发到的容器端口
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
selector: # 该服务管理 app=kubia 的 Pod
app: kubia
ports:
- port: 80 # 服务暴露端口
targetPort: 8080 # 服务将连接转发到的容器端口
测试
# 该服务集群 IP 为 10.111.249.153,只能在集群内部访问$ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubia ClusterIP 10.111.249.153 <none> 80/TCP 2d16h# 1. 在 K8s 节点 curl$ curl 10.111.249.153You've hit kubia-5fje3# 2. 在运行的 Pod 容器中发送 curl 命令(`--`表示 kubectl 命令的结束,后跟 Pod 内部执行的指令)$ kubectl exec kubia-7nog1 -- curl -s http://10.111.249.153You've hit kubia-gzwli
# 该服务集群 IP 为 10.111.249.153,只能在集群内部访问
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubia ClusterIP 10.111.249.153 <none> 80/TCP 2d16h
# 1. 在 K8s 节点 curl
$ curl 10.111.249.153
You've hit kubia-5fje3
# 2. 在运行的 Pod 容器中发送 curl 命令(`--`表示 kubectl 命令的结束,后跟 Pod 内部执行的指令)
$ kubectl exec kubia-7nog1 -- curl -s http://10.111.249.153
You've hit kubia-gzwli
让同一个 client IP 的请求转发到同一个 Pod
spec: sessionAffinity: ClientIP # 默认 None(仅支持这两种)
sessionAffinity: ClientIP # 默认 None(仅支持这两种)
服务会话亲和性不能基于 Cookie K8s 服务不是在 HTTP 层面上工作。服务处理 TCP 和 UDP 包,并不关心其中的荷载内容。而 cookie 是 HTTP 协议的一部分,服务并不知道它们 会话亲和性和 Web 浏览器 浏览器使用 keep-alive 连接,通过单个连接发送所有请求,而 curl 每次打开一个新连接。服务在连接级别工作,因此当首次与服务连接时会随机,但属于该连接的所有网络数据包全部发送到单个 Pod(即使服务会话亲和性设置为 None),直到连接关闭
服务会话亲和性不能基于 Cookie
K8s 服务不是在 HTTP 层面上工作。服务处理 TCP 和 UDP 包,并不关心其中的荷载内容。而 cookie 是 HTTP 协议的一部分,服务并不知道它们
会话亲和性和 Web 浏览器
浏览器使用 keep-alive 连接,通过单个连接发送所有请求,而 curl 每次打开一个新连接。服务在连接级别工作,因此当首次与服务连接时会随机,但属于该连接的所有网络数据包全部发送到单个 Pod(即使服务会话亲和性设置为 None),直到连接关闭
spec: ports: - name: http # 多个端口的服务必须指定端口名字 port: 80 targetPort: 8080 - name: https port: 443 targetPort: 8443
- name: http # 多个端口的服务必须指定端口名字
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
kind: Podspec: containers: - name: kubia ports: - name: http # 端口 8080 被命名为 http containerPort: 8080 - name: https containerPort: 8443
kind: Pod
containers:
- name: kubia
- name: http # 端口 8080 被命名为 http
containerPort: 8080
containerPort: 8443
kind: Servicespec: ports: - name: http port: 80 targetPort: http # 映射到容器中被称为 http 的端口 - name: https port: 443 targetPort: https
- name: http
targetPort: http # 映射到容器中被称为 http 的端口
targetPort: https
Pod 获取服务 IP 和端口
Pod 启动时,K8s 会初始化一系列环境变量指向现存的服务。若服务早于 Pod 创建,Pod 进程便可根据环境变量获取服务信息
规则:如名为backend-database的服务会生成BACKEND_DATABASE_SERVICE_HOST和BACKEND_DATABASE_SERVICE_PORT两个环境变量
backend-database
BACKEND_DATABASE_SERVICE_HOST
BACKEND_DATABASE_SERVICE_PORT
$ kubectl exec kubia-3inly envKUBIA_SERVICE_HOST=10.111.249.153KUBIA_SERVICE_PORT=80...
$ kubectl exec kubia-3inly env
KUBIA_SERVICE_HOST=10.111.249.153
KUBIA_SERVICE_PORT=80
...
kube-system 下的 kube-dns Pod 运行 DNS 服务,集群中的其他 Pod 都被配置成使用其作为 dns(K8s 通过修改每个容器的 /etc/resolve.conf 实现)。因此,运行在 Pod 上的进程 DNS 查询都会被 K8s 自身的 DNS 服务器响应,该服务器知道系统中运行的所有服务
Pod 是否使用内部的 DNS 服务器是根据 Pod 中 spec.dnsPolicy 决定
$ kubectl get svc -n kube-systemNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 3d20h$ kubectl exec kubia-3inly -- cat /etc/resolv.confnameserver 10.96.0.10search default.svc.cluster.local svc.cluster.local cluster.local...
$ kubectl get svc -n kube-system
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 3d20h
$ kubectl exec kubia-3inly -- cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
每个服务从内部 DNS 服务器中获得一个 DNS 条目,客户端 Pod 在知道服务名称的情况下可通过 FQDN(全限定域名)来访问。格式为:<服务名称>.<服务命名空间>.svc.cluster.local。其中svc.cluster.local是在所有集群本地服务名称中使用的可配置集群域后缀
<服务名称>.<服务命名空间>.svc.cluster.local
svc.cluster.local
客户端仍需知道服务的端口号。服务可直接使用标准端口号(如 HTTP 的 80 端口或 Postgres 的 5432 端口)或从环境变量中获取端口号
$ kubectl exec -it kubia-3inly bashroot@kubia-3inly:/# curl kubia.default.svc.cluster.localYou've hit kubia-3inly# 若两个 Pod 在同一个命名空间,可直接使用服务名称root@kubia-3inly:/# curl kubiaYou've hit kubia-5asi2# 服务的集群 IP 为虚拟 IP,且只有与服务端口结合时才有意义root@kubia-3inly:/# ping kubia6 packets transmitted, 0 packets received, 100% packet loss
$ kubectl exec -it kubia-3inly bash
root@kubia-3inly:/# curl kubia.default.svc.cluster.local
You've hit kubia-3inly
# 若两个 Pod 在同一个命名空间,可直接使用服务名称
root@kubia-3inly:/# curl kubia
You've hit kubia-5asi2
# 服务的集群 IP 为虚拟 IP,且只有与服务端口结合时才有意义
root@kubia-3inly:/# ping kubia
6 packets transmitted, 0 packets received, 100% packet loss
服务将请求重定向到外部 IP 和端口
$ kubectl get endpoints kubiaNAME ENDPOINTS AGEkubia 10.108.1.4:8080,10.108.2.5:8080,10.108.2.6:8080 2h
$ kubectl get endpoints kubia
NAME ENDPOINTS AGE
kubia 10.108.1.4:8080,10.108.2.5:8080,10.108.2.6:8080 2h
创建不包含 Pod 选择器的服务将不会创建 Endpoint 资源,此时需要手动创建 Endpoint
apiVersion: v1kind: Servicemetadata: name: external-servicespec: # 没有指定 Pod 选择器 ports: - port: 80
name: external-service
spec: # 没有指定 Pod 选择器
- port: 80
apiVersion: v1kind: Endpointsmetadata: name: external-service # Endpoint 名称需和服务名称匹配subsets: - addresses: # 服务将连接重定向到 Endpoint 的 IP 地址 - ip: 11.11.11.11 - ip: 22.22.22.22 ports: # Endpoint 的目标端口 - port: 80
kind: Endpoints
name: external-service # Endpoint 名称需和服务名称匹配
subsets:
- addresses: # 服务将连接重定向到 Endpoint 的 IP 地址
- ip: 11.11.11.11
- ip: 22.22.22.22
ports: # Endpoint 的目标端口
通过 FQDN(完全限定域名)访问外部服务
apiVersion: v1kind: Servicemetadata: name: external-servicespec: type: ExternalName # 创建一个具有别名的外部服务的服务 externalName: someapi.somecompany.com # 实际服务的全限定名 ports: - port: 80
type: ExternalName # 创建一个具有别名的外部服务的服务
externalName: someapi.somecompany.com # 实际服务的全限定名
Pod 通过external-service.default.svc.cluster.local访问外部服务
external-service.default.svc.cluster.local
ExternalName 服务仅在 DNS 级别实施,为服务创建了简单的 CNAME DNS 记录。因此连接到服务的客户端将直接连接到外部服务,完全绕过服务代理。因此该类型服务不会获得集群 IP CNAME 记录指向完全限定的域名而不是数字 IP 地址
ExternalName 服务仅在 DNS 级别实施,为服务创建了简单的 CNAME DNS 记录。因此连接到服务的客户端将直接连接到外部服务,完全绕过服务代理。因此该类型服务不会获得集群 IP
CNAME 记录指向完全限定的域名而不是数字 IP 地址
apiVersion: v1kind: Servicemetadata: name: kubia-nodeportspec: type: NodePort # 默认 ClusterIP ports: - port: 80 targetPort: 8080 nodePort: 30123 # 集群节点端口(不指定则随机) selector: app: kubia
name: kubia-nodeport
type: NodePort # 默认 ClusterIP
nodePort: 30123 # 集群节点端口(不指定则随机)
selector:
可通过<node-ips>:30123或<cluster-ip>:80访问
<node-ips>:30123
<cluster-ip>:80
spec: type: LoadBalancer
type: LoadBalancer
可通过<external-ip>:80访问
<external-ip>:80
网络跳数
当访问到某个节点的端口,服务随机转发 Pod,此时 Pod 可能不在此节点上,这就需要额外的网络跳转。可将服务配置为仅将外部连接重定向到接收该连接的节点上的 Pod 来阻止跳转:
spec: externalTrafficPolicy: Local
externalTrafficPolicy: Local
缺点:
客户端 IP 不会被记录
当通过节点端口接收到连接时,会对数据包进行 SNAT(源网络地址转换),因此数据包的源 IP 将发生更改
Local 外部流量策略会保留客户端 IP,因为接收连接的节点和 Pod 所在节点没有额外跳跃(不执行 SNAT)
apiVersion: extensions/v1beta1kind: Ingressmetadata: name: kubiaspec: rules: # 接收所有请求主机 kubia.example.com 的 HTTP 请求,转发到 kubia-nodeport 的 80 端口 - host: kubia.example.com # must be a DNS name, not an IP address http: paths: - path: / backend: serviceName: kubia-nodeport servicePort: 80
apiVersion: extensions/v1beta1
kind: Ingress
rules:
# 接收所有请求主机 kubia.example.com 的 HTTP 请求,转发到 kubia-nodeport 的 80 端口
- host: kubia.example.com # must be a DNS name, not an IP address
http:
paths:
- path: /
backend:
serviceName: kubia-nodeport
servicePort: 80
$ kubectl get ingressNAME CLASS HOSTS ADDRESS PORTS AGEkubia <none> kubia.example.com 192.168.99.100 80 14s# 要将域名解析为 Ingress 控制器的 IP$ vi /etc/hosts192.168.99.100 kubia.example.com$ curl http://kubia.example.comYou've hit kubia-5asi2
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
kubia <none> kubia.example.com 192.168.99.100 80 14s
# 要将域名解析为 Ingress 控制器的 IP
$ vi /etc/hosts
192.168.99.100 kubia.example.com
$ curl http://kubia.example.com
将不同的服务映射到不同主机的不同路径
需要将两个域名都指向 Ingress 控制器的 IP 地址,通过 Host 头判断
spec: rules: - host: kubia.example.com http: paths: - path: /kubia backend: serviceName: kubia servicePort: 80 - path: /foo backend: serviceName: foo servicePort: 80 - host: bar.example.com http: paths: - path: / backend: serviceName: bar servicePort: 80
- host: kubia.example.com
- path: /kubia
serviceName: kubia
- path: /foo
serviceName: foo
- host: bar.example.com
serviceName: bar
kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
kind: Ingressspec: tls: # tls 配置 - hosts: # 接收主机的 tls 连接 - kubia.example.com serviceName: tls-secret # 私钥和证书
tls: # tls 配置
- hosts: # 接收主机的 tls 连接
- kubia.example.com
serviceName: tls-secret # 私钥和证书
类型
对比
添加就绪探针
apiVersion: v1kind: ReplicationControllermetadata: name: kubiaspec: replicas: 2 template: metadata: labels: app: kubia spec: containers: - name: kubia image: luksa/kubia readinessProbe: exec: command: ["ls", "/var/ready"] ports: - containerPort: 8080
kind: ReplicationController
replicas: 2
template:
labels:
image: luksa/kubia
readinessProbe:
exec:
command: ["ls", "/var/ready"]
- containerPort: 8080
$ kubectl get podNAME READY STATUS RESTARTS AGEkubia-5csgl 0/1 Running 0 2m5skubia-qj7gz 0/1 Running 0 2m5s$ kubectl exec kubia-5csgl -- touch /var/ready$ kubectl get podNAME READY STATUS RESTARTS AGEkubia-5csgl 1/1 Running 0 3m43skubia-qj7gz 0/1 Running 0 3m43s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
kubia-5csgl 0/1 Running 0 2m5s
kubia-qj7gz 0/1 Running 0 2m5s
$ kubectl exec kubia-5csgl -- touch /var/ready
kubia-5csgl 1/1 Running 0 3m43s
kubia-qj7gz 0/1 Running 0 3m43s
创建 headless 服务
apiVersion: v1kind: Servicemetadata: name: kubia-headlessspec: clusterIP: None # headless selector: app: kubia ports: - port: 80 targetPort: 8080
name: kubia-headless
clusterIP: None # headless
执行 DNS 查找
# 创建可支持 DNS 查找的 Pod$ kubectl run dnsutils --image=tutum/dnsutils --command -- sleep infinitypod/dnsutils created# headless 服务返回的是(就绪的)Pod IP$ kubectl exec dnsutils nslookup kubia-headless...Name: kubia-headless.default.svc.cluster.localAddress: 10.42.0.20Name: kubia-headless.default.svc.cluster.localAddress: 10.42.0.19# 常规服务返回的是 Cluster IP$ kubectl exec dnsutils nslookup kubia...Name: kubia.default.svc.cluster.localAddress: 10.43.99.228
# 创建可支持 DNS 查找的 Pod
$ kubectl run dnsutils --image=tutum/dnsutils --command -- sleep infinity
pod/dnsutils created
# headless 服务返回的是(就绪的)Pod IP
$ kubectl exec dnsutils nslookup kubia-headless
Name: kubia-headless.default.svc.cluster.local
Address: 10.42.0.20
Address: 10.42.0.19
# 常规服务返回的是 Cluster IP
$ kubectl exec dnsutils nslookup kubia
Name: kubia.default.svc.cluster.local
Address: 10.43.99.228
原文链接:http://www.cnblogs.com/lb477/p/14892364.html
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728