Service(サービス)とは何ですか?

Service(サービス)は、Kubernetesで最も重要なリソースオブジェクトの1つであり、サービスはアクセスポイントのアドレスを定義し、フロントエンドのアプリケーション(Pod)はこのアクセスポイントを使用してその背後にある一連のPodレプリカで構成されるクラスターインスタンスにアクセスします。 ServiceとそのバックエンドのPodレプリカの間の関係は、ラベルセレクターを使用して “シームレスな接続”を実現します。そして、RCの役割は実際には、Serviceのサービス能力とサービス品質が予想される基準にあることを保証することです。

Kubernetesが提供するマイクロサービスネットワークアーキテクチャ

すべてのサービスを分析、識別し、システム内のすべてのサービスをマイクロサービスとしてモデル化することにより—Kubernetesサービス、最終的には、私たちのシステムは異なるビジネス機能を提供し、お互いに独立している複数のマイクロサービスユニットで構成されます。サービス間の通信はTCP/IPを介して行われ、強力な分散能力、弾力性のある拡張能力、耐障害性を備えています。

各Podには個別のIPアドレスが割り当てられ、各Podはクライアントがアクセスするための独自のエンドポイント(Pod IP+コンテナポート)を提供します。現在、複数のPodレプリカがアクセスを提供するためにクラスターを形成しました。

Kubernetesは、各Nodeにkube-proxyをインストールする必要があります。kube-proxyプロセスは実際にはスマートなソフトウェアロードバランサーであり、Serviceへのリクエストをバックエンドの特定のPodインスタンスに転送し、サービスの負荷分散とセッション維持メカニズムを内部で実装します。

Kubernetesは、非常に巧妙なデザインを考案しました。Serviceは負荷分散器のIPアドレスを共有するのではなく、各Serviceにはグローバルでユニークな仮想IPアドレスが割り当てられます。この仮想IPはCluster IPと呼ばれます。これにより、各サービスは”通信ノード”として一意のIPアドレスを持つことになり、サービス呼び出しは最も基本的なTCPネットワーク通信の問題に変わります。

Podのエンドポイントアドレスは、Podが破棄され、再作成されるたびに変更されます。新しいPodアドレスは以前の古いPodとは異なります。一方、Serviceが作成されると、Kubernetesは自動的に使用可能なCluster IPを割り当て、Serviceのライフサイクル全体でそのCluster IPが変更されないようにします。したがって、Serviceの名前とServiceのCluster IPアドレスをDNSドメインマッピングとして使用するだけで問題が解決します。

Serviceの作成
例:Serviceの手動作成

kind: Service
apiVersion: v1
metadata:
  name: mallh5-service
  namespace: abcdocker
spec:
  selector:
    app: mallh5web
  type: NodePort
  ports:
    - protocol: TCP      #仅支持TCP和UDP,不写默认TCP
      port: 3017
      targetPort: 5003
      nodePort: 31122

パラメーターの解説
ポート:ポートは、サービスがクラスターIP(サーバーIP)で公開されるポートを表します。 :ポートは、クラスター内のクライアントがサービスにアクセスするための入り口を提供します。
ノードポート:ノードポートは、Kubernetesが外部クライアントがサービスにアクセスするための入り口として提供する方法の1つです(もう1つの方法はLoadBalancerです)。 :ノードポートは、クラスターの外部クライアントがサービスにアクセスするための入り口を提供します。
ターゲットポート:ターゲットポートは非常に理解しやすいです。ターゲットポートは、ポッド上のポートであり、ポートとノードポートを通過するデータが最終的にはkube-proxyを介してバックエンドのポッドのターゲットポートに入るためです。
作成

[root@master test]# kubectl create -f abcdocker-server.yaml
service/mallh5-service created

サーバーの詳細情報を表示

[root@master test]# kubectl get service --namespace=abcdocker
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
mallh5-service   NodePort   10.254.22.153   <none>        

 3017:31122/TCP   13m
[root@master test]# kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.254.0.1       <none>         443/TCP        35d
nginx-service   NodePort    10.254.200.178   <none>         80:31000/TCP   34d
[root@abcdockeryaml]# kubectl describe svc myserver
Name:              myserver     #名称
Namespace:         default      #命名空間
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx    #マッチングPodラベル
Type:              ClusterIP    #svc IPタイプ
IP:                10.254.219.137   #svc IPアドレス
Port:              mynginx-http  80/TCP   #svcポート(ビジネスに応じてポートを調整できます)
TargetPort:        80/TCP       #ポッドポート
Endpoints:         172.30.144.2:80  #一致するポッドIP
Session Affinity:  None
Events:            <none>

外部システムへのServiceのアクセス問題

Kubernetes内の3種類のIPを理解する必要があります。

  1. ノードIP:ノードのIPアドレス
  2. Pod IP:PodのIPアドレス
  3. クラスターIP:ServiceのIPアドレス

パラメータの説明:

  1. ノードIPは、Kubernetesクラスター内の各ノードの物理的なネットワークインターフェイスのIPアドレスです。これは実際の物理ネットワークであり、このネットワークに属するすべてのサーバーは、ネットワーク内に存在するかどうかに関係なく、このネットワークを介して直接通信できます。Kubernetes外のノードがKubernetes内のノードまたはTCP/IPサービスにアクセスする場合、ノードIPを介して通信する必要があります。

