k8s基本使用入门-了解Service

1、引入

现在准备了两个 pod 的 yaml 文件
pod_nginx.yml

[root@kube-node01 yaml]$ cat pod_nginx.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - name: nginx-port
      containerPort: 80

pod_busybox.yml

[root@kube-node01 yaml]$ cat pod_busybox.yml
apiVersion: v1
kind: Pod
metadata:
  name: busybox-pod
  labels:
    app: busybox
spec:
  containers:
  - name: busybox-container
    image: busybox
    command:
      - sleep
      - "360000"

启动

kubectl create -f pod_nginx.yml
kubectl create -f pod_busybox.yml

然后看一下两个 pod 的 ip:

[root@kube-node01 yaml]$ kubectl get pod -o wide
NAME          READY     STATUS    RESTARTS   AGE       IP            NODE
busybox-pod   1/1       Running   0          15m       10.244.1.58   node
nginx-pod     1/1       Running   0          15m       10.244.1.59   node

此时,这两个生成的 ip,在集群当中任一节点里,都是可以畅通访问的。


image.png

详细的介绍,可以看官方的文档介绍:https://kubernetes.io/docs/concepts/cluster-administration/networking/

2、缘由

现在可以思考一个问题:为什么不直接通过 pod 来作为 k8s 的管理单位进行管理呢?

  • 当我们使用 ReplicaSet 或者 ReplicationController 做水平扩展 scale 的时候,Pod 会在这个过程中被 terminated,随着这个更替,Pod 的 ip 等的也都在变幻。

  • 当我们使用 Deployment 的时候,我们去更新 Docker Image Version,旧的 Pods 会被 terminated,然后新的 Pods 创建,这个过程中,同样会发生 Pod 的 ip 改变等问题。从而难于对其进行访问。

3、service 概念

之于如上所提问题,那么就引入了 service 这个概念。

k8s 分配给 Service 一个固定 IP,这是一个虚拟 IP(也称为 ClusterIP),并不是一个真实存在的 IP,而是由 k8s 虚拟出来的。虚拟 IP 的范围通过 k8s API Server 的启动参数 –service-cluster-ip-range=19.254.0.0/16 配置;

虚拟 IP 属于 k8s 内部的虚拟网络,外部是寻址不到的。在 k8s 系统中,实际上是由 k8s Proxy 组件负责实现虚拟 IP 路由和转发的,所以 k8s Node 中都必须运行了 k8s Proxy,从而在容器覆盖网络之上又实现了 k8s 层级的虚拟转发网络。

服务代理:

在逻辑层面上,Service 被认为是真实应用的抽象,每一个 Service 关联着一系列的 Pod。在物理层面上,Service 有事真实应用的代理服务器,对外表现为一个单一访问入口,通过 k8s Proxy 转发请求到 Service 关联的 Pod。

Service 同样是根据 Label Selector 来刷选 Pod 进行关联的,实际上 k8s 在 Service 和 Pod 之间通过 Endpoint 衔接,Endpoints 同 Service 关联的 Pod;相对应,可以认为是 Service 的服务代理后端,k8s 会根据 Service 关联到 Pod 的 PodIP 信息组合成一个 Endpoints。

4、service 几种类型。

1)ClusterIP 方式
kubernetes 默认就是这种方式,是集群内部访问的方式,外部的话,是无法访问的。

[root@kube-node01 yaml]$ cat XX.yaml
spec:
  clusterIP: 内网IP
  ports:
  - name: http

2)NodePort 方式

