Kubernetesのアーキテクチャはとてもシンプルです

Kubernetesのアーキテクチャはとてもシンプルです

Kubernetesとは

Kubernetes (K8s とも呼ばれる) は、コンテナ化されたアプリケーションの展開、スケーリング、管理を自動化するオープンソース システムです。 Kubernetes は、宣言型の構成と自動化を容易にする、コンテナ化されたワークロードとサービスを管理するための、移植可能で拡張可能なオープンソース プラットフォームです。 Kubernetes には、幅広いサービス、サポート、ツールを備えた大規模かつ急速に成長しているエコシステムがあります。 Kubernetes という名前は、ギリシャ語で「操舵手」または「パイロット」を意味する言葉に由来しています。 k8s という略語は、k と s の間に 8 文字の関係があるためです。 Google は 2014 年に Kubernetes プロジェクトをオープンソース化しました。Kubernetes は、大規模な本番環境ワークロードを実行してきた Google の 10 年以上の経験に基づいて構築されており、コミュニティからの優れたアイデアと実践を組み合わせています。

過去に戻る

Kubernetesがなぜ有益なのかを見てみましょう

従来の展開時代:初期の頃は、組織は物理サーバー上でアプリケーションを実行していました。物理サーバーで実行されているアプリケーションのリソース使用量を制限する方法がないため、リソース割り当ての問題が発生します。たとえば、同じ物理サーバー上で複数のアプリケーションを実行すると、1 つのアプリケーションがリソースの大部分を占有し、他のアプリケーションのパフォーマンスが低下する可能性があります。 1 つの解決策は、各アプリケーションを異なる物理サーバー上で実行することです。しかし、あるアプリケーションのリソース使用率が低いと、残りのリソースを他のアプリケーションに割り当てることができず、多くの物理サーバーを維持するためのコストが高くなります。

仮想化展開の時代:そのため、仮想化技術が導入されました。仮想化テクノロジーを使用すると、単一の物理サーバーの CPU 上で複数の仮想マシン (VM) を実行できます。仮想化により、アプリケーションを異なる VM 内で相互に分離できるようになり、あるアプリケーションの情報に別のアプリケーションが自由にアクセスできないため、ある程度のセキュリティが確保されます。仮想化テクノロジーは、物理サーバーのリソースをより有効に活用でき、アプリケーションを簡単に追加または更新できるため、スケーラビリティが向上し、ハードウェア コストが削減されるという利点があります。仮想化により、一連の物理リソースを使い捨ての仮想マシンのクラスターとして提供できます。各 VM は、独自のオペレーティング システムを含むすべてのコンポーネントが仮想化されたハードウェア上で実行される完全なコンピューターです。

コンテナ展開時代:コンテナは VM に似ていますが、分離機能が緩やかであるため、コンテナはオペレーティング システム (OS) を共有できます。したがって、コンテナは VM よりも軽量であると考えられます。また、VM と同様に、各コンテナには独自のファイル システム、CPU、メモリ、プロセス スペースなどがあります。これらはインフラストラクチャから分離されているため、クラウドや OS ディストリビューション間で移植可能です。コンテナは、次のような多くの利点があるため人気が高まっています。

  • アジャイルなアプリケーションの作成と展開: VM イメージを使用する場合と比較して、コンテナ イメージの作成の容易さと効率性が向上します。
  • 継続的な開発、統合、およびデプロイメント: 信頼性が高く頻繁なコンテナ イメージのビルドとデプロイメントを提供し、ロールバックは高速かつ簡単です (イメージの不変性による)。
  • 開発と運用の分離に重点を置きます。アプリケーション コンテナー イメージをデプロイメント時ではなくビルド時とリリース時に作成し、アプリケーションをインフラストラクチャから分離します。
  • 可観測性: OS レベルの情報とメトリックだけでなく、アプリケーションの健全性やその他の指標信号も表示できます。
  • 開発、テスト、本番環境全体での環境の一貫性: クラウドと同じアプリケーションをラップトップで実行します。
  • クラウドと OS ディストリビューション間の移植性: Ubuntu、RHEL、CoreOS、オンプレミス、Google Kubernetes Engine、その他あらゆる場所で実行できます。
  • アプリケーション中心の管理: 仮想ハードウェア上での OS の実行から、論理リソースを使用して OS 上でのアプリケーションの実行へと抽象化のレベルを上げます。
  • 疎結合、分散、弾力性、解放性に優れたマイクロサービス: アプリケーションは、単一の大きなマシン上で全体として実行されるのではなく、動的にデプロイおよび管理できる小さな独立した部分に分割されます。
  • リソースの分離: 予測可能なアプリケーション パフォーマンス。
  • リソースの利用:高効率、高密度。

