service管理
- 容器化带来的问题
- 自动调度:在Pod创建之前,用户无法预知Pod所在的节点,以及Pod的IP地址
- 一个已经存在的Pod在运行过程中,如果出现故障,Pod也会在新的节点使用新的IP进行部署
- 应用程序访问服务的时候,地址也不能经常变换
- 多个相同的Pod如何访问他们上面的服务
- service就是解决这些问题的
clusterIP
- 服务的自动跟踪
- 服务会创建一个clusterIP,这个地址对应资源地址,不管Pod如何变化,服务总能找到对应的Pod,且clusterIP保持不变
- 服务的负载均衡
- 如果服务后端对应多个Pod,则会通过IPTables/LVS规则将访问的请求最终映射到Pod的容器内部,自动在多个容器间实现负载均衡
- 服务的自动发现
- 服务创建时会自动在内部DNS上注册域名
- 域名:<服务名称>.<名称空间>.svc.cluster.local
- cluster.local是在集群创建前,kubeadm-init.yaml文件里定义的,如果公司有自己的域名,可以替换
- 服务的工作原理
- kube-proxy是在所有节点上运行的代理。可以实现简单的数据转发,可以设置更新IPTables/LVS规则,在服务创建时,还提供服务地址DNS自动注册与服务发现功能
- kube-proxy是在所有节点上运行的代理。可以实现简单的数据转发,可以设置更新IPTables/LVS规则,在服务创建时,还提供服务地址DNS自动注册与服务发现功能
自动注册域名
[root@master ~]# vim mysvc.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc
spec:
type: ClusterIP
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc created
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d18h
mysvc ClusterIP 10.245.1.80 <none> 80/TCP 8s
[root@master ~]# yum install -y bind-utils
# k8s DNS地址
[root@master ~]# kubectl -n kube-system get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.245.0.10 <none> 53/UDP,53/TCP,9153/TCP 13d
metrics-server ClusterIP 10.245.66.175 <none> 443/TCP 10d
[root@master ~]# host mysvc.default.svc.cluster.local 10.245.0.10
Using domain server:
Name: 10.245.0.10
Address: 10.245.0.10#53
Aliases:
mysvc.default.svc.cluster.local has address 10.245.1.80
后端Pod
[root@master ~]# vim myweb.yaml
---
kind: Pod
apiVersion: v1
metadata:
name: myweb
labels:
app: web
spec:
terminationGracePeriodSeconds: 0
restartPolicy: Always
containers:
- name: apache
image: myos:httpd
imagePullPolicy: IfNotPresent
ports:
- name: myhttp
protocol: TCP
containerPort: 80
[root@master ~]# sed 's,myweb,web1,' myweb.yaml |kubectl apply -f -
pod/web1 created
[root@master ~]# curl http://10.245.1.80
Welcome to The Apache.
# service 靠标签寻找 Pod
[root@master ~]# kubectl label pod web1 app-
pod/web1 labeled
[root@master ~]# curl http://10.245.1.80
curl: (7) Failed connect to 10.245.1.80:80; Connection refused
[root@master ~]# kubectl label pod web1 app=web
pod/web1 labeled
[root@master ~]# curl http://10.245.1.80
Welcome to The Apache.
多个Pod负载均衡
[root@master ~]# sed 's,myweb,web2,' myweb.yaml |kubectl apply -f -
pod/web2 created
[root@master ~]# sed 's,myweb,web3,' myweb.yaml |kubectl apply -f -
pod/web3 created
[root@master ~]# curl -s http://10.245.1.80/info.php |grep php_host
php_host: web1
[root@master ~]# curl -s http://10.245.1.80/info.php |grep php_host
php_host: web2
[root@master ~]# curl -s http://10.245.1.80/info.php |grep php_host
php_host: web3
为服务设置固定IP
- ClusterIP是随即分配IP的,如果想使用固定IP,可以自定义,但IP的范围必须符合服务的CIDR
[root@master ~]# vim mysvc.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc
spec:
type: ClusterIP
clusterIP: 10.245.1.80
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: myhttp
[root@master ~]# kubectl delete -f mysvc.yaml
service "mysvc" deleted
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc created
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d18h
mysvc ClusterIP 10.245.1.80 <none> 80/TCP 65s
服务类型
- 发布服务
- ClusterIP服务可以解决集群内应用互访的问题,但外部的应用无法访问集群内的资源,某些应用需要访问集群内的资源,我们需要对外发布服务
- 服务类型
- k8s的ServiceTypes允许指定不同的Service类型,以满足不同的需求,有效的类型有:ClusterIP、NodePort、LoadBalancer、ExternaIName
- ClusterIP:默认类型,只能在集群内部使用,可以实现Pod的自动跟踪与负载均衡,是最核心的服务类型
- NodePort:通过将真实节点的端口映射到ClusterIP服务上,对外暴露服务的类型
- LoadBalancer:使用云提供商的负载均衡器,通过外部路由将流量转发到NodePort和ClusterIP服务上
- ExternaIName:通过CNAME和对应值,可以将外部服务映射到externaIName字段的内容
- 对外发布服务
- 使用基于端口映射(默认值:30000-32767)的NodePort对外发布服务,可以发布任意服务(四层)
- 使用lngress控制器(一般由Nginx或HAProxy构成),用来发布http、https服务(七层)
- LoadBalancer:使用外部云服务或externaIIPs(需要特定的服务或付费支持)
nodePort
[root@master ~]# vim mysvc.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc
spec:
type: NodePort # 指定服务类型
clusterIP: 10.245.1.80
selector:
app: web
ports:
- protocol: TCP
port: 80
nodePort: 30080 # 可选配置,如果不指定就使用随即端口
targetPort: myhttp
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc configured
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 5d18h
mysvc NodePort 10.245.1.80 <none> 80:30080/TCP 17m
# NodePort会在所有节点映射端口,可以访问任意节点
[root@master ~]# curl http://node-0001:30080
Welcome to The Apache.
[root@master ~]# curl http://node-0002:30080
Welcome to The Apache.
[root@master ~]# curl http://node-0003:30080
Welcome to The Apache.
Ingress
- Ingress公开从集群外部到集群内服务的HTTP和HTTPS路由。流量路由由Ingress资源上定义的规则控制
- Ingress控制器通常由负载均衡器来实现(Nginx、HAProxy)
安装Ingress控制器
- Ingress服务由规则+控制器组成
- 规则负责制定策略,控制器负责执行
- 如果没有控制器,单独设置规则无效
- 获取控制器镜像及资源文件
- 地址:http://github.com/kubernetes/ingress-nginx
[root@master ingress]# docker load -i ingress.tar.xz
[root@master ingress]# docker images|while read i t _;do
[[ "${t}" == "TAG" ]] && continue
[[ "${i}" =~ ^"registry:5000/".+ ]] && continue
docker tag ${i}:${t} registry:5000/plugins/${i##*/}:${t}
docker push registry:5000/plugins/${i##*/}:${t}
docker rmi ${i}:${t} registry:5000/plugins/${i##*/}:${t}
done
[root@master ingress]# sed 's,\(image: \).*/\(.*\),\1registry:5000/plugins/\2,' -i deploy.yaml
328: image: registry:5000/plugins/controller:v1.1.0
609: image: registry:5000/plugins/kube-webhook-certgen:v1.1.1
661: image: registry:5000/plugins/kube-webhook-certgen:v1.1.1
[root@master ingress]# kubectl apply -f deploy.yaml
[root@master ingress]# kubectl -n ingress-nginx get pods
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create--1-lm52c 0/1 Completed 0 29s
ingress-nginx-admission-patch--1-sj2lz 0/1 Completed 0 29s
ingress-nginx-controller-5664857866-tql24 0/1 Running 0 29s
创建后端服务
[root@master ~]# vim mysvc.yaml
---
kind: Service
apiVersion: v1
metadata:
name: mysvc
spec:
type: ClusterIP
clusterIP: 10.245.1.80
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master ~]# kubectl apply -f mysvc.yaml
service/mysvc configured
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 5d19h
mysvc ClusterIP 10.245.1.80 <none> 80/TCP 36m
[root@master ~]# kubectl get pods -l app=web --show-labels
NAME READY STATUS RESTARTS AGE LABELS
web1 1/1 Running 0 36m app=web
web2 1/1 Running 0 34m app=web
web3 1/1 Running 0 34m app=web
[root@master ~]# curl http://10.245.1.80
Welcome to The Apache.
对外发布服务
[root@master ~]# kubectl get ingressclasses.networking.k8s.io
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 5m7s
[root@master ~]# vim mying.yaml
---
kind: Ingress # 资源对象类型
apiVersion: networking.k8s.io/v1 # 资源对象版本
metadata: # 元数据
name: mying # 资源对象名称
spec: # 资源对象定义
ingressClassName: nginx # 使用的类名称
rules: # ingress规则定义
- host: test.zhixi.cn # 域名定义,没有可以不写
http: # 协议
paths: # 访问的路径定义
- backend: # 后端服务
service: # 服务声明
name: mysvc # 服务名称
port: # 端口号声明
number: 80 # 访问服务的端口号
path: / # 访问的url路径
pathType: Prefix # 路径类型(implementationSpecific、Exact 、Prefix)
[root@master ~]# kubectl apply -f mying.yaml
ingress.networking.k8s.io/mying created
[root@master ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
mying nginx test.zhixi.cn 192.168.1.51 80 70s
[root@master ~]# curl -H "Host: test.zhixi.cn" http://192.168.1.51
Welcome to The Apache.