web-dev-qa-db-ja.com

Azure上の外部から見えるKubernetesサービス

AzureのKubernetes(v1.4.5)クラスターにELKスタックをデプロイしています。これは、Kibana ServiceおよびDeploymentを作成する構成です。

# deployment.yml
---
apiVersion: v1
kind: Namespace
metadata:
  name: logging
---
# elasticsearch deployment and Service
---
# logstash Deployment and Service
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kibana
  namespace: logging
spec:
  replicas: 1
  template:
    metadata:
      labels:
        component: kibana
    spec:
      containers:
      - name: kibana
        image: sebp/elk:521
        env:
          - name: "LOGSTASH_START"
            value: "0"
          - name: "ELASTICSEARCH_START"
            value: "0"
        ports:
        - containerPort: 5601
          name: ui
          protocol: TCP
        volumeMounts:
          - name: config-volume
            mountPath: '/opt/kibana/config/'
      volumes:
      - name: config-volume
        configMap:
          name: kibana-config
---
apiVersion: v1
kind: Service
metadata:
  name: kibana
  namespace: logging
  labels:
    component: kibana
spec:
  type: LoadBalancer
  ports:
  - port: 5601
    protocol: TCP
    targetPort: ui
    nodePort: 30257
  selector:
    component: kibana

kubectl apply -f deployment.ymlを介してデプロイします。 kubectl delete namespace loggingを介してELKスタック全体をクリアします。
Azureにはロードバランサーがあり、バックエンドプールはk8sエージェントです。デプロイすると、パブリックIPとルールがロードバランサーに追加されます。また、ロードバランサーのアドレスのフロントエンドプールからIPアドレスを使用して、ブラウザーでkibanaにアクセスできます。

そしてここに問題があります1)そして私が達成したい2):

  1. I kubect applyするたびに、newIPアドレスとルールがロードバランサーのフロントエンドプールに追加されます。不思議なことに、以前のIPアドレスとルールはまだ残っています(デプロイする前にkubectl delete namespace loggingを実行したとしても、以前に使用したIPアドレスとルールを解放する必要があります。コードを確認しました ここ そして私が見る限り、古いパブリックIPアドレスと負荷分散ルールがないことを保証する機能があります)。以前のデプロイから追加されたIPアドレスは、現在デプロイされているKibanaサービスにアクセスできません。
  2. ELKスタックのクライアント(ブラウザ<-> kibana、ログ発行サーバー<-> logstashなど)がクライアントにIPアドレスをハードコードすることなくELKサービスを参照するために使用できるDNS名が必要です(したがって、 ELKスタックの再デプロイはクライアントに対して透過的です)。

これまでに試したこと:Azureのダッシュボードを使用して、DNS名を使用してパブリックIPアドレスを手動で作成しました。 kubectl applyで自動的に作成されたもののように見える負荷分散ルールをロードバランサーに追加しました。この手動で作成されたパブリックIPを、kibanaサービス仕様のexternalIPsの下、次にloadBalancerIPの下で使用しようとしました( k8s docs )。
externalIPsがパブリックIPに設定されている場合、kubectl describe service --namespace=logging

Name:           kibana
Namespace:      logging
Labels:         component=kibana
Selector:       component=kibana
Type:           LoadBalancer
IP:         10.x.xxx.xx
External IPs:       52.xxx.xxx.xxx   <- this is the IP I manually created
LoadBalancer Ingress:   52.xxx.xxx.xxx
Port:           <unset> 5601/TCP
NodePort:       <unset> 30257/TCP
Endpoints:      10.xxx.x.xxx:5601
Session Affinity:   None
Events:
  FirstSeen LastSeen    Count   From            SubobjectPath   Type        Reason          Message
  --------- --------    -----   ----            -------------   --------    ------          -------
  15m       15m     1   {service-controller }           Normal      CreatingLoadBalancer    Creating load balancer
  14m       14m     1   {service-controller }           Normal      CreatedLoadBalancer Created load balancer

ただし、DNS名または直接外部IPへの要求はタイムアウトします。サービス仕様でloadBalancerIPを設定すると、kubectl describe serviceは同様の出力を返しますが、外部IP行はありません。また、新しいパブリックIPアドレス+ルールがロードバランサーに作成されます。手動で作成したパブリックIPのDNS名/ IPを使用することもできません。

どんな助けでも大歓迎です:)

4
Joro Tenev

ああ。最も簡単な方法は、すべての展開の前にサービスを削除しないようにすることです。私の経験では、サービスは非常に長続きする傾向があります。これらは、ポート、IP、DNSなどの動的な値を気にすることなく物事を参照するための優れた固定方法を提供します。

Kibanaサービス仕様で、ポート構成からnodePortエントリを削除して、サービスが独自のことを実行できるようにします。考えることが1つ少なくなります。 loadBalancerIPまたはexternalIPの値を設定しないでください。同じルールが他のサービスにも適用されます。

ELKスタック構成ファイル(頭のてっぺんからどのように見えるか思い出せません)については、サービス名で他のコンポーネントを参照してください。ハードコードされたIPなどを使用する必要はありません。 (これを行っているかどうかはわかりませんが、念のためです。)

サービスの作成を許可します。ロードバランサーの外部IPを取得し、DNS構成に接続します。

好みに応じて名前空間を引き続き使用できますが、ELKコンポーネントのデプロイメントをクリアするために名前空間全体を削除しないでください。

ELKスタックの仕様をデプロイメントとサービス用に別々のファイルに分割し(技術的には、これが必要かどうかはわかりません。回避できる可能性があります)、次を使用できるようにします。

kubectl delete -f logging-deployments.yaml
kubectl apply -f logging-deployments.yaml

または同様のコマンドを使用して、サービスに煩わされることなくデプロイメントを更新します。

新しいスタックを作成する前に別の方法でELKスタックを削除する必要がある(または希望する)場合は、次を使用することもできます。

kubectl -n logging delete deployments --all

ロギング名前空間内のすべてのデプロイメントを削除します。私には、このオプションは必要以上に危険に思えます。

2番目のオプションは次のとおりです。

kubectl delete deployments kibana
kubectl delete deployments elasticsearch
kubectl delete deployments logstash

余分なタイピングを気にしないのなら

別のオプションは、次のような新しいラベルを追加することです。

role: application

または

stack: ELK

各デプロイメント仕様に。あなたが使用できるより:

kubectl delete deployments -l stack=ELK

削除の範囲を制限するために...しかし、繰り返しますが、これは危険なようです。


私の好みは、そうしないという最優先の理由がない限り、構成を2つ以上のファイルに分割して使用することです。

kubectl create -f svc-logging.yaml
kubectl create -f deploy-logging.yaml
kubectl delete -f deploy-logging.yaml
kubectl apply -f deploy-logging.yaml
...  
etc

厄介なタイプミスによる事故を防ぐために。

展開とサービスを含むコンポーネントごとに個別のフォルダーを作成し、意味のあるようにネストします(リポジトリに保持するのが簡単で、複数の人が関連するが個別に変更を加える必要がある場合は簡単です)コンポーネント)、そして通常はドキュメントのようなものを提供するためのbash create/destroyスクリプトを使用します...しかし、あなたはその考えを理解します。

このように設定すると、DNS /負荷分散構成を壊すことなく、一部またはすべてのデプロイメントコンポーネントを更新できるはずです。

(もちろん、これはすべてを1つのファイルに入れることは、ある種の難しい要件ではないことを前提としています...その場合、頭から離れてあなたに良い答えはありません...)

2
mdavids