Service:
Service是定義在集羣中一組運行Pod集合的抽象資源,它提供了所有相同的功能,當一個Service資源被創建後,將會分配一個唯一的IP,也叫做集羣IP,這個IP地址將存在於Service的整個生命資源中,Service一旦被創建,整個IP無法進行修改。
Pod可以通過Service進行通信,並且所有的通信將會通過Service自動負載均衡到所有的Pod中的容器。
- Service是真實應用服務的抽象。
- Service通常用來將浮動的資源與後端真實提供服務的容器進行關聯。
- Service對外表現爲一個單一的訪問接口,外部不需要了解後端的規模與機制。
Server工作模式:
- userspace:1.1版本以及之前的版本所使用。
- iptables:被1.10版本以及之前的版本所使用。
- ipvs:被1.11版本以及以上的版本所使用。
Service類型:
- ClusterIP:默認方式,根據是否生成ClusterIP又可分爲Service和Headless Service。
- Service:通過Kubernetes的Service分配一個集羣內部可訪問的固定虛擬。
- Headless Service:該服務不會分配Cluster IP,也不會通過kube-proxy做反向代理和負載均衡。而是通過DNS提供穩定的網絡ID來訪問,DNS會將Headless Service的後端直接解析爲PodIP列表,主要提供StatefulSet使用。
- NodePort:除了使用Cluster IP之外,還通過將Service的port映射到集羣內每個節點的相同一個端口,實現通過NodeIP:NodePort從集羣外訪問。
- LoadBalancer:和NodePort類似,不過除了使用一個Cluster IP和NodePort之外還會向所使用的公有云申請一個負載均衡器(負載均衡器後端映射到各節點的NodePort),實現集羣外通過LB訪問服務。
- ExternalName:是Service的特例,此模式主要面向在集羣外部的服務,通過它可以將外部服務映射到k8s集羣,且具備k8s內服務的一些特徵(如namesapce等屬性),來爲集羣內部提供服務。此模式要求k8s-dns的版本爲1.7或以上,這種模式和前三種模式(除了Headless Service)最大的不同是重定向依賴的是DNS層次,而不是通過kube-proxy。
ClusterIP:
創建Service時k8s默認爲ClusterIP,創建好Service,會生成一個ClusterIP,集羣內可以訪問這個ClusterIP,集羣外部無法訪問它。
#創建一個service
[root@k8smaster data]# vim redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: redis
role: logstor
template:
metadata:
labels:
app: redis
role: logstor
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- name: redis
containerPort: 6379
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
namespace: default
spec:
selector:
matchLabels:
app: filebeat
release: stable
template:
metadata:
labels:
app: filebeat
release: stable
spec:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alpine
env:
- name: REDIS_HOST
value: redis.default.svc.cluster.local
- name: REDIS_LOG_LEVEL
value: info
[root@k8smaster data]# kubectl apply -f redis.yaml
deployment.apps/redis created
daemonset.apps/filebeat-ds unchanged
[root@k8smaster data]# vim redis-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: default
spec:
selector:
app: redis
role: logstor
clusterIP: 10.97.97.97
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
[root@k8smaster data]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44d
redis ClusterIP 10.97.97.97 <none> 6379/TCP 17m
[root@k8smaster data]# kubectl apply -f redis-svc.yaml
service/redis created
[root@k8smaster data]# kubectl describe svc redis
Name: redis
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterIP":"10.97.97.97","...
Selector: app=redis,role=logstor
Type: ClusterIP
IP: 10.97.97.97
Port: <unset> 6379/TCP
TargetPort: 6379/TCP
Endpoints: 10.244.2.147:6379
Session Affinity: None
Events: <none>
#使用命令創建
[root@k8smaster kubernetes]# kubectl create deployment nginx-deployment --image=nginx
deployment.apps/nginx-deployment created
[root@k8smaster kubernetes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6f77f65499-dbhvp 1/1 Running 0 2m33s 10.244.1.95 k8snode1 <none> <none>
[root@k8smaster kubernetes]# kubectl create service clusterip nginx-deployment --tcp=80:80
service/nginx-deployment created
[root@k8smaster kubernetes]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d20h
nginx-deployment ClusterIP 10.103.139.34 <none> 80/TCP 12s
[root@k8smaster kubernetes]# kubectl describe service/nginx-deployment
Name: nginx-deployment
Namespace: default
Labels: app=nginx-deployment
Annotations: <none>
Selector: app=nginx-deployment
Type: ClusterIP
IP: 10.103.139.34
Port: 80-80 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.95:80 #Endpoints爲關聯的Pod的IP
Session Affinity: None
Events: <none>
[root@k8smaster kubernetes]# curl 10.103.139.34
<!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:
[root@k8smaster kubernetes]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f77f65499-dbhvp 1/1 Running 0 5m38s
[root@k8smaster kubernetes]# kubectl delete pods nginx-deployment-6f77f65499-dbhvp
pod "nginx-deployment-6f77f65499-dbhvp" deleted
[root@k8smaster kubernetes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6f77f65499-f8xtb 1/1 Running 0 26s 10.244.2.87 k8snode2 <none> <none>
[root@k8smaster kubernetes]# kubectl describe service/nginx-deployment
Name: nginx-deployment
Namespace: default
Labels: app=nginx-deployment
Annotations: <none>
Selector: app=nginx-deployment
Type: ClusterIP
IP: 10.103.139.34
Port: 80-80 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.87:80 #刪掉原來的Pod,Endpoints關聯到了新的Pod。
Session Affinity: None
Events: <none>
[root@k8smaster kubernetes]# curl 10.103.139.34
<!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>
訪問Service:
[root@k8smaster kubernetes]# curl nginx-deployment
curl: (6) Could not resolve host: nginx-deployment; Unknown error
[root@k8smaster kubernetes]# kubectl get service -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 2d21h
[root@k8smaster kubernetes]# kubectl get service -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 2d21h
[root@k8smaster kubernetes]# vim /etc/resolv.conf
# Generated by NetworkManager
nameserver 10.96.0.10
# nameserver 2408:84e1:a3:98c4::f7
[root@k8smaster kubernetes]# curl nginx-deployment.default.svc.cluster.local
<!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>
如果刪除Service:
[root@k8smaster kubernetes]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d21h
nginx-deployment ClusterIP 10.103.139.34 <none> 80/TCP 15m
[root@k8smaster kubernetes]# kubectl delete service/nginx-deployment
service "nginx-deployment" deleted
[root@k8smaster kubernetes]# kubectl create service clusterip nginx-deployment --tcp=80:80
service/nginx-deployment created
[root@k8smaster kubernetes]# kubectl describe service/nginx-deployment
Name: nginx-deployment
Namespace: default
Labels: app=nginx-deployment
Annotations: <none>
Selector: app=nginx-deployment
Type: ClusterIP
IP: 10.101.21.249
Port: 80-80 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.87:80 #只要關聯到Pods的名字,就能實現訪問,不管IP變沒變。
Session Affinity: None
Events: <none>
[root@k8smaster kubernetes]# curl 10.101.21.249
[root@k8smaster kubernetes]# curl 10.101.21.249
<!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>
實時伸縮:
[root@k8smaster ~]# kubectl delete deployment nginx-deployment
deployment.extensions "nginx-deployment" deleted
[root@k8smaster kubernetes]# kubectl create deployment myapp-deployment --image=ikubernetes/myapp:v1
deployment.apps/myapp-deployment created
[root@k8smaster kubernetes]# kubectl create service clusterip myapp-deployment --tcp=80:80
service/myapp-deployment created
[root@k8smaster kubernetes]# kubectl scale --replicas=3 deployment myapp-deployment
deployment.extensions/myapp-deployment scaled
[root@k8smaster ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deployment-558f94fb55-plk4v 1/1 Running 0 85m 10.244.2.93 k8snode2 <none> <none>
myapp-deployment-558f94fb55-rd8f5 1/1 Running 0 99m 10.244.2.91 k8snode2 <none> <none>
myapp-deployment-558f94fb55-zzmpg 1/1 Running 0 85m 10.244.1.101 k8snode1 <none> <none>
[root@k8smaster ~]# kubectl describe service/myapp-deployment
Name: myapp-deployment
Namespace: default
Labels: app=myapp-deployment
Annotations: <none>
Selector: app=myapp-deployment
Type: ClusterIP
IP: 10.110.41.201
Port: 80-80 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.101:80,10.244.2.91:80,10.244.2.93:80 #發現關聯了3個。
Session Affinity: None
Events: <none>
[root@k8smaster ~]# curl 10.110.41.201/hostname.html
myapp-deployment-558f94fb55-zzmpg
[root@k8smaster ~]# curl 10.110.41.201/hostname.html
myapp-deployment-558f94fb55-rd8f5
[root@k8smaster ~]# curl 10.110.41.201/hostname.html
myapp-deployment-558f94fb55-zzmpg
#發現Service自動實現了Pod的負載均衡。(調度方式是隨機調度)
NodePort:
NodePort時引導外部流量到集羣內服務最原始的方式,NodePort,正如這個名字所示,在所有節點上開發一個特定的端口,任何發送到該端口的流量都被轉發到對應服務。
- 端口範圍爲30000~32767。
- 節點的IP可能會發生變化。
不建議在生成環境上用這種方式暴露服務,如果運行的服務不要求一直可用,或者對成本筆記敏感,你可以使用這種方法。
[root@k8smaster ~]# kubectl delete service/myapp-deployment
service "myapp-deployment" deleted
[root@k8smaster ~]# kubectl create service nodeport myapp-deployment --tcp=80:80
service/myapp-deployment created
[root@k8smaster ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d23h
myapp-deployment NodePort 10.107.69.16 <none> 80:30930/TCP 79s #30930爲宿主機端口,我們來訪問以下。
myweb-deployment ClusterIP 10.99.246.129 <none> 80/TCP 162m
nginx-deployment ClusterIP 10.101.21.249 <none> 80/TCP 169m
LoadBalancer:
這種方式也會在節點上開放一個端口,所有通過該端口的流量都會被轉發到對應的服務上,它沒有過濾規則,沒有路由。這意味着你可以發送任何協議的流量,如HTTP,TCP,UDP,Websocket,gRPC或其他任意協議,這種方式會通過給你一個公網ip的方式來將服務暴露在公網上,但是每個使用LoadBalancer的服務都用於一個公網IP,每個公網IP都將會付費,開銷比較大。