最近学习k8s遇到很多问题,建了一个qq群:153144292,交流devops、k8s、docker等

service

因为pod是有生命周期的,为了让客户端访问不变,就出现了service,service通过dns(CoreDNS,kube-dns)来实现不变的访问。

node network:节点上
pod network:pod上
cluster network:virtual IP--service ip

每个节点上都工作有kube-proxy,kube-proxy一直和api service连接(watch),service资源有任何变动都通过kube-proxy传达。

三种模型:userspace、iptables、ipvs
userspace--效率低--所有访问都来回在kube-proxy接受调度--1.1-
iptables--由service调度-1.10-
ipvs-1.11+

类型:
    ExternalName、ClusterIP、NodePort、and LoadBalancer
===========================
清单创建service资源
[root@master ~]# kubectl explain svc
[root@master ~]# kubectl explain svc.spec
[root@master ~]# kubectl explain svc.spec.selector
---------------------------
其中重要的4个字段:
apiVersion:
kind:
metadata:
spec:
  clusterIP: 可以自定义,也可以动态分配
  ports:(与后端容器端口关联)
  selector:(关联到哪些pod资源上)
  type:服务类型
service的类型

对一些应用(如 Frontend)的某些部分,可能希望通过外部(Kubernetes 集群外部)IP 地址暴露 Service。
Kubernetes ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型。

Type 的取值以及行为如下:
    ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType。
    NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 <NodeIP>:<NodePort>,可以从集群的外部访问一个 NodePort 服务。
    LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
    ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。 没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。
===========================================
1、ClusterIP的service类型演示:
[root@master manifests]# cat redis-demo.yaml 
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: default
spec:
  selector:
    app: redis
    role: logstor
  type: ClusterIP
  ports:
  - port: 6379
    targetPort: 6379 

[root@k8s-master mainfests]# kubectl apply -f redis-svc.yaml 
service/redis created
[root@k8s-master mainfests]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    36d
redis        ClusterIP   10.107.238.182   <none>        6379/TCP   1m

[root@k8s-master mainfests]# 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":{"ports":[{"port":6379,"targetPort":6379}...
Selector:          app=redis,role=logstor
Type:              ClusterIP
IP:                10.107.238.182  #service ip
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.244.1.16:6379  #此处的ip+端口就是pod的ip+端口
Session Affinity:  None
Events:            <none>

[root@k8s-master mainfests]# kubectl get pod redis-5b5d6fbbbd-v82pw -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
redis-5b5d6fbbbd-v82pw   1/1       Running   0          20d       10.244.1.16   k8s-node01

总结出:service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod

资源创建之后就会在etcd创建一条记录,dns

service的类型

对一些应用(如 Frontend)的某些部分,可能希望通过外部(Kubernetes 集群外部)IP 地址暴露 Service。

Kubernetes ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型。

资源记录:
    SVC_NAME.NS_NAME.DOMAIN.LTD.
    svc.cluster.local.
    redis.default.svc.cluster.local.
=======================================
2、NodePort的service类型演示:
   NodePort即节点Port,通常在部署Kubernetes集群系统时会预留一个端口范围用于NodePort,其范围默认为:30000~32767之间的端口。定义NodePort类型的Service资源时,需要使用.spec.type进行明确指定。
[root@master manifests]# cat myapp-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: 10.99.99.99
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    
[root@master manifests]# kubectl apply -f myapp-svc.yaml 
service/myapp created[root@master manifests]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        11d
myapp        NodePort    10.99.99.99   <none>        80:30080/TCP   40s

[root@master manifests]# kubectl describe svc myapp
Name:                     myapp
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterIP":"10.99.99.99","...
Selector:                 app=myapp,release=canary
Type:                     NodePort
IP:                       10.99.99.99
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.244.1.24:80,10.244.1.25:80,10.244.2.25:80 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

集群之外找一台机器ping node节点的30080
[root@master manifests]# kubectl get pods
NAME                            READY   STATUS    RESTARTS   AGE
liveness-httpget-pod            1/1     Running   1          5d23h
myapp-deploy-69dc8c7655-jkkwv   1/1     Running   0          30h
myapp-deploy-69dc8c7655-q97jc   1/1     Running   0          30h
myapp-deploy-69dc8c7655-sldk8   1/1     Running   0          30h
myapp-deploy-69dc8c7655-v9dvc   1/1     Running   0          30h
myapp-deploy-69dc8c7655-x5qth   1/1     Running   0          30h
nginx-7849c4bbcd-dscjr          1/1     Running   0          9d
nginx-7849c4bbcd-vdd45          1/1     Running   0          9d
nginx-7849c4bbcd-wrvks          1/1     Running   0          9d
nginx-deploy-84cbfc56b6-mjcw5   1/1     Running   0          9d