サーバーへのアクセスグラフ

  1. Pod IPは、各PodのIPアドレスであり、Docker Engineがdocker0ブリッジのIPアドレス範囲に基づいて割り当てます。通常、これは仮想的なレイヤ2ネットワークです。Kubernetesは、異なるノード上にあるPodがお互いに直接通信できるようにする必要があります。したがって、KubernetesのPod内のコンテナは、Pod IPがある仮想レイヤ2ネットワークを介して通信し、実際のTCP/IPトラフィックは物理ネットワークカードのIPアドレスを通じてフローします。
  2. クラスターIPは、仮想IPであり、ほとんど偽のIPネットワークです。
  • クラスターIPは、Kubernetes Serviceオブジェクトにのみ適用され、KubernetesがIPアドレスを管理および割り当てます(クラスターIPアドレスプールからのソース)。
  • クラスターIPにはPingできません。これは “実体ネットワークオブジェクト” がないためです。
  • Kubernetesクラスター内では、ノードIP、Pod IP、クラスターIP間の通信には、Kubernetesが独自に設計した特別なルーティング規則が適用されます。

NodePortの実装方法の概要
NodePortの実装方法は、Kubernetesクラスターの各ノードで外部アクセスが必要なServiceに対して対応するTCPリクエストを開始することです。外部システムは、任意のノードのIPアドレス+特定のNodePortポートを使用してサービスにアクセスできます。任意のノード上でnetstatサービスを実行すると、NodePortポートが監視されていることがわかります。

ただし、NodePortは外部からServiceへのアクセスのすべての問題を完全に解決していません。たとえば、クラスターに10個のノードがある場合、外部のリクエストが単一の負荷分散器にアクセスすることが望ましい場合があります。外部のリクエストは、負荷分散器のIPアドレスにのみアクセスすればよく、負荷分散器がトラフィックを後方のNodePortに転送します。負荷分散器は通常、Kubernetesクラスターの外部に独立して存在し、ハードウェアロードバランサーまたはソフトウェア方式(たとえばHaproxyやNginx)で実装されます。各Serviceには、後ろ向きのNodeにトラフィックを転送するための対応する負荷分散器インスタンスが構成されることが一般的です。

apiVersion: v1
kind: Service
metadata:
  name: myserver
  namespace: default
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - name: mynginx-http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30001       #もしnodeportポートを指定しない場合、ランダムポート30000〜32767が生成されます

作成が完了したら、svcを確認します。

[root@abcdocker yaml]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.254.0.1       <none>        443/TCP        83d
myserver     NodePort    10.254.201.121   <none>        80:30001/TCP   5s

[root@abcdocker yaml]# kubectl describe svc myserver
Name:                     myserver
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myserver","namespace":"default"},"spec":{"ports":[{"name":"myngin...
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.254.201.121
Port:                     mynginx-http  80/TCP
TargetPort:               80/TCP
NodePort:                 mynginx-http  30001/TCP
Endpoints:                172.30.

144.2:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

次に、ブラウザを使用してアクセスできます。

[root@abcdocker yaml]# netstat -lntup|grep 30001
tcp6       0      0 :::30001                :::*                    LISTEN      933/kube-proxy

Kube-proxyの動作原理

  1. Serviceは多くの場合、概念に過ぎません。実際にServiceが機能するのはkube-proxyサービスプロセスです。
  2. 各ノードノード上でkube-proxyサービスプロセスが実行されます。
  3. 各TCPタイプのKubernetes Serviceに対して、kube-proxyはローカルノード上にリクエストを受信するためのSocketServerを作成し、それをバックエンドのいずれかのPodのポートに均等に送信します。このプロセスはデフォルトでラウンドロビン(rr)ロードバランシングアルゴリズムを使用します。
  4. kube-proxyは、Api Server内のServiceとEndpointsの変更をクエリおよびリッスンし、各Serviceに対して “サービスプロキシオブジェクト” を作成し、自動的に同期します。サービスプロキシオブジェクトは、kube-proxyプログラム内の一種のアーキテクチャであり、このサービスに対するリクエストをリッスンするためのSocketServerを含みます。 SocketServerのポートは、ローカルの空いているポートをランダムに選択します。さらに、kube-proxy内部でロードバランサーLoadBalancerが作成されます。
  5. 変更されたServiceのリストに対して、kube-proxyは個別に処理します。
  • クラスターIPが設定されていない場合、何もしません。そうでなければ、そのServiceのすべてのポート定義リストを取得します。
  • Serviceポートにサービスプロキシオブジェクトを割り当て、そのServiceに関連するiptablesルールを作成します。
  • 負荷分散コンポーネントの対応するServiceに対する転送アドレスリストを更新します。
  1. kube-proxyは、起動時とServiceまたはEndpointの変更を検出すると、ローカルのIptablesのNATテーブルに4つのルールチェーンを追加します。
  • KUBE-PORTABLS-CONTAINER:Cluster IPおよびポート番号を使用してコンテナからServiceにアクセスします。
  • KUBE-PORTALS-HOST:Cluster IPおよびポート番号を使用してホストからServiceにアクセスします。
  • KUBE-NODEPORT-CONTAINER:Node IPおよびポート番号を使用してコンテナからServiceにアクセスします。
  • KUBE-NODEPORT-HOST:ホストからNode IPおよびポート番号を使用してServiceにアクセスします。

注意:kube-proxyには、ポッドをランダムに選択するデフォルトのポリシーを設定することもできます。クライアントIPに基づくセッションアフィニティを実現することもできます。これには、service.spec.sessionAffinityの値を “ClientIP” に設定します(デフォルト値は “None” です)。

By bai

Leave a Reply

Your email address will not be published. Required fields are marked *