一起来学k8s 10.service

Service

Kubernetes集群为我们提供了这样的一个对象 ServiceService是一种抽象的对象,它定义了一组Pod的逻辑集合和一个用于访问它们的策略,其实这个概念和微服务非常类似。一个Serivce下面包含的Pod集合一般是由Label Selector来决定的。
一起来学k8s 10.service

环境

192.168.48.101 master01
192.168.48.201 node01
192.168.48.202 node0

三种IP

在继续往下学习Service之前,我们需要先弄明白Kubernetes系统中的三种IP这个问题,因为经常有同学混乱。

  • Node IP:Node节点的IP地址
  • Pod IP: Pod的IP地址
  • Cluster IP: ServiceIP地址

首先,Node IPKubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络的服务器之间都可以直接通信,所以Kubernetes集群外要想访问Kubernetes集群内部的某个节点或者服务,肯定得通过Node IP进行通信(这个时候一般是通过外网IP了)

然后Pod IP是每个PodIP地址,它是Docker Engine根据docker0网桥的IP地址段进行分配的(我们这里使用的是flannel这种网络插件保证所有节点的Pod IP不会冲突)

最后Cluster IP是一个虚拟的IP,仅仅作用于Kubernetes Service这个对象,由Kubernetes自己来进行管理和分配地址,当然我们也无法ping这个地址,他没有一个真正的实体对象来响应,他只能结合Service Port来组成一个可以通信的服务。

定义Service

先创建一个deployment

vim myapp-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
  labels:
    app: myapp
    type: deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      type: deploy
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        type: deploy
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

[root@master01 deploy_yaml]# kubectl apply -f myapp-deploy.yaml 
deployment.apps/myapp-deploy created

[root@master01 deploy_yaml]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
myapp-deploy-8675c97685-6br95   1/1     Running   0          21s   10.244.1.51   node01   <none>           <none>
myapp-deploy-8675c97685-d9jh4   1/1     Running   0          21s   10.244.2.42   node02   <none>           <none>

直接访问pod试试

[root@master01 deploy_yaml]# curl 10.244.1.51
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 deploy_yaml]# curl 10.244.2.42
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 deploy_yaml]# 

创建service

Cluster IP

vim myapp-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
  labels:
    type: svc
    app: myapp
spec:
  selector:
    app: myapp
    type: deploy
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http

[root@master01 svc_yaml]# kubectl apply  -f myapp-svc.yaml 
service/myapp-svc created


[root@master01 svc_yaml]# kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   10d   <none>
myapp-svc    ClusterIP   10.102.65.215   <none>        80/TCP    39s   app=myapp,type=deploy

Service能够将一个接收端口映射到任意的targetPort。 默认情况下,targetPort将被设置为与port字段相同的值。 Service能够支持 TCP 和 UDP 协议,默认是 TCP 协议。

测试试试

[root@master01 svc_yaml]# curl 10.102.65.215
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

NodePort

vim myapp-svc.yaml 

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
  labels:
    type: svc
    app: myapp
spec:
  selector:
    app: myapp
    type: deploy
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    protocol: TCP
    name: http

[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml 
service/myapp-svc configured
[root@master01 svc_yaml]# kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        10d     <none>
myapp-svc    NodePort    10.102.65.215   <none>        80:30080/TCP   6m25s   app=myapp,type=deploy

测试

[root@master01 svc_yaml]# curl 10.102.65.215
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 svc_yaml]# curl 192.168.48.200:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 svc_yaml]# curl 192.168.48.201:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 svc_yaml]# curl 192.168.48.202:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>



默认调度是轮训

[root@master01 svc_yaml]# while true;do curl 192.168.48.200:30080/hostname.html;sleep 1;done
myapp-deploy-8675c97685-6br95
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-6br95
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-6br95
myapp-deploy-8675c97685-d9jh4


sessionAffinity: ClientIP

也可以pod绑定

vim myapp-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
  labels:
    type: svc
    app: myapp
spec:
  selector:
    app: myapp
    type: deploy
  type: NodePort
  sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    protocol: TCP
    name: http


[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml 
service/myapp-svc configured
[root@master01 svc_yaml]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        10d
myapp-svc    NodePort    10.102.65.215   <none>        80:30080/TCP   16m


测试试试

[root@master01 svc_yaml]# while true;do curl 192.168.48.200:30080/hostname.html;sleep 1;done
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4


无头service

vim myapp-svc.yaml 


apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
  labels:
    type: svc
    app: myapp
spec:
  selector:
    app: myapp
    type: deploy
  clusterIP: None
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
                

[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml 
service/myapp-svc created

[root@master01 svc_yaml]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   10d
myapp-svc    ClusterIP   None         <none>        80/TCP    28s


解析测试下

[root@master01 svc_yaml]# yum install bind-utils -y

[root@master01 svc_yaml]# kubectl get svc -n kube-system 
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
heapster               ClusterIP   10.108.106.25   <none>        80/TCP                   2d
kube-dns               ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   10d
kubernetes-dashboard   NodePort    10.103.36.52    <none>        443:30001/TCP            2d2h
metrics-server         ClusterIP   10.100.95.210   <none>        443/TCP                  2d1h

[root@master01 svc_yaml]# dig -t A myapp-svc.default.svc.cluster.local @10.96.0.10

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> -t A myapp-svc.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55803
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-svc.default.svc.cluster.local. IN	A

;; ANSWER SECTION:
myapp-svc.default.svc.cluster.local. 5 IN A	10.244.2.42
myapp-svc.default.svc.cluster.local. 5 IN A	10.244.1.51

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Apr 10 21:51:25 CST 2019
;; MSG SIZE  rcvd: 166



ExternalName

ExternalName 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。 对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

当查询主机 my-service.prod.svc.cluster.local (后面服务发现的时候我们会再深入讲解)时,集群的 DNS 服务将返回一个值为 my.database.example.com 的 CNAME 记录。 访问这个服务的工作方式与其它的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。

上一篇:k8s中的pod控制器之Deployment、DaemonSet、StatefulSet


下一篇:腾讯知文自然语言处理平台上云实践