echo myapp-deploy-69dc8c7655-jkkwv >/usr/share/nginx/html/index.html
echo myapp-deploy-69dc8c7655-q97jc >/usr/share/nginx/html/index.html
echo myapp-deploy-69dc8c7655-sldk8 >/usr/share/nginx/html/index.html
echo myapp-deploy-69dc8c7655-v9dvc >/usr/share/nginx/html/index.html
echo myapp-deploy-69dc8c7655-x5qth >/usr/share/nginx/html/index.html
# cat index.html
1
# exit
[root@master manifests]# kubectl exec -it myapp-deploy-69dc8c7655-jkkwv -- /bin/sh
[root@master manifests]#kubectl exec -it myapp-deploy-69dc8c7655-q97jc -- /bin/sh
# echo myapp-deploy-69dc8c7655-q97jc >/usr/share/nginx/html/index.html
# exit
[root@master manifests]# kubectl exec -it myapp-deploy-69dc8c7655-sldk8 -- /bin/sh
# echo myapp-deploy-69dc8c7655-sldk8 >/usr/share/nginx/html/index.html
# exit
[root@master manifests]# kubectl exec -it myapp-deploy-69dc8c7655-v9dvc  -- /bin/sh
# echo myapp-deploy-69dc8c7655-v9dvc >/usr/share/nginx/html/index.html
# exit
[root@master manifests]# kubectl exec -it myapp-deploy-69dc8c7655-x5qth  -- /bin/sh
# echo myapp-deploy-69dc8c7655-x5qth >/usr/share/nginx/html/index.html

[root@haproslave ~]# while true;do curl http://10.249.6.101:30080/index.html; sleep 1; done
myapp-deploy-69dc8c7655-sldk8
1
myapp-deploy-69dc8c7655-x5qth
myapp-deploy-69dc8c7655-x5qth
myapp-deploy-69dc8c7655-sldk8
1
myapp-deploy-69dc8c7655-x5qth
myapp-deploy-69dc8c7655-sldk8
myapp-deploy-69dc8c7655-q97jc
myapp-deploy-69dc8c7655-v9dvc
myapp-deploy-69dc8c7655-q97jc
myapp-deploy-69dc8c7655-q97jc
myapp-deploy-69dc8c7655-v9dvc

可以看到通过NodePort方式已经实现了从集群外部端口进行访问,访问链接如下:http://nodeip:30080/。
实践中并不鼓励用户自定义使用节点的端口,因为容易和其他现存的Service冲突,建议留给系统自动配置。

现在在集群外做一个lvs或者haproxy即可实现负载均衡
==========================
3、LoadBalancer  我们这里做不到
一般在公有云上做:云负载均衡--代理到nodeip--serviceip--pod
==========================
4、ExternalName
服务在k8s之外,我们期望内部的pod能够访问到,这里我就要建立一个ExternalName service服务,通过关联到外部服务,各种转换,由nodeip转换。
这样就可以像使用内部服务一样使用外部服务。
===========================
5、Pod的会话保持
  Service资源还支持Session affinity(粘性会话)机制,可以将来自同一个客户端的请求始终转发至同一个后端的Pod对象,这意味着它会影响调度算法的流量分发功用,进而降低其负载均衡的效果。因此,当客户端访问Pod中的应用程序时,如果有基于客户端身份保存某些私有信息,并基于这些私有信息追踪用户的活动等一类的需求时,那么应该启用session affinity机制。

  Service affinity的效果仅仅在一段时间内生效,默认值为10800秒,超出时长,客户端再次访问会重新调度。该机制仅能基于客户端IP地址识别客户端身份,它会将经由同一个NAT服务器进行原地址转换的所有客户端识别为同一个客户端,由此可知,其调度的效果并不理想。Service 资源 通过. spec. sessionAffinity 和. spec. sessionAffinityConfig 两个字段配置粘性会话。 spec. sessionAffinity 字段用于定义要使用的粘性会话的类型,它仅支持使用“ None” 和“ ClientIP” 两种属性值。如下:
