ドッカー+ K8S基礎(V)
- サービスリソースの紹介
- A:動作特性サービスリソース
- サービス利用
- A:サービスフィールドの紹介
- B:CLUSTERIPの簡単な使用
- C:NodePortの簡単な使用
- D:ロードバランサ和ExternalName
- E:ヘッドレスサービス
♣:サービス・リソースの説明
:動作特性サービスリソース:
サービスリソースのkubernetes:
ポッドリソースのK8Sクラスタ全体のノード我々は外部要因によってアクセスする必要がある場合、エンドポイントにアクセスするために、実際のサービスの重要な部分を提供最小のオブジェクトで、各ポッドのリソースが矛盾しています私たちはアクセスを提供するために、固定されたエンドポイントへのアクセスを設定する必要があり、アクセスのエンドポイントは覇権とコントロールポッドの下で、中間層、サービスと呼ばれる中間層である、サービスはK8Sと呼ばれる重要な要素に厳密に依存することになりますcoredns(新バージョン)とKUBE-DNS(以前のバージョン1.11に古いバージョン)ので、私たちは、展開時にcoredesまたはKUBE-dnを展開する必要があります。
ネットワーク機能を提供するためにkubernetesクライアント、サードパーティ製のプログラムに依存する必要があり、新しいバージョンでは、このようなプログラムは、任意のサードパーティ製のプログラムは、たとえば、私たちが使用し、CNI(コンテナネットワークプラグインの標準インターフェース)によって、この規格に従うアクセスするために使用することができますフランネルへ。
kubernetes IPアドレス3種類:
1:ネットワーク・ノード
2:ポッドのネットワーク・
ノード・アドレスとポッド現実と配置されています。
3:アドレスが仮想アドレス(仮想IP)であるcluater(クラスタアドレス)またはサービスアドレスと呼ばれるが、これらのアドレスは、ちょうど間の定期的なサービスで表示され、インターフェイスには表示されません。
作業KUBEプロキシコンポーネント上の各ノードは、構成要素が情報サービスリソースの変化のリアルタイム監視となり、本実施形態は、一旦、要求が(時計)の方法によって固有KUBEプロキシによって実現されるモニタサービスリソース(このルールはIPVS iptablesのルールであるか、または、サービスの実装に依存してもよい)KUBEプロキシは、現在のノードが定期的なサービス・スケジュールの上にあることができるの上にそれを変換する必要があり、変更
にサービス実装K8Sの3つのモデルがあります:
1:ユーザ空間(ユーザ空間)
ユーザのアクセスサービス要求が最初KUBEプロキシにおいてサービスによって、上部に到達するリスニングソケットにユーザ空間を変換し、次のプロセスは、サブKUBEをプロキシ完了するそれぞれに関連するサービスへのポッドの上にエージェントにサービスを提供するために、スケジューリングを実現しています。
このモデルは、ユーザのサービス要求は、「ホスト」、ユーザ空間KUBEプロキシ、KUBEプロキシ上記コアのそれぞれの作業を介してワークに転送されるので、効率的でない要求パケットに対してカーネル空間をカプセル化サービスリソースは、サービスが各ポッドのリソースに支配するために予定されています。
2:iptabeles:
リクエストに直接IPサービス要求の現在のユーザーは、要求がカーネル空間内のローカルサービス作業で取らされ、その後に直接関連するポッドを派遣し、全体のスケジュールは、ベースのiptablesのルールで行われます。
3:IPVS:
とiptables同じですが、ルールはIPVSルールを置き換えます。
設定K8SがK8Sは、任意のモードで動作する設定した場合、ルールはIPVSが起動しない場合、それはiptablesのに格下げされ、対応するモード、1.11 IPVSはデフォルトを使用する1.1ユーザ空間の前にデフォルトを生成します。
ポッドリソースのクラスタが変更された場合は、この変更は、それらをECTDのapiserviceに直接格納されるため、この情報はすぐに、上記apiserviceに反応する、この変更はすぐにKUBE-プロキシがそのリソースをサービスに送信されますトリガされますまたはiptablesのルールIPVSに変換し、これらの変換は、動的かつリアルタイムです。
♣2:サービス利用:
A:サービスのフィールドの説明:
[root@www kubeadm]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 77m 在我们初始化集群的时候已然帮忙创建了一个名称叫kubernetes的service资源,这个资源很重要,是保证我们service和集群节点之间联系的,而且10.96.0.1是面向集群内部的地址。 [root@www kubeadm]# kubectl explain svc 也是包含5个一级字段 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 [root@www kubeadm]# kubectl explain svc.spec.ports(ports是用于把那个端口和后端的容器端口建立关联关系) KIND: Service VERSION: v1 RESOURCE: ports <[]Object> DESCRIPTION: The list of ports that are exposed by this service. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies ServicePort contains information on service's port. FIELDS: name <string> The name of this port within the service. This must be a DNS_LABEL. All ports within a ServiceSpec must have unique names. This maps to the 'Name' field in EndpointPort objects. Optional if only one ServicePort is defined on this service. nodePort <integer> The port on each node on which this service is exposed when type=NodePort or LoadBalancer. Usually assigned by the system. If specified, it will be allocated to the service if unused or else creation of the service will fail. Default is to auto-allocate a port if the ServiceType of this Service requires one. More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport port <integer> -required- service的端口 The port that will be exposed by this service. protocol <string> node端口 The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP. targetPort <string> pods端口 Number or name of the port to access on the pods targeted by the service. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If this is a string, it will be looked up as a named port in the target Pod's container ports. If this is not specified, the value of the 'port' field is used (an identity map). This field is ignored for services with clusterIP=None, and should be omitted or set equal to the 'port' field. More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service [root@www kubeadm]# kubectl explain svc.spec.selector (我们需要关联到哪些pods资源上) KIND: Service VERSION: v1 FIELD: selector <map[string]string> DESCRIPTION: Route service traffic to pods with label keys and values matching this selector. If empty or not present, the service is assumed to have an external process managing its endpoints, which Kubernetes will not modify. Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName. More info: https://kubernetes.io/docs/concepts/services-networking/service/ spec.clusterIP(指定固定的ip,创建之后无法改变) [root@www kubeadm]# kubectl explain svc.spec.type (service的类型) KIND: Service VERSION: v1 FIELD: type <string> DESCRIPTION: type determines how the Service is exposed. Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer. "ExternalName" maps to the specified externalName. "ClusterIP" allocates a cluster-internal IP address for load-balancing to endpoints. Endpoints are determined by the selector or if that is not specified, by manual construction of an Endpoints object. If clusterIP is "None", no virtual IP is allocated and the endpoints are published as a set of endpoints rather than a stable IP. "NodePort" builds on ClusterIP and allocates a port on every node which routes to the clusterIP. "LoadBalancer" builds on NodePort and creates an external load-balancer (if supported in the current cloud) which routes to the clusterIP. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
svc.spec.type字段类型:
类型一共分为4种:
1:ExternalName(把集群外部的服务引入到集群内部直接使用);
2:ClusterIP;
3:NodePort(接入外部);
4:LoadBalancer(支持lbaas负载均衡的一键调度)
B:ClusterIP的简单使用:
[root@www TestYaml]# cat redis-svc.yaml apiVersion: v1 kind: Service metadata: name: redis namespace: default spec: selector: app: redis clusterIP: 10.98.98.98 (指定ip创建的时候需要注意网段和地址冲突问题) type: ClusterIP ports: - port: 6379 targetPort: 6379 [root@www TestYaml]# kubectl apply -f redis-svc.yaml service/redis created [root@www TestYaml]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 102m redis ClusterIP 10.98.98.98 <none> 6379/TCP 14s 可以看到redis的ip和端口是配置文件指定的ip和端口 [root@www TestYaml]# 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.98.98.98","... Selector: app=redis Type: ClusterIP IP: 10.98.98.98 Port: <unset> 6379/TCP 指定的service端口 TargetPort: 6379/TCP 指定的pod端口 Endpoints: <none> Session Affinity: None Events: <none> 这里需要说明的是service不会直接到pod,而是需要进过中间层Endpoints的,Endpoints也是k8s上标准的对象,再由Endpoints关联至pods资源上。
C:NodePort的简单使用:
[root@www TestYaml]# cat NodePort.svc.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp clusterIP: 10.99.99.99 type: NodePort ports: - port: 8088 targetPort: 8088 nodePort: 30008 从30000到32767之间的都可以,默认是动态分配的 [root@www TestYaml]# kubectl apply -f NodePort.svc.yaml service/myapp created [root@www TestYaml]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 125m myapp NodePort 10.99.99.99 <none> 8088:30008/TCP 22s service的8088端口映射成node上的30008 redis ClusterIP 10.98.98.98 <none> 6379/TCP 23m 通过此种方式创建的pod就可以在外部直接访问了,只不过要进过好几级转换,先是port,再是protocol,在转换到targetPort上。
D:LoadBalancer和ExternalName:
如果购买了阿里云平台的环境虚拟机(带ibaas负载均衡服务),你在上面搭建了一共k8s的集群服务,k8s会自动去调用云平台的ibaas服务,用软件的方式去把用户的访问请求负载调度至后端的任意一个node节点上,在由节点上的service服务再负载调度至后端的任意一个pod之上,整个过程都是自动的,而且是两级负载均衡调度。
ExternalName:
我们在构建pods的时候本来就是层级关系的,例如db被tomcat访问,tomcat被nginx访问,这种被访问的形式本身就是一种client的存在,那如果是我们的nginx服务在集群外部的某台集群上,想nginx能访问到集群内部的tomcat就需要使用ExternalName,在创建yaml文件的时候ExternalName是一个真实有效且能被dns所解析的服务名,然后用户的访问请求走外部的nginx,nginx在发送请求报文给集群内部的nodeIP到service,有service调度到后端的pod(tomcat),pod在返回给service,最后返回到nginx上,实现访问,但是此种方式用的不多。
[root@www kubeadm]# kubectl explain svc.spec.externalName (externalName只能是类型为ExternalName的时候才有效) KIND: Service VERSION: v1 FIELD: externalName <string> DESCRIPTION: externalName is the external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved. Must be a valid RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) and requires Type to be ExternalName. [root@www kubeadm]#
[root@www kubeadm]# kubectl explain svc.spec.sessionAffinity(svc还支持sessionAffinity) KIND: Service VERSION: v1 FIELD: sessionAffinity <string> DESCRIPTION: Supports "ClientIP" and "None". Used to maintain session affinity. Enable client IP based session affinity. Must be ClientIP or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies 这里的session支持两种,一个是ClientIP,将来自同一个ip访问的请求始终调度到同一个pod上。 None就是默认的随机调度。
E:无头service:
无头service,即值创建service的时候不指定clusterIP,此时用户的访问请求不再是访问clusterIP而是转而访问pod上的ip
[root@www TestYaml]# kubectl explain svc.spec.clusterIP KIND: Service VERSION: v1 FIELD: clusterIP <string> DESCRIPTION: clusterIP is the IP address of the service and is usually assigned randomly by the master. If an address is specified manually and is not in use by others, it will be allocated to the service; otherwise, creation of the service will fail. This field can not be changed through updates. Valid values are "None", empty string (""), or a valid IP address. "None" can be specified for headless services when proxying is not required. Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies 在指定clusterIP的时候可以指定为none(格式是""即可) 案例: [root@www TestYaml]# cat NodePort.svc.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp clusterIP: None 不指定ip ports: - port: 8088 targetPort: 8088 [root@www TestYaml]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 81m myapp ClusterIP None <none> 8088/TCP 9s 可以看到ip是none标记 [root@www TestYaml]# 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,9153/TCP 83m 我们直接去解析coredns的ip就能直接看到pod ip的解析记录 [root@www TestYaml]# dig -t A myapp.default.svc.cluster.local. @10.96.0.10 我们直接解析coredns的ip看看下解析记录 ; <<>> DiG 9.9.4-RedHat-9.9.4-74.el7_6.1 <<>> -t A myapp.default.svc.cluster.local. @10.96.0.10 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60422 ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;myapp.default.svc.cluster.local. IN A ;; ANSWER SECTION: myapp.default.svc.cluster.local. 5 IN A 10.244.2.9 可以看到这里有三个记录,ip分别是2.9,2.8,1.8 myapp.default.svc.cluster.local. 5 IN A 10.244.2.8 myapp.default.svc.cluster.local. 5 IN A 10.244.1.8 ;; Query time: 0 msec ;; SERVER: 10.96.0.10#53(10.96.0.10) ;; WHEN: 日 7月 14 11:29:23 CST 2019 ;; MSG SIZE rcvd: 201 [root@www TestYaml]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-9758dcb6b-hl957 1/1 Running 0 4m6s 10.244.2.8 www.kubernetes.node1.com <none> <none> myapp-9758dcb6b-z8rk6 1/1 Running 0 4m6s 10.244.2.9 www.kubernetes.node1.com <none> <none> myapp-9758dcb6b-zl5jt 1/1 Running 0 4m6s 10.244.1.8 www.kubernetes.node2.com <none> <none> 上面的2.9,2.8,1.8对应的ip就是pod的ip,这样我们得出的结论就是当service没有clusterip的时候就会通过coredns来解析并转发到后端的pod之上。
service很好用,但是也是存在缺陷的,当面我们创建了service的时候,用户访问需要进行两级转换,如果是阿里云的lbaas则是两级调度,其实我们看到的是两级转换,但是落到ipvs或者iptebles之上就是四层调度。因为ipvs和iptables都是四层的,如果我们建立的是https服务的话,例如https对应的名称是myapp,那么你的每一个myapp都要配置成htpps的主机,因为ipvs或者iptables自身是无法卸载https会话的。
kubernetes还有一种引入外部流量的方式,叫ingress(是一种7层调度器)将外部的流量引入到内部来,但是也是无法脱离service的工作,必需要用pod7层功能的应用来调度,起能提供的应用有nginx,haprxoy等。在kubernetes之上应用比较多的是nginx,当然还有别的应用有各自相应的优势。