Service
K8S Service可以簡單理解爲邏輯上的一組Pod。一種可以訪問Pod的策略,其他Pod可以通過這個Service訪問到這個Service代理的Pod。
相對於Pod而言,它會有一個固定的名稱,一旦創建就固定不變。可以簡單的理解成訪問一個或者一組Pod的時候,先去訪問Service,然後再去訪問的IP,Service的名稱的固定的,不管Pod是否更新或者重啓,都不影響用戶的使用
爲什麼需要Service
啓動 nginx
[root@master01 ~]#
[root@master01 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 4 5d23h 172.18.71.31 master03 <none> <none>
nginx-deployment-5787596d54-6ffh4 1/1 Running 1 24h 172.18.71.30 master03 <none> <none>
nginx-deployment-5787596d54-7m47n 1/1 Running 1 24h 172.31.112.157 master01 <none> <none>
nginx-deployment-5787596d54-cnjb8 1/1 Running 1 24h 172.21.231.156 node02 <none> <none>
可以通過Pod IP 訪問
[root@master01 ~]# curl 172.31.112.157
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
存在的問題
Pod 一旦更新Ip就會發生變化
[root@master01 deployment]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 4 5d23h 172.18.71.31 master03 <none> <none>
nginx-deployment-559d658b74-4td67 1/1 Running 0 12s 172.31.112.159 master01 <none> <none>
nginx-deployment-559d658b74-nkb72 1/1 Running 0 16s 172.31.112.158 master01 <none> <none>
nginx-deployment-559d658b74-stql7 1/1 Running 0 14s 172.20.59.219 master02 <none> <none>
[root@master01 deployment]# kubectl edit deployment nginx-deployment
deployment.apps/nginx-deployment edited
[root@master01 deployment]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 4 6d 172.18.71.31 master03 <none> <none>
nginx-deployment-5787596d54-7564h 1/1 Running 0 13m 172.31.112.160 master01 <none> <none>
nginx-deployment-5787596d54-76txc 1/1 Running 0 13m 172.21.231.158 node02 <none> <none>
nginx-deployment-5787596d54-j77s9 1/1 Running 0 13m 172.18.71.32 master03 <none> <none>
通過 Service 可以這一層抽象,當Pod IP發生變化時,客戶端是無感的。
Service 是如何找到Pod
Service 創建的時候,k8s 會創建一個同名的 endpoint, endpoint 記錄的就是 Pod 的ip
kube-dns Service
[root@master01 deployment]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 14d
metrics-server ClusterIP 10.109.10.62 <none> 443/TCP 14d
[root@master01 deployment]# kubectl get ep -n kube-system
NAME ENDPOINTS AGE
kube-dns 172.29.55.27:53,172.29.55.27:53,172.29.55.27:9153 14d
metrics-server 172.21.231.157:4443 14d
[root@master01 deployment]# kubectl get po -n kube-system -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-kube-controllers-5f6d4b864b-k45q5 1/1 Running 10 14d 192.168.44.13 node01 <none> <none>
calico-node-58hbg 1/1 Running 10 14d 192.168.44.12 master03 <none> <none>
calico-node-dlj65 1/1 Running 10 14d 192.168.44.11 master02 <none> <none>
calico-node-jqb6h 1/1 Running 10 14d 192.168.44.14 node02 <none> <none>
calico-node-r8fl5 1/1 Running 11 14d 192.168.44.10 master01 <none> <none>
calico-node-wv4vx 1/1 Running 10 14d 192.168.44.13 node01 <none> <none>
coredns-867d46bfc6-ljdjr 1/1 Running 10 14d 172.29.55.27 node01 <none> <none>
metrics-server-595f65d8d5-6k4wq 1/1 Running 18 14d 172.21.231.157 node02 <none> <none>
包含 selector 的 Service
- nginx-svc.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app.kubernetes.io/name: proxy
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
name: http-web-svc
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app.kubernetes.io/name: proxy
ports:
- name: name-of-service-port
protocol: TCP
port: 80
targetPort: http-web-svc
- 創建 Service 和 Pod
[root@master01 service]# kubectl create -f nginx-svc.yaml
pod/nginx created
service/nginx-service created
[root@master01 service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
nginx-service ClusterIP 10.98.35.249 <none> 80/TCP 21s
[root@master01 service]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 4 6d 172.18.71.31 master03 <none> <none>
nginx 1/1 Running 0 33s 172.31.112.161 master01 <none> <none>
- 測試訪問 pod
通過 pod IP
[root@master01 service]# curl 172.31.112.161
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
通過 Service Ip
[root@master01 service]# curl 10.98.35.249
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
通過 Service 域名
[root@master01 service]# kubectl exec -it busybox -- sh
/ # wget http://nginx-service
Connecting to nginx-service (10.98.35.249:80)
index.html 100% |************************************************************************************************************| 615 0:00:00 ETA
/ # ls
bin dev etc home index.html proc root sys tmp usr var
/ # cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 跨名稱空間訪問
/ # wget http://nginx-service.default
Connecting to nginx-service.default (10.98.35.249:80)
index.html 100% |************************************************************************************************************| 615 0:00:00 ETA
- 查看 endpoint
[root@master01 service]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.44.10:6443,192.168.44.11:6443,192.168.44.12:6443 14d
nginx-service 172.31.112.161:80
不包含 Selector 的 Service
- 希望在生產環境中使用某個固定的名稱而非IP地址進行訪問外部的中間件服務
- 希望Service指向另一個Namespace中或其他集羣中的服務
- 某個項目正在遷移至k8s集羣,一部分服務仍然在集羣外部,此時可以使用service代理至k8s集羣外部的服務
使用Service代理k8s外部應用
- 創建一個類型爲external的service,這個svc不會自動創建一個ep
[root@master01 service]# vim nginx-svc-external.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-svc-external
name: nginx-svc-external
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
sessionAffinity: None
type: ClusterIP
[root@master01 service]# kubectl create -f nginx-svc-external.yaml
service/nginx-svc-external created
- 查看svc
[root@master01 service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
nginx-service ClusterIP 10.110.20.106 <none> 80/TCP 8s
nginx-svc-external ClusterIP 10.106.237.1 <none> 80/TCP 112s
- 查看 ep
[root@master01 service]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 192.168.44.10:6443,192.168.44.11:6443,192.168.44.12:6443 14d
nginx-service 172.31.112.162:80 37s
- 手動創建 ep, 名稱跟上面創建的svc關聯起來
[root@master01 service]# vim nginx-ep-external.yaml
apiVersion: v1
kind: Endpoints
metadata:
labels:
app: nginx-svc-external #名字要跟svc的一致
name: nginx-svc-external
namespace: default
subsets:
- addresses:
- ip: 14.215.177.39 # baidu
ports:
- name: http
port: 80
protocol: TCP
[root@master01 service]# kubectl create -f nginx-ep-external.yaml
endpoints/nginx-svc-external created
- 查看ep
[root@master01 service]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 192.168.44.10:6443,192.168.44.11:6443,192.168.44.12:6443 14d
nginx-service 172.31.112.162:80 8m14s
nginx-svc-external 14.215.177.39:80 23s
- 訪問ep
# pod ip
[root@k8s-master01 ~]# curl 220.181.38.148:80 -I
HTTP/1.1 200 OK
Date: Sat, 26 Dec 2020 16:00:57 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-47cf7e6ee8400"
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Sun, 27 Dec 2020 16:00:57 GMT
Connection: Keep-Alive
Content-Type: text/html
# service ip
[root@master01 service]# curl 10.106.237.1 -I
HTTP/1.1 302 Found
Connection: keep-alive
Content-Length: 17931
Content-Type: text/html
Date: Tue, 08 Nov 2022 17:09:49 GMT
Etag: "54d9748e-460b"
Server: bfe/1.0.8.18
Service 類型
- ClusterIP 集羣內部使用
- ExternalName 通過返回定義的 CNAME 別名
- NodePort 在所有安裝 kube-proxy 的節點上打開一個端口,此端口可以代理至後端 Pod,集羣外部可以使用節點IP以及 NodePort端口號訪問集羣Pod服務。
- LoadBalance 使用雲提供商的負載均衡器提供服務
[root@master01 service]# kubectl get svc -n kubernetes-dashboard -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
dashboard-metrics-scraper ClusterIP 10.96.223.156 <none> 8000/TCP 14d k8s-app=dashboard-metrics-scraper
kubernetes-dashboard NodePort 10.107.33.199 <none> 443:30929/TCP 14d k8s-app=kubernetes-dashboard
[root@master01 service]# kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master01 Ready matser 14d v1.20.0 192.168.44.10 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://19.3.15
master02 Ready <none> 14d v1.20.0 192.168.44.11 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://19.3.15
master03 Ready <none> 14d v1.20.0 192.168.44.12 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://19.3.15
node01 Ready <none> 14d v1.20.0 192.168.44.13 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://19.3.15
node02 Ready <none> 14d v1.20.0 192.168.44.14 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://19.3.15
[root@master01 service]# curl https://192.168.44.14:30929
curl: (60) Issuer certificate is invalid.
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.