[root@master manifests]# cat myapp-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  sessionAffinity: ClientIP   这里新增,也可以使用命令
  clusterIP: 10.99.99.99
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
使用上面修改配置文件就需要执行
[root@master mainfests]# kubectl apply -f myapp-svc.yaml 
直接使用命令
[root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}'  #session保持,同一ip访问同一个pod
service/myapp patched

[root@master manifests]# kubectl describe svc myapp
Name:                     myapp
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterIP":"10.99.99.99","...
Selector:                 app=myapp,release=canary
Type:                     NodePort
IP:                       10.99.99.99
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.244.1.24:80,10.244.1.25:80,10.244.2.25:80 + 2 more...
Session Affinity:         ClientIP  这里生效了
External Traffic Policy:  Cluster
Events:                   <none>

[root@haproslave ~]# while true;do curl http://10.249.6.101:30080/; sleep 1; done
1
1
1
1
1
1

取消session,可以是命令行或者是修改yaml
kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"None"}}'
可以看到立马生效了
[root@haproslave ~]# while true;do curl http://10.249.6.101:30080/; sleep 1; done
1
1
1
1
1
myapp-deploy-69dc8c7655-v9dvc
myapp-deploy-69dc8c7655-x5qth
myapp-deploy-69dc8c7655-x5qth
myapp-deploy-69dc8c7655-sldk8
myapp-deploy-69dc8c7655-x5qth
===========================
6、Headless Service(无头)
  有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。
  这个选项允许开发人员自由寻找他们自己的方式,从而降低与 Kubernetes 系统的耦合性。 应用仍然可以使用一种自注册的模式和适配器,对其它需要发现机制的系统能够很容易地基于这个 API 来构建。
[root@master manifests]# cat myapp-svc-headless.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: "None"
  ports:
  - port: 80
    targetPort: 80
    
[root@master manifests]# kubectl apply -f myapp-svc-headless.yaml 
service/myapp-headless created

[root@master manifests]# 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   11d

[root@master manifests]# kubectl get pods -o wide -l app=myapp
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
myapp-deploy-69dc8c7655-jkkwv   1/1     Running   0          31h   10.244.1.24   node01   <none>           <none>
myapp-deploy-69dc8c7655-q97jc   1/1     Running   0          31h   10.244.2.25   node02   <none>           <none>
myapp-deploy-69dc8c7655-sldk8   1/1     Running   0          30h   10.244.2.27   node02   <none>           <none>
myapp-deploy-69dc8c7655-v9dvc   1/1     Running   0          30h   10.244.2.28   node02   <none>           <none>
myapp-deploy-69dc8c7655-x5qth   1/1     Running   0          31h   10.244.1.25   node01   <none>           <none>

[root@master manifests]# dig -t A myapp-headless.default.svc.cluster.local. @10.96.0.10

; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> -t A myapp-headless.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41896
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;myapp-headless.default.svc.cluster.local. IN A

;; ANSWER SECTION:
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.2.25
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.1.24
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.2.28
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.2.27
myapp-headless.default.svc.cluster.local. 5 IN A 10.244.1.25

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Mar 11 10:26:13 EDT 2019
;; MSG SIZE  rcvd: 338

对比含有ClusterIP的service解析
[root@master manifests]# dig -t A myapp.default.svc.cluster.local. @10.96.0.10

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

;; QUESTION SECTION:
;myapp.default.svc.cluster.local. IN    A

;; ANSWER SECTION:
myapp.default.svc.cluster.local. 5 IN    A    10.99.99.99

;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Mar 11 10:27:51 EDT 2019
;; MSG SIZE  rcvd: 96

[root@master manifests]# kubectl get svc
NAME             TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes       ClusterIP   10.96.0.1     <none>        443/TCP        11d
myapp            NodePort    10.99.99.99   <none>        80:30080/TCP   46m
myapp-headless   ClusterIP   None          <none>        80/TCP         2m35

