サービス
私たちは以前に基本的な使い方を学びましたし、命には限りがあり、死後は復活しないこともPod
学びました。Pod
後で学習することは、を動的に作成および破棄するために使用RC
できます。それぞれに独自のアドレスがありますが、再起動すると変更される可能性が非常に高くなります。これは問題を引き起こします: たとえば、クラスター内の他のフロントエンド コレクションにサービスを提供するいくつかのバックエンド コレクションがあります。これらすべてのバックエンドのアドレスをフロントエンドにハードコードして、次のようにすると、特定の方法でサービスのいずれかにアクセスするには、機能するようですよね? ただし、ハングアップしてから再起動すると、アドレスが変更される可能性が高く、この時点では、フロントエンドがバックエンド サービスにアクセスできない可能性があります。Deployment
Pod
Pod
IP
Pod
IP
Pod
Pod
API
Pod
Pod
Pod
Pod
IP
このような問題を解決するにはどうすればよいでしょうか? 利用前にKubernetes
このような問題に遭遇したことがある人も多いと思いますが、必ずしもIP
変更の問題ではありません 例えばサービスをデプロイする際WEB
、通常フロントエンドはNginx
サービスエントランスをデプロイし、Nginx
それをマウントする必要がありますこのサービスには多くのバックエンドがあります。昔は、提供されるサービスの数を動的に変更するためにNginx
構成内のオプションを手動で変更することがありました。その後、 などのいくつかのツールがupstream
登場し、私たちが使い慣れたツールも登場しました。これらを使用すると、ツールを使用した後、これらのサービス ディスカバリー センターにサービスを登録するだけで、これらのツールが構成を動的に更新できるようになり、手動操作がまったく必要なくなり、非常に便利です。服务发现
Consul
ZooKeeper
etcd
Nginx
同様に、上記で発生した問題を解決するために、サービス検出ツールを実装することは可能でしょうか? そうです、Pod
破棄または新しく作成された場合、このアドレスをサービス検出センターに登録できますPod
が、この場合、フロントエンドのPod
組み合わせはバックエンドのPod
コレクションに直接接続できませんね? A に接続される必要があります。サービスディスカバリができるミドルウェアですよね?
そうです、Kubernetes
クラスターはそのようなオブジェクト、つまり一連の論理コレクションとそれらにアクセスするための戦略を定義する抽象オブジェクトを提供しますService
。Service
実際Pod
、この概念はマイクロサービスに非常に似ています。Serivce
以下に含まれるセットはPod
、一般的Label Selector
に によって。
たとえば、上記の例では、バックエンドで 3 つのコピーを実行した場合、フロントエンドは使用するバックエンド サービスを気にしないため、これらのコピーはすべて置き換え可能です。バックエンドPod
コレクションはさまざまな理由で変更を送信しますが、フロントエンドはこれらの変更を知る必要はなく、リストを使用してバックエンド サービスを記録する必要もありません。この抽象化は、この分離を実現するのに役立ちますService
。 . .
3 つの IP
人々は混乱することが多いため、研究を続ける前に、システム内の 3 つの IP の問題をService
理解する必要があります。Kubernetes
- ノードIP:
Node
ノードのIP
アドレス - ポッド IP:ポッド
Pod
の IP アドレス - クラスター IP:
Service
のIP
アドレス
まず第一に、Node IP
これはKubernetes
クラスター内のノードIP
(通常はイントラネット) の物理ネットワーク カード アドレスです。このネットワークに属するすべてのサーバーは相互に直接通信できます。したがって、クラスター内のノードまたはサービスにKubernetes
アクセスしたい場合は、Kubernetes
クラスターの外では、Node IP
経由で通信する必要があります (現時点では、通常は外部ネットワーク経由ですIP
)。
次に、各アドレスPod IP
があり、ブリッジのアドレス セグメントに従って割り当てられます(すべてのノードが競合しないようにするために、ここではこの種のネットワーク プラグインを使用します)。Pod
IP
Docker Engine
docker0
IP
flannel
Pod IP
最後に、Cluster IP
これは仮想的なものでありIP
、Kubernetes Service
このオブジェクトにのみ作用し、Kubernetes
それ自体でアドレスを管理および割り当てます。もちろん、ping
このアドレスを使用することはできません。応答する実際のエンティティ オブジェクトはありません。を組み合わせてService Port
通信できるサービスを形成します。
サービスの定義
前に定義したさまざまなリソース オブジェクトの定義メソッドとメソッド タイプ。たとえば、ポート 8080 を外部に公開し、すべてそのようにラベル付けされているサービスService
のグループがあるとします。その後、サービスを次のオブジェクトとして定義できます。 :Pod
app=myapp
Service
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 8080
name: myapp-http
次に、それを使用してkubectl create -f myservice.yaml
名前を付けたオブジェクトを作成できます。これは、TCP ポート 8080 を使用してラベルを持つオブジェクトにリクエストをプロキシします。これは、上で説明したようにシステムによって割り当てられ、次のメッセージをリッスンし続けます。情報は、上で説明したコレクションに似た という名前のオブジェクトに更新されます。myservice
Service
app=myapp
Pod
Service
Cluster IP
Service
selector
Pod
Pod
myservice
Endpoints
Pod
Service
受信ポートを任意の にマッピングできることに注意してくださいtargetPort
。デフォルトでは、フィールドと同じ値targetPort
に設定されます。port
おそらくもっと興味深いのは、targetPort がバックエンド Pod 上のポート名を参照する文字列である可能性があることです。ポート名に実際に割り当てられるポート番号は各バックエンド Pod で同じではない可能性があるため、この方法により、サービスのデプロイと設計の柔軟性が高まります。
さらに、Service
TCP および UDP プロトコルをサポートでき、デフォルトは TCP プロトコルです。
代理人になる
前に述べたように、Kubernetes
クラスター内ではそれぞれがプロセスNode
を実行します。このプロセスは、プロキシ形式の VIP (仮想 IP、上で述べたもの)を実装するkube-proxy
役割を果たします。現在、このモードではデフォルトでプロキシとして使用されています。このモードは、Service オブジェクトと Endpoints オブジェクトの追加と削除を監視します。サービスごとに、サービスのクラスターIP (仮想IP) とポートへのリクエストをキャプチャする iptables ルールを追加し、リクエストをサービスのバックエンドのセットの 1 つにリダイレクトします。各 Endpoints オブジェクトに対して、バックエンド ポッドを選択する iptables ルールもインストールします。Service
clusterIP
Kubernetes
iptables
kube-proxy
Kubernetes master
デフォルトの戦略は、バックエンドをランダムに選択することです。クライアント IP に基づいてセッション アフィニティを実装することもできます。これを「ClientIP」に設定できますservice.spec.sessionAffinity
(デフォルト値は「None」)。
もう 1 つ理解すべき点は、最初に選択された Pod が応答しない場合、iptables プロキシは別の Pod を自動的に再試行できるため、readiness プローブに依存する必要があることです。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-sD0QIvZU-1678238488098)(./images/services-iptables-overview.svg)]
サービスの種類
Service
定義時に必要な型を指定できますがService
、指定しない場合は、ClusterIP
その型がデフォルトになります。
ご利用いただけるサービスの種類は以下の通りです。
-
ClusterIP: サービスはクラスタの内部 IP を通じて公開されます。この値が選択されている場合、サービスはクラスタ内でのみアクセスできます。これはデフォルトの ServiceType でもあります。
-
NodePort: 各 Node ノード上の IP および静的ポート (NodePort) を通じてサービスを公開します。NodePort サービスは、自動的に作成される ClusterIP サービスにルーティングされます。NodePort サービスには、次のリクエストを行うことでクラスターの外部からアクセスできます。
-
ロードバランサー: クラウド プロバイダーのロード バランサーを使用して、サービスを外部に公開します。外部ロード バランサーは、特定のクラウド ベンダーと連携して運用する必要がある NodePort サービスおよび ClusterIP サービスにルーティングできます。
-
ExternalName: CNAME とその値を返すことにより、サービスを externalName フィールドの内容 (foo.bar.example.com など) にマッピングできます。いかなる種類のプロキシも作成されません。これは、Kubernetes 1.7 以降の kube-dns によってのみサポートされます。
ノードポートの種類
type の値を「NodePort」に設定すると、Kubernetes マスターは指定された構成範囲 (デフォルト: 30000 ~ 32767) からポートを割り当て、各ノードはこのポート (各ノードの同じポート) からサービスにプロキシします。 )。ポートは Service の spec.ports[*].nodePort フィールドで指定されます。指定しない場合、ポートは自動的に生成されます。
Service は、:spec.ports[ ].nodePort および spec.clusterIp:spec.ports[ ].port を通じて外部から参照できることに注意してください。
NodePort
次に、誰もが以前のサービスにアクセスできるようにサービスを作成しましょうNginx
: (service-demo.yaml として保存)
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
selector:
app: myapp
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
name: myapp-http
これを作成しますService
:
$ kubectl create -f service-demo.yaml
Service
次に、オブジェクト情報を表示できます。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d
myservice NodePort 10.104.57.198 <none> 80:32560/TCP 14h
myservice
TYPE タイプが変更され、NodePort
後半PORT(S)
に 32560 という追加のマップされたポートがあることがわかります。
外部名
ExternalName
これはサービスの特殊なケースであり、セレクターがなく、ポートやエンドポイントも定義されていません。クラスターの外部で実行されているサービスの場合、外部サービスのエイリアスを返すことによってサービスを提供します。
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 層で行われ、プロキシや転送が行われないことです。後でデータベースを Kubernetes クラスターに移行することにした場合は、呼び出しコードをまったく変更せずに、対応するポッドを起動し、適切なセレクターまたはエンドポイントを追加して、サービスのタイプを変更することで、完全に分離することができます。