[root@kube-node01 yaml]$ cat XX.yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"creationTimestamp":"20XX-XX-XXTXX:XX:XXZ","labels":{"kubernetes.io/name":"heapster","plugin":"heapster"},"name":"heapster","namespace":"kube-system","resourceVersion":"173906247","selfLink":"/api/v1/namespaces/kube-system/services/heapster","uid":"91470fbb-404b-11e7-ba41-5254eec04736"},"spec":{"clusterIP":"节点 IP ","externalTrafficPolicy":"Cluster","ports":[{"nodePort":30003,"port":80,"protocol":"TCP","targetPort":8082}],"selector":{"k8s-app":"heapster"},"sessionAffinity":"None","type":"NodePort"},"status":{"loadBalancer":{}}}
  creationTimestamp: 20XX-XX-XXTXX:XX:XXZ
  labels:
    kubernetes.io/name: heapster
    plugin: heapster
  name: heapster
  namespace: kube-system
  resourceVersion: "789489505"
  selfLink: /api/v1/namespaces/kube-system/services/heapster
  uid: e56886a2-8fb9-11e8-acd2-5254171bf8db
spec:
  clusterIP: 节点 IP
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30003
    port: 80
    protocol: TCP
    targetPort: 8082
  selector:
    k8s-app: heapster
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

3)LoadBalancer 方式
这种方式主要是利用其他第三方的 LB 暴露服务的,谷歌或者亚马逊的 LB 等等

[root@kube-node01 yaml]$ cat XX.yaml
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
  clusterIP: 10.0.171.239
  loadBalancerIP: 78.11.24.19
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 146.148.47.155

4)ExternalName 方式
这种方式主要是通过 CNAME 实现的,在 kubernetes 1.7.x 以及以上才支持这种方式,例如

[root@kube-node01 yaml]$ cat XX.yaml
kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

访问时,kube-dns 服务直接解析到指定的 Cnamemy.database.example.com 这个域名上

5、service 学习示例

1)cluster IP
首先准备一个 deployment 的 yaml 文件:

[root@kube-node01 yaml]$  cat deployment_python_http.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service_test_pod
  template:
    metadata:
      labels:
        app: service_test_pod
    spec:
      containers:
      - name: simple-http
        image: python:2.7
        imagePullPolicy: IfNotPresent
        command: ["/bin/bash"]
        args: ["-c","echo \"<p>Hello from $(hostname)<p>\" > index.html; python -m SimpleHTTPServer 8080"]
        ports:
        - name: http
          containerPort: 8080

创建之前,可以先在 node 节点将镜像 pull 下来,以免等会儿创建的时候比较慢

[root@kube-node01 yaml]$ kubectl create -f deployment_python_http.yaml
deployment.extensions "service-test" created

[root@kube-node01 yaml]$ kubectl get deployment
NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
service-test   2         2         2            2           10m

[root@kube-node01 yaml]$ kubectl get pod
NAME                            READY     STATUS    RESTARTS   AGE
service-test-7bd7775475-ltbfc   1/1       Running   0          6m
service-test-7bd7775475-m4pbv   1/1       Running   0          6m

先在分别访问一下这两个 pod:

[root@kube-node01 yaml]$ kubectl describe pod service-test-7bd7775475-ltbfc|grep IP
IP:             172.30.64.2

[root@kube-node01 yaml]$ kubectl describe pod service-test-7bd7775475-m4pbv|grep IP
IP:             172.30.87.2

[root@kube-node01 yaml]$ curl 172.30.64.2:8080
<p>Hello from service-test-7bd7775475-ltbfc<p>

[root@kube-node01 yaml]$ curl 172.30.87.2:8080
<p>Hello from service-test-7bd7775475-m4pbv<p>

看到返回了两个不同的结果,之前有对这个名称做过分析,那么现在将请求的返回数据掐在 service 阶段,从而让访问统一,让返回值负载均衡。

实验快速更新部署:
现在同时开启两个窗口,一个窗口一直 curl 刚刚的 CLUSTER-IP


image.png

那么现在模拟应用升级,可以通过直接编译 yaml 文件来实现

[root@kube-node01 yaml]$ kubectl edit deployment service-test
在刚刚的echo处更改一下输出: 
添加一个new version然后保存退出:
- echo "<p>Hello from new version $(hostname)<p>" > index.html; python -m

deployment.extensions "service-test" edited