Kubernetes はなぜ必要なのでしょうか? また、Kubernetes で何ができるのでしょうか?

コンテナは、アプリケーションをパッケージ化して実行するための優れた方法です。運用環境では、アプリケーションを実行するコンテナを管理し、サービスがオフラインにならないようにする必要があります。たとえば、1 つのコンテナに障害が発生した場合は、別のコンテナを起動する必要があります。この動作がシステムによって処理されれば、もっと簡単ではないでしょうか?それが Kubernetes の目的です。 Kubernetes は、分散システムの回復力を実行するためのフレームワークを提供します。 Kubernetes は、スケーリング要件を満たし、アプリケーションをフェイルオーバーし、デプロイメント パターンなどを提供します。たとえば、Kubernetes を使用すると、システムの Canary デプロイメントを簡単に管理できます。 Kubernetes は以下を提供します:

  • サービス検出と負荷分散: Kubernetes は、DNS 名または独自の IP アドレスを使用してコンテナを公開し、複数のコンテナに統合されたアクセス ポータル (内部 IP アドレスと DNS 名) を提供し、関連付けられているすべてのコンテナの負荷を分散できるため、ユーザーはコンテナの IP の問題を心配する必要がありません。
  • ストレージ オーケストレーション: 外部ストレージをサポートし、外部ストレージ リソースをオーケストレーションします。外部ストレージシステムは、ローカルストレージ、パブリッククラウド (AWS など)、ネットワークストレージ (NFS、Glusterfs、Ceph など) からマウントされ、クラスターリソースの一部として使用されるため、ストレージ使用の柔軟性が大幅に向上します。
  • 自動デプロイメントとロールバック: K8S は、アプリケーションを更新するためにローリング戦略を採用し、すべての Pod を同時に削除するのではなく、一度に 1 つの Pod を更新します。更新プロセス中に問題が発生した場合、アップグレードがビジネスに影響を与えないように変更がロールバックされます。
  • 自動リソース計算: Kubernetes は、コンテナ化されたタスクが実行される多数のノードで構成されるクラスターを提供します。各コンテナに必要な CPU とメモリ (RAM) の量を Kubernetes に伝えます。 Kubernetes は、リソースを最大限に活用するために、必要に応じてこれらのコンテナをノードにスケジュールできます。
  • 自己修復: ノードに障害が発生したときに、障害が発生したコンテナを再起動し、置き換えて再デプロイし、予想されるレプリカ数を確保します。ヘルスチェックに失敗したコンテナを強制終了し、準備ができるまでクライアントの要求を処理しないため、オンライン サービスが中断されないようにします。
  • 集中構成管理とキー管理: イメージ内の機密データを公開せずに機密データとアプリケーション構成を管理し、機密データのセキュリティを強化し、一般的に使用される構成の一部を K8S に保存してアプリケーションの使用を容易にします。
  • タスクのバッチ処理と実行: バッチ データ処理と分析のシナリオに合わせて、1 回限りのタスクとスケジュールされたタスクを提供します。

Kubernetes コンポーネント

K8S はマスタースレーブアーキテクチャに属します。つまり、マスターノードはクラスターのスケジュール、管理、および操作を担当し、スレーブノードはクラスター内のコンピューティングワークロードノードです。マスターノードは一般にマスターノードと呼ばれます。マスターノードには、apiserver、controller-manager、schedulerがあり、k8s クラスターストレージに etcd を使用します。スレーブノードはワーカーノードノードと呼ばれます。ノードには、kubelet、kube-proxy、コンテナ エンジン (docker など) があります。

マスターコンポーネント

Kube-apiサーバー

kube-apiserver は Kubernetes の最も重要なコアコンポーネントの 1 つであり、主に次の機能を提供します。

  • 認証と承認、データ検証、クラスター ステータスの変更など、クラスター管理用の REST API インターフェイスを提供します。
  • 他のモジュール間のデータのやり取りと通信のためのハブを提供します (他のモジュールは API サーバーを介してデータを照会または変更し、API サーバーのみが etcd を直接操作します)。

