第六章: 通過Service訪問Pod
不應該直接使用Pod的ID地址作為對外提供服務的接口汪茧,應為一旦Pod重啟,IP地址就變化了呀舔,解決方案是使用Service。
6.1 創(chuàng)建Service
K8s service從邏輯上代表了一組Pod霜瘪,具體是哪些Pod則由label來挑選的惧磺。
service有自己的IP,而且這個IP是不變的缤底,客戶端只需要訪問Service的IP番捂,K8s負責建立和維護service和Pod的映射關系设预。無論Pod如何變化,對客戶端無影響鳖枕。
httpd.yml
vim httpd.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: httpd
spec:
replicas: 3
template:
metadata:
labels:
run: httpd # 定義label給service用
spec:
containers:
- name: httpd
image: httpd
ports:
- containerPort: 80 # port對外暴露的端口
部署之后耕魄,可以直接通過IP地址訪問Pod:
$kubectl apply -f httpd.yml
$kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-69cb5b9fdd-9vtrp 1/1 Running 0 5m11s 10.244.3.119 k8s-node-122132073 <none> <none>
httpd-69cb5b9fdd-crtfm 1/1 Running 0 5m11s 10.244.3.118 k8s-node-122132073 <none> <none>
httpd-69cb5b9fdd-k9xbv 1/1 Running 0 5m11s 10.244.4.35 k8s-node-122132072 <none> <none>
#測試
$curl 10.244.3.119:80
<html><body><h1>It works!</h1></body></html>
定義service 配置
vim httpd-svc.yml
apiVersion: v1
kind: Service
metadata:
name: httpd-svc # service 名字
spec:
selector:
run: httpd # selector指明挑選 label為run:httpd 的Pod作為Service的后端吸奴。
ports:
- protocol: TCP
port: 8080 # service的端口; service的8080端口映射到Pod的80端口
targetPort: 80 # Port的端口
~~
**部署service**
~~
$kubectl apply -f httpd-svc.yml
$service/httpd-svc created
$kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc ClusterIP 10.10.60.67 <none> 8080/TCP 5s
#測試
curl 10.10.60.67:8080
<html><body><h1>It works!</h1></body></html>
通過kubectl describe可以查看httpd-svc與pod的對應關系:
kubectl describe service httpd-svc
Name: httpd-svc
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"httpd-svc","namespace":"default"},"spec":{"ports":[{"port":8080,"...
Selector: run=httpd
Type: ClusterIP
IP: 10.10.60.67
Port: <unset> 8080/TCP
TargetPort: 80/TCP
Endpoints: 10.244.3.118:80,10.244.3.119:80,10.244.4.35:80
Session Affinity: None
Events: <none>
6.2 Cluster IP底層實現(xiàn)
Cluster IP 是一個虛擬IP,是由K8s節(jié)點上的iptables規(guī)則管理的读处。使用類似輪詢的方法訪問Pod罚舱。
$iptables -L
$iptables-save #打印出規(guī)則
6.3 DNS訪問service
在Cluster中,除了可以通過Cluster IP訪問 services管闷, K8s還提供了更為方便的DNS訪問。
kubeadm部署時會默認安裝kube-dns組件刷允。
kube-dns是一個DNS服務器。每當有新的Service被創(chuàng)建纤怒,kube-dns會添加該service的DNS記錄天通。
Cluster中的Pod可以通過
比如可以用httpd-svc.default(service name. namespace name) 訪問service httpd-svc.(注意: 這是在port里訪問)
$kubectl get deployment -n kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
coredns 2/2 2 2 8d
$kubectl run busybox --rm -ti --image=busybox /bin/sh
#
$wget httpd-svc:8080 ## 因為都屬于同一個namespace default谜洽, 說與可以省略default
Connecting to httpd-svc:8080 (10.10.60.67:8080)
saving to 'index.html'
index.html 100% |*************************| 45 0:00:00 ETA
'index.html' saved
$nslookup httpd-svc
Server: 10.10.0.10
Address: 10.10.0.10:53
httpd2.yml
$vim httpd2.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: httpd2
namespace: kube-public
spec:
replicas: 2
template:
metadata:
labels:
run: httpd2 # 定義label給service用
spec:
containers:
- name: httpd2
image: httpd
ports:
- containerPort: 80 # port對外暴露的端口
---
apiVersion: v1
kind: Service
metadata:
name: httpd2-svc # service 名字
namespace: kube-public
spec:
selector:
run: httpd2 # selector指明挑選 label為run:httpd2 的Pod作為Service的后端阐虚。
ports:
- protocol: TCP
port: 8080 # service的端口; service的8080端口映射到Pod的80端口
targetPort: 80 # Port的端口
布署httpd2
$kubectl apply -f httpd2.yml
$kubectl get service -n kube-public
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd2-svc ClusterIP 10.10.64.178 <none> 8080/TCP 11m
#需要加上namespace
$wget httpd2-svc.kube-public:8080
Connecting to httpd2-svc.kube-public:8080 (10.10.64.178:8080)
saving to 'index.html'
index.html 100% |*******************************| 45 0:00:00 ETA
'index.html' saved
6.4 外網如何訪問service
- ClusterIp:
Service通過Cluster內部的IP對外提供服務奥秆,只有Cluster內節(jié)點和Pod可以訪問构订,這是默認的Service類型避矢。 - NodePort:
Service通過Cluster節(jié)點的靜態(tài)端口對外提供服務。Cluster外部可以通過<NodeIp>.<NodePort>訪問Service. - LoadBalancer:
Service利用cloud provider特有的load balancer對外提供服務亥宿。
實踐一下NodePort
$kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc ClusterIP 10.10.60.67 <none> 8080/TCP 43m
$修改httpd-svc.yml
vim httpd-svc.yml
spec:
type: NodePort #指定為NodePort
$kubectl apply -f httpd-svc.yml
#Type欄變?yōu)镹odePortPort欄會多出32686
$kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc NodePort 10.10.60.67 <none> 8080:32686/TCP 46m
這時可以通過node_ip:23686訪問
$ netstat -an |grep 32686
tcp6 0 0 :::32686 :::* LISTEN
#這時可以通過node_ip:23686訪問
$kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-svc NodePort 10.10.60.67 <none> 8080:32686/TCP 56m
#這時可以通過node_ip:23686訪問
$ curl k8s-node-122132072:32686 #也可用node_ip
<html><body><h1>It works!</h1></body></html>
$ curl 10.10.60.67:8080
<html><body><h1>It works!</h1></body></html>
vim httpd-svc.yml
apiVersion: v1
kind: Service
metadata:
name: httpd-svc # service 名字
spec:
type: NodePort
selector:
run: httpd # selector指明挑選 label為run:httpd 的Pod作為Service的后端烫扼。
ports:
- protocol: TCP
nodePort: 30000 # node監(jiān)聽Port
port: 8080 # service的端口碍庵; service的8080端口映射到Pod的80端口
targetPort: 80 # Port的端口
$curl k8s-node-122132072:30000
<html><body><h1>It works!</h1></body></html>