从以上的演示可以看到对比普通的service和headless service,headless service做dns解析是直接解析到pod的,而servcie是解析到ClusterIP的,那么headless有什么用呢???这将在statefulset中应用到,这里暂时仅仅做了解什么是headless service和创建方法。
===========================
[root@master ~]# kubectl get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP   11d
nginx-deploy   ClusterIP   10.100.251.191   <none>        80/TCP    10d
[root@master ~]# kubectl delete svc nginx-deploy
service "nginx-deploy" deleted
[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11d
[root@master ~]# kubectl explain svc
KIND:     Service
VERSION:  v1

DESCRIPTION:
     Service is a named abstraction of software service (for example, mysql)
     consisting of local port (for example 3306) that the proxy listens on, and
     the selector that determines which pods will answer requests sent through
     the proxy.

FIELDS:
   apiVersion    <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#resources

kind    <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds

metadata    <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

spec    <Object>
     Spec defines the behavior of a service.
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

status    <Object>
     Most recently observed status of the service. Populated by the system.
     Read-only. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

群名称:k8s学习群   群   号:153144292

kubenetes入门学习-十-service相关推荐

  1. OpenGL入门学习(十五)

    OpenGL入门学习[十五] 这次讲的所有内容都装在一个立方体中,呵呵. 呵呵,绘制一个立方体,简单呀,我们学了第一课第二课,早就会了. 先别着急,立方体是很简单,但是这里只是拿立方体做一个例子,来说 ...

  2. Linux入门学习(十二)

    软件安装 软件名称识别 [abrt-addon-ccpp]-[2.1.11-19].[el7].[x86_64].rpm :rpm结尾的适用与redhat操作系统 软件名 abrt-addon-ccp ...

  3. Linux入门学习(十)

    管理网络 ip基础知识 ipv4 2进制32位-–10进制 172.25.0.10/255.255.255.0 172.25.0.10:ip地址 255.255.255.0:子网掩码 子网掩码255位 ...

  4. 【转】OpenGL入门学习[十五]

    这次讲的所有内容都装在一个立方体中,呵呵. 呵呵,绘制一个立方体,简单呀,我们学了第一课第二课,早就会了. 先别着急,立方体是很简单,但是这里只是拿立方体做一个例子,来说明OpenGL在绘制方法上的改 ...

  5. 最全面的openGL 入门学习

    自己在找openGL学习资料的时候,找到此篇openGL入门学习(虽然不是移动开发,但给我提供了非常好的思路),所以转一下让更多人知道,本文来自http://www.cppblog.com/doing ...

  6. OpenGL编程入门学习

    OpenGL编程入门学习  非常详细的教程,很适合初学者 本文转自:http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html === ...

  7. OpenGLGLUT入门学习

    本文为转载,原文出处:OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的? ...

  8. OpenGL入门学习 (转)

    OpenGL入门学习 (转) 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜 ...

  9. OpenGL入门学习[三]

    OpenGL入门学习[三] http://xiaxveliang.blog.163.com/blog/static/2970803420126246501930/ OpenGL入门学习[十一] 我们在 ...

最新文章

  1. C++ 三五法则,看看你能不能理解
  2. 艾伟_转载:C# Design Patterns (3) - Decorator
  3. Linux su切换用户后命令提示符变为bash-4.2$
  4. 取火的N种方式:学好物理是野外求生第一步
  5. 一叶障目:排查问题的思路
  6. 03MyBatis动态sql
  7. 正则表达式 6. 存在(或)
  8. 购买物品_1美元能买些啥?盘点1美元在10个不同的国家所能购买的物品
  9. [MATLAB]设置坐标轴标签
  10. java属性定义_Java管理扩展指南--几分钟带你理解MBean
  11. sublime3定制化为python3编辑利器。
  12. 怎样测试通达信软件,如何测试通达信指标成功率?
  13. polkit启动失败_Linux MySQL 常见无法启动或启动异常的解决方案
  14. 杭州异地身份证办理条件以及材料
  15. drawline java_Java代码g.drawLine(100,100,100,100)的功能是()
  16. Java应届生面试必备考题(附答案)
  17. SHELL脚本下获取文件时间转换时间戳,使用时间戳计算日期差
  18. 计算机导论alu的全名,计算机导论试题1.doc
  19. Java设计模式第一章(软件设计原则)(学习笔记)
  20. python爬取微博热门消息(一)——效果展示

热门文章

  1. 【安卓Handler】Handler消息机制
  2. 《吐血整理》Linux面试题Top100@面试官你好,我精通Linux!嘿嘿~
  3. vue实际运用五:不需要响应式的数据的处理
  4. java基于微信小程序的流浪猫狗动物收养系统 uniapp 小程序
  5. 通过面向对象实现猫狗大战案例
  6. KITTI数据集学习笔记
  7. lamp 安装 mysql_LAMP 之 mysql 安装
  8. 软件工程小组项目——单词计数
  9. IBM欧洲裁员一万人、Salesforce 考虑收购 Slack​、杰夫·贝佐斯如何做决定等|Decode the Week...
  10. 【E文件解析】Java实现E文件解析为对象