不用动,可以看到下边的输出已经自动的变化了,基本上零停顿

image.png

2)NodePort
了解之前,先将之前所有的环境都清理一波,还原成一个干净的环境。

2.1)通过指令创建 NodePort
准备有 nginx 的一个 yaml 文件:

[root@kube-node01 yaml]$ cat pod_nginx.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - name: nginx-port
      containerPort: 80

启动这个常规的 pod:

[root@kube-node01 yaml]$ kubectl create -f pod_nginx.yml
pod "nginx-pod" created

[root@kube-node01 yaml]$ kubectl get pod
NAME                            READY     STATUS    RESTARTS   AGE
nginx-pod                       1/1       Running   0          7s
service-test-7ddddbdd69-b7s2x   1/1       Running   0          27m
service-test-7ddddbdd69-hqgxb   1/1       Running   0          29m


[root@kube-node01 yaml]$ kubectl get pod -o wide
NAME                            READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-pod                       1/1       Running   0          15s       172.30.87.2   kube-node02
service-test-7ddddbdd69-b7s2x   1/1       Running   0          27m       172.30.87.3   kube-node02
service-test-7ddddbdd69-hqgxb   1/1       Running   0          29m       172.30.84.2   kube-node01

现在将其配置为 NodePort 的形式,使用如下指令:

[root@kube-node01 yaml]$ kubectl expose pod nginx-pod --type=NodePort
service "nginx-pod" exposed

[root@kube-node01 yaml]$ kubectl get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)       AGE
kubernetes         ClusterIP   10.254.0.1       <none>        443/TCP       3d
nginx-pod          NodePort    10.254.202.150   <none>        80:8675/TCP   19s

这个时候可以看到类型变成 NodePort 了,而且后边也详细标出了端口的映射关系,是将 pod 的 80 端口映射到 node 的 8675 上。

那么现在就可以通过这种方式就可以访问了:
master


image.png

node1~2


image.png

2.2)通过 yaml 形式创建 NodePort。
现在介绍另外一种情况,介绍之前,先将刚刚的 service 删除。

[root@kube-node01 yaml]$ kubectl get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)       AGE
kubernetes         ClusterIP   10.254.0.1       <none>        443/TCP       3d
nginx-pod          NodePort    10.254.202.150   <none>        80:8675/TCP   8m

[root@kube-node01 yaml]$ kubectl delete svc nginx-pod
service "nginx-pod" deleted

[root@kube-node01 yaml]$ kubectl get svc
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)       AGE
kubernetes         ClusterIP   10.254.0.1      <none>        443/TCP       3d

然后添加一个文件:

[root@kube-node01 yaml]$ more service_nginx.yml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 8999
    nodePort: 8999
    targetPort: nginx-port
    protocol: TCP
  selector:
    app: nginx
  type: NodePort

此文件内容是基于刚刚还存在的 pod 而成立的,selector,就是检索刚刚创建的 nginx 的 pod,然后直接将端口类型设置为 NodePort,端口为 8999。

然后创建之:

[root@kube-node01 yaml]$ kubectl create -f service_nginx.yml
service "nginx-service" created

[root@kube-node01 ~]$ kubectl get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
kubernetes         ClusterIP   10.254.0.1       <none>        443/TCP         3d
nginx-service      NodePort    10.254.184.147   <none>        8999:8999/TCP   1m

访问之:


image.png

kubeadm 更改NodePort端口范围

提示:The Service "nginx-service" is invalid: spec.ports[0].nodePort: Invalid value: 8999: provided port is not in the valid range. The range of valid ports is 30000-32767

1)配置文件里,一般的在这个文件夹下: /etc/kubernetes/manifests/
2)找到文件名为kube-apiserver.yaml的文件,也可能是json格式
3)编辑添加配置 service-node-port-range=1000-9999

[root@master01 manifests]# sed -n "12,43p" /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    ..........
    - --service-node-port-range=1000-9999   # 添加配置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容