API サーバーは、すべての K8S リクエスト (UI インターフェースまたは CLI コマンドライン ツールから) を受信し、ユーザーの特定のリクエストに基づいて他のコンポーネントに動作を通知する役割を担います。 API サーバーは、K8S クラスター アーキテクチャの頭脳であり、すべてのリソース オブジェクトの操作エントリ ポイントであると言えます。

Kube コントローラー マネージャー

さまざまなコントローラーを実行および管理します。これは、K8S クラスター内の日常的なタスクを処理するバックグラウンド スレッドであり、K8S クラスター内のすべてのリソース オブジェクトの自動化制御センターです。 K8S クラスターでは、1 つのリソースが 1 つのコントローラーに対応し、コントローラー マネージャーがこれらのコントローラーの管理を担当します。これは、API サーバーを通じてクラスター全体のステータスを監視し、クラスターが期待どおりの動作状態にあることを確認する一連のコントローラーで構成されています。たとえば、ノードが予期せずダウンした場合、コントローラ マネージャーはすぐにそれを検出して自動修復プロセスを実行し、クラスターが常に期待どおりの動作状態にあることを確認します。これらのコントローラには主に次のものが含まれます。

  • ノード コントローラー: ノード障害の検出と対応を担当します。
  • レプリケーション コントローラー: クラスター内の RC (リソース オブジェクト レプリケーション コントローラー) に関連付けられた Pod レプリカの数が常に事前設定された値のままであることを保証する役割を担います。これは、クラスター内に N 個の Pod インスタンスのみが存在することを保証するものと理解できます。ここで、N は RC で定義されている Pod レプリカの数です。
  • エンドポイント コントローラー: エンドポイント オブジェクトを設定 (つまり、サービスとポッドを接続) し、サービスと対応するポッドのコピーの変更を監視する役割を担います。エンドポイントは、サービスによって公開されるアクセス ポイントであると理解できます。サービスにアクセスする必要がある場合は、そのエンドポイントを知っておく必要があります。
  • サービス アカウントとトークン コントローラー: 新しい名前空間のデフォルトのアカウントと API アクセス トークンを作成します。
  • ResourceQuota コントローラー: 指定されたリソース オブジェクトが常に過剰なシステム物理リソースを占有しないようにします。
  • 名前空間コントローラー: 名前空間のライフサイクルを管理します。
  • サービスコントローラ: K8Sクラスタと外部クラウドプラットフォーム間のインターフェースコントローラ

Kube スケジューラ

クラスター リソース全体のスケジューリングを担当し、スケジューリング アルゴリズムに従って新しく作成されたポッドに適したノードを選択します。ユーザーがサービスをデプロイする場合、スケジューラはスケジューリング アルゴリズムに基づいて、ポッドをデプロイするのに最も適切なノードを選択します。スケジューリングアルゴリズム:

  • 述語
  • 優先事項

API サーバーは、Pod のバッチを作成する要求を受信すると、事前設定されたテンプレートに従って Pod を作成するようにコントローラー マネージャーに要求します。コントローラー マネージャーは、API サーバーを通じてスケジューラーを見つけ、新しく作成されたポッドに最適なノードを選択します。たとえば、このポッドを実行するには 2C4G のリソースが必要な場合、スケジューラは事前選択ポリシーを通じてポリシーを満たさないノードを除外します。ノード内の残りのリソースは API サーバーに報告され、etcd に保存されます。 API サーバーは、etcd 内のすべてのノードの残りのリソースを見つけるメソッドを呼び出し、それらを Pod に必要なリソースと比較します。ノードのリソースが不十分であるか、事前選択戦略の条件を満たしていない場合、事前選択に合格しません。事前選択段階で選択されたノードは、最適化段階で最適化戦略に従ってスコア付けされ、ランク付けされ、最も高いスコアを持つノードが選択されます。たとえば、リソースが豊富で負荷が少ないノードの方がランキングが高くなる可能性があります。

Etcdストレージ

