Kubernetes Service 笔记
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.