0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

kubernetesで冗長化されたReactサーバーの各ホストネームを取得して表示する方法

Last updated at Posted at 2023-03-26

問題:Reactサーバのホスト名を取得する方法は?

あなたは以下のようにkubernetesを使ってReactサーバーのレプリカを生成し、冗長化しました。

image.png

さて、同じIPアドレスにアクセスしても、実際には違うPodのReactサーバーにアクセスしていることを確認するために、各Reactサーバーのホストネームをレンダリング時に表示したいと思います。

こんなとき、どうすれば良いでしょう??
ちなみに、クライアントサイドで以下のコードで取得できるのは、今回取得したいものではないです。

const hostname = window.location.hostname;
console.log(`Hostname: ${hostname}`);

例えば、Qiitaのページを開いているときに、ブラウザの開発者ツールを開いて以上を実行すると、以下が表示されます。

Hostname: qiita.com

これは、FQDNであり実際にはロードバランサーやプロキシーサーバのアドレスを示しています。実際にReactを動かしているサーバーやポッドのホスト名ではないですね。

(クライアントサイドレンダリングの)Reactのコードはブラウザ上で実行されていますので、クライアントサーバーのコードに最初から工夫がなされていなければ、ブラウザからでは、どうやったってポッドに振り分けられる前までのアドレスしか分かりません。

作戦:Pod起動時にホストネームをテキストファイルに書き込む

では、どうすれば、Reactサーバが置かれているPodのホストネームを取得できるのでしょうか?

泥臭いながら、考えられる作戦として「ポッド作成時にホストネームをテキストファイルに書き込み、それを読み込むようにする」があります。

具体的には以下です。

  1. Reactアプリケーションをコンテナ化し、kubenetesのPod内でコンテナをデプロイする
  2. コンテナ起動時に、ホストネームを記述したhostname.txtを生成し、/react-app/public/以下に保存
  3. Reactのコンポーネントレンダリング時に、hostname.txtを読み込み、記述されたホストネームを表示

以下でその具体的手順を紹介します。

1. テキストファイルテキストを読み込むロジック

あとでPublicフォルダにホストネームが書かれたテキストファイルを置くので、先にそれを読み込み表示するロジックを作成しておきます。

function App() {
  const [ hostname, setHostname] = useState("");
  const getHostname = async () => {
    const reponse = await fetch(`${process.env.PUBLIC_URL}/hostname.txt`);
    const text = await reponse.text();
    setHostname(text);
    return text;
  };
  useEffect(
    () => {getHostname();}, [hostname]
  );
  return (
      <div>{`pod name : ${hostname}`}</div>
    )

}

2. アプリケーションのコンテナ化

create-react-appコマンドなどでReactのアプリケーションを作ったあと、package.jsonなどがあるのと同じ階層に、以下のDocerfileとstartup.sh(コンテナ起動時に実行したいコマンドをまとめて書くためのファイル)を作成します。

Docerfile
FROM node:16.13.0-alpine AS builder

WORKDIR /usr/local/app

COPY . .

RUN yarn --frozen-lockfile && \
    yarn build

FROM nginx:1.20-alpine

COPY --from=builder /usr/local/app/build /usr/share/nginx/html

COPY startup.sh /startup.sh
RUN chmod 744 /startup.sh

CMD ["/startup.sh"]

以下のstartup.shが、コンテナ起動時に実行されますが、見ての通り、一行目でホストネームをhostname.txtへと書き込んでいます。

startup.sh
hostname >> /usr/share/nginx/html/hostname.txt
nginx -g "daemon off;"

次に、コンテナイメージをビルドしていきます。
コマンドは以下です。(DockerHubにプッシュしますので、先にDockerHubにサインアップしておく必要があります。以下、あなたのアカウント名をyournameとします。)

docker build --tag {yourname}/react-app:latest --no-cache . 
docker run --name react-app --rm --publish 3000:80 {yourname}/react-app:latest
docker push {yourname}/react-app:latest

ビルドしたイメージのDockerHubへUploadも終わり、これで準備は完了です。

3. kubenetesでPodを3つ作成し、Reactアプリケーションを冗長化する

kubernetesでPodを3つ作るには、以下のyamlファイルを作成します。ローカルで実行していますので、ここではminikube使っています。

deployment-service-react.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: react-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: react-app
  template:
    metadata:
      labels:
        app: react-app
    spec:
      containers:
      - name: react
        image: {yourname}/react-app  # Edit
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: react-app
spec:
  type: NodePort
  selector:
    app: react-app
  ports:
    - port: 3000
      targetPort: 80
      protocol: TCP
      name: react-app

そして、以下のコマンドを実行します。

minikube start
kubectl apply --filename ./deployment-service-react.yaml
minikube service reputation-checker-react

で、アプリのデプロイとアドレスの公開までできます。

以下↓に自分の環境で実行したときのスクリーンショットを貼ります。
image.png
クロームのシークレットウィンドウを用いて同じアドレスにアクセスすると、表示されるPodの名前が異なることが分かります。
image.png

まとめ

さて、以上の手順を経ることで、KubenetesでReactサーバが複数のPodに置かれ冗長化されたときの、各Reactサーバが置かれているPodのホスト名を表示することができることを示しました。

実際問題、ホストネームを表示したいときなんてかなり稀ですが、どうしても確認したくなった時は以上をお試しください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?