クラスター データベースには、クラスター全体のステータスが保存されます。サービス検出システムとして、etcd には次の機能があります。

  • シンプル: インストールと設定が簡単で、対話用の HTTP API も提供されており、使いやすいです。
  • セキュリティ: SSI証明書検証をサポート
  • 高速: 1つのインスタンスで1秒あたり2,000以上の読み取り操作をサポート
  • 信頼性: 分散システムデータの可用性と一貫性を実現するために RAT アルゴリズムを使用する

デフォルトでは、etcd は現在、HTTP API サービスを提供するためにポート 2379 を使用し、ピアと通信するためにポート 2380 を使用します (これらの 2 つのポートは、IANA によって etcd 用に正式に予約されています)。つまり、etcd はクライアントに外部通信を提供するためにデフォルトでポート 2379 を使用し、サーバー間の内部通信にはポート 2380 を使用します。実稼働環境では、etcd をクラスター モードでデプロイすることが一般的に推奨されます。 etcd のリーダー選出メカニズムにより、少なくとも 3 台の奇数サーバーが必要になります。

ノードコンポーネント

クベレット

コンテナを実際に実行するコンポーネントは、ポッドの宣言ライフサイクルを管理します。各ノードで kubelet サービス プロセスが開始されます。このプロセスは、マスターからこのノードに送信されたタスクを処理し、ポッドとポッド内のコンテナを管理するために使用されます。各 kubelet プロセスは、API サーバーに独自のノード情報を登録し、ノード リソースの使用状況をマスターに定期的に報告し、cAdvisor を通じてコン​​テナとノードのリソースを監視します。

Kube プロキシ

K8S クラスター内のマイクロサービスの負荷分散は、Kube-proxy によって実装されます。 Kube-proxy は、K8S クラスター内のロードバランサーです。これは、各 K8S ノード上で Kube プロキシ コンポーネントを実行する分散プロキシ サーバーです。各ノードに Pod ネットワーク プロキシを実装し、ネットワーク ルールとレイヤー 4 の負荷分散の維持を担当します。サービス マッピング アクセス、リクエストの転送、負荷分散プロセスの管理を実装するために、iptables および ipvs にルールを記述する責任があります。 Kube-apiserver は、Kube-Proxy を監視して Kubernetes Service を更新し、エンドポイントを維持します。

コンテナランタイム

アプリケーションを実際に実行するキャリア。 kubernetes がポッドをノードにスケジュールすると、ノード上の kubelet は docker に特定のコンテナを起動するように指示します。次に、kubelet は Docker を通じてコン​​テナ情報を収集し、それをマスターノードに送信し続けます。 Docker はコンテナ イメージをプルし、通常どおりコンテナを起動または停止します。唯一の違いは、管理者が各ノードで手動で操作するのではなく、自動化されたシステムによって制御されることです。 Kubernetes は、containerd、docker、CRI-O、Kubernetes CRI (Container Runtime Interface) など、多くのコンテナ ランタイムをサポートしています。

Kubernetes コアオブジェクト

Kubernetes 内のすべては「リソース」として抽象化されており、Pod、Service、Node などはすべてリソースです。 「オブジェクト」は「リソース」のインスタンスであり、永続的なエンティティです。 Kubernetes は、次のようなさまざまな方法で Kubernetes オブジェクトを作成および管理することをサポートしています。

  • kubectlコマンドの使用
  • YAMLファイル方式

ポッド

Pod は、Kubernetes によって作成またはデプロイされる最小/最も単純な基本単位です。 Pod は 1 つ以上のコンテナーで構成されます。 Pod 内のコンテナは、ネットワーク、ストレージ、コンピューティング リソースを共有します。 yaml を使用して、nginx イメージを含むコンテナを含むシンプルな nginx サービスを定義します: (nginx-pod.yaml):

 apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80

Kubectl ツールを使用して、Kubernetes クラスターにこの Pod を作成します。

 kubectl apply -f nginx-pod.yaml

Kubernetes クラスターで Pod を作成する基本的なプロセスは次のとおりです。

1. ユーザーがPOD作成リクエストを送信する

2. APIサーバーはユーザーリクエストを処理し、PodデータをEtcdに保存します。

3. スケジュールはAPIサーバーの監視メカニズムを通じて新しいポッドを検出し、ノードをポッドにバインドしようとします。

4. ホストのフィルタリング: スケジューラは、一連のルールを使用して、要件を満たさないホストをフィルタリングします。たとえば、Pod が必要なリソースを指定する場合、リソースが不足しているホストは除外す​​る必要があります。

5. ホストのスコアリング: 最初のステップで選択した要件を満たすホストにスコアを付けます。この段階で、スケジューラは、レプリケーション コントローラのレプリカを別のホストに分散したり、負荷が最も低いホストを使用したりといった、いくつかの全体的な最適化戦略を検討します。

6. ホストの選択: スコアが最も高いホストを選択し、バインディング操作を実行し、結果をEtcdに保存します。

7. Kubelet は、スケジューリング結果に従って Pod 作成操作を実行します。バインドが成功すると、コンテナが起動し、Docker が実行され、スケジューラが API サーバーの API を呼び出して、etcd にバインドされた Pod オブジェクトを作成し、動作中のノードでバインドされて実行されているすべての Pod 情報を記述します。各ワーカーノードで実行されている kubelet は、バインドされたポッド情報を etcd と定期的に同期します。ワーカー ノードで実行されているはずのバインドされたポッド オブジェクトが更新されていないことが判明すると、Docker API を呼び出してポッド内にコンテナーを作成して起動します。

8. POD作成完了

名前空間

名前空間は、リソースとオブジェクトの抽象的なコレクションです。たとえば、システム内のオブジェクトを異なるプロジェクト グループまたはユーザー グループに分割するために使用できます。共通のポッド、サービス、デプロイメントなどはすべて、特定の名前空間に属します (デフォルトでは)。たとえば、上記の Nginx Pod では名前空間が指定されていないため、デフォルトでデフォルトの名前空間が使用されます。ただし、Node や PersistentVolume などのリソースは、どの Namespace にも属さず、グローバルです。

ラベル

リソース オブジェクトのラベルを定義することは、そのオブジェクトにラベルを付けるのと同じです。ラベル セレクターを使用して、特定のラベルを持つリソース オブジェクトをクエリおよびフィルター処理できます。

展開

デプロイメントは、ポッドを管理するために使用されるリソース オブジェクトです。デプロイメントにより、指定された数の Pod「レプリカ」が常に実行されることが保証されます。 Pod のデプロイメントを作成し、3 つのレプリカを指定すると、3 つの Pod が作成され、継続的に監視されます。ポッドが応答しなくなった場合、デプロイメントはそれを置き換え、常に合計を 3 に保ちます。以前に応答しなかったポッドが復元され、現在 4 つのポッドがある場合、デプロイメントはそのうちの 1 つを終了して合計数を 3 に保ちます。操作中にレプリカの合計数を 5 に変更すると、デプロイメントはすぐに 2 つの新しいポッドを開始して、合計数が 5 になるようにします。ロールバックとローリング アップグレードをサポートします。デプロイメントを作成するときは、次の 2 つのことを指定する必要があります。

  • Podテンプレート: Podレプリカを作成するために使用されるテンプレート
  • ラベル: デプロイメントが監視する必要があるポッドのラベル。

サービス

K8S クラスターでは、各 Pod に個別の IP アドレスが割り当てられますが、Pod にはライフサイクル (作成可能で、破棄された後は再起動されない) があるため、業務の変更により IP アドレスがいつでも消えてしまう可能性があります。サービスは、この問題を解決するために使用される中核的な概念です。サービスは、アプリケーション サービスの抽象化であり、ラベルを通じてアプリケーションの負荷分散とサービス検出を提供します。ラベルに一致するポッド IP とポートのリストはエンドポイントを形成し、kube-proxy はこれらのエンドポイントへのサービス IP の負荷分散を担当します。各サービスには、クラスター IP (クラスター内でのみアクセス可能な仮想アドレス) と DNS 名が自動的に割り当てられます。他のコンテナは、バックエンド コンテナの動作を理解していなくても、このアドレスまたは DNS を介してサービスにアクセスできます。

K8S コンポーネントワークフロー

1. 運用保守担当者が kube-apiserver に指示を出します (何をしたいのか、どのような状態を期待するのか)

2. API はコマンドに応答し、一連の認証と承認を渡し、ポッド データを etcd に保存し、デプロイメント リソースを作成して初期化します。 (予想される状態)

3. コントローラは、リスト監視メカニズムを通じて新しいデプロイメントを監視および検出し、リソースを内部作業キューに追加し、リソースに関連付けられたポッドとレプリカセットがないことを検知します。これにより、デプロイメント コントローラーがレプリカセット リソースを作成できるようになり、レプリカセット コントローラーがポッドを作成できるようになります。

