はじめての Kubernetes | 実際に動かして学ぶKubernetes入門 #1

こんにちは 株式会社FIXERの村上 滉樹です(何気にTechBlog初投稿です💦)。

2022年は Kubernetes管理者認定(CKA) にチャレンジしたくて 毎日 ちょこちょこ勉強しています。
しかし、ただ勉強するだけではモチベーションに対する限界があり、、 私個人で「Kubernetes入門シリーズ」をスタートしました。

目次

■ 本記事の紹介

  • Azure VM で Kubernetes 環境を構築して nginx コンテナを実行する
  • Microsoft Azure の Kubernetes サービス紹介

※ 基本的に ハンズオン形式で投稿します。実際にチャレンジしてみてください。
※ この記事では Kubernetes用語の紹介や説明は省きます。まずは 動くものを作っていきましよう。
(後日 紹介します!!)

実行環境
– MacBook Pro | os: Catalina 10.15.7 | cpu: Intel
– シェル | PowerShell v7.1.3

■ Azure VM で Kubernetes 環境を構築して nginx コンテナを実行する

Azure Virtual Machine(CentOS)で Minikube クラスターを構築して nginxコンテナを動かします。
Azure アカウントがなくても、手元のPCでVirtual BoxやVMware 等で 仮想マシンを構築できれば Minikube は構築できます👍

追記:ホストOS上で Minikube を構築しても構いません。OS依存の問題に悩むかもしれないですが Mac は問題なかったです。

1. Azureリソースを構築する

▶︎ リソース構築に必要な環境変数を定義する

$Location = 'japaneast'
$ResourceGroup = 'rg-kube'
$VirtualMachine = 'centosvm'

▶︎ リソースグループ と Azure Virtual Machine を作成する

公式 : Minikube の最小動作環境 『 cpu: 2コア | ram: 2GB | storage: 20GB 』

# リソースグループ 作成する
PS> az group create --location $Location --name $ResourceGroup

# 仮想マシン 作成する (2コア/4GBで構築)
PS> az vm create `
    --resource-group $ResourceGroup `
    --name $VirtualMachine `
    --size Standard_B2s `
    --image CentOS `
    --admin-username azureuser `
    --generate-ssh-keys

# vm create 後に出力される パブリックIPアドレス をメモしてください(Azure ポータルから確認することもできます)

▶︎ ssh接続する

# 接続開始
PS> ssh azureuser@<メモしたパブリックIPアドレス>

▶︎ 初回接続するとき「本当に接続するけどいい?」と聞かれるので ‘yes’ と入力して実行する

Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

# 下のように表示されると 接続完了です
[azureuser@centosvm ~]$

リソースの準備は整いました。次のステップにいきましょう。

2. Kubernetes 環境を構築するためのツールをインストールする

▶︎ Docker をインストールする

# インストールする
[azureuser@centosvm ~]$ sudo yum -y install docker

# Docker を起動する
[azureuser@centosvm ~]$ sudo systemctl start docker

▶︎ Kubernetesをインストールする(cf. https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/

# バイナリファイルをインストールする
[azureuser@centosvm ~]$ curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"

# すべてのユーザーにkubectlコマンドの実行権限を付与する
[azureuser@centosvm ~]$ chmod +x ./kubectl

# 環境パスを通す
[azureuser@centosvm ~]$ sudo mv ./kubectl /usr/local/bin/kubectl

▶︎ Minikube をインストールする(cf. https://minikube.sigs.k8s.io/docs/start/

# バイナリファイルをインストールする
[azureuser@centosvm ~]$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

# minikube-linux-amd64を使用して インストールする
[azureuser@centosvm ~]$ sudo install minikube-linux-amd64 /usr/local/bin/minikube

# Docker をドライバーにして Kubernetesクラスター を起動する cf. https://minikube.sigs.k8s.io/docs/drivers/docker/
[azureuser@centosvm ~]$ minikube start --driver=docker

あれ?エラーが表示されました…。

😄  Centos 7.5.1804 上の minikube v1.24.0
✨  ユーザーの設定に基づいて docker ドライバーを使用します

💣  Exiting due to PROVIDER_DOCKER_NEWGRP: "docker version --format -" exit status 1: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/version: dial unix /var/run/docker.sock: connect: permission denied
💡  提案: Add your user to the 'docker' group: 'sudo usermod -aG docker $USER && newgrp docker'
📘  ドキュメント: https://docs.docker.com/engine/install/linux-postinstall/

原因は、
– ユーザー権限で dockerコマンド使用できない。
– 解決策として、dockerグループを作成して、「sudo usermod -aG docker $USER && newgrp docker」を実行。

▶︎ 📘 ドキュメント に記載されている 公式ドキュメントを試す

# dockerグループを作成する 
[azureuser@centosvm ~]$ sudo groupadd docker

# ユーザーをdockerグループに追加する
[azureuser@centosvm ~]$ sudo usermod -aG docker $USER

# Docker を再起動する
[azureuser@centosvm ~]$ sudo systemctl restart docker

# 一度、ssh接続を切断する
[azureuser@centosvm ~]$ exit 
 
# 再度 ssh接続を行う
PS> ssh azureuser@<メモしたパブリックIPアドレス>

# エラー原因を対応したため、もう一度 Kubernetesクラスター を起動する
[azureuser@centosvm ~]$ minikube start --driver=docker

成功 🎉

😄  Centos 7.5.1804 上の minikube v1.24.0
✨  ユーザーの設定に基づいて docker ドライバーを使用します
💨  For improved Docker performance, Upgrade Docker to a newer version (Minimum recommended version is 18.09.0)
👍  コントロールプレーンのノード minikube を minikube 上で起動しています
🚜  イメージを Pull しています...
💾  Kubernetes v1.22.3 のダウンロードの準備をしています
    > preloaded-images-k8s-v13-v1...: 501.73 MiB / 501.73 MiB  100.00% 265.85 M
    > gcr.io/k8s-minikube/kicbase: 355.78 MiB / 355.78 MiB  100.00% 25.28 MiB p
🔥  docker container (CPUs=2, Memory=2200MB) を作成しています...
🐳  Docker 20.10.8 で Kubernetes v1.22.3 を準備しています...
    ▪ 証明書と鍵を作成しています...
    ▪ Control Plane を起動しています...
    ▪ RBAC のルールを設定中です...
🔎  Kubernetes コンポーネントを検証しています...
    ▪ イメージ gcr.io/k8s-minikube/storage-provisioner:v5 を使用しています
🌟  有効なアドオン: storage-provisioner, default-storageclass
🏄  完了しました! kubectl が「"minikube"」クラスタと「"default"」ネームスペースを使用するよう構成されました

Docker + Kubernetes + Minikube 環境が整いました。次のステップにいきましょう。

3. Minikube でコンテナを動作する

▶︎ Minikube(クラスター)の状態を確認する

# クラスターステータスを確認する
[azureuser@centosvm ~]$ minikube status

▶︎ マニフェスト ファイルを作成する

# ファイルを保管するフォルダを作成して、移動する
[azureuser@centosvm ~]$ mkdir ./app && cd app

# ファイルを作成する
[azureuser@centosvm app]$ vim nginx_deployment_service.yaml

以下のコードをコピペしてください!
※「i」でインサートモードに切り替え、コピペ後 escキーを押して「:wq」で保存して終了(vimの基本的な使い方)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - name: http
      port: 8080
      targetPort: 80

▶︎ マニフェストファイルを適用する

kubectl create deployment nginx --image=nginx でもNginxイメージを元に Podを作成できますが、マニフェストファイルに慣れた方がいいので apply を使いましょう。
cf. 今更ながら学ぼう kubernetes での Pod の立て方

【余談】
kubectl のサブコマンドは 基本的に apply を使う癖を身につけときましょう。 オブジェクトが存在している、していない関係なく apply はどこでも実行できるので 使い分ける必要がないです。
(サブコマンド:create・apply・replace・patch・delete)
cf. Kubernetes: kubectl apply の動作

# マニフェストファイルを適用する
[azureuser@centosvm app]$ kubectl apply -f nginx_deployment_service.yaml

# デプロイメントとサービス オブジェクトが作成されました
# deployment.apps/nginx created
# service/nginx created

▶︎ 適用した情報を取得する

# pod,service,deployment,replicaset 等のリソースリストを取得する
[azureuser@centosvm app]$ kubectl get all

# NAME                        READY   STATUS    RESTARTS   AGE
# pod/nginx-585449566-srj8p   1/1     Running   0          5m19s

# NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
# service/kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP          16m
# service/nginx        LoadBalancer   10.111.129.191   <pending>     8080:31810/TCP   5m19s

# NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
# deployment.apps/nginx   1/1     1            1           5m19s

# NAME                              DESIRED   CURRENT   READY   AGE
# replicaset.apps/nginx-585449566   1         1         1       5m19s

▶︎ 適用したnginxサービスのみを取得する

# nginxサービス情報を取得する
[azureuser@centosvm app]$ kubectl get service nginx

# NAME    TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
# nginx   LoadBalancer   10.111.129.191   <pending>     8080:31810/TCP   13m

EXTERNAL-IP からアクセスしたいですが、<pending>になっていますね。Minikubeクラスター内の外部IPアドレスを公開しただけで ホストOS側のブラウザでは動かないので まずは ゲストOSからアクセスしてみます。

▶︎ Azure NSGに8080ポートを受信可能にする(Azure ポータルから操作)

Azure Virtual Machineリソース -> 設定 -> ネットワーク から 受信セキュリティ規則の追加 をしてください。
※ LoadBalancer Service のポートを確認すると、TCP/8080 を許可する必要がありますね。

▶︎ LoadBalancer Service を取得する

# クラスター内でアクセスできるnginxサービス情報を取得する
[azureuser@centosvm app]$ minikube service nginx

# TARGET PORT に接続することを確認(curl してみる)
# |-----------|-------|-------------|---------------------------|
# | NAMESPACE | NAME  | TARGET PORT |            URL            |
# |-----------|-------|-------------|---------------------------|
# | default   | nginx | http/8080   | http://192.168.49.2:31810 |
# |-----------|-------|-------------|---------------------------|
# 🎉  Opening service default/nginx in default browser...
# xdg-open: no method available for opening 'http://192.168.49.2:31810'

▶︎ curlで疎通確認する

[azureuser@centosvm app]$ curl http://192.168.49.2:31810

# 成功
# <!DOCTYPE html>
# <html>
# <head>
# <title>Welcome to nginx!</title>
# ・・・
# </html>

成功したリスクエストに対して レスポンスが返ってきたので大丈夫ですね。
けど、やっぱり ホストOSのブラウザで確認したい・・・やりましょう。

▶︎ 外部IPアドレスにアクセスする(実行したままにする)

[azureuser@centosvm app]$ kubectl port-forward --address 0.0.0.0 service/nginx 8080

# minikube tunnel で LoadBalancer Serviceをルーティングして外部公開する方法もあります。

▶︎ Azure VMのパブリックIPアドレスからホストOSのブラウザ経由でアクセスする

http://<メモしたパブリックIPアドレス>:8080 を Google ChromeやEdge 等のブラウザでアクセスする

無事、確認できました。(安全に SSL通信を取り入れたいですが、後日 投稿予定)

いかがでしたか?初めてKubernetesを学ぶ人からすると コマンドをコピペするだけで動いてしまって 満足感がないかもしれません。ごめんなさい🙇‍♂️

次回からkubectlやAPIサーバーの紹介について投稿していきます❗️(第二段も執筆中)

■ Microsoft Azure の Kubernetes サービス紹介

上記で紹介した Minikube はローカル環境でKubernetesを簡単に実行するためのツールです。ですが、ローカル環境ということは、オンプレミス環境と同じです(大変だ)。

Kubernetes はサーバー上で動作するソフトウェアなので それに伴ってサーバー/ネットワーク/セキュリティを誰かが管理する必要があります。

そこでオススメしたいのが 『パブリッククラウド版のマネージドKubernetesサービス』です。
Azureで Kubernetesサービスとして提供されているのは、以下のリソースです。

  • Azure Kubernetes Service : マネージドサービス
  • Azure Container Apps(プレビュー);フル マネージド サーバーレス  サービス
  • Azure Spring Cloud:Spring Bootアプリ向けのフルマネージド サービス

コンテナサービスまで範囲を広げると

  • Azure Container Instance
  • WebApps on Container(Functionsも含む)

も存在します。

この中で1番 有名なのは、「Azure Kubernetes Service(通称:AKS)」です(AWS、GCP、IBMにもよく似たサービスがあるからでしょうか・・・)。
中規模から大規模 システム向けのIaaSに近いPaaSサービスと、個人的に解釈しています。

AKSには、魅力は大きく分けて2点あります。

  • 1つ目は、Microsoftが提供する「フルマネージド コントロールプレーン」です。

マスターノードの管理が不要になります。API ServerやControl Manager、Schedule等をコントロールします。マスターノードの役割をフルマネージドするので、ワーカーノードに対して 開発が集中できます。

  • 2つ目は、「負荷分散機能」です。

エンドユーザーからのリクエストは、
TCP通信 → ロードバランサー(L4階層で負荷分散) → イングレスPod(L7階層で負荷分散) → クラスターIP(L3階層負荷分散) → アプリケーションPod の順に通信します。この分散により、Pod上にデプロイされたコンテナが安定的に動作する仕組みになっています。

■ さいごに

この記事から Kubernetesディベロッパーが1人でも多く誕生してくれると嬉しいです😊

FIXER Inc. 村上 滉樹
  • FIXER Inc. 村上 滉樹
  • 阿南高専出身、現Azureインフラエンジニア。
    PaaSとServerlessを好んで学習してます。
    最近は、AWSとKubernetesを独学しています。