4. すべてのコントローラーが作成されたら、デプロイメント、レプリカセット、およびポッド リソースを更新し、etcd に保存します。

5. スケジューラは、リスト監視メカニズムを通じて新しいポッドを監視および検出し、ホスト フィルタリングおよびホスト スコアリング ルールに基づいてポッドを適切なホストにバインドします。 6. バインディング結果をetcdに保存します。

7. kubelet は 20 秒ごとに (カスタマイズ可能)、NodeName を介して apiserver から独自のノードで実行されるポッドのリストを取得します。独自の内部キャッシュと比較して新しいポッドを追加します。

8. Kubelet がポッドを作成します。

9. kube-proxy は、新しく作成されたポッドのダイナミック DNS を CoreOS に登録します。サービス検出と負荷分散のために、ポッドのサービスに iptables/ipvs ルールを追加します。

10. コントローラは、制御ループを通じて現在のポッドの状態とユーザーの予想される状態を比較します。現在のステータスがユーザーの予想ステータスと異なる場合、コントローラーはポッドをユーザーの予想ステータスに変更します。機能しない場合は、コントローラーはポッドを削除してからポッドを再作成します。

<<:  エンタープライズクラウドの需要が回復し、AWSの利益と収益が増加

>>:  エッジでのコンピュータビジョンの 7 つの主要アプリケーション

推薦する

RSSが消滅するかどうかの鍵はユーザーではなくコンテンツプロバイダーにある

はじめに: Google Reader の閉鎖に伴い、やや「オタクっぽい」技術である RSS が、再...

画像ショッピングガイドウェブサイト:中国における Pinterest の変貌

ユーザーがPinterestに登録する際は、FacebookまたはTwitterアカウントにログイン...

ITを近代化するための3つの主要戦略

アメリカ技術評議会 (ATC) の最近の IT 近代化レポートでは、米国の機関や組織の IT チーム...

ウェブサイト上の不合理な内部リンクはウェブサイトのホームページの重みを低下させる

月収10万元の起業の夢を実現するミニプログラム起業支援プランXiaoxiaoketang.com の...

事例分析:ウェブサイトが開けないのにランキングが残る理由

なぜ一部のウェブサイトは開けないのでしょうか?なぜランキングが残っているのでしょうか?中には長期間ラ...

アリババの人事担当副社長が260万元の賄賂を受け取った罪で懲役8年6ヶ月の刑を宣告されたと報じられている。

アリババ【TechWeb Report】6月12日、メディア報道によると、アリババは最近、従業員が2...

Douban は 2 億人の影響力をどのように活用して、興味に基づくソーシャル ネットワーキングで成功しているのでしょうか?

少し前に、「Douban では、興味関心マーケティングによって 2 億人のユーザーが 200 のブラ...

リアルタイム検索と分析データのニーズに応えるため、UCloud ElasticSearch(UES)サービスが正式に開始されました。

オープンソースの分散検索エンジンとして、ElasticSearch はもはや目新しいものではありませ...

AI が CAPTCHA を破ります。人間であることをどうやって証明するのでしょうか?

インターネットを閲覧する以上のことをしている場合(ほとんどの人がそうします)、さまざまな種類の CA...

56.com の簡単な分析: 合併後の解決策は?

2011年9月、Renrenはビデオウェブサイト56.comを正式に買収するために8000万ドルを費...

なぜ多くの企業は SEO に注意を払わないのでしょうか?これらの理由を理解していますか?

月収10万元の起業の夢を実現するミニプログラム起業支援プラン国内のトラフィックプールからのすべてのメ...

あなたのウェブサイトに偶然訪れるキーワードを知っていますか?

私は毎日ウェブサイトのトラフィック統計をチェックする習慣があり、まったく最適化していない単語が依然と...

新しく作成されたウェブサイトが検索エンジンにインデックスされないのはなぜですか?

多くの新しい SEO 仲間は、どれだけ時間が経ってもまだインデックスに含まれない Web サイトを構...

ネットワークマーケティングの秘密を具体的な事例とともに詳しく説明します

インターネット マーケティングは、さまざまな企業がブランド認知度と売上を高めるのに役立つ素